使用 Yubikey 進行公鑰認證

Yubikey 4

最近入手了 Yubikey 4,這個東西除了具備 OTP 以及 U2F 二階段認證的功能外,還具備了 OpenPGP 智慧卡與 PIV 智慧卡的功能,可以儲存私鑰並用在任何需要 RSA 加解密的場合,比如說 SSH 登入或簽發憑證。以下將會介紹如何在 Linux 中使用 Yubikey 來登入系統。

聲明 本文僅分享 Yubikey 4 的使用經驗,Yubikey 4 是由 Yubico 公司生產的 USB 鑰匙。本人與 Yubico 公司無利益關係,也不提供任何資訊安全方面的保證。若您想要在正式環境中導入 Yubikey,請詳細閱讀官方說明文件並多方搜集相關使用資訊再做決定。

公鑰認證與智慧卡 (Smart Card)

有爬過 SSH log 的人都知道,只要你的 SSH 主機放在公開網路上,每天 24 小時都會有攻擊者不停用各種帳號密碼試圖破解它。為了讓你的主機安全一點,你要嘛設定一個超長超難記的密碼,不然就是乾脆關掉密碼登入,只允許使用者用公鑰認證。在量子電腦還沒開始量產的 2016 年,電腦亂數產生的 2048bit RSA 還是比使用者自己設定的密碼要安全些。

使用公鑰認證還有另一個好處:使用者不會把私鑰寫在便條紙上亂丟。當然這也伴隨缺點,那就是使用者為了方便,會把這個檔案隨便複製到不安全的地方。為了避免這種情況,我們可以用一些特殊的硬體來儲存私鑰,比如說智慧卡 (Smart Card) 或是信賴平台模組 (Trusted Platform Module)。私鑰只能單向寫入這類裝置中,而無法讀出來。所有牽涉到私鑰的操作,比如說解密或簽章都是在這個安全硬體上進行運算,因而確保私鑰的安全。

OpenPGP 及 PIV

智慧卡的原理雖然不複雜,但由於廠商眾多,也區分許多不同的規格與標準。Yubikey 4 支援以下兩種智慧卡標準:

  • OpenPGP
  • NIST PIV

Yubikey 可以同時儲存 PGP 私鑰以及 PIV 私鑰,兩邊互不影響,而且都可以拿來當作 SSH 登入用的憑證。這邊會先說明使用 PIV 的情況。除了前半部使用專屬工具進行設定的部份以外,本文其它部份同時也適用於 PIV 標準的一般智慧卡。

開始使用 Yubikey

首先要安裝 yubico-piv-toolopensc 以及 opensc-pkcs11

1
$ sudo apt-get install yubico-piv-tool opensc opensc-pkcs11

Yubikey 在 PIV 模式下有三組操作密碼:

  • PIN:當你要使用私鑰進行運算時需要輸入 PIN 碼,這也是你最常用到的密碼,可為六位到八位英數字,預設為 123456
  • PUK:Yubikey 在輸入三次錯誤的 PIN 碼後就會被鎖定,此時必需輸入 PUK 才能解鎖,可為六位到八位英數字,預設為 12345678
  • Management key:任何會寫入資料到 Yubikey 的操作會需要 management key,長度為 24 bytes,可包含任何位元,因此會使用 48 個十六進位碼來表示。預設值為 010203040506070801020304050607080102030405060708

使用前,先為它設定好 PIN、PUK。

1
2
3
4
$ yubico-piv-tool -a change-pin -P 123456
Enter new pin:
Veryfying - Enter new pin:
Successfully changed the pin code.
1
2
3
4
$ yubico-piv-tool -a change-puk -P 12345678
Enter new puk:
Veryfying - Enter new puk:
Successfully changed the puk code.

你也可以設定新的 management key,但一但這麼做,後面所有指令都會需要輸入新的 management key 才能修改 Yubikey 的內容。因此建議你產生完金鑰後再來設定 management key,不然重覆打那麼多指令手會很累。

產生金鑰對

注意:受到 ROCA (CVE-2017-15361) 的影響,直接在 Yubikey 上產生的 RSA 金鑰可能有強度不足的問題。在你實際操作之前,請先 確認 Yubikey 型號及韌體版本 是否有 ROCA 漏洞。

ROCA 的弱點在於金鑰生成。如果你的 Yubikey 確認為 affected,改用 OpenSSL 來產生並匯入金鑰即可,使用時仍然是安全的。

你可以指定在 Yubikey 上產生金鑰對,由於私鑰無法從外部讀取,這種方式確保即使是金鑰對產生的過程中,私鑰也不致於外洩。

1
$ yubico-piv-tool -s 9a -a generate -o public.pem

這個例子中,我們在 Yubikey 上產生私鑰並存放在 9a 這個欄位中,這是 PIV 標準預設作為登入認證用的金鑰欄位。你也可以指定其它欄位,詳見官方說明文件

如果你的 Yubikey 有 ROCA 弱點,或是你想要備份私鑰,你也可以用 OpenSSL 產生私鑰後再匯入 Yubikey:

1
2
3
$ openssl genrsa -out private.pem 2048
$ openssl rsa -in private.pem -pubout -out public.pem
$ yubico-piv-tool -s 9a -a import-key -i private.pem

產生金鑰對後,公鑰會直接輸出到 public.pem 這個檔案,而不會存在 Yubikey 裡面。依照 PIV 的標準,Yubikey 只能存入 X.509 憑證,而不能單純儲存公鑰。因此這邊得用我們剛才產生的私鑰,製作一份自我簽核 (self-signed) 的憑證:

1
$ yubico-piv-tool -a verify-pin -a selfsign-certificate -s 9a -S "/CN=SSH KEY/" -i public.pem -o cert.pem

這個步驟由於需要私鑰進行簽章,因此要輸入 PIN 才能進行。-S "/CN=SSH KEY/" 這項參數指定憑證簽發對象的名稱,你可以隨意指定,但一定要給個值。

最後,把剛生好的憑證裝進 Yubikey 中,就完成了這把鑰匙:

1
yubico-piv-tool -a import-certificate -s 9a -i cert.pem

設定 SSH 公鑰認證

安裝好 opensc-pkcs11 後,你可以用 pkcs15-tool 這個指令讀取 Yubikey 中的公鑰,並且輸出 SSH 格式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ pkcs15-tool --list-public-key
Using reader with a card: Yubico Yubikey 4 OTP+U2F+CCID 00 00
Public RSA Key [PIV AUTH pubkey]
Object Flags : [0x0]
Usage : [0xD1], encrypt, wrap, verify, verifyRecover
Access Flags : [0x2], extract
ModLength : 2048
Key ref : 154 (0x9A)
Native : yes
ID : 01
DirectValue : <absent>
$ pkcs15-tool --read-ssh-key 01
Using reader with a card: Yubico Yubikey 4 OTP+U2F+CCID 00 00
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCeI5Dvrl9kViY5PqkvH4NTriwC8xNsp3NN63dm7EQQB7K7xQ223ffrETMFGo+iGxer3+rc4p7dUTIAuQMmBUPh5ylxNEF11+43u97CUaquV4nxrmUes373mNxtgbfGvHEIN3Uo7Fwha1kOjjugTsAHoJWEN6f8vFkZg8qi1+OOMnN33yddngXixpqAXV05YrpoKfmO+dbkvMov09+E4IuTs3I/3N0x6kEVib6U/xRY/rl9xAwbE9MDcv9mFT5YUSC4LA4FEqUnPtYvVC1JFWs3S0xDZ+qyVWfoxLHDG39WZ00GPeHkcbuwAtkpqlaLlujX3CrKoNTkV7aa7unZlQon PIV AUTH pubkey

複製後面 ssh-rsa 開頭的那行字後,貼到目標機器的 ~/.ssh/authorized_keys 檔案內,你就可以用這個金鑰對來登入目標機器了。

1
2
$ ssh -I /usr/lib/x86_64-linux-gnu/opensc-pkcs11.so syyang@foo.bar
Enter PIN for 'PIV_II (PIV Card Holder pin)':

注意 -I 參數後需要指定 opensc-pkcs11.so 函式庫的路徑,系統不同安裝路徑也會不一樣。登入時只要把 Yubikey 插入 USB,SSH 會提示你輸入 PIN,這時要輸入 Yubikey 的 PIN 碼,而不是遠端帳戶上的密碼。

當然,你不會想要每次使用 SSH 都還要打這麼一長串,這只要編輯 .ssh/config 並且加入適當的參數即可。

1
2
3
4
host foo
hostname foo.bar
user syyang
PKCS11Provider /usr/lib/x86_64-linux-gnu/opensc-pkcs11.so

讓 PuTTY / WinSCP 使用智慧卡

大部份使用者還是在 Windows 環境底下工作,那麼 PuTTY 或是 WinSCP 是否可以搭配智慧卡使用呢?答案是可以的!

首先下載 Windows 版本的 OpenSC,在 SourceForge 即可下載編譯好的安裝檔。注意 PuTTY Agent 還是在 32bit 模式下運作,所以你也應該安裝 32bit 的 OpenSC。

接著是下載 PuTTY SC 以及對應的 PuTTY Agent,這是支援 PIV 智慧卡的版本。執行後你可以在 SSH 設定中找到 Pkcs11 的設定選項。

在 PuTTY SC 中設定智慧卡

在 PKCS#11 Library 這個選項中要填入 opensc-pkcs11.dll 的位置,預設是安裝在 C:\Windows\SysWOW64 底下。填入正確位置後,PuTTY 會試圖讀取智慧卡,這時只要把 Yubikey 插進 USB,在 Certificate label 即可選擇你要用來進行 SSH 認證的金鑰欄位。

把這些設定寫入 default settings,接著執行 pageantsc.exe,你會發現右下角出現了一個戴帽子電腦的圖示,表示 PuTTY Agent 已經在運作了。對著圖示按下右鍵選擇 View Keys 之後,便能列出它目前讀取到的金鑰列表。

PuTTY Agent

現在你可以使用任何支援 PuTTY Agent 的 SSH 用戶端來連接 SSH 主機了。包括 PieTTY 或是 WinSCP,它們會向 PuTTY Agent 查詢金鑰,而 PuTTY Agent 則操作 Yubikey,並提示使用者輸入 pin 碼。

WinSCP

使用 Yubikey 取代所有 Linux 密碼認證

如果安裝 PAM 模組,你甚至可以用智慧卡認證取代所有需要輸入密碼的地方,包括從主控台登入以及 sudo 的密碼認證。設定上也非常容易,首先是安裝 pam-p11 這個簡易的 PAM 模組:

1
$ sudo apt-get install libpam-p11

注意 編輯 PAM 設定檔前請先備份原檔,並且保留 root shell,免得你搞砸了又登不進去。

接著是修改 PAM 設定檔。Debian 會把共用認證設定寫在 /etc/pam.d/common-auth,因為我們需要修改這個檔案。你的 distribution 可能會寫在其它位置,不過通常都會放在 /etc/pam.d 底下。

找到設定檔後,追加一行如下:

1
auth sufficient pam_p11_openssh.so /usr/lib/x86_64-linux-gnu/opensc-pkcs11.so

同樣的,最後面的參數是 opensc-pkcs11.so 的路徑,請自行改為你系統上正確的安裝位置。

pam_p11_openssh.so 採用與 ssh 完全相同的認證方式,也就是直接去看使用者目錄內的 .ssh/authorized_keys。因此只要複製一份前面的 authorized_keys,你就可以試著執行 sudo,看看它是否提示你輸入 PIN:

1
2
$ sudo -s
Enter PIN for 'PIV_II (PIV Card Holder pin)':

這表示你已經可以使用 Yubikey 來取代密碼認證了。

設定 Management Key

若不設定 management key,yubico-piv-tool 會自動採用預設的 management key 進行操作,等於是允許 Yubikey 可任意寫入。除非心臟夠大顆,不然還是設定一下吧:

1
2
$ xxd -p -l 24 /dev/random mgm-key.hex
$ yubico-piv-tool -a set-mgm-key -n $(cat mgm-key.hex)

好好保存 mgm-key.hex 這個檔案,之後如果你要產生新的金鑰對,就需要這組密碼了。

問答時間

既然智慧卡是一把鑰匙,為什麼使用它之前我還要輸入 PIN 碼?

如果它被偷走,PIN 碼是保護密鑰的最後手段。

既然最後都要輸入密碼,那為什麼還要用智慧卡?

  1. 智慧卡必需要同時有硬體及 PIN 碼才能使用,與單純使用密碼相較多了一層保護。
  2. 換密碼考驗你的記憶力,但是換智慧卡中的私鑰則相當輕鬆。
  3. 密碼外洩你可能毫無所悉,但智慧卡搞丟會讓你馬上警覺到。

我有密碼輸入障礙,能不能設空白的 PIN?

如果真的有特殊需求,你可以把密鑰存在 9e 這個欄位,依照 PIV 標準,這個欄位的金鑰不需 PIN 碼即可使用,詳情可參考 Yubico 的說明文件

這可以用來登入 Windows 嗎?

Windows 支援 PIV 智慧卡認證,但前提是你的電腦有加入 Active Directory。一般家庭使用者應該沒這麼閒,但在企業環境中倒是相當實用。

分享到 評論