Flat File Encryption with OpenSSL and GPG

This entire script can be worked into an email system for automated transfers. To do this on Oracle Linux 7 with the default Postfix SMTP server, ensure that the following two lines are set in /etc/postfix/main.cf:


inet_interfaces = $myhostname, localhost
...
default_privs = nobody

Here I will place a copy of the SSH private RSA host key in the /etc/postfix directory, set the configuration and permissions, open firewall port 25, then generate a public key as outlined below:


cd /etc/postfix
cp /etc/ssh/ssh_host_rsa_key .prv.key
chown nobody:nobody .prv.key
chmod 400 .prv.key
chcon system_u:object_r:postfix_etc_t:s0 .prv.key
iptables -I INPUT -p tcp --dport 25 --syn -j ACCEPT
openssl rsa -in .prv.key -pubout -out .pub.key

Notice that I'm using the nobody user with the system host key. If you are not comfortable with this security, note that the key file is in the ssh_keys group, and create a separate user for postfix to handle the keypair.

Next, place a copy of decrypter in /etc/postfix. The script must be modified to do the following: 1) skip the email header, 2) remove the password clause from the host key processing, 3) set /tmp as the unpack directory and 4) define new locations for the keypair. Below, sed is used with in-place editing to accomplish this:


sed -i.old '/^ while read Z/s:^:sed '"'"'1,/^$/d'"'"' |:
        s/^[ ]*-passin "[^"]*"//
        /^ DGST=/s:#.*$:cd /tmp:
        /^PVK=/c \
PVK=/etc/postfix/.prv.key; PBK=/etc/postfix/.pub.key' decrypter

With those changes in place, I create an email alias that will trigger the decrypter:


echo 'crypter: "| /etc/postfix/decrypter >> /tmp/cryp.log 2>&1"' \
        >> /etc/aliases
newaliases
chcon system_u:object_r:postfix_local_exec_t:s0 decrypter
postfix reload
systemctl restart postfix.service

Now, pipe the encrypter output to the mail client:


cd /etc
encrypter resolv.conf hostname | mail crypter@localhost

The files sent into the mail client should appear in /tmp. Move the public key to a remote server, and automatic encrypted file transfer over SMTP is established.

It is also possible to work RSA encryption in reverse, decrypting with the public key. This is useful in establishing authenticity of data—for example, to encrypt a small amount of clear text (bounded by RSA length limitations) with the private key:


echo 'I have control of the private key.' |
  openssl rsautl -sign -inkey ~/.prv.key -passin "file:$HOME/.pas" |
  openssl base64 > blob

The blob file then can be posted in a public medium (website, file server and so on), and holders of the public key can successfully decrypt the message like so:


openssl base64 -d < blob |
        openssl rsautl -inkey ~/.pub.key -pubin

In doing so, users verify that the private key was involved in the creation of the message, lending some authenticity to the data that has been transferred. The public key is not assumed to be secret, so this establishes data authenticity, not data privacy.

Rather than arbitrary text, you can pipe in the text from an SHA-256 signature program call, and thus "sign" a larger file in a way that proves authenticity:


openssl dgst -sha256 crypter.sh |
  openssl rsautl -sign -inkey ~/.prv.key -passin "file:$HOME/.pas" |
  openssl base64 > csign

You decrypt this text in exactly the same manner as you did before, producing an SHA-256 clear-text digest that you can verify independently. However, OpenSSL can summarize in one step the signed SHA-256 checksum (note that full x.509 keys also can be manipulated to sign a digest):


openssl dgst -sha256 -sign ~/.prv.key \
        -out crypter.sha256 crypter.sh

If the two files above are placed accessibly, holders of the public key can verify that the files have not been altered:


openssl dgst -sha256 -verify ~/.pub.key \
        -signature crypter.sha256 crypter.sh

OpenSSL should output "Verified OK" when the files are intact. The capability of using an encrypted SHA-256 digest to verify a file securely is far beyond the features of the standard sha256sum utility and demonstrates authenticity unambiguously.

Introduction to GPG

GNU Privacy Guard has much more comprehensive tools for the management of keypairs and peer identities. This includes databases for storing the various types of keys, tools for revocation of keys and mechanisms for establishing key reputation in a "web of trust".

Oracle Linux 7 bundles GPG 2.0.22, which uses the 128-bit CAST5 symmetric cipher by default (newer versions have switched to AES128). Here, I will conform to the previous NIST guidelines for a 2868-bit asymmetric keypair of equal strength (note that the GPG documentation does warn that "Moving past RSA-2048 means you lose the ability to migrate your certificate to a smartcard, or to effectively use it on some mobile devices, or to interoperate with other OpenPGP applications that don't handle large keys gracefully."):


$ gpg --gen-key

gpg (GnuPG) 2.0.22; Copyright (C) 2013 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.

gpg: directory `/home/ol7_user/.gnupg' created
gpg: new configuration file `/home/ol7_user/.gnupg/gpg.conf' created
gpg: WARNING: options in `/home/ol7_user/.gnupg/gpg.conf' are not yet
        active during this run
gpg: keyring `/home/ol7_user/.gnupg/secring.gpg' created
gpg: keyring `/home/ol7_user/.gnupg/pubring.gpg' created
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
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048) 2868
Requested keysize is 2868 bits
rounded up to 2880 bits
Please specify how long the key should be valid.
         0 = key does not expire
        = key expires in n days
      w = key expires in n weeks
      m = key expires in n months
      y = key expires in n years
Key is valid for? (0) 5y
Key expires at Sat 10 Jul 2021 08:40:19 PM CDT
Is this correct? (y/N) y

GnuPG needs to construct a user ID to identify your key.

Real name: Oracle Linux
Email address: ol7_user@localhost
Comment: Test Key
You selected this USER-ID:
    "Oracle Linux (Test Key) <ol7_user@localhost>

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O
You need a Passphrase to protect your secret key.

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: /home/ol7_user/.gnupg/trustdb.gpg: trustdb created
gpg: key 6F862596 marked as ultimately trusted
public and secret key created and signed.

gpg: checking the trustdb
gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model
gpg: depth: 0  valid:   1  signed:   0  trust: 0-, 0q, 0n, 0m, 0f, 1u
gpg: next trustdb check due at 2021-07-11
pub   2880R/6F862596 2016-07-12 [expires: 2021-07-11]
      Key fingerprint = F423 3B2C ACE1 AD0E 95C3  4769 679D 66ED 6F86 2596
uid                  Oracle Linux (Test Key)
sub   2880R/FF79FC31 2016-07-12 [expires: 2021-07-11]

Once the (rounded-up) 2880-bit private key has been created, a command is needed to generate a public key that can be shared with others:


$ gpg --export -a

-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v2.0.22 (GNU/Linux)

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
=gBp9
-----END PGP PUBLIC KEY BLOCK-----

______________________

Charles Fisher has an electrical engineering degree from the University of Iowa and works as a systems and database administrator for a Fortune 500 mining and manufacturing corporation.