structstd.crypto.ecdsa.Ecdsa.Verifier[src]

A Verifier is used to incrementally verify a signature. It can be obtained from a Signature, using the verifier() function.

Fields

h: Hash
r: Curve.scalar.Scalar
s: Curve.scalar.Scalar
public_key: PublicKey

Error Sets

Error SetInitError[src]

Errors

anyerror means the error set is known only at runtime.

IdentityElement IdentityElementError
NonCanonical NonCanonicalError

Source Code

Source code
pub const InitError = IdentityElementError || NonCanonicalError

Error SetVerifyError[src]

Errors

anyerror means the error set is known only at runtime.

IdentityElement IdentityElementError
NonCanonical NonCanonicalError
SignatureVerificationFailed SignatureVerificationError

Source Code

Source code
pub const VerifyError = IdentityElementError || NonCanonicalError ||
    SignatureVerificationError

Functions

Functionupdate[src]

pub fn update(self: *Verifier, data: []const u8) void

Add new content to the message to be verified.

Parameters

self: *Verifier
data: []const u8

Source Code

Source code
pub fn update(self: *Verifier, data: []const u8) void {
    self.h.update(data);
}

Functionverify[src]

pub fn verify(self: *Verifier) VerifyError!void

Verify that the signature is valid for the entire message.

Parameters

self: *Verifier

Source Code

Source code
pub fn verify(self: *Verifier) VerifyError!void {
    const ht = Curve.scalar.encoded_length;
    const h_len = @max(Hash.digest_length, ht);
    var h: [h_len]u8 = [_]u8{0} ** h_len;
    self.h.final(h[h_len - Hash.digest_length .. h_len]);

    const z = reduceToScalar(ht, h[0..ht].*);
    if (z.isZero()) {
        return error.SignatureVerificationFailed;
    }

    const s_inv = self.s.invert();
    const v1 = z.mul(s_inv).toBytes(.little);
    const v2 = self.r.mul(s_inv).toBytes(.little);
    const v1g = try Curve.basePoint.mulPublic(v1, .little);
    const v2pk = try self.public_key.p.mulPublic(v2, .little);
    const vxs = v1g.add(v2pk).affineCoordinates().x.toBytes(.big);
    const vr = reduceToScalar(Curve.Fe.encoded_length, vxs);
    if (!self.r.equivalent(vr)) {
        return error.SignatureVerificationFailed;
    }
}

Source Code

Source code
pub const Verifier = struct {
    h: Hash,
    r: Curve.scalar.Scalar,
    s: Curve.scalar.Scalar,
    public_key: PublicKey,

    pub const InitError = IdentityElementError || NonCanonicalError;

    fn init(sig: Signature, public_key: PublicKey) InitError!Verifier {
        const r = try Curve.scalar.Scalar.fromBytes(sig.r, .big);
        const s = try Curve.scalar.Scalar.fromBytes(sig.s, .big);
        if (r.isZero() or s.isZero()) return error.IdentityElement;

        return Verifier{
            .h = Hash.init(.{}),
            .r = r,
            .s = s,
            .public_key = public_key,
        };
    }

    /// Add new content to the message to be verified.
    pub fn update(self: *Verifier, data: []const u8) void {
        self.h.update(data);
    }

    pub const VerifyError = IdentityElementError || NonCanonicalError ||
        SignatureVerificationError;

    /// Verify that the signature is valid for the entire message.
    pub fn verify(self: *Verifier) VerifyError!void {
        const ht = Curve.scalar.encoded_length;
        const h_len = @max(Hash.digest_length, ht);
        var h: [h_len]u8 = [_]u8{0} ** h_len;
        self.h.final(h[h_len - Hash.digest_length .. h_len]);

        const z = reduceToScalar(ht, h[0..ht].*);
        if (z.isZero()) {
            return error.SignatureVerificationFailed;
        }

        const s_inv = self.s.invert();
        const v1 = z.mul(s_inv).toBytes(.little);
        const v2 = self.r.mul(s_inv).toBytes(.little);
        const v1g = try Curve.basePoint.mulPublic(v1, .little);
        const v2pk = try self.public_key.p.mulPublic(v2, .little);
        const vxs = v1g.add(v2pk).affineCoordinates().x.toBytes(.big);
        const vr = reduceToScalar(Curve.Fe.encoded_length, vxs);
        if (!self.r.equivalent(vr)) {
            return error.SignatureVerificationFailed;
        }
    }
}