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()); } } }
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); }
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; } } }
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); }
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)); } } }
public static byte[] GenerateKey() { using (var aes = new AuthenticatedAesCng()) { aes.CngMode = CngChainingMode.Gcm; aes.GenerateKey(); return(aes.Key); } }
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); } }
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)); } } } }
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); }
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."); } }
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."); } }
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)); } }
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)); } } }
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."); }
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); } } }
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; }
public void AuthenticatedAesCngChainingTest() { byte[] plaintext = new byte[20 * 1024]; byte[] iv = new byte[12]; byte[] authenticatedData = new byte[1024]; using (RNGCng rng = new RNGCng()) { rng.GetBytes(plaintext); rng.GetBytes(iv); rng.GetBytes(authenticatedData); } foreach (CngChainingMode chainingMode in new CngChainingMode[] { CngChainingMode.Ccm, CngChainingMode.Gcm }) { using (AuthenticatedAesCng aes = new AuthenticatedAesCng()) { aes.AuthenticatedData = authenticatedData; aes.CngMode = chainingMode; aes.IV = iv; // Encrypt the whole block of data at once byte[] wholeCiphertext = null; byte[] wholeTag = null; using (IAuthenticatedCryptoTransform encryptor = aes.CreateAuthenticatedEncryptor()) { wholeCiphertext = encryptor.TransformFinalBlock(plaintext, 0, plaintext.Length); wholeTag = encryptor.GetTag(); } // Encrypt it in chunks byte[] blockCiphertext = null; byte[] blockTag = null; using (MemoryStream ms = new MemoryStream()) using (IAuthenticatedCryptoTransform encryptor = aes.CreateAuthenticatedEncryptor()) using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write)) { int chunkSize = 128; for (int offset = 0; offset < plaintext.Length; offset += chunkSize) { cs.Write(plaintext, offset, chunkSize); } cs.FlushFinalBlock(); blockCiphertext = ms.ToArray(); blockTag = encryptor.GetTag(); } // Make sure we got the same results in both cases Assert.IsTrue(Util.CompareBytes(wholeCiphertext, blockCiphertext)); Assert.IsTrue(Util.CompareBytes(wholeTag, blockTag)); aes.Tag = wholeTag; // Decrypt the whole block of data at once using (ICryptoTransform decryptor = aes.CreateDecryptor()) { byte[] wholePlaintext = decryptor.TransformFinalBlock(wholeCiphertext, 0, wholeCiphertext.Length); Assert.IsTrue(Util.CompareBytes(plaintext, wholePlaintext)); } // Decrypt the data in chunks using (MemoryStream ms = new MemoryStream()) using (ICryptoTransform decryptor = aes.CreateDecryptor()) using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Write)) { int chunkSize = 128; for (int offset = 0; offset < blockCiphertext.Length; offset += chunkSize) { cs.Write(blockCiphertext, offset, chunkSize); } cs.FlushFinalBlock(); byte[] blockPlaintext = ms.ToArray(); Assert.IsTrue(Util.CompareBytes(plaintext, blockPlaintext)); } } } }
/// <summary> /// Perform a round trip test given input and the expected output /// </summary> private void AuthenticatedAesCngRoundTripTest(RoundTripTestData testData) { using (AuthenticatedAesCng aes = new AuthenticatedAesCng()) { aes.CngMode = testData.ChainingMode; if (testData.Key != null) { aes.Key = testData.Key; } if (testData.IV != null) { aes.IV = testData.IV; } if (testData.AuthenticationData != null) { aes.AuthenticatedData = testData.AuthenticationData; } if (testData.ExpectedTag != null) { aes.Tag = testData.ExpectedTag; } // Encrypt byte[] ciphertext = null; byte[] tag = null; using (MemoryStream ms = new MemoryStream()) using (IAuthenticatedCryptoTransform encryptor = aes.CreateAuthenticatedEncryptor()) using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write)) { cs.Write(testData.Plaintext, 0, testData.Plaintext.Length); cs.FlushFinalBlock(); tag = encryptor.GetTag(); ciphertext = ms.ToArray(); // Check if the ciphertext and tag are what are expected. if (testData.ExpectedCiphertext != null) { Assert.IsTrue(Util.CompareBytes(testData.ExpectedCiphertext, ciphertext)); } if (testData.ExpectedTag != null) { Assert.IsTrue(Util.CompareBytes(testData.ExpectedTag, tag)); } } if (testData.ExpectedTag == null) { aes.Tag = tag; } // Decrypt using (MemoryStream ms = new MemoryStream()) using (ICryptoTransform decryptor = aes.CreateDecryptor()) using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Write)) { cs.Write(ciphertext, 0, ciphertext.Length); cs.FlushFinalBlock(); // Compare the decrypted text to the initial ciphertext. byte[] decrypted = ms.ToArray(); Assert.IsTrue(Util.CompareBytes(testData.Plaintext, decrypted)); } } }
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; }
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)); } }
public static byte[] GenerateKey() { using (var aes = new AuthenticatedAesCng()) { aes.CngMode = CngChainingMode.Gcm; aes.GenerateKey(); return aes.Key; } }
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; } } }
/// <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); }
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)); } } } }
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); }
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"); }
// 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(); } }
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))); } }
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()); }
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; } } }
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))); } } } }