diff --git a/LiftLog.Lib/Services/AesEncryptionService.cs b/LiftLog.Lib/Services/AesEncryptionService.cs index ed0b982f..951e275a 100644 --- a/LiftLog.Lib/Services/AesEncryptionService.cs +++ b/LiftLog.Lib/Services/AesEncryptionService.cs @@ -17,11 +17,22 @@ public ValueTask DecryptAsync(byte[] data, byte[] IV, byte[] key) return ValueTask.FromResult(decryptor.TransformFinalBlock(data, 0, data.Length)); } - public ValueTask<(byte[] EncryptedPayload, byte[] IV)> EncryptAsync(byte[] data, byte[] key) + public ValueTask<(byte[] EncryptedPayload, byte[] IV)> EncryptAsync( + byte[] data, + byte[] key, + byte[]? iv = null + ) { var aes = Aes.Create(); - aes.GenerateIV(); + if (iv is not null) + { + aes.IV = iv; + } + else + { + aes.GenerateIV(); + } aes.Key = key; using var encryptor = aes.CreateEncryptor(); diff --git a/LiftLog.Lib/Services/IEncryptionService.cs b/LiftLog.Lib/Services/IEncryptionService.cs index dcb33fa6..3932df98 100644 --- a/LiftLog.Lib/Services/IEncryptionService.cs +++ b/LiftLog.Lib/Services/IEncryptionService.cs @@ -4,6 +4,10 @@ public interface IEncryptionService { ValueTask DecryptAsync(byte[] data, byte[] IV, byte[] key); - public ValueTask<(byte[] EncryptedPayload, byte[] IV)> EncryptAsync(byte[] data, byte[] key); + public ValueTask<(byte[] EncryptedPayload, byte[] IV)> EncryptAsync( + byte[] data, + byte[] key, + byte[]? iv = null + ); ValueTask GenerateKeyAsync(); } diff --git a/LiftLog.Tests/Encryption/AesEncryptionServiceTests.cs b/LiftLog.Tests/Encryption/AesEncryptionServiceTests.cs index 99e0b780..e5b54ced 100644 --- a/LiftLog.Tests/Encryption/AesEncryptionServiceTests.cs +++ b/LiftLog.Tests/Encryption/AesEncryptionServiceTests.cs @@ -37,4 +37,24 @@ public async Task EncryptAndDecrypt_EncryptsAndDecryptsData() // Assert Assert.Equal(data, decryptedData); } + + [Fact] + public async Task EncryptAndDecrypt_EncryptsAndDecryptsDataGivenSameIV() + { + // Arrange + var key = await _encryptionService.GenerateKeyAsync(); + var data1 = Encoding.UTF8.GetBytes("Hello, world!"); + var data2 = Encoding.UTF8.GetBytes("Goodbye, world!"); + + // Act + var (encryptedData1, iv) = await _encryptionService.EncryptAsync(data1, key); + var decryptedData1 = await _encryptionService.DecryptAsync(encryptedData1, iv, key); + + var (encryptedData2, _) = await _encryptionService.EncryptAsync(data2, key, iv); + var decryptedData2 = await _encryptionService.DecryptAsync(encryptedData2, iv, key); + + // Assert + Assert.Equal(data1, decryptedData1); + Assert.Equal(data2, decryptedData2); + } } diff --git a/LiftLog.Web/Services/JsAesEncryptionService.cs b/LiftLog.Web/Services/JsAesEncryptionService.cs index 70aece54..d1cc46b0 100644 --- a/LiftLog.Web/Services/JsAesEncryptionService.cs +++ b/LiftLog.Web/Services/JsAesEncryptionService.cs @@ -10,7 +10,11 @@ public ValueTask DecryptAsync(byte[] data, byte[] IV, byte[] key) throw new NotImplementedException(); } - public ValueTask<(byte[] EncryptedPayload, byte[] IV)> EncryptAsync(byte[] data, byte[] key) + public ValueTask<(byte[] EncryptedPayload, byte[] IV)> EncryptAsync( + byte[] data, + byte[] key, + byte[]? iv = null + ) { throw new NotImplementedException(); }