I have an RSA private key $\{d,n\}$ and a public key $\{e,n\}$, where $n$ is the modulus, and I also have the prime factors $p$ and $q$ of $n$.

I want to create a PEM file containing this information, so that I can decrypt a file encrypted with the public key using OpenSSL. How can I do this?

  • 3
    $\begingroup$ I'm voting to close this question as off-topic because this is a question about how to use a particular software program (OpenSSL), not cryptography $\endgroup$ – poncho May 8 '15 at 12:15
  • $\begingroup$ @poncho: Technically, this question is about implementing a standard storage format for cryptographic keys. The mention of OpenSSL is really a red herring. I think it's on topic here, if perhaps marginally. (And there's certainly some overlap with Stack Overflow here; not that there's necessarily anything wrong with that.) $\endgroup$ – Ilmari Karonen May 9 '15 at 11:44

RFC 2313 specifies the RSAPrivateKey ASN1 structure as a SEQUENCE containing the INTEGERs

  • $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.encodestring(der).decode('ascii'))

The parameters dP, dQ and qInv are most easily (as in: lines of code) computed as follows:

dP = d % p
dQ = d % q
qInv = pow(q, p - 2, p)
  • $\begingroup$ PyAsn1Error: Attempted "__len__" operation on ASN.1 schema object $\endgroup$ – evandrix Jun 6 '20 at 17:30
  • 1
    $\begingroup$ @evandrix Thanks, seems like some internals of pyasn1 changed. Fixed. $\endgroup$ – yyyyyyy Jun 6 '20 at 18:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.