Tommy Skaug
805a34f937
All checks were successful
Export / Explore-GitHub-Actions (push) Successful in 2m19s
126 lines
4.6 KiB
Markdown
126 lines
4.6 KiB
Markdown
## 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](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
|