SHALO AUTHをGnuPGで使う

Masayuki Tanemura
Axell Corporation
Published in
20 min readJun 21, 2023

SHALO AUTH は 秘密鍵を安全・簡単に管理し、認証・デジタル署名・暗号化できるUSB セキュリティキーで、業界標準の PKCS #11 や FIDO U2F / CTAP1 に対応しています。

デジタル署名や暗号化はセキュアな電子メールの実現に必要で、 PGP や S/MIME といった暗号技術の標準規格が使われています。特に PGP は電子メールの他に Git のコミット署名にも使われています。

今回は、 PGP でデジタル署名・暗号化する際に SHALO AUTH に格納されている鍵を利用する方法を解説します。

PGPとセキュリティキー

PGP には秘密鍵をセキュリティキーに保存して運用するための規格(OpenPGP card specification) があります。残念なことに SHALO AUTH はこの規格に対応していません。

しかしGPLに基づいた PGP の実装である GnuPG (gpg) では PKCS #11 向けの追加モジュール gnupg-pkcs11-scd を導入することで SHALO AUTH をGnuPG 向けセキュリティキーとして使用できます。

OpenPGP cardと異なり、 gnupg-pkcs11-scd ではセキュリティキーへの鍵の保存はサポートされません代わりにセキュリティキーにすでに保存されている秘密鍵を PGP の秘密鍵として使用します。

インストール

gnupg-pkcs11-scd バージョン 0.9.2 まではセキュリティキーに ECC 鍵などRSA 以外の鍵が存在すると処理を中止してしまいます。
バージョン 0.10.0 以降では対応していない暗号方式の鍵がセキュリティキーに存在してもその鍵だけを無視して動作するように修正されているので、できればバージョン 0.10.0 以降をインストールしましょう。

まずは SHALO AUTH のユーザーマニュアルに従って、 SHALO Keyring とPKCS #11モジュールをインストールします。

次に Linux や macOS のパッケージ管理システムで gpg パッケージと gnupg-pkcs11-scd パッケージをインストールします。

例えば Ubuntu / Debian 環境では以下のようにしてインストールします。

sudo apt install gpg gnupg-pkcs11-scd

Windowsではソースコードからビルドする必要があります。
MSYS2のMingw64で Git for Windows の GnuPG 向けにビルドできますが、多くの作業が必要なので慣れていない方にはお勧めできません。

設定ファイルを作成する

GnuPG の設定ファイルは ~/.gnupg/gpg-agent.conf です。
このファイルを作成して以下の2行を入力します。各行のファイルパスは環境によって異なります。

scdaemon-program /usr/bin/gnupg-pkcs11-scd
pinentry-program /usr/bin/pinentry

scdaemon-program には gnupg-pkcs11-scd の絶対パスを指定します。pinentry-program にはパスフレーズ・PINを入力するときに使用する pinentry プログラムを指定します。

pinentry プログラムは環境に応じていくつか種類があります。 /usr/bin/pinentry-* を探して自分に合ったファイルを指定します。

次に gnupg-pkcs11-scd の設定ファイル ~/.gnupg/gnupg-pkcs11-scd.conf を以下の内容で作成します。

pin-cache 20
providers shalo
provider-shalo-library /usr/lib/libslpkcs11.so

pin-cache は入力したPINをキャッシュする秒数です。pin-cacheを指定しなければ gnupg-pkcs11-scd を終了するまでPINがキャッシュされます。

provider-shalo-library には SHALO AUTH の PKCS #11 ライブラリの絶対パスを指定します。

Windows の場合、 gnupg-pkcs11-scd.conf に入力するファイルパスには注意が必要です。 C:\Users\ログイン名\shalo_pkcs11\x64\slpkcs11-vc.dll のように Windows のパス表記で指定する必要があります。

PKCS#11 DLLのファイルパスは OpenSC の pkcs11-helper が処理します。Windows向け pkcs11-helper は Windows の API を直接使用するため、ファイルパスのようにOS毎に異なるものでは Windows の流儀に従います。

これらのファイルを作成した後は以下のコマンドを実行し、起動しているかもしれない gpg を終了させます。

gpgconf --kill all

SHALO AUTHにPGP鍵を用意する

SHALO Keyring を使って、 SHALO AUTH に RSA 4096 bit の鍵を新規作成します。 gnupg-pkcs11-scd は ver 0.10.0 では ECC 鍵に対応していません。

SHALO Keyringの鍵作成ダイアログ

ここで入力する有効期限は GnuPG には影響しません。

SHALO AUTHの鍵のKeygripを取得する

Keygrip とは GnuPG が RSA 鍵そのものを識別するための文字列です。先ほど SHALO Keyring で作成した RSA 鍵の Keygrip がわかれば、 GnuPG から SHALO AUTH の RSA 鍵を使えるようになります。

まず GnuPG のバックエンドプログラム gpg-agent と gnupg-pkcs11-scd の通信内容を確認します。ターミナルから次のように入力します。

gpg-agent --server gpg-connect-agent << EOF
RELOADAGENT
SCD LEARN
EOF

すると次のような情報が出力されます。

OK Pleased to meet you
gpg-agent[1039]: SIGHUP received - re-reading configuration and flushing cache
gpg-agent[1039]: reading options from '/c/Users/ログイン名/.gnupg/gpg-agent.conf'
OK
gnupg-pkcs11-scd[628.0]: accepting connection
gnupg-pkcs11-scd[628]: chan_0x0000000000000280 -> OK PKCS#11 smart-card server for GnuPG ready
gnupg-pkcs11-scd[628.0]: processing connection
gnupg-pkcs11-scd[628]: chan_0x0000000000000280 <- GETINFO socket_name
gnupg-pkcs11-scd[628]: chan_0x0000000000000280 -> ERR 79 Invalid data <Unspecified source>
gnupg-pkcs11-scd[628]: chan_0x0000000000000280 <- LEARN
gnupg-pkcs11-scd[628]: chan_0x0000000000000280 -> S SERIALNO D27600012401115031315F500F551111
gnupg-pkcs11-scd[628]: chan_0x0000000000000280 -> S APPTYPE PKCS11
S SERIALNO D27600012401115031315F500F551111
S APPTYPE PKCS11
gnupg-pkcs11-scd[628]: chan_0x0000000000000280 -> S KEY-FRIEDNLY 58C6AA3964248FC031C019E7B470ECA2273693B8 CN=PGP key on home
gnupg-pkcs11-scd[628]: chan_0x0000000000000280 -> S CERTINFO 101 AXELL\x20CORPORATION/SHALO\x20AUTH//home/4158544F4F4C4B45592331
gnupg-pkcs11-scd[628]: chan_0x0000000000000280 -> S KEYPAIRINFO 58C6AA3964248FC031C019E7B470ECA2273693B8 AXELL\x20CORPORATION/SHALO\x20AUTH//home/4158544F4F4C4B45592331
gnupg-pkcs11-scd[628]: chan_0x0000000000000280 -> OK
S KEY-FRIEDNLY 58C6AA3964248FC031C019E7B470ECA2273693B8 CN=PGP key on home
S CERTINFO 101 AXELL\x20CORPORATION/SHALO\x20AUTH//home/4158544F4F4C4B45592331
S KEYPAIRINFO 58C6AA3964248FC031C019E7B470ECA2273693B8 AXELL\x20CORPORATION/SHALO\x20AUTH//home/4158544F4F4C4B45592331
OK
gnupg-pkcs11-scd[628]: chan_0x0000000000000280 <- RESTART
gnupg-pkcs11-scd[628]: chan_0x0000000000000280 -> OK
gnupg-pkcs11-scd[628]: chan_0x0000000000000280 <- [eof]
gnupg-pkcs11-scd[628.0]: post-processing connection
gnupg-pkcs11-scd[628.0]: accepting connection
gnupg-pkcs11-scd[628.0]: cleanup connection

この出力内容から S KEY-FRIEDNLY で始まる行を見つけてください。
出力例だと以下の一行です。

S KEY-FRIEDNLY 58C6AA3964248FC031C019E7B470ECA2273693B8 CN=PGP key on home

ここで KEY-FRIDENDLY に続く40文字の文字列 58C6AA3964248FC031C019E7B470ECA2273693B8 が Keygrip です。

SHALO AUTH に複数個の鍵が存在する場合、 S KEY-FRIENDLY は複数表示されます。鍵の名前が CN= に続いて表示されるので、それを手がかりに PGP で使用する鍵の Keygrip を特定します。

SHALO AUTHの鍵をGnuGPの鍵にする

Keygripが特定できたので、GnuGPから使えるようにします。
まず以下を実行してgpg-agentにスマートカードデーモンを強制的に起動させます。

gpg --card-status

次に以下を実行してPGP鍵を作成します。

gpg --expert --full-generate-key

以下のように出力され、作成する鍵の種類を聞かれます。

gpg (GnuPG) 2.2.19; Copyright (C) 2019 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Please select what kind of key you want:
(1) RSA and RSA (default)
(2) DSA and Elgamal
(3) DSA (sign only)
(4) RSA (sign only)
(7) DSA (set your own capabilities)
(8) RSA (set your own capabilities)
(9) ECC and ECC
(10) ECC (sign only)
(11) ECC (set your own capabilities)
(13) Existing key
(14) Existing key from card
Your selection? 13

ここで 13 を入力して Existing keyを指定します。
ちなみに、13を指定するとスマートカードデーモンを起動しないため、最初に起動させています。

副鍵の作成する場合も、SHALO AUTHの鍵を使用する場合は Existing key を選択することを覚えておいてください。

Enter the keygrip: 58C6AA3964248FC031C019E7B470ECA2273693B8

SHALO AUTHの鍵に対応する Keygrip を入力します。

Possible actions for a RSA key: Sign Certify Encrypt Authenticate
Current allowed actions: Sign Certify Encrypt

(S) Toggle the sign capability
(E) Toggle the encrypt capability
(A) Toggle the authenticate capability
(Q) Finished

Your selection? q

鍵の用途を指定します。このままで特に問題は無いので q を入力します。

Please specify how long the key should be valid.
0 = key does not expire
<n> = key expires in n days
<n>w = key expires in n weeks
<n>m = key expires in n months
<n>y = key expires in n years
Key is valid for? (0) 0
Key does not expire at all
Is this correct? (y/N) y

PGP 鍵の有効期限を指定します。ここでは無期限にしています。

GnuPG needs to construct a user ID to identify your key.

Real name: SHALO Test
Email address: example@foo.bar
Comment:
You selected this USER-ID:
"SHALO Test <example@foo.bar>"

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o

ユーザーIDとメールアドレスを入力し、oを入力します。
すると gpg-agent.conf の pinentry-program で指定したプログラムが起動するので SHALO AUTH のユーザーPINを入力します。

pinentry-w32.exeのPIN入力ダイアログ

PIN認証が成功すると、SHALO AUTHの鍵を使う PGP 鍵が作成されます。

gpg: revocation certificate stored as '/c/Users/tester/.gnupg/openpgp-revocs.d/65D5DB11957CB9C297452B34705BFE3F58EABA28.rev'
public and secret key created and signed.

pub rsa4096 2023-06-19 [SCE]
65D5DB11957CB9C297452B34705BFE3F58EABA28
uid SHALO Test <example@foo.bar>

PGP 鍵のなかには RSA 秘密鍵の実体は含まれません。 PGP 鍵を使って署名する際には SHALO AUTH が必要です。

複数の PC で同じ PGP 鍵を運用する場合、それぞれの PC で上記手順を行うと異なる PGP 鍵になってしまいます。1つの PC で PGP 鍵を作成した後に PGP 鍵をエクスポートし、他の PC でインポートするといいでしょう。

署名・検証してみよう

PGP 鍵でテキストにクリアサイン(メッセージと署名を1つの ASCII ファイルにする)してみましょう。

gpgコマンドに -u オプションで署名するユーザーIDを指定します。署名する際に SHALO AUTH を PC に装着することを忘れずに。

echo -n "Hello world with SHALO AUTH" | gpg --clearsign --textmode -u "SHALO Test" --output sign.txt

PINを入力すると署名され、 sign.txt ファイルが作られます。

$ cat sign.txt
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

Hello world with SHALO AUTH
-----BEGIN PGP SIGNATURE-----

iQJEBAEBCAAuFiEEZdXbEZV8ucKXRSs0cFv+P1jquigFAmSQOOMQHGV4YW1wbGVA
Zm9vLmJhcgAKCRBwW/4/WOq6KC9LEADbwD9PA07a+SEW1i38tOQRP8Bj/+5wc+mC
ZU7CPQ0l0La8T0mJ4e46DdduWGTEOXSTPbnqisP6GQAOXnLGSiHIGoarojBgP/va
DXm5GmbmjEKPPSS2gxEwFiWx0UzYGiBFsZkg/2VDXGG/QkxNxM61/d1QQuIo2Lu6
EnnO7eivIbM+c09cGfzH99WgMilwxWafE6qSECig+yZ8+GslW/sbNYpXQXmR/LRN
6tARqhKxJB5UZyHpx0oFerD5Yvu/G2Xg76sc926TUInodotznaSWgF6LQT18szhg
VCYgLVuxzMzlzmHMbKMNRNts0Cvc3n6aBnjcPefFoPJFnDe978XDlnSxjitWgNsG
Ak+UWwKWS+BryPQVO3Six/DqgSBdX/D7pxtctgHv3ZfEhPzXLgoyR4WO2+o76D89
ulfMm4m38iNVpLooKdJXIXpawhEHplA34D248qqvsw0csOAPA+/q0qnI0aNMKPBM
j2q3cxO3uaRA7s87v8KbI+wxHrZRXcr17u+KsHkE8T0VHhk4pIwy5LCiFgzInsxq
CRJXe/tGSBIFi7qq07xMl9FBug+QYiROpz8snK1j8I3HpwK23FoqZbCUesXnR2Zm
iAaRfsaBeCfmMgGWazDkleEzkPein7TO1cebSxpkUeJMTocvQkd1Kdg4caDOTeW0
Qfz0fy5hwg==
=0R4C
-----END PGP SIGNATURE-----

今度は逆に sign.txt ファイルの署名を検証します。

$ gpg --verify sign.txt
gpg: Signature made Mon Jun 19 20:15:47 2023
gpg: using RSA key 65D5DB11957CB9C297452B34705BFE3F58EABA28
gpg: issuer "example@foo.bar"
gpg: Good signature from "SHALO Test <example@foo.bar>" [ultimate]

暗号化・復号してみよう

gpgコマンドに -r オプションで受信者を指定して暗号化します。受信者の公開鍵しか使わないので SHALO AUTH は必要ありません。

使用例なので受信者に” SHALO Test”(つまり秘密鍵を持っている自分宛です)を指定します。

$ echo -n "Hello world with SHALO AUTH" | gpg --armor --encrypt --textmode -r "SHALO Test" --output msg.enc
$ cat msg.enc
-----BEGIN PGP MESSAGE-----

hQIMA3Bb/j9Y6rooAQ/+Ksa6LuVCPDNfYMHWzG17z1z5/frUdmiQRTmLrRre5pEE
TMtHhm2X7Ub3qwq8DejCZ1z0pm2qkH1H2qNnk6qdQHBbtsF0wn0vkPzXZQjEq8PK
eYXUb9sOOqmHENo2li+/nWKvw/+qJOvTKa4XEcWHYLXdVYxQO7tzoqKpVZs7+C+9
i7ql/Y8Je+hBFgdpE66A/Bqb8iD0qkLZHq/0mz5vS8nL6PRNnleJG6adNgpm3KnK
GImVwqlRC8BA5yy++HyN5144+51piArVeB3D3hnOnL+S+MdJyiRhJALhz1tJZRSY
P3Zt5m/QJ3cD8RDBQvOmm/wHMrMYHEMVsohlJi4ID8xoy4Wi3YUCbt6kbELX+upG
B4/+D3ATwfFXrhgOoIN66oX4GCUKqVT1AwmxT/3BC75ILnkiFuWcUWmVhUoCwnAT
6C7fMzD+a9WP2Y9rtnovqNGbrJLeOljPzPC5iPoaMfozQVJYqF14UfAL19+42CO6
u3sKp8CWFDFgrangMkBZA3BdA3RjLAwSL7ehIkHJT9LTZWKNEAVxF1hfBG9ilUKp
5KAxFB4kNL142vi7RY3sIQQuyDOJC/qPE9ieQsq89Xjh8BFhzxjrGcoAHnZE+/0o
a6EhG2g/5ObTz8q5EI0bNIHLBRpvRJuYvLTQ66LzZRX4ZuHMZjWt80M0GJh8AFTS
VgEGVYB9qnPZBa3GSEkzfc9w+kEaZTP+QFw+Y5pSxZFv80Gl5uJM8vkc5bH9tfgv
vj5lkoj05RfgwHWgg5dlT76cB0BTv4/+267nODnVFu8od+OzZORe
=U9RL
-----END PGP MESSAGE-----

プレーンテキストでメール本文にこのメッセージを貼って送る方式をPGP/Inlineと呼びます。

自分宛にこのメッセージが送られてきたと想定して復号しましょう。復号には SHALO AUTH が必要です。
SHALO AUTH を PC に装着してから以下を実行します。

gpg --decrypt -u "SHALO Test" msg.enc

PINを入力すると次のように出力され、正しくメッセージが復号されていることがわかります。

gpg: encrypted with 4096-bit RSA key, ID 705BFE3F58EABA28, created 2023-06-19
"SHALO Test <example@foo.bar>"
Hello world with SHALO AUTH

OpenPGP / GnuGP に馴染みがないと PGP 鍵の作成が難しいと思ったかもしれません。実際には普通のPGP鍵の作成方法と比べてKeygripの特定するステップが増えただけです。それも一度作成してしまえば暗号化・署名などでの PGP 鍵の利用方法に違いはありません。

今回紹介しませんでしたが、 PGP 鍵を元に役割毎にPGP副鍵を作るなど柔軟な鍵管理・運用が可能です。興味を持った方はGnuPGでSHALO AUTHを活用してみてください。

--

--