large amounts dd cryptocurrency ea
Found at: gopher.blog.benjojo.co.uk:70/tls-https-server-from-a-yubikey
Yubikey/Smartcard backed TLS servers
===

It has become clear that storing secrets in computers is
hard. The best demo to the world that storing secrets on
“online” computers is hard and sometimes devastating, is the large
amounts of cryptocurrency theft due to critical keys being in
memory of systems directly or indirectly connected to the
internet.
For the last one and a half years, I’ve had a set of
Yubikeys on my keychain. A Yubikey is a USB stick that acts like
a two factor token, but can also act as a smart card.
Smart cards are neat, since they allow you to store
sensitive cryptographic keys on another removable device, and they
come with a guarantee that once they are programmed with a key
they will not give it back to a system (they can be
overwritten though)
This allows someone to separate a cryptographic key from
the system it lives on. This is useful for things like SSH,
since it means you can have a key that moves on your person,
rather than a per machine key in the case that you use multiple
machines to access systems.
Under the hood, all these smart cards are doing are the
operations that require the private key, like data signing and
decryption.
I figured that we could also retrofit them to provide for
other roles where keys would normally be in memory (and
stealable), Like TLS/HTTPS servers!
To start with, I took a spare yubikey I had never setup
and used the GPG tooling on Linux to setup the card and
generate keys.
```
ben@eshwil:~$ gpg2 --card-status
Reader ...........: 1050:0407:X:0
Application ID ...: D2760001240102010006069118380000
Version ..........: 2.1
Manufacturer .....: Yubico
Serial number ....: 0xxxxxxx
Name of cardholder: [not set]
Language prefs ...: [not set]
Sex ..............: unspecified
URL of public key : [not set]
Login data .......: [not set]
Signature PIN ....: not forced
Key attributes ...: rsa2048 rsa2048 rsa2048
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 0 3
Signature counter : 0
Signature key ....: [none]
Encryption key....: [none]
Authentication key: [none]
General key info..: [none]
```
Here we see that the system is able to query the card
and is empty and ready to program a key on to it.
```
ben@eshwil:~$ gpg2 --card-edit
gpg/card> admin
Admin commands are allowed
gpg/card> generate
Make off-card backup of encryption key? (Y/n) n
Please note that the factory settings of the PINs are
PIN = '123456' Admin PIN = '12345678'
You should change them using the command --change-pin
What keysize do you want for the Signature key? (2048)
What keysize do you want for the Encryption key? (2048)
What keysize do you want for the Authentication key? (2048)
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) 91
Key expires at Tue 31 Jul 2018 11:52:47 EDT
Is this correct? (y/N) Y
You need a user ID to identify your key; the software
constructs the user ID
from the Real Name, Comment and Email Address in this
form:
"Heinrich Heine (Der Dichter)
"
Real name: yubitls.benjojo.co.uk
E-mail address:
Comment:
You selected this USER-ID:
"yubitls.benjojo.co.uk"
Change (N)ame, (C)omment, (E)-mail or (O)kay/(Q)uit? O
gpg: /home/ben/.gnupg/trustdb.gpg: trustdb created
gpg: key 3FCD18FAB4FC1CF9 marked as ultimately trusted
gpg: directory '/home/ben/.gnupg/openpgp-revocs.d' created
gpg: revocation certificate stored as
'/home/ben/.gnupg/openpgp-revocs.d/8236069819F168BB781D31B53FCD18FAB4FC1CF9.rev'
public and secret key created and signed.
```
Above we used the smart card itself to generate keys. We
could have generated keys locally on the system and then uploaded
keys to the card, however that would mean that at some point
the keys that we are trying to secure would have been visible
to a system connected to the internet. This is not optimal
since if I had malware on my laptop while I did this, the keys
could have been copied without me knowing.
Generation on the card ensures that the system provisioning
the smart card never sees the sensitive key material, all of
the generation is done on the card itself.
```
gpg/card> list
Reader ...........: 1050:0407:X:0
Application ID ...: D2760001240102010006069118380000
Version ..........: 2.1
Manufacturer .....: Yubico
Serial number ....: 0xxxxxxx
Name of cardholder: [not set]
Language prefs ...: [not set]
Sex ..............: unspecified
URL of public key : [not set]
Login data .......: [not set]
Signature PIN ....: not forced
Key attributes ...: rsa2048 rsa2048 rsa2048
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 0 3
Signature counter : 4
Signature key ....: 8236 0698 19F1 68BB 781D 31B5 3FCD
18FA B4FC 1CF9
created ....: 2018-05-01 15:53:07
Encryption key....: 2E4F E811 2814 EA33 FA1E C23F 99F1
667F C9BE 44A3
created ....: 2018-05-01 15:53:07
Authentication key: 1A1A 6594 F7D6 5EA2 0E1C C0AE 5786
AF8D 1462 E84D
created ....: 2018-05-01 15:53:07
General key info..: pub rsa2048/3FCD18FAB4FC1CF9 2018-05-01
yubitls.benjojo.co.uk
sec> rsa2048/3FCD18FAB4FC1CF9 created: 2018-05-01 expires:
2018-07-31
card-no: 0006 06911838
ssb> rsa2048/5786AF8D1462E84D created: 2018-05-01 expires:
2018-07-31
card-no: 0006 06911838
ssb> rsa2048/99F1667FC9BE44A3 created: 2018-05-01 expires:
2018-07-31
card-no: 0006 06911838
```
Now that we have our key setup, it's worth going through
where the key will be needed to serve as a HTTP/TLS server.

To start a TLS connection, the client states who it is
expecting to see to the server, as well as some information about
what the clients capabilities and requirements are. The server
then replies with a certificate and a signature to prove it has
the key for that certificate, plus information on what the
clients capabilities are as well.
Assuming all is well, the two systems figure out a
solution to connect, and then begin communicating with encryption
enabled.
unless some other creative solutions are involved
This means that for every fresh connection the server must
do operations that involve the sensitive private key. In almost
every case this means it has to be accessible in memory for a
server to function (unless some other creative solutions are
involved). However here we want to move this operation to a external
bit of hardware.
Where most programming languages/runtimes link to OpenSSL,
golang is different in that it has its own internal TLS stack
internally. This is useful for us, since we want to make a "fake
private key" that has the function calls of a regular private key,
but actually does other logic with those function calls.

Lucky for us, someone has already implemented a library
that implements a `crypto.PrivateKey` but where the backend is a
GPG Agent. This is especially useful in our case since the
Yubikey works with a GPG agent.

Now that we have a chain that works, we can create a
Certificate Signing Request file for the domain we are going to use:
```
$ ./yubiTLS -csr.cn yubitls.benjojo.co.uk -signcsr
You appear to have not selected a key to use, or the key
you selected
Does not exist in the agent at this time, Do you see
your key in this list?
2018/05/02 15:39:33 Key: 09A25C1D64EF0E7170F9C3A0FAF9080B02216FD5
- {Keygrip:09A25C1D64EF0E7170F9C3A0FAF9080B02216FD5 Type:1
SerialNo:D2760001240102010006069118380000 CardID:OPENPGP.3 Cached:false Protection:2
Fingerprint:fe:96:e4:c2:68:f7:2f:75:a7:94:8d:1f:24:20:28:be TimeToLive: conn:publicKey:{N:0xc42000c340 E:65537}}
$ ./yubiTLS -csr.cn yubitls.benjojo.co.uk -signcsr -keyid
09A25C1D64EF0E7170F9C3A0FAF9080B02216FD5
$ ls *.csr
yubitls.benjojo.co.uk.csr
```
We can then use Let's Encrypt via SSL For Free to get
this CSR signed.

After verifying the domain, we tell the site we have a
CSR:
After that, we obtain a SSL certificate for the key on
our Yubikey!

Then we can provide these certificates to the server, and
run the HTTPS demo server!
```
$ ./yubiTLS -keyid 09A25C1D64EF0E7170F9C3A0FAF9080B02216FD5
-crtpath cert.crt -cacrtpath bundle.crt
2018/05/02 15:49:57 Listening
```
The first time you visit it, it may ask for the PIN to
unlock the Yubikey, it was amusing when this happened for the
first time, because I knew at that point it worked :)

After we enter the pin, we get content served from a
HTTPS server backed by a key contained on a USB stick!

If you want to try this out for yourself on a **blank
yubikey** you can find the code on my github here:
https://github.com/benjojo/yubiTLS
And if you enjoyed this, you will be glad to know that I
am going to be at Recurse Center in NY for the next 7
weeks! Meaning you can follow my Twitter or RSS to keep up with
the other silly (or sometimes sensible) things I will do!
Until next time!