struct PublicKey [src]
Fields
n: Modulus
e: Fe
 Members
- fromBytes (Function)
- FromBytesError (Error Set)
- parseDer (Function)
- ParseDerError (Error Set)
Source
 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],
        };
    }
}