ブログに書くつもりじゃなかった

フリーのプログラマーが綴る、裏チラ系の備忘録や雑記帳。

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トークン認証することはできない。