Added the use of DEK's for encryption of secrets. Both the KEK's and DEK's are stored in a way that you can have multiple key of which one is active. But the others are still available for decrypting. This allows for implementing key rotation. Co-authored-by: eelke <eelke@eelkeklein.nl> Co-authored-by: Eelke76 <31384324+Eelke76@users.noreply.github.com> Reviewed-on: #6
41 lines
No EOL
1.3 KiB
C#
41 lines
No EOL
1.3 KiB
C#
using IdentityShroud.Core.Contracts;
|
|
using IdentityShroud.Core.Model;
|
|
using IdentityShroud.Core.Security;
|
|
|
|
namespace IdentityShroud.Core.Services;
|
|
|
|
public class DataEncryptionService(
|
|
IRealmContext realmContext,
|
|
IDekEncryptionService dekCryptor) : IDataEncryptionService
|
|
{
|
|
|
|
// Note this array is expected to have one item in it most of the during key rotation it will have two
|
|
// until it is ensured the old key can safely be removed. More then two will work but is not really expected.
|
|
private IList<RealmDek>? _deks = null;
|
|
|
|
private IList<RealmDek> GetDeks()
|
|
{
|
|
if (_deks is null)
|
|
_deks = realmContext.GetDeks().Result;
|
|
|
|
return _deks;
|
|
}
|
|
|
|
private RealmDek GetActiveDek() => GetDeks().Single(d => d.Active);
|
|
private RealmDek GetKey(DekId id) => GetDeks().Single(d => d.Id == id);
|
|
|
|
public byte[] Decrypt(EncryptedValue input)
|
|
{
|
|
var dek = GetKey(input.DekId);
|
|
var key = dekCryptor.Decrypt(dek.KeyData);
|
|
return Encryption.Decrypt(input.Value, key);
|
|
}
|
|
|
|
public EncryptedValue Encrypt(ReadOnlySpan<byte> plain)
|
|
{
|
|
var dek = GetActiveDek();
|
|
var key = dekCryptor.Decrypt(dek.KeyData);
|
|
byte[] cipher = Encryption.Encrypt(plain, key);
|
|
return new (dek.Id, cipher);
|
|
}
|
|
} |