メインコンテンツにスキップ

アプリのアップデートをセキュアにする署名検証

Learn how signature verification protects Capacitor and Electron app updates, covering cryptographic principles and CI/CD integration.

マーティン・ドナディュー氏

コンテンツマーケター

アプリのアップデートをセキュアにする署名検証

アップデートのパイプラインは緑色で、エッジでバンドルが利用可能で、デバイスはそれをチェックしています。すると、誰かが生成されたJavaScriptの不審な変更を発見します。ビルドランナーが妨害された、開発者資格情報が盗まれた、またはアーティファクトが変更された場合、リリース後テストが終了した後にも、悪意のあるペイロードがリリースに含まれる可能性があります。

署名検証がなければ signature verification、チームが作成したバンドルと、攻撃者が転送中または配信層で変更したバンドルを区別する方法がないため、クライアントには信頼できない方法しかありません。

署名付きの更新では、この決定が変わる。デバイスは、現在実行中の code を置き換える前に、信頼された公開鍵を使用してバンドルを検証します。署名が一致しない場合、更新は非活性のままです。それが直感的には思えますが、実際には生産障害は暗号化の周辺で発生することが多いです。チームは鍵のローテーションを追跡できず、誤ったアーティファクトに署名したり、検証されていないキャッシュファイルを適用したり、または更新を拒否したデバイスの情報を収集することが少ないため、原因を説明することができない。

以下のセクションでは、信頼モデルと検証フロー、CI/CD制御、インシデント対応、署名自体で解決しない制限など、実際の運用上のエッジを焦点に置いています。

目次

シグネチャ検証が大規模アップデートを防ぐ理由

人気のあるCapacitorプラグインのCI/CDパイプラインはリリースプロセスの後半で乗っ取られます。攻撃者はライブアップデートパッケージを変更し、codeを追加し、データを読み取るアプリケーションを追加し、通常の配信パスを使用してアーティファクトを公開します。デバイスは不明なダウンロードドメインを認識しません。デバイスは有効なアップデートをインストールするために待機していることを認識します。

検証がクライアント側の暗号化チェックがない場合、アプリは更新ポリシーが許可するときに変更されたパッケージをダウンロードして実行します。可能な破壊範囲にはデータ漏洩、資格情報の盗用、支払いフローの変更、ビジネスロジックの静かな操作が含まれます。調査も痛みが伴います。エンジニアはどのアーティファクトが配信されたか、どのチャネルが受信したか、どのデバイスがダウンロードしたか、どのデバイスが適用したか、そしてリリースが取り消された前に悪質なcodeが実行されたかを判断する必要があります。

ソフトウェアアップデート配信パイプラインにおける悪質なcodeの注入をブロックするシグネチャ検証の図

A signature verification が有効になっているチームは、異なる失敗モードを取得します。アプリは同じ汚染されたバンドルをダウンロードし、期待されるダイジェストを計算し、信頼されたキーと比較する署名を検証します。暗号化チェックが失敗し、アップデートャーはバンドルを有効化せず、セキュリティチームにイベントが到達する前に、新しい code が実行されるまで、イベントが到達します。

生産ルール: デバイスが両方のアイデンティティと精確なバイトを検証するまで、更新を敵対的扱いとしてください。

保護は、バージョナライザーがデバイス上で実行され、抽出または有効化前に実行され、信頼されたキーが更新自体によって置き換えられない場合にのみ機能します。そのため、証明書とキー管理はアップデートの設計に含まれ、管理上の詳細ではありません。Capacitor を使用するチームは、この境界を含む証明書管理プロセスと共にドキュメント化する必要があります。包括的に、誰が署名できるか、キーがどこに保存されているか、クライアントが承認された後継キーについて学ぶ方法を含めてください。 現代の研究では、署名検証を数十年間で測定可能なエンジニアリング分野として扱ってきました。1977年に最初に公開されたオフラインとオンライン署名検証の研究は、後続の研究でHMMとFFTを含む方法が拡大されました。広く引用された比較では、専門家は約0.5%の誤認と7%の誤認を達成し、一般人は約6.5%の誤認と26%の誤認を達成したと報告されました。これは署名検証研究の歴史的概要としてまとめられています。, including who can sign, where keys live, and how a client learns about an authorized successor key.

Modern research has treated signature verification as a measurable engineering discipline for decades. The first published studies of both off-line and on-line signature verification appeared in 1977, and later work expanded into methods including HMM and FFT. A widely cited comparison reported human experts at approximately 0.5% false acceptance and 7% false rejection, while laypeople reached 6.5% false acceptance and 26% false rejection, as summarized in this historical overview of signature verification researchハンド書きの署名に関係する数字は、ソフトウェアのアップデートとは関係ありませんが、有用な点を強調しています:検証の品質は検証者、検証元データ、決定ポリシーに依存します。

暗号署名による信頼の構築

リリースバンドルを封筒に例えると、ビルドシステムはバンドルの精確なバイトを計算し、そのdigestにプライベートキーを使用してデジタル署名を作成します。 プライベートキー バンドルの対応するパブリックキーがアプリに含まれているか、安全に受信されている場合、署名は有効になります。パブリックキーは、封筒の知られている紋章のように機能します。 開発者が署名を作成し、モバイルアプリが検証する暗号署名プロセスの図示。このフローには4つの異なる部分があります。

ハッシュ化

バンドルを固定長のdigestに変換します。SHA-256とSHA-512は、この整合性ステップの一般的な選択肢です。

  1. 鍵生成 __CAPGO_KEEP_0__
  2. __CAPGO_KEEP_1__ 非対称ペアを作成します。プライベートキーは署名し、パブリックキーは検証します。
  3. 署名 ダイジェストをリリースメタデータにバインドし、バージョン、チャネル、プラットフォーム、対象者を含めて理想的には。
  4. 検証 ダウンロードされたバイトからダイジェストを再計算し、信頼されたプライベートキーによって生成された署名が検証されます。

アップデータが適用するペイロードと同じペイロードに署名をバインドする必要があります。マニフェストの署名だけでは、後でバンドルをダウンロードする際にマニフェストのハッシュがバンドルのハッシュと一致することを確認しないと、十分ではありません。同様に、バンドルのハッシュを検証するだけでは、ハッシュ自体が認証されていない場合、誰が承認したかを確実に判断することはできません。

モバイル配信のためのアルゴリズムの選択

RSAは馴染みのあるもので広くサポートされていますが、通常は大きいキー材料と慎重なパディングの選択が必要です。新しいモバイルアップデートプロトコルでは、Ed25519はしばしば魅力的なものです。キーと署名はコンパクトであり、モバイルプロセッサ上の検証パスも効率的です。RSA-PSSは、互換性の要件がRSAを必要とする場合に適切なものです。選択は、プラットフォームの暗号ライブラリ、サポートされているハードウェア、相互運用性の要件、移行計画に従うべきであり、別の環境からコピーしたベンチマークではありません。

非対称署名の理解のための独立した導入として、以下のガイドをご覧ください。 ブロックチェーンの署名理解のための。トランザクションのコンテキストはOTA配信とは異なりますが、プライベートキー認証とパブリックキー検証の説明は直接転用できます。

信頼チェーンと固定鍵

A certificate chain delegates trust from a root through intermediate authorities to a leaf certificate. That model can simplify broad PKI operations, but an app update client often has a narrower requirement: trust only the publisher key that authorized this update. Embedding a public key, or a small set of authorized keys, directly in the app binary is a form of pinning. It reduces dependence on external certificate authorities, but it creates a rotation problem because the binary must already trust the replacement key.

署名されたエンベロープを完全に維持する。 Your release metadata should identify the artifact, its digest, the intended channel, and the key identifier. Teams building this into Capacitor can use a focused Capacitor アプリ用のトークン署名チェックリスト モバイルとWebシステムにおける実用例

署名検証はモバイル製品のいくつかの層に現れ、各層は異なる質問に答えます。 App-store signing helps the operating system decide whether an installable package comes from an authorized publisher. A signed OTA bundle answers whether the JavaScript and asset payload came from the release authority your updater trusts. A JWT signature helps an __CAPGO_KEEP_0__ validate that a token was issued by the expected identity service.

Signature verification appears in several layers of a mobile product, and each layer answers a different question. App-store signing helps the operating system decide whether an installable package comes from an authorized publisher. A signed OTA bundle answers whether the JavaScript and asset payload came from the release authority your updater trusts. A JWT signature helps an API validate that a token was issued by the expected identity service.

層を混同することはギャップを生み出す。有効なIPA署名は、後続のウェブパッケージを自動的に認証するわけではない。有効なJWTは、更新パッケージが安全であることを証明するわけではない。TLS接続は輸送を保護するが、CDN、プロキシ、キャッシュ、またはビルドシステムが改ざんの元になる場合にアーティファクト署名を置き換えるわけではない。

コンテキスト 署名機構 失敗モードを防止 一般的なギャップ
アプリストアパッケージ プラットフォームcode署名とプラットフォームレビュー制御 再署名または未承認のインストール可能パッケージ チームはストア署名がポストインストールのウェブアセットをカバーすると仮定している
ウェブパッケージとサービスワーカー 署名済みエクスチェンジまたはSRIスタイルの整合性参照 毒性のあるCDNの応答または変更されたアセット エントリーファイルのみがチェックされ、インポートされたアセットは未検証のまま
API トークン 信頼された公開鍵でJWT署名が検証され、JWKSエンドポイントから取得されることが多い 偽造または改ざんされたトークン サーバーは署名を検証するが、発行者、受信者、有効期限、またはトークンの目的を無視する
オーバー・ザ・エア更新 デタッチドまたはエンメデッドバンドルの署名がデバイス上で検証される マニン・ザ・ミッドルまたは改ざんされた更新インジェクション クライアントはコンテンツをダウンロード、キャッシュ、または展開する前に決定を強制する

ウェブアセットの場合、サブリソースの整合性は参照されるリソースに対してブラウザが受け入れるものを制限できるが、ダイナミックインポート、サービスワーカーキャッシュ、または更新マニフェストが攻撃者が選択したファイルに指すことは自動的に解決しない。実装は、実行されるバイトを完全に定義し、検証する必要がある。

JWTのデプロイは異なる方法で失敗する。エンジニアは正しい公開鍵を公開するが、誤った発行者または受信者を持つトークンを受け入れるか、トークンヘッダから提供された暗号化アルゴリズムを信頼することが多い。暗号化署名は有効であるが、承認決定はまだ間違っている。

運用上のコンテキストも、頻繁なリリースと顧客向けモバイルエクスペリエンスに依存する製品の評価において重要である。 2026年の小売アプリケーションエンゲージメント戦略 アップデートの整合性を迅速な実験の前提条件として扱うべきである。迅速なロールアウトは、リリースチャネル、アーティファクト、受信者がすべて同じ認可決定に結びついている場合にのみ有効である。

完全な検証フローの構築

生産用のアップデートツールは検証をゲートとして行うべきであり、インストールの近くで実行されるコールバックではなりません。安全なシーケンスは決定論的です:

  1. 署名付きのマニフェストと署名を認証されたトランスポート上で取得する。
  2. マニフェスト構造、バージョンポリシー、チャネル、有効期限、そしてアーティファクトの識別情報を検証する。
  3. マニフェストによって指定された正確なバンドルをダウンロードする。
  4. ローカルでバンドルのダイジェストを計算する。
  5. 信頼できるEd25519またはRSA-PSS公開鍵に対して署名を検証する。
  6. 検証されたアーティファクトを隔離された場所に保存する。
  7. 原子的に適用し、ロールバックパスを保持する。

ソフトウェアアップデートバンドルの取得、署名検証、検証のプロセスを示す4ステップの図

manifestは決定に影響を与えるすべての値をバインドする必要があります。少なくとも、バンドルダイジェスト、バージョン、チャネル、プラットフォーム、キー識別子が含まれます。ダウンローダーが検証後にURL、ファイル名、またはチャネルを置き換えることを許可しないでください。検証者は不変のバイトと不変のメタデータを受け取り、受け入れられたり拒否されたりする単一の結果を返す必要があります。

TypeScriptの簡略化された形は次のようになります。

type UpdateManifest = {
  version: string
  channel: string
  platform: string
  sha256: string
  signature: string
  keyId: string
}

async function verifyBundle(
  bundle: Uint8Array,
  manifest: UpdateManifest,
  trustedKeys: Map<string, Uint8Array>
): Promise<boolean> {
  const publicKey = trustedKeys.get(manifest.keyId)
  if (!publicKey) return false

  const digest = await sha256(bundle)
  if (!constantTimeEqual(digest, hexToBytes(manifest.sha256))) {
    return false
  }

  try {
    return await ed25519Verify(
      base64ToBytes(manifest.signature),
      digest,
      publicKey
    )
  } catch {
    return false
  }
}

この例は意図的に厳密です。Base64が不正形、不明なキー識別子、ダイジェストの不一致、署名の失敗が発生した場合、拒否を生じさせるように設計されています。ダウンロード中にタイムアウトが発生した場合、前の部分ファイルを適用する理由ではありません。インコンプリートなアーティファクトを削除し、最後の知られている良好なバージョンを保存し、制限されたポリシー下で再試行する必要があります。

競合とロールバックミスを防ぐ

一時的なパスにダウンロードします。ファイルを閉じてフラッシュし、完全な内容を検証し、バージョン化された検証済みストアにファイル名を変更します。アクティベーションステップは検証済みパスを参照する必要があります。CapacitorとElectron環境では、検証プロミス独立してアクティベーションをトリガーする可能性のある非同期ダウンロード完了イベントを許可しないでください。単一のアップデート状態マシンは、例えば downloading, verified, pending, active, rejectedrolled_back.

比較が時間がかかる場合、特に攻撃者が繰り返し検証行動を観察できる場合、敏感なバイトシーケンスを比較するには適切な方法です。 さらに重要な実行上の考慮事項は、前の試行でバージョンを利用可能としてマークした場合に、バンドルを受け入れるショートカットを公開しないことです。 利用可能性と正当性は別々の状態です。

The Capacitor の更新の整合性チェック は、ハッシュ検証とアクティベーションロジックを区別する実装の参考実装として有用です。 また、短縮されたファイル、不正な署名、不明なキー、古いマニフェスト、重複バージョン、プロセスの終了時にアクティベーション中の場合など、失敗分岐を意図的にテストする必要があります。

自動署名検証の研究は、他のドメインで閾値と参照データの重要性を示しています。 1994 年のオンライン研究では、 22 の特性, 最も適切なものを選択し、 10、正しい署名の正確な分類を報告し、 99.5% の偽造を Euclidean 距離法で排除した 86%の出版された統計的方法研究によると。 ソフトウェア更新検証は、生物学的検証ではなく決定論的ですが、教訓は依然として関連しています: 決定境界を厳密に定義する必要があります。

Key Management Challenges Most Teams Underestimate

最初の署名キーは簡単です。2 番目のキーは、設計が試される場所です。

チームはキーペアを生成し、パブリックキーをアプリに配置し、最初のバンドルを 1 日で署名できます。数か月後、エンジニアがラップトップにアクセスし、CI シークレットがビルドログに印刷されたり、署名ジョブがランナーを 1 つから別のランナーに移動したりします。その時点で、「キーを回転するだけ」は、チェックインしないデバイスを捨てることを意味する場合があります。

複雑な、継続的な生産現実と比較するグラフィック。

最初のリリース前に設計に注目すべき 3 つの問題があります。

  • ローテーションなしの死角: 後継キーを要求する前に、信頼できるキーに信頼を送信してください。署名されたキートランジションレコードは、既存の信頼されたキーが次のキーを承認できるようにし、定義されたマイグレーションウィンドウ中はアプリが古いキーを受け入れるようにします。
  • 無保証の削除: アプリ内にピン留めされたキーは、OCSP または CRL スタイルの削除を自動的に提供しません。クライアントには署名された拒否リスト、最小許容するキー バージョン、またはサーバーが制御するポリシーが必要です。このポリシーは、ネットワークが利用できない場合でも安全です。
  • 制限付き署名アクセス: CIランナーのは、シグネチャーオペレーションをVaultまたはHSMから要求するようにし、再利用可能なプライベートキーを平文の環境変数として受け取るのではなくてください。ログはコマンド出力を暗号化し、信頼できないブランチからプルリクエストは生産環境のシグネチャーキーに到達しないでください。

実際の運用状況: キー更新は更新問題です。更新メカニズムが安全に信頼性の変更を提供できない場合、キーが侵害された場合にきれいに復元できないためです。

キー階層は爆発半径を減らします。ルート権限を持つ権威者はリリースキーを承認し、開発、ステージング、生産チャンネルのそれぞれに別のキーで署名します。Threshold署名では、敏感な生産リリースに複数の承認されたパーティが必要になり、1つの盗まれた資格情報が有効な更新を作成するのを防止します。これらの制御はプロセスと遅延を追加するため、チームは更新の影響とチャンネルの感受性に応じて適用する必要があります。

最初の信頼の基準は、モバイル更新の場合に特に弱いです。最初のキーがバンドルと同じチャンネルから到着した場合、攻撃者がそのチャンネルを制御している場合、両方を置き換えることができます。初期の信頼アナーカーは、アプリバイナリ、プラットフォーム保護された構成、または独立して認証されたパスで到着する必要があります。

Capacitorチームの場合、Capgoの文書化されたアプローチには、公開鍵ピンニングとキー更新のサポートが含まれます。 安全なOTA更新のためのキー管理のガイドライン 更新サイクルを計画するのではなく、キー生成を一度のセットアップとして扱うのではなく、実用的な参考資料として提供します。

CI/CDと監視に検証を統合する

リリーストランザクション内に署名を含める。パイプラインは、最初にバンドルを公開し、その後別の手動ステップで署名を追加することはしない。不可変アーティファクトを構築し、そのハッシュ値を計算し、正確なバイトを署名し、クリーンな検証ステップで署名を検証し、最後にバンドルとメタデータを一つのリリースユニットとして公開する。

実用的パイプラインは、次のアーティファクトを生成する。

  • 不可変バンドル: クライアントがダウンロードするファイルであり、CDNが再パッケージするディレクトリではない。
  • マニフェスト: バージョン、チャネル、プラットフォーム、ハッシュ値、鍵識別子、ロールアウトポリシー。
  • 分離署名: canonicalマニフェストデータまたは厳密に定義されたハッシュ表現に対する署名。
  • 検証結果: 署名が環境の公開鍵と検証されるかどうかを機械で読み取るチェック。

GitHub ActionsとGitLab CIは、シンタックスが異なるにもかかわらず同じパターンを強制できる。署名ジョブは、プライベート署名サービスが利用できない場合、署名が不正である場合、または新しくダウンロードしたテストコピーが検証されない場合に失敗する。デプロイジョブは、その結果に依存する必要があり、単にビルドが成功した場合にのみ依存する必要はない。

パスを署名せずに、後でジョブがそのパスを変更するのを許可しないようにする。署名後、パブリッシュする前にアーティファクトのダイジェストを比較し、リリースレコードからパブリッシュされたマニフェストを再現できるようにする。この方法は、CIジョブが圧縮アーカイブを署名するのに対し、配信層が再圧縮または再生成されたファイルを提供するという、意外と一般的な統合ギャップを捕捉する。

デバイス上で観測性を実現する

署名ジョブが成功した場合、パイプラインが有効な署名を生成したことを証明するだけである。デバイスが意図したバイトを受信したこと、またはアプリが意図したキーを使用したことを証明するものではない。アプリバージョン、更新バージョン、チャネル、プラットフォーム、キーID、結果カテゴリ、プライバシーサフティなリリース関連IDとともに、検証結果を記録する。バンドル、トークン、プライベートメタデータ、またはユーザーコンテンツをログに記録しないようにする。

便利なダッシュボードは次のように区別する。

  • 署名失敗とダウンロード失敗
  • ダイジェスト不一致と不正なマニフェスト
  • 未知のキーとポリシー拒否
  • アプリバージョン、リージョン、チャネル、リリース年齢による失敗

ダイジェスト不一致の突然のクラスタは、キャッシュの破損、配信パスの変更、またはアーティファクトのパブリッシュエラーを示唆する。未知のキーイベントは、不完全なローテーションまたは未承認のリリース試行を示唆する。検証テレメトリは、単独では攻撃者を特定できないが、対応者にタイムラインと調査対象の人口を提供する。

CI/CDセキュリティガイドライン Capacitor OTA更新 チームは、署名、検証、デプロイゲートを1つのワークフロー内に配置するのに役立ちます。重要な設計上の選択肢は、所有権です。セキュリティは、検証が実行されたかどうかをエンジニアに尋ねる必要はありません。リリースレコードとクライアントのテレメトリは、その答えを直接提供する必要があります。

セキュリティのベストプラクティスと一般的な誤り

Signature verification should be a hard requirement for every update path that can execute code. The updater must verify before extraction, installation, or activation, and it must fail closed when the signature, digest, key, or policy check is unavailable.

このチェックリストを即時で使用してください:

  • プライベートキーを保護する: 署名材料をHSMまたはマネージドバウツに保持し、ソースコントロールにコミットしないようにし、モバイルバイナリに配置しないようにし、CIログに許可しないようにします。
  • 信頼できる公開キーを固定する: 初期の信頼アナーカーをアップデートペイロード外に保存します。複数のキーをサポートする場合、その目的と移行ルールを定義します。
  • リリースを完全にバインドする: 特定のバンドル、チャネル、プラットフォーム、意図されたポリシーを識別するためのcanonicalメタデータを署名します。
  • すべての検証エラーを拒否する: タイムアウト、不正な署名、不明なキー、または欠落したマニフェストは、前の未検証の結果を続行するための招待状ではありません。
  • テストの妥当性回復: ステージングでキーのローテーション、削除されたキーの処理、ロールバック、中断されたダウンロード、および古いデバイスを実行します。
  • 検証者変更のレビュー: 暗号化ライブラリ、canonicalization、パース、フォールバック動作、およびデバッグ構成のセキュリティに焦点を当てたcodeレビューを必要とします。
  • デバッグ動作を分離する: デフォルトのフラグまたは環境ミスによって、開発者バイパスがプロダクションビルドにパッケージ化されることが不可能でなければなりません。

署名も新鮮さ、受信者への結合、再送信抵抗、またはプロバイダーの現在の状態と互換性のあるペイロードが残っていることを証明するものではありません。ウェブホックのセキュリティガイドラインは、この区別を明確に示しており、最近の脆弱性報告では、不正確または null の署名とcanonicality の問題は、狭い検証チェックを乗り越えることができます。ウェブホックのセキュリティギャップ分析を設計する際の周辺の承認ルールに読み込むことが推奨されます。

閾値の選択は、生物学的システムに関連する教訓を生み出します。102人の個人の1,232の署名と62のパラメトリック特性を使用した研究では 1,232の署名 102人の個人の 62のパラメトリック特性 署名依存の閾値 2.8% の偽認証1.6% の偽承認、もう一方の方法は 2.68% の偽認証1.99% の偽承認, 以下に記載されている 閾値選択研究. このアプリケーションは異なりますが、運用原理は同じです: 検証者の決定ポリシーは、暗号化原理と同じくらい重要です。

Capgo は、Capacitor と Electron チームが署名されたライブアップデートパッケージ、オンデバイス検証、ロールアウト制御、ロールバック保護、配信観察性を同じシステムで提供する必要がある場合の実装オプションとして機能することができます。Visit Capgo アップデートワークフローがあなたのキーマネジメント、CI/CD、監視要件に合致するかどうかを評価するために。

Capacitor アプリ用の即時更新

When a web-layer bug is live, ship the fix through Capgo instead of waiting days for app store approval. Users get the update in the background while native changes stay in the normal review path.

ウェブ層のバグが生じたときは、__CAPGO_KEEP_0__ を通して修正を配信するのではなく、数日間待ってアプリストアの承認を待つのではなく、ユーザーはバックグラウンドで更新を受け取り、ネイティブの変更は通常のレビュー経路で残る。

コンテキスト:Capgo マーケティング ウェブサイト。役割:サポートする説明文またはメタ説明文。見つける場所:コンポーネント GetStarted.astro。Capgo の製品/ブランド名と開発者用語をそのまま保存。メッセージキー `instant_updates_for_capacitor_apps_description` (Capacitor アプリ用の即時更新の説明)。

マーティンから人間のサポート

Capgo gives you the best insights you need to create a truly professional mobile app.