5-improve-encrypted-storage #6
10 changed files with 45 additions and 38 deletions
|
|
@ -11,10 +11,7 @@ namespace IdentityShroud.Api.Tests.Mappers;
|
||||||
|
|
||||||
public class KeyServiceTests
|
public class KeyServiceTests
|
||||||
{
|
{
|
||||||
private readonly IDekEncryptionService _dekEncryptionService = EncryptionServiceSubstitute.CreatePassthrough();
|
private readonly NullDekEncryptionService _dekEncryptionService = new();
|
||||||
|
|
||||||
//private readonly IDataEncryptionService _dataEncryptionService = Substitute.For<IDataEncryptionService>();
|
|
||||||
//private readonly IKeyProviderFactory _keyProviderFactory = Substitute.For<IKeyProviderFactory>();
|
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Test()
|
public void Test()
|
||||||
|
|
@ -30,7 +27,7 @@ public class KeyServiceTests
|
||||||
{
|
{
|
||||||
Id = new("60bb79cf-4bac-4521-87f2-ac87cc15541f"),
|
Id = new("60bb79cf-4bac-4521-87f2-ac87cc15541f"),
|
||||||
KeyType = "RSA",
|
KeyType = "RSA",
|
||||||
Key = new(EncryptionServiceSubstitute.KeyId, rsa.ExportPkcs8PrivateKey()),
|
Key = new(_dekEncryptionService.KeyId, rsa.ExportPkcs8PrivateKey()),
|
||||||
CreatedAt = DateTime.UtcNow,
|
CreatedAt = DateTime.UtcNow,
|
||||||
Priority = 10,
|
Priority = 10,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
using IdentityShroud.Core.Contracts;
|
using IdentityShroud.Core.Contracts;
|
||||||
using IdentityShroud.Core.Model;
|
using IdentityShroud.Core.Model;
|
||||||
using IdentityShroud.Core.Security;
|
|
||||||
using IdentityShroud.Core.Services;
|
using IdentityShroud.Core.Services;
|
||||||
using IdentityShroud.Core.Tests.Fixtures;
|
using IdentityShroud.Core.Tests.Fixtures;
|
||||||
using IdentityShroud.TestUtils.Substitutes;
|
using IdentityShroud.TestUtils.Substitutes;
|
||||||
|
|
@ -11,17 +10,13 @@ namespace IdentityShroud.Core.Tests.Services;
|
||||||
public class ClientServiceTests : IClassFixture<DbFixture>
|
public class ClientServiceTests : IClassFixture<DbFixture>
|
||||||
{
|
{
|
||||||
private readonly DbFixture _dbFixture;
|
private readonly DbFixture _dbFixture;
|
||||||
//private readonly IDekEncryptionService _dekEncryptionService = EncryptionServiceSubstitute.CreatePassthrough();
|
private readonly NullDataEncryptionService _dataEncryptionService = new();
|
||||||
private readonly IDataEncryptionService _dataEncryptionService = Substitute.For<IDataEncryptionService>();
|
|
||||||
|
|
||||||
private readonly IClock _clock = Substitute.For<IClock>();
|
private readonly IClock _clock = Substitute.For<IClock>();
|
||||||
private readonly Guid _realmId = new("a1b2c3d4-0000-0000-0000-000000000001");
|
private readonly Guid _realmId = new("a1b2c3d4-0000-0000-0000-000000000001");
|
||||||
|
|
||||||
public ClientServiceTests(DbFixture dbFixture)
|
public ClientServiceTests(DbFixture dbFixture)
|
||||||
{
|
{
|
||||||
_dataEncryptionService.Encrypt(Arg.Any<ReadOnlyMemory<byte>>())
|
|
||||||
.Returns(x => new EncryptedValue(DekId.NewId(), x.ArgAt<ReadOnlyMemory<byte>>(0).ToArray()));
|
|
||||||
|
|
||||||
_dbFixture = dbFixture;
|
_dbFixture = dbFixture;
|
||||||
using Db db = dbFixture.CreateDbContext();
|
using Db db = dbFixture.CreateDbContext();
|
||||||
if (!db.Database.EnsureCreated())
|
if (!db.Database.EnsureCreated())
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,6 @@ namespace IdentityShroud.Core.Contracts;
|
||||||
|
|
||||||
public interface IDataEncryptionService
|
public interface IDataEncryptionService
|
||||||
{
|
{
|
||||||
EncryptedValue Encrypt(ReadOnlyMemory<byte> plain);
|
EncryptedValue Encrypt(ReadOnlySpan<byte> plain);
|
||||||
byte[] Decrypt(EncryptedValue input);
|
byte[] Decrypt(EncryptedValue input);
|
||||||
}
|
}
|
||||||
|
|
@ -6,6 +6,6 @@ namespace IdentityShroud.Core.Contracts;
|
||||||
|
|
||||||
public interface IDekEncryptionService
|
public interface IDekEncryptionService
|
||||||
{
|
{
|
||||||
EncryptedDek Encrypt(ReadOnlyMemory<byte> plain);
|
EncryptedDek Encrypt(ReadOnlySpan<byte> plain);
|
||||||
byte[] Decrypt(EncryptedDek input);
|
byte[] Decrypt(EncryptedDek input);
|
||||||
}
|
}
|
||||||
|
|
@ -12,7 +12,7 @@ public static class Encryption
|
||||||
new(1, 12, 16), // version 1
|
new(1, 12, 16), // version 1
|
||||||
];
|
];
|
||||||
|
|
||||||
public static byte[] Encrypt(ReadOnlyMemory<byte> plaintext, ReadOnlySpan<byte> key)
|
public static byte[] Encrypt(ReadOnlySpan<byte> plaintext, ReadOnlySpan<byte> key)
|
||||||
{
|
{
|
||||||
const int versionNumber = 1;
|
const int versionNumber = 1;
|
||||||
AlgVersion versionParams = _versions[versionNumber];
|
AlgVersion versionParams = _versions[versionNumber];
|
||||||
|
|
@ -31,7 +31,7 @@ public static class Encryption
|
||||||
// use the spans to place the data directly in its place
|
// use the spans to place the data directly in its place
|
||||||
RandomNumberGenerator.Fill(nonce);
|
RandomNumberGenerator.Fill(nonce);
|
||||||
using var aes = new AesGcm(key, versionParams.TagSize);
|
using var aes = new AesGcm(key, versionParams.TagSize);
|
||||||
aes.Encrypt(nonce, plaintext.Span, cipher, tag);
|
aes.Encrypt(nonce, plaintext, cipher, tag);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ public class DataEncryptionService(
|
||||||
return Encryption.Decrypt(input.Value, key);
|
return Encryption.Decrypt(input.Value, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
public EncryptedValue Encrypt(ReadOnlyMemory<byte> plain)
|
public EncryptedValue Encrypt(ReadOnlySpan<byte> plain)
|
||||||
{
|
{
|
||||||
var dek = GetActiveDek();
|
var dek = GetActiveDek();
|
||||||
var key = dekCryptor.Decrypt(dek.KeyData);
|
var key = dekCryptor.Decrypt(dek.KeyData);
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ public class DekEncryptionService : IDekEncryptionService
|
||||||
// throw new Exception("Key must be 256 bits (32 bytes) for AES‑256‑GCM.");
|
// throw new Exception("Key must be 256 bits (32 bytes) for AES‑256‑GCM.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public EncryptedDek Encrypt(ReadOnlyMemory<byte> plaintext)
|
public EncryptedDek Encrypt(ReadOnlySpan<byte> plaintext)
|
||||||
{
|
{
|
||||||
var encryptionKey = ActiveKey;
|
var encryptionKey = ActiveKey;
|
||||||
byte[] cipher = Encryption.Encrypt(plaintext, encryptionKey.Key);
|
byte[] cipher = Encryption.Encrypt(plaintext, encryptionKey.Key);
|
||||||
|
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
using IdentityShroud.Core.Contracts;
|
|
||||||
using IdentityShroud.Core.Security;
|
|
||||||
|
|
||||||
namespace IdentityShroud.TestUtils.Substitutes;
|
|
||||||
|
|
||||||
public static class EncryptionServiceSubstitute
|
|
||||||
{
|
|
||||||
public static KekId KeyId { get; } = KekId.NewId();
|
|
||||||
|
|
||||||
public static IDekEncryptionService CreatePassthrough()
|
|
||||||
{
|
|
||||||
var encryptionService = Substitute.For<IDekEncryptionService>();
|
|
||||||
encryptionService
|
|
||||||
.Encrypt(Arg.Any<ReadOnlyMemory<byte>>())
|
|
||||||
.Returns(x => new EncryptedDek(KeyId, x.ArgAt<ReadOnlyMemory<byte>>(0).ToArray()));
|
|
||||||
encryptionService
|
|
||||||
.Decrypt(Arg.Any<EncryptedDek>())
|
|
||||||
.Returns(x => x.ArgAt<EncryptedDek>(0).Value);
|
|
||||||
return encryptionService;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
using IdentityShroud.Core.Contracts;
|
||||||
|
using IdentityShroud.Core.Security;
|
||||||
|
|
||||||
|
namespace IdentityShroud.TestUtils.Substitutes;
|
||||||
|
|
||||||
|
public class NullDataEncryptionService : IDataEncryptionService
|
||||||
|
{
|
||||||
|
public DekId KeyId { get; } = DekId.NewId();
|
||||||
|
public EncryptedValue Encrypt(ReadOnlySpan<byte> plain)
|
||||||
|
{
|
||||||
|
return new(KeyId, plain.ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] Decrypt(EncryptedValue input)
|
||||||
|
{
|
||||||
|
return input.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
using IdentityShroud.Core.Contracts;
|
||||||
|
using IdentityShroud.Core.Security;
|
||||||
|
|
||||||
|
namespace IdentityShroud.TestUtils.Substitutes;
|
||||||
|
|
||||||
|
public class NullDekEncryptionService : IDekEncryptionService
|
||||||
|
{
|
||||||
|
public KekId KeyId { get; } = KekId.NewId();
|
||||||
|
public EncryptedDek Encrypt(ReadOnlySpan<byte> plain)
|
||||||
|
{
|
||||||
|
return new(KeyId, plain.ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] Decrypt(EncryptedDek input)
|
||||||
|
{
|
||||||
|
return input.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue