Technology with Security
16 July 2020
Image: Yubikeys from Yubico
Asymmetric(Public Key) Cryptography is a great way to maintain Confidentiality, Non-repudiation and Authentication. This method overcomes the key exchange issues that generally happens with Symmetric key encryption but on the other side one has to really keep the other half of the key (private key) secure and also use it appropriately.
One of the convenient way is to store the keys in a hardware security card such as Yubikey and Google Titan.
This page describes the procedure on how to store the keys in a hardware security card and how to use it for regular activities like:
This following procedure is tested on Debian based Operating System and for Yubikey.
Before you proceed, please make sure you have both admin and user password for the security card. For Yubikey, the default admin password is 12345678
and the user password is 123456
.
Let’s first install the required packages for the Debian based operating System:
$ sudo apt update -y
$ sudo apt install -y \
curl gnupg2 gnupg-agent \
cryptsetup scdaemon pcscd \
yubikey-personalization \
dirmngr \
secure-delete \
hopenpgp-tools
If you don’t have a key pair already, please generate a new one and if you already have one, you can skip this step.
gpg --full-gen-key
option 1
, which generates the keys with RSA algorithm along with encryption subkey.4096
bits for better security.0
for life long validity.O
(as in Okay) to generate the new key.pub rsa4096 2020-07-17 [SC]
993ECC149B693F4496D3987BC911A16425694327
uid Test-Key (This is a demo key) <test@example.com>
sub rsa4096 2020-07-17 [E]
From above you can notice, the Master key was generated and with a key id 993ECC149B693F4496D3987BC911A164256943271
and also a subkey for Encryption, denoted by [E].
Lets generate separate subkeys for Signing and Authentication purposes by editing the Master key. For sake of simplicity, lets create save the key id in a variable and can use the variable for rest of the process.
#Assign your key id to KEYID variable
$ export KEYID=993ECC149B693F4496D3987BC911A16425694327
Editing the Master key:
$ gpg --expert --edit-key $KEYID
This will open the gpg prompt.
Generate a subkey for Signing purposes - like code signing etc.
gpg> addkey
Please select what kind of key you want:
(3) DSA (sign only)
(4) RSA (sign only)
(5) Elgamal (encrypt only)
(6) RSA (encrypt only)
(7) DSA (set your own capabilities)
(8) RSA (set your own capabilities)
(10) ECC (sign only)
(11) ECC (set your own capabilities)
(12) ECC (encrypt only)
(13) Existing key
(14) Existing key from card
Your selection? 4
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (3072) 4096
Requested keysize is 4096 bits
Please specify how long the key should be valid.
0 = key does not expire
<n> = key expires in n days
<n>w = key expires in n weeks
<n>m = key expires in n months
<n>y = key expires in n years
Key is valid for? (0) 1y
Key expires at Fri 16 Jul 2021 10:21:57 PM EDT
Is this correct? (y/N) y
Really create? (y/N) y
option 4
for creating the signing key with RSA.1y
for 1 year.ssb rsa4096/A5361560938D5F1D
created: 2020-07-17 expires: 2021-07-17 usage: S
[ultimate] (1). Test-Key (This is a demo key) <test@example.com>
Lets continue within gpg
prompt to generate a separate sub-key for Authentication purposes. By default gpg didn’t have an option for Authentication in its menu. So we will generate with own capabilities option.
gpg> addkey
Please select what kind of key you want:
(3) DSA (sign only)
(4) RSA (sign only)
(5) Elgamal (encrypt only)
(6) RSA (encrypt only)
(7) DSA (set your own capabilities)
(8) RSA (set your own capabilities)
(10) ECC (sign only)
(11) ECC (set your own capabilities)
(12) ECC (encrypt only)
(13) Existing key
(14) Existing key from card
Your selection? 8
Possible actions for a RSA key: Sign Encrypt Authenticate
Current allowed actions: Sign Encrypt
(S) Toggle the sign capability
(E) Toggle the encrypt capability
(A) Toggle the authenticate capability
(Q) Finished
Your selection? S
Possible actions for a RSA key: Sign Encrypt Authenticate
Current allowed actions: Encrypt
(S) Toggle the sign capability
(E) Toggle the encrypt capability
(A) Toggle the authenticate capability
(Q) Finished
Your selection? E
Possible actions for a RSA key: Sign Encrypt Authenticate
Current allowed actions:
(S) Toggle the sign capability
(E) Toggle the encrypt capability
(A) Toggle the authenticate capability
(Q) Finished
Your selection? A
Possible actions for a RSA key: Sign Encrypt Authenticate
Current allowed actions: Authenticate
(S) Toggle the sign capability
(E) Toggle the encrypt capability
(A) Toggle the authenticate capability
(Q) Finished
Your selection? Q
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (3072) 4096
Requested keysize is 4096 bits
Please specify how long the key should be valid.
0 = key does not expire
<n> = key expires in n days
<n>w = key expires in n weeks
<n>m = key expires in n months
<n>y = key expires in n years
Key is valid for? (0) 1y
Key expires at Fri 16 Jul 2021 10:37:49 PM EDT
Is this correct? (y/N) y
Really create? (y/N) y
ssb rsa4096/ECCA4FC9281139C6
created: 2020-07-17 expires: 2021-07-17 usage: A
[ultimate] (1). Test-Key (This is a demo key) <test@example.com>
Quit the prompt and save the changes:
gpg> quit
Save changes? (y/N) y
Verify the keys that are generated:
$ gpg --list-secret-keys
------------------------------
sec rsa4096 2020-07-17 [SC]
993ECC149B693F4496D3987BC911A16425694327
uid [ultimate] Test-Key (This is a demo key) <test@example.com>
ssb rsa4096 2020-07-17 [E]
ssb rsa4096 2020-07-17 [S] [expires: 2021-07-17]
ssb rsa4096 2020-07-17 [A] [expires: 2021-07-17]
You can modify the validity of any sub-key with expire
option and also with adduid
you can add additonal identities with gpg edit-key. Please refer help
option within gpg.
It is important to export the keys to a file and storage in a safe medium.
#exporting the private key
$ gpg --armor --output private_key.gpg --export-secret-key $KEYID
#exporting sub keys
$ gpg --armor --output sub_keys.gpg --export-secret-subkeys $KEYID
#exporting the public key
$ gpg --armor --output public_key.gpg --export $KEYID
Move the above generated files (.gpg) to a secure medium and share the public_key.gpg
to rest of the world by posting to key servers or to your website or to my favorite keybase profile .
It’s time to transfer the keys to the hardware security device, Yubikey.
gpg --card-status
.gpg --edit-key $KEYID
.gpg> key 1
.keytocard
to transfer the key to the card.gpg> key 1
and select Signing key by gpg> key 2
.gpg --card-status
and the keys information will be under General Key info.#selecting sub key
$gpg --edit-key $KEYID
sec rsa4096/C911A16425694327
created: 2020-07-17 expires: never usage: SC
trust: ultimate validity: ultimate
ssb rsa4096/36986E709A44F19E
created: 2020-07-17 expires: never usage: E
ssb rsa4096/A5361560938D5F1D
created: 2020-07-17 expires: 2021-07-17 usage: S
ssb rsa4096/ECCA4FC9281139C6
created: 2020-07-17 expires: 2021-07-17 usage: A
[ultimate] (1). Test-Key (This is a demo key) <test@example.com>
gpg> key 1
sec rsa4096/C911A16425694327
created: 2020-07-17 expires: never usage: SC
trust: ultimate validity: ultimate
ssb* rsa4096/36986E709A44F19E
created: 2020-07-17 expires: never usage: E
ssb rsa4096/A5361560938D5F1D
created: 2020-07-17 expires: 2021-07-17 usage: S
ssb rsa4096/ECCA4FC9281139C6
created: 2020-07-17 expires: 2021-07-17 usage: A
[ultimate] (1). Test-Key (This is a demo key) <test@example.com>
$ gpg --delete-secret-keys $KEYID
.gpg --card-status
and you will now notice sec#
, under General Key info.At this point, we have our master keys and its sub keys on the card safely and only the public keys on the computer.
We need to let gpg-agent to handle the requests from SSH, add the below line to the gpg-agent.conf
file:
$ echo "enable-ssh-support" >> ~/.gnupg/gpg-agent.conf
Notify the agent, which key id it should use during the ssh session establishment:
$ echo $KEYID >> ~/.gnupg/sshcontrol
Let the SSH know how to access the gpg-agent:
$ echo "export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket)" >> ~/.bashrc
$ echo "gpgconf --launch gpg-agent" >> ~/.bashrc
Extract the SSH public key to a file:
$ ssh-add -L >> id_rsa_card.pub
Transfer this ssh public key to the desired remote server and add it to authorized_keys file.
We have completed all the required setup.
Lets validate the setup by performing Confidentiality, Signing and Authentication use cases.
Before we proceed further, please unplug the security key card from the computer to notice the prompts for the device during the operations.
Validating the encryption and decryption process:
#Encryption
$ echo "This is a secret message" | gpg --encrypt --recipient $KEYID > message.gpg
#Decryption
$ gpg --decrypt --recipient $KEYID < message.gpg
#This will prompt to plug in the security card and for user pin.
Validating the signing process with GitHub:
Add the public_key.gpg to your GitHub account.
Tip: Make sure key uid email address is same as Git commits email address.
# Please make sure the Signing is enabled for commits to your repo.
$ git config commit.gpgsign true
# Tell Git which key needs to use for commits
$ git config --global user.signingkey $KEYID
# Perform a commit
$ git commit -S -m "commit message"
#This will prompt to plug in the security card and for user pin.
Validating the ssh login with a server
#ssh to the server where the ssh public key is transfered
$ ssh user@server
#This will prompt to plug in the security card and for user pin.
Though the overall setup process looks lengthy, it is a one-time process and makes easy to maintain and manage the keys. You can carry the hardware security card along with you everyday and use the appropriate keys where needed by just plugging the card. This will also enable the Multi Factor Authentication (MFA) with “something you have (Card) and something you know (Card PIN)”.