[Crypto] Using HTTPS certificates to sign/encrypt arbitrary data

You may have heard that it's possible to sign/verify files using SSH keys.

HTTPS certificates (included those obtained from Let's Encrypt) can be used for that as well.

Signing

This is a real data on my https://yurichev.com webserver.

root@vps7:/etc/letsencrypt/live/yurichev.com# ls -la
...
lrwxrwxrwx  1 root root   42 Apr  4 23:05 cert.pem -> ../../archive/yurichev.com-0001/cert22.pem
lrwxrwxrwx  1 root root   43 Apr  4 23:05 chain.pem -> ../../archive/yurichev.com-0001/chain22.pem
lrwxrwxrwx  1 root root   47 Apr  4 23:05 fullchain.pem -> ../../archive/yurichev.com-0001/fullchain22.pem
lrwxrwxrwx  1 root root   45 Apr  4 23:05 privkey.pem -> ../../archive/yurichev.com-0001/privkey22.pem
...

Here I create a message:

# cat msg.txt
Hello world. Yes, this is me, D.Y.

Here I use my private key for my webserver (created by certbot):

# openssl dgst -sha256 -sign privkey.pem -out msg.txt.sig msg.txt

The file is binary, but you can convert it to base64 using openssl:

# openssl base64 -in msg.txt.sig -out msg.txt.sig.asc

# cat msg.txt.sig.asc
k8XS4R3Urpa3G8dqlFCKkPsg76LpwQ7F+jRogLy0dkyJeChbgn+erAmqZLj4SQ1I
tNYPjeJjIRwgCWHTPGowvCz2kNgofRkSuSvvH3N+ju1tv7O3GJAQaJiXyvsZRb9V
PVZnfb/fz5m3mC3P67QO0ePc22miVbP5LuMceeSj5Sfl/JDwO/JdYvSCs1PkSms2
i22HoYOSo2s//Kb5k+ggJlioo82K5j9a/QCCTOix5VyEtBiS7jGMRap1uMd7ia2b
jgRDf6M2LytZJFqhfcM4a8VEAPTI2i82+JqsBnet3QvCjj9FlwaQqbgGW5UHptxJ
+em2Vy2FNW2GwmeT9PiAPw==

I publish msg.txt and msg.txt.sig.asc.

Now anyone can download my public key from my webserver:

$ openssl s_client -connect yurichev.com:443 -showcerts  1.pem

$ openssl x509 -pubkey -noout -in 1.pem > pubkey.pem

(sed is used here to get only certificate... There are two of them, actually, but OK.)

Convert base64-encoded signature back to binary form:

$ openssl base64 -d -in msg.txt.sig.asc -out msg.txt.sig

Verify it all:

$ openssl dgst -keyform pem -verify pubkey.pem -signature msg.txt.sig msg.txt
Verified OK

The second half of this recipe can be done by anyone -- my webserver's public key is easily obtainable.

The only problem to keep in mind is that Let's Encrypt certs are short-lived (3 months). Also, my private key may be stolen.

Encryption

And now something SSH can't do. (Yet?)

Given the fact you can have my public key so easy, you can encrypt a message for me.

% cat to_dennis.txt
Hi, Dennis. The Secret Meetup is today, at The Venue 123. 1800 UTC.

% openssl pkeyutl -in to_dennis.txt -out to_dennis.enc -pubin -inkey pubkey.pem -encrypt

The resulting to_dennis.enc is in binary form, you can convert it to base64 or not. Send me that file somehow.

Now I can decrypt it using my private key of my webserver:

root@vps7:/etc/letsencrypt/live/yurichev.com# openssl pkeyutl -in to_dennis.enc -out to_dennis.txt -inkey privkey.pem -decrypt

root@vps7:/etc/letsencrypt/live/yurichev.com# cat to_dennis.txt
Hi, Dennis. The Secret Meetup is today, at The Venue 123. 1800 UTC.

Anyone can encrypt a message to me, so easilty. I didn't even distribute my public key. It's only on my webserver. And only I can decrypt the message -- well, if my private key wasn't stolen.

This may be handy if you need to say something to someone urgently, in secure form. And you have no time to setup PGP or another secured messenger. And/or you send cold/unsolicited email, out of the blue. This is possible if your recipient has running HTTPS server, nothing else.

You can even publish this encrypted message on your website, soc.network profile, etc. Only recipient can decrypt it. (Well, again, if his/her private key will not be stolen in some (distant) future.)

IOW, anyone with HTTPS server can receive encrypted messages from strangers. Without any additional key setup/exchange.

UPD: 20240526 16:00:45 UTC:

You can post your encrypted and base64-encoded message to, say, pastebin-like service. To get webserver's owner's attention, you can run curl or something like that, many times per second against his/her webserver, so he/she will notice bloated log files.

It's like a small DoS attack.

URL to pastebin can be transmitted in referer's part: curl --referer.

UPD: 20240528 11:48:10 UTC: Further work -- check server's certificate validity, expiration...

UPD: 20240529 13:33:09 EEST: Next part: Encrypt/decrypt with SSH keys

(the post first published at 20240521, updated at 20240529.)


List of my other blog posts.

Subscribe to my news feed,

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.