Files
suaveplan/packages/security-stack/crypto/crypto-rsa/src/keys/parse-pkcs1-public.ts
2026-05-27 23:47:53 +01:00

49 lines
1.5 KiB
TypeScript

import { DerReader } from "../asn1/reader.js";
import { CRYPTO_RSA_CODES, CryptoRsaError } from "../errors/errors.js";
import type { RsaPublicKey } from "./keys.types.js";
/**
* Parse a DER-encoded PKCS#1 `RSAPublicKey ::= SEQUENCE { modulus INTEGER,
* publicExponent INTEGER }` per RFC 8017 Appendix A.1.1.
*
* Validates that the public exponent is odd and `>= 3`, matching the
* conformance requirement in the spec delta.
*/
export function parseRsaPublicKeyPkcs1(bytes: Uint8Array): RsaPublicKey {
const reader = new DerReader(bytes);
const seq = reader.readSequence();
const n = seq.readInteger();
const e = seq.readInteger();
seq.assertEnd();
reader.assertEnd();
return finalisePublicKey(n, e);
}
/**
* Internal: validate `(n, e)` and compute `bitLength`. Used by SPKI / JWK
* parsers as well as the PKCS#1 path.
*/
export function finalisePublicKey(n: bigint, e: bigint): RsaPublicKey {
if (n <= 0n) {
throw new CryptoRsaError(
CRYPTO_RSA_CODES.INVALID_KEY,
"error.crypto-rsa.invalid-key.modulus"
);
}
if (e < 3n) {
throw new CryptoRsaError(
CRYPTO_RSA_CODES.INVALID_KEY,
"error.crypto-rsa.invalid-key.exponent-too-small",
{ context: { e: e.toString() } }
);
}
if ((e & 1n) === 0n) {
throw new CryptoRsaError(
CRYPTO_RSA_CODES.INVALID_KEY,
"error.crypto-rsa.invalid-key.exponent-even"
);
}
const bitLength = n.toString(2).length;
return { n, e, bitLength };
}