struct Verifier [src]
A Verifier is used to incrementally verify a signature.
It can be obtained from a Signature, using the verifier() function.
Fields
h: Sha512
s: CompressedScalar
a: Curve
expected_r: Curve
Members
- InitError (Error Set)
- update (Function)
- verify (Function)
- VerifyError (Error Set)
- verifyStrict (Function)
Source
pub const Verifier = struct {
h: Sha512,
s: CompressedScalar,
a: Curve,
expected_r: Curve,
pub const InitError = NonCanonicalError || EncodingError || IdentityElementError;
fn init(sig: Signature, public_key: PublicKey) InitError!Verifier {
const r = sig.r;
const s = sig.s;
try Curve.scalar.rejectNonCanonical(s);
const a = try Curve.fromBytes(public_key.bytes);
try a.rejectIdentity();
try Curve.rejectNonCanonical(r);
const expected_r = try Curve.fromBytes(r);
try expected_r.rejectIdentity();
var h = Sha512.init(.{});
h.update(&r);
h.update(&public_key.bytes);
return Verifier{ .h = h, .s = s, .a = a, .expected_r = expected_r };
}
/// Add new content to the message to be verified.
pub fn update(self: *Verifier, msg: []const u8) void {
self.h.update(msg);
}
pub const VerifyError = WeakPublicKeyError || IdentityElementError ||
SignatureVerificationError;
/// Verify that the signature is valid for the entire message.
///
/// This function uses cofactored verification for broad interoperability.
/// It aligns single-signature verification with common batch verification approaches.
///
/// Return IdentityElement or NonCanonical if the public key or signature are not in the expected range,
/// or SignatureVerificationError if the signature is invalid for the given message and key.
pub fn verify(self: *Verifier) VerifyError!void {
var hram64: [Sha512.digest_length]u8 = undefined;
self.h.final(&hram64);
const hram = Curve.scalar.reduce64(hram64);
const sb_ah = (try Curve.basePoint.mulDoubleBasePublic(
Curve.scalar.mul8(self.s),
self.a.clearCofactor().neg(),
hram,
));
const check = sb_ah.sub(self.expected_r.clearCofactor());
if (check.rejectIdentity()) |_| {
return error.SignatureVerificationFailed;
} else |_| {}
}
/// Verify that the signature is valid for the entire message using cofactorless verification.
///
/// This function performs strict verification without cofactor multiplication,
/// checking the exact equation: [s]B = R + [H(R,A,m)]A
///
/// This is more restrictive than the cofactored `verify()` method and may reject
/// specially crafted signatures that would be accepted by cofactored verification.
/// But it will never reject valid signatures created using the `sign()` method.
///
/// Return IdentityElement or NonCanonical if the public key or signature are not in the expected range,
/// or SignatureVerificationError if the signature is invalid for the given message and key.
pub fn verifyStrict(self: *Verifier) VerifyError!void {
var hram64: [Sha512.digest_length]u8 = undefined;
self.h.final(&hram64);
const hram = Curve.scalar.reduce64(hram64);
const sb_ah = (try Curve.basePoint.mulDoubleBasePublic(
self.s,
self.a.neg(),
hram,
));
const check = sb_ah.sub(self.expected_r);
if (check.rejectIdentity()) |_| {
return error.SignatureVerificationFailed;
} else |_| {}
}
}