セキュリティレビュー
リリース前に、BitTool Signer 1.0.0 のソースコードは、プラットフォームごとに AI 支援による 2 件のセキュリティレビューを、それぞれ独立して受けました。4 件のレポートはすべて下に全文を公開しています。深刻度が重大・高の問題はどのレビューでも見つかっていません。iPhone 版のレビューではそれぞれ深刻度「低」の問題が 1 件見つかりました。Android 版のレビューでは深刻度「中」の問題が見つかり、そのうち 4 件はリリースされた Android 1.0.0 で未修正です。さらにそのうち 3 件は、両アプリが共有する署名エンジンにあります。
- いずれもセキュリティ企業による監査ではなく、人間の監査人も関わっていません。
- Opus 5 と Opus 5.5 のレビューは、対象となるコードの大部分を書いた、または変更したのと同じモデルファミリーによるものです。レポート自身が、第三者による証明や認証ではないと述べています。
- GPT-6 Astra のレビューは、プロジェクトの所有者向けに作成された AI 支援のエンジニアリングレビューであり、監査法人の認証でも人間による承認でもないと自ら述べています。
- Android 版の 2 件のレポートはどちらも、価値の高いウォレットを守る前に、未修正の深刻度「中」の指摘を修正するよう推奨しています。 Android 版 BitTool Signer 1.0.0 は、それらが未修正のままリリースされました。すべての指摘事項を参照してください。
- 独立した第三者による監査は、まだ実施されていません。 レポートは、実機でのテストや実際の他社ウォレットとの往復テストとともに、多額の資金を保管する前に残っている作業として挙げています。
iPhone 版 BitTool Signer
2 件のレポート
| Opus 5 | GPT-6 Astra | |
|---|---|---|
| 日付 | 2026 年 10 月 19 日 | 2026 年 10 月 18 日(レポート BTS-SEC-2026-1018-R3) |
| レビュー対象のコード | タグ v1.0.0、コミット f621372 | 10 月 18 日時点の作業ツリー:コミット 3d706b7 に加え、変更された 59 ファイルと新規テスト 1 件 |
レビュー対象のエンジン(signer.js、SHA-256) | 6933d0d8…f21077 | 6933d0d8…f21077 |
| 手法 | ソースコードの 1 行ずつのレビュー(JavaScript 3,546 行、Swift 11,858 行)、11 件の攻撃プローブ、QR 入力に対する 4,000 ケースのミューテーションテスト、テストスイート、クリーンルームでの再ビルド | サブシステムごとのソースレビュー、前回ラウンドとの比較、独立した Bitcoin と Solana のフィクスチャ、1,509 ケースのミューテーションテスト、テストスイート、再現可能ビルド、依存パッケージのセキュリティアドバイザリ |
| 実行したテスト | エンジン 210 件、ネイティブ 168 件 | エンジン 210 件、ネイティブと UI 177 件 |
| 結果 | 重大 0 · 高 0 · 中 0 · 低 1 · 情報 3 | 重大 0 · 高 0 · 中 0 · 低 1 · 所見 4 |
| 独立性 | コードの多くの部分の作成者自身によるセルフレビュー | AI 支援、プロジェクトオーナー向けに作成 |
両レビューは、BitTool Signer 1.0.0 に同梱されているのと同じエンジンファイルを調べました。すべてのトランザクションパーサー、リスクルール、署名計画は、このファイルに含まれています。アプリのそれ以外の部分(インターフェース、キーチェーン、ストレージ)は、Swift のソースコードを読んでレビューしています。
すべての指摘事項
| ID | 深刻度 | 指摘事項 | 1.0.0 での状況 |
|---|---|---|---|
| BTS-OP5-01 | 低 | 高リスクへの同意を強制しているのはインターフェースだけです。 エンジンは、部分的にデコードされたリクエストと不透明なリクエストについては明示的な同意を要求しますが、完全にデコードされた高リスクのリクエスト(無制限の承認、setApprovalForAll、Safe の権限の変更、トークンのバーン)については要求しません。アプリはチェックボックスがオンになるまで署名ボタンを無効にしているため、1.0.0 で攻撃者がこれを突くことはできません。それでも問題になるのは、ユーザーがハッシュで検証できる部分がエンジンだからです。 | 未解決。レポートは、1.0.1 でこのチェックをエンジンに追加するよう推奨しています。 |
| R3-01 | 低 | おつりのあるバーンに対する Bitcoin の要約。 金額がゼロでない OP_RETURN アウトプットと検証済みのおつりを持つトランザクションでは、結果画面とアクティビティに表示される短い要約が「Every output returns to your wallet」(すべてのアウトプットがウォレットに戻ります)となります。署名画面そのものには、バーン、その金額、高リスクが正しく表示されます。 | 未解決(1.0.0 に同梱されているエンジンは、レビューされたエンジンそのものです)。 |
| BTS-OP5-02 | 情報 | アクティビティで使うローカライズキーがエンジンの出力から組み立てられており、SwiftUI はこれを Markdown としてレンダリングします。現時点でこのキーが取り得る値はすべて固定のラベルなので、潜在的な問題にとどまります。 | 未解決(潜在的)。 |
| BTS-OP5-03 | 情報 | Vault のパスワード KDF(PBKDF2-HMAC-SHA256、600,000 回)はメモリハードではありません。端末に紐付いたキーチェーンの鍵による 2 層目の暗号化で緩和されており、コピーした Vault ファイルだけでは攻撃を始めることすらできません。 | 受容済み。将来の Vault フォーマットでは Argon2id が提案されています。 |
| BTS-OP5-04 | 情報 | Solana の導出における Ed25519 の中間的な鍵素材は、明示的には消去されません。実際の対策となっているのは、JavaScript コンテキストの破棄です。 | 未解決(本質的な制約)。 |
| O-01 | 情報 | インポート中、時間のかかる「このウォレットはすでにあるか」の照会がフレーズの編集後に完了し、前のウォレットに対するパスワードのリセットを提示してしまうことがあります。リセット自体はウォレットの識別情報を再導出し、異なるウォレットであれば拒否します。Vault は変更されません。 | レポート作成時点で未解決。 |
| O-02 | 情報 | Safe と Solana の要約は、トランザクションを実行して得たものではなく、対象範囲を限定したデコーダーから得たものです。現在のコントラクトの状態は、オフラインでは分かりません。 | 設計どおり。確認画面で開示しています。 |
| O-03 | 情報 | Swift と JavaScript では、メモリの完全なゼロ化を保証できません。物理デバイス、OS の乱数生成器、配布されたバイナリはテストされていません。 | 制約事項。 |
| O-04 | 情報 | 開発時のみ使う依存パッケージに関するアドバイザリが 6 件(中程度 3 件、低 3 件)あります。該当するパッケージは、同梱のエンジンには含まれていません。 | 保守対応。 |
両レポートは、それ以前の 2 回のレビューラウンドの指摘事項も再テストし、修正済みであることを確認しています。その中には、「高」の指摘 1 件(DELEGATECALL とネストした MultiSend を含む Safe マルチシグトランザクションの要約)と、Bitcoin の手数料と Solana のバーンの要約に関する「低」の指摘数件が含まれます。さらに Opus 5 は、欠陥ではなく TRON プロトコルの性質として、TRON の署名にはネットワーク識別子が含まれないことを指摘しています。アプリはこの点を開示しています。
共有エンジンで後から見つかった問題
iPhone 版 BitTool Signer 1.0.0 には、SHA-256 が 6933d0d8…f21077 のエンジンが含まれています。GPT-6 Astra による Android 版のレビューは、まさにこのファイルを対象にエンジンの指摘を再現しており、Opus 5.5 の指摘に関わる Bitcoin・EVM・TRON のコードもこのファイル内で同一です。そのため、これらのエンジンの指摘は iPhone 1.0.0 にも当てはまります。
| ID | 深刻度 | iPhone 1.0.0 での意味 |
|---|---|---|
| BTS-02、BTS-07 | 中 | ごく少額の送金と一緒に送られた Solana のバーン、権限変更、委任が、その送金として要約されます。詳細にある警告とリスクの確認は残ります。 |
| BTS-08 | 中 | Bitcoin のおつりは、ウォレットのシングルシグ構成のどのアドレスインデックスでも受け入れられます。閲覧専用ウォレットが決してスキャンしないインデックスも含まれます。 |
| BTS-09 | 低〜中 | 不明な EVM または TRON のコントラクト呼び出しと一緒に送られるネイティブコインが、保存される要約に含まれません。確認カードには表示されます。 |
上の R3-01 は Android の BTS-04 と同じ不具合で、Android 版のエンジンでは修正されています。Opus 5.5 のレポートは、残りを共有エンジンで修正するよう推奨しており、修正は両アプリに反映されます。
レビューで確認されたこと
| 領域 | 確認された内容 | 詳細 |
|---|---|---|
| 署名 | Release ビルドで署名する方法は、確定した計画を経由するものだけです。6 つの独立したチェックが、署名を確認済みのリクエスト、計画されたウォレット、承認された鍵に紐付け、エンジンは署名の前に、復号したシードからすべてを再導出します。実際に実行して確認されています。 | 署名前のチェック |
| 乱数 | リカバリーフレーズは SecRandomCopyBytes から生成され、エラーが起きるとフォールバックなしで作成が中止されます。エンジンの crypto.getRandomValues と Math.random は、同じ乱数源にブリッジされています。 | シードの生成 |
| 鍵の保管 | 認証付きヘッダーを持つ 2 層の AES-GCM、この端末専用のキーチェーン鍵、そして再起動後も維持される、失敗回数に応じた試行制限。 | 鍵の保管 |
| 拒否 | このドキュメントで説明しているすべての拒否が、そのとおりに機能します:SIGHASH_NONE/SINGLE/ANYONECANPAY、前のトランザクションのない SegWit v0 インプット、Solana のルックアップテーブル、EIP-7702、blob トランザクション、生ハッシュへの eth_sign、非対応のチェーン ID。 | 上限とエラー |
| 信頼できない入力 | 両レビューを合わせて、変異させた QR、CBOR、PSBT、JSON の入力 5,509 件:無効な入力が受け付けられたことはなく、制御されない例外も発生していません。 | UR と CBOR |
| オフライン | CFNetwork と Network.framework のどちらもリンクされておらず、JavaScript ブリッジはネットワーク API を一切公開していません。 | セキュリティモデル |
| サプライチェーン | エンジンはタグからバイト単位で同一に再ビルドでき、実行時の依存関係は正確なバージョンに固定されています。本番用依存関係の監査では、脆弱性は報告されませんでした。 | 下記 |
レビューの対象外だったこと
物理デバイスでのテスト(フォールトインジェクション、メモリダンプ、サイドチャネル)、OS の乱数生成器と Secure Enclave の内部、エンジンファイル以外の App Store バイナリの出所、実際のチェーン上でのトランザクション、サードパーティ製ウォレットとの往復、暗号ライブラリの依存関係の完全な監査、21 のインターフェース言語の言語面でのレビュー、そして形式検証は対象外です。テストスイートが通ることで確認できるのはテストしたケースだけであり、すべてのトランザクションやデバイスではありません。
エンジンを自分で検証する
App Store の実行ファイルはバイト単位では再現できません(Apple が再署名して暗号化するため)。しかしエンジンは暗号化されていないリソースなので、比較できます。タグからビルドしてください。
git clone https://github.com/bitbill/bittool-signer-ios
cd bittool-signer-ios && git checkout v1.0.0
cd engine && npm ci --ignore-scripts && npm run build
shasum -a 256 ../BitToolSigner/Resources/signer.js
# 6933d0d8a6f60faa8222506ac0bd7eef80eb884c9f73e31e9f354b4740f21077 (1,181,026 bytes)
次に、インストールしたアプリ内のファイルと比較します。Apple Configurator でアプリを .ipa としてダウンロードし、展開して、Payload/BitToolSigner.app/signer.js のハッシュを計算します。検証が及ばない範囲も含めた完全な手順は、リポジトリの Reproducible-Build.md にあります。
Android 版 BitTool Signer
2 件のレポート
| Opus 5.5 | GPT-6 Astra | |
|---|---|---|
| 日付 | 2026 年 10 月 25 日 | 2026 年 10 月 24 日 |
| 対象のコード | リリース版 1.0.0(バージョンコード 1000001):コードのコミット 71af693、リリース記録 62996b8 | リリース前のコミット e7e71fb:前回のベースライン bb1e656 以降の変更を対象とした再監査 |
対象のエンジン(signer.js、SHA-256) | 4b371759…00fa19 | 6933d0d8…f21077(iPhone 1.0.0 に含まれるエンジン) |
| 方法 | 5 つの領域に分けたソースレビュー(それぞれを端から端まで追跡)、すべての指摘をコードと照合して再確認、合成データによるエンジンの再現、依存関係と成果物の確認 | 変更されたコードとその呼び出し元のレビュー、3 件の修正の検証、コミット済みバンドルでのエンジンの再現、自動回帰チェック |
| 実行したテスト | アプリのテスト 2,075 件、エンジンのテスト 217 件、リリース検証スクリプト 25 件中 25 件 | Android のテスト 1,616 件、エンジンのテスト 210 件(1 件失敗、1 件は実行されないまま成功扱い。BTS-06) |
| 結果 | 重大 0 · 高 0 · 中 4(うち 1 件は低〜中)· 低 9 · 情報提供の注記 | 重大 0 · 高 0 · 未修正:中 1、低 1、検証関連 1 · 修正済み 3 |
| 推奨 | 価値の高いウォレットを守る一般公開の前に BTS-07、BTS-08、BTS-10 を修正する | その時点の版では、価値の高いウォレット向けの一般公開を見送る |
| 独立性 | 対象コードの多くを同じモデルファミリーが書いている | AI 支援。本番コードは変更していない |
どちらのレビューも Android アプリ全体を対象にしています。Kotlin のモジュール、ネイティブホスト(QuickJS を使う JNI 層とネイティブの PBKDF2)、そして iPhone 版と共有する署名エンジンです。
すべての指摘事項
Opus 5.5 はリリースされたコードをレビューしているため、以下は Android 版 BitTool Signer 1.0.0 の指摘事項です。
| ID | 深刻度 | 指摘事項 | 場所 |
|---|---|---|---|
| BTS-07 | 中 | Solana の権限変更が少額送金の陰に隠れる。 アカウントの所有者や権限を変更する、委任先を承認する、または内容不明の命令を含むリクエストに 1 lamport の送金が添えられていると、その送金が見出しと保存される要約になります。詳細の高リスク警告は残り、リスクの確認も引き続き必要です。 | 共有エンジン(iPhone も同様) |
| BTS-08 | 中 | Bitcoin のおつりがどのインデックスでも受け入れられる。 出力のスクリプトがウォレットのいずれかのシングルシグ構成と一致すれば、ブランチ 0 でも 1 でも、2³¹−1 までのどのインデックスでも確認済みのおつりと見なされます。そこに送られた資金は「すべての出力がウォレットに戻ります」と表示されますが、限られた範囲しかスキャンしないウォレットでは見つからないことがあります。 | 共有エンジン(iPhone も同様) |
| BTS-09 | 低〜中 | コントラクト呼び出しで、保存される要約にネイティブコインの金額が含まれない。 ネイティブコインも送る不明な EVM または TRON のコントラクト呼び出しは「不明なコントラクト呼び出し」として保存されます。確認カードとその警告には金額が表示されます。 | 共有エンジン(iPhone も同様) |
| BTS-10 | 中 | リリース用の署名鍵が開発マシン上にある。 鍵とそのパスワードが、作業ツリーに平文で保存されていました(Git からは除外)。 | リリース手順 |
| BTS-11 | 低 | アプリロックの画面の裏で、QR カメラがスキャンを続けることがあります。署名には引き続きウォレットのパスワードが必要です。 | Android アプリ |
| BTS-12 | 低 | 完全にデコードされた高リスクのリクエストに対するリスクの確認を、インターフェースだけが強制しています。 | Android アプリ(iPhone:BTS-OP5-01) |
| BTS-13 | 低 | Android 8〜11 で Keystore のエラーが起きると、公開ウォレットデータを認証する鍵が作り直され、ウォレットの「修復」が必要になることがあります。秘密情報や資金は失われません。 | Android アプリ |
| BTS-14 | 低 | 2 つの補助的な鍵が画面ロックの有無を確認しておらず、ドキュメントの一部が保護を過大に記述しています。保管庫そのものは引き続き画面ロックを必要とします。 | Android アプリ |
| BTS-15 | 低 | 既定のタスクアフィニティのため、古い Android ではタスクの乗っ取りが起こり得ます。 | Android アプリ |
| BTS-16 | 低 | バックアップの確認は、試行錯誤で通過できてしまいます。 | Android アプリ(レポートによれば iPhone も同じ) |
| BTS-17 | 低 | 12 語のフレーズでは、リカバリーカード 1 枚に残るエントロピーは約 40 ビットです。 | Android アプリ |
| BTS-18 | 低 | ウォレットの照合をキャンセルすると、確認画面が「一致するウォレットを探しています…」のまま止まることがあります。 | Android アプリ |
| BTS-19 | 低 | Android 8.0〜9 では、確認用の操作部品の一部だけを覆うオーバーレイを検出できません。署名には引き続きパスワードが必要です。 | Android アプリ |
レポートには情報提供の注記も挙げられています。たとえば、エンジンのスレッドに CPU 時間の上限がないこと(可用性のみに影響)、別のアップロード鍵を用意するまで Google Play 版が APK と同じ鍵で署名されていること、再試行の待ち時間が端末の時計に基づくこと、JVM では消去できないフレーズの一時的なコピーがあること、などです。
GPT-6 Astra は、それより前のコミットをレビューしています。その指摘事項と、リリース版での状況:
| ID | 深刻度 | 指摘事項 | e7e71fb 時点 | Android 1.0.0 |
|---|---|---|---|---|
| BTS-01 | 中 | 一部が覆われた「署名」とリスク確認の操作部品を、オーバーレイ越しにタップできた | 修正済み | 修正済み |
| BTS-02 | 中 | 少額送金と組み合わされた Solana のバーンや権限変更が、その送金として要約される | 未修正 | バーンは修正済み。権限変更は BTS-07 として残る |
| BTS-03 | 低 | 処理をキャンセルした後に、秘密情報のバッファが残ることがあった | 修正済み | 修正済み |
| BTS-04 | 低 | おつりのある Bitcoin のバーンが「すべての出力がウォレットに戻ります」と要約される(iPhone の R3-01) | 未修正 | 修正済み |
| BTS-05 | 機能 | 中断した QR スキャンが再開されなかった | 修正済み | 修正済み |
| BTS-06 | 検証 | 古いファイルパスのため、エンジンのテストが 1 件失敗し、別の 1 件が実行されないまま成功扱いになっていた | 未修正 | 修正済み(エンジンのテスト 217 件すべて成功) |
レビューで確認されたこと
| 領域 | 確認された内容 |
|---|---|
| 署名 | パスワードを回避する方法はなく、確認・照合済みのリクエスト以外に署名する手段もありません。計画はリクエストのハッシュ、計画のハッシュ、署名対象バイトのダイジェストに結び付けられ、エンジンは復号したシードに対して計画を解決し直し、未署名の Bitcoin トランザクションへのいかなる変更も拒否します。キャンセル、アプリロック、新しいリクエストの後に届いた結果は破棄されます。 |
| 鍵の保管 | ネイティブコードによる PBKDF2-HMAC-SHA256(600,000 回)、暗号化のたびに新しいナンスとソルトを使う AES-256-GCM、さらにウォレットごとのエクスポート不可能な Android Keystore の鍵(端末にあれば StrongBox)。パスワードの試行はすべて鍵導出の前に数えられ、カウンターが壊れていれば拒否されます。 |
| メモリ上の秘密情報 | ロック解除された秘密情報は、使い終わると閉じられる入れ物に保持され、キャンセルされた場合も消去されます。リカバリーフレーズはアプリ独自のキーボードで入力され、どの入力方式からも見えません。 |
| エンジンのホスト | バンドルは SHA-256 と長さで固定されています。QuickJS は eval も Function もない状態で動き、秘密情報や信頼できない入力を扱う処理のたびに新しいランタイムを使い、メモリとスタックに上限があります。 |
| オフラインとプラットフォーム | インターネット権限もネットワーク処理のコードもありません。公開されているのはメイン画面だけでディープリンクはなく、バックアップと端末間の移行から除外され、すべてのウィンドウはスクリーンショット、録画、履歴画面に映りません。Android 12 以降では他のアプリのオーバーレイを隠します。アプリロックが署名を承認することはなく、リリース版はログを出力しません。 |
| サプライチェーン | クリーンな npm ci --ignore-scripts の後に再ビルドしたエンジンは、コミット済みのファイルおよび APK 内のコピーとバイト単位で一致します。本番用の依存関係の監査では、勧告は報告されていません。 |
レビューの対象外だったこと
実機でのテスト(メーカーごとの Keystore と StrongBox の挙動、生体認証、オーバーレイ、画面キャプチャ)、悪意あるオーバーレイの実地検証、サイドチャネル、ARM 上でのネイティブコードの実行、実際のチェーン上でのトランザクション、Maven とネイティブの依存関係の CVE スキャン、そして Google Play がビルドするコピー。どちらのレポートも、Android 8 から最新版までの代表的な端末でリリース版を確認するよう求めており、Opus 5.5 は、アプリが多額の資金を守る前に独立した人間による監査を行うよう推奨しています。
APK とエンジンを検証する
bittool.com/signer で公開している APK は、すべてを確認できます。ハッシュ、署名証明書、その中のエンジン、そしてインターネット権限がないこと(aapt2 dump badging の一覧に android.permission.INTERNET はありません)。
# 1. The APK from bittool.com/signer
shasum -a 256 BitToolSigner-1.0.0-1000001.apk
# 109dbf5c622ee77672904c34a10229df3c9b0eac45b07096c510b1e1e169c2a4
apksigner verify --print-certs BitToolSigner-1.0.0-1000001.apk
# Signer #1 certificate DN: CN=BITTOOL PTE. LTD., O=BITTOOL PTE. LTD., C=SG
# Signer #1 certificate SHA-256 digest: af41ed101765393ae89038eb4c6fc7fa96d930f6fcd76b881437a39b5a9e4631
# 2. The engine inside it
unzip -p BitToolSigner-1.0.0-1000001.apk assets/engine/signer.js | shasum -a 256
# 4b3717599e8ee3ed9d2480e640e7203731543cc8ab0f2c3cec3b78e6f400fa19 (1,181,432 bytes)
# 3. The same engine, rebuilt from source
git clone https://github.com/bitbill/bittool-signer-android
cd bittool-signer-android && git checkout 71af693
cd engine && npm ci --ignore-scripts && npm run build
shasum -a 256 ../core/engine/src/main/assets/engine/signer.js
証明書はリリース間で変わることがなく、Android は同じ証明書を持つ更新しかインストールしません。アプリも[設定 › 完全オープンソース › このビルド]で証明書を表示します。Google Play からインストールしたコピーは、アップロードされたバンドルから Google Play がビルドする別のファイルなので、ハッシュは比較できません。ただし、その中の assets/engine/signer.js は変更されないため、adb pull の後に同じ方法で比較できます。手順の全体は、リポジトリの Reproducible-Build.md にあります。上記の値は、2026 年 10 月 25 日に公開中の APK と照合しました。
レポートのダウンロード
| レポート | ページ数 | SHA-256 |
|---|---|---|
| iPhone · Opus 5、2026 年 10 月 19 日(PDF、118 KB) | 17 | ff7ddd17e5dffccd99db6aaa43b8f0041167b58bd9b2bd7cc11d185e779bca1a |
| iPhone · GPT-6 Astra、レポート R3、2026 年 10 月 18 日(PDF、46 KB) | 16 | 02d7a358f8f35b2978eab7db1292add4365a94b736ff79e158dee3afb842b64a |
| Android · Opus 5.5、2026 年 10 月 25 日(PDF、252 KB) | 8 | 8242d58aeec1aa88823eb0a938c9461b0681abfab3f37805e2f77a41b3bba34c |
| Android · GPT-6 Astra、再監査、2026 年 10 月 24 日(PDF、22 KB) | 7 | b37aaefd40d0d522384a86255accadeb976067175d76e38466a1b4c90b036f53 |
このページの要約は私たちがまとめたものです。表現がレポートと異なる箇所については、レポートの記述が正となります。