ソース公開す るArduinoプログラムに秘密情報を埋め込む
aoirint/RoomSystemSensorESP32: ESP32とFirebaseを使った部屋センシング・オンライン化 クライアントの開発中に
Arduinoプログラム(.ino
)にWiFiパスワード・APIキーなどの秘密情報を埋め込む必要が出てきた。
ここでは、Arduino IDEの主要機能を持つCLIソフトウェアarduino-cli
を使う。
arduino/arduino-cli: Arduino command line interface
arduino-cliの使い方については、別記事参照。
秘密情報の埋め込み
秘密情報の埋め込みには、以下のようなシェルスクリプトcompile.sh
を作成するのが楽でよい。
DEFINES=
の部分の-D
から=
までの文字列が定数名、=
の右辺が定数値として
定義された状態でソースコードがコンパイルされる。
ここでは同ディレクトリの.env
ファイルを読み込んで使用する。
.env
ファイルのフォーマットはよくあるものと同じで、
改行で区切られ、#
から始まる行を無視するKEY=VALUE
形式のテキストファイル。
ボードへの書き込みには以下のupload.sh
のようなスクリプトを使うとよい。
screen
コマンドをラップするスクリプトserialmon.sh
もおいておく。
compile.sh
#!/bin/bashset -euif [ -f .env ]; thenecho "Found .env file."export $(cat .env | sed 's/#.*//g' | xargs)fi# ESP32-DevKitCFQBN="esp32:esp32:esp32"# Arduino UNO# FQBN="arduino:avr:uno"DEFINES="-DSECRET_WIFI_SSID=$WIFI_SSID"DEFINES="${DEFINES} -DSECRET_WIFI_PW=$WIFI_PW"DEFINES="${DEFINES} -DSECRET_FIREBASE_HOST=$FIREBASE_HOST"DEFINES="${DEFINES} -DSECRET_FIREBASE_AUTH=$FIREBASE_AUTH"SKETCH="$(basename $PWD).ino"arduino-cli compile \-b "$FQBN" \--build-properties \"build.defines=${DEFINES}" \"$SKETCH" "$@"
プログラム側では以下のようにする。#x
はコメントではないので注意(文字列リテラルとして展開するマクロ)。
#define _Q(x) #x#define Q(x) _Q(x)#ifdef SECRET_WIFI_SSID#define WIFI_SSID Q(SECRET_WIFI_SSID)#else#define WIFI_SSID "WIFI-SSID"#endif#ifdef SECRET_WIFI_PW#define WIFI_PW Q(SECRET_WIFI_PW)#else#define WIFI_PW "WIFI-PASSWORD"#endifvoid initWiFi() {WiFi.begin(WIFI_SSID, WIFI_PW);Serial.print("WiFi ");Serial.print(WIFI_SSID);Serial.println(" connecting");while (WiFi.status() != WL_CONNECTED) {Serial.print(".");delay(100);}Serial.println();Serial.print("WiFi connected: ");Serial.println(WiFi.localIP());}
upload.sh
#!/bin/bashset -euSERIAL_PORT="$1"# ESP32-DevKitCFQBN="esp32:esp32:esp32"# Arduino UNO# FQBN="arduino:avr:uno"SKETCH="$(basename $PWD).ino"ARGS="${@:2}"arduino-cli upload \-b "$FQBN" \-p "$SERIAL_PORT" \"$ARGS"
./upload.sh /dev/ttyACM0
serialmon.sh
#!/bin/bashset -euSERIAL_PORT="$1"BAUDRATE=115200screen "$SERIAL_PORT" "$BAUDRATE"
./serialmon.sh /dev/ttyACM0
閉じるにはCtrl+A k
を押した後にy
を押してEnter
。
update.sh
まとめて実行する
#!/bin/bashset -euSERIAL_PORT="$1"./compile.sh && ./upload.sh "$SERIAL_PORT" && ./serialmon.sh "$SERIAL_PORT"
./update.sh
compile.shの中身
同ディレクトリ中にある.env
ファイルを読み込み、
C言語の定数として取り込まれるbuild.defines
に手動で変数を列挙している
(nginx Dockerのtemplate置換のように定義済みの環境変数を自動で入れ込む改良もしたい)。
またDEFINESの中身をエスケープしたい(変数内に-D
を許容したい)が、
まだやり方がわかっていない。
関連
- Arduinoスケッチに安全に秘匿値を埋め込む|o3c9|note
- Arduino IDEのコマンドライン機能を使ったりMakefile作ったりしている