GnukのEmulation mode

Pocket

2021/3/10 FSIJセミナーで解説されたのでメモ

これでできること:

  • 実物のGnukを使わない動作テスト
    • 鍵生成などは失敗すると最悪なにもできなくなるので練習ができる

事前に必要なもの

  • scdaemon
  • usbip
  • python3-cffi,
  • python3-pytest

ソースコードの準備とビルド手順、起動まで

別のターミナルを開き、vhci, usbipを用いてUSBデバイスとして扱えるようにする

$ git clone -b STABLE-BRANCH-1-2 git://git.gniibe.org/gnuk/gnuk.git
$ cd gnuk && git submodule update --init
$ cd src
$ ./configure --target=GNU_LINUX --enable-factory-reset
$ make
$ cd build
$ ./gnuk --vidpid=234b:0000
Gnuk (emulation with USBIP), a GnuPG USB Token implementation
Copyright (C) 2021 Free Software Initiative of Japan
This is free software under GPLv3+.
USBIP thread started.
You can use this by attaching following commands:
    # modprobe vhci_hcd
    # usbip attach -r 127.0.0.1 -b 1-1
User interaction thread for AckBtn started.
$ sudo modprobe vhci_hcd
$ sudo usbip attach -r 127.0.0.1 -b 1-1
$ lsusb | grep 234b
Bus 005 Device 002: ID 234b:0000
$ lsusb -t
(略)
/:  Bus 05.Port 1: Dev 1, Class=root_hub, Driver=vhci_hcd/15p, 480M
    |__ Port 1: Dev 2, If 0, Class=Chip/SmartCard, Driver=, 12M
(略)

テストの動作

$ cd ../../tests
$ pytest3 -x
============================= test session starts ==============================
platform linux -- Python 3.7.3, pytest-3.10.1, py-1.7.0, pluggy-0.8.0
rootdir: /home/knok/gnuk/tests, inifile:
collected 416 items

test_000_empty_card.py ..............................                    [  7%]
(略)
test_025_kdf_none.py ...                                                 [100%]

========================= 416 passed in 12.17 seconds ==========================

gpgでカードとして扱う

PINはadmin: 12345678, 通常 123456

  • 初期化 (factory-reset)
  • 新規鍵生成 (generate)
    • 内容は ~/.gnuk-flash-image に保存される
  • 作成した鍵で暗号化 (gpg -e)
$ gpg --edit-card

Reader ...........: 234B:0000:FSIJ-1.2.17-EMULATED:0
Application ID ...: D276000124010200FFFEF1420A7A0000
Version ..........: 2.0
Manufacturer .....: unmanaged S/N range
Serial number ....: F1420A7A
Name of cardholder: [未設定]
Language prefs ...: [未設定]
Sex ..............: 無指定
URL of public key : [未設定]
Login data .......: [未設定]
Signature PIN ....: 強制
Key attributes ...: rsa2048 rsa2048 rsa2048
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 3 3
Signature counter : 0
KDF setting ......: off
Signature key ....: [none]
Encryption key....: [none]
Authentication key: [none]
General key info..: [none]

gpg/card> admin
gpg/card> factory-reset
gpg: OpenPGPカードno. D276000124010200FFFEF1420A7A0000を検出

gpg: 注意: このコマンドはカードに保管してあるすべての鍵を破壊します!

続けますか? (y/N) y
工場出荷リセットを行いますか? (本当なら "yes" と入力) yes

gpg/card> key-attr
こちらのカード鍵の属性を変更します: 署名鍵
ご希望の鍵の種類を選択してください:
   (1) RSA
   (2) ECC
あなたの選択は? 2
ご希望の楕円曲線を選択してください:
   (1) Curve 25519
   (4) NIST P-384
あなたの選択は? 1
カードは、今、こちらのタイプの鍵を生成するように再コンフィグされます: ed25519
注意: カードが要求された鍵長をサポートしているという保証はありません。
      鍵生成が成功しない場合、あなたのカードに関する技術文書を確認し、
      利用できる鍵長について確認ください。
こちらのカード鍵の属性を変更します: 暗号化鍵
ご希望の鍵の種類を選択してください:
   (1) RSA
   (2) ECC
あなたの選択は? 2
ご希望の楕円曲線を選択してください:
   (1) Curve 25519
   (4) NIST P-384
あなたの選択は? 1
カードは、今、こちらのタイプの鍵を生成するように再コンフィグされます: cv25519
こちらのカード鍵の属性を変更します: 認証鍵
ご希望の鍵の種類を選択してください:
   (1) RSA
   (2) ECC
あなたの選択は? 2
ご希望の楕円曲線を選択してください:
   (1) Curve 25519
   (4) NIST P-384
あなたの選択は? 1
カードは、今、こちらのタイプの鍵を生成するように再コンフィグされます: ed25519

gpg/card> generate
暗号化鍵のカード外バックアップを作成しますか? (Y/n) n

工場設定のPINは下記のとおり
   PIN = '123456'     管理者PIN = '12345678'
次のコマンドを使って変更すべきです --change-pin

鍵の有効期限を指定してください。
         0 = 鍵は無期限
      <n>  = 鍵は n 日間で期限切れ
      <n>w = 鍵は n 週間で期限切れ
      <n>m = 鍵は n か月間で期限切れ
      <n>y = 鍵は n 年間で期限切れ
鍵の有効期間は? (0)
鍵は無期限です
これで正しいですか? (y/N) y

GnuPGはあなたの鍵を識別するためにユーザIDを構成する必要があります。

本名: Test User
電子メール・アドレス: test@example.org
コメント:
次のユーザIDを選択しました:
    "Test User <test@example.org>"

名前(N)、コメント(C)、電子メール(E)の変更、またはOK(O)か終了(Q)? o
gpg: 鍵B805A9C910609E90を究極的に信用するよう記録しました
gpg: 失効証明書を '/home/knok/.gnupg/openpgp-revocs.d/70486A8D5034085FCFE80844B805A9C910609E90.rev' に保管しました。
公開鍵と秘密鍵を作成し、署名しました。

gpg/card> quit
pub   ed25519 2021-03-10 [SC]
      70486A8D5034085FCFE80844B805A9C910609E90
uid                      Test User <test@example.org>
sub   ed25519 2021-03-10 [A]
sub   cv25519 2021-03-10 [E]

$ gpg -o /tmp/encrypt.gpg -r test -e /etc/motd
gpg: 信用データベースの検査
gpg: marginals needed: 3  completes needed: 1  trust model: pgp
gpg: 深さ: 0  有効性:   2  署名:   0  信用: 0-, 0q, 0n, 0m, 0f, 2u
gpg: 次回の信用データベース検査は、2021-10-06です

追記(2020-03-12) Facebookでg新部さんよりいくつかご指摘いただきました

  • encryptでは秘密鍵を使わない(のでここはテストになっていない)
  • Debian 10 (Buster)のGnuPG 2.2.12では復号化に失敗する。2.2.27では問題ないとのこと
  • Gnuk 1.2.17時点で鍵生成にバグがある。今は修正がpushされている

By knok

I am a Debian Developer and a board member of Free Software Initiative (FSIJ).