/// <summary>
            /// Pads the signature with extra data.
            /// </summary>
            /// <param name="signature">The signature.</param>
            /// <param name="outputStream">The padded signature.</param>
            /// <param name="extra">The extra data passed by sigData.</param>
            protected override void PadSignature(byte[] signature, Stream outputStream, object extra)
            {
                var padData    = (Tuple <long, long, Stream>)extra;
                var stopLength = padData.Item1;
                var position   = padData.Item2;
                var input      = padData.Item3;

                var key = GetPrimaryKey() as ISignerKey;

                outputStream.Write(FormatBytes, 0, FormatBytes.Length);
                outputStream.Write(key.GetKeyHash(), 0, KeyHashLength);

                var lengthBytes = Utility.GetBytes((int)(stopLength - position));

                outputStream.Write(lengthBytes, 0, lengthBytes.Length);
                padData.Item3.Seek(position, SeekOrigin.Begin);
                using (var reader = new NondestructiveBinaryReader(input))
                {
                    var adjustedBufferSize = (int)Math.Min(BufferSize, (stopLength - input.Position));
                    while (reader.Peek() != -1 && input.Position < stopLength)
                    {
                        byte[] buffer = reader.ReadBytes(adjustedBufferSize);
                        outputStream.Write(buffer, 0, buffer.Length);
                    }
                }
                outputStream.Write(signature, 0, signature.Length);
            }
Exemple #2
0
        /// <summary>
        /// Signs the specified data.
        /// </summary>
        /// <param name="input">The input.</param>
        /// <param name="outstream">The outstream.</param>
        /// <param name="prefixData">The prefix data.</param>
        /// <param name="postfixData">The postfix data.</param>
        /// <param name="signatureData">The sig data.</param>
        /// <param name="inputLength"> Length of the input.</param>
        protected void Sign(Stream input, Stream outstream, object prefixData, object postfixData, object signatureData, long inputLength)
        {
            var stopLength = inputLength < 0 ? long.MaxValue : input.Position + inputLength;

            if (!(GetPrimaryKey() is ISignerKey key))
            {
                throw MakeInvalidKeySetTypeException();
            }
            using (var reader = new NondestructiveBinaryReader(input))
            {
                using (var signingStream = key.GetSigningStream(this))
                {
                    PrefixDataSign(signingStream, prefixData);
                    while (reader.Peek() != -1 && input.Position < stopLength)
                    {
                        var    adjustedBufferSize = (int)Math.Min(BufferSize, (stopLength - input.Position));
                        byte[] buffer             = reader.ReadBytes(adjustedBufferSize);
                        signingStream.Write(buffer, 0, buffer.Length);
                    }
                    PostfixDataSign(signingStream, postfixData);
                    signingStream.Finish();

                    var signature = signingStream.HashValue;
                    PadSignature(signature, outstream, signatureData);
                }
            }
        }
        public bool Verify(Stream input, byte[] signature, long inputLength = -1)
        {
            var milliseconds = FromDateTime(_currentDateTime());

            if (!_verifier.Verify(input, signature, inputLength))
            {
                return(false);
            }
            using (var stream = new MemoryStream(signature))
                using (var reader = new NondestructiveBinaryReader(stream))
                {
                    reader.ReadBytes(HeaderLength);
                    var expiration      = reader.ReadBytes(TimeoutLength);
                    var expMilliseconds = Utility.ToInt64(expiration);
                    return(milliseconds < expMilliseconds);
                }
        }
            public bool VerifyHidden(Stream input, Stream verifiedMessage, byte[] hidden, long inputLength)
            {
                var fullLength = inputLength < 0 ? input.Length : inputLength + input.Position;

                using (var reader = new NondestructiveBinaryReader(input))
                {
                    var header = reader.ReadBytes(KeyczarConst.HeaderLength);
                    var length = Utility.ToInt32(reader.ReadBytes(4));

                    if (fullLength < input.Position + length)
                    {
                        throw new InvalidCryptoDataException("Data doesn't appear to have signatures attached!");
                    }

                    using (var sigStream = new MemoryStream())
                    {
                        using (Utility.ResetStreamWhenFinished(input))
                        {
                            sigStream.Write(header, 0, header.Length);
                            input.Seek(length, SeekOrigin.Current);
                            while (reader.Peek() != -1 && input.Position < fullLength)
                            {
                                var adjustedBufferSize = (int)Math.Min(BufferSize, (fullLength - input.Position));
                                var buffer             = reader.ReadBytes(adjustedBufferSize);
                                sigStream.Write(buffer, 0, buffer.Length);
                            }
                            sigStream.Flush();
                        }
                        using (var signedMessageLimtedLength = new NondestructivePositionLengthLimitingStream(input))
                        {
                            signedMessageLimtedLength.SetLength(length);
                            if (verifiedMessage != null)
                            {
                                using (Utility.ResetStreamWhenFinished(input))
                                {
                                    signedMessageLimtedLength.CopyTo(verifiedMessage);
                                }
                            }
                            var verified = Verify(signedMessageLimtedLength, sigStream.ToArray(), prefixData: null, postfixData: hidden, inputLength: inputLength);
                            input.Seek(fullLength, SeekOrigin.Begin);
                            return(verified);
                        }
                    }
                }
            }
Exemple #5
0
        /// <summary>
        /// Verifies the specified data.
        /// </summary>
        /// <param name="input">The input.</param>
        /// <param name="signature">The signature.</param>
        /// <param name="prefixData">The prefix data.</param>
        /// <param name="postfixData">The postfix data.</param>
        /// <param name="inputLength">(optional) Length of the input.</param>
        /// <returns></returns>
        protected virtual bool Verify(Stream input, byte[] signature, object prefixData, object postfixData, long inputLength)
        {
            var stopLength = inputLength < 0 ? long.MaxValue : input.Position + inputLength;

            using (var reader = new NondestructiveBinaryReader(input))
            {
                byte[] trimmedSig;
                var    resetData = Utility.ResetStreamWhenFinished(input);
                foreach (var key in GetKeys(signature, out trimmedSig))
                {
                    resetData.Reset();
                    //in case there aren't any keys that match that hash we are going to fake verify.
                    using (var verifyStream = key.Maybe(m => m.GetVerifyingStream(), () => new DummyStream()))
                    {
                        PrefixDataVerify(verifyStream, prefixData);
                        while (reader.Peek() != -1 && input.Position < stopLength)
                        {
                            var    adjustedBufferSize = (int)Math.Min(BufferSize, (stopLength - input.Position));
                            byte[] buffer             = reader.ReadBytes(adjustedBufferSize);
                            verifyStream.Write(buffer, 0, buffer.Length);
                        }
                        PostfixDataVerify(verifyStream, postfixData);

                        try
                        {
                            if (verifyStream.VerifySignature(trimmedSig))
                            {
                                return(true);
                            }
                        }
                        catch (Exception e)
                        {
                            //We don't want exceptions to keep us from trying different keys
                            System.Diagnostics.Debug.WriteLine(e.Message);
                            System.Diagnostics.Debug.WriteLine(e.StackTrace);
                        }
                    }
                }
                return(false);
            }
        }
Exemple #6
0
        /// <summary>
        /// Decrypts the specified input.
        /// </summary>
        /// <param name="input">The input.</param>
        /// <param name="output">The output.</param>
        /// <param name="inputLength">(optional) Length of the input.</param>
        /// <exception cref="InvalidCryptoDataException">Ciphertext was invalid!</exception>
        public void Decrypt(Stream input, Stream output, long inputLength = -1)
        {
            var fullLength = inputLength < 0 ? input.Length : inputLength + input.Position;

            using (var reader = new NondestructiveBinaryReader(input))
            {
                byte[] keyHash;
                var    resetStream = Utility.ResetStreamWhenFinished(input);
                var    header      = Utility.ReadHeader(input, out keyHash);
                var    verify      = false;
                foreach (var key in GetKey(keyHash))
                {
                    var cryptKey = key as ICrypterKey;
                    resetStream.Reset();


                    bool ciphertextIsPreverified = false;
                    //in case there aren't any keys that match that hash we are going to fake verify.
                    using (var verifyStream = cryptKey.Maybe(m => m.GetAuthVerifyingStream(this), () => new DummyStream()))
                    {
                        //If we verify in once pass like with AEAD verify stream will be null;
                        if (verifyStream != null)
                        {
                            //Perform ciphertext verification
                            ciphertextIsPreverified = true;
                            var tagLength = verifyStream.GetTagLength(header);
                            while (input.Position < fullLength - tagLength)
                            {
                                byte[] buffer =
                                    reader.ReadBytes((int)Math.Min(BufferSize, fullLength - tagLength - input.Position));
                                verifyStream.Write(buffer, 0, buffer.Length);
                            }
                            var signature = reader.ReadBytes(tagLength);

                            try
                            {
                                verify = verifyStream.VerifySignature(signature);
                            }
                            catch (Exception e)
                            {
                                System.Diagnostics.Debug.WriteLine(e.Message);
                                System.Diagnostics.Debug.WriteLine(e.StackTrace);
                                //We don't want exceptions to keep us from trying different keys
                                verify = false;
                            }
                        }
                    }

                    if ((!verify && ciphertextIsPreverified) || input.Length == 0)
                    {
                        continue;
                    }

                    //
                    Stream baseStream = ciphertextIsPreverified
                        ? output
                        : new MemoryStream();
                    Stream wrapper = baseStream;
                    bool   success = false;
                    if (Compression == CompressionType.Gzip)
                    {
                        wrapper = new WriteDecompressGzipStream(baseStream);
                    }
                    else if (Compression == CompressionType.Zlib)
                    {
                        wrapper = new ZlibStream(baseStream, CompressionMode.Decompress, true);
                    }

                    //Perform Decryption
                    using (Compression == CompressionType.None ? null : wrapper){
                        FinishingStream crypterStream;
                        resetStream.Reset();

                        input.Seek(KeyczarConst.HeaderLength, SeekOrigin.Current);
                        crypterStream = cryptKey.Maybe(m => m.GetDecryptingStream(wrapper, this), () => new DummyStream());

                        try
                        {
                            using (crypterStream)
                            {
                                var tagLength = crypterStream.GetTagLength(header);
                                while (input.Position < fullLength - tagLength)
                                {
                                    byte[] buffer =
                                        reader.ReadBytes((int)Math.Min(BufferSize, fullLength - tagLength - input.Position));
                                    crypterStream.Write(buffer, 0, buffer.Length);
                                }
                                crypterStream.Finish();
                                input.Seek(tagLength, SeekOrigin.Current);
                                success = true;
                            }
                        }
                        catch (Exception e)
                        {
                            //We don't want exceptions to keep us from trying different keys
                            //particularly ones that aren't pre verified
                            System.Diagnostics.Debug.WriteLine(e.Message);
                            System.Diagnostics.Debug.WriteLine(e.StackTrace);
                        }
                    }
                    if (success)
                    {
                        if (!ciphertextIsPreverified)
                        {
                            //If the ciphertext is verified in one pass,
                            //we have to make sure that verification was successful before copying it to output.
                            baseStream.Seek(0, SeekOrigin.Begin);
                            baseStream.CopyTo(output);
                        }

                        return;
                    }
                }

                throw new InvalidCryptoDataException("Cipher text was invalid!");
            }
        }
Exemple #7
0
        public void Encrypt(Stream input, Stream output, long inputLength = -1)
        {
            var stopLength = inputLength < 0 ? long.MaxValue : input.Position + inputLength;
            var key        = GetPrimaryKey();
            var header     = new byte[HeaderLength];

            Array.Copy(FormatBytes, 0, header, 0, FormatBytes.Length);
            Array.Copy(key.GetKeyHash(), 0, header, FormatBytes.Length, KeyHashLength);

            var cryptKey = key as IEncrypterKey;

            var resetStream = Utility.ResetStreamWhenFinished(output);

            using (var reader = new NondestructiveBinaryReader(input))
            {
                FinishingStream encryptingStream;


                output.Write(header, 0, header.Length);
                encryptingStream = cryptKey.GetEncryptingStream(output);


                Stream wrapper = encryptingStream;
                if (Compression == CompressionType.Gzip)
                {
                    wrapper = new GZipStream(encryptingStream, CompressionMode.Compress, true);
                }
                else if (Compression == CompressionType.Zlib)
                {
                    wrapper = new ZlibStream(encryptingStream, CompressionMode.Compress, true);
                }

                using (encryptingStream)
                {
                    encryptingStream.GetTagLength(header);
                    using (Compression == CompressionType.None ? null : wrapper){
                        while (reader.Peek() != -1 && input.Position < stopLength)
                        {
                            var    adjustedBufferSize = (int)Math.Min(BufferSize, (stopLength - input.Position));
                            byte[] buffer             = reader.ReadBytes(adjustedBufferSize);
                            wrapper.Write(buffer, 0, buffer.Length);
                        }
                    }
                    encryptingStream.Finish();
                }
            }


            byte[] hash;
            using (var outputReader = new NondestructiveBinaryReader(output))
                using (var signingStream = cryptKey.GetAuthSigningStream())
                {
                    if (signingStream == null || signingStream.GetTagLength(header) == 0)
                    {
                        return;
                    }
                    resetStream.Reset();
                    while (outputReader.Peek() != -1)
                    {
                        byte[] buffer = outputReader.ReadBytes(BufferSize);
                        signingStream.Write(buffer, 0, buffer.Length);
                    }
                    signingStream.Finish();

                    hash = signingStream.HashValue;
                }

            output.Write(hash, 0, hash.Length);
        }