public void AuthenticatedAesCngGcmMultiRoundTripTest()
        {
            byte[] plaintext          = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6 };
            byte[] plaintext2         = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6 };
            byte[] expectedCiphertext = new byte[]
            {
                0x54, 0x2d, 0x26, 0x15, 0x9c, 0xb3, 0x6e, 0x21, 0xd2, 0x58, 0xcf, 0x9c, 0x6e, 0xce, 0xfb, 0x5f,
                0x8c, 0x2a, 0xb8, 0x22, 0x4d, 0x6d, 0xd0, 0x02, 0x76, 0xd2, 0xab, 0x22, 0xa2, 0xd6, 0xee, 0x5b
            };
            byte[] expectedTag = new byte[] { 0xc1, 0x34, 0x38, 0x0b, 0xc3, 0x87, 0x7c, 0xf5, 0x2f, 0x3b, 0xa9, 0xfe, 0x3c, 0x69, 0x4b, 0x9f };
            byte[] key         = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6 };
            byte[] iv          = new byte[] { 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 };

            using (AuthenticatedAesCng gcm = new AuthenticatedAesCng())
            {
                gcm.CngMode = CngChainingMode.Gcm;
                gcm.Key     = key;
                gcm.IV      = iv;
                gcm.Tag     = expectedTag;

                // Encrypt
                byte[] ciphertext = null;
                using (MemoryStream ms = new MemoryStream())
                    using (IAuthenticatedCryptoTransform encryptor = gcm.CreateAuthenticatedEncryptor())
                        using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
                        {
                            // Push through two blocks and call final to get the tag.
                            cs.Write(plaintext, 0, plaintext.Length);
                            cs.Write(plaintext2, 0, plaintext2.Length);
                            cs.FlushFinalBlock();

                            ciphertext = ms.ToArray();

                            // Check if the ciphertext and tag are what are expected.
                            Assert.IsTrue(Util.CompareBytes(expectedCiphertext, ciphertext));
                            Assert.IsTrue(Util.CompareBytes(expectedTag, encryptor.GetTag()));
                        }

                // Decrypt
                using (MemoryStream ms = new MemoryStream())
                    using (ICryptoTransform decryptor = gcm.CreateDecryptor())
                        using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Write))
                        {
                            cs.Write(ciphertext, 0, ciphertext.Length / 2);
                            cs.Write(ciphertext, ciphertext.Length / 2, ciphertext.Length / 2);

                            cs.FlushFinalBlock();

                            byte[] decrypted = ms.ToArray();

                            // Compare the decrypted text to the initial ciphertext.
                            byte[] fullPlaintext = new byte[plaintext.Length + plaintext2.Length];
                            Array.Copy(plaintext, 0, fullPlaintext, 0, plaintext.Length);
                            Array.Copy(plaintext2, 0, fullPlaintext, plaintext.Length, plaintext2.Length);
                            Assert.IsTrue(Util.CompareBytes(fullPlaintext, decrypted));
                        }
            }
        }
示例#2
0
        private static MemoryStream Encrypt(Stream source, string fileName, out string seed_encoded, out string ident)
        {
            // Randomly generate a new seed for upload
            byte[] seed = new byte[16];

            using (RNGCryptoServiceProvider rngCsp = new RNGCryptoServiceProvider())
            {
                rngCsp.GetBytes(seed);
            }

            seed_encoded = UrlBase64Encode(seed);

            // Derive the parameters (key, IV, ident) from the seed
            byte[] key, iv;
            DeriveParams(seed, out key, out iv, out ident);

            // Create a new String->String map for JSON blob, and define filename and metadata
            Dictionary <string, string> metadataMap = new Dictionary <string, string>();

            metadataMap["mime"] = Helpers.IsTextFile(fileName) ? "text/plain" : Helpers.GetMimeType(fileName);
            metadataMap["name"] = fileName;

            // Encode the metadata with UTF-16 and a double-null-byte terminator, and append data
            // Unfortunately, the CCM cipher mode can't stream the encryption, and so we have to GetBytes() on the source.
            // We do limit the source to 50MB however
            byte[] data = Encoding.BigEndianUnicode.GetBytes(JsonConvert.SerializeObject(metadataMap)).Concat(new byte[] { 0, 0 }).Concat(source.GetBytes()).ToArray();

            // Calculate the length of the CCM IV and copy it over
            long ccmIVLen = FindIVLen(data.Length);

            byte[] ccmIV = new byte[ccmIVLen];
            Array.Copy(iv, ccmIV, ccmIVLen);

            // http://blogs.msdn.com/b/shawnfa/archive/2009/03/17/authenticated-symmetric-encryption-in-net.aspx
            using (AuthenticatedAesCng aes = new AuthenticatedAesCng())
            {
                aes.CngMode = CngChainingMode.Ccm;
                aes.Key     = key;
                aes.IV      = ccmIV;
                aes.TagSize = MacSize;

                MemoryStream ms = new MemoryStream();

                using (IAuthenticatedCryptoTransform encryptor = aes.CreateAuthenticatedEncryptor())
                {
                    CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write);
                    cs.Write(data, 0, data.Length);
                    cs.FlushFinalBlock();
                    byte[] tag = encryptor.GetTag();
                    ms.Write(tag, 0, tag.Length);
                    return(ms);
                }
            }
        }
        private void RunTestVector(GcmTestVector test)
        {
            // Encrypt the input
            byte[] ciphertext = null;
            using (AuthenticatedAesCng gcm = new AuthenticatedAesCng())
            {
                gcm.CngMode           = CngChainingMode.Gcm;
                gcm.Key               = test.Key;
                gcm.IV                = test.IVBytes;
                gcm.AuthenticatedData = test.AuthenticationData;

                using (MemoryStream ms = new MemoryStream())
                    using (IAuthenticatedCryptoTransform encryptor = gcm.CreateAuthenticatedEncryptor())
                        using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
                        {
                            if (test.Plaintext != null)
                            {
                                cs.Write(test.Plaintext, 0, test.Plaintext.Length);
                            }

                            cs.FlushFinalBlock();
                            ciphertext = ms.ToArray();

                            // Verify the produced tag is what we expected it to be
                            Assert.IsTrue(Util.CompareBytes(test.Tag, encryptor.GetTag()));
                        }
            }

            if (test.Ciphertext != null)
            {
                // Verify the ciphertext is what we expected it to be
                Assert.IsTrue(Util.CompareBytes(test.Ciphertext, ciphertext));

                // Round trip the data
                using (AuthenticatedAesCng gcm = new AuthenticatedAesCng())
                {
                    gcm.CngMode           = CngChainingMode.Gcm;
                    gcm.Key               = test.Key;
                    gcm.IV                = test.IVBytes;
                    gcm.AuthenticatedData = test.AuthenticationData;
                    gcm.Tag               = test.Tag;

                    using (MemoryStream ms = new MemoryStream())
                        using (CryptoStream cs = new CryptoStream(ms, gcm.CreateDecryptor(), CryptoStreamMode.Write))
                        {
                            cs.Write(test.Ciphertext, 0, test.Ciphertext.Length);
                            cs.FlushFinalBlock();

                            byte[] plaintext = ms.ToArray();
                            Assert.IsTrue(Util.CompareBytes(test.Plaintext, plaintext));
                        }
                }
            }
        }
示例#4
0
        public bool Encrypt(ref byte[] data, int length, ref byte[] tag)
        {
            if (IsInitialized)
            {
                _serverEncrypt.IV = BitConverter.GetBytes(_serverCounter).Combine(BitConverter.GetBytes(0x52565253));

                using (IAuthenticatedCryptoTransform encryptor = _serverEncrypt.CreateAuthenticatedEncryptor())
                {
                    data = encryptor.TransformFinalBlock(data, 0, length);
                    tag  = encryptor.GetTag();
                }
            }

            ++_serverCounter;
            return(true);
        }
        // returns the encrypted string in the format [IV]-[TAG]-[DATA]
        public static string EncryptString(string str)
        {
            if (String.IsNullOrEmpty(str))
            {
                throw new ArgumentNullException("encryption string invalid");
            }

            using (AuthenticatedAesCng aes = new AuthenticatedAesCng())
            {
                byte[] message = Encoding.UTF8.GetBytes(str);
                aes.Key = GetEncryptionKey();
                aes.IV  = GenerateIV();
                // use the GCM mode, which should prevent the Padding Oracle attack
                // https://en.wikipedia.org/wiki/Padding_oracle_attack
                aes.CngMode           = CngChainingMode.Gcm;
                aes.AuthenticatedData = GetAdditionalAuthenticationData();

                using (MemoryStream memoryStream = new MemoryStream())
                    using (IAuthenticatedCryptoTransform encryptor = aes.CreateAuthenticatedEncryptor())
                        using (CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
                        {
                            // Write through and retrieve encrypted data.
                            cryptoStream.Write(message, 0, message.Length);
                            cryptoStream.FlushFinalBlock();
                            byte[] cipherText = memoryStream.ToArray();

                            // Retrieve tag and create array to hold encrypted data.
                            byte[] authenticationTag = encryptor.GetTag();
                            byte[] encrypted         = new byte[cipherText.Length + aes.IV.Length + authenticationTag.Length];

                            // encrypt the data in the format [IV]-[TAG]-[DATA]
                            aes.IV.CopyTo(encrypted, 0);
                            authenticationTag.CopyTo(encrypted, IV_LENGTH);
                            cipherText.CopyTo(encrypted, IV_LENGTH + TAG_LENGTH);

                            // Store encrypted value in base 64.
                            return(Convert.ToBase64String(encrypted));
                        }
            }
        }
        public void AuthenticatedAesCngChainingTest()
        {
            byte[] plaintext         = new byte[20 * 1024];
            byte[] iv                = new byte[12];
            byte[] authenticatedData = new byte[1024];

            using (RNGCng rng = new RNGCng())
            {
                rng.GetBytes(plaintext);
                rng.GetBytes(iv);
                rng.GetBytes(authenticatedData);
            }

            foreach (CngChainingMode chainingMode in new CngChainingMode[] { CngChainingMode.Ccm, CngChainingMode.Gcm })
            {
                using (AuthenticatedAesCng aes = new AuthenticatedAesCng())
                {
                    aes.AuthenticatedData = authenticatedData;
                    aes.CngMode           = chainingMode;
                    aes.IV = iv;

                    // Encrypt the whole block of data at once
                    byte[] wholeCiphertext = null;
                    byte[] wholeTag        = null;
                    using (IAuthenticatedCryptoTransform encryptor = aes.CreateAuthenticatedEncryptor())
                    {
                        wholeCiphertext = encryptor.TransformFinalBlock(plaintext, 0, plaintext.Length);
                        wholeTag        = encryptor.GetTag();
                    }

                    // Encrypt it in chunks
                    byte[] blockCiphertext = null;
                    byte[] blockTag        = null;
                    using (MemoryStream ms = new MemoryStream())
                        using (IAuthenticatedCryptoTransform encryptor = aes.CreateAuthenticatedEncryptor())
                            using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
                            {
                                int chunkSize = 128;
                                for (int offset = 0; offset < plaintext.Length; offset += chunkSize)
                                {
                                    cs.Write(plaintext, offset, chunkSize);
                                }
                                cs.FlushFinalBlock();

                                blockCiphertext = ms.ToArray();
                                blockTag        = encryptor.GetTag();
                            }

                    // Make sure we got the same results in both cases
                    Assert.IsTrue(Util.CompareBytes(wholeCiphertext, blockCiphertext));
                    Assert.IsTrue(Util.CompareBytes(wholeTag, blockTag));

                    aes.Tag = wholeTag;

                    // Decrypt the whole block of data at once
                    using (ICryptoTransform decryptor = aes.CreateDecryptor())
                    {
                        byte[] wholePlaintext = decryptor.TransformFinalBlock(wholeCiphertext, 0, wholeCiphertext.Length);
                        Assert.IsTrue(Util.CompareBytes(plaintext, wholePlaintext));
                    }

                    // Decrypt the data in chunks
                    using (MemoryStream ms = new MemoryStream())
                        using (ICryptoTransform decryptor = aes.CreateDecryptor())
                            using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Write))
                            {
                                int chunkSize = 128;
                                for (int offset = 0; offset < blockCiphertext.Length; offset += chunkSize)
                                {
                                    cs.Write(blockCiphertext, offset, chunkSize);
                                }
                                cs.FlushFinalBlock();

                                byte[] blockPlaintext = ms.ToArray();
                                Assert.IsTrue(Util.CompareBytes(plaintext, blockPlaintext));
                            }
                }
            }
        }
        /// <summary>
        ///     Perform a round trip test given input and the expected output
        /// </summary>
        private void AuthenticatedAesCngRoundTripTest(RoundTripTestData testData)
        {
            using (AuthenticatedAesCng aes = new AuthenticatedAesCng())
            {
                aes.CngMode = testData.ChainingMode;

                if (testData.Key != null)
                {
                    aes.Key = testData.Key;
                }

                if (testData.IV != null)
                {
                    aes.IV = testData.IV;
                }

                if (testData.AuthenticationData != null)
                {
                    aes.AuthenticatedData = testData.AuthenticationData;
                }

                if (testData.ExpectedTag != null)
                {
                    aes.Tag = testData.ExpectedTag;
                }

                // Encrypt
                byte[] ciphertext = null;
                byte[] tag        = null;
                using (MemoryStream ms = new MemoryStream())
                    using (IAuthenticatedCryptoTransform encryptor = aes.CreateAuthenticatedEncryptor())
                        using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
                        {
                            cs.Write(testData.Plaintext, 0, testData.Plaintext.Length);
                            cs.FlushFinalBlock();

                            tag        = encryptor.GetTag();
                            ciphertext = ms.ToArray();

                            // Check if the ciphertext and tag are what are expected.
                            if (testData.ExpectedCiphertext != null)
                            {
                                Assert.IsTrue(Util.CompareBytes(testData.ExpectedCiphertext, ciphertext));
                            }

                            if (testData.ExpectedTag != null)
                            {
                                Assert.IsTrue(Util.CompareBytes(testData.ExpectedTag, tag));
                            }
                        }

                if (testData.ExpectedTag == null)
                {
                    aes.Tag = tag;
                }

                // Decrypt
                using (MemoryStream ms = new MemoryStream())
                    using (ICryptoTransform decryptor = aes.CreateDecryptor())
                        using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Write))
                        {
                            cs.Write(ciphertext, 0, ciphertext.Length);
                            cs.FlushFinalBlock();

                            // Compare the decrypted text to the initial ciphertext.
                            byte[] decrypted = ms.ToArray();
                            Assert.IsTrue(Util.CompareBytes(testData.Plaintext, decrypted));
                        }
            }
        }
示例#8
0
        public override string ToString()
        {
            string header    = JsonConvert.SerializeObject(this);
            string claims    = JsonConvert.SerializeObject(this.claims);
            string signature = String.Empty; //First segment

            using (HMACSHA256 hmac = new HMACSHA256())
            {
                string data           = String.Format("{0}.{1}", header, claims);
                byte[] signatureBytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(data));
                signature = signatureBytes.ToBase64String();
            }

            byte[] masterKey  = new byte[32];
            byte[] initVector = new byte[12]; //Third segment
            using (var provider = new RNGCryptoServiceProvider())
            {
                provider.GetBytes(masterKey);
                provider.GetBytes(initVector);
            }


            byte[] encryptedMasterKey = null; //Second segment
            using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
            {
                rsa.FromXmlString(this.AsymmetricKey);
                encryptedMasterKey = rsa.Encrypt(masterKey, true); // OAEP Padding
            }

            var authData = new EncryptedPayload()
            {
                Header = header, EncryptedMasterKey = encryptedMasterKey, InitializationVector = initVector
            };

            byte[] additionalAuthenticatedData = authData.ToAdditionalAuthenticatedData();

            byte[] tag        = null; //Fifth segment
            byte[] cipherText = null; //Fourth segment
            using (var aes = new AuthenticatedAesCng())
            {
                aes.CngMode           = CngChainingMode.Gcm; // Galois/Counter Mode
                aes.Key               = masterKey;
                aes.IV                = initVector;
                aes.AuthenticatedData = additionalAuthenticatedData;
                using (MemoryStream ms = new MemoryStream())
                {
                    using (IAuthenticatedCryptoTransform encryptor = aes.CreateAuthenticatedEncryptor())
                    {
                        using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
                        {
                            // Encrypt the claims set
                            byte[] claimsSet = Encoding.UTF8.GetBytes(claims);
                            cs.Write(claimsSet, 0, claimsSet.Length);
                            cs.FlushFinalBlock();
                            tag        = encryptor.GetTag();
                            cipherText = ms.ToArray();
                        }
                    }
                }
            }

            authData.CipherText = cipherText;
            authData.Tag        = tag;

            return(authData.ToString());
        }
        /// <summary>
        ///     Utility to encapsulate round-tripping ciphertext
        /// </summary>
        private static bool RoundTripHelper <TEncryptionAlgorithm, TDecryptionAlgorithm>(Action <TEncryptionAlgorithm> encryptionSetup,
                                                                                         Action <TDecryptionAlgorithm> decryptionSetup)
            where TEncryptionAlgorithm : AuthenticatedSymmetricAlgorithm, new()
            where TDecryptionAlgorithm : AuthenticatedSymmetricAlgorithm, new()
        {
            // Encryption parameters
            byte[] key = null;
            byte[] iv  = null;
            byte[] authenticatedData = Encoding.UTF8.GetBytes("Additional authenticated data");

            // Round tripping data
            byte[] plainText  = Encoding.UTF8.GetBytes("Authenticated round trip message");
            byte[] cipherText = null;
            byte[] tag        = null;
            AuthenticatedSymmetricEncryptionState encryptionState = null;

            AuthenticatedSymmetricAlgorithm encryptionObject = null;

            try
            {
                // Setup the encryption algorithm
                encryptionObject = new TEncryptionAlgorithm();
                encryptionObject.AuthenticatedData = authenticatedData;
                encryptionObject.IV = new byte[] { 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 };
                encryptionSetup(encryptionObject as TEncryptionAlgorithm);
                encryptionObject = encryptionObject.EnableLogging();

                // Encrypt the data
                using (MemoryStream ms = new MemoryStream())
                    using (IAuthenticatedCryptoTransform encryptor = encryptionObject.CreateAuthenticatedEncryptor())
                        using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
                        {
                            cs.Write(plainText, 0, plainText.Length);
                            cs.FlushFinalBlock();

                            cipherText = ms.ToArray();
                            tag        = encryptor.GetTag();
                        }

                // Save the encryption parameters
                key = encryptionObject.Key;
                iv  = encryptionObject.IV;
                authenticatedData = encryptionObject.AuthenticatedData;
                encryptionState   = encryptionObject.GetLastEncryptionState();
            }
            finally
            {
                if (encryptionObject != null)
                {
                    (encryptionObject as IDisposable).Dispose();
                }
            }

            byte[] roundTrip = null;

            // Now verify the data
            AuthenticatedSymmetricAlgorithm decryptionObject = null;

            try
            {
                decryptionObject = new TDecryptionAlgorithm();

                decryptionObject.Key = key;
                decryptionObject.IV  = iv;
                decryptionObject.AuthenticatedData = authenticatedData;
                decryptionObject.Tag = tag;

                decryptionSetup(decryptionObject as TDecryptionAlgorithm);
                decryptionObject = decryptionObject.EnableDecryptionVerification(encryptionState);

                using (MemoryStream ms = new MemoryStream())
                    using (CryptoStream cs = new CryptoStream(ms, decryptionObject.CreateDecryptor(), CryptoStreamMode.Write))
                    {
                        cs.Write(cipherText, 0, cipherText.Length);
                        cs.FlushFinalBlock();

                        roundTrip = ms.ToArray();
                    }
            }
            finally
            {
                if (decryptionObject != null)
                {
                    (decryptionObject as IDisposable).Dispose();
                }
            }

            if (roundTrip.Length != plainText.Length)
            {
                return(false);
            }

            for (int i = 0; i < roundTrip.Length; ++i)
            {
                if (roundTrip[i] != plainText[i])
                {
                    return(false);
                }
            }

            return(true);
        }
示例#10
0
        public override string ToString()
        {
            string header = JsonConvert.SerializeObject(this);
            string claims = JsonConvert.SerializeObject(this.claims);

            // Generate a 256 bit random Content Master Key and a 96 bit initialization vector
            byte[] masterKey  = new byte[32];
            byte[] initVector = new byte[12];
            using (var provider = new RNGCryptoServiceProvider())
            {
                provider.GetBytes(masterKey);
                provider.GetBytes(initVector);
            }

            byte[] encryptedMasterKey = null;
            using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
            {
                rsa.FromXmlString(this.AsymmetricKey);
                encryptedMasterKey = rsa.Encrypt(masterKey, true); // OAEP Padding
            }

            var authData = new EncryptedPayload()
            {
                Header               = header,
                EncryptedMasterKey   = encryptedMasterKey,
                InitializationVector = initVector
            };

            byte[] additionalAuthenticatedData = authData.ToAdditionalAuthenticatedData();

            byte[] tag        = null;
            byte[] cipherText = null;

            using (var aes = new AuthenticatedAesCng())
            {
                aes.CngMode           = CngChainingMode.Gcm; // Galois/Counter Mode
                aes.Key               = masterKey;
                aes.IV                = initVector;
                aes.AuthenticatedData = additionalAuthenticatedData;

                using (MemoryStream ms = new MemoryStream())
                {
                    using (IAuthenticatedCryptoTransform encryptor = aes.CreateAuthenticatedEncryptor())
                    {
                        using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
                        {
                            // Encrypt the claims set
                            byte[] claimsSet = Encoding.UTF8.GetBytes(claims);
                            cs.Write(claimsSet, 0, claimsSet.Length);
                            cs.FlushFinalBlock();
                            tag        = encryptor.GetTag();
                            cipherText = ms.ToArray();
                        }
                    }
                }
            }

            var payload = new EncryptedPayload()
            {
                Header               = header,
                EncryptedMasterKey   = encryptedMasterKey,
                InitializationVector = initVector,
                CipherText           = cipherText,
                Tag = tag
            };

            string token = payload.ToString();

            return(token);
        }