58 lines
1.7 KiB
C#
58 lines
1.7 KiB
C#
using System.Security.Cryptography;
|
|
using System.Text;
|
|
|
|
namespace Aegis.Repository.Crypto;
|
|
|
|
public class ServerSecretLabelKeyProvider : ILabelKeyProvider
|
|
{
|
|
private readonly byte[] _serverSecret;
|
|
|
|
public ServerSecretLabelKeyProvider(byte[] serverSecret)
|
|
{
|
|
if (serverSecret.Length < 32)
|
|
throw new ArgumentException("Server secret deve ter pelo menos 32 bytes.");
|
|
|
|
_serverSecret = serverSecret;
|
|
}
|
|
|
|
public byte[] GetLabelKey(string lkKid, int lkVersion)
|
|
{
|
|
// HKDF simples via HMACSHA256 (ok para derivação)
|
|
// info amarra ao kid+version
|
|
var info = Encoding.UTF8.GetBytes($"aegis:lk:{lkKid}:v{lkVersion}");
|
|
return HkdfSha256(_serverSecret, salt: null, info, 32);
|
|
}
|
|
|
|
private static byte[] HkdfSha256(byte[] ikm, byte[]? salt, byte[] info, int len)
|
|
{
|
|
salt ??= new byte[32]; // salt zero (ok se ikm for segredo forte)
|
|
using var hmac = new HMACSHA256(salt);
|
|
var prk = hmac.ComputeHash(ikm);
|
|
|
|
var okm = new byte[len];
|
|
byte[] t = Array.Empty<byte>();
|
|
var pos = 0;
|
|
byte counter = 1;
|
|
|
|
using var hmac2 = new HMACSHA256(prk);
|
|
while (pos < len)
|
|
{
|
|
var input = new byte[t.Length + info.Length + 1];
|
|
Buffer.BlockCopy(t, 0, input, 0, t.Length);
|
|
Buffer.BlockCopy(info, 0, input, t.Length, info.Length);
|
|
input[^1] = counter;
|
|
|
|
t = hmac2.ComputeHash(input);
|
|
|
|
var take = Math.Min(t.Length, len - pos);
|
|
Buffer.BlockCopy(t, 0, okm, pos, take);
|
|
|
|
pos += take;
|
|
counter++;
|
|
}
|
|
|
|
CryptographicOperations.ZeroMemory(prk);
|
|
CryptographicOperations.ZeroMemory(t);
|
|
return okm;
|
|
}
|
|
} |