USBトークンとは?

 形はUSBフラッシュメモリに似ていますが、内部にCPUやEEPROMを搭載した特殊なデバイスで、別の形として、接触型・非接触型ICカード(スマートカード)などがあります。トークン内部でキーペアの生成などの暗号処理ができ、格納された秘密鍵を使用するためには、PINや生体認証を使用します。PINの入力に失敗した場合、ロックさせる機能や、デバイスを破壊して、情報を盗むようなことをすると、自動的に秘密情報を消去するような仕組み(耐タンパ性)を持つことが特徴です。これらを、「(暗号処理機能付き)ハードウェア・トークン」や「セキュリティ・トークン」と呼びます。

 認証システムの要素として、 

 Something You Know・・・その人しか知り得ない知識(パスワード・PIN)
 Something You Have・・・その人しか持ち得ない物(社員証・住民基本台帳カードなど)
 Something You Are ・・・その人自身の情報(指紋・掌紋など生体認証情報など)

 がありますが、上記2つの要素を組み合わせることで、よりセキュアになります。このことを二要素認証 (Two-Factor Authentication)といい、ハードウェア・トークンはこれを実現することができます。

 今回、ハードウェア・トークンであるAladdin eToken PRO を使って、実験を行いました。

Debian Linux にOpenSCをインストールする

LinuxでICカードやUSBトークンにX.509 ディジタル証明書やRSA 秘密鍵などの暗号クレデンシャルを格納するには、オープンソースのミドルウェアOpenSC が使用できます。

購入したスマートカードリーダやUSBトークンに、Linux用のドライバが付属していない場合があると思います。

OpenCT (スマートカードリーダ用ドライバ類)は、eTokenなど、メジャーなスマートカードリーダやUSBトークンに対応しています。

 

 

 

まず、トークン内でRSAキーペアを生成し、自己署名証明書を格納してみます。

準備 

  • インストール

debian etchでは以下のコマンドでインストールできます。

# apt-get install opensc openct pcscd
あと、libopenct1 libusb libopensc2 も必要かもしれません。opensslコマンドをUSBトークン上で行うため、openssl と libopensc-openssl もインストールしておきます。
<セキュリティ情報>
OpenSCに脆弱性 JPSERT 2008月27日号
OpenSC 0.11.5 より前のバージョンをお使いの方は、修正済みのバージョンに更新して下さい。
  • デバイスの確認
eTokenをUSBポートに挿すと、赤く点灯します。
#lsusb
Bus 005 Device 001: ID 0000:0000
Bus 003 Device 001: ID 0000:0000
Bus 002 Device 002: ID 0529:0600 Aladdin Knowledge Systems
Bus 002 Device 001: ID 0000:0000
Bus 004 Device 001: ID 0000:0000
Bus 001 Device 001: ID 0000:0000
デバイスがきちんと認識されているようです。
  • スマートカードリーダ番号の確認
# opensc-tool --list-readers
Readers known about:
Nr.    Driver     Name
0      openct     Aladdin eToken PRO 64k
1      openct     OpenCT reader (detached)
2      openct     OpenCT reader (detached)
3      openct     OpenCT reader (detached)
4      openct     OpenCT reader (detached)

今回リーダ番号は0で認識されています。0以外のときは、各コマンドでリーダ番号を指定する必要があります。

例) 

# opensc-tool --reader 1 --name
CardOS M4

キーペアの生成からディジタル証明書の格納まで

トークン管理ユーザをscardグループに追加します。以降、rootでなくても作業可能です。

# adduser <hoge> scard

  • トークンの中身を消去する (ブランクカードの場合は省略)
$ pkcs15-init --erase-card
PIN [Security Officer PIN] required.
Please enter PIN [Security Officer PIN]:
PIN [Security Officer PIN] required.
Please enter PIN [Security Officer PIN]:

ここでエラーになってしまう場合は、付属のトークン管理ツール
(Aladdin eTokenでは、Windows版 eToken RTE 3.65) でイニシャライズし,ブランクカードの状態にします。(トークン内に格納されている証明書など、すべて削除されてしまうので注意してください)

  • トークンの初期化と管理者PINの設定
$ pkcs15-init --create-pkcs15
New Security Officer PIN (Optional - press return for no PIN).
Please enter Security Officer PIN:
Please type again to verify:
Unblock Code for New User PIN (Optional - press return for no PIN).
Please enter User unblocking PIN (PUK):
Please type again to verify:
これで、USBトークン内にPKCS#15用のディレクトリが作成され、RSAキーペアやディジタル証明書を格納するための領域が確保されました。 
  • ユーザPINの設定 (必須) 
$ pkcs15-init --store-pin --auth-id 01 --label "Test User"
New User PIN.
Please enter User PIN:
Please type again to verify:
Unblock Code for New User PIN (Optional - press return for no PIN).
Please enter User unblocking PIN (PUK):
Please type again to verify:
Security officer PIN required.
Please enter Security officer PIN:
ユーザPINは8文字以内で設定して下さい。(eTokenの場合) また、auth-id 01 は必須です。 
  • RSAキーペアの生成
$ pkcs15-init --generate-key rsa/1024 --auth-id 01
Security officer PIN required.
Please enter Security officer PIN:
User PIN required.
Please enter User PIN:
Security officer PIN required.
Please enter Security officer PIN:
eToken 64k は、RSA/2048bitキーに対応していますが、ここでは、1024bitで生成しています。
$ pkcs15-tool --list-keys
Private RSA Key [Private Key]
Com. Flags : 3
Usage : [0x4], sign
Access Flags: [0x1D], sensitive, alwaysSensitive, neverExtract, local
ModLength : 1024
Key ref : 16
Native : yes
Path : 3f005015
Auth ID : 01
ID : 45
USBトークン内にRSA秘密鍵、RSA公開鍵がキーID:45として、格納されました。 
  • opensslをトークンで使用できるようにする
$openssl
OpenSSL> engine dynamic -pre SO_PATH:/usr/lib/engines/engine_pkcs11.so \
-pre ID:pkcs11 -pre LIST_ADD:1 -pre LOAD \
-pre MODULE_PATH:opensc-pkcs11.so
(dynamic) Dynamic engine loading support
[Success]: SO_PATH:/usr/lib/engines/engine_pkcs11.so
[Success]: ID:pkcs11
[Success]: LIST_ADD:1
[Success]: LOAD
Loaded: (pkcs11) pkcs11 engine
OpenSSL>
Opensslからpkcs#11を通してUSBトークンを操作できるようになりました。
(openssl.confを編集しておく方法もあります。) 
  • 証明書要求~自己署名証明書の作成 
OpenSSL> req -engine pkcs11 -new -key id_45 -keyform engine -out req.pem -text -x509
engine "pkcs11" set.
PKCS#11 token PIN:
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:JP
State or Province Name (full name) [Some-State]:kanagawa
Locality Name (eg, city) []:sagamihara
Organization Name (eg, company) [Internet Widgits Pty Ltd]:clustcom
Organizational Unit Name (eg, section) []:
Common Name (eg, YOUR name) []:Test User
Email Address []:このメールアドレスはスパムボットから保護されています。閲覧するにはJavaScriptを有効にする必要があります。
OpenSSL>
OpenSSL> q
カレントディレクトリに証明書要求ファイル(req.pem)が保存されました。このファイルをベリサインなどのCAに送って署名をしてもらうこともできます。 
  • ディジタル証明書をトークンに格納する
$ pkcs15-init --store-certificate req.pem --auth-id 01 --id 45 --format pem
User PIN required.
Please enter User PIN:
Security officer PIN required.
Please enter Security officer PIN:
ここで、auth-id と (キー)id 45 は、キーの生成時の値と一致させる必要があります。 
  • トークンの中身を確認
$pkcs15-tool --dump
PKCS#15 Card [OpenSC Card]:
        Version        : 1
        Serial number  : 2556CE140420
        Manufacturer ID: OpenSC Project
        Last update    : 20081127174631Z
        Flags          : EID compliant
PIN [Security Officer PIN]
        Com. Flags: 0x3
        ID        : ff
        Flags     : [0xBA], local, unblock-disabled, initialized, needs-padding, soPin
        Length    : min_len:6, max_len:8, stored_len:8
        Pad char  : 0x00
        Reference : 1
        Type      : ascii-numeric
        Path      : 3f005015
PIN [Test User]
        Com. Flags: 0x3
        ID        : 01
        Flags     : [0x3A], local, unblock-disabled, initialized, needs-padding
        Length    : min_len:4, max_len:8, stored_len:8
        Pad char  : 0x00
        Reference : 3
        Type      : ascii-numeric
        Path      : 3f005015
Private RSA Key [Private Key]
        Com. Flags  : 3
        Usage       : [0x4], sign
        Access Flags: [0x1D], sensitive, alwaysSensitive, neverExtract, local
        ModLength   : 1024
        Key ref     : 16
        Native      : yes
        Path        : 3f005015
        Auth ID     : 01
        ID          : 45
Public RSA Key [Public Key]
        Com. Flags  : 2
        Usage       : [0x4], sign
        Access Flags: [0x0]
        ModLength   : 1024
        Key ref     : 0
        Native      : no
        Path        : 3f0050153048
        Auth ID     :
        ID          : 45
X.509 Certificate [Certificate]
        Flags    : 2
        Authority: no
        Path     : 3f0050153149
        ID       : 45
以上で、ひととおりの作業が完了しました。 
  • トークンのテスト
$pkcs11-tool --login --test
Please enter User PIN:

ユーザPINを入力すると、テスト結果が表示されます。得にエラーがでていなければ、問題ないでしょう。

PKCS12形式ファイルのインポート

前回の実験で作成した pkcs#12形式ファイルをインポートしてみます。

$ pkcs15-init --store-private-key newcert.p12 --format pkcs12 --auth-id 01
error:23076071:PKCS12 routines:PKCS12_parse:mac verify failure
Please enter passphrase to unlock secret key:
Importing 1 certificates:
  0: /C=JP/O=clustcom/CN=User8
Security officer PIN required.
Please enter Security officer PIN:
User PIN required.
Please enter User PIN:
Security officer PIN required.
Please enter Security officer PIN:

インポートできましたがエラーが表示されています。

$ pkcs15-init --store-private-key newscert.p12 --format pkcs12 --passphrase XXXXX --auth-id 01
Importing 1 certificates:
  0: /C=JP/O=clustcom/CN=User8
Security officer PIN required.
Please enter Security officer PIN:
User PIN required.
Please enter User PIN:
Security officer PIN required.
Please enter Security officer PIN:

このように、--passphrase XXXXXを指定すると、エラー表示はなくなりました。 

クライアントから接続してみる

Firefoxの「ツール」→「オプション」→「暗号化」→「セキュリティデバイス」を選択。(Debian のiceweaselの場合は、「編集」→「設定」→「詳細」→「暗号化」

「セキュリティデバイス」の「追加」でPKCS#11モジュールを選択します。Debianの場合は、/usr/lib/opensc/opensc-pkcs11.soを指定し、Windowsの場合は、OpenSCのWindows版 scb-0.10.exe をインストールし、C:\Program Files\Smart card bundle\opensc-pkcs11.dllを指定します。(windows用のトークンドライバも必要です。)

PINを入力すると、トークン内にアクセスできます。

サーバに接続すると、証明書の選択画面が表示されますので、使用する証明書を選択すると、クライアント認証で接続することができました。以下の図は Wireshark というスニファでパケットをキャプチャーしたものです。(注意! 自管理下以外のネットワークで実験しないて下さい)

パケットの説明

クライアント(192.168.20.1)、 サーバ(192.168.20.150)

No19からNo27まで、証明書の交換や暗号方式の選択と、データの暗号化に使用する共通鍵の生成と受け渡しが行われています。

No28から暗号化したデータの通信が行われています。

もしも証明書になんらかの問題がある場合は、 Alert Message がサーバから通知されます。

正当なクライアント証明書を持っていない場合は、接続することはできません。

まとめ

このように、USBトークンから秘密鍵は一切外にでることはなく、サーバとセキュアに通信することができます。また、秘密鍵にアクセスするためには、PINの入力が必要であり、トークン内で秘密鍵の生成~署名処理までが行われるため、セキュリティレベルが向上します。

物理的な実体であるUSBトークンは、所有者が紛失・盗難に気づく可能性が高く、即座に証明書を失効させれば、危険にさらされる時間は短時間で済みます。

参考

電子認証に関するガイドライン

 

OpenSCOnDebian