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:
- identifying header/footer line in PEM, and base64 encoding validity
- valid ASN.1 format (mostly limited to type and length checks)
- 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)