chore: initial project import
This commit is contained in:
commit
26620707a0
347 files changed
+56172
No files matched your search
@@ -0,0 +1,55 @@
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
namespace Fleet.Identity;
|
||||
|
||||
/// <summary>点对点会话派生出的数据面凭据。<c>SessionId</c> 8 字节,<c>Key</c> 32 字节(HMAC-SHA256 的密钥)。</summary>
|
||||
public sealed record SessionCredentials(byte[] SessionId, byte[] Key)
|
||||
{
|
||||
public long SessionIdValue => BitConverter.ToInt64(SessionId, 0);
|
||||
}
|
||||
|
||||
/// <summary>临时 ECDH 密钥:每个会话各生成一个,用完即弃,所以会话密钥具有前向保密。</summary>
|
||||
public sealed class EphemeralKey : IDisposable
|
||||
{
|
||||
private readonly ECDiffieHellman _key = ECDiffieHellman.Create(ECCurve.NamedCurves.nistP256);
|
||||
|
||||
public byte[] PublicKeySpki => _key.ExportSubjectPublicKeyInfo();
|
||||
|
||||
/// <summary>
|
||||
/// 与对端的临时公钥协商,再经 HKDF-SHA256 派生会话凭据。
|
||||
/// 盐是服务端的随机数,info 绑定双方的临时公钥,防止凭据被挪用到别的握手上。
|
||||
/// </summary>
|
||||
public SessionCredentials Derive(ReadOnlySpan<byte> remotePublicKeySpki, ReadOnlySpan<byte> nonce, ReadOnlySpan<byte> clientPublic, ReadOnlySpan<byte> serverPublic)
|
||||
{
|
||||
using ECDiffieHellman remote = ECDiffieHellman.Create();
|
||||
remote.ImportSubjectPublicKeyInfo(remotePublicKeySpki, out _);
|
||||
byte[] secret = _key.DeriveRawSecretAgreement(remote.PublicKey);
|
||||
byte[] info = [.. Encoding.UTF8.GetBytes("fleet|v1|session|"), .. SHA256.HashData(clientPublic), .. SHA256.HashData(serverPublic)];
|
||||
byte[] material = HKDF.DeriveKey(HashAlgorithmName.SHA256, secret, 40, nonce.ToArray(), info);
|
||||
CryptographicOperations.ZeroMemory(secret);
|
||||
return new SessionCredentials(material[..8], material[8..]);
|
||||
}
|
||||
|
||||
public void Dispose() => _key.Dispose();
|
||||
}
|
||||
|
||||
/// <summary>数据面的消息认证:HMAC-SHA256 截断到 16 字节。</summary>
|
||||
public static class DataPlaneMac
|
||||
{
|
||||
public const int Bytes = 16;
|
||||
|
||||
public static void Compute(ReadOnlySpan<byte> key, ReadOnlySpan<byte> data, Span<byte> destination)
|
||||
{
|
||||
Span<byte> full = stackalloc byte[32];
|
||||
HMACSHA256.HashData(key, data, full);
|
||||
full[..Bytes].CopyTo(destination);
|
||||
}
|
||||
|
||||
public static bool Verify(ReadOnlySpan<byte> key, ReadOnlySpan<byte> data, ReadOnlySpan<byte> mac)
|
||||
{
|
||||
Span<byte> expected = stackalloc byte[Bytes];
|
||||
Compute(key, data, expected);
|
||||
return CryptographicOperations.FixedTimeEquals(expected, mac);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user