Android签名机制

本文详细介绍了Android应用签名的重要性,包括确保应用来源的真实性和完整性。解释了所有应用必须具备数字证书的原因,并介绍了签名的方法,包括使用默认签名、自签名以及签名工具的使用。此外,还列举了常见的签名错误及其解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

1.  为什么要签名 

    1)  发送者的身份认证
         由于开发商可能通过使用相同的 Package Name 来混淆替换已经安装的程序,以此保证签名不同的包不被替换

    2)  保证信息传输的完整性
         签名对于包中的每个文件进行处理,以此确保包中内容不被替换

    3)  防止交易中的抵赖发生, Market 对软件的要求

2.   签名的说明 

    1)  所有的应用程序都必须有数字证书, Android 系统不会安装一个没有数字证书的应用程序

    2)  Android 程序包使用的数字证书可以是自签名的,不需要一个权威的数字证书机构签名认证

    3)  如果要正式发布一个 Android 应用,必须使用一个合适的私钥生成的数字证书来给程序签名,而不能使用 adt 插件或者 ant 工具生成的调试证书来发布

    4)  数字证书都是有有效期的, Android 只是在应用程序安装的时候才会检查证书的有效期。如果程序已经安装在系统中,即使证书过期也不会影响程序的正常功能

    5)  签名后需使用 zipalign 优化程序

    6)  Android 将数字证书用来标识应用程序的作者和在应用程序之间建立信任关系,而不是用来决定最终用户可以安装哪些应用程序

3.   签名的方法

 

a)          使用源码中的默认签名 
在源码中编译一般 都使用默认签名的,在某源码目录中用运行 
$ mm showcommands 
能看到签名命令 
Android 
提供了签名的程序 signapk.jar ,用法如下: 
$ signapk publickey.x509[.pem] privatekey.pk8 input.jar output.jar 
*.x509.pem 
为 x509 格式公钥, pk8 为私钥 
build/target/product/security 
目录中有四组默认签 名可选: testkey, platform, shared, media (具体见 README.txt ),应用程序中Android.mk 中有一个 LOCAL_CERTIFICATE 字段,由它指定用哪个 key 签名,未指定的默认用 testkey.

b)         在源码中自签名 
Android 
提供了一个脚本 mkkey.sh ( build/target/product/security/mkkey.sh ),用于生成密钥,生成后在应用程序中通过 Android.mk 中的LOCAL_CERTIFICATE 字段指名用哪个签名

c)          mkkey.sh 介绍

                                       i.              生成公钥 
openssl genrsa -3 -out testkey.pem 2048 
其中 -3 是算法的参数, 2048 是密钥长度, testkey.pem 是输出的文件

                                      ii.              转成 x509 格式(含作者有效期等) 
openssl req -new -x509 -key testkey.pem -out testkey.x509.pem -days 10000 -subj ‘/C=US/ST=California/L=MountainView/O=Android/OU=Android/CN=Android/emailAddress=android@android.com 

                                    iii.              生成私钥 
openssl pkcs8 -in testkey.pem -topk8 -outform DER -out testkey.pk8 -nocrypt 
把的格式转换成 PKCS #8 ,这里指定了 -nocryp ,表示不加密,所以签名时不用输入密码



4.  签名的相关文件
 

1)         apk 包中签名相关的文件在 META_INF 目录下 
CERT.SF 
:生成每个文件相对的密钥 
MANIFEST.MF 
:数字签名信息 
xxx.SF 
:这是 JAR 文件的签名文件,占位符 xxx 标识了签名者 
xxx.DSA 
:对输出文件的签名和公钥

2)         相关源码 
development/tools/jarutils/src/com.anroid.jarutils/SignedJarBuilder.java
frameworks/base/services/java/com/android/server/PackageManagerService.java
frameworks/base/core/java/android/content/pm/PackageManager.java
frameworks/base/cmds/pm/src/com/android/commands/pm/Pm.java
dalvik/libcore/security/src/main/java/java/security/Sign*
build/target/product/security/platform.*
build/tools/signapk/*



5.  签名的相关问题

 

 

一般在安装时提示 出错: INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES

1)         两个应用,名字相同,签名不同

2)         升级时前一版本签名,后一版本没签名

3)         升级时前一版本为 DEBUG 签名,后一个为自定义签名

4)         升级时前一版本为 Android 源码中的签名,后一个为 DEBUG 签名或自定义签名

5)         安装未签名的程序

6)         安装升级已过有效期的程序



6.  相关工具

1)         查看某个 x509 证书的的有效日期 
在 SignApk.java 中打印出 publicKey.getNotAfter() 即可



7.  参考  
<think>我们正在讨论Android应用签名机制。根据用户的问题,我们需要详细解释Android应用签名机制的原理,特别是V1(JAR签名)和V2(全文件签名)机制。参考引用内容: [^1]介绍了V2签名机制,它是在Android7.0引入的,目的是加快验证速度并加强完整性保证。V2签名是对整个APK文件进行签名和验证,而不是像V1那样对每个文件进行验证。[^2]提到了签名校验的机制,以及申请第三方SDK时需要填入的SAH1值(实际上是证书的SHA1指纹)和快速批量打包如何绕过签名校验。[^3]解释了数字签名的基本概念:计算数据的消息摘要,然后用私钥对消息摘要进行加密得到签名。因此,我们的回答应该包括:1.签名的基本目的:确保应用来源的真实性和完整性。2.V1签名(JAR签名)的详细过程及其缺点。3. V2签名的引入和原理,以及它与V1签名的区别。4.可能还会提到V3签名(如果引用中没有,但根据知识,可以简要提及,但用户问题中未要求,引用中也没有,所以可以省略或简单带过)。5.签名在安装过程中的验证。注意:用户要求使用中文回答,并且按照系统级指令处理数学公式(但本问题可能不涉及数学公式,所以可以忽略数学格式要求,但如果有公式,比如哈希函数,则用$...$)。另外,根据指令,我们需要在回答末尾生成相关问题。结构:1.首先介绍签名的目的。2.然后介绍V1签名(JAR签名)的原理和步骤,以及其缺点。3.接着介绍V2签名的原理和步骤,以及如何解决V1的问题。4.最后简要说明安装时的验证过程。注意:引用内容中提到了V2签名机制,我们可以引用[^1]和[^3]来解释数字签名的基本原理和V2的设计。由于用户要求引用标识,我们在引用内容的末尾添加引用标识。我们开始组织回答。</think>### Android应用签名机制原理详解 Android应用签名机制的核心是**验证应用来源的真实性和完整性**,防止恶意篡改。签名过程基于非对称加密技术,主要包含V1(JAR签名)和V2(全文件签名)两种机制: #### 1. **数字签名基础原理** - **签名生成**: 1. 开发者使用`keytool`生成密钥对(私钥+公钥证书)。 2. 计算APK文件的**消息摘要**(如SHA-256哈希值)$H = \text{Hash}(APK)$。 3. 用**私钥加密摘要**生成签名:$S = \text{Encrypt}_{\text{private}}(H)$。 - **签名验证**: 1. 系统提取APK中的签名$S$和公钥证书。 2. 用公钥解密$S$得到$H'$:$H' = \text{Decrypt}_{\text{public}}(S)$。 3. 重新计算APK的哈希值$H$,若$H = H'$则验证通过[^3]。 > **为什么不直接加密整个APK?** > 加密摘要而非完整数据,可大幅提升效率并保持同等安全性[^3]。 #### 2. **V1签名(JAR签名)** - **原理**: - 解压APK,对每个文件单独计算哈希值,写入`MANIFEST.MF`。 - 用私钥加密`MANIFEST.MF`的哈希值,生成签名文件`CERT.SF`和`CERT.RSA`。 - **缺点**: - **校验慢**:需解压并逐个验证文件,资源多时效率低。 - **篡改风险**:攻击者可修改压缩包内容后重新签名[^1]。 #### 3. **V2签名(全文件签名)** - **Android 7.0引入**: - 直接对整个APK文件(包括ZIP结构)计算哈希树(Merkle Tree)。 - 将签名块(含加密摘要)插入APK的**ZIP中央目录之前**(如图): ``` [文件数据] → [V2签名块] → [ZIP中央目录] → [文件尾] ``` - **优势**: - **完整性更强**:任何修改(包括ZIP结构)都会破坏哈希树。 - **验证更快**:只需校验单个签名块和整体哈希树[^1]。 - **兼容性**:Android 7.0+优先使用V2,低版本自动降级V1。 #### 4. **签名验证流程** 安装APK时: 1. 系统检查签名证书是否可信(如系统证书或用户信任证书)。 2. 根据APK版本选择V1/V2验证机制。 3. 校验摘要一致性,失败则拒绝安装[^2]。 > **第三方SDK的SHA1值是什么?** > 即开发者证书的SHA1指纹,用于第三方平台(如微信支付)验证应用身份[^2]。 #### 5. **绕过签名校验的风险** 批量打包工具常篡改`AndroidManifest.xml`或资源文件后重签名,但V2签名能有效防御此类攻击[^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值