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

A Signer is used to incrementally compute a signature. It can be obtained from a KeyPair, using the signer() function.

Fields

h: Hash
secret_key: SecretKey
noise: ?[noise_length]u8

Functions

Functionupdate[src]

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

Add new data to the message being signed.

Parameters

self: *Signer
data: []const u8

Source Code

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

Functionfinalize[src]

Compute a signature over the entire message.

Parameters

self: *Signer

Source Code

Source code
pub fn finalize(self: *Signer) (IdentityElementError || NonCanonicalError)!Signature {
    const scalar_encoded_length = Curve.scalar.encoded_length;
    const h_len = @max(Hash.digest_length, scalar_encoded_length);
    var h: [h_len]u8 = [_]u8{0} ** h_len;
    const h_slice = h[h_len - Hash.digest_length .. h_len];
    self.h.final(h_slice);

    std.debug.assert(h.len >= scalar_encoded_length);
    const z = reduceToScalar(scalar_encoded_length, h[0..scalar_encoded_length].*);

    const k = deterministicScalar(h_slice.*, self.secret_key.bytes, self.noise);

    const p = try Curve.basePoint.mul(k.toBytes(.big), .big);
    const xs = p.affineCoordinates().x.toBytes(.big);
    const r = reduceToScalar(Curve.Fe.encoded_length, xs);
    if (r.isZero()) return error.IdentityElement;

    const k_inv = k.invert();
    const zrs = z.add(r.mul(try Curve.scalar.Scalar.fromBytes(self.secret_key.bytes, .big)));
    const s = k_inv.mul(zrs);
    if (s.isZero()) return error.IdentityElement;

    return Signature{ .r = r.toBytes(.big), .s = s.toBytes(.big) };
}

Source Code

Source code
pub const Signer = struct {
    h: Hash,
    secret_key: SecretKey,
    noise: ?[noise_length]u8,

    fn init(secret_key: SecretKey, noise: ?[noise_length]u8) !Signer {
        return Signer{
            .h = Hash.init(.{}),
            .secret_key = secret_key,
            .noise = noise,
        };
    }

    /// Add new data to the message being signed.
    pub fn update(self: *Signer, data: []const u8) void {
        self.h.update(data);
    }

    /// Compute a signature over the entire message.
    pub fn finalize(self: *Signer) (IdentityElementError || NonCanonicalError)!Signature {
        const scalar_encoded_length = Curve.scalar.encoded_length;
        const h_len = @max(Hash.digest_length, scalar_encoded_length);
        var h: [h_len]u8 = [_]u8{0} ** h_len;
        const h_slice = h[h_len - Hash.digest_length .. h_len];
        self.h.final(h_slice);

        std.debug.assert(h.len >= scalar_encoded_length);
        const z = reduceToScalar(scalar_encoded_length, h[0..scalar_encoded_length].*);

        const k = deterministicScalar(h_slice.*, self.secret_key.bytes, self.noise);

        const p = try Curve.basePoint.mul(k.toBytes(.big), .big);
        const xs = p.affineCoordinates().x.toBytes(.big);
        const r = reduceToScalar(Curve.Fe.encoded_length, xs);
        if (r.isZero()) return error.IdentityElement;

        const k_inv = k.invert();
        const zrs = z.add(r.mul(try Curve.scalar.Scalar.fromBytes(self.secret_key.bytes, .big)));
        const s = k_inv.mul(zrs);
        if (s.isZero()) return error.IdentityElement;

        return Signature{ .r = r.toBytes(.big), .s = s.toBytes(.big) };
    }
}