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

An ECDSA signature.

Fields

r: Curve.scalar.CompressedScalar

The R component of an ECDSA signature.

s: Curve.scalar.CompressedScalar

The S component of an ECDSA signature.

Values

Constantencoded_length[src]

Length (in bytes) of a raw signature.

Source Code

Source code
pub const encoded_length = Curve.scalar.encoded_length * 2

Constantder_encoded_length_max[src]

Maximum length (in bytes) of a DER-encoded signature.

Source Code

Source code
pub const der_encoded_length_max = encoded_length + 2 + 2 * 3

Error Sets

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 = Verifier.InitError || Verifier.VerifyError

Functions

Functionverifier[src]

pub fn verifier(sig: Signature, public_key: PublicKey) Verifier.InitError!Verifier

Create a Verifier for incremental verification of a signature.

Parameters

public_key: PublicKey

Source Code

Source code
pub fn verifier(sig: Signature, public_key: PublicKey) Verifier.InitError!Verifier {
    return Verifier.init(sig, public_key);
}

Functionverify[src]

pub fn verify(sig: Signature, msg: []const u8, public_key: PublicKey) VerifyError!void

Verify the signature against a message and public key. 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.

Parameters

msg: []const u8
public_key: PublicKey

Source Code

Source code
pub fn verify(sig: Signature, msg: []const u8, public_key: PublicKey) VerifyError!void {
    var st = try sig.verifier(public_key);
    st.update(msg);
    try st.verify();
}

FunctiontoBytes[src]

pub fn toBytes(sig: Signature) [encoded_length]u8

Return the raw signature (r, s) in big-endian format.

Parameters

Source Code

Source code
pub fn toBytes(sig: Signature) [encoded_length]u8 {
    var bytes: [encoded_length]u8 = undefined;
    @memcpy(bytes[0 .. encoded_length / 2], &sig.r);
    @memcpy(bytes[encoded_length / 2 ..], &sig.s);
    return bytes;
}

FunctionfromBytes[src]

pub fn fromBytes(bytes: [encoded_length]u8) Signature

Create a signature from a raw encoding of (r, s). ECDSA always assumes big-endian.

Parameters

bytes: [encoded_length]u8

Source Code

Source code
pub fn fromBytes(bytes: [encoded_length]u8) Signature {
    return Signature{
        .r = bytes[0 .. encoded_length / 2].*,
        .s = bytes[encoded_length / 2 ..].*,
    };
}

FunctiontoDer[src]

pub fn toDer(sig: Signature, buf: *[der_encoded_length_max]u8) []u8

Encode the signature using the DER format. The maximum length of the DER encoding is der_encoded_length_max. The function returns a slice, that can be shorter than der_encoded_length_max.

Parameters

Source Code

Source code
pub fn toDer(sig: Signature, buf: *[der_encoded_length_max]u8) []u8 {
    var fb = io.fixedBufferStream(buf);
    const w = fb.writer();
    const r_len = @as(u8, @intCast(sig.r.len + (sig.r[0] >> 7)));
    const s_len = @as(u8, @intCast(sig.s.len + (sig.s[0] >> 7)));
    const seq_len = @as(u8, @intCast(2 + r_len + 2 + s_len));
    w.writeAll(&[_]u8{ 0x30, seq_len }) catch unreachable;
    w.writeAll(&[_]u8{ 0x02, r_len }) catch unreachable;
    if (sig.r[0] >> 7 != 0) {
        w.writeByte(0x00) catch unreachable;
    }
    w.writeAll(&sig.r) catch unreachable;
    w.writeAll(&[_]u8{ 0x02, s_len }) catch unreachable;
    if (sig.s[0] >> 7 != 0) {
        w.writeByte(0x00) catch unreachable;
    }
    w.writeAll(&sig.s) catch unreachable;
    return fb.getWritten();
}

FunctionfromDer[src]

pub fn fromDer(der: []const u8) EncodingError!Signature

Create a signature from a DER representation. Returns InvalidEncoding if the DER encoding is invalid.

Parameters

der: []const u8

Source Code

Source code
pub fn fromDer(der: []const u8) EncodingError!Signature {
    var sig: Signature = mem.zeroInit(Signature, .{});
    var fb = io.fixedBufferStream(der);
    const reader = fb.reader();
    var buf: [2]u8 = undefined;
    _ = reader.readNoEof(&buf) catch return error.InvalidEncoding;
    if (buf[0] != 0x30 or @as(usize, buf[1]) + 2 != der.len) {
        return error.InvalidEncoding;
    }
    try readDerInt(&sig.r, reader);
    try readDerInt(&sig.s, reader);
    if (fb.getPos() catch unreachable != der.len) return error.InvalidEncoding;

    return sig;
}

Source Code

Source code
pub const Signature = struct {
    /// Length (in bytes) of a raw signature.
    pub const encoded_length = Curve.scalar.encoded_length * 2;
    /// Maximum length (in bytes) of a DER-encoded signature.
    pub const der_encoded_length_max = encoded_length + 2 + 2 * 3;

    /// The R component of an ECDSA signature.
    r: Curve.scalar.CompressedScalar,
    /// The S component of an ECDSA signature.
    s: Curve.scalar.CompressedScalar,

    /// Create a Verifier for incremental verification of a signature.
    pub fn verifier(sig: Signature, public_key: PublicKey) Verifier.InitError!Verifier {
        return Verifier.init(sig, public_key);
    }

    pub const VerifyError = Verifier.InitError || Verifier.VerifyError;

    /// Verify the signature against a message and public key.
    /// 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(sig: Signature, msg: []const u8, public_key: PublicKey) VerifyError!void {
        var st = try sig.verifier(public_key);
        st.update(msg);
        try st.verify();
    }

    /// Return the raw signature (r, s) in big-endian format.
    pub fn toBytes(sig: Signature) [encoded_length]u8 {
        var bytes: [encoded_length]u8 = undefined;
        @memcpy(bytes[0 .. encoded_length / 2], &sig.r);
        @memcpy(bytes[encoded_length / 2 ..], &sig.s);
        return bytes;
    }

    /// Create a signature from a raw encoding of (r, s).
    /// ECDSA always assumes big-endian.
    pub fn fromBytes(bytes: [encoded_length]u8) Signature {
        return Signature{
            .r = bytes[0 .. encoded_length / 2].*,
            .s = bytes[encoded_length / 2 ..].*,
        };
    }

    /// Encode the signature using the DER format.
    /// The maximum length of the DER encoding is der_encoded_length_max.
    /// The function returns a slice, that can be shorter than der_encoded_length_max.
    pub fn toDer(sig: Signature, buf: *[der_encoded_length_max]u8) []u8 {
        var fb = io.fixedBufferStream(buf);
        const w = fb.writer();
        const r_len = @as(u8, @intCast(sig.r.len + (sig.r[0] >> 7)));
        const s_len = @as(u8, @intCast(sig.s.len + (sig.s[0] >> 7)));
        const seq_len = @as(u8, @intCast(2 + r_len + 2 + s_len));
        w.writeAll(&[_]u8{ 0x30, seq_len }) catch unreachable;
        w.writeAll(&[_]u8{ 0x02, r_len }) catch unreachable;
        if (sig.r[0] >> 7 != 0) {
            w.writeByte(0x00) catch unreachable;
        }
        w.writeAll(&sig.r) catch unreachable;
        w.writeAll(&[_]u8{ 0x02, s_len }) catch unreachable;
        if (sig.s[0] >> 7 != 0) {
            w.writeByte(0x00) catch unreachable;
        }
        w.writeAll(&sig.s) catch unreachable;
        return fb.getWritten();
    }

    // Read a DER-encoded integer.
    fn readDerInt(out: []u8, reader: anytype) EncodingError!void {
        var buf: [2]u8 = undefined;
        _ = reader.readNoEof(&buf) catch return error.InvalidEncoding;
        if (buf[0] != 0x02) return error.InvalidEncoding;
        var expected_len = @as(usize, buf[1]);
        if (expected_len == 0 or expected_len > 1 + out.len) return error.InvalidEncoding;
        var has_top_bit = false;
        if (expected_len == 1 + out.len) {
            if ((reader.readByte() catch return error.InvalidEncoding) != 0) return error.InvalidEncoding;
            expected_len -= 1;
            has_top_bit = true;
        }
        const out_slice = out[out.len - expected_len ..];
        reader.readNoEof(out_slice) catch return error.InvalidEncoding;
        if (has_top_bit and out[0] >> 7 == 0) return error.InvalidEncoding;
    }

    /// Create a signature from a DER representation.
    /// Returns InvalidEncoding if the DER encoding is invalid.
    pub fn fromDer(der: []const u8) EncodingError!Signature {
        var sig: Signature = mem.zeroInit(Signature, .{});
        var fb = io.fixedBufferStream(der);
        const reader = fb.reader();
        var buf: [2]u8 = undefined;
        _ = reader.readNoEof(&buf) catch return error.InvalidEncoding;
        if (buf[0] != 0x30 or @as(usize, buf[1]) + 2 != der.len) {
            return error.InvalidEncoding;
        }
        try readDerInt(&sig.r, reader);
        try readDerInt(&sig.s, reader);
        if (fb.getPos() catch unreachable != der.len) return error.InvalidEncoding;

        return sig;
    }
}