作者:yechaoa
链接:
https://juejin.cn/post/7404778275019407412
本文由作者授权发布。
应用签名是一种数字签名,主要用来验证应用的完整性以及发布者身份认证。在Android应用发布之前非常重要的一环就是应用签名,Android系统要求所有APK在安装到设备上或更新之前都必须使用证书进行数字签名,Android系统会验证应用的签名。版本更新时,新版本APK必须使用相同密钥签名,否则无法覆盖安装;如果签名变更,也无法更新应用,必须卸载重新安装。可见签名对Android应用发布的重要性。
在Android中,签名一般包含三个信息,密钥库、秘钥和证书,在应用首次发布时,我们可以借助Android Studio工具来生成它们。选择Build > Generate Signed Bundle / APK开始生成密钥库和秘钥。选择签名类型,这里选择APK,然后点击Next按钮。点击Create new按钮来创建新的秘钥库文件,如果已有秘钥库文件,选择对应路径即可。- 密钥库路径(Key store path):输入一个存储密钥库文件的路径并命名,例如my-release-key.jks。
- 密钥库密码(Password):输入并确认密钥库的密码。
- 秘钥别名(Alias):为新的密钥创建一个别名,例如my-key-alias。
- 秘钥密码(Key password):输入并确认密钥的密码。通常与密钥库的密码相同,但也可以选择不同的密码。
- 有效期(Validity (years)):设置密钥的有效期,例如25年(通常是设置一个较长的时间)。
- 证书(Certificate):填写证书信息,包括名字、组织单位、组织、市、州/省和国家代码(例:CN)。
填写完所有信息之后,点击OK按钮即可创建密钥文件。
密钥库和秘钥创建成功之后,会自动回到上一页并填充我们刚才填好的签名信息。打包构建完成后,签名好的APK文件在app/变体/目录下:
上面可视化的签名打包方式,一般适用于临时构建,或应用渠道较少的场景。不足的是不适用自动化构建(CI/CD)场景,以及多渠道构建场景下,可能会出现渠道选漏的情况。如果在工作中,渠道包是自动化构建的,那么就需要在build.gradle文件中进行签名配置了。第一步,在项目的根目录下创建一个名为keystore.properties的文件,并在其中包含以下信息:storePassword=myStorePassword
keyPassword=myKeyPassword
keyAlias=myKeyAlias
storeFile=myStoreFileLocation
第二步,在build.gradle文件中,按如下方式加载keystore.properties文件(必须在android代码块前面):import java.util.Properties
import java.io.FileInputStream
val keystorePropertiesFile = rootProject.file("keystore.properties")
val keystoreProperties = Properties()
keystoreProperties.load(FileInputStream(keystorePropertiesFile))
android {
...
}
...
第三步,在signingConfigs{ }中配置存储在keystoreProperties文件中的签名信息:android {
signingConfigs {
create("config") {
keyAlias = keystoreProperties["keyAlias"] as String
keyPassword = keystoreProperties["keyPassword"] as String
storeFile = file(keystoreProperties["storeFile"] as String)
storePassword = keystoreProperties["storePassword"] as String
}
}
...
}
第四步,在构建类型buildTypes中引用signingConfigs{ }中的签名配置: buildTypes {
release {
signingConfig = signingConfigs.getByName("release")
// ...
}
}
这样就可以使用命令./gradlew assembleRelease来进行批量签名打包了。在本地开发阶段,Android Studio会自动生成Debug签名,无需手动配置,但是Debug签名无法用于应用发布。
5.1、介绍
v1签名 (Jar签名):传统的JAR签名机制,验证速度慢,但兼容早期版本(7.0以前)。v1 签名不保护APK的某些部分,例如ZIP元数据。v2签名 (APK签名方案):Android 7.0引入,基于Merkle哈希树,比v1签名更安全,验证速度更快,支持Android 7.0及以上。v3签名 (APK签名方案):Android 9.0引入,继承了v2签名的性能优势和安全性,并对整个APK文件进行签名检查,还增加了秘钥轮换能力,就是允许对应用的签名密钥进行更新,而不会影响应用的安装和更新。v3.1签名 (APK签名方案):Fix版本,Android 13.0引入,修复了v3方案中秘钥轮换的已知问题。v4签名 (APK签名方案):Android 11.0引入,主要是在验证方面,提升了APK增量更新和安装速度。美团基于v2签名方案的多渠道打包方案(walle)原理是:打包过程中在META-INF目录下添加空文件用来作为渠道的唯一标识。在v3签名方案中,基于 Merkle 哈希树对整个APK文件进行签名检查,确保APK文件的完整性,对APK进行的任何修改都会使APK签名作废,从而导致安装失败。而META-INF作为APK的一部分(签名块),自然也是会被签名检查,且不能修改的。所以这也是walle为什么会在Android 9.0(v3)以后失效的原因。
5.2、选择签名方案
那这几个签名方案怎么选呢?不妨先看看市面上大型APP它们是怎么选的?
在查看了微信、淘宝和拼多多的签名方案之后,发现它们都惊人的一致。
v1、v2的兼容性和安全性不错,一般是必选的,v3、v4有新特性,性能较好,可以结合自己的项目按需配置(v4需要与v2或v3结合使用)。5.3、配置签名方案
确定了签名方案之后,就是怎么让签名方案生效了,这就需要在build.gradle文件中添加签名方案配置了。 // 配置签名方案
buildTypes {
release {
// ...
// 启用v1签名
v1SigningEnabled true
// 启用v2签名
v2SigningEnabled true
// 启用v3签名
v3SigningEnabled true
// 启用v4签名
v4SigningEnabled true
}
}
新的签名格式向后兼容,比如使用v3签名方案的APK可以在5.0的设备上安装,前提是包含v1签名方案。5.4、APK签名验证流程
- 校验APK文件中是否存在v4签名文件,存在则继续确认v2或v3方案,因为v4签名本身不足以验证APK的完整性和来源,所以需要与v2或v3方案结合使用,验证通过则允许安装;如果不存在v4签名文件或验证不通过则继续走v3签名验证流程。
- v3签名方案的验证流程,先校验APK文件中是否存在v3签名方案的签名块,存在且校验通过则允许安装,否则拒接安装;如果不存在则继续走v2签名验证流程。
- v2签名方案的验证流程,先校验APK文件中是否存在v2签名方案的签名块,存在且校验通过则允许安装,否则拒接安装;如果不存在则继续走v1签名验证流程。
- v1签名方案的验证流程,验证通过则允许安装,否则拒接安装。
在v2、v3、v4签名验证流程中,最大的区别在于,v2、v3的签名规则验证不通过会直接拒接安装,v4则是继续往下走。5.5、查看应用签名方案
查看一个已经签名的APK文件使用了哪种签名方案,通常需要一些工具来解析和分析APK的签名信息。我们可以使用Android SDK提供的apksigner工具,apksigner主要用于签名和验证APK文件,通过apksigner可以查看APK的签名信息。5.5.1、配置环境
在使用apksigner之前,需要先确认环境变量是否配置正确。找到~/.bash_profile 或 ~/.bashrc 文件,进入编辑。export PATH=$PATH:~/Library/Android/sdk/build-tools/33.0.1
Android SDK路径和版本号替换成你自己的。
source ~/.bashrc
// or
source ~/.zshrc
5.5.2、apksigner使用
apksigner verify --verbose --print-certs /Users/yechao/AndroidStudioProjects/GradleX/app/release/app-release.apk
在输出信息中,可以看到v1 scheme、v2 scheme、v3 scheme和v4 scheme的相关信息,true表示该签名方案开启,false表示关闭,默认开启v1、v2方案。
在上传应用市场或集成第三方SDK的时候,通常会要求填写APK相关的信息来进行验证,其中包括签名信息,比如SHA-1、SHA-256。6.1、signingReport
signingReport是Gradle插件提供的一个能力,用于生成签名报告。在Gradle面板中找到signingReport任务,app > Tasks > android > signingReport。在执行signingReport任务前,确认在build.gradle文件中已经正确配置了signingConfigs。双击执行signingReport任务,在构建日志中会同时输出debug和release签名信息。6.2、keytool
keytool是Java SDK自带的一个工具,可以用来查看密钥库文件(例如.jks或.keystore)中的签名信息,包括SHA-1指纹。keytool 支持两种文件方式查看签名信息,分别是keystore和apk。6.2.1、keystore方式
keytool -list -v -keystore your-keystore-file.jks
6.2.2、apk方式
keytool -printcert -jarfile your-apk-file.apk
如果签名文件丢失或者损坏,唯一的解决办法就是生成新的签名文件,但是会导致应用版本更新问题,需要用户卸载重装,沉没成本较大。所以,签名文件和签名相关信息一定要保存好,定期做好备份。本章我们了解了Android应用签名的重要性、具体的实现方法,和签名方案的介绍及方案选择,还有签名验证流程,最后是一些关于签名安全的建议。GitHub
https://github.com/yechaoa/GradleX相关文档
Sign your app
https://developer.android.com/studio/publish/app-signingapksigner
https://developer.android.com/tools/apksigner?hl=zh-cn
SigningConfig
https://developer.android.com/reference/tools/gradle-api/8.2/com/android/build/api/dsl/SigningConfig
Application Signing
https://source.android.com/docs/security/features/apksigning
最后推荐一下我做的网站,玩Android: wanandroid.com ,包含详尽的知识体系、好用的工具,还有本公众号文章合集,欢迎体验和收藏!
推荐阅读:
扫一扫 关注我的公众号
如果你想要跟大家分享你的文章,欢迎投稿~
┏(^0^)┛明天见!