diff --git a/Rijndael256.Tests/RijndaelEtMTests.cs b/Rijndael256.Tests/RijndaelEtMTests.cs
index f30ec1d..dbf1fbc 100644
--- a/Rijndael256.Tests/RijndaelEtMTests.cs
+++ b/Rijndael256.Tests/RijndaelEtMTests.cs
@@ -142,5 +142,16 @@ public void GenerateAeKeyRing()
Assert.Equal(keyRing.CipherKey, AeKeyRingProof.CipherKey);
Assert.True(keyRing.MacKey.SequenceEqual(AeKeyRingProof.MacKey));
}
+
+ [Fact]
+ public void BinaryBlob()
+ {
+ var plainblob = UTF8Encoding.UTF8.GetBytes(Plaintext);
+
+ var cipherblob = RijndaelEtM.EncryptBinary(plainblob, Password, KeySize.Aes128);
+ var plainresult = RijndaelEtM.DecryptBinary(cipherblob, Password, KeySize.Aes128);
+
+ Assert.Equal(plainblob, plainresult);
+ }
}
}
diff --git a/Rijndael256.Tests/RijndaelTests.cs b/Rijndael256.Tests/RijndaelTests.cs
index c2e4b3e..45bc7f5 100644
--- a/Rijndael256.Tests/RijndaelTests.cs
+++ b/Rijndael256.Tests/RijndaelTests.cs
@@ -98,5 +98,16 @@ public void RandomIv256()
Assert.Equal(plaintext, Plaintext);
Assert.NotEqual(ciphertext1, ciphertext2);
}
+
+ [Fact]
+ public void BinaryBlob()
+ {
+ var plainblob = UTF8Encoding.UTF8.GetBytes(Plaintext);
+
+ var cipherblob = Rijndael.EncryptBinary(plainblob, Password, KeySize.Aes128);
+ var plainresult = Rijndael.DecryptBinary(cipherblob, Password, KeySize.Aes128);
+
+ Assert.Equal(plainblob, plainresult);
+ }
}
}
diff --git a/Rijndael256/Rijndael.cs b/Rijndael256/Rijndael.cs
index 3f11a8d..9769425 100644
--- a/Rijndael256/Rijndael.cs
+++ b/Rijndael256/Rijndael.cs
@@ -54,6 +54,26 @@ public static string Encrypt(byte[] plaintext, string password, KeySize keySize)
return Convert.ToBase64String(ciphertext);
}
+ ///
+ /// Encrypts plaintext using the Rijndael cipher in CBC mode with a password derived HMAC SHA-512 salt.
+ /// A random 128-bit Initialization Vector is generated for the cipher.
+ ///
+ /// The plaintext to encrypt.
+ /// The password to encrypt the plaintext with.
+ /// The cipher key size. 256-bit is stronger, but slower.
+ /// The encoded ciphertext.
+ public static byte[] EncryptBinary(byte[] plaintext, string password, KeySize keySize)
+ {
+ // Generate a random IV
+ var iv = Rng.GenerateRandomBytes(InitializationVectorSize);
+
+ // Encrypt the plaintext
+ var ciphertext = Encrypt(plaintext, password, iv, keySize);
+
+ // Encode the ciphertext
+ return ciphertext;
+ }
+
///
/// Encrypts plaintext using the Rijndael cipher in CBC mode with a password derived HMAC SHA-512 salt.
///
@@ -142,6 +162,34 @@ public static string Decrypt(string ciphertext, string password, KeySize keySize
return Decrypt(Convert.FromBase64String(ciphertext), password, keySize);
}
+ ///
+ /// Decrypts ciphertext using the Rijndael cipher in CBC mode with a password derived HMAC SHA-512 salt.
+ ///
+ /// The ciphertext to decrypt.
+ /// The password to decrypt the ciphertext with.
+ /// The size of the cipher key used to create the ciphertext.
+ /// The plaintext.
+ public static byte[] DecryptBinary(byte[] ciphertext, string password, KeySize keySize)
+ {
+ using (var ms = new MemoryStream(ciphertext))
+ {
+ // Extract the IV from the ciphertext
+ var iv = new byte[InitializationVectorSize];
+ ms.Read(iv, 0, iv.Length);
+
+ // Create a CryptoStream to decrypt the ciphertext
+ using (var cs = new CryptoStream(ms, CreateDecryptor(password, iv, keySize), CryptoStreamMode.Read))
+ {
+ // Decrypt the ciphertext
+ using (var buffer = new MemoryStream())
+ {
+ cs.CopyTo(buffer);
+ return buffer.ToArray();
+ }
+ }
+ }
+ }
+
///
/// Decrypts ciphertext using the Rijndael cipher in CBC mode with a password derived HMAC SHA-512 salt.
///
diff --git a/Rijndael256/RijndaelEtM.cs b/Rijndael256/RijndaelEtM.cs
index d41345b..4468b83 100644
--- a/Rijndael256/RijndaelEtM.cs
+++ b/Rijndael256/RijndaelEtM.cs
@@ -54,6 +54,27 @@ public class RijndaelEtM : Rijndael
return Convert.ToBase64String(etmCiphertext);
}
+ ///
+ /// Encrypts plaintext using the Encrypt-then-MAC (EtM) mode via the Rijndael cipher in
+ /// CBC mode with a password derived HMAC SHA-512 salt. A random 128-bit Initialization
+ /// Vector is generated for the cipher.
+ ///
+ /// The plaintext to encrypt.
+ /// The password to encrypt the plaintext with.
+ /// The cipher key size. 256-bit is stronger, but slower.
+ /// The encoded EtM ciphertext.
+ public static new byte[] EncryptBinary(byte[] plaintext, string password, KeySize keySize)
+ {
+ // Generate a random IV
+ var iv = Rng.GenerateRandomBytes(InitializationVectorSize);
+
+ // Encrypt the plaintext
+ var etmCiphertext = Encrypt(plaintext, password, iv, keySize);
+
+ // Encode the EtM ciphertext
+ return etmCiphertext;
+ }
+
///
/// Encrypts plaintext using the Encrypt-then-MAC (EtM) mode via the Rijndael cipher in
/// CBC mode with a password derived HMAC SHA-512 salt.
@@ -96,6 +117,41 @@ public class RijndaelEtM : Rijndael
return Decrypt(Convert.FromBase64String(etmCiphertext), password, keySize);
}
+ ///
+ /// Decrypts authenticated ciphertext using the Rijndael cipher in CBC mode with a password derived
+ /// HMAC SHA-512 salt.
+ ///
+ /// The EtM ciphertext to decrypt.
+ /// The password to decrypt the EtM ciphertext with.
+ /// The size of the cipher key used to create the EtM ciphertext.
+ /// The plaintext.
+ public static new byte[] DecryptBinary(byte[] etmCiphertext, string password, KeySize keySize)
+ {
+ // Generate AE keys
+ var keyRing = AeKeyRing.Generate(password);
+
+ // Extract the ciphertext and MAC from the EtM ciphertext
+ var mac = new byte[keyRing.MacKey.Length];
+ var ciphertext = new byte[etmCiphertext.Length - mac.Length];
+ using (var ms = new MemoryStream(etmCiphertext))
+ {
+ // Extract the ciphertext
+ ms.Read(ciphertext, 0, ciphertext.Length);
+
+ // Extract the MAC
+ ms.Read(mac, 0, mac.Length);
+ }
+
+ // Calculate the MAC from the ciphertext
+ var newMac = CalculateMac(ciphertext, keyRing.MacKey);
+
+ // Authenticate ciphertext
+ if (!mac.SequenceEqual(newMac)) throw new Exception("Authentication failed!");
+
+ // Decrypt the ciphertext
+ return Rijndael.DecryptBinary(ciphertext, keyRing.CipherKey, keySize);
+ }
+
///
/// Decrypts authenticated ciphertext using the Rijndael cipher in CBC mode with a password derived
/// HMAC SHA-512 salt.