3

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?

Ilmari Karonen
  • 46,120
  • 5
  • 105
  • 181
NxA
  • 103
  • 3
  • 7
  • 3
    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 – poncho May 08 '15 at 12:15
  • @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 [so] here; not that there's necessarily anything wrong with that.) – Ilmari Karonen May 09 '15 at 11:44

1 Answers1

6

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.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)
yyyyyyy
  • 12,081
  • 4
  • 47
  • 68
  • PyAsn1Error: Attempted "__len__" operation on ASN.1 schema object – evandrix Jun 06 '20 at 17:30
  • 1
    @evandrix Thanks, seems like some internals of pyasn1 changed. Fixed. – yyyyyyy Jun 06 '20 at 18:58
  • python3 says: DeprecationWarning: encodestring() is a deprecated alias since 3.1, use encodebytes(). replacing it works fine as far as I can see. – acapola Mar 05 '21 at 20:57
  • the code given for dP and dQ is wrong. the one given for qInv is convoluted. consider this instead expected_dP = d % (p - 1);expected_dQ = d % (q - 1); expected_qInv = pow(q, -1, p) – acapola Mar 05 '21 at 22:06
  • @acapola Thanks! Fixed. – yyyyyyy Mar 06 '21 at 18:49