structstd.crypto.Certificate.rsa.PKCS1v1_5Signature[src]

RFC 3447 8.2 RSASSA-PKCS1-v1_5

Error Sets

Error SetVerifyError[src]

Errors

anyerror means the error set is known only at runtime.

InvalidSignature
MessageTooLong EncryptError

Source Code

Source code
pub const VerifyError = EncryptError || error{InvalidSignature}

Functions

FunctionfromBytes[src]

pub fn fromBytes(comptime modulus_len: usize, msg: []const u8) [modulus_len]u8

Parameters

modulus_len: usize
msg: []const u8

Source Code

Source code
pub fn fromBytes(comptime modulus_len: usize, msg: []const u8) [modulus_len]u8 {
    var result: [modulus_len]u8 = undefined;
    @memcpy(result[0..msg.len], msg);
    @memset(result[msg.len..], 0);
    return result;
}

Functionverify[src]

pub fn verify( comptime modulus_len: usize, sig: [modulus_len]u8, msg: []const u8, public_key: PublicKey, comptime Hash: type, ) VerifyError!void

Parameters

modulus_len: usize
sig: [modulus_len]u8
msg: []const u8
public_key: PublicKey
Hash: type

Source Code

Source code
pub fn verify(
    comptime modulus_len: usize,
    sig: [modulus_len]u8,
    msg: []const u8,
    public_key: PublicKey,
    comptime Hash: type,
) VerifyError!void {
    try concatVerify(modulus_len, sig, &.{msg}, public_key, Hash);
}

FunctionconcatVerify[src]

pub fn concatVerify( comptime modulus_len: usize, sig: [modulus_len]u8, msg: []const []const u8, public_key: PublicKey, comptime Hash: type, ) VerifyError!void

Parameters

modulus_len: usize
sig: [modulus_len]u8
msg: []const []const u8
public_key: PublicKey
Hash: type

Source Code

Source code
pub fn concatVerify(
    comptime modulus_len: usize,
    sig: [modulus_len]u8,
    msg: []const []const u8,
    public_key: PublicKey,
    comptime Hash: type,
) VerifyError!void {
    const em_dec = try encrypt(modulus_len, sig, public_key);
    const em = try EMSA_PKCS1_V1_5_ENCODE(msg, modulus_len, Hash);
    if (!std.mem.eql(u8, &em_dec, &em)) return error.InvalidSignature;
}

Source Code

Source code
pub const PKCS1v1_5Signature = struct {
    pub fn fromBytes(comptime modulus_len: usize, msg: []const u8) [modulus_len]u8 {
        var result: [modulus_len]u8 = undefined;
        @memcpy(result[0..msg.len], msg);
        @memset(result[msg.len..], 0);
        return result;
    }

    pub const VerifyError = EncryptError || error{InvalidSignature};

    pub fn verify(
        comptime modulus_len: usize,
        sig: [modulus_len]u8,
        msg: []const u8,
        public_key: PublicKey,
        comptime Hash: type,
    ) VerifyError!void {
        try concatVerify(modulus_len, sig, &.{msg}, public_key, Hash);
    }

    pub fn concatVerify(
        comptime modulus_len: usize,
        sig: [modulus_len]u8,
        msg: []const []const u8,
        public_key: PublicKey,
        comptime Hash: type,
    ) VerifyError!void {
        const em_dec = try encrypt(modulus_len, sig, public_key);
        const em = try EMSA_PKCS1_V1_5_ENCODE(msg, modulus_len, Hash);
        if (!std.mem.eql(u8, &em_dec, &em)) return error.InvalidSignature;
    }

    fn EMSA_PKCS1_V1_5_ENCODE(msg: []const []const u8, comptime emLen: usize, comptime Hash: type) VerifyError![emLen]u8 {
        comptime var em_index = emLen;
        var em: [emLen]u8 = undefined;

        // 1. Apply the hash function to the message M to produce a hash value
        //    H:
        //
        //       H = Hash(M).
        //
        //    If the hash function outputs "message too long," output "message
        //    too long" and stop.
        var hasher: Hash = .init(.{});
        for (msg) |part| hasher.update(part);
        em_index -= Hash.digest_length;
        hasher.final(em[em_index..]);

        // 2. Encode the algorithm ID for the hash function and the hash value
        //    into an ASN.1 value of type DigestInfo (see Appendix A.2.4) with
        //    the Distinguished Encoding Rules (DER), where the type DigestInfo
        //    has the syntax
        //
        //    DigestInfo ::= SEQUENCE {
        //        digestAlgorithm AlgorithmIdentifier,
        //        digest OCTET STRING
        //    }
        //
        //    The first field identifies the hash function and the second
        //    contains the hash value.  Let T be the DER encoding of the
        //    DigestInfo value (see the notes below) and let tLen be the length
        //    in octets of T.
        const hash_der: []const u8 = &switch (Hash) {
            crypto.hash.Sha1 => .{
                0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e,
                0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14,
            },
            crypto.hash.sha2.Sha224 => .{
                0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
                0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05,
                0x00, 0x04, 0x1c,
            },
            crypto.hash.sha2.Sha256 => .{
                0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
                0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05,
                0x00, 0x04, 0x20,
            },
            crypto.hash.sha2.Sha384 => .{
                0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
                0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05,
                0x00, 0x04, 0x30,
            },
            crypto.hash.sha2.Sha512 => .{
                0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
                0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05,
                0x00, 0x04, 0x40,
            },
            else => @compileError("unreachable"),
        };
        em_index -= hash_der.len;
        @memcpy(em[em_index..][0..hash_der.len], hash_der);

        // 3. If emLen < tLen + 11, output "intended encoded message length too
        //    short" and stop.

        // 4. Generate an octet string PS consisting of emLen - tLen - 3 octets
        //    with hexadecimal value 0xff.  The length of PS will be at least 8
        //    octets.
        em_index -= 1;
        @memset(em[2..em_index], 0xff);

        // 5. Concatenate PS, the DER encoding T, and other padding to form the
        //    encoded message EM as
        //
        //       EM = 0x00 || 0x01 || PS || 0x00 || T.
        em[em_index] = 0x00;
        em[1] = 0x01;
        em[0] = 0x00;

        // 6. Output EM.
        return em;
    }
}