Bumped by Community user
    Bumped by Community user
    Bumped by Community user
    Tweeted twitter.com/StackSecurity/status/663556093197615104
2 Following https://martin.kleppmann.com/2013/05/24/improving-security-of-ssh-private-keys.html, I switched to PKCS#8 for storing the RSA keys. Ctulhu's comment is absolutely valid; therefore I removed the salt wherever it occurred.
source | link

EDIT: switched to PKCS#8 for the keys, being probably more resistant to brute force attacks

openssl genrsagenpkey -aes256aes-256-cbc -algorithm RSA -pkeyopt 'rsa_keygen_bits:8192' -out private.key 8192
openssl rsapkey -in private.key -out public.key -pubout

EDIT: removed salt as per Ctulhu's comment

key=$(openssl rand -hex 32)
iv=$(openssl rand -hex 16)
salt=$(openssl rand -hex 64)
hmacpw=$(openssl rand -base64 48)

EDIT: removed salt as per Ctulhu's comment

data-generator | xz -zc | openssl enc -e -aes-256-ctr -K $key -iv $iv -S $salt -out message.enc

EDIT: removed salt as per Ctulhu's comment

hmac=$(openssl dgst -sha512 -hmac $hmacpw -hex message.enc | sed 's/^.*=[[:space:]]//g')
echo "${key}:${iv}:${salt}:${hmacpw}:${hmac}" | openssl rsautl -inkey public.key -pubin -encrypt -out message.key

And here it becomes obvious why the RSA key had to be that large: hex digits in shell strings are counted as one byte each, not half a byte. Therefore, the size of the key string sums up to (2x32 + 2x16 + 2x64 + 64 + 128 + 5) = 421293 Bytes = 33682344 Bits.

openssl genrsa -aes256 -out private.key 8192
openssl rsa -in private.key -out public.key -pubout
key=$(openssl rand -hex 32)
iv=$(openssl rand -hex 16)
salt=$(openssl rand -hex 64)
hmacpw=$(openssl rand -base64 48)
data-generator | xz -zc | openssl enc -e -aes-256-ctr -K $key -iv $iv -S $salt -out message.enc
hmac=$(openssl dgst -sha512 -hmac $hmacpw -hex message.enc | sed 's/^.*=[[:space:]]//g')
echo "${key}:${iv}:${salt}:${hmacpw}:${hmac}" | openssl rsautl -inkey public.key -pubin -encrypt -out message.key

And here it becomes obvious why the RSA key had to be that large: hex digits in shell strings are counted as one byte each, not half a byte. Therefore, the size of the key string sums up to (2x32 + 2x16 + 2x64 + 64 + 128 + 5) = 421 Bytes = 3368 Bits.

EDIT: switched to PKCS#8 for the keys, being probably more resistant to brute force attacks

openssl genpkey -aes-256-cbc -algorithm RSA -pkeyopt 'rsa_keygen_bits:8192' -out private.key
openssl pkey -in private.key -out public.key -pubout

EDIT: removed salt as per Ctulhu's comment

key=$(openssl rand -hex 32)
iv=$(openssl rand -hex 16)
hmacpw=$(openssl rand -base64 48)

EDIT: removed salt as per Ctulhu's comment

data-generator | xz -zc | openssl enc -e -aes-256-ctr -K $key -iv $iv -out message.enc

EDIT: removed salt as per Ctulhu's comment

hmac=$(openssl dgst -sha512 -hmac $hmacpw -hex message.enc | sed 's/^.*=[[:space:]]//g')
echo "${key}:${iv}:${hmacpw}:${hmac}" | openssl rsautl -inkey public.key -pubin -encrypt -out message.key

And here it becomes obvious why the RSA key had to be that large: hex digits in shell strings are counted as one byte each, not half a byte. Therefore, the size of the key string sums up to (2x32 + 2x16 + 64 + 128 + 5) = 293 Bytes = 2344 Bits.

1
source | link

Secure backup encryption with OpenSSL

I know, the general advice is "keep your hands off crypto stuff". And the standard way to encrypt backup data securely would be using GnuPG. However, for a rather academic exercise, I would like to think through a protocol that would work just with OpenSSL's standard tools (i. e. dgst, enc, rsautl & Co) invoked from a POSIX shell.

The scenario includes a more or less trusted system on and from which backups are created - this could e. g. be a mail or file server. Then there's a storage which is not 100% to be trusted (e. g. a cloud storage, or a backup server not entirely under my control). So the purpose of the crypto is to protect confidentiality and integrity of the data while stored on the untrusted storage. This protection should also work in case the trusted system gets compromised - at least for data stored before the trusted system was compromised.

So here's a kind of protocol that should fulfill the aforementioned criteria:

Step 1: RSA Key Pair

This step only needs to be performed once. An RSA key pair is needed. This key pair shall not be created on the "trusted" system, but instead on a really trusted box (e. g. a trusted work station or wherever you'd trust to keep your GPG key ring). Since the private key is only needed for recovery, it shall never enter the realms of either the trusted system or the untrusted storage. Key size needs to be 4096 bits or above (we come to that later). OpenSSL usually offers key generation and separation by those commands:

openssl genrsa -aes256 -out private.key 8192
openssl rsa -in private.key -out public.key -pubout

Step 2: Generate Session Secrets

For each encryption process, dedicated secrets (key, initialisation vector and salt) shall be generated:

key=$(openssl rand -hex 32)
iv=$(openssl rand -hex 16)
salt=$(openssl rand -hex 64)
hmacpw=$(openssl rand -base64 48)

Please note: I am aware that this will have the secrets unprotected in the trusted machine's memory. However, if an attacker has access to the machine in a way he can skim the backup process' memory, he probably already has access to the data to be protected by these secrets.

Step 3: Compress and Encrypt

Data shall be compressed before encryption. Compression is required anyway, so I consider it a good idea to do it before encrypting the data:

data-generator | xz -zc | openssl enc -e -aes-256-ctr -K $key -iv $iv -S $salt -out message.enc

Step 4: Generate HMAC and Pack up Keys

The last step would be to generate a HMAC of the just encrypted data, and pack it up together with the session secrets in an RSA encrypted file, using the public key for encryption:

hmac=$(openssl dgst -sha512 -hmac $hmacpw -hex message.enc | sed 's/^.*=[[:space:]]//g')
echo "${key}:${iv}:${salt}:${hmacpw}:${hmac}" | openssl rsautl -inkey public.key -pubin -encrypt -out message.key

And here it becomes obvious why the RSA key had to be that large: hex digits in shell strings are counted as one byte each, not half a byte. Therefore, the size of the key string sums up to (2x32 + 2x16 + 2x64 + 64 + 128 + 5) = 421 Bytes = 3368 Bits.

Again, I'm aware that exposing secrets on a command line is generally a bad idea, but given the circumstances, I do not see how this would compromise confidentiality or integrity of data which are available in plain text on said system, where an attacker could much easier compromise their privacy or integrity. However, if I would really go and implement this, I'd rather use named pipes to avoid having the secrets popping up in the process list.

Now my questions:

  1. What did I miss? Do you see any flaw or potential attack vector I haven't noticed yet?
  2. Would it be more secure to create a signature with openssl dgst -sha512 -sign private.key -out message.sig message.enc, given that this would require the private key to reside on the more or less trusted system?