2

I've built a simple application that reads in an RSA key, checks the header and starts identifying properties of the RSA key to make sure it is valid (Using child_process in express to run

$ openssl rsa -inform PEM -in ~/.ssh/id_rsa -check

So off of a rest call from my local server, I can check the headers, take a guess that it is PEM base64 encoded, dump out to the terminal, verify it is consistent with the proper structure of a key.

When I started seeing there were many ways that the RSA key could come in, whether PEM, DER, NET, I was hoping to get guidance from some experts on what the most likely form that you have received keys in and ways that can be used to verify their integrity or perhaps their structure.

I would be considering keys for dates after 2030 ultimately (So if a 2048 bit key came through I may suggest that the key be made 4096 bits as a stronger alternative).

TL;DR - Of all the forms that RSA keys are typically handled, what are the primary formats that are used, and what are some potential validation approaches.

  • IF you are using RSA for private communications with friends, then there will obviously be no need at all to care the standards concerning the form (format) in which the keys are represented on paper. In that case and with reference to the fact that you are considering eventual use of arbitrarily larger keys than commonly used today, I suppose it could be of some benefit to you to at least take a look at my RSA software which is coded in Python (s13.zetaboards.com/Crypto/topic/7234475/1/). – Mok-Kong Shen Jul 5 '16 at 14:25
2

Common forms are PKCS#12/PFX (an encrypted key pair, possibly with additional certificates) and PEM or DER form PKCS#1 as used by OpenSSL and OpenSSH (that's what id_rsa will be). PEM is a base64 version of the DER binary (ASN.1) form with identifying header/footer, it's not otherwise a distinct form, except that it allows encryption where as PKCS#1 DER does not.

If the key is encrypted (PEM form only) it will contain extra header lines to indicate the encryption and IV, e.g.:

-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,AA171F6005B3DD31
...

PKCS#1 is RSA only, PKCS#8 is a more general purpose "container" for keys, it too is ASN.1 but it explicitly indicates the type of data within, e.g. (see offset 9, line 4):

$ openssl pkcs8 -inform PEM -in ~/.ssh/id_rsa -topk8 -nocrypt \
  -outform DER -out id_rsa.p8 
$ dumpasn1 -tilda id_rsa.p8
 0 1213: SEQUENCE {
 4    1: . INTEGER 0
 7   13: . SEQUENCE {
 9    9: . . OBJECT IDENTIFIER rsaEncryption (1 2 840 113549 1 1 1)
       : . . . (PKCS #1)
20    0: . . NULL
       : . . }
22 1191: . OCTET STRING, encapsulates {
26 1187: . . SEQUENCE {
30    1: . . . INTEGER 0
33  257: . . . INTEGER    
       : . . . . 00 B1 1F 09 61 C1 A1 09    ....a...
 ...

(I'm using dumpasn1 here instead of openssl asn1parse, embarrassingly, the latter fails to parse the pkcs8 output correctly.)

OpenSSH doesn't (AFAIK) support PKCS#8 other than for import/export, they have their own format. That format is used for newer key types only (Ed25519) but is planned to be the default in future.

There are a few things you can usefully check:

  1. identifying header/footer line in PEM, and base64 encoding validity
  2. valid ASN.1 format (mostly limited to type and length checks)
  3. numeric integrity of RSA parameters

You might also ruminate on the value of the public exponent (too large can cause interoperability problems, too small is implicated with security problems for some applications).

The openssl rsa ... -check command checks 1 (PEM only) and 2 implicitly, and 3 explicitly. See the OpenSSL API RSA_check_key() documentation for details of the checks. That should be sufficient checking for most, I think.

An RSA private key file (almost always) contains more than just the private key exponent, it also contains the public key parameters and some intermediate values for optimisation (via the CRT), those values can be checked for consistency or primacy. The "key size" is the length of the ''modulus'', with the caveat that there will (usually) be a leading 00 byte to ensure it's interpreted as a positive integer (ASN.1 signed-ness issue).

For a different view you could also do:

openssl asn1parse -inform PEM -in ~/.ssh/id_rsa

(but that does not check the RSA parameters)

0

There are a few standards that discuss this topic:

  • PKCS #8 is about private key storage.
  • PKCS #11 is about the API's being used by cryptographic software.
  • PKCS #12 is about an archive format for many cryptography objects in a single file.
  • PKCS #7 the RFC2315 is also a good source of information. It is about how the PKIs work with signing / encrypting.
  • PKCS Wikipedia has a good overview of the subject.

In short, the landscape of keys and certificates is too wide to give you a specific answer. All I can do is give you this list of further study subjects to get you on your way.

  • 1
    What about non-PKCS standards like PGP ascii armor? – Mike Ounsworth Dec 7 '15 at 19:19
  • As far as I know pgp follows the PKCS standards. I know pgp can utilize X.509 certificates. I will look into the pgp key format. – LvB Dec 7 '15 at 21:31

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.