[Android] 基于 Linux 命令行构建 Android 应用(六):Android 应用签名

时间:2023-12-21 20:27:17

  Android 要求所有应用在安装前必须使用证书进行数字签名。Android 使用该证书来确定一个应用以及其作者身份,该证书不要求由证书发行机构颁发,因此 Android 应用经常使用自我签名的证书,而开发者保管证书的私钥。

  你可以使用调试和发行两种模式进行签名。在调试模式下 Android SDK 负责自动生成证书并对应用签名,在发行模式下你需要自行生成属于你自己的证书。

调试模式签名

  在该模式下,Android SDK 会自动生成一个调试用的证书,并且使用默认密码对应用进行签名,因此当你需要调试你的应用程序时,构建过程无需输入任何密码。

  Android Studio 和 Eclipse + ADT 在调试模式下能自动对应用进行签名。

  你可以通过 USB 连接到你的安卓设备来调试你的应用,但调试模式签名的应用无法用于公开发行。

发行模式签名

  在该模式下,你使用自己的证书对应用进行签名:

  1. 创建 keystore。keystore 是指一个二进制文件,它包含了一系列私钥。你需要将你的 keystore 保存在一个安全可靠的地方。

  2. 创建私钥。私钥代表着可以确认应用身份的实体,例如某个人或者公司。

  3. 构建项目。生成一个未签名的 .apk。

  4. 应用签名。使用你的私钥对未签名的 .apk 进行签名。

  完成以上四个步骤后,你就可以在 Google Play 上发行你的应用了[1]

签名注意事项

  在应用的整个生命周期,你都需要使用相同的证书对其进行签名,因为:

  ● 升级:当安卓系统对一个应用进行更新安装时,会首先比较新旧两个版本的证书,只有二者吻合系统才允许升级。如果在新版本应用中你使用了新的证书,你必须重新命名你的包名,那么对用户而言,他们其实是安装了另外一个应用。

  ● 模块性:安卓系统允许具有相同证书签名的应用在同一个进程中运行,对系统而言它们是同一个应用。这样的话你就可以按模块部署你的应用,用户可以独立升级各个模块。

  ● 按权限分享代码和数据:安卓系统提供了一套基于签名的权限管理系统,因此当一个应用使用了特定的证书签名,那么另一个应用就可以为其提供指定的功能支持。通过这套权限管理系统和对多个应用使用相同证书签名,你的应用就可以安全的共享代码和数据。

  如果你想要对应用进行后续升级,你就必须保证证书的有效期大于应用的生命周期。一般推荐有效期为 25 年或者更长。一旦你的密钥过期,用户将无法顺利升级你的应用。

  如果你想要在 Google Play 上发行你的应用,你用以签名应用的密钥有效期必须超过 2033 年 10 月 22 日。这是 Google Play 为了保证用户可以顺利升级他们的应用而采取的强制措施。

妥善保管私钥

  安全妥善的保管你的私钥,无论对你还是用户都是非常重要的。如果你允许其他人使用你的密钥,或者将 keystore 和密码保管在一个不安全的地方,那将危害你作为应用所有者身份的认定以及用户的信任。

  如果其他人设法在你不知情或未许可的情况下获取了你的密钥,那他就可以恶意发行应用来取代你的应用。他还可以以你的名义攻击其他应用或者系统,盗取用户数据。

  你的应用未来所有版本都将使用你的私钥进行签名。如果你丢失私钥,你将无法对已发行应用推送更新,你也不能重新生成私钥。

  你作为一名开发者的声誉取决于你是否妥善保管你的密钥,以下是保障密钥安全的几个建议:

  ● 为 keystore 和密钥设置一个健壮的密码。

  ● 不把私钥交给其他任何人,不告诉任何未授权的人你的 keystore 和私钥密码。

  ● 将 keystore 和私钥文件保管在一个安全可靠的地方。

  一般来说,只要在生成、使用和保管密钥时遵循一个普世安全意识,那么一切就都是安全的。

调试证书过期

  调试模式使用的证书有效期为 365 天,当证书过期时,你会得到一个构建错误。

  要修复这个问题只要删除 debug.keystore 文件即可。该文件默认保存路径为 ~/.android/ (OS X 或 Linux)或者 C:\Documents and Settings\<user>\.android\ (Windows XP),或 C:\Users\<user>\.android\ (Windows Vista 和 Windows 7)

  在你下次构建时,构建工具会自动生成一个新的 keystore 和调试密钥[2]

手动签名应用

  你可以使用 Android SDK 和 JDK 提供的标准工具来手动签名你的应用。以下演示如何在命令行以发行模式进行签名:

  1. 使用 keytool 工具(由 JDK 提供)生成私钥:

$ keytool -genkey -v -keystore my-release-key.keystore
-alias alias_name -keyalg RSA -keysize -validity

  

  以上示例会要求你输入 keystore 和私钥密码,并要求输入一些个人信息,最后生成一个名为 my-release-key.keystore 的文件。这个 keystore 包含一个私钥,有效期为 10000 天。-alias 选项提供的别名在稍后签名应用时会用到。

  2. 在发行模式下编译一个未签名的 .apk。

  3. 使用 jarsigner 工具(由 JDK 提供) + 私钥来签名应用:

$ jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1
-keystore my-release-key.keystore my_application.apk alias_name

  以上示例会要求输入 keystore 和私钥密码,它会修改 APK 文件以完成签名。你可以使用不同的密钥对 APK 文件进行多次签名。

  4. 确认 APK 是否已签名:

$ jarsigner -verify -verbose -certs my_application.apk

  5. 使用 zipalign 工具(由 Android SDK 提供)调整最终的 APK 包:

$ zipalign -v  your_project_name-unaligned.apk your_project_name.apk

  zipalign 工具确保所有未压缩的数据都以一个特别的字节开始,使其与文件起始点保持相对整齐。这样可以减少应用的 RAM 占有率。

注:

[1] 你应该将 keystore 和私钥保存在一个安全可靠的地方,同时保管一份安全的备份。如果你丢失了它们,你将无法在 Google Play 上更新你的应用,因此你必须使用相同的密钥来签名同一个应用的所有版本。

[2] 如果你的开发环境不是使用公历纪年(准确说是格里高利历),构建工具可能会错误地生成一个已经过期的调试证书,从而导致无法编译应用。要解决这个问题,参见 I can't compile my app because the build tools generated an expired debug certificate

附:

1. Signing Your Applications