A draft-cavage hs2019 signature leaves the hash to the key: with an RSA key it is tried with SHA-256, as nearly everyone signs, then with SHA-512, as some do; rsa-sha256 stays SHA-256 only. A Digest of SHA-512= is checked as SHA-256= is. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LsXgEaXee4GCU1hwYgPJXw
46 lines
2.2 KiB
C#
46 lines
2.2 KiB
C#
namespace PrivaPub.Federation.Signing
|
|
{
|
|
// What signed a request: an RFC 9421 message signature when it carries Signature-Input, else a draft-cavage Signature;
|
|
// the inbox and signed fetches check either the same way.
|
|
public sealed class RequestSignature
|
|
{
|
|
readonly SignatureParameters _cavage;
|
|
readonly MessageSignature _message;
|
|
|
|
RequestSignature(SignatureParameters cavage, MessageSignature message)
|
|
{
|
|
_cavage = cavage;
|
|
_message = message;
|
|
}
|
|
|
|
public string KeyId => _message?.KeyId ?? _cavage.KeyId;
|
|
public string Algorithm => _message != default ? _message.Algorithm ?? "rsa-v1_5-sha256" : _cavage.Algorithm;
|
|
// how the ledger names it: "cavage:rsa-sha256", "rfc9421:rsa-v1_5-sha256"
|
|
public string Scheme => _message != default ? "rfc9421:" + Algorithm : "cavage:" + Algorithm;
|
|
public string[] Covered => _message?.Components ?? _cavage.Headers;
|
|
|
|
// the request's signature, or null when it has none it can read
|
|
public static RequestSignature Of(HttpRequest request)
|
|
{
|
|
if (MessageSignatures.Present(request))
|
|
{
|
|
var message = MessageSignatures.Parse(request.Headers["Signature-Input"].ToString(), request.Headers["Signature"].ToString());
|
|
return message == default ? default : new RequestSignature(default, message);
|
|
}
|
|
var cavage = HttpSignatures.Parse(request.Headers["Signature"].ToString());
|
|
return cavage == default ? default : new RequestSignature(cavage, default);
|
|
}
|
|
|
|
// what is wrong with the request as signed (unsigned target or digest, a stale date...), or null
|
|
public string Problem(HttpRequest request, byte[] body) =>
|
|
_message != default ? MessageSignatures.CheckRequest(request, _message, body) : HttpSignatures.CheckRequest(request, _cavage, body);
|
|
|
|
// the string the signature is over: the signing string, or RFC 9421's signature base against our public address
|
|
public string Signed(HttpRequest request, string baseAddress) =>
|
|
_message != default ? MessageSignatures.Base(request, _message, baseAddress) : HttpSignatures.SigningString(request, _cavage);
|
|
|
|
public bool VerifiedBy(string publicKeyPem, string signed) =>
|
|
_message != default ? MessageSignatures.Verify(publicKeyPem, _message, signed) : HttpSignatures.Verify(publicKeyPem, signed, _cavage.Signature, _cavage.Algorithm);
|
|
}
|
|
}
|