using IdentityShroud.Core.Contracts; using IdentityShroud.Core.Services; namespace IdentityShroud.Core.Tests.Services; public class EncryptionServiceTests { [Fact] public void RoundtripWorks() { // Note this code will tend to only test the latest verion. // setup byte[] keyValue = Convert.FromBase64String("IGd9yUMusjNW0ezv8ink3QWlAHKFH45d21LyrbJTokw="); var secretProvider = Substitute.For(); EncryptionKey[] keys = [ new EncryptionKey("1", true, "AES", keyValue) ]; secretProvider.GetKeys("master").Returns(keys); ReadOnlySpan input = "Hello, World!"u8; // act EncryptionService sut = new(secretProvider); EncryptedValue cipher = sut.Encrypt(input.ToArray()); byte[] result = sut.Decrypt(cipher); // verify Assert.Equal(input, result); } [Fact] public void DecodeV1_Success() { // When introducing a new version we need version specific tests to // make sure decoding of legacy data still works. // setup byte[] cipher = [ 1, 198, 55, 58, 56, 110, 238, 59, 158, 214, 85, 241, 26, 44, 140, 229, 128, 111, 167, 154, 160, 177, 152, 193, 74, 4, 235, 82, 207, 87, 32, 10, 239, 4, 246, 25, 21, 249, 25, 59, 160, 101 ]; EncryptedValue secret = new("kid", cipher); byte[] keyValue = Convert.FromBase64String("IGd9yUMusjNW0ezv8ink3QWlAHKFH45d21LyrbJTokw="); var secretProvider = Substitute.For(); EncryptionKey[] keys = [ new EncryptionKey("kid", true, "AES", keyValue) ]; secretProvider.GetKeys("master").Returns(keys); // act EncryptionService sut = new(secretProvider); byte[] result = sut.Decrypt(secret); // verify Assert.Equal("Hello, World!"u8, result); } [Fact] public void DetectsCorruptInput() { // When introducing a new version we need version specific tests to // make sure decoding of legacy data still works. // setup byte[] cipher = // NOTE INCORRECT CIPHER DO NOT USE IN OTHER TESTS [ 1, 198, 55, 58, 56, 110, 238, 59, 158, 214, 85, 241, 26, 44, 140, 229, 128, 111, 167, 154, 160, 177, 152, 193, 75, 4, 235, 82, 207, 87, 32, 10, 239, 4, 246, 25, 21, 249, 25, 59, 160, 101 ]; EncryptedValue secret = new("kid", cipher); byte[] keyValue = Convert.FromBase64String("IGd9yUMusjNW0ezv8ink3QWlAHKFH45d21LyrbJTokw="); var secretProvider = Substitute.For(); EncryptionKey[] keys = [ new EncryptionKey("kid", true, "AES", keyValue) ]; secretProvider.GetKeys("master").Returns(keys); // act EncryptionService sut = new(secretProvider); Assert.Throws( () => sut.Decrypt(secret), ex => ex.Message.Contains("Decryption failed") ? null : "Expected Decryption failed in message"); } [Fact] public void DecodeSelectsRightKey() { // The key is marked inactive also it is the second key // setup byte[] cipher = [ 1, 198, 55, 58, 56, 110, 238, 59, 158, 214, 85, 241, 26, 44, 140, 229, 128, 111, 167, 154, 160, 177, 152, 193, 74, 4, 235, 82, 207, 87, 32, 10, 239, 4, 246, 25, 21, 249, 25, 59, 160, 101 ]; EncryptedValue secret = new("1", cipher); byte[] keyValue1 = Convert.FromBase64String("IGd9yUMusjNW0ezv8ink3QWlAHKFH45d21LyrbJTokw="); byte[] keyValue2 = Convert.FromBase64String("Dat1RwRvuLX3wdKMMP4NwHdBl8tJJsKfp01qikyo8aw="); var secretProvider = Substitute.For(); EncryptionKey[] keys = [ new EncryptionKey("2", true, "AES", keyValue2), new EncryptionKey("1", false, "AES", keyValue1), ]; secretProvider.GetKeys("master").Returns(keys); // act EncryptionService sut = new(secretProvider); byte[] result = sut.Decrypt(secret); // verify Assert.Equal("Hello, World!"u8, result); } [Fact] public void EncryptionUsesActiveKey() { // setup byte[] keyValue1 = Convert.FromBase64String("IGd9yUMusjNW0ezv8ink3QWlAHKFH45d21LyrbJTokw="); byte[] keyValue2 = Convert.FromBase64String("Dat1RwRvuLX3wdKMMP4NwHdBl8tJJsKfp01qikyo8aw="); var secretProvider = Substitute.For(); EncryptionKey[] keys = [ new EncryptionKey("1", false, "AES", keyValue1), new EncryptionKey("2", true, "AES", keyValue2), ]; secretProvider.GetKeys("master").Returns(keys); ReadOnlySpan input = "Hello, World!"u8; // act EncryptionService sut = new(secretProvider); EncryptedValue cipher = sut.Encrypt(input.ToArray()); // Verify Assert.Equal("2", cipher.KeyId); } }