Azure IoT Hub X.509証明書によるデバイス認証
やりたいこと
前回の続き。今度はAzure IoT HubでX.509証明書を使ってデバイスを認証したい。
Azure IoT Hub側
デバイスは登録後に認証方法を変えられないみたいなので、新しいデバイス登録を登録する。認証の種類は「X.509 CA署名済み」を選択。
次にCA証明書を登録する。前々回作ったオレオレ認証局の鍵と証明書を使い回そう。が、拡張子チェックがあるので.crt
は通らない。
ここは.pem
に直して登録しよう。ついでに「アップロード時に証明書の状態を確認済みに設定する」をチェックして、アップロード後の証明書の確認手順をスキップ。
クライアント側
keytool
コマンドでデバイスの秘密鍵と自己署名証明書を生成し、新しいキーストアを作成する。
$ keytool -keystore mykeystore -genkey -keyalg RSA -keysize 2048 -alias client キーストアのパスワードを入力してください: 新規パスワードを再入力してください: 姓名は何ですか。 [Unknown]: device0002 組織単位名は何ですか。 [Unknown]: 組織名は何ですか。 [Unknown]: 都市名または地域名は何ですか。 [Unknown]: Sendai 都道府県名または州名は何ですか。 [Unknown]: Miyagi この単位に該当する2文字の国コードは何ですか。 [Unknown]: JP CN=device0002, OU=Unknown, O=Unknown, L=Sendai, ST=Miyagi, C=JPでよろしいですか。 [いいえ]: y 90日間有効な2,048ビットのRSAのキー・ペアと自己署名型証明書(SHA256withRSA)を生成しています ディレクトリ名: CN=device0002, OU=Unknown, O=Unknown, L=Sendai, ST=Miyagi, C=JP
続いて証明書署名要求を作成する。
$ keytool -keystore mykeystore -certreq -alias client -keyalg RSA -file client.csr キーストアのパスワードを入力してください:
証明書署名要求にopenssl
コマンドで署名する。
$ openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client.crt -days 365 -sha256 Signature ok subject=/C=JP/ST=Miyagi/L=Sendai/O=Unknown/OU=Unknown/CN=device0002 Getting CA Private Key Enter pass phrase for ca.key:
署名された証明書をキーストアにインポートする。前もってCAの証明書をインポートしないとkeytoolエラー: java.lang.Exception: 応答から連鎖を確立できませんでした
が出るよ。
$ keytool -import -keystore mykeystore -file ca.crt -alias rootCA キーストアのパスワードを入力してください: 所有者: CN=rootCA 発行者: CN=rootCA シリアル番号: fad999777ea4f00a 有効期間の開始日: Fri Apr 01 14:01:33 JST 2022終了日: Fri Apr 08 14:01:33 JST 2022 証明書のフィンガプリント: SHA1: AC:34:65:2F:17:15:F2:A4:6A:96:05:31:B8:B6:6D:20:A6:6F:95:5B SHA256: AD:C6:DE:C2:F4:8E:1C:83:8D:92:EB:49:EE:1A:12:D2:87:8A:20:A3:6D:E1:A7:6E:07:CD:E6:F7:F1:A5:58:D1 署名アルゴリズム名: SHA256withRSA サブジェクト公開キー・アルゴリズム: 2048ビットRSAキー バージョン: 1 この証明書を信頼しますか。 [いいえ]: y 証明書がキーストアに追加されました
CAの証明書に続いて自身の証明書をキーストアにインポートする。
$ keytool -import -keystore mykeystore -file client.crt -alias client キーストアのパスワードを入力してください: 証明書応答がキーストアにインストールされました
実行
前回のクライアントプログラムのデバイスIDを変更して、パスワード(SASトークン)はコメントアウトする。最後に以下のシステムプロパティを付けて実行。
-Djavax.net.ssl.keyStore=mykeystore -Djavax.net.ssl.keyStorePassword=topsecret
上手く動いたようだ。
Published message. Delivered message.
ついでに確認
- 証明書で認証をする場合は、MQTT ConnectパケットのクライアントIDと証明書のCommon Nameが一致するかまでチェックするみたい。デバイスIDを変えて実行するとエラーになったよ。
- 証明書で認証するデバイスは、共有アクセスポリシーのキー(以下)を使ってSASトークン認証することはできない。