struct PublicKey [src]

Fields

n: Modulus
e: Fe

Members

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], }; } }