PKCS#1 RSA keys, the RSA PRIVATE KEY and RSA PUBLIC KEY encodings
RSAPrivateKey and RSAPublicKey, the RSA PRIVATE KEY and RSA PUBLIC KEY PEM blocks OpenSSL wrote by default for years and appliances still emit. parse and parsePublic read them into their components, and encode and encodePublic write them back.
Neither structure carries an algorithm identifier, which is what separates them from PKCS#8 and SubjectPublicKeyInfo. So what the key is used under is the caller's decision, never a default this module supplies, and nothing here routes through pki.schema.parse: a SEQUENCE of INTEGERs is a shape other structures take, and detecting by shape alone would be a guess.
Every relation the specification states between the components is checked, in the same pass that reads them. Appendix A.1 fixes the field order and the two-or-more-primes rule, sec. 3.1 requires the public exponent to be odd and between 3 and the modulus, and sec. 3.2 places the private exponent, the two CRT exponents and the coefficient below the modulus or their own prime. A component outside those describes no key, and the structure alone cannot say so.
pki.schema.pkcs1.parse
pki.schema.pkcs1.parse(input, opts) -> key
Read an RFC 8017 Appendix A.1.2 RSAPrivateKey, as DER bytes or an RSA PRIVATE KEY PEM block, into { version, modulus, publicExponent, privateExponent, prime1, prime2, exponent1, exponent2, coefficient, otherPrimeInfos }. Every component is a BigInt.
The structure names no algorithm, so nothing here decides what the key is used under. Read it and hand the components to the verb that does.
Fail-closed on the specification's own relations: a version other than 0 or 1, a version disagreeing with whether other prime infos are present, an OtherPrimeInfo that is not three integers, a component that is not a positive integer, a public exponent outside 3 <= e < n or an even one, and a private exponent, CRT exponent or coefficient at or above its bound are each refused with their own pkcs1/* code.
Example
// requires: der -- an RSAPrivateKey, from `openssl genrsa` or an appliance that emits one
var key = pki.schema.pkcs1.parse(der);
key.version; // 0
key.publicExponent; // 65537n
References
- spec RFC 8017
pki.schema.pkcs1.parsePublic
pki.schema.pkcs1.parsePublic(input, opts) -> key
Read an RFC 8017 Appendix A.1.1 RSAPublicKey, as DER bytes or an RSA PUBLIC KEY PEM block, into { modulus, publicExponent }. A structure carrying anything else, including a private key, is refused: the two encodings are told apart by their shape and neither door reads the other's.
Example
// requires: der -- an RSAPrivateKey, from `openssl genrsa` or an appliance that emits one
var priv = pki.schema.pkcs1.parse(der);
var pubDer = pki.schema.pkcs1.encodePublic({ modulus: priv.modulus, publicExponent: priv.publicExponent });
pki.schema.pkcs1.parsePublic(pubDer).publicExponent; // 65537n
References
- spec RFC 8017
pki.schema.pkcs1.encode
pki.schema.pkcs1.encode(key) -> Buffer
Write an RSAPrivateKey back to DER from the shape parse returns. What parse read is what this writes: a key read and written again produces the bytes it came from.
Example
// requires: der -- an RSAPrivateKey, from `openssl genrsa` or an appliance that emits one
pki.schema.pkcs1.encode(pki.schema.pkcs1.parse(der)).equals(der); // true
References
- spec RFC 8017
pki.schema.pkcs1.encodePublic
pki.schema.pkcs1.encodePublic(key) -> Buffer
Write an RSAPublicKey back to DER from the shape parsePublic returns.
Example
// requires: der -- an RSAPrivateKey, from `openssl genrsa` or an appliance that emits one
var priv = pki.schema.pkcs1.parse(der);
var pubDer = pki.schema.pkcs1.encodePublic({ modulus: priv.modulus, publicExponent: priv.publicExponent });
pki.schema.pkcs1.encodePublic(pki.schema.pkcs1.parsePublic(pubDer)).equals(pubDer); // true
References
- spec RFC 8017