[Crypto] Safe backups (or ransomware) using RSA/PGP/GnuPG/OpenSSL

As you may know, RSA itself isn't used for encryption/decryption, because it's too slow for that. (However, this is possible.)

But rather RSA is used to generate a small key that is used with AES (or another symmetric cryptoalgo).

Here is a typical scheme. Alice wants to encrypt a message to Bob. She generates a random session key. A message is then encrypted with using the session key with AES. Session key is then encrypted by RSA and also passed to Bob. Alice destroys session key.

Bob receives encrypted session key and encrypted message. He can decrypt session key, since he has his private/secret key. He then decrypts the data with AES.

Alice can't decrypt what she sent -- and this is important. How this could be? Because the session key was random and it was encrypted for Bob. And then destroyed. Alice don't possess Bob's private/secret RSA key, so she can't decrypt what she encrypted.

And this is a common mistake by PGP/GnuPG users. When they encrypt a file or message to someone else, they can't decrypt it back. Ouch! What to do? The correct answer -- to encrypt for recepient and to himself. Alice would encrypt to her public key and to Bob's public key.

Let's see what GnuPG can say.

I have two keys -- 'User 1' and 'User 2'. I encrypted small text file for User 2:

% gpg --encrypt test.txt

gpg: WARNING: unsafe permissions on homedir '/home/i/tmp/1/user1'
You did not specify a user ID. (you may use "-r")

Current recipients:

Enter the user ID.  End with an empty line: user 2
gpg: C5E1BC95AEDE79CB: There is no assurance this key belongs to the named user

sub  rsa3072/C5E1BC95AEDE79CB 2022-06-17 User 2
 Primary key fingerprint: A9DF 9694 91B2 578E 381B  5AD1 F86F BB9A 3297 C309
      Subkey fingerprint: 4F79 C3B5 309A BEF2 0862  1F1D C5E1 BC95 AEDE 79CB

It is NOT certain that the key belongs to the person named
in the user ID.  If you *really* know what you are doing,
you may answer the next question with yes.

Use this key anyway? (y/N) y

Current recipients:
rsa3072/C5E1BC95AEDE79CB 2022-06-17 "User 2"

Enter the user ID.  End with an empty line:

You see, GnuPG asking for several recipients.

OK, if I encrypted for 'User 2' only, 'User 1' can't get data back!

% gpg test.txt.gpg

gpg: WARNING: unsafe permissions on homedir '/home/i/tmp/1/user1'
gpg: WARNING: no command supplied.  Trying to guess what you mean ...
gpg: encrypted with 3072-bit RSA key, ID C5E1BC95AEDE79CB, created 2022-06-17
      "User 2"
gpg: decryption failed: No secret key

You see, it says, it's encrypted for 'User 2' only. 'User 2' can decrypt it all and show the session key:

% gpg -v --show-session-key test.txt.gpg

gpg: WARNING: unsafe permissions on homedir '/home/i/tmp/1/user2'
gpg: WARNING: no command supplied.  Trying to guess what you mean ...
gpg: public key is C5E1BC95AEDE79CB
gpg: no running gpg-agent - starting '/usr/bin/gpg-agent'
gpg: waiting for the agent to come up ... (5s)
gpg: connection to agent established
gpg: using subkey C5E1BC95AEDE79CB instead of primary key F86FBB9A3297C309
gpg: pinentry launched (212808 curses 1.1.0 /dev/pts/16 screen :0)
gpg: using subkey C5E1BC95AEDE79CB instead of primary key F86FBB9A3297C309
gpg: encrypted with 3072-bit RSA key, ID C5E1BC95AEDE79CB, created 2022-06-17
      "User 2"
gpg: AES256 encrypted data
gpg: session key: '9:4170F192E14B5140CC74FF80DD85AF51631943A6590E95E98834BEDCC4001FD1'
gpg: original file name='test.txt'
...

BTW, session key will different after each encryption. You can see in GnuPG source code, how it is generated. This may be important, if one session key was compromised. That shouldn't help attacker to decrypt all other files/messages. ( Forward/backward secrecy )

OK, what if a message encrypted to both 'User 1' and 'User 2'? It can be decrypted by both.

gpg: WARNING: unsafe permissions on homedir '/home/i/tmp/user1'
gpg: WARNING: no command supplied.  Trying to guess what you mean ...
gpg: public key is C5E1BC95AEDE79CB
gpg: public key is 7B458B03D5CD8EAA
gpg: using subkey 7B458B03D5CD8EAA instead of primary key B73C3A671A75E68D
gpg: using subkey C5E1BC95AEDE79CB instead of primary key F86FBB9A3297C309
gpg: encrypted with 3072-bit RSA key, ID C5E1BC95AEDE79CB, created 2022-06-17
      "User 2"
gpg: using subkey 7B458B03D5CD8EAA instead of primary key B73C3A671A75E68D
gpg: encrypted with 3072-bit RSA key, ID 7B458B03D5CD8EAA, created 2022-06-17
      "User 1"
gpg: AES256 encrypted data
gpg: session key: '9:05D37CA50E5525BE3150BB430C0698B356BF9FA2A30E804C22AF554640E4BABB'
gpg: original file name='test.txt'

Safe backup

Now imagine your server generates some data or log files that is better to kept secret. This is the solution. PGP/GnuPG running on your server can encrypt that data using a public key. While the private/secret key is kept somewhere off-site.

The data is destroyed after encryption. The data is then can be recovered only using your private/secret key. No other (known) ways to do so (unless RSA modulus can be factored, AES can be broken, etc).

And even more.

Encrypted backups can be transfered to a remote backup server. And again -- backup server will not contain any useful data to decrypt this stuff. MITM attack between backup server and everything else wouldn't give attacker anything.

But remember to keep your private/secret key safe and don't lost it. Interesting thing is that you need to access your private/secret key only twice -- during generation and during decryption/recovery (in case of emergency, maybe). Meanwhile, your server can use your public key for years.

So true:

The Danger of Backing Up Data

A common denominator in most of us is that when we want to do a backup, we want to make it really easy for ourselves. If there’s enough space available, we back up everything. And then we forget about it. The number of backups lying around becomes enormous. People just let them build up, they gather, and nobody ever thinks about removing them until the server or backup device runs out of space.

“Often,” Robert comments, “the backup contains critical, essential, amazing information which no one gives any thought to because it’s the backup. They treat it with really low security.” (During my own younger hacking days, I noticed the same thing. A company would go to extreme lengths to protect certain data, but the backups of the same data were treated as unimportant. When I was a fugitive, I worked for a law firm that would leave their backup tapes in a box outside the secured computer room entrance to be picked up by an off-site storage company. Anyone could have stolen the tapes with little danger of being caught.) On BACKUP2, he noticed a shared area where someone had backed up all his goodies — everything. He imagined how it had happened, and the story will have a familiar ring to many:

This guy had been in a hurry one day. He thought, “I need to back this up,” so he’d done it. And, after being backed up like maybe three or four months ago, it was still sitting there.

( Kevin D. Mitnick, William L. Simon - The Art of Intrusion: The Real Stories Behind the Exploits of Hackers, Intruders and Deceivers-Wiley (2005) )

GnuPG hater? OpenSSL is an option

You can use OpenSSL.

We are going to repeat all the steps manually.

Generate RSA key:

openssl genrsa -out rsaprivkey.pem 2048
# extract public key from private/secret key:
openssl rsa -in rsaprivkey.pem -outform PEM -pubout -out public.pem

Encryption side. Only public.pem is here allowed:

# message:
echo Hello, world! > test.txt
# generate session key:
openssl rand -out rnd.bin 32
# encrypt plain text with random session key:
openssl aes-256-cbc -in test.txt -out test.txt.enc -pass file:rnd.bin
# encrypt session key for recepient:
openssl rsautl -encrypt -oaep -pubin -inkey public.pem -in rnd.bin -out rnd.bin.enc
# delete random key and plain text:
rm rnd.bin test.txt

Of course, the session key length must coincide with AES key length or any other symmetric cryptoalgo. And a good PRNG is very important here.

These two files are passed to recepient: rnd.bin.enc and test.txt.enc

Decryption side:

# decrypt session key using secret/private key:
openssl rsautl -decrypt -oaep -inkey rsaprivkey.pem -in rnd.bin.enc -out rnd.bin
# decrypt the message using decrypted session key:
openssl aes-256-cbc -d -in test.txt.enc -out test.txt -pass file:rnd.bin
# dump message:
cat test.txt

Ransomware

Alas! This very same method is used by ransomware creators with the same success.

So please use (snapshot) backups of your data (pun intended).

(the post first published at 20220618.)


List of my other blog posts.

Yes, I know about these lousy Disqus ads. Please use adblocker. I would consider to subscribe to 'pro' version of Disqus if the signal/noise ratio in comments would be good enough.