安卓破解必备 签名验证原理

发布时间:2018-06-27 17:52:51

安卓 签名验证原理 查找资料得知MANIFEST.MF装的是apk资源的SHA1,*.SF文件装的是正版apk的SHA1的RSA私钥加密的密文,*.RSA装的是RSA的公钥。当Android系统安装apk时,会把apk资源SHA1一下,用*.RSA装的公钥把*.SF解密后与算得的SHA1对比确保资源的完整性。问题就是,当一个有相同包名的应用被请求安装的时候,Android系统会做哪些事情来决定是替换旧版apk还是反馈包名冲突而拒绝安装?系统如何得知新旧apk是来自同一开发者且没有被修改过? 自己研究了一阵子,大致理解是:系统检测到新apk与某已装某apk包名冲突时,就判断两个apk签名是否一致,如果不一致,则可判断新apk来自不同开发者,拒绝安装。如果签名一致,则使用*.RSA的公钥解密*.SF的密文得到正版apk的hash值并亲自计算验证之,如果相同则证明apk未被修改,反之安装失败。 请高人帮忙看一下上面的理解是否正确,再解答一下比对新旧apk签名的一致性是如何实现的。是直接比对.RSA文件一致性吗? 开始之前先学习一下签名校验的原理和如何绕过签名校验。 Android签名生成步骤和原理: 我们在App开发完成后将其编译为apk包,这个时候包中没有签名信息,如果直接通过adb install安装到手机上,将会报错:[INSTALL_PARSE_FAILED_NO_CERTIFICATES] 解压apk包可以发现未签名的apk中不包含META-INF目录,该目录在签名后生成,其中包含签名信息相关的3个文件CERT.RSA,CERT.SF,MANIFEST.MF,签名过程就是这3个文件的生成过程。 签名第一步:遍历apk中所有文件(entry),逐一生成SHA-1数字签名,然后通过Base64编码,写入MANIFEST.MF文件。 vim查看MANIFEST.MF文件内容如下: Manifest-Version: 1.0 Created-By: 1.0 (Android) Name: res/drawable-hdpi/m03_0.png SHA1-Digest: Odo4l7R6YcmMl9HtbhLpb8hChts= Name: res/layout/shop_fav_item.xml SHA1-Digest: CVvGtpAo1cLWo7OQfR3tZQwYOY4= ...... 第二步:使用SHA1-RSA算法,用私钥对MANIFEST.MF摘要文件签名,并对其中每个文件摘要签名,生成CERT.SF文件 vim查看其内容如下: Signature-Version: 1.0 Created-By: 1.0 (Android) SHA1-Digest-Manifest: 4pIv24erc5QG+i/kLOOhG6n+EdY= Name: res/drawable-hdpi/m03_0.png SHA1-Digest: 9ZYIfLFplSPcDEIxLJl0JUzmJLs= Name: res/layout/shop_fav_item.xml SHA1-Digest: nqQ+nd6yZn3sB5LfHltWOYlXJMA= ...... (SHA1-Digest-Manifest:是对MANIFEST.MF文件的摘要签名后的值) 第三步:生成CERT.RSA文件,其中记录了RSA公钥,加密算法等信息用于签名校验,该文件是二进制格式,有兴趣可以研究下。 插入学习一下RSA加密和签名原理: RSA有2种应用方式,加密和验证,这里只用到了验证,为了使整个实现过程更加清晰明了,先学习下其原理,这里我们 可以假定加密和验证过程无法被破解,通过私钥加密的信息唯有公钥才能解密。 RSA加密过程(以客户端A发送一条消息给客户端B为例,其中A持有公钥,B持有私钥): 客户端A消息原文:msg 将msg映射为整数(实际上分为很多段整数):Int(msg) 用公钥进行加密:En( Int(msg) ) ) ————发送加密后的信息———— 客户端B收到加密信息:En( Int(msg) ) 用私钥解密:De( En( Int( msg) ) ) = Int(msg) 还原msg:UnInt( Int(msg) ) = msg (通过私钥加密的信息唯有公钥才能解密,可以确保信息不会泄漏) RSA签名与验证过程(客户端A发送一条签名后消息给客户端B,B验证该消息是否为A发出或者未被篡改,其中A持有私钥,B持有公钥): 客户端A消息原文:msg 对msg提取摘要:Dig(msg) 对摘要Base64编码:Base64( Dig(msg) ) 用私钥进行签名(把摘要当作已经加密后的内容,用私钥解密):Sign( Base64( Dig(msg) ) ) ————发送消息和签名———— 客户端B收到信息和签名:msg 和 Sign( Base64( Dig(msg) ) ) 对msg提取摘要:Dig(msg) 对摘要Base64编码:Base64( Dig(msg) ) 将摘要当作未加密过的内容,用公钥加密:En( Base64( Dig(msg) ) ) 签名验证,即判断En( Base64( Dig(msg) ) ) 和Sign( Base64( Dig(msg) ) )是否相等。(这里的Sign跟上面的De一模一样) (通过私钥加密的信息唯有公钥才能解密,可以验证这条消息肯定是A发出来的) 在Android里面签名验证的实现: 覆盖安装时用旧版本的公钥对新安装apk包中MANIFEST.MF进行加密,生成新的MANIFEST.MF'文件,再和原始的MANIFEST.MF文件对比所有的摘要信息是否一致,以此确保是否为同一个机构发布的升级app。(实际当然不是生成新的MANIFEST.MF'文件,可以这么理解)

安卓破解必备 签名验证原理

相关推荐