Пример #1
0
        public byte[] Encrypt(byte[] key, byte[] plainText)
        {
            var iv = GenerateIV();

            using (var authAesCng = new AuthenticatedAesCng())
            {
                authAesCng.CngMode = CngChainingMode.Gcm;

                authAesCng.Key = key;
                authAesCng.IV = iv;
                authAesCng.TagSize = _tagSize;
                using (var stream = new MemoryStream())
                using (var encryptor = authAesCng.CreateAuthenticatedEncryptor())
                using (var cryptoStream = new CryptoStream(stream, encryptor, CryptoStreamMode.Write))
                {
                    cryptoStream.Write(plainText, 0, plainText.Length);
                    cryptoStream.FlushFinalBlock();
                    var cipherText = stream.ToArray();
                    var encrypted = new byte[cipherText.Length + _ivSize + _tagSize];
                    iv.CopyTo(encrypted, 0);
                    authAesCng.Tag.CopyTo(encrypted, _ivSize);
                    cipherText.CopyTo(encrypted, _ivSize + _tagSize);
                    return cipherText;
                }
            }
        }
Пример #2
0
        private static byte[] EncryptAes(byte[] nonce, byte[] cek, byte[] message)
        {
            using (AuthenticatedAesCng aes = new AuthenticatedAesCng())
            {
                aes.CngMode = CngChainingMode.Gcm;

                aes.Key = cek;

                aes.IV = nonce;

                using (MemoryStream ms = new MemoryStream())
                    using (var encryptor = aes.CreateAuthenticatedEncryptor())
                        using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
                        {
                            // Encrypt the secret message
                            cs.Write(message, 0, message.Length);

                            // Finish the encryption and get the output authentication tag and ciphertext
                            cs.FlushFinalBlock();
                            var ciphertext = ms.ToArray();

                            var tag = encryptor.GetTag();

                            return(ciphertext.Concat(tag).ToArray());
                        }
            }
        }
Пример #3
0
        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));
                        }
            }
        }
        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));
                        }
                }
            }
        }
Пример #5
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);
                }
            }
        }
Пример #6
0
        public byte[] Encrypt(byte[] Plain, out byte[] Tag, byte[] PacketHead, long PacketID)
        {
            byte[] RetVar;
            using (AuthenticatedAesCng aes = new AuthenticatedAesCng())
            {
                aes.CngMode = CngChainingMode.Gcm;
                aes.Key     = EncryptionKey;

                //------------- Build Nonce -------------
                byte[] nonce = new byte[12];
                Array.Copy(EncryptNonceHash, nonce, 4);
                //Encryption flag probably
                Array.Copy(new byte[] { 0x00, 0x01 }, 0, nonce, 4, 2);
                //Little Endian Packet ID to be send
                //Array.Copy(new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, 0, nonce, 6, 6);
                Array.Copy(BitConverter.GetBytes(PacketID).Reverse().ToArray(), 2, nonce, 6, 6);
                Console.WriteLine("nonce:" + Helpers.ByteArrayToString(nonce));
                aes.IV = nonce;

                //------------- Build Associated Data -------------
                byte[] associatedData = new byte[13]; // { 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0xFE, 0xFD, 0x00, 0x18 };
                //Encryption flag probably
                Array.Copy(new byte[] { 0x00, 0x01 }, associatedData, 2);
                //Little Endian Packet ID to be send
                Array.Copy(BitConverter.GetBytes(PacketID).Reverse().ToArray(), 2, associatedData, 2, 6);
                //Packet header
                //Array.Copy(new byte[] { 0x16, 0xFE, 0xFD }, 0, associatedData, 8, 3);
                Array.Copy(PacketHead, 0, associatedData, 8, 3);
                //data length
                short EncryptedDataLen = (short)Plain.Length;
                Array.Copy(BitConverter.GetBytes(EncryptedDataLen).Reverse().ToArray(), 0, associatedData, 11, 2);
                //Array.Copy(new byte[] { 0x00, 0x18 }, 0, associatedData, 11, 2);
                Console.WriteLine("associatedData:" + Helpers.ByteArrayToString(associatedData));

                aes.AuthenticatedData = associatedData;

                using (MemoryStream ms = new MemoryStream())

                    using (var encryptor = aes.CreateAuthenticatedEncryptor())

                        using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))

                        {
                            cs.Write(Plain, 0, Plain.Length);
                            cs.FlushFinalBlock();
                            RetVar = ms.ToArray();
                            Tag    = encryptor.GetTag();
                        }
            }

            return(RetVar);
        }
        // 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 AuthenticatedSymmetricAlgorithmVerifierTestNegativeAuthenticationEncryptStandardDecryptTest()
        {
            byte[] plaintext  = Encoding.UTF8.GetBytes("Plaintext");
            byte[] ciphertext = null;

            byte[] key = null;
            SymmetricEncryptionState encryptionState = null;

            using (AuthenticatedSymmetricAlgorithm encryptAes = new AuthenticatedAesCng().EnableLogging())
            {
                key           = encryptAes.Key;
                encryptAes.IV = new byte[] { 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 };

                using (IAuthenticatedCryptoTransform encryptor = encryptAes.CreateAuthenticatedEncryptor())
                    using (MemoryStream ms = new MemoryStream())
                        using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
                        {
                            cs.Write(plaintext, 0, plaintext.Length);
                            cs.FlushFinalBlock();

                            ciphertext      = ms.ToArray();
                            encryptionState = encryptAes.GetLastEncryptionState();
                        }
            }

            using (SymmetricAlgorithm decryptAes = new AesCng().EnableDecryptionVerification(encryptionState))
            {
                decryptAes.Key = key;

                using (MemoryStream ms = new MemoryStream())
                    using (CryptoStream cs = new CryptoStream(ms, decryptAes.CreateDecryptor(), CryptoStreamMode.Write))
                    {
                        cs.Write(ciphertext, 0, ciphertext.Length);
                        cs.FlushFinalBlock();
                    }
            }

            Assert.Fail("Decryption should have failed.");
        }
Пример #9
0
        public static byte[] Encrypt(byte[] plaintext, byte[] key)
        {
            if (key.Length != KEY_SIZE)
            {
                throw new ArgumentOutOfRangeException(nameof(key), "Invalid key size.");
            }

            var nonce = GenerateNonce();

            using (var aes = new AuthenticatedAesCng())
            {
                aes.CngMode = CngChainingMode.Gcm;
                aes.Key     = key;
                aes.IV      = nonce;

                using (var ms = new MemoryStream())
                    using (var encryptor = aes.CreateAuthenticatedEncryptor())
                        using (var cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
                        {
                            cs.Write(plaintext, 0, plaintext.Length);
                            cs.FlushFinalBlock();
                            var cipherText        = ms.ToArray();
                            var authenticationTag = encryptor.GetTag();
                            var record            = new byte[HEADER_LENGTH + cipherText.Length];

                            var offset = 1;
                            Buffer.BlockCopy(nonce, 0, record, offset, NONCE_SIZE);

                            offset += NONCE_SIZE;
                            Buffer.BlockCopy(authenticationTag, 0, record, offset, TAG_SIZE);

                            offset += TAG_SIZE;
                            Buffer.BlockCopy(cipherText, 0, record, offset, cipherText.Length);

                            return(record);
                        }
            }
        }
Пример #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);
        }
Пример #11
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;
                }
            }
        }
Пример #12
0
        /// <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));
                        }
            }
        }
Пример #13
0
        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));
                            }
                }
            }
        }
Пример #14
0
        // encrypted = LSByte [AddtnlAuthData || IV || cipherOnly || hmac ] MSByte
        public byte[] Encrypt(byte[] plainBytes, byte[] AddtnlAuthData)
        {
            if (plainBytes == null)
                return null;

            // Additional Authenticated (but NOT encrypted) Data
            AddtnlAuthData = AddtnlAuthData ?? new byte[] { };
            byte[] tag;
            byte[] cipherBytes;

            using (AuthenticatedAesCng aes = new AuthenticatedAesCng())
            {
                RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
                // Setup an authenticated chaining mode - The two current CNG options are
                // CngChainingMode.Gcm and CngChainingMode.Ccm.  This should be done before setting up
                // the other properties, since changing the chaining mode can update things such as the
                // valid and current tag sizes.
                aes.CngMode = CngChainingMode.Gcm;

                // Keys work the same as standard AES
                aes.Key = aesKey;

                // The IV (called the nonce in many of the authenticated algorithm specs) is not sized for
                // the input block size. Instead its size depends upon the algorithm.  12 bytes works
                // for both GCM and CCM. Generate a random 12 byte nonce here.
                if (this.IV == null)
                {
                    this.IV = new byte[IVBitSize / 8];
                    rng.GetBytes(this.IV);
                }

                aes.IV = this.IV;

                // Authenticated data becomes part of the authentication tag that is generated during
                // encryption, however it is not part of the ciphertext.  That is, when decrypting the
                // ciphertext the authenticated data will not be produced.  However, if the
                // authenticated data does not match at encryption and decryption time, the
                // authentication tag will not validate.
                aes.AuthenticatedData = AddtnlAuthData;

                // Perform the encryption - this works nearly the same as standard symmetric encryption,
                // however instead of using an ICryptoTransform we use an IAuthenticatedCryptoTrasform
                // which provides access to the authentication tag.
                using (MemoryStream ms = new MemoryStream())
                using (IAuthenticatedCryptoTransform encryptor = aes.CreateAuthenticatedEncryptor())
                using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
                {
                    // Encrypt the secret message
                    cs.Write(plainBytes, 0, plainBytes.Length);

                    // Finish the encryption and get the output authentication tag and ciphertext
                    cs.FlushFinalBlock();
                    tag = encryptor.GetTag();
                    cipherBytes = ms.ToArray();
                }
            }

            //Assemble Message
            using (var combinedStream = new MemoryStream())
            {
                using (var binaryWriter = new BinaryWriter(combinedStream))
                {
                    //Prepend Authenticated Payload
                    binaryWriter.Write(AddtnlAuthData);
                    //Prepend Nonce
                    binaryWriter.Write(this.IV);
                    //Write Cipher Text
                    binaryWriter.Write(cipherBytes);
                    //Write Tag
                    binaryWriter.Write(tag);
                }
                return combinedStream.ToArray();
            }
        }
Пример #15
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());
        }
Пример #16
0
        /// <summary>
        /// To encrypt this token, we need receiver's public key
        /// </summary>
        /// <returns></returns>
        public override string SerializeToBase64UrlString()
        {
            string header = JsonConvert.SerializeObject(this);
            string claims = JsonConvert.SerializeObject(this.claims);

            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 (var rsa = new RSACryptoServiceProvider())
            {
                rsa.FromXmlString(AsymmetricKey);
                encryptedMasterKey = rsa.Encrypt(masterKey, true);
            }

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

            byte[] additionalAuthenticatedData = authoData.ToAdditionalAuthenticatedData();

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

            using (var aes = new AuthenticatedAesCng())
            {
                //AES+GCM is used for encryption AND authentication(digital signature)
                aes.CngMode           = CngChainingMode.Gcm;
                aes.Key               = masterKey;
                aes.IV                = initVector;
                aes.AuthenticatedData = additionalAuthenticatedData;

                using (var ms = new MemoryStream())
                {
                    using (var encryptor = aes.CreateAuthenticatedEncryptor())
                    {
                        using (var cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
                        {
                            byte[] claimSet = Encoding.UTF8.GetBytes(claims);
                            cs.Write(claimSet, 0, claimSet.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.SerializeToBase64UrlString();

            return(token);
        }
Пример #17
0
        public static byte[] Encrypt(byte[] plaintext, byte[] key)
        {
            if (key.Length != KEY_SIZE)
            {
                throw new ArgumentOutOfRangeException("key", "Invalid key size.");
            }

            var nonce = GenerateNonce();
            using (var aes = new AuthenticatedAesCng())
            {
                aes.CngMode = CngChainingMode.Gcm;
                aes.Key = key;
                aes.IV = nonce;

                using (var ms = new MemoryStream())
                using (var encryptor = aes.CreateAuthenticatedEncryptor())
                using (var cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
                {
                    cs.Write(plaintext, 0, plaintext.Length);
                    cs.FlushFinalBlock();
                    var cipherText = ms.ToArray();
                    var authenticationTag = encryptor.GetTag();
                    var record = new byte[HEADER_LENGTH + cipherText.Length];

                    var offset = 1;
                    Buffer.BlockCopy(nonce, 0, record, offset, NONCE_SIZE);

                    offset += NONCE_SIZE;
                    Buffer.BlockCopy(authenticationTag, 0, record, offset, TAG_SIZE);

                    offset += TAG_SIZE;
                    Buffer.BlockCopy(cipherText, 0, record, offset, cipherText.Length);

                    return record;
                }
            }
        }
Пример #18
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;
        }