Files
SocialPub/PrivaPub/Federation/Signing/RequestSignature.cs
T
thepraandClaude Opus 5.5 e708f1ad2e hs2019 signatures hashed with SHA-512, and SHA-512 digests
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
2026-10-06 11:13:59 +02:00

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);
}
}