4.7 KiB
Key Takeaways
- PGP are replaceable with native OpenSSL RSA public key crypto and AES-256 keys.
- This approach simplifies crypto operations, and only requires OpenSSL which is widely available.
- Existing PGP keys stored in GnuPG work with OpenSSL via
gpgsm
.
Introduction
The rabbit hole mission of mine to get rid of PGP continues.
Lately I have been looking into converting PGP keys from GnuPG to OpenSSL. This way I can send encrypted data to people not using my OpenSSL-only approach. After all, most people still depend on PGP and it is the format they publish their public keys in.
Exporting A PGP Public Key for Encryption Using OpenSSL
A PGP key cannot be directly read by OpenSSL, but GPG can natively export to SSH and ssh-keygen to PKCS8:
gpg --export-ssh-key <key-id>! > /tmp/test.pub
ssh-keygen -f /tmp/test.pub -e -m PKCS8 > /tmp/test.pem
The above pubkey can be used to encrypt data with OpenSSL as shown on my contact page:
KEY=`openssl rand -hex 32` IV=`openssl rand -hex 16`
ENCRYPTED_KEY_B64=`openssl pkeyutl -encrypt -pubin -inkey /tmp/test.pem \
-pkeyopt rsa_padding_mode:oaep <<< $KEY|base64`
BLOB=`openssl enc -aes-256-cfb -a -e -K ${KEY} -iv ${IV} -in some-file`
echo "PKCS11-VAULT;aes-256-cfb;rsa_padding_mode:oaep;$ENCRYPTED_KEY_B64:$IV:$BLOB;" \
> encrypted.txt
The steps of the above are:
- Create an initialization vector [1] and an encryption key
- Encrypt the one-time key to test.pem (our exported PGP-key)
- Encrypt
some-file
using the key and IV using 256 bits AES in CFB-mode - Format the output in my PV-format.
Store encrypted.txt
for decryption in the next section.
Exporting a PGP Private Key for Decryption Using OpenSSL
This part is a bit more complex. For the sake of an example, let us say you received an encrypted blob with an IV and encrypted key, using the approach shown in the former section. You have the key stored in GnuPG.
gpgsm
can export your private key to p12, which is readable for
OpenSSL [2].
First list your secret keys in the GnuPG store: gpg --list-secret-keys --with-keygrip
.
Convert the key to X.509 by: gpgsm --gen-key -o /tmp/temp.crt
. You need to fill the values requested:
- Select "existing key"
- Fill the keygrip from the GPG secret key listing. Make sure you use the right key, since GPG generates several keys behind the scenes (the encryption key)
- Fill the cn (this needs to be on the format "cn=...") and e-mail
- Accept the other values as empty and accept the creation
Now import the certificate into gpgsm
: gpgsm --import /tmp/temp.crt
. When imported, find the key ID by: gpgsm --list-keys
.
Using the key ID, you can now export the key in p12-format.
gpgsm -o /tmp/$keyid.p12 --export-secret-key-p12 $keyid
openssl pkcs12 -in /tmp/$key.p12 -nodes -nocerts|tail -n +5 > /tmp/$key.key
You only need to do the conversion once and now have your key in
/tmp/$key.key
. This should be secured accordingly, and have a
password set as is offered in the guidance by gpgsm.
The resulting /tmp/$key.key
is usable for decrypting content
encrypted by the public key. To decrypt the data in encrypted.txt
:
IFS=';' read IDENTIFIER ALGORITHM PADDING_MODE ENCRYPTION_BLOBS SIGNATURE < encrypted.txt
for BLOB in ${ENCRYPTION_BLOBS[@]}; do
IFS=':' read ENCRYPTED_KEY_B64 IV TEXTFILE_ENC <<< $BLOB
ENCRYPTED_KEY=`printf $ENCRYPTED_KEY_B64 | base64 -d`
decrypted=false
DECRYPTED_KEY=`echo $ENCRYPTED_KEY_B64 |base64 -d | \
openssl pkeyutl -decrypt -inkey /tmp/$key.key \
-pkeyopt ${PADDING_MODE} 2> /dev/null` && decrypted=true
if [ $decrypted != false ]; then
TEXTFILE_DEC=`printf %s "$TEXTFILE_ENC"|base64 -d|openssl enc \
-$ALGORITHM -d -K "$DECRYPTED_KEY" -iv "$IV" |base64`
break
fi
done
echo $TEXTFILE_DEC
The above format supports encryption to multiple parties. It:
- Reads the PV-format into variables
- Loops through the encryption blobs (one pass if one recipient)
- Decrypts the key with the private key generated from
gpgsm
- Using the IV and decrypted key, decrypts the content, which is
eventually the same as in the previous section's
some-file
- Prints the decrypted content
Conclusion
It is possible to convert PGP keys to use with OpenSSL via gpgsm
.
Since OpenSSL is more widely distributed and installed than GnuPG, it is a method applicable in more environments.
Using OpenSSL instead of GnuPG provides more options, and reduces the complexity of cryptography (since GnuPG has lots of options).
[1] https://stackoverflow.com/questions/39412760/what-is-an-openssl-iv-and-why-do-i-need-a-key-and-an-iv