ESP8266のWiFiClientSecure系でcertを扱う時のメモ

今、調べながら試しているけどchatgptに存在しないメソッド言われたりと騙されるっぽいのでメモを残す。終了

ESP8266(ESP-WROOM-02)の内容。ESP-WROOM-32ではないので注意。

環境

  • Windows11
  • Arfuino IDE 2.3.1
  • esp8266 by ESP8266 Community 3.1.2(レポジトリ)

動きそうなやつ(これから確認、動いたら記事修正する)

WiFiClientSecureBearSSL#setInsecure

基本こちらのまんまで動いた。(リンク先はESP8266でなくESP32なので他を参考にするときはクラス仕様違うので注意)

最初は戻り値にバイト数とか入ってたけどサーバ側でcontents-length指定していないのが原因だった。

BearSSL_Validation.ino

Example->Esp8266Wifiの中にいるサンプル。

単独のCAをツールでヘッダーファイルに変えて読み込むやつだと思う。

includeで気になった奴

#include <StackThunk.h>というのがある。(実装のcpp

StackThunk.c - Allow use second stack for BearSSL calls


  BearSSL uses a significant amount of stack space, much larger than
  the default Arduino core stack. These routines handle swapping
  between a secondary, user-allocated stack on the heap and the real
  stack.

BearSSLはスタックすごい使うからうんぬんと。通常のスタックだと足りないから、ヒープを使ってごにょごにょしてくれるらしい。

サンプルソースだと割り当て関連の機能は使っておらず使用量確認のみに見えるけど中で読んでいるかも。一見、足りてそうに見えるときも内部でこいつが使い切ってるとかはあるかもしれないので心に留めておく。

事前準備

cert.pyを使用して証明書のデータを更新。(長くなったのでこちら

フィンガープリントだけで接続

フィンガープリント設定すればとりあえずつながる。

何もないよりましだといっている

The SHA-1 fingerprint of an X.509 certificate can be used to validate it
instead of the while certificate.  This is not nearly as secure as real
X.509 validation, but is better than nothing.  

自己署名証明書で接続

allowSelfSignedCertすればOKとのこと。

こいつは自己署名は誰でも作れるから注意を(略

It is also possible to accept *any* self-signed certificate.  This is
absolutely insecure as anyone can make a self-signed certificate.

ハードコード公開鍵で接続

公開鍵をハードコードしておいてそいつを使って(通常のSSLは認証プロセスを飛ばして)通信できる。一般公開しないサービスならこれでもよさそうな気がする。

The server certificate can be completely ignored and its public key
hardcoded in your application. This should be secure as the public key
needs to be paired with the private key of the site, which is obviously
private and not shared.  A MITM without the private key would not be
able to establish communications.

certをハードコード方式(多分一番固い)

certをハードコードして検証する方式。

有効期限チェックはするけれどもCRLはサポートしていないらしい。発行された証明書が有効期限内に無効化されていてもチェックされない。自己署名証明書をルートにしたチェーンも作れるらしい。

A specific certification authority can be passed in and used to validate
a chain of certificates from a given server.  These will be validated
using BearSSL's rules, which do NOT include certificate revocation lists.
A specific server's certificate, or your own self-signed root certificate
can also be used.  ESP8266 time needs to be valid for checks to pass as
BearSSL does verify the notValidBefore/After fields.

上のようにcertをルート証明書にしても動くはずだがレスポンスとりそびれるときがあるのに気づいた。ルートじゃなくてサーバのcertを使っているときも取りそびれ発生しているかもしれない。原因調査未。とり急ぎ調査はおいておいて他の方式の確認進める。と、思ったら方式別でも発生している。=> 解決方法

暗号化方式の選択

早さ優先したいときとか

client.setInsecure();

ノーチェック

client.setCiphersLessSecure();

以下のやつら指定(と思う)

// For apps which want to use less secure but faster ciphers, only
  static const uint16_t faster_suites_P[] PROGMEM = {
    BR_TLS_RSA_WITH_AES_256_CBC_SHA256,
    BR_TLS_RSA_WITH_AES_128_CBC_SHA256,
    BR_TLS_RSA_WITH_AES_256_CBC_SHA,
    BR_TLS_RSA_WITH_AES_128_CBC_SHA };
  • BR_TLS_RSA_WITH_AES_256_CBC_SHA256: RSA鍵交換、AES-256-CBC暗号、SHA-256ハッシュ
  • BR_TLS_RSA_WITH_AES_128_CBC_SHA256: RSA鍵交換、AES-128-CBC暗号、SHA-256ハッシュ
  • BR_TLS_RSA_WITH_AES_256_CBC_SHA: RSA鍵交換、AES-256-CBC暗号、SHA-1ハッシュ
  • BR_TLS_RSA_WITH_AES_128_CBC_SHA: RSA鍵交換、AES-128-CBC暗号、SHA-1ハッシュ
自分で指定

使えるリストはおそらくこちら。(さらに制限かかっているかもしれないが細かくは追っていない)

ちなみにサンプルソースのwww.example.comはsha1のBR_TLS_RSA_WITH_AES_256_CBC_SHAとBR_TLS_RSA_WITH_AES_128_CBC_SHAは通じたがsha256では通じなかったので上の指定だと接続エラーになった。

つなげるサーバの証明書を取得

こちらを参照

変数名サンプルソースと違うので適宜修正

BearSSL_CertStore.ino

モジラから読み込んだルートcaを複数ストアして使えるやつっぽい。容量気にしない状況ならこいつが使いやすそう。

証明書の更新

長くなったのでこちら

証明書のアップロード

初めにアップロード用ツールのインストール。(手順はこちら

IDEから[Ctrl] + [Shift] + [P]から ‘Upload Little FS to Pico/ESP8266‘ を選択し、(リセットボタン押したりするプログラム書き込みモードで)アップロード実行。

手順の方にも書いたけどシリアルモニター開いていると競合して書きこめないので注意

動作確認

サイトのドメイン入れて実行。大体の場合、htmlソースの表示がレスポンス待ち処理が足りなくてされない。 解決方法

課題

Upload LittleFSだとファイルシステムがすべて上書きされるらしい。一部差し換え的なことがやりたい。ファイルシステムルート直下のcerts.idxとcerts.arを差し替えたらよさそうだがcerts.idxがどこでできているのかまだ理解していない。CertStore::initCertStoreの中でcerts.idx作成しているのでcerts.arだけさしかえればよさそう。失敗したら接続できなくなりそうだけど、ネット越しにファイル放り込んで再起動とかもできそうかな。

ESP8266HTTPClientへの連携

以下の感じでcertを設定済みのWiFiClientSecureをHTTPClient のbeginメソッドに渡してやると動いた

以下蛇足

Chatgptに言われたけどなさそうな奴

無いっぽい奴1

とchatgptにいわれた。が、

C:\Users\kitam\Desktop\https\https.ino: In function 'void setup()':
https:32:10: error: 'class BearSSL::WiFiClientSecure' has no member named 'setCACertBundle'
   32 |   client.setCACertBundle(x509_crt_bundle);
      |          ^~~~~~~~~~~~~~~
exit status 1
'class BearSSL::WiFiClientSecure' has no member named 'setCACertBundle'

ないよと。ソース見ると確かにいない。なお、ESP32ならこれで動く模様。(参考

無いっぽい奴2

といわれたが、同じように

C:\Users\kitam\Desktop\https\https.ino: In function 'void setup()':
C:\Users\kitam\Desktop\https\https.ino:32:9: error: 'class BearSSL::WiFiClientSecure' has no member named 'addServerKey'
   32 |  client.addServerKey(x509_crt_bundle);
      |         ^~~~~~~~~~~~

exit status 1

Compilation error: 'class BearSSL::WiFiClientSecure' has no member named 'addServerKey'

addServerKeyはぱっとみESP32のライブラリにもなさそうなのでchatgptがどこから拾ってきたかよくわからない。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です