Пример #1
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());
                        }
            }
        }
Пример #2
0
        private byte[] DecryptBuffer(byte[] encryptedInput, byte[] nonce, byte[] gcmtag, int keyinfo)
        {
            byte[] result;

            using (var authenticatedAesCng = new AuthenticatedAesCng())
            {
                authenticatedAesCng.CngMode = CngChainingMode.Gcm;
                if (keyinfo == 1)
                {
                    authenticatedAesCng.Key = this._key;
                }
                else if (keyinfo == 2)
                {
                    authenticatedAesCng.Key = this._altKey;
                }
                authenticatedAesCng.IV  = nonce;
                authenticatedAesCng.Tag = gcmtag;
                using (MemoryStream memoryStream = new MemoryStream())
                {
                    using (CryptoStream cryptoStream = new CryptoStream(memoryStream, authenticatedAesCng.CreateDecryptor(), CryptoStreamMode.Write))
                    {
                        cryptoStream.Write(encryptedInput, 0, encryptedInput.Length);
                        cryptoStream.FlushFinalBlock();
                        result = memoryStream.ToArray();
                    }
                }
            }
            return(result);
        }
Пример #3
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;
                }
            }
        }
Пример #4
0
        public static JsonWebEncryptedToken Parse(string token, string privateKey)
        {
            byte[]           claimSet = null;
            EncryptedPayload payload  = null;

            try
            {
                payload = EncryptedPayload.Parse(token);

                byte[] masterKey = null;
                using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
                {
                    rsa.FromXmlString(privateKey);
                    masterKey = rsa.Decrypt(payload.EncryptedMasterKey, true);
                }

                byte[] additionalAuthenticatedData = payload.ToAdditionalAuthenticatedData();
                using (AuthenticatedAesCng aes = new AuthenticatedAesCng())
                {
                    aes.CngMode           = CngChainingMode.Gcm;
                    aes.Key               = masterKey;
                    aes.IV                = payload.InitializationVector;
                    aes.AuthenticatedData = additionalAuthenticatedData;
                    aes.Tag               = payload.Tag;

                    using (MemoryStream ms = new MemoryStream())
                    {
                        using (CryptoStream cs = new CryptoStream(ms, aes.CreateDecryptor(),
                                                                  CryptoStreamMode.Write))
                        {
                            byte[] cipherText = payload.CipherText;
                            cs.Write(cipherText, 0, cipherText.Length);
                            cs.FlushFinalBlock();

                            claimSet = ms.ToArray();
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                throw new SecurityException("Invalid Token", ex);
            }

            var jwt = JsonConvert.DeserializeObject <JsonWebEncryptedToken>(payload.Header);

            jwt.AsymmetricKey = privateKey;
            jwt.claims        = JsonConvert.DeserializeObject
                                <Dictionary <string, string> >(Encoding.UTF8.GetString(claimSet));

            TimeSpan ts = DateTime.UtcNow - epochStart;

            if (jwt.ExpiresOn < Convert.ToUInt64(ts.TotalSeconds))
            {
                throw new SecurityException("Token has expired");
            }

            return(jwt);
        }
Пример #5
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));
                        }
            }
        }
Пример #6
0
 public static byte[] GenerateKey()
 {
     using (var aes = new AuthenticatedAesCng())
     {
         aes.CngMode = CngChainingMode.Gcm;
         aes.GenerateKey();
         return(aes.Key);
     }
 }
Пример #7
0
 public void AuthenticatedAesCngPropertiesTest()
 {
     using (AuthenticatedAesCng aes = new AuthenticatedAesCng())
     {
         Assert.AreEqual(128, aes.BlockSize);
         Assert.AreEqual(CngChainingMode.Gcm, aes.CngMode);
         Assert.AreEqual(256, aes.KeySize);
         Assert.AreEqual(128, aes.TagSize);
         Assert.AreEqual(CngProvider2.MicrosoftPrimitiveAlgorithmProvider, aes.Provider);
     }
 }
Пример #8
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));
                        }
                }
            }
        }
Пример #10
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);
        }
Пример #11
0
        public static byte[] Decrypt(byte[] record, byte[] key)
        {
            if (key.Length != KEY_SIZE)
            {
                throw new ArgumentOutOfRangeException(nameof(key), "Invalid key size.");
            }

            //check version
            if (record[0] != VERSION)
            {
                var offset = 1;
                var nonce  = new byte[NONCE_SIZE];
                Buffer.BlockCopy(record, 1, nonce, 0, NONCE_SIZE);

                offset += NONCE_SIZE;
                var tag = new byte[TAG_SIZE];
                Buffer.BlockCopy(record, offset, tag, 0, TAG_SIZE);

                offset += TAG_SIZE;
                var cipherText = new byte[record.Length - HEADER_LENGTH];
                Buffer.BlockCopy(record, offset, cipherText, 0, record.Length - HEADER_LENGTH);

                using (var aes = new AuthenticatedAesCng())
                {
                    aes.CngMode = CngChainingMode.Gcm;
                    aes.KeySize = KEY_SIZE * 8; //bytes to bits
                    aes.Key     = key;
                    aes.IV      = nonce;
                    aes.Tag     = tag;

                    using (var ms = new MemoryStream())
                        using (var encryptor = aes.CreateDecryptor())
                            using (var cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
                            {
                                cs.Write(cipherText, 0, cipherText.Length);
                                cs.FlushFinalBlock();
                                return(ms.ToArray());
                            }
                }
            }
            else
            {
                //unsupported data versions
                throw new CryptographicException("Unsupported encrypted format.");
            }
        }
Пример #12
0
        public static byte[] Decrypt(byte[] record, byte[] key)
        {
            if (key.Length != KEY_SIZE)
            {
                throw new ArgumentOutOfRangeException("key", "Invalid key size.");
            }

            //check version
            if (record[0] != VERSION)
            {
                var offset = 1;
                var nonce = new byte[NONCE_SIZE];
                Buffer.BlockCopy(record, 1, nonce, 0, NONCE_SIZE);

                offset += NONCE_SIZE;
                var tag = new byte[TAG_SIZE];
                Buffer.BlockCopy(record, offset, tag, 0, TAG_SIZE);

                offset += TAG_SIZE;
                var cipherText = new byte[record.Length - HEADER_LENGTH];
                Buffer.BlockCopy(record, offset, cipherText, 0, record.Length - HEADER_LENGTH);

                using (var aes = new AuthenticatedAesCng())
                {
                    aes.CngMode = CngChainingMode.Gcm;
                    aes.KeySize = KEY_SIZE * 8; //bytes to bits
                    aes.Key = key;
                    aes.IV = nonce;
                    aes.Tag = tag;

                    using (var ms = new MemoryStream())
                    using (var encryptor = aes.CreateDecryptor())
                    using (var cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
                    {
                        cs.Write(cipherText, 0, cipherText.Length);
                        cs.FlushFinalBlock();
                        return ms.ToArray();
                    }
                }
            }
            else
            {
                //unsupported data versions
                throw new CryptographicException("Unsupported encrypted format.");
            }
        }
Пример #13
0
        public void AuthenticatedAesCngUpdateModePreserveTagTest()
        {
            using (AuthenticatedAesCng aes = new AuthenticatedAesCng())
            {
                byte[] originalTag = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
                aes.Tag = originalTag;

                // We just set the tag, so it should be valid
                Assert.IsTrue(Util.CompareBytes(originalTag, aes.Tag));

                // Changing to the current mode should not reset the tag
                aes.CngMode = aes.CngMode;
                Assert.IsTrue(Util.CompareBytes(originalTag, aes.Tag));

                // Explicitly changing to GCM should not reset the tag
                aes.CngMode = CngChainingMode.Gcm;
                Assert.IsTrue(Util.CompareBytes(originalTag, aes.Tag));

                // Switching from GCM to CCM should not reset the tag
                aes.CngMode = CngChainingMode.Ccm;
                Assert.IsTrue(Util.CompareBytes(originalTag, aes.Tag));

                // Switching from CCM back to GCM should not reset the tag
                aes.CngMode = CngChainingMode.Gcm;
                Assert.IsTrue(Util.CompareBytes(originalTag, aes.Tag));

                // Using a large tag size that both modes support should not cause a reset
                byte[] largeTag = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
                aes.CngMode = CngChainingMode.Ccm;
                aes.Tag     = largeTag;
                Assert.IsTrue(Util.CompareBytes(largeTag, aes.Tag));
                aes.CngMode = CngChainingMode.Gcm;
                Assert.IsTrue(Util.CompareBytes(largeTag, aes.Tag));

                // However, using a small tag size that is only supported in CCM should reset when we switch
                // to GCM
                byte[] smallTag = new byte[] { 0, 1, 2, 3 };
                aes.CngMode = CngChainingMode.Ccm;
                aes.Tag     = smallTag;
                Assert.IsTrue(Util.CompareBytes(smallTag, aes.Tag));
                aes.CngMode = CngChainingMode.Gcm;
                Assert.IsFalse(Util.CompareBytes(smallTag, aes.Tag));
            }
        }
Пример #14
0
        public void Initialize(byte[] key)
        {
            if (IsInitialized)
            {
                throw new InvalidOperationException("PacketCrypt already initialized!");
            }

            _clientDecrypt         = new AuthenticatedAesCng();
            _clientDecrypt.Key     = key;
            _clientDecrypt.CngMode = CngChainingMode.Gcm;
            _clientDecrypt.TagSize = 96;

            _serverEncrypt         = new AuthenticatedAesCng();
            _serverEncrypt.Key     = key;
            _serverEncrypt.CngMode = CngChainingMode.Gcm;
            _serverEncrypt.TagSize = 96;

            IsInitialized = true;
        }
        public static string DecryptString(string str)
        {
            if (String.IsNullOrEmpty(str))
            {
                throw new ArgumentNullException("decryption string invalid");
            }

            using (AuthenticatedAesCng aes = new AuthenticatedAesCng())
            {
                byte[] encrypted = Convert.FromBase64String(str);               // Convert string to bytes.
                aes.Key               = GetEncryptionKey();                     // Retrieve Key.
                aes.IV                = GetIV(encrypted);                       // Parse IV from encrypted text.
                aes.Tag               = GetTag(encrypted);                      // Parse Tag from encrypted text.
                encrypted             = RemoveTagAndIV(encrypted);              // Remove Tag and IV for proper decryption.
                aes.CngMode           = CngChainingMode.Gcm;                    // Set Cryptographic Mode.
                aes.AuthenticatedData = GetAdditionalAuthenticationData();      // Set Authentication Data.

                using (MemoryStream memoryStream = new MemoryStream())
                    using (ICryptoTransform decryptor = aes.CreateDecryptor())
                        using (CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Write))
                        {
                            // Decrypt through stream.
                            cryptoStream.Write(encrypted, 0, encrypted.Length);

                            // If the authentication tag does not validate, this call will throw a CryptographicException.
                            try
                            {
                                cryptoStream.FlushFinalBlock();
                            }
                            catch (CryptographicException cryptoException)
                            {
                            }
                            catch (NotSupportedException notSupportedException)
                            {
                            }

                            // Remove from stream and convert to string.
                            byte[] decrypted = memoryStream.ToArray();
                            return(Encoding.UTF8.GetString(decrypted));
                        }
            }
        }
Пример #16
0
        public byte[] Decrypt(byte[] key, byte[] encryptedText)
        {
            using (var authAesCng = new AuthenticatedAesCng())
            {
                authAesCng.CngMode = CngChainingMode.Gcm;

                authAesCng.Key = key;
                authAesCng.IV = GetIV(encryptedText);
                authAesCng.Tag = GetTag(encryptedText);
                var cipherText = GetCipherText(encryptedText);
                using (var stream = new MemoryStream())
                using (var encryptor = authAesCng.CreateDecryptor())
                using (var cryptoStream = new CryptoStream(stream, encryptor, CryptoStreamMode.Write))
                {
                    cryptoStream.Write(cipherText, 0, cipherText.Length);
                    cryptoStream.FlushFinalBlock();

                    return stream.ToArray();
                }
            }
        }
        // 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.");
        }
Пример #19
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);
                        }
            }
        }
Пример #20
0
        public static JWE Parse(string token, string privateKey)
        {
            byte[] claimSet = null;
            EncryptedPayload payload = null;

            try
            {
                payload = EncryptedPayload.Parse(token);

                byte[] masterKey = null;
                using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
                {
                    rsa.FromXmlString(privateKey);
                    masterKey = rsa.Decrypt(payload.EncryptedMasterKey, true);
                }

                byte[] additionalAuthenticatedData = payload.ToAdditionalAuthenticatedData();
                using (AuthenticatedAesCng aes = new AuthenticatedAesCng())
                {
                    aes.CngMode = CngChainingMode.Gcm;
                    aes.Key = masterKey;
                    aes.IV = payload.InitializationVector;
                    aes.AuthenticatedData = additionalAuthenticatedData;
                    aes.Tag = payload.Tag;

                    using (MemoryStream ms = new MemoryStream())
                    {
                        using (CryptoStream cs = new CryptoStream(ms, aes.CreateDecryptor(),CryptoStreamMode.Write))
                        {
                            byte[] cipherText = payload.CipherText;
                            cs.Write(cipherText, 0, cipherText.Length);
                            cs.FlushFinalBlock();

                            claimSet = ms.ToArray();
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                throw new SecurityException("Invalid Token", ex);
            }

            var jwt = JsonConvert.DeserializeObject<JWE>(payload.Header);
            jwt.AsymmetricKey = privateKey;
            jwt.claims = JsonConvert.DeserializeObject<Dictionary<string, string>>(Encoding.UTF8.GetString(claimSet));

            TimeSpan ts = DateTime.UtcNow - epochStart;

            if (jwt.ExpiresOn < Convert.ToUInt64(ts.TotalSeconds))
                throw new SecurityException("Token has expired");

            return jwt;
        }
Пример #21
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));
                            }
                }
            }
        }
Пример #22
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));
                        }
            }
        }
Пример #23
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;
        }
Пример #24
0
        public static Some<Tuple<string, long>> EncryptFile(string dstDir, EncryptOperation oper, byte[] key)
        {
            if (!File.Exists(oper.FileName)) return ErrorValues[ErrorType.FileNoExist];

            var outputFileName = Path.Combine(dstDir, oper.EncFileName);
            var outputDir = Path.GetDirectoryName(outputFileName);
            if (string.IsNullOrWhiteSpace(outputDir)) return ErrorValues[ErrorType.OutDirMissing];
            Directory.CreateDirectory(outputDir);

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

                byte[] tag;

                using (var outputFile = File.OpenWrite(outputFileName))
                {
                    outputFile.Write(OuterMagicHeader.ToArray());
                    outputFile.Write(BitConverter.GetBytes(aes.Tag.Length));
                    outputFile.Write(BitConverter.GetBytes(aes.IV.Length));
                    outputFile.Write(aes.Tag);
                    outputFile.Write(aes.IV);

                    using (var enc = aes.CreateEncryptor())
                    {
                        using (var cryptoStream = new CryptoStream(outputFile, enc, CryptoStreamMode.Write))
                        {
                            cryptoStream.Write(MagicHeader.ToArray());
                            var fileName = Encoding.UTF8.GetBytes(oper.RelFileName);
                            var fileNameSize = BitConverter.GetBytes(Convert.ToInt32(fileName.Length));
                            cryptoStream.Write(fileNameSize);
                            cryptoStream.Write(fileName);

                            using (var inputFile = File.OpenRead(oper.FileName))
                            {
                                inputFile.CopyTo(cryptoStream);
                            }
                        }

                        tag = ((IAuthenticatedCryptoTransform)enc).GetTag();
                    }
                }

                using (var outputFile = File.OpenWrite(outputFileName))
                {
                    outputFile.Seek(TagStartPos, SeekOrigin.Begin);
                    outputFile.Write(tag, 0, tag.Length);
                }

                return new Some<Tuple<string, long>>(Tuple.Create(outputFileName, new FileInfo(oper.FileName).Length));
            }
        }
Пример #25
0
 public static byte[] GenerateKey()
 {
     using (var aes = new AuthenticatedAesCng())
     {
         aes.CngMode = CngChainingMode.Gcm;
         aes.GenerateKey();
         return aes.Key;
     }
 }
Пример #26
0
        public byte[] Decrypt(byte[] cipherBytes, int AddtnlAuthDataLength)
        {
            if (cipherBytes == null)
                return null;

            byte[] tag = new byte[TagBitSize / 8];

            try
            {

                using (AuthenticatedAesCng aes = new AuthenticatedAesCng())
                {
                    using (var cipherReader = new BinaryReader(new MemoryStream(cipherBytes)))
                    {
                        aes.CngMode = CngChainingMode.Gcm;
                        aes.Key = aesKey;
                        //Read Additional Authenticated Data (AddtnlAuthData)
                        aes.AuthenticatedData = cipherReader.ReadBytes(AddtnlAuthDataLength);
                        aes.IV = cipherReader.ReadBytes(IVBitSize / 8);
                        // Tag lives at the end and it small, array copy it over
                        Array.Copy(cipherBytes, cipherBytes.Length - (TagBitSize / 8), tag, 0, (TagBitSize / 8));
                        aes.Tag = tag;
                    }

                    using (var ms = new MemoryStream())
                    using (var cs = new CryptoStream(ms, aes.CreateDecryptor(), CryptoStreamMode.Write))
                    {
                        int startOffset = AddtnlAuthDataLength + (IVBitSize / 8);
                        var length = cipherBytes.Length - AddtnlAuthDataLength - (IVBitSize / 8) - (TagBitSize / 8);

                        cs.Write(cipherBytes, startOffset, length);

                        // If the authentication tag does not match, we'll fail here with a
                        // CryptographicException, and the ciphertext will not be decrypted.
                        cs.FlushFinalBlock();

                        return ms.ToArray();
                    }
                }
            }

            catch (Exception ex)
            {
                //Logger.Exception(ex);
                if (ex is ArgumentException ||
                    ex is CryptographicException ||
                    ex is OverflowException)
                {
                    return null; // this is null here
                }
                else
                {
                    throw;
                }
            }
        }
Пример #27
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);
        }
Пример #28
0
        public static Some<Tuple<string, long>> DecryptFile(string dstDir, string filename, byte[] key)
        {
            if (!File.Exists(filename)) return ErrorValues[ErrorType.FileNoExist];

            using (var inputFile = File.OpenRead(filename))
            {
                var outerBuffer = new byte[TagStartPos];
                if (inputFile.Read(outerBuffer, 0, outerBuffer.Length) != outerBuffer.Length)
                {
                    return ErrorValues[ErrorType.NotAnEncryptedFile];
                }

                if (!outerBuffer.Take(OuterMagicHeader.Count).SequenceEqual(OuterMagicHeader))
                {
                    return ErrorValues[ErrorType.MagicBytesMismatch];
                }

                var tagLength = BitConverter.ToInt32(outerBuffer, OuterMagicHeader.Count);
                var ivLength = BitConverter.ToInt32(outerBuffer, OuterMagicHeader.Count + sizeof(Int32));

                using (var aes = new AuthenticatedAesCng())
                {
                    outerBuffer = new byte[tagLength + ivLength];
                    if (inputFile.Read(outerBuffer, 0, outerBuffer.Length) != outerBuffer.Length)
                    {
                        return ErrorValues[ErrorType.NotAnEncryptedFile];
                    }

                    aes.CngMode = CngChainingMode.Gcm;
                    aes.Key = key;
                    aes.Tag = outerBuffer.Take(tagLength).ToArray();
                    aes.IV = outerBuffer.Skip(tagLength).Take(ivLength).ToArray();

                    using (var dec = aes.CreateDecryptor())
                    using (var cryptoStream = new CryptoStream(inputFile, dec, CryptoStreamMode.Read))
                    {
                        var buf = new byte[MagicHeader.Count + sizeof(Int32)];
                        if (cryptoStream.Read(buf, 0, buf.Length) != buf.Length)
                        {
                            return ErrorValues[ErrorType.CorruptFile];
                        }

                        if (!buf.Take(MagicHeader.Count).SequenceEqual(MagicHeader))
                        {
                            return ErrorValues[ErrorType.MagicBytesMismatch];
                        }

                        var nameLength = BitConverter.ToInt32(buf, MagicHeader.Count);
                        buf = new byte[nameLength];
                        if (cryptoStream.Read(buf, 0, buf.Length) != buf.Length)
                        {
                            return ErrorValues[ErrorType.CorruptFile];
                        }
                        var fileName = Encoding.UTF8.GetString(buf, 0, buf.Length);

                        var outputFileName = Path.Combine(dstDir, fileName);
                        var outputDir = Path.GetDirectoryName(outputFileName);

                        if (string.IsNullOrWhiteSpace(outputDir)) return ErrorValues[ErrorType.OutDirMissing];
                        Directory.CreateDirectory(outputDir);

                        try
                        {
                            using (var outputFile = File.OpenWrite(outputFileName))
                            {
                                cryptoStream.CopyTo(outputFile);
                            }
                        }
                        catch (CryptographicException)
                        {
                            File.Delete(outputFileName);
                            return ErrorValues[ErrorType.FailedChecksum];
                        }

                        return new Some<Tuple<string, long>>(Tuple.Create(outputFileName, new FileInfo(outputFileName).Length));
                    }
                }
            }
        }
Пример #29
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);
        }
Пример #30
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;
                }
            }
        }
        public void AuthenticatedSymmetricAlgorithmVerifierNegativeThreadingTest()
        {
            // Synchronization state
            object lockCheckParameter = new object();
            AuthenticatedSymmetricAlgorithm encryptorInstance = null;
            bool lockChecked = false;

            SymmetricAlgorithmDiagnosticOptions diagnosticOptions = new SymmetricAlgorithmDiagnosticOptions
            {
                CheckThreadSafety  = true,
                LockCheckParameter = lockCheckParameter,
                LockCheckCallback  = delegate(CryptographyLockContext <SymmetricAlgorithm> lockCheck)
                {
                    Assert.AreSame(lockCheck.Parameter, lockCheckParameter, "Unexpected lock check parameter");
                    Assert.AreSame(lockCheck.Algorithm, encryptorInstance, "Unexpected algorithm check parameter");
                    lockChecked = true;
                    return(false);
                }
            };

            // Encryption state
            bool      encryptionSucceeded = true;
            Exception encryptionException = null;

            try
            {
                encryptorInstance = new AuthenticatedAesCng();
                AuthenticatedSymmetricAlgorithm encryptor = encryptorInstance.EnableLogging(diagnosticOptions);

                // Thread to do the encryption
                Thread encryptionThread = new Thread(delegate()
                {
                    try
                    {
                        using (MemoryStream ms = new MemoryStream())
                            using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateEncryptor(), CryptoStreamMode.Write))
                            {
                                byte[] plainText = Encoding.UTF8.GetBytes("Secret round trip message");
                                cs.Write(plainText, 0, plainText.Length);
                                cs.FlushFinalBlock();
                            }

                        encryptionSucceeded = true;
                    }
                    catch (Exception e)
                    {
                        encryptionException = e;
                        encryptionSucceeded = false;
                    }
                });

                encryptionThread.Start();
                encryptionThread.Join();
            }
            finally
            {
                if (encryptorInstance != null)
                {
                    (encryptorInstance as IDisposable).Dispose();
                }
            }

            // Verify that our lock check was called, that we failed encryption, and that we got the correct exception
            Assert.IsTrue(lockChecked, "Lock check callback was not performed");
            Assert.IsFalse(encryptionSucceeded, "Encryption should not have succeeded");
            Assert.IsInstanceOfType(encryptionException, typeof(CryptographicDiagnosticException), "Did not get expected exception");
        }
Пример #32
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();
            }
        }
Пример #33
0
        public static Some <Tuple <string, long> > EncryptFile(string dstDir, EncryptOperation oper, byte[] key)
        {
            if (!File.Exists(oper.FileName))
            {
                return(ErrorValues[ErrorType.FileNoExist]);
            }

            var outputFileName = Path.Combine(dstDir, oper.EncFileName);
            var outputDir      = Path.GetDirectoryName(outputFileName);

            if (string.IsNullOrWhiteSpace(outputDir))
            {
                return(ErrorValues[ErrorType.OutDirMissing]);
            }
            Directory.CreateDirectory(outputDir);

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

                byte[] tag;

                using (var outputFile = File.OpenWrite(outputFileName))
                {
                    outputFile.Write(OuterMagicHeader.ToArray());
                    outputFile.Write(BitConverter.GetBytes(aes.Tag.Length));
                    outputFile.Write(BitConverter.GetBytes(aes.IV.Length));
                    outputFile.Write(aes.Tag);
                    outputFile.Write(aes.IV);

                    using (var enc = aes.CreateEncryptor())
                    {
                        using (var cryptoStream = new CryptoStream(outputFile, enc, CryptoStreamMode.Write))
                        {
                            cryptoStream.Write(MagicHeader.ToArray());
                            var fileName     = Encoding.UTF8.GetBytes(oper.RelFileName);
                            var fileNameSize = BitConverter.GetBytes(Convert.ToInt32(fileName.Length));
                            cryptoStream.Write(fileNameSize);
                            cryptoStream.Write(fileName);

                            using (var inputFile = File.OpenRead(oper.FileName))
                            {
                                inputFile.CopyTo(cryptoStream);
                            }
                        }

                        tag = ((IAuthenticatedCryptoTransform)enc).GetTag();
                    }
                }

                using (var outputFile = File.OpenWrite(outputFileName))
                {
                    outputFile.Seek(TagStartPos, SeekOrigin.Begin);
                    outputFile.Write(tag, 0, tag.Length);
                }

                return(new Some <Tuple <string, long> >(Tuple.Create(outputFileName, new FileInfo(oper.FileName).Length)));
            }
        }
Пример #34
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());
        }
Пример #35
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;
                }
            }
        }
Пример #36
0
        public static Some <Tuple <string, long> > DecryptFile(string dstDir, string filename, byte[] key)
        {
            if (!File.Exists(filename))
            {
                return(ErrorValues[ErrorType.FileNoExist]);
            }

            using (var inputFile = File.OpenRead(filename))
            {
                var outerBuffer = new byte[TagStartPos];
                if (inputFile.Read(outerBuffer, 0, outerBuffer.Length) != outerBuffer.Length)
                {
                    return(ErrorValues[ErrorType.NotAnEncryptedFile]);
                }

                if (!outerBuffer.Take(OuterMagicHeader.Count).SequenceEqual(OuterMagicHeader))
                {
                    return(ErrorValues[ErrorType.MagicBytesMismatch]);
                }

                var tagLength = BitConverter.ToInt32(outerBuffer, OuterMagicHeader.Count);
                var ivLength  = BitConverter.ToInt32(outerBuffer, OuterMagicHeader.Count + sizeof(Int32));

                using (var aes = new AuthenticatedAesCng())
                {
                    outerBuffer = new byte[tagLength + ivLength];
                    if (inputFile.Read(outerBuffer, 0, outerBuffer.Length) != outerBuffer.Length)
                    {
                        return(ErrorValues[ErrorType.NotAnEncryptedFile]);
                    }

                    aes.CngMode = CngChainingMode.Gcm;
                    aes.Key     = key;
                    aes.Tag     = outerBuffer.Take(tagLength).ToArray();
                    aes.IV      = outerBuffer.Skip(tagLength).Take(ivLength).ToArray();

                    using (var dec = aes.CreateDecryptor())
                        using (var cryptoStream = new CryptoStream(inputFile, dec, CryptoStreamMode.Read))
                        {
                            var buf = new byte[MagicHeader.Count + sizeof(Int32)];
                            if (cryptoStream.Read(buf, 0, buf.Length) != buf.Length)
                            {
                                return(ErrorValues[ErrorType.CorruptFile]);
                            }

                            if (!buf.Take(MagicHeader.Count).SequenceEqual(MagicHeader))
                            {
                                return(ErrorValues[ErrorType.MagicBytesMismatch]);
                            }

                            var nameLength = BitConverter.ToInt32(buf, MagicHeader.Count);
                            buf = new byte[nameLength];
                            if (cryptoStream.Read(buf, 0, buf.Length) != buf.Length)
                            {
                                return(ErrorValues[ErrorType.CorruptFile]);
                            }
                            var fileName = Encoding.UTF8.GetString(buf, 0, buf.Length);

                            var outputFileName = Path.Combine(dstDir, fileName);
                            var outputDir      = Path.GetDirectoryName(outputFileName);

                            if (string.IsNullOrWhiteSpace(outputDir))
                            {
                                return(ErrorValues[ErrorType.OutDirMissing]);
                            }
                            Directory.CreateDirectory(outputDir);

                            try
                            {
                                using (var outputFile = File.OpenWrite(outputFileName))
                                {
                                    cryptoStream.CopyTo(outputFile);
                                }
                            }
                            catch (CryptographicException)
                            {
                                File.Delete(outputFileName);
                                return(ErrorValues[ErrorType.FailedChecksum]);
                            }

                            return(new Some <Tuple <string, long> >(Tuple.Create(outputFileName, new FileInfo(outputFileName).Length)));
                        }
                }
            }
        }