示例#1
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(this), () => 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);
            }
        }
示例#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;
            var key        = GetPrimaryKey() as ISignerKey;

            using (var reader = new NondestructiveBinaryReader(input))
            {
                using (var signingStream = key.GetSigningStream())
                {
                    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);
                }
            }
        }
示例#3
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!");
            }
        }
示例#4
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);
        }