Exemple #1
0
        public void PackingAndUnpackingResultsInOriginal()
        {
            CryptoHeader header = new CryptoHeader
            {
                PackageName   = "MyAppName",
                AlgorithmName = "Twofish",
                KdfName       = "PBKDF2",
                Cost          = "10",
                Nonce         = CommonMocksAndStubs.FilledByteArray(8, 66),
                Salt          = CommonMocksAndStubs.FilledByteArray(8, 77),
                Compression   = "gzip",
            };

            byte[] cipher = CommonMocksAndStubs.FilledByteArray(16, 88);

            byte[] packedHeader = CryptoHeaderPacker.PackHeaderAndCypher(header, cipher);
            CryptoHeaderPacker.UnpackHeaderAndCipher(packedHeader, "MyAppName", out CryptoHeader unpackedHeader, out byte[] unpackedCipher);

            Assert.AreEqual(header.PackageName, unpackedHeader.PackageName);
            Assert.AreEqual(header.AlgorithmName, unpackedHeader.AlgorithmName);
            Assert.AreEqual(header.KdfName, unpackedHeader.KdfName);
            Assert.AreEqual(header.Cost, unpackedHeader.Cost);
            Assert.AreEqual(header.Nonce, unpackedHeader.Nonce);
            Assert.AreEqual(header.Salt, unpackedHeader.Salt);
            Assert.AreEqual(cipher, unpackedCipher);
            Assert.AreEqual(header.Compression, unpackedHeader.Compression);
        }
Exemple #2
0
        public void PackingAndUnpackingWorksWithKeyOnly()
        {
            // If the encryption is started with a key instead of a password, there are not all parametes set.
            CryptoHeader header = new CryptoHeader
            {
                PackageName   = "MyAppName",
                AlgorithmName = "Twofish",
                KdfName       = null,
                Cost          = null,
                Nonce         = CommonMocksAndStubs.FilledByteArray(8, 66),
                Salt          = null,
                Compression   = "gzip",
            };

            byte[] cipher = CommonMocksAndStubs.FilledByteArray(16, 88);

            byte[] packedHeader = CryptoHeaderPacker.PackHeaderAndCypher(header, cipher);
            CryptoHeaderPacker.UnpackHeaderAndCipher(packedHeader, "MyAppName", out CryptoHeader unpackedHeader, out byte[] unpackedCipher);

            Assert.AreEqual(header.PackageName, unpackedHeader.PackageName);
            Assert.AreEqual(header.AlgorithmName, unpackedHeader.AlgorithmName);
            Assert.AreEqual(header.KdfName, unpackedHeader.KdfName);
            Assert.AreEqual(header.Cost, unpackedHeader.Cost);
            Assert.AreEqual(header.Nonce, unpackedHeader.Nonce);
            Assert.AreEqual(header.Salt, unpackedHeader.Salt);
            Assert.AreEqual(cipher, unpackedCipher);
            Assert.AreEqual(header.Compression, unpackedHeader.Compression);
        }
        public static CryptoHeader ReadHeader(Stream cipherTextStream, bool leaveOpen)
        {
            cipherTextStream.Position = 0;

            var header = new CryptoHeader();

            using (var br = new BinaryReader(cipherTextStream, Encoding.UTF8, leaveOpen))
            {
                header.PayloadLength = UnpackInt64(br);
                header.Magic         = UnpackBytes(br);
                if (header.Magic.SequenceEqual(brPackMagic) == false)
                {
                    throw new Exception("Unsupported magic.");
                }
                header.Signature           = UnpackBytes(br);
                header.EncryptionAlgorithm = UnpackString(br);
                if (header.EncryptionAlgorithm != EncryptionType.Aes256CbcPkcs7)
                {
                    throw new Exception("Unsupported encryption algorithm.");
                }
                header.CreatedBy      = UnpackBytes(br);
                header.Id             = UnpackString(br);
                header.KeyId          = UnpackString(br);
                header.Purpose        = UnpackString(br);
                header.MimeType       = UnpackString(br);
                header.Created        = DateTimeOffset.FromUnixTimeMilliseconds(UnpackInt64(br));
                header.Iv             = UnpackBytes(br);
                header.CipherMetadata = UnpackBytes(br);
            }

            return(header);
        }
        public static async Task <string> DecryptAndUncompressStreamAsync(byte[] key, Stream cipherTextStream, Stream tempUncompressStream, Stream plainTextStream)
        {
            if (key == null || key.Length != 32)
            {
                throw new ArgumentNullException("key");
            }

            string metadata = null;

            cipherTextStream.Position     = 0;
            tempUncompressStream.Position = 0;
            plainTextStream.Position      = 0;

            var header = new CryptoHeader();

            long signaturePosition;

            using (var br = new BinaryReader(cipherTextStream, Encoding.UTF8, true))
            {
                header.PayloadLength = UnpackInt64(br);
                header.Magic         = UnpackBytes(br);
                if (header.Magic.SequenceEqual(brPackMagic) == false)
                {
                    throw new Exception("Unsupported magic.");
                }
                signaturePosition          = cipherTextStream.Position;
                header.Signature           = UnpackBytes(br);
                header.EncryptionAlgorithm = UnpackString(br);
                if (header.EncryptionAlgorithm != EncryptionType.Aes256CbcPkcs7)
                {
                    throw new Exception("Unsupported encryption algorithm.");
                }
                header.CreatedBy      = UnpackBytes(br);
                header.Id             = UnpackString(br);
                header.KeyId          = UnpackString(br);
                header.Purpose        = UnpackString(br);
                header.MimeType       = UnpackString(br);
                header.Created        = DateTimeOffset.FromUnixTimeMilliseconds(UnpackInt64(br));
                header.Iv             = UnpackBytes(br);
                header.CipherMetadata = UnpackBytes(br);
                if (header.CipherMetadata != null && header.CipherMetadata.Length > 0)
                {
                    metadata = Encoding.UTF8.GetString(Aes256Decrypt(key, header.Iv, header.CipherMetadata));
                }

                var cipherTextPosition = cipherTextStream.Position;

                cipherTextStream.Seek(signaturePosition + 32 + 4, SeekOrigin.Begin);
                var signingKey       = key;
                var signatureCompare = HmacSha256Hash(signingKey, cipherTextStream);
                if (signatureCompare.SequenceEqual(header.Signature) == false)
                {
                    throw new Exception("Signature comparison failed.");
                }

                using (var aes = Aes.Create())
                {
                    aes.Key     = key;
                    aes.IV      = header.Iv;
                    aes.Mode    = CipherMode.CBC;
                    aes.Padding = PaddingMode.PKCS7;

                    cipherTextStream.Seek((int)cipherTextPosition, SeekOrigin.Begin);

                    using (var decryptor = aes.CreateDecryptor(key, header.Iv))
                    {
                        var cs = new CryptoStream(cipherTextStream, decryptor, CryptoStreamMode.Read);
                        await cs.CopyToAsync(tempUncompressStream);

                        await tempUncompressStream.FlushAsync();

                        aes.Clear();

                        tempUncompressStream.Seek(0, SeekOrigin.Begin);
                        await DecompressAsync(tempUncompressStream, plainTextStream, true);
                    }
                }
            }

            return(metadata);
        }