24

Inside a shell script I want verify public RSA file. All I want to do is that find a way to check this file is a genuine public key file, nothing else.

Can I ask experts here what are the ways I can verify this input file to check this is a genuine public key file , not a regular file.

I will be using this public key file in future to validate an incoming encrypt gzip file but that is out of scope for now.

All I want is validate input file to check its genuine RSA public key file not an ordinary file.please note that I do not have any other files with me (eg : private key) .

e.g.: if the file is ‘public.pem’ I just want check inside that it’s a genuine RSA public key file not just a file with texts or file is not corrupted . I’m already checking that file is not zero sized and md5 .

other possible checks I found check file got text ‘BEGIN PUBLIC KEY’ and ‘END PUBLIC KEY’ Also found this command in google , Is there a better way to do this using openssl

‘openssl rsa -noout -text -inform PEM -in pubkey.pem -pubin’

Thanks

divanov
  • 6,173
  • 3
  • 32
  • 51
csf
  • 529
  • 1
  • 4
  • 16
  • using openssl is probably the only way you want to do this. simply checking for the begin/end delimiters is pointless. I could send you a file with `BEGIN PUBLIC KEY heeheeheethisisnotvalidrsa END PUBLIC KEY` and your "verifier" would accept that. – Marc B Oct 08 '14 at 14:31
  • exactly thats why i would like to know a better way to validay this public rsa file, please note that this a public RSA file of a remote server . – csf Oct 08 '14 at 14:35

3 Answers3

45

It's possible to use any public key format parser, including openssl or even parse key yourself as the format is not that difficult.

Command line tools set a non-zero exit code, when parsing fails:

openssl rsa -inform PEM -pubin -in pubkey.pem -noout &> /dev/null
if [ $? != 0 ] ; then
    echo "this was definitely not a RSA public key in PEM format"
    exit 1
fi

Just to check any public key:

openssl pkey -inform PEM -pubin -in pubkey.pem -noout &> /dev/null
if [ $? != 0 ] ; then
    echo "this was definitely not a public key in PEM format"
    exit 1
fi
divanov
  • 6,173
  • 3
  • 32
  • 51
  • 1
    Assuming you mean Java (JRE) keytool, that cannot read a public key. A certficate yes, and an app can then `.getPublicKey()` from the cert, but publickey directly no. OTOH an app can directly read a generic (PKCS#8) pubkey in DER, but base64 less easily without an addon like BouncyCastle. As an aside, on `openssl` commandline `-inform PEM` is the default and can be omitted, and output options `-text -noout` can be omitted when you're discarding the output anyway; or with `-noout` and no other output option(s) you don't need to discard. – dave_thompson_085 Oct 09 '14 at 22:06
  • Yes, it looks like keytool cannot do that. base64 is supported both by `base64` utility, for example, and in Java by `javax.xml.bind.DataTypeConverter` class. I like to be explicit about formats and other things, there is not much gain in skipping format neither. You are correct that `-noout` and `-text` does not make sense together, but output still have to discarded, because there are possible error messages reported even with `-noout` option. – divanov Oct 14 '14 at 10:47
  • You're right I forgot about javax.xml, which wasn't there when I first encountered this issue. Although you actually need both base64 and the BEGIN/END handling, which is a few lines more. `-noout -text` do make sense *together* (to output the human-readable display without the encoded cert) and so do similar combinations like `-noout -subject -enddate`; they just don't make any difference when stdout is discarded. You're also right about discarding the error messages; I'm so used to them I hardly notice, but others will. – dave_thompson_085 Oct 15 '14 at 08:51
  • 3
    Note to future me: you could do `openssl pkey -inform PEM -pubin -in pubkey.pem -noout &> /dev/null || echo "this was definitely not a public key in PEM format"` – eis Mar 09 '17 at 15:07
  • Is it possible to validate against a certification chain? To make sure the certificate (public key) came from a valid private key... Can't find in the answer :( – zion Nov 11 '21 at 04:13
5

The following script should work for all PEM-formatted keys and certs supported by OpenSSL. I have tested it on various valid and invalid ECDSA and RSA keys with matching and non-matching certs.

Save this as verify-cert-key:

#!/usr/bin/env bash
certFile="${1}"
keyFile="${2}"
certPubKey="$(openssl x509 -noout -pubkey -in "${certFile}")"
keyPubKey="$(openssl pkey -pubout -in "${keyFile}")"
if [[ "${certPubKey}" == "${keyPubKey}" ]]
then
  echo "PASS: key and cert match"
else
  echo "FAIL: key and cert DO NOT match"
fi

Make it executable:

chmod +x verify-cert-key

Run it on a cert and key:

./verify-cert-key server-crt.pem server-key.pem
Alain O'Dea
  • 21,033
  • 1
  • 58
  • 84
  • I should note that running the commands and doing a visual comparison is quite easy – Ricardo Saracino Sep 25 '19 at 15:51
  • @ricardo-saracino does comparing the public keys visually when they are dozens of hex digits long and potentially off by one digit expose you to greater risk of error? – Alain O'Dea Sep 26 '19 at 21:36
2

Try this command if your public key starts with -----BEGIN RSA PUBLIC KEY-----

openssl rsa -RSAPublicKey_in -in /path/to/pub_key.pem -noout -text
Quanlong
  • 24,028
  • 16
  • 69
  • 79
  • 1
    If the file only has `-----BEGIN PUBLIC KEY-----` (PKCS#8), you can do `openssl rsa -pubin -in public.pem -RSAPublicKey_out | openssl rsa -RSAPublicKey_in -noout -text` to make this answer work. It shows the modulus and exponent. – artless noise May 08 '23 at 13:44