RFC 2313 specifies the RSAPrivateKey
ASN1 structure as a SEQUENCE
containing the INTEGER
s
- $0$;
- $n$;
- $e$;
- $d$;
- $p$;
- $q$;
- $d\bmod(p-1)$;
- $d\bmod(q-1)$;
- $q^{-1}\bmod p$.
The PEM format consists of such a structure encoded as Base64 and framed by the typical BEGIN/END RSA PRIVATE KEY
header and footer lines.
Thus, you can use any ASN1 library you like to encode the private key parameters. For example, with Python's pyasn1
module, a private key file's contents can be obtained as follows:
import pyasn1.codec.der.encoder
import pyasn1.type.univ
import base64
def pempriv(n, e, d, p, q, dP, dQ, qInv):
template = '-----BEGIN RSA PRIVATE KEY-----\n{}-----END RSA PRIVATE KEY-----\n'
seq = pyasn1.type.univ.Sequence()
for i,x in enumerate((0, n, e, d, p, q, dP, dQ, qInv)):
seq.setComponentByPosition(i, pyasn1.type.univ.Integer(x))
der = pyasn1.codec.der.encoder.encode(seq)
return template.format(base64.encodebytes(der).decode('ascii'))
The parameters dP
, dQ
and qInv
are most easily (as in: lines of code) computed as follows:
dP = d % (p-1)
dQ = d % (q-1)
qInv = pow(q, p-2, p)