As a developer|sysadmin|devops or almost any other kind of IT person you are going to need to share some secret information with your colleagues at some point. Think passwords, DB credentials, AWS credentials… extremely sensitive stuff.
Below are a couple of my favourite ways to do it, ordered from least secure and easiest to use to most secure and “hardest” to wrap your head around and use. They are all UNIX/terminal based since I have literally never seen GUI in my life :)
First off, let’s create a playground directory and a fake secret file:
$ cd ~ $ mkdir secret_sharing/ $ cd secret_sharing/ $ cat << _EOF_ >> ./secret.txt USER: dusan PASS: password123 _EOF_ $ ls secret.txt
- Troubleshooting: GnuPG Non-ASCII User Identifier
- Bonus 1: GnuPG Key Management
- Bonus 2: GnuPG Signatures
- Bonus 3: GnuPG Public Key Verification & Web of Trust
- Pushing Privacy Further - Final Tips
zip is a utility that comes with most popular UNIX derivatives, so there
is most likely no need to even install anything. You can check if you have
it by running:
In order to transfer the secret file securely to another person we can
compress it and encrypt the compressed file with a simple password:
$ zip -e secret.zip secret.txt Enter password: Verify password: adding: secret.txt (stored 0%) $ ls secret.txt secret.zip
Remove the original secret file, since we are going to derive it from the zip package:
$ rm secret.txt
Now let’s reverse the process and unzip/decrypt:
$ unzip secret.zip Archive: secret.zip [secret.zip] secret.txt password: extracting: secret.txt $ ls secret.txt secret.zip
And remove the zip file in order to clean up:
$ rm secret.zip
That’s as simple as it gets.
UX and Security
zip is extremely easy to use and in most cases requires no installation or
There are a couple of problems with this method though. Everyone can see the
names of the files inside the encrypted
zip archive. This is an unnecessary
information leak. Choose your filenames wisely if you wish to use this method.
There are also problems inherent to all symmetric encryption schemes. Using symmetric encryption only works well if the person that you want to share the secret file with is physically near you so you can verbally share the decryption password with them.
You can also use this method to share secret files with people who are not in your physical vicinity - by sending them the password over some different channel than the one that you used to send the encrypted file to them.
Let’s say that you have sent the compressed/encrypted file to the recipient in an Email attachment. There are a couple of ways to pretty securely send the decryption password, here are 2 ideas:
- Call them using some E2E encrypted VoIP application and tell them the password
- Send the password using some E2E encrypted chat application, preferably with message auto-expiry
One of the big security risks with symmetric, password based secret sharing are keyloggers and audio surveillance (smartphones, laptop or hidden mics), so you should keep in mind that this is not the best way to share information that is a matter of life or death.
Security : 5 UX : 10
ccrypt is a nice and easy tool designed for secret sharing.
Go to http://ccrypt.sourceforge.net/ and install
ccrypt on your machine if
you don’t have it already.
To encrypt, use
ccencrypt and enter an encryption password which will be
used for decryption later:
$ ccencrypt ./secret.txt Enter encryption key: Enter encryption key: (repeat) $ ls secret.txt.cpt
Once you encrypt the file, the original is rewritten by the newly created
encrypted file -
In order to decrypt - use
ccdecrypt which will prompt you for the password
that you entered during encryption.
$ ccdecrypt secret.txt.cpt Enter decryption key: $ ls secret.txt
UX and Security
ccrypt is extremely simple and easy to set up and use.
It is more secure than
zip compression because of the fact that it overwrites
the original file on disk, leaving no way to recover it afterwards.
Aside from that - it shares the same security challenges as the previous method since we’re again dealing with passwords.
Security : 6.5 UX : 10
OpenSSL has received some pretty negative publicity in the past because of its shortcomings (see - heartbleed). The programmers who worked on it dispersed which made the OpenSSL development stop. That’s why we will use LibreSSL instead.
As the LibreSSL website states:
LibreSSL is a version of the TLS/crypto stack forked from OpenSSL in 2014, with goals of modernizing the codebase, improving security, and applying best practice development processes.
OpenSSL comes with most UNIX-like derivatives, and some of them have upgraded to LibreSSL.
The LibreSSL GitHub README says:
LibreSSL is API compatible with OpenSSL 1.0.1, but does not yet include all new APIs from OpenSSL 1.0.2 and later. LibreSSL also includes APIs not yet present in OpenSSL. The current common API subset is OpenSSL 1.0.1.
What this means, for the purpose of this article, is that you can use either OpenSSL or LibreSSL. Commands I use below are the same for both.
If neither one of those are present on your system, the installation is pretty straight-forward for both, so pick one (LibreSSL if you can’t decide) and let’s get on with it.
Symmetric key use case
Let’s start with the simplest possible example, using the AES-256 cypher.
$ openssl enc -aes-256-ctr -in secret.txt -out secret.txt.enc enter aes-256-ctr encryption password: Verifying - enter aes-256-ctr encryption password:
We now have an encrypted file that we can send to the recipient.
$ ls secret.txt secret.txt.enc
Notice that the original file is still there. Let’s (naively) delete it:
$ rm secret.txt
-d flag to decrypt and enter the decryption password:
$ openssl enc -aes-256-ctr -d -in secret.txt.enc -out secret.txt enter aes-256-ctr decryption password: $ cat secret.txt USER: dusan PASS: password123
This is as simple as it gets and it’s not much more secure than using
Asymmetric key use case
Generating an asymmetric key pair
Up until now we have been dealing with
symmetric encryption - meaning that
both parties share the same key, which is used both for encryption and
From this point forward, we are going to explore
meaning that there are 2 keys involved - one for encryption (public key) and
the other one for decryption (private key).
The reverse is also common - using the private key to encrypt and the public key to decrypt, but that’s not relevant for our particular use case here.
Let’s start by generating the private/public key pair.
I’ll generate an RSA 4096 bit private key first:
$ openssl genrsa -out privkey.pem 4096
NOTICE: The private key should be kept in a very safe place! Never share it with anyone. It should absolutely always stay only on your machine. I will go one step forward and encrypt the private key itself with a password:
$ openssl rsa -in privkey.pem -aes-256-ctr -out privkey.pem.enc
Delete the unencrypted private key (naively):
$ rm privkey.pem
Now, for the second part, I derive the public key from the previously created and encrypted private key:
$ openssl rsa -in privkey.pem.enc -pubout -out pubkey.pem
If you want someone to send you an encrypted file, you need to give them your public key. Use a “secure” channel transfer it to them.
Now, the other person (who also has LibreSSL or OpenSSL installed) can use your public key to encrypt a file and send it to you:
$ openssl rsautl -encrypt -in secret.txt -pubin -inkey pubkey.pem -out secret.txt.enc
If you’re encrypting and decrypting on the same machine for testing purposes make sure that you (naively) delete the original file:
After you receive the encrypted file, use your encrypted private key to decrypt it:
$ openssl rsautl -decrypt -in secret.txt.enc -out secret.txt -inkey privkey.pem.enc Enter pass phrase for privkey.pem.enc:
Enter the password for decrypting your private key and you’re done!
$ cat secret.txt USER: dusan PASS: password123
Symmetric key use case::
Security : 5.5 UX : 8
Aymmetric key use case::
Security : 9 UX : 7
gpg man page says:
GnuPGis a tool to provide digital encryption and signing services using the OpenPGP standard.
GnuPGfeatures complete key management and all the bells and whistles you would expect from a full OpenPGP implementation.
GnuPG is a tool for secure communication, be it email encryption or
secure file sharing as in the case of this article.
Symmetric key use case
You can use
GnuPG for symmetric key encryption, but I’m not going
to cover it in detail. Here is just a short example:
# Run the encryption command and enter the symmetric key passphrase twice: $ gpg -c secret.txt $ rm secret.txt $ ls secret.txt.gpg # Send the encrypted file to the other computer and decrypt it using the same # passphrase: $ gpg -d -o secret.txt secret.txt.gpg gpg: AES encrypted data gpg: encrypted with 1 passphrase $ cat secret.txt USER: dusan PASS: password123
Now let’s get to the more secure, asymmetric key use case…
Asymmetric key use case
Generating a GnuPG private/public key pair
I advise that you use the
gpg --full-gen-key command for key generation,
since it’s going to offer you the most control. Running this command will
prompt you for a couple of input parameters, first of them being the encryption
algorithm. I will choose
RSA AND RSA:
$ gpg --full-gen-key gpg (GnuPG) 2.2.7; Copyright (C) 2018 Free Software Foundation, Inc. This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Please select what kind of key you want: (1) RSA and RSA (default) (2) DSA and Elgamal (3) DSA (sign only) (4) RSA (sign only) Your selection? 1
Next you need to choose the keysize, I will pick
4096 bits which will make
it opaque to brute-force attacks:
RSA keys may be between 1024 and 4096 bits long. What keysize do you want? (2048) 4096 Requested keysize is 4096 bits
For key validity, I suggest using a definite expiry period. For the sake of an
example I’ll choose
Please specify how long the key should be valid. 0 = key does not expire <n> = key expires in n days <n>w = key expires in n weeks <n>m = key expires in n months <n>y = key expires in n years Key is valid for? (0) 3m Key expires at Mon Jun 18 22:07:00 2019 CEST Is this correct? (y/N) y
Next up, GnuPG is going to ask for some personal info in order to create a user ID to go along with the newly created key pair:
- Real name: You can put in whatever you want, but be sure to use only ASCII characters because otherwise you might introduce bugs.
- Email address: Self explanatory.
- Comment: Whatever you want, I just leave this blank.
GnuPG needs to construct a user ID to identify your key. Real name: Dusan Dimitric Email address: firstname.lastname@example.org Comment: You selected this USER-ID: "Dusan Dimitric <email@example.com>" Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O
Next you’re going to be presented with 2 dialogs where you will choose and confirm a passphrase that will protect your private key:
┌──────────────────────────────────────────────────────┐ │ Please enter the passphrase to │ │ protect your new key │ │ │ │ Passphrase: ***********_____________________________ │ │ │ │ <OK> <Cancel> │ └──────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────┐ │ Please re-enter this passphrase │ │ │ │ Passphrase: ***********_____________________________ │ │ │ │ <OK> <Cancel> │ └──────────────────────────────────────────────────────┘
The GnuPG manual states:
From the perspective of security, the passphrase to unlock the private key is one of the weakest points in GnuPG (and other public-key encryption systems as well) since it is the only protection you have if another individual gets your private key.
So choose a good passphrase! And it’s a passphrase not a password so you can use whitespace to string multiple words together if you want.
Now to finish generating the keys - generate some precious entropy (as instructed) and you’re done:
We need to generate a lot of random bytes. It is a good idea to perform some other action (type on the keyboard, move the mouse, utilize the disks) during the prime generation; this gives the random number generator a better chance to gain enough entropy. gpg: key 08BDFF7DC22C37D1 marked as ultimately trusted gpg: revocation certificate stored as '/home/dusan/.gnupg/openpgp-revocs.d/CF5D0CCA5563381584AD977A08BDFF7DC22C37D1.rev' public and secret key created and signed. pub rsa4096 2019-03-20 [SC] [expires: 2019-06-18] CF5D0CCA5563381584AD977A08BDFF7DC22C37D1 uid Dusan Dimitric <firstname.lastname@example.org> sub rsa4096 2019-03-20 [E] [expires: 2019-06-18]
You can now see your newly generated key pair in the keyring:
$ gpg --list-keys gpg: checking the trustdb gpg: marginals needed: 3 completes needed: 1 trust model: pgp gpg: depth: 0 valid: 1 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 1u gpg: next trustdb check due at 2019-06-18 /home/dusan/.gnupg/pubring.kbx pub rsa4096 2019-03-20 [SC] [expires: 2019-06-18] CF5D0CCA5563381584AD977A08BDFF7DC22C37D1 uid [ultimate] Dusan Dimitric <email@example.com> sub rsa4096 2019-03-20 [E] [expires: 2019-06-18]
Notice that GnuPG takes care of securely storing your private keys so you don’t have to do it manually.
If you want to change some of the key pair parameters just delete the current key and generate a new one. You can delete a key pair with:
gpg --delete-secret-and-public-key firstname.lastname@example.org
In order for someone to securely send you a GPG encrypted file you must send them your public key. In order to send your public key to someone, you must export it first:
$ gpg --output my_pubkey.gpg --export email@example.com $ ls my_pubkey.gpg
The key we exported is in binary format by default. The
--armor flag can be
used to export the public key in an
ASCII-armored format, which makes it easy
to share your public key using email, your webpage or any other textual medium.
Let’s remove the binary public key and create an ASCII-armored one:
$ rm my_pubkey.gpg $ gpg --armor --output my_pubkey.asc --export firstname.lastname@example.org $ ls my_pubkey.asc
I like to use the
.ascextension for ASCII-armored keys, and
.gpgfor plain, binary keys.
In order for someone to securely send you a file with the help of
first have to import your private key and then use it to encrypt the intended
file. You can share your public key with the sender by any means that you want.
Your public key is safe for anyone to see and use.
$ gpg --import my_pubkey.asc
Before using the imported public key, make sure to validate it first. A key is validated by verifying the key’s fingerprint and then signing the key to certify it as a valid key.
$ gpg --fingerprint email@example.com pub rsa4096 2019-03-24 [SC] [expires: 2019-06-22] 0C83 BB42 8D9B C164 9182 F5C6 9F2F 6AA3 E63E D6A0 uid [ultimate] Dusan Dimitric <firstname.lastname@example.org> sub rsa4096 2019-03-24 [E] [expires: 2019-06-22]
The fingerprint here is:
0C83 BB42 8D9B C164 9182 F5C6 9F2F 6AA3 E63E D6A0.
You must verify that the fingerprint is the same by communicating with the public key’s owner. This can be in person, over the phone or any other secure method. If those 20 bytes match, you can go ahead and proceed with encryption using this verified public key.
$ gpg --encrypt --output secret.txt.enc --recipient email@example.com secret.txt $ ls my_pubkey.gpg secret.txt secret.txt.enc
The sender will send the encrypted file to you, using whichever channel they want. When you get the encrypted file, you can decrypt it using:
$ gpg --output secret.txt --decrypt secret.txt.enc
You will be prompted to enter the private key passphrase, and if the correct one is entered you will have your decrypted file:
$ cat secret.txt USER: dusan PASS: password123
Security : 9+ UX : 7
Troubleshooting: GnuPG Non-ASCII User Identifier:
Let’s say you create a GnuPG key pair and use non-ASCII characters in the
field (I used
Dušan Dimitrić, with
ć obviously being non-ASCII).
Doing that will cause the remove keys command not to work, along with other
$ gpg --list-keys gpg: checking the trustdb gpg: marginals needed: 3 completes needed: 1 trust model: pgp gpg: depth: 0 valid: 1 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 1u gpg: next trustdb check due at 2019-06-19 /home/dusan/.gnupg/pubring.kbx -------------------------------------- pub rsa4096 2019-03-21 [SC] [expires: 2019-06-19] C5875F42BB3439D2505E032D1E93F87508BC08D0 uid [ultimate] Dušan Dimitri\xc4\x20<firstname.lastname@example.org> sub rsa4096 2019-03-21 [E] [expires: 2019-06-19]
Trying to remove the key pair will fail, no matter if you use the
$ gpg --delete-secret-and-public-key Dušan Dimitri\xc4\x20 gpg (GnuPG) 2.2.7; Copyright (C) 2018 Free Software Foundation, Inc. This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. sec rsa4096/1E93F87508BC08D0 2019-03-21 Dušan Dimitri\xc4\x20<email@example.com> Delete this key from the keyring? (y/N) y This is a secret key! - really delete? (y/N) y gpg: deleting secret key failed: A locale function failed gpg: deleting secret subkey failed: A locale function failed gpg: Dušan: delete key failed: A locale function failed
Easiest way to solve this is to remove all surface level files from your
cd ~/.gnupg rm *
Now everything regarding keys and keyrings is deleted and
re-create the missing files next time you run it.
Lesson learned: Don’t use non-ASCII characters for any of your GnuPG key identifiers.
Bonus 1: GnuPG Key Management
The most cumbersome part of using GnuPG so far is the public key distribution.
It simply does not scale well. The straight-forward solution to sharing your
public key to everyone interested would be to host it on one of the GnuPG
keys.gnupg.net because of it seems popular enough and has a convenient
web interface: http://keys.gnupg.net
At the time of writing this,
http://keys.gnupg.netseems like one of the few keyservers that actually work. If someone knows a reliable keyserver shoot me an email.
Consult the manual for more information regarding key distribution.
Bonus 2: GnuPG Signatures
In order to make sure that an encrypted file is coming from the sender that you are expecting it from, a digital signature can be employed.
The sender will digitally sign the file with their private key and you, the receiver, will verify that signature using the sender’s public key.
$ gpg --output secret.txt.sig --detach-sig secret.txt.enc
$ gpg --verify secret.txt.sig secret.txt.enc gpg: Signature made Thu Apr 4 19:33:31 2019 CEST gpg: using RSA key 0C83BB428D9BC1649182F5C69F2F6AA3E63ED6A0 gpg: Good signature from "Dusan Dimitric <firstname.lastname@example.org>" [ultimate]
If the verification passes - you can be sure that the file is sent by the owner of the public key that you used for the verification. Either that, or their private key has been compromised.
You can also use signatures for regular, non-encrypted files to ensure that they haven’t been tampered with.
Bonus 3: GnuPG Public Key Verification & Web of Trust
To prevent man-in-the-middle attacks, it would be wise to develop your
trust - a network of people whose public keys you can use with a certain
degree of trust.
web of trust is formed by people signing, and therefore validating each
other’s public keys, making them more trustworthy and tamper-resistant.
The process goes like this:
- Check the fingerprint of the other person’s public key
- Sign the public key if the fingerprint is correct
- Check to see if your newly added signature is there
- Send them the signed public key so they can import it in their keychain and upload to a keyserver
- Or - send the signed public key to a public keyserver and the owner of the public key can pull it down along with all the new signatures
You can organize key signing within your company, or, if you are using GnuPG
privately you can develop this
web of trust with your friends, people you
work with and generally people you trust.
If you want to learn more about signing and verification make sure to consult the GnuPG manual.
Pushing Privacy Further - Final Tips
I will leave you with some of my favorite ways to increase security to the MAX!
Tip #1 - Encrypt Your Storage Medium
Encrypting your storage partition will add another layer of protection. In the case that someone grabs a hold of your hardware they will have a difficult time accessing any of your files including your private keys.
Tip #2 - Use Secure Channels of Communication
For exchanging the encrypted files and encryption/decryption passwords make sure to use a secure service - something that has E2E encryption… or at least it markets itself that way.
Here are some of the unsecure channels:
- Cellular calls
- Proprietary services
Tip #3 - Expire Encrypted Files
Upload the encrypted files somewhere where you can expire them - have the service delete the files after a short period of time.
Tip #4 - Tunnel traffic through VPN
This could prevent any eavesdroppers, including your ISP. Choosing a VPN that you can trust is not an easy job though.
Tip #5 - Use Layers of Encryption
Combine encryption tools to enforce practically impenetrable communication. By combining multiple tools you mitigate the risk of one of them being compromised or zero-day exploited.
Here are some ideas:
- Encrypt the file using ccrypt - with an encryption password
- Encrypt the output of the previous step with LibreSSL or GnuPG, using the recipients public key
- Safely remove the output from step #1
- Send the encrypted file using a “secure” communication channel - channel 1
- Send encryption password using a “secure” channel 2
- Get the file via channel 1
- Get the encryption password via channel 2
- Decrypt using your LibreSSL or GnuPG private key
- Decrypt using ccrypt and encryption password
- Encrypt the secret file using LibreSSL AES-256 and a password
- Encrypt a file containing the password with GnuPG using the recipients public key
- Send the encrypted password file and the encrypted secret file to the recipient via any 2 “secure” channels
- Retreive the password and secret files
- Decrypt the password file using your GnuPG private key
- Decrypt the secret file using LibreSSL AES-256 and the decrypted password
Etc. etc… you can combine any of the tools however you want.
If you wish to add some more tips or have any comments regarding this post or any other - shoot me an email at: email@example.com (GPG encrypted, of course :) ).