Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions Rijndael256.Tests/RijndaelEtMTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
}
11 changes: 11 additions & 0 deletions Rijndael256.Tests/RijndaelTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
}
48 changes: 48 additions & 0 deletions Rijndael256/Rijndael.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,26 @@ public static string Encrypt(byte[] plaintext, string password, KeySize keySize)
return Convert.ToBase64String(ciphertext);
}

/// <summary>
/// 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.
/// </summary>
/// <param name="plaintext">The plaintext to encrypt.</param>
/// <param name="password">The password to encrypt the plaintext with.</param>
/// <param name="keySize">The cipher key size. 256-bit is stronger, but slower.</param>
/// <returns>The encoded ciphertext.</returns>
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;
}

/// <summary>
/// Encrypts plaintext using the Rijndael cipher in CBC mode with a password derived HMAC SHA-512 salt.
/// </summary>
Expand Down Expand Up @@ -142,6 +162,34 @@ public static string Decrypt(string ciphertext, string password, KeySize keySize
return Decrypt(Convert.FromBase64String(ciphertext), password, keySize);
}

/// <summary>
/// Decrypts ciphertext using the Rijndael cipher in CBC mode with a password derived HMAC SHA-512 salt.
/// </summary>
/// <param name="ciphertext">The ciphertext to decrypt.</param>
/// <param name="password">The password to decrypt the ciphertext with.</param>
/// <param name="keySize">The size of the cipher key used to create the ciphertext.</param>
/// <returns>The plaintext.</returns>
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();
}
}
}
}

/// <summary>
/// Decrypts ciphertext using the Rijndael cipher in CBC mode with a password derived HMAC SHA-512 salt.
/// </summary>
Expand Down
56 changes: 56 additions & 0 deletions Rijndael256/RijndaelEtM.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,27 @@ public class RijndaelEtM : Rijndael
return Convert.ToBase64String(etmCiphertext);
}

/// <summary>
/// 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.
/// </summary>
/// <param name="plaintext">The plaintext to encrypt.</param>
/// <param name="password">The password to encrypt the plaintext with.</param>
/// <param name="keySize">The cipher key size. 256-bit is stronger, but slower.</param>
/// <returns>The encoded EtM ciphertext.</returns>
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;
}

/// <summary>
/// Encrypts plaintext using the Encrypt-then-MAC (EtM) mode via the Rijndael cipher in
/// CBC mode with a password derived HMAC SHA-512 salt.
Expand Down Expand Up @@ -96,6 +117,41 @@ public class RijndaelEtM : Rijndael
return Decrypt(Convert.FromBase64String(etmCiphertext), password, keySize);
}

/// <summary>
/// Decrypts authenticated ciphertext using the Rijndael cipher in CBC mode with a password derived
/// HMAC SHA-512 salt.
/// </summary>
/// <param name="etmCiphertext">The EtM ciphertext to decrypt.</param>
/// <param name="password">The password to decrypt the EtM ciphertext with.</param>
/// <param name="keySize">The size of the cipher key used to create the EtM ciphertext.</param>
/// <returns>The plaintext.</returns>
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);
}

/// <summary>
/// Decrypts authenticated ciphertext using the Rijndael cipher in CBC mode with a password derived
/// HMAC SHA-512 salt.
Expand Down