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

Fields

n: Modulus
e: Fe

Error Sets

Error SetFromBytesError[src]

Errors

anyerror means the error set is known only at runtime.

CertificatePublicKeyInvalid

Source Code

Source code
pub const FromBytesError = error{CertificatePublicKeyInvalid}

Error SetParseDerError[src]

Errors

anyerror means the error set is known only at runtime.

CertificateFieldHasInvalidLength ParseError
CertificateFieldHasWrongDataType

Source Code

Source code
pub const ParseDerError = der.Element.ParseError || error{CertificateFieldHasWrongDataType}

Functions

FunctionfromBytes[src]

pub fn fromBytes(pub_bytes: []const u8, modulus_bytes: []const u8) FromBytesError!PublicKey

Parameters

pub_bytes: []const u8
modulus_bytes: []const u8

Source Code

Source code
pub fn fromBytes(pub_bytes: []const u8, modulus_bytes: []const u8) FromBytesError!PublicKey {
    // Reject modulus below 512 bits.
    // 512-bit RSA was factored in 1999, so this limit barely means anything,
    // but establish some limit now to ratchet in what we can.
    const _n = Modulus.fromBytes(modulus_bytes, .big) catch return error.CertificatePublicKeyInvalid;
    if (_n.bits() < 512) return error.CertificatePublicKeyInvalid;

    // Exponent must be odd and greater than 2.
    // Also, it must be less than 2^32 to mitigate DoS attacks.
    // Windows CryptoAPI doesn't support values larger than 32 bits [1], so it is
    // unlikely that exponents larger than 32 bits are being used for anything
    // Windows commonly does.
    // [1] https://learn.microsoft.com/en-us/windows/win32/api/wincrypt/ns-wincrypt-rsapubkey
    if (pub_bytes.len > 4) return error.CertificatePublicKeyInvalid;
    const _e = Fe.fromBytes(_n, pub_bytes, .big) catch return error.CertificatePublicKeyInvalid;
    if (!_e.isOdd()) return error.CertificatePublicKeyInvalid;
    const e_v = _e.toPrimitive(u32) catch return error.CertificatePublicKeyInvalid;
    if (e_v < 2) return error.CertificatePublicKeyInvalid;

    return .{
        .n = _n,
        .e = _e,
    };
}

FunctionparseDer[src]

pub fn parseDer(pub_key: []const u8) ParseDerError!struct { modulus: []const u8, exponent: []const u8 }

Parameters

pub_key: []const u8

Source Code

Source code
pub fn parseDer(pub_key: []const u8) ParseDerError!struct { modulus: []const u8, exponent: []const u8 } {
    const pub_key_seq = try der.Element.parse(pub_key, 0);
    if (pub_key_seq.identifier.tag != .sequence) return error.CertificateFieldHasWrongDataType;
    const modulus_elem = try der.Element.parse(pub_key, pub_key_seq.slice.start);
    if (modulus_elem.identifier.tag != .integer) return error.CertificateFieldHasWrongDataType;
    const exponent_elem = try der.Element.parse(pub_key, modulus_elem.slice.end);
    if (exponent_elem.identifier.tag != .integer) return error.CertificateFieldHasWrongDataType;
    // Skip over meaningless zeroes in the modulus.
    const modulus_raw = pub_key[modulus_elem.slice.start..modulus_elem.slice.end];
    const modulus_offset = for (modulus_raw, 0..) |byte, i| {
        if (byte != 0) break i;
    } else modulus_raw.len;
    return .{
        .modulus = modulus_raw[modulus_offset..],
        .exponent = pub_key[exponent_elem.slice.start..exponent_elem.slice.end],
    };
}

Source Code

Source code
pub const PublicKey = struct {
    n: Modulus,
    e: Fe,

    pub const FromBytesError = error{CertificatePublicKeyInvalid};

    pub fn fromBytes(pub_bytes: []const u8, modulus_bytes: []const u8) FromBytesError!PublicKey {
        // Reject modulus below 512 bits.
        // 512-bit RSA was factored in 1999, so this limit barely means anything,
        // but establish some limit now to ratchet in what we can.
        const _n = Modulus.fromBytes(modulus_bytes, .big) catch return error.CertificatePublicKeyInvalid;
        if (_n.bits() < 512) return error.CertificatePublicKeyInvalid;

        // Exponent must be odd and greater than 2.
        // Also, it must be less than 2^32 to mitigate DoS attacks.
        // Windows CryptoAPI doesn't support values larger than 32 bits [1], so it is
        // unlikely that exponents larger than 32 bits are being used for anything
        // Windows commonly does.
        // [1] https://learn.microsoft.com/en-us/windows/win32/api/wincrypt/ns-wincrypt-rsapubkey
        if (pub_bytes.len > 4) return error.CertificatePublicKeyInvalid;
        const _e = Fe.fromBytes(_n, pub_bytes, .big) catch return error.CertificatePublicKeyInvalid;
        if (!_e.isOdd()) return error.CertificatePublicKeyInvalid;
        const e_v = _e.toPrimitive(u32) catch return error.CertificatePublicKeyInvalid;
        if (e_v < 2) return error.CertificatePublicKeyInvalid;

        return .{
            .n = _n,
            .e = _e,
        };
    }

    pub const ParseDerError = der.Element.ParseError || error{CertificateFieldHasWrongDataType};

    pub fn parseDer(pub_key: []const u8) ParseDerError!struct { modulus: []const u8, exponent: []const u8 } {
        const pub_key_seq = try der.Element.parse(pub_key, 0);
        if (pub_key_seq.identifier.tag != .sequence) return error.CertificateFieldHasWrongDataType;
        const modulus_elem = try der.Element.parse(pub_key, pub_key_seq.slice.start);
        if (modulus_elem.identifier.tag != .integer) return error.CertificateFieldHasWrongDataType;
        const exponent_elem = try der.Element.parse(pub_key, modulus_elem.slice.end);
        if (exponent_elem.identifier.tag != .integer) return error.CertificateFieldHasWrongDataType;
        // Skip over meaningless zeroes in the modulus.
        const modulus_raw = pub_key[modulus_elem.slice.start..modulus_elem.slice.end];
        const modulus_offset = for (modulus_raw, 0..) |byte, i| {
            if (byte != 0) break i;
        } else modulus_raw.len;
        return .{
            .modulus = modulus_raw[modulus_offset..],
            .exponent = pub_key[exponent_elem.slice.start..exponent_elem.slice.end],
        };
    }
}