APKの全体検証に通った成果物が、追加した検査項目ひとつで止まりました。署名済みAPKを配布する小規模な開発・ホームラボ運用では、「検査を増やせば安全になる」と考えたくなります。しかし、検査項目が保証したい仕様から離れると、正常な成果物を不合格にすることがあります。
今回の対象はminSdk 28のAPKです。apksigner verify による全体検証は成功していました。一方、追加のリリースゲートはAPK Signature Scheme v2だけを必須とし、v2=falseを理由に停止しました。
秘密鍵を開かずに署名済みAPKを再検査すると、v3=true、signer 1、RSA-4096、16 KiB alignment passを確認できました。成果物は壊れていません。止まっていたのは、検査側の前提です。
v2だけを必須にすると何が起きるか
SDK同梱のhelpでは、APK Signature Scheme v3はAPI 28で導入され、各署名方式の既定はmin/max SDKに依存します。また verify は、manifestが宣言する対応platform全体を対象に検証する仕様です。
つまりminSdk 28の成果物に対して、v2が常に存在することを無条件の合格条件にする根拠はありません。今回のtoolchainはv3を既定で選択していました。v2がfalseであることは署名不良の証拠ではなく、個別ゲートが生んだfalse negativeでした。
| 確認の置き方 | 固定方式を必須にする設計 | 対応範囲を起点にする設計 |
|---|---|---|
| 一次判定 | v2など一方式の有無 | 宣言したmin/max SDKでの全体検証 |
| 方式表示の扱い | 不一致なら停止 | 互換性と結び付けた補助証跡 |
| 起こりやすい問題 | 正常な成果物のfalse negative | 仕様外の成果物を検出しやすい |
| 判断の説明 | 「この値がtrueか」 | 「対応範囲で成果物が検証できるか」 |
修復では、modern schemeの条件を「v2またはv3」としました。ただし、単にv2をv3へ置き換えたわけではありません。apksigner verify の成功を一次判定に戻し、signer 1と16 KiBの zipalign 成功も維持しています。
完了条件は、成果物の仕様から並べる
- 成果物の仕様を宣言する。ここではminSdk 28を含む対応範囲です。
- その対応範囲で成果物全体を検証する。APKでは
apksigner verifyの成功が中心になります。 - 署名方式、署名者数、鍵種別、alignmentのような補助証跡を照合する。
- 一次判定と補助証跡がそろって初めて、公開判定へ進める。
「v2かv3か」は重要な観測値です。ただし、それだけで完了を決める絶対基準ではありません。対応範囲と検証仕様に結び付けて初めて意味を持ちます。
監視や自動化の判定そのものを観測対象にする考え方は、先行記事誤検知も監視のバグであるともつながります。
false negativeの後、秘密を触らずに再開する

今回、fail-safeは機能しました。誤判定の時点でAPK公開、certificate pin、owner-device installには進みませんでした。
復旧経路では、primaryと2 backupsの暗号化bytes hash、backup readback pin、別filesystem、file owner/mode、root-owned signing checkpointを照合してから、既存の署名済みAPKだけを扱いました。復旧後は同一の署名済みAPKを再検証し、転送hashとcertificate pinを確認してから、既存の認証内download pageへ公開しました。未認証の応答は401であること、serviceがactiveであること、restart countが0であることも確認しています。
ここでの完了条件は「一度成功した工程をもう一度実行する」ことではありません。「秘密を増やして触らずとも、検証済みの同一artifactに安全に戻れる」ことです。
修復は停止解除だけで終わっていない
修復後、script testは68/68を通過しました。確認対象には、既存の検証済みartifactのcheckpoint移行、hardened resume、署名済みAPK hash、download copy hash、certificate pin、HTML link、未認証401、service active、restart count 0が含まれます。
ただし、端末所有者による初回installとrelease-build acceptanceは未完了です。署名・転送・公開前後の検証が通っても、実端末での受け入れ確認までは別の完了条件として残ります。
リリースゲートを見直す3項目
- 完了条件は、宣言した対応範囲で成果物全体を検証していますか。
- 個別の方式・属性チェックは、一次判定を補強する証跡に留まっていますか。
- false negativeの後、秘密を再操作せず、同一artifactで検証と公開を再開できますか。
個別の検査項目は、上位の仕様を代替しません。完了判定はまず「宣言した対応範囲で成果物全体が検証できるか」に置くべきです。apksigner verify の成功とminSdk互換性を一次判定に戻し、v2またはv3の観測を仕様に従属させる。その順序なら、検査は公開してよい理由を積み上げるために働きます。
この検証を回している環境
この検証は、自宅の常設ラボ(使い捨てVM/LXCを回す母艦+GPU+VLAN分離ネットワーク)で動かしています。使っている機材と選定理由、全体構成は1本にまとめています。
ラボ構成のまとめを見る →