app bundle 的代码透明性机制

代码公开透明是一种可选的代码签名和验证机制,适用于通过 Android App Bundle 发布的应用。该机制使用仅由应用开发者持有的代码公开透明签名密钥。

代码透明性机制不受 app bundle 和 APK 中所用签名方案的影响。代码公开透明密钥是一个单独的密钥,与使用 Play 应用签名时存储在 Google 安全基础架构中的应用签名密钥不同。

代码公开透明机制的运作方式

该机制是通过以下方式实现的:在 bundle 已完成构建但还未上传到 Play 管理中心进行分发之前,将代码公开透明文件添加到其中。

代码公开透明文件是一个 JSON Web 令牌 (JWT),其中包含 bundle 中所含 DEX 文件和原生库的列表,以及这些 DEX 文件和原生库对应的哈希值。这样一来,系统会使用仅由开发者持有的代码公开透明密钥对代码公开透明文件进行签名。

代码透明性机制示意图

此代码公开透明文件会传播到以 app bundle 为基础构建的基础 APK(具体来讲,就是基础模块的主要分块)。这样一来,我们就可以验证:

  • APK 中存在的所有 DEX 文件和原生代码文件在代码公开透明机制文件中都有相匹配的哈希值。
  • 应用中代码公开透明机制签名密钥的公钥组成部分与开发者的公钥(必须由开发者通过单独的安全信道提供)相匹配。

我们会结合这类信息来验证,APK 中包含的代码是否与开发者的预期相符,是否未被修改。

代码公开透明文件不会验证 lib/ 文件夹中包含的资源、资产、Android 清单,以及不属于 DEX 文件或原生库的任何其他文件。

代码透明性验证仅供开发者和最终用户用于检查用途,以确保他们运行的代码与应用开发者最初构建和签名的代码一致。

已知限制

在以下情况下无法使用代码公开透明机制:

  • 应用在清单中指定了 sharedUserId 属性。此类应用可能会与其他应用共享其进程,因此难以保证代码的执行。
  • 如果应用使用的防篡改保护功能或任何其他服务会在代码公开透明文件生成后更改代码,会导致代码公开透明验证失败。
  • 应用使用 API 级别低于 21 (Android 5.0) 的旧版 MultiDex,并使用功能模块。当应用通过 Google Play 安装到搭载 Android 5.0 及更高版本的设备后,代码透明性机制将会继续发挥作用。在较旧版本的操作系统上,代码透明性机制将会被停用。

如何添加代码公开透明机制

在向应用添加代码公开透明机制之前,请确保您拥有可用于代码公开透明签名的私钥/公钥对。这应该是一个唯一密钥,与您用于 Play 应用签名的应用签名密钥不同。请务必妥善保存该密钥,切勿与贵组织以外的对象共享。

如果您没有密钥,可以按照为应用签名指南中的说明,在计算机上生成一个密钥。代码透明性机制使用的是标准密钥库文件,因此,即使这是一个应用签名指南,密钥生成过程也是一样的。

使用 Android Gradle 插件

若要支持代码透明性机制,需要 Android Gradle 插件版本 7.1.0-alpha03 或更高版本。如需配置用于代码公开透明签名的密钥,请在 bundle 代码块中添加以下内容。

Groovy

// In your app module's build.gradle file:
android {
    ...
    bundle {
        codeTransparency {
            signing {
                keyAlias = "ALIAS"
                keyPassword = "PASSWORD"
                storeFile = file("path/to/keystore")
                storePassword = "PASSWORD"
            }
        }
        ...
    }
}

Kotlin

// In your app module's build.gradle.kts file:
android {
    ...
    bundle {
        codeTransparency {
            signing {
                keyAlias = "ALIAS"
                keyPassword = "PASSWORD"
                storeFile = file("path/to/keystore")
                storePassword = "PASSWORD"
            }
        }
        ...
    }
}

使用的密钥必须是仅用于代码公开透明机制的密钥,不得是 Play 应用签名所用的应用签名密钥。

在命令行中使用 bundletool

若要支持代码透明性机制,您可以从 GitHub 下载所需的 bundletool 版本 1.7.0 或更高版本。

通过运行以下命令,可以将代码公开透明机制添加到 Android App Bundle。使用的密钥必须是仅用于代码公开透明机制的密钥,不得是 Play 应用签名所用的应用签名密钥。

bundletool add-transparency \
  --bundle=/MyApp/my_app.aab \
  --output=/MyApp/my_app_with_transparency.aab \
  --ks=/MyApp/keystore.jks \
  --ks-pass=file:/MyApp/keystore.pwd \
  --ks-key-alias=MyKeyAlias \
  --key-pass=file:/MyApp/key.pwd

此外,如果您想使用自己的签名工具,则可以使用 bundletool 生成未签名的代码公开透明文件,并在单独的环境中为该文件签名,然后再将签名注入 bundle:

# Generate code transparency file
bundletool add-transparency \
  --mode=generate_code_transparency_file \
  --bundle=/MyApp/my_app.aab \
  --output=/MyApp/code_transparency_file.jwt \
  --transparency-key-certificate=/MyApp/transparency.cert

# Add code transparency signature to the bundle
bundletool add-transparency \
  --mode=inject_signature \
  --bundle=/MyApp/my_app.aab \
  --output=/MyApp/my_app_with_transparency.aab \
  --transparency-key-certificate=/MyApp/transparency.cert \
  --transparency-signature=/MyApp/signature

验证应用的代码公开透明机制

根据代码公开透明文件验证代码的方法有很多,具体取决于您是将 APK 安装在 Android 设备上,还是下载到计算机本地。

使用 Bundletool 检查 app bundle 或 APK 集

您可以使用 bundletool 来验证 app bundle 或 APK 集中的代码公开透明机制。使用 check-transparency 命令可输出公钥证书指纹:

# For checking a bundle:
bundletool check-transparency \
  --mode=bundle \
  --bundle=/MyApp/my_app_with_transparency.aab

No APK present. APK signature was not checked.
Code transparency signature is valid. SHA-256 fingerprint of the code transparency key certificate (must be compared with the developer's public key manually): 01 23 45 67 89 AB CD EF ..
Code transparency verified: code related file contents match the code transparency file.


# For checking a ZIP containing app's APK splits:
bundletool check-transparency \
  --mode=apk \
  --apk-zip=/MyApp/my_app_with_transparency.zip

APK signature is valid. SHA-256 fingerprint of the apk signing key certificate (must be compared with the developer's public key manually): 02 34 E5 98 CD A7 B2 12 ..
Code transparency signature is valid. SHA-256 fingerprint of the code transparency key certificate (must be compared with the developer's public key manually): 01 23 45 67 89 AB CD EF ..
Code transparency verified: code related file contents match the code transparency file.

您可以视情况指定要用于验证 bundle 或 APK 集的公钥证书,这样您就不必手动比较哈希值:

bundletool check-transparency \
  --mode=bundle \
  --bundle=/MyApp/my_app_with_transparency.aab \
  --transparency-key-certificate=/MyApp/transparency.cert

No APK present. APK signature was not checked.
Code transparency signature verified for the provided code transparency key certificate.
Code transparency verified: code related file contents match the code transparency file.


bundletool check-transparency \
  --mode=apk \
  --apk-zip=/MyApp/my_app_with_transparency.zip \
  --apk-signing-key-certificate=/MyApp/apk.cert \
  --transparency-key-certificate=/MyApp/transparency.cert

APK signature verified for the provided apk signing key certificate.
Code transparency signature verified for the provided code transparency key certificate.
Code transparency verified: code related file contents match the code transparency file.

使用 Bundletool 检查设备上安装的应用

如需检查 Android 设备上安装的应用,请务必通过 adb 将设备连接到计算机,然后发出以下命令:

bundletool check-transparency \
  --mode=connected_device \
  --package-name="com.my.app"

APK signature is valid. SHA-256 fingerprint of the apk signing key certificate (must be compared with the developer's public key manually): 02 34 E5 98 CD A7 B2 12 ..
Code transparency signature is valid. SHA-256 fingerprint of the code transparency key certificate (must be compared with the developer's public key manually): 01 23 45 67 89 AB CD EF ..
Code transparency verified: code related file contents match the code transparency file.

如果需要,已连接的设备透明性检查也可以根据指定的公钥验证签名:

bundletool check-transparency \
  --mode=connected-device \
  --package-name="com.my.app" \
  --apk-signing-key-certificate=/MyApp/apk.cert \
  --transparency-key-certificate=/MyApp/transparency.cert

APK signature verified for the provided apk signing key certificate.
Code transparency signature verified for the provided code transparency key certificate.
Code transparency verified: code related file contents match the code transparency file.