OpenSCでThales eToken 5110上にキーペアを生成してCSRを提出する
この記事は、既に手元にあるThales製のSafeNet eToken 5110 CC (940)上に、OpenSCを用いて新しくキーペア(秘密鍵及び公開鍵)及びCSR(Certificate Signing Request)を生成する方法を紹介します。
SafeNet eToken 5110
eToken 5110シリーズは、USBトークンによるプロビジョニング方法を選んだ場合に、DigiCertやSectigoなどの様々な商用CA(Certificate Authority:認証局)が配送する物理USBトークンです。主に、HSM(Hardware Security Module)デバイス上で管理することが義務付けられているEV(Extended Validation)証明書をオーダーする際に、CAが配送するeTokenではなく、既に手元にある新品若しくは再利用としてのeTokenを使用したい場合に有効です。
特に、YubiKey 5のFIPSシリーズはRSA2048までしかサポートしておらず、Thales製のeTokenは重宝します。
OpenSC
OpenSCは、スマートカードを利用した認証や暗号化機能を提供するオープンソースのライブラリおよびツールセットです。PKCS#11、PKCS#15、ISO 7816 などの標準規格をサポートし、さまざまなスマートカードやセキュリティトークンと連携できます。今回は、PKCS#11を扱うことになります。
OpenSCのインストールについては、公式リポジトリのWikiを参考にしてください。
SafeNet Authentication Client
SAC(SafeNet Authentication Client)は、公開鍵暗号を基盤とした安全な情報交換を提供するPKI(公開鍵基盤)ミドルウェアです。
インストールについては、各CAのドキュメントを確認してください。SACのインストールには、OpenSCを介してeTokenを操作する際に必要なモジュールが含まれています。PKCS#11に関する操作では、SACインストール時に%system32%及びSysWOW64に配置されるeTPKCS11.dllが必要となります。
ハードウェアテスト
--testでハードウェアテストを行い、eTokenデバイスが正常に動作していることを確認します。
pkcs11-tool --module "eTPKCS11.dll" --test --login
Using slot 0 with a present token (0x0)
Logging in to "My Token".
Please enter User PIN: C_SeedRandom() and C_GenerateRandom():
seems to be OK
Digests:
all 4 digest functions seem to work
SHA-1: OK
SHA256: OK
Ciphers: not implemented
Signatures (currently only for RSA)
Signatures: no private key found in this slot
Verify (currently only for RSA)
No private key found for testing
Decryption (currently only for RSA)
No errors
キーペア生成
RSA4096のキーペア(秘密鍵及び公開鍵)を生成します。Private Key Objectのuriは後で必要になるのでメモしておきます。
pkcs11-tool --module "eTPKCS11.dll" --login --keypairgen --key-type RSA:4096 --label "csev" --id 01
Using slot 0 with a present token (0x0)
Key pair generated:
Private Key Object; RSA
label: csev
ID: 01
Usage: decrypt, sign, unwrap
Access: sensitive, always sensitive, never extractable, local
uri: pkcs11:model=ID%20Prime%20MD;manufacturer=Gemalto;serial=0000000000000000;token=My%20Token;id=%01;object=csev;type=private
Public Key Object; RSA 4096 bits
label: csev
ID: 01
Usage: encrypt, verify, wrap
Access: local
uri: pkcs11:model=ID%20Prime%20MD;manufacturer=Gemalto;serial=0000000000000000;token=My%20Token;id=%01;object=csev;type=public
--list-objectsで生成された秘密鍵オブジェクトの情報を確認できます。
pkcs11-tool --module "eTPKCS11.dll" --login --list-objects --type privkey
ここで、生成された秘密鍵をテストして正常に動作していることを再度確認します。
pkcs11-tool --module "eTPKCS11.dll" --test --login
CSRの生成
SACにはキーペアの生成やCSRの生成を行う機能はありません。ここからは、OpenSCとOpenSSLを用いて、それぞれキーペアとCSRを生成します。
OpenSSLについては、デフォルトでPKCS#11エンジンがサポートされていないため、個別にビルドする必要があります。
libp11のビルド(Win64)
git clone https://github.com/OpenSC/libp11.git
cd libp11
git checkout libp11-0.4.13
nmake /f Makefile.mak OPENSSL_DIR="C:/path/to/openssl" BUILD_FOR=WIN64
正常にビルドが終ると、src/に2つのDLLが生成されます。
Get-ChildItem -Name -Filter "src/*.dll"
libp11.dllとpkcs11.dllを任意の場所に配置します。ここでは、C:/libp11に配置します。
OpenSSLがこれらのモジュールを正常に読み込めていることを確認します。
openssl engine dynamic \
-pre "SO_PATH:C:\libp11\pkcs11.dll" \
-pre ID:pkcs11 -pre LIST_ADD:1 -pre LOAD \
-post "MODULE_PATH:C:\Program Files\OpenSC Project\OpenSC\pkcs11\opensc-pkcs11.dll"
OpenSSLにPKCS#11モジュールを追加
さらに、OpenSSLのbinにあるopenssl.cfgを編集します。個別のコンフィグファイルとして記述してコマンドラインで指定しても問題ありません。
%System32%にeTPKCS11.dllがあることを確認します。
+openssl_conf = openssl_init
+[openssl_init]
+engines = engine_section
+[engine_section]
+pkcs11 = pkcs11_section
+[pkcs11_section]
+engine_id = pkcs11
+dynamic_path = "C:\\libp11\\pkcs11.dll"
+MODULE_PATH = "C:\\Windows\\System32\\eTPKCS11.dll"
+init = 0
PKCS#11モジュールが問題なく認識されていることを確認します。
openssl engine -t
openssl engine pkcs11 -t
(pkcs11) pkcs11 engine
[ available ]
CSRを生成
生成した秘密鍵で署名されたCSRを生成します。-keyには秘密鍵へのuriを指定します。
openssl req \
-new \
-subj '/C=JP/ST=Tokyo/L=Shibuya/CN=My Company' \
-sha256 \
-engine pkcs11 \
-keyform engine \
-key "pkcs11:model=ID%20Prime%20MD;manufacturer=Gemalto;serial=0000000000000000;token=My%20Token;id=%01;object=csev;type=private" \
-out my.csr
証明書のマージ
CSRをCAに送り、これが署名されると、PEM形式の証明書がCAから送付されます。最後にこれをeTokenにマージします。
pkcs11-tool \
--module "eTPKCS11.dll" \
--login \
--write-object my.crt \
--type cert \
--label "csev" \
--id 01
署名
パワーシェルスクリプトを署名してみます。signtoolはデフォルトで最適な証明書を選択しますが、複数の証明書が存在する場合、/aで選択すべき証明書のsha1を明示的に指定します。
signtool \
sign \
/sha1 D6846A11501FDEB5B420B0C91C2C4572BDD8F035 \
/tr http://timestamp.digicert.com \
/td sha256 \
/fd sha256 \
my.ps1
正常に署名されていることを確認します。
echo "hello world"
# SIG # Begin signature block
# MIIhCAYJKoZIhvcNAQcCoIIg+TCCIPUCAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# ...
# SIG # End signature block
Discussion