YubiKey a U2F jsou jedny z nejlepších věcí, které se staly v počítačové bezpečnosti posledních let. Je to čipová karta a zároveň usb čtečka v balení, které se zcela schová do usb portu (verze nano). Nijak tedy nevyčnívá a je možné ho třeba v notebooku prostě nechat jako takovou simku na které máte hardwarově chráněné všechny svoje kryptografické klíče, protože tahle titěrnost zvládá prakticky všechny standardizované bezpečnostní technologie. Jeho využití je ve skutečnosti tak široké, že nastavit ho v plném rozsahu je vlastně dost práce. Proto tady nechám svoje poznámky z takového nastavování v Debian Jessie, může to někomu pomoct.
POZOR!!! Toto jsou opravdu pouze poznámky a rozcestník odkazů. Nejedná se o doslovný návod a v žádném případě jej tak nepoužívejte, pokud zcela nerozumíte popsané problematice. Počítačová bezpečnost na této úrovni je velmi ostrý nástroj se kterým se můžete šeredně pořezat. Tím nemyslím jen potenciální bezpečnostní díry, ale třeba také lock-out z vlastního systému!
EDIT: Až tři čtvrtě roku od napsání článku jsem objevil staršího a bohatšího anglického příbuzného https://github.com/drduh/YubiKey-Guide. Vědět to, tak jsem si ušetřil dost práce.
EDIT2: A další… https://www.jfry.me/articles/2015/gpg-smartcard/
Prerekvizity
sudo apt-get install pcscd pcsc-tools opensc
Yubico personalization tool
Je potřeba inicializovat token do správného usb módu. Není potřeba celý GUI nástroj, stačí jen verze s command line interface.
sudo apt-get install libusb-dev
wget https://developers.yubico.com/yubico-c/Releases/libyubikey-1.13.tar.gz # lib je potreba pro build personalisation tool
tar tar -xf libyubikey-1.13.tar.gz
cd libyubikey-1.13
./configure
make check
sudo make install
cd ..
wget https://developers.yubico.com/yubikey-personalization/Releases/ykpers-1.17.3.tar.gz
tar -xf ykpers-1.17.3.tar.gz
cd ykpers-1.17.3/
./configure
make
sudo make install
sudo ./ykpersonalize -m 6 # Nastav token do modu OTP+U2F+CCID
V Debian Jessie je pro YubiKey 4 potřeba updatovat seznam známých zařízení libccid:
sudo vim /etc/libccid_Info.plist
<key>ifdVendorID</key> <array> + <string>0x1050</string> + <string>0x1050</string> + <string>0x1050</string> + <string>0x1050</string> ... <key>ifdProductID</key> <array> + <string>0x0407</string> + <string>0x0406</string> + <string>0x0405</string> + <string>0x0404</string> ... <key>ifdFriendlyName</key> <array> + <string>Yubico Yubikey 4 OTP+U2F+CCID</string> + <string>Yubico Yubikey 4 U2F+CCID</string> + <string>Yubico Yubikey 4 OTP+CCID</string> + <string>Yubico Yubikey 4 CCID</string>
sudo service pcscd restart
Přehled základních nástrojů (zobrazen stav po vygenerování certifikátu)
opensc-tool --list-readers
# Detected readers (pcsc) Nr. Card Features Name 0 Yes Yubico Yubikey NEO OTP+U2F+CCID 00 00
piv-tool -n
Using reader with a card: Yubico Yubikey NEO OTP+U2F+CCID 00 00 PIV-II card
pcsc_scan
Reader 0: Yubico Yubikey NEO OTP+U2F+CCID 00 00 Card state: Card inserted, ATR: ... Possibly identified card (using /usr/share/pcsc/smartcard_list.txt): YubiKey NEO (PKI) http://www.yubico.com/
pkcs15-tool -D
Using reader with a card: Yubico Yubikey NEO OTP+U2F+CCID 00 00 PKCS#15 Card [PIV_II]: Version : 0 Serial number : 00000000 Manufacturer ID: piv_II Flags : PIN [PIV Card Holder pin] Object Flags : [0x1], private ...
yubico-piv-tool -a status
CHUID: No data available CCC: No data available PIN tries left: 3
pkcs11-tool --module /usr/lib/x86_64-linux-gnu/opensc-pkcs11.so --list-objects
Using slot 1 with a present token (0x1) Public Key Object; RSA 2048 bits label: SIGN pubkey ID: 02 Usage: encrypt, verify Certificate Object, type = X.509 cert label: Certificate for Digital Signature ID: 02
pkcs11-tool --module /usr/lib/x86_64-linux-gnu/opensc-pkcs11.so --read --slot 1 --id 2 --type pubkey
Public key binárně...
U2F
sudo vim /etc/udev/rules.d/70-u2f.rules
# this udev file should be used with udev 188 and newer ACTION!="add|change", GOTO="u2f_end" # Yubico YubiKey KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="1050", ATTRS{idProduct}=="0113|0114|0115|0116|0120|0402|0403|0406|0407|0410", TAG+="uaccess" LABEL="u2f_end"
PIV
Info
PIV applet AID: a000000308
The default PIN code is 123456. The default PUK code is 12345678.
The default 3DES management key (9B) is 010203040506070801020304050607080102030405060708.
The following key slots exists:
-
9A, 9C, 9D, 9E: RSA 1024, RSA 2048, or ECC secp256r1 keys (algorithms 6, 7, 11 respectively).
-
9B: Triple-DES key (algorithm 3) for PIV management.
The maximum size of stored objects is 2025/3049 bytes for current versions of YubiKey NEO and YubiKey 4, respectively.
Currently all functionality are available over both contact and contactless interfaces (contrary to what the specifications mandate).
Sloty v YubiKey NEO
- Slot 9a: PIV Authentication
- Slot 9c: Digital Signature
- Slot 9d: Key Management
- Slot 9e: Card Authentication
Yubico PIV tool
sudo apt-get install libssl-dev libpcsclite-dev
wget https://developers.yubico.com/yubico-piv-tool/Releases/yubico-piv-tool-1.4.2.tar.gz
tar -xvf yubico-piv-tool-1.4.2.tar.gz
cd yubico-piv-tool-1.4.2
./configure
make # vysledek v tool/
sudo make install
sudo ldconfig -v
Vytvoření klíče, resp. certifikátu
Přímo na kartě
V této variantě je privátní klíč uložen jen na Yubikey, nedají se tedy vytvořit kopie pro případ ztráty, což celkově není moc použitelné.
yubico-piv-tool -a change-pin # pin i puk nejsou ty same, jako treba pro gpg, je nutne je nastavit samostatne.
yubico-piv-tool -a change-puk
yubico-piv-tool -s 9a -o public_key.pem --touch-policy=always -a generate
yubico-piv-tool -s 9a -i public_key.pem -o certificate.pem -S '/CN=Frantisek Rezac/OU=individual/O=calavera.info/' -a verify -a selfsign
yubico-piv-tool -s 9a -i certificate.pem --touch-policy=always -a import-certificate
pkcs15-tool --list-keys # Pro zjisteni ID klice
pkcs15-tool --read-ssh-key <ID klice>
echo <ssh-rsa ...> >> ~/.ssh/authorized_keys # pro pouziti PIV pro SSH login
Ověření informací v certifikátu
pkcs15-tool --list-certificates # pro zjisteni ID certifikatu
pkcs15-tool --read-certificate <ID certifikatu> # Ulozit vystup do certificate.pem
openssl x509 -in certificate.pem -text -noout
Alternativní generování klíče pomocí OpenSSL na počítači
V této variantě se ukládá klíč na počítači, takže je možné vyrábět kopie pro případ ztráty. Klíč ale nebude na disku nijak chráněný, proto je k tomu nejlépe používat airgapovaný (offline) počítač.
openssl genpkey -algorithm RSA -out private_key.pem -pkeyopt rsa_keygen_bits:2048
openssl rsa -pubout -in private_key.pem -out public_key.pem
yubico-piv-tool -s 9a --touch-policy=always -i private_key.pem -a import-key
# zbytek stejny jako pri generovani na karte
Alternativní generování klíče pomocí piv-tool/OpenSSL na YubiKey (experimentální hybrid předchozích variant)
echo -n 01:02:03:04:05:06:07:08:01:02:03:04:05:06:07:08:01:02:03:04:05:06:07:08 > admin.key
export PIV_EXT_AUTH_KEY=/home/calavera/admin.key
piv-tool --genkey 9A:07 --admin A:9B:03 --out ./9a-public
export PIV_9A_KEY=/home/calavera/prace/passwords/yubikey-info/9a-public
openssl
engine dynamic -pre SO_PATH:/usr/lib/engines/engine_pkcs11.so -pre ID:pkcs11 -pre NO_VCHECK:1 -pre LIST_ADD:1 -pre LOAD -pre MODULE_PATH:/usr/lib/x86_64-linux-gnu/opensc-pkcs11.so
req -engine pkcs11 -x509 -new -key slot_1-id_1 -keyform engine -out 9a-x509.pem -text
req -engine pkcs11 -pubkey -new -key slot_1-id_1 -keyform engine -out 9a-public.pem -text
SSH
Na serveru přidat do ~/.ssh/authorized-keys
klíč vygenerovaný při inicializaci (řádka pkcs15-tool --read-ssh-key
).
Na klientu buď v ~/.ssh/config
PKCS11Provider /usr/lib/x86_64-linux-gnu/pkcs11/opensc-pkcs11.so
nebo jako parametr příkazové řádky
-I /usr/lib/x86_64-linux-gnu/pkcs11/opensc-pkcs11.so
PAM
man pam_pkcs11
sudo apt-get install libpam-pkcs11
sudo mkdir /etc/pam_pkcs11
zcat /usr/share/doc/libpam-pkcs11/examples/pam_pkcs11.conf.example.gz | sudo tee /etc/pam_pkcs11/pam_pkcs11.conf
sudo mkdir /etc/pam_pkcs11/cacerts /etc/pam_pkcs11/crls
sudo vim /etc/pam_pkcs11/pam_pkcs11.conf
pkcs11_module opensc { module = /usr/lib/x86_64-linux-gnu/pkcs11/opensc-pkcs11.so; cert_policy = signature; ... } ... use_mappers = openssh;
Test
sudo vim /etc/pam.d/sudo
%PAM-1.0 +auth sufficient pam_pkcs11.so debug @include common-auth
Globálně
sudo vim /etc/pam.d/common-auth
# pam-auth-update(8) for details. +auth [success=3 default=ignore] pam_pkcs11.so # here are the per-package modules (the "Primary" block)
Keyring
Side efekt zavedení PKCS11 PAM je, že se nemůže automaticky odemkdnout defaultní Gnome keyring pomocí login hesla. Ještě horší je, že se nějakou automagií po ručním otevření keyringu změní heslo keyringu na PIN (který se zadává na přihlašovací obrazovce místo hesla). Tohle funguje i opačně, tedy když se někdy v budoucnu člověk opět přihlásí heslem, změní se heslo keyringu z PINu na heslo.
GPG
Defaultně je v Debianu Jessie instalované GPG 1.x.x, které má omezení na RSA max 3072 bitů. Pro využití RSA 4096, kterého je schopný YubiKey 4, je potřeba instalovat GPG řady 2.
sudo apt-get install gnupg2 scdaemon
gpg2 --change-pin # GPG PIN i admin PIN neni ten samy jako u PIV, je potreba jej nastavit zvlast
Generování klíče
Přímo na kartě
Tuto variantu nepoužívat! Při generování se sice nabídne vytvoření off card zálohy, ale to se bude zálohovat jen podklíč pro encryption, ne hlavní certifikační klíč!
gpg2 --card-edit
admin generate # souhlasit s off-card zálohou, která vytvoří soubor sk_XXXXXXXXXXXXXXXXX.gpg
Na air-gapovaném počítači
gpg2 --gen-key # vytvori hlavni (certifikacni a podepisovaci) klic a podklic pro encryption
# expiration nedavat, na hlavni klic se sbiraji overovaci podpisy ostatnich o ktere by se po expiration prislo
# lepsi je dat expiration na podklice vytvorene pozdeji, hlavni klic se stejne z airgapovaneho pocitace nedostane, na Yubikey se budou davat jen podklice
# bez zadane expiration pri generovani bude sice bez expiration i podklic pro encryption, ale to se da opravit pozdeji
gpg2 --expert --edit-key <key id> # expert je potreba aby bylo mozne vytvorit podklic pro authentication
key 1 # vybere encryption podklic pro nasledujici pokyny expire # nastavit expiration, ktere je z predchoziho kroku nenastavene key 0 # zrusi vybrani addkey # pridat podklic pro signing (mozne zvolit primo z nabidky) a authentication (je potreba togglovat rucne) save
# vytvorit zalohy
gpg2 --armor --export <key id> > gpg-public-key.asc
gpg2 --armor --export-secret-keys <key id> > gpg-secret-key.asc
gpg2 --armor --export-secret-subkeys <key id> > gpg-secret-subkeys.asc
gpg2 --gen-revoke <key id> --output pgp-revocation.asc
cp -R ~/.gnupg /mnt/usb/gpg-backup/
# publikovat klic na http://keys.gnupg.net/ nebo jinem serveru z sks keyserver pool nebo
gpg2 --send-key <key id> # v pgp.conf musi byt nastaveny keyserver (to je defaultne) nebo pridat parametr --keyserver keys.gnupg.net
# prenest klice na kartu
gpg2 --edit-key <key id>
key 1 keytocard # vybrat prislusny slot, udelat pro subklice pro signing, encryption, authentication save
Záloha GPG klíče na druhou kartu
Pokud byl klíč generován přímo na kartě
V tomto případě nelze klíč duplikovat celý, jen encryption podklíč, který se při vytváření uložil na disk (i to ale může někomu pomoci, když už je v tom).
gpg2 --edit-key <key id>
toggle bkuptocard sk_XXXXXXXXXXXXXXX.gpg # soubor vytvoreny pri vygenerovani klice
Pokud byl klíč generován na airgapovaném počítači
cp -R /mnt/usb/gpg-backup/.gnupg ~/alt-gpg-home
gpg2 --homedir ~/alt-gpg-home --edit-key <key id>
# zopakovat prikaz keytocard jako pri vytvareni primarni karty, je mozne vynechat save
Inicializace pracovního počítače
sudo apt-get install pinentry-curses
sudo update-alternatives --display pinentry
sudo update-alternatives --config pinentry
# import public klice je mozne provest nekolika zpusoby
# bud stazenim z keyserveru s odvozenim key id ze secret klice na karte
gpg2 --card-edit
fetch
# nebo importem souboru
gpg2 --import gpg-public-key.asc
# nebo stazenim z keyserveru
gpg2 --recv-keys <key id>
# v gpg se neda odvodit public klic ze secret klice! (neobsahoval by asi uid)
gpg2 --card-status # jako vedlejsi efekt propoji privatni klic na karte s klicem stazenym pomoci fetch
gpg2 --edit-key <key id>
trust # zvolit ultimate trust
vim ~/.gnupg/gpg.conf
+default-key <key id> +default-recipient-self
Přechod na záložní kartu na pracovním počítači
gpg2 --delete-secret-keys <key id>
gpg2 --card-status # svaze aktualni (nahradni) kartu s puvodnim public klicem (stejne jako pri inicializaci karty primarni)
Revokace certifikátu
gpg2 --gen-revoke <key id> --output pgp-revocation.asc
gpg2 --import pgp-revocation.asc
gpg2 --send-key <key id>
Troubleshooting
gpg2 --list-packets secret-exported-key.gpg # zobrazi jednotlive pakety v klici
cat secret-exported-key.gpg > gpgsplit # rozdeli klic do souboru obsahujicich jednotlive pakety
cat paket1.sig paket2.uid paket3.sig | gpg2 --import # importuje jen vybranou podmnozinu klicu
Chyba při importu klíče na úplně novou kartu
Symptom: přesun klíče z počítače na kartu selže s hláškou, že klíč nemůže být větší než 2048 bitů.
Důvod: import klíče, na rozdíl od generování, nedokáže nastavit parametr délky klíče na kartě. Defaultně je tento parametr nastaven na 2048, proto import většího klíče selže.
Workaround: vygenerovat klíč potřebné velikosti na kartě, tím se nastaví příslušný parametr a import pak už projde.
Simultánní používání PKCS11/PIV a GPG
PKCS11 a GPG nemohou k Yubikey přistupovat najednou. Proto
- Není možné používat trvale spuštěného GPG agenta (PKCS11 třeba v SSH pak skončí s chybou
Permission denied (publickey).
). Pokud se dělá nějaká batch akce, kde to bez GPG agenta nejde, je možné spustit shell s ním ručně a batch akci provést v něm:gpg-agent --daemon /bin/bash
. - Někdy PKCS11 neuvolní kartu a GPG pak selže s hláškou
PC/SC OPEN failed: sharing violation
. Workaround je prostě vytáhnout a znovu zastrčit kartu.
Použití
gpg2 --clearsign sometext.txt
Nedostatek entropie
GPG může zůstat “viset”, což znamená, že má nedostatek entropie. Dá se to spravit démonem pro doplňování entropie v kernelu, kterému se dá zadat zdroj entropie. Tím se dá doplňovat entropie z pseudonáhodných čísel, ale u Raspberry jde využít i hardwarový generátor.
sudo apt-get install rng-tools
# pokud se rngd nespousti automaticky, je mozne spustit rucne
sudo rngd -r /dev/hwrng # raspberry nebo
sudo rngd -r /dev/urandom # pseudonahodna cisla
Jiná možnost je ještě použít hardwarový generátor přímo z karty pomocí příkazu scdrand
, ale to jsem netestoval.
Přechod na nový GPG klíč v pass
Pass init je možné dělat opakovaně i s několika různými key id. Pass zajistí šifrování pro všechny klíče, které si uchovává v ~/.password-store/.gpg-id
pass init <old key id> <new key id>
GIT
V gitu je možné explicitně podepisovat commity pomocí GPG.
vim ~/.gitconfig
[user] ... + signingkey = <signing key id> +[gpg] + program = gpg2
git commit -S -am 'signed commit'
git log --show-signature -1