Skip to content

Instantly share code, notes, and snippets.

@kennwhite
Last active January 16, 2024 15:47
Show Gist options
  • Save kennwhite/9918739 to your computer and use it in GitHub Desktop.
Save kennwhite/9918739 to your computer and use it in GitHub Desktop.
OpenSSL command line recipe for multi-public key file encryption. Any single private key paired to one of the public keys can decrypt the file.
#!/usr/bin/env bash
#
# Example of multiple key AES encryption for text files using the openssl v. 0.9.8+ command line utility
# Uses n public certs as key for MIME PKCS envelope, any individual private key can decrypt.
#
# If standard RSA ssh keys exist, these can be converted to public certs as well (and ssh keys can decrypt)
#
# To sign (and verify) the encrypted file, one of the private keys is required, see:
# http://www.openssl.org/docs/apps/smime.html#EXAMPLES for openssl smime examples
# or http://www.openssl.org/docs/apps/cms.html#EXAMPLES for cms utility (OpenSSL v. 1.0+)
#
# Author: Kenneth White
# Released under the terms of the MIT license: http://en.wikipedia.org/wiki/MIT_License
# Basically: Feel free to use, just give credit please
#
# Alice runs this locally, then publishes/distributes her self-signed public cert (key stays private)
# Optionally, if local private key passphrase is required remove: -nodes
openssl req -x509 -newkey rsa:4096 -days 3650 -nodes -subj "/C=US/ST=*/L=*/O=*/OU=*/CN=Alice/" -keyout alice.key -out alice.pub
# Ditto for Bob...
openssl req -x509 -newkey rsa:4096 -days 3650 -nodes -subj "/C=US/ST=*/L=*/O=*/OU=*/CN=Bob/" -keyout bob.key -out bob.pub
# Ditto for Frank...
openssl req -x509 -newkey rsa:4096 -days 3650 -nodes -subj "/C=US/ST=*/L=*/O=*/OU=*/CN=Frank/" -keyout frank.key -out frank.pub
# If you wanna get crazy, Carol can use an existing SSH private key to generate a public cert (and decrypt w/ her ssh key)
openssl req -x509 -new -key ~/.ssh/id_rsa -days 3650 -nodes -subj "/C=US/ST=*/L=*/O=*/OU=*/CN=Carol/" -out carol.pub
# Central secrets repo
echo 'All our secretz are belong to us' > secrets.txt
echo 'Germans *love* David Hasselhoff!' >> secrets.txt
cat secrets.txt
# Encrypt it with multiple public certs (PKCS PEM base64 text format) in aes256 cbc mode
#
openssl smime -encrypt -aes256 -in secrets.txt -out secrets.txt.enc -outform PEM bob.pub alice.pub frank.pub carol.pub
cat secrets.txt.enc
# secrets.txt.enc file is safe to distribute
# Bob, Alice, Frank or Carol can now decrypt it with their private keys (SSL or SSH)
# Optionally: -out secrets.decrypted.txt
#
openssl smime -decrypt -in secrets.txt.enc -inform PEM -inkey alice.key
@kennwhite
Copy link
Author

@burner I don't have the energy to try to wrangle the openssl command line tool to cough up the right incantation, but in 2021 you probably want something like age (https://github.com/FiloSottile/age). Might also take a look at magic wormhole (https://magic-wormhole.readthedocs.io/en/latest/welcome.html) for a different (painless) way to securely send a file to recipients. And if you're building from API as I understood your and the parent comment, libsodium Box & Secretbox would almost certainly be a better option for building blocks than openssl.

@burner
Copy link

burner commented Mar 22, 2023

for reference the dlang lib can be found here https://github.com/symmetryinvestments/smimeasym

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment