Android系统要求所有APK(Android Application Package,Android应用程序包)必须使用证书进行数字签名,否则无法安装或更新。在Android安装或更新APK时,系统首先检验APK签名,如果APK未签名或签名校验失败,则其安装操作将被拒绝。开发者可以自行为APK签名并将其上传到Google Play或其他应用商店。如果使用Android App Bundle格式在Google Play发布应用,则需要将其上传至Google Play管理中心,使用Google Play提供的功能进行应用签名。
签名利用摘要和非对称加密技术确保APK由开发者发布且未被篡改。摘要是使用哈希算法计算出来的APK内部文件唯一映射值,相当于APK的指纹。当APK文件内容发生任何改变时,摘要都会发生改变。签名使用开发者的私钥对摘要进行加密。在用户端安装APK时,系统会重新计算APK文件的摘要,然后使用开发者的公钥解密签名中的摘要,两者对比一致则可说明APK来源可信且未被篡改。
Android 11及以前的版本中存在以下4种应用签名方案。
❑v1签名:最基本的签名方案,基于JAR的签名实现。
❑v2签名:提高验证速度并增强完整性保证(在Android 7.0版本中引入)。
❑v3签名:支持密钥轮替(在Android 9.0版本中引入)。
❑v4签名:根据APK的所有字节计算得出Merkle哈希树,并通过v2或v3签名进行补充。
注意
v4签名是Google为解决APK增量安装问题而推出的功能,目前只能通过ADB的方式安装,安装时*.apk.idsig文件需要和*.apk文件在同一目录中。
Android签名方案是向下兼容的。Android 7.0引入v2签名,Android 9.0引入v3签名,Android 11开始支持v4签名,v4签名需要以v2或v3签名为补充,且签名信息需要单独存储在<apk name>.apk.idsig文件中。在进行应用验证时,Android系统会优先寻找并校验最高版本的签名。如果无法找到更高版本的签名,系统会逐级向下寻找,直至找到兼容的签名方案。具体签名校验流程如图1-1所示。
图1-1 签名校验流程
注:Y表示“是”或“通过校验”;N表示“否”或“未通过校验”。
jarsigner是JDK提供的工具,用于对JAR文件进行签名,apksigner是Google官方提供的用于Android应用签名和验证的工具。无论是Android应用的APK包还是JAR包,本质都是ZIP格式的压缩包,因此它们的签名流程相似。
jarsigner与apksigner的区别如下。
❑jarsigner只能用于应用的v1签名,且只能使用keystore文件进行签名。
❑apksigner可以用于v1、v2、v3和v4签名,签名时既可以使用keystore文件进行签名,也可以使用PEM证书和私钥进行签名。
jarsigner签名语法如下:
jarsigner -keystore keystore.jks -signedjar signed.apk unsigned.apk alias_name -storepass pwd
其中,keystore.jks是签名证书;signed.apk是签名后的APK;unsigned.apk是待签名的APK;alias_name是签名证书的alias属性,用来区分不同的证书;pwd是签名证书的密码。
apksigner签名语法如下:
apksigner sign [signer_options] --ks keystore.jks | --key key.pk8 --cert cert.x509.pem --in unsigned_app.apk --out app-signed.apk
使用--ks选项指定密钥库文件。使用--key和--cert选项分别指定私钥文件和证书文件,私钥文件必须使用PKCS #8格式,证书文件必须使用X.509格式。如果未指定签名选项(signer_options),默认情况下apksigner会根据应用中的最小SDK版本(minSdkVersion)和最大SDK版本(maxSdkVersion)来决定使用哪种签名方案。
如果想禁用v2签名,则代码如下:
apksigner sign --v2-signing-enabled false --ks keystore.jks --in unsigned_app.apk --out app-signed.apk
如果想使用v3签名,则代码如下:
apksigner sign --v3-signing-enabled true --ks keystore.jks --in unsigned_app.apk --out app-signed.apk
(1)Android Studio创建签名文件
如图1-2所示是使用Android Studio创建签名文件:Build→GenerateSignedBundle/APK→APK→Next→Create new。根据提示设置文件生成路径和访问文件密码、文件名和签名密码、国家和城市等信息即可。
图1-2 使用Android Studio生成签名证书
(2)keytool创建签名文件
如图1-3所示是使用命令行工具keytool创建签名文件。
keytool -genkeypair -alias test -keyalg RSA -keypass 123456 -keystore TestKey.jks -storepass 123456 -validity 3650
图1-3 使用命令行生成签名证书
代码参数说明如表1-1所示。
表1-1 使用命令行工具keytool生成签名证书的参数
如图1-4所示是查看签名证书内容。
keytool -list -v -keystore TestKey.jks -storepass 123456
图1-4 查看签名证书内容
完成签名后,应用中会新增META-INF文件夹,该文件夹中包含3个文件,如表1-2所示。
表1-2 META-INF文件夹中的文件
1)遍历应用中的文件并计算文件对应的SHA-1摘要,对文件摘要进行BASE64编码,然后将其写入签名文件,即MANIFEST.MF文件。MANIFEST.MF文件的具体内容如图1-5所示。
图1-5 MANIFEST.MF文件的具体内容
2)计算整个MANIFEST.MF文件的SHA-1摘要,进行BASE64编码后写入签名文件,即*.SF文件;再次计算MANIFEST.MF文件中每一条摘要内容的SHA-1摘要,将摘要内容进行BASE64编码后写入签名文件,即*.SF文件。*.SF文件的具体内容如图1-6所示。
图1-6 *.SF文件的具体内容
3)计算整个*.SF文件的数字签名,将数字签名和开发者的X.509数字证书写入*.RSA文件。*.RSA文件的具体内容如图1-7所示。
图1-7 *.RSA文件的具体内容
到这里,我们已经对Android应用签名有了比较清晰的了解,接下来介绍Android应用签名都有哪些用处,如表1-3所示。
表1-3 Android应用签名的作用
苹果在iOS 2.0版本中引入了强制代码签名(Mandatory Code Signing)技术。签名是iOS设备安全和苹果的App Store生态安全的基础。通过代码签名技术,苹果公司能够严格控制在苹果设备上运行的代码,可以有效防止来自外部的攻击。
苹果的签名证书按照用途可以分为3类:开发者证书、企业证书和发布证书。
开发者证书旨在为开发人员提供一个便利的签名方案,使他们能够在应用开发过程中频繁地对代码进行修改并将应用安装到设备上进行测试。其实现原理是,苹果公司分发给开发者一套密钥和证书,使其通过这套密钥和证书对App进行签名,从而对开发者的身份进行认证“背书”,让设备信任由这些开发者签名的应用。
开发者证书需要开发者手动生成,主要步骤如下。
第一步,通过密钥串中的证书助理生成CSR(Certificate Signing Request,证书签名请求)文件,如图1-8和图1-9所示。
图1-8 请求颁发开发者证书
图1-9 填写证书申请信息
完成操作之后,会生成一个名为CertificateSigningRequest.certSigningRequest的文件,存储到指定的目录中。同时,密钥串中会自动生成一对公/私钥,如图1-10所示。
图1-10 查看证书公/私钥
第二步,在苹果开发者中心的All Certificates界面中创建一个证书(Create a New Certificate),按要求上传第一步中生成的CertificateSigningRequest.certSigningRequest文件,便可生成开发者证书,如图1-11所示。
图1-11 生成开发者证书
企业证书实际上就是苹果公司为企业级开发人员提供的签名证书。使用企业证书签名的应用可以直接安装到iOS设备上而不用提交给苹果公司审核,只需要在第一次启动应用时选择信任该证书即可。企业包常用于内部测试,或者被提供给一些测试用户来进行应用正式上线前的灰度测试。使用企业证书签名的应用无法上架到App Store。
发布证书就是苹果公司为正式上架App Store的应用提供的签名证书,开发者将应用提交给App Store审核前需要使用发布证书对应用进行签名。该证书通常命名为iPhone Distribution: xxxx,用于App Store校验所提交的应用的完整性。只有拥有管理员或者更高权限的开发者账号才可以申请该证书,并且可以控制提交权限的范围。发布证书只能用于应用的正式上架发布,不能用于应用的开发调试。
下面以开发者证书为例,介绍使用Xcode进行签名的流程。使用苹果的私钥对开发者的公钥进行签名并结合开发者的公/私钥生成证书,将证书整合进Provisioning Profile文件后,同样使用苹果的私钥进行签名。应用开发完成以后使用开发者的私钥进行签名,将Provisioning Profile文件导入应用中完成整个签名打包流程。具体签名流程如图1-12所示。
图1-12 iOS应用签名流程
生成的应用签名文件CodeResources存放在IPA安装包的_CodeSignature目录中。签名文件存储了安装包中所有文件的签名信息,具体内容如图1-13所示。
图1-13 签名文件内容
iOS系统会在应用安装时进行签名校验,应用通过校验后才能被正常安装到设备上。签名校验流程如图1-14所示。
图1-14 签名校验流程
iOS系统不仅可以通过签名保证应用的完整性,防止应用被篡改,还可以根据开发者公钥生成证书,验证其是否为合法的开发者。应用程序只有签名后才能够正常使用苹果公司的服务,苹果公司就是通过这些手段实现对整个生态的控制的。