## 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 ! > /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](https://contact.252.no): ``` 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: 1. Create an initialization vector [1] and an encryption key 2. Encrypt the one-time key to test.pem (our exported PGP-key) 3. Encrypt `some-file` using the key and IV using 256 bits AES in CFB-mode 4. 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: 1. Reads the PV-format into variables 2. Loops through the encryption blobs (one pass if one recipient) 3. Decrypts the key with the private key generated from `gpgsm` 4. Using the IV and decrypted key, decrypts the content, which is eventually the same as in the previous section's `some-file` 5. 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 [2] https://superuser.com/a/1414277