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; } } }
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()); } } }
public void AuthenticatedAesCngGcmMultiRoundTripTest() { byte[] plaintext = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6 }; byte[] plaintext2 = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6 }; byte[] expectedCiphertext = new byte[] { 0x54, 0x2d, 0x26, 0x15, 0x9c, 0xb3, 0x6e, 0x21, 0xd2, 0x58, 0xcf, 0x9c, 0x6e, 0xce, 0xfb, 0x5f, 0x8c, 0x2a, 0xb8, 0x22, 0x4d, 0x6d, 0xd0, 0x02, 0x76, 0xd2, 0xab, 0x22, 0xa2, 0xd6, 0xee, 0x5b }; byte[] expectedTag = new byte[] { 0xc1, 0x34, 0x38, 0x0b, 0xc3, 0x87, 0x7c, 0xf5, 0x2f, 0x3b, 0xa9, 0xfe, 0x3c, 0x69, 0x4b, 0x9f }; byte[] key = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6 }; byte[] iv = new byte[] { 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 }; using (AuthenticatedAesCng gcm = new AuthenticatedAesCng()) { gcm.CngMode = CngChainingMode.Gcm; gcm.Key = key; gcm.IV = iv; gcm.Tag = expectedTag; // Encrypt byte[] ciphertext = null; using (MemoryStream ms = new MemoryStream()) using (IAuthenticatedCryptoTransform encryptor = gcm.CreateAuthenticatedEncryptor()) using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write)) { // Push through two blocks and call final to get the tag. cs.Write(plaintext, 0, plaintext.Length); cs.Write(plaintext2, 0, plaintext2.Length); cs.FlushFinalBlock(); ciphertext = ms.ToArray(); // Check if the ciphertext and tag are what are expected. Assert.IsTrue(Util.CompareBytes(expectedCiphertext, ciphertext)); Assert.IsTrue(Util.CompareBytes(expectedTag, encryptor.GetTag())); } // Decrypt using (MemoryStream ms = new MemoryStream()) using (ICryptoTransform decryptor = gcm.CreateDecryptor()) using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Write)) { cs.Write(ciphertext, 0, ciphertext.Length / 2); cs.Write(ciphertext, ciphertext.Length / 2, ciphertext.Length / 2); cs.FlushFinalBlock(); byte[] decrypted = ms.ToArray(); // Compare the decrypted text to the initial ciphertext. byte[] fullPlaintext = new byte[plaintext.Length + plaintext2.Length]; Array.Copy(plaintext, 0, fullPlaintext, 0, plaintext.Length); Array.Copy(plaintext2, 0, fullPlaintext, plaintext.Length, plaintext2.Length); Assert.IsTrue(Util.CompareBytes(fullPlaintext, decrypted)); } } }
private void RunTestVector(GcmTestVector test) { // Encrypt the input byte[] ciphertext = null; using (AuthenticatedAesCng gcm = new AuthenticatedAesCng()) { gcm.CngMode = CngChainingMode.Gcm; gcm.Key = test.Key; gcm.IV = test.IVBytes; gcm.AuthenticatedData = test.AuthenticationData; using (MemoryStream ms = new MemoryStream()) using (IAuthenticatedCryptoTransform encryptor = gcm.CreateAuthenticatedEncryptor()) using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write)) { if (test.Plaintext != null) { cs.Write(test.Plaintext, 0, test.Plaintext.Length); } cs.FlushFinalBlock(); ciphertext = ms.ToArray(); // Verify the produced tag is what we expected it to be Assert.IsTrue(Util.CompareBytes(test.Tag, encryptor.GetTag())); } } if (test.Ciphertext != null) { // Verify the ciphertext is what we expected it to be Assert.IsTrue(Util.CompareBytes(test.Ciphertext, ciphertext)); // Round trip the data using (AuthenticatedAesCng gcm = new AuthenticatedAesCng()) { gcm.CngMode = CngChainingMode.Gcm; gcm.Key = test.Key; gcm.IV = test.IVBytes; gcm.AuthenticatedData = test.AuthenticationData; gcm.Tag = test.Tag; using (MemoryStream ms = new MemoryStream()) using (CryptoStream cs = new CryptoStream(ms, gcm.CreateDecryptor(), CryptoStreamMode.Write)) { cs.Write(test.Ciphertext, 0, test.Ciphertext.Length); cs.FlushFinalBlock(); byte[] plaintext = ms.ToArray(); Assert.IsTrue(Util.CompareBytes(test.Plaintext, plaintext)); } } } }
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 byte[] Encrypt(byte[] Plain, out byte[] Tag, byte[] PacketHead, long PacketID) { byte[] RetVar; using (AuthenticatedAesCng aes = new AuthenticatedAesCng()) { aes.CngMode = CngChainingMode.Gcm; aes.Key = EncryptionKey; //------------- Build Nonce ------------- byte[] nonce = new byte[12]; Array.Copy(EncryptNonceHash, nonce, 4); //Encryption flag probably Array.Copy(new byte[] { 0x00, 0x01 }, 0, nonce, 4, 2); //Little Endian Packet ID to be send //Array.Copy(new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, 0, nonce, 6, 6); Array.Copy(BitConverter.GetBytes(PacketID).Reverse().ToArray(), 2, nonce, 6, 6); Console.WriteLine("nonce:" + Helpers.ByteArrayToString(nonce)); aes.IV = nonce; //------------- Build Associated Data ------------- byte[] associatedData = new byte[13]; // { 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0xFE, 0xFD, 0x00, 0x18 }; //Encryption flag probably Array.Copy(new byte[] { 0x00, 0x01 }, associatedData, 2); //Little Endian Packet ID to be send Array.Copy(BitConverter.GetBytes(PacketID).Reverse().ToArray(), 2, associatedData, 2, 6); //Packet header //Array.Copy(new byte[] { 0x16, 0xFE, 0xFD }, 0, associatedData, 8, 3); Array.Copy(PacketHead, 0, associatedData, 8, 3); //data length short EncryptedDataLen = (short)Plain.Length; Array.Copy(BitConverter.GetBytes(EncryptedDataLen).Reverse().ToArray(), 0, associatedData, 11, 2); //Array.Copy(new byte[] { 0x00, 0x18 }, 0, associatedData, 11, 2); Console.WriteLine("associatedData:" + Helpers.ByteArrayToString(associatedData)); aes.AuthenticatedData = associatedData; using (MemoryStream ms = new MemoryStream()) using (var encryptor = aes.CreateAuthenticatedEncryptor()) using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write)) { cs.Write(Plain, 0, Plain.Length); cs.FlushFinalBlock(); RetVar = ms.ToArray(); Tag = encryptor.GetTag(); } } return(RetVar); }
// returns the encrypted string in the format [IV]-[TAG]-[DATA] public static string EncryptString(string str) { if (String.IsNullOrEmpty(str)) { throw new ArgumentNullException("encryption string invalid"); } using (AuthenticatedAesCng aes = new AuthenticatedAesCng()) { byte[] message = Encoding.UTF8.GetBytes(str); aes.Key = GetEncryptionKey(); aes.IV = GenerateIV(); // use the GCM mode, which should prevent the Padding Oracle attack // https://en.wikipedia.org/wiki/Padding_oracle_attack aes.CngMode = CngChainingMode.Gcm; aes.AuthenticatedData = GetAdditionalAuthenticationData(); using (MemoryStream memoryStream = new MemoryStream()) using (IAuthenticatedCryptoTransform encryptor = aes.CreateAuthenticatedEncryptor()) using (CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write)) { // Write through and retrieve encrypted data. cryptoStream.Write(message, 0, message.Length); cryptoStream.FlushFinalBlock(); byte[] cipherText = memoryStream.ToArray(); // Retrieve tag and create array to hold encrypted data. byte[] authenticationTag = encryptor.GetTag(); byte[] encrypted = new byte[cipherText.Length + aes.IV.Length + authenticationTag.Length]; // encrypt the data in the format [IV]-[TAG]-[DATA] aes.IV.CopyTo(encrypted, 0); authenticationTag.CopyTo(encrypted, IV_LENGTH); cipherText.CopyTo(encrypted, IV_LENGTH + TAG_LENGTH); // Store encrypted value in base 64. return(Convert.ToBase64String(encrypted)); } } }
public void AuthenticatedSymmetricAlgorithmVerifierTestNegativeAuthenticationEncryptStandardDecryptTest() { byte[] plaintext = Encoding.UTF8.GetBytes("Plaintext"); byte[] ciphertext = null; byte[] key = null; SymmetricEncryptionState encryptionState = null; using (AuthenticatedSymmetricAlgorithm encryptAes = new AuthenticatedAesCng().EnableLogging()) { key = encryptAes.Key; encryptAes.IV = new byte[] { 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 }; using (IAuthenticatedCryptoTransform encryptor = encryptAes.CreateAuthenticatedEncryptor()) using (MemoryStream ms = new MemoryStream()) using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write)) { cs.Write(plaintext, 0, plaintext.Length); cs.FlushFinalBlock(); ciphertext = ms.ToArray(); encryptionState = encryptAes.GetLastEncryptionState(); } } using (SymmetricAlgorithm decryptAes = new AesCng().EnableDecryptionVerification(encryptionState)) { decryptAes.Key = key; using (MemoryStream ms = new MemoryStream()) using (CryptoStream cs = new CryptoStream(ms, decryptAes.CreateDecryptor(), CryptoStreamMode.Write)) { cs.Write(ciphertext, 0, ciphertext.Length); cs.FlushFinalBlock(); } } Assert.Fail("Decryption should have failed."); }
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 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); }
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; } } }
/// <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 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)); } } } }
// 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 override string ToString() { string header = JsonConvert.SerializeObject(this); string claims = JsonConvert.SerializeObject(this.claims); string signature = String.Empty; //First segment using (HMACSHA256 hmac = new HMACSHA256()) { string data = String.Format("{0}.{1}", header, claims); byte[] signatureBytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(data)); signature = signatureBytes.ToBase64String(); } byte[] masterKey = new byte[32]; byte[] initVector = new byte[12]; //Third segment using (var provider = new RNGCryptoServiceProvider()) { provider.GetBytes(masterKey); provider.GetBytes(initVector); } byte[] encryptedMasterKey = null; //Second segment using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider()) { rsa.FromXmlString(this.AsymmetricKey); encryptedMasterKey = rsa.Encrypt(masterKey, true); // OAEP Padding } var authData = new EncryptedPayload() { Header = header, EncryptedMasterKey = encryptedMasterKey, InitializationVector = initVector }; byte[] additionalAuthenticatedData = authData.ToAdditionalAuthenticatedData(); byte[] tag = null; //Fifth segment byte[] cipherText = null; //Fourth segment using (var aes = new AuthenticatedAesCng()) { aes.CngMode = CngChainingMode.Gcm; // Galois/Counter Mode aes.Key = masterKey; aes.IV = initVector; aes.AuthenticatedData = additionalAuthenticatedData; using (MemoryStream ms = new MemoryStream()) { using (IAuthenticatedCryptoTransform encryptor = aes.CreateAuthenticatedEncryptor()) { using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write)) { // Encrypt the claims set byte[] claimsSet = Encoding.UTF8.GetBytes(claims); cs.Write(claimsSet, 0, claimsSet.Length); cs.FlushFinalBlock(); tag = encryptor.GetTag(); cipherText = ms.ToArray(); } } } } authData.CipherText = cipherText; authData.Tag = tag; return(authData.ToString()); }
/// <summary> /// 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 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 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; }