Flutter向けにアクセストークンとかを暗号化保存しておく機構を作ったというお話
コードにこういうの混ざってるの嫌ですよね
動作確認の時も含めて、コードにこの手のセンシティブな情報を入れて作業してると、ついウッカリとGitHubに保存しちゃったりとか、疲れてる時に「ちょっとこのコード見てよ」ってChatGPTにまるッとコピペしたやつとか投げちゃいそうで怖いじゃないですか。自分に対するそういう疑いの姿勢、大事
そんなわけで前回Azure用のChatServiceを公開した時から、クライアントアプリ側でこういうの使ってもらうなら、アプリ内で安全にトークン等の情報を保存・管理できるようになってるのとセットだよなー、と思ってたワケです。
そこで今回も作っちゃいました
アプリ初回起動時にユーザーに入力してもらったパスワードを使ってPBKDF2のアルゴリズムでコンテンツ鍵を生成、その鍵を使って、設定画面を経由してユーザー入力されたトークン等の情報は暗号化され、FlutterSecureStorage を通じてセキュアに保存(なんかflutter_secure_storageは「iOSではKeychain、AndroidではKeyStoreを使ってデータを保存してくれるライブラリ」ということらしい)される、みたいな形で使うようにしました(早口)
こんな画面で使うイメージ
アプリに暗号化用の鍵を抱き込ませたりしても、鍵が漏れたらダメなので、まぁユーザの頭の中にしかないパスワードで鍵を作る、というのがひとまずは良い手なのかな、と。
まあ、基本的には呼び出して
import 'package:chat_sample_app/src/services/crypt_service.dart'; // パスは自分で置いたところで
final cryptoService = CryptoService();
新規ユーザーに鍵作ってもらう時には
await CryptoService().generateNewKey(passwordController.text);
で鍵作って、再ログイン後は
await CryptoService().generateKey(passwordController.text);
で、前に鍵作った時のパラメータとパスワードを使って鍵を再生成するイメージで
暗号化は
value = await cryptoService.encrypt(value);
復号は
value = await cryptoService.decrypt(settingData['value']);
するだけなので、まぁそんな難しくはないと思います。使い方のサンプルになりそうなコードは、前回同様のココに転がってますので宜しければご確認ください。まぁまぁ、必要最低限のChatGPTクローン的なやつができたかなー、という感じにはなってきたので、気が向いたら別途、専用のリポジトリを置くかもです。ホワイトレーベルで色々な人がチャットアプリを作る基礎部品的な位置付けで改めてメンテしていってもいいかもな、と(まだ思っただけ)
おまけ
ただアレですね。まだFlutter歴5日目とかなんで全然分かってなくて苦労したんですが、せっかく設定画面でトークンの情報とか保存してても、すでに表示済み扱いの画面に戻る場合、「戻ったタイミングで勝手にページをリロード」みたいなゆるふわな事は起きてくれないので、「更新されたぜー!設定情報読み込みしなおせよお前らー!」って通知しないといけないんですね。いやー、EventBus君、君がいてくれて本当に助かった... (そして、そういうのを雑に話しながら教えてくれるChatGPT君も本当にありがとうな!)
グローバルに参照できるようにして
import 'package:event_bus/event_bus.dart';
final EventBus eventBus = EventBus();
イベント定義して
class SettingsUpdatedEvent {
// 必要に応じてイベントに関するデータをフィールドとして持たせることができる
final String sendBy = "settingApp";
}
イベント起きたら発報して
eventBus.fire(SettingsUpdatedEvent());
処理しなきゃいけないヤツがそれを受け取って処理を動かすだけでOK
void _subscribeToSettingsUpdate() {
_settingsUpdatedSubscription = eventBus.on<SettingsUpdatedEvent>().listen((event) {
_loadInitialSettings();
});
}
うーん、シンプル!
とはいえ、Flutter、そんな楽チン簡単ではない感じですね〜
Discussion
riverpod使えば簡単にできます!
なんと!そうだったんですね!!ChatGPT先生に習ってみます!