android签名校验,Android基础『V1V2V3签名』
android签名校验,Android基础『V1V2V3签名』详细介绍
本文目录一览: APK签名机制原理详解
众所周知,Android系统在安装Apk的过程中,会对Apk进行签名校验,校验通过后才能安装成功。那你知道签名校验的机制是什么?具体校验的是什么内容吗?申请第三方SDK(如微信支付)时填入的SAH1值是什么?目前众多的快速批量打包方案又是如何绕过签名检验的?
我将通过一系列的文章来解开这些疑惑:
这篇文章先来介绍Apk签名相关的基本知识。
要知道签名是什么,先来看为什么需要签名 。大家都知道,在消息通信时,必须至少解决两个问题:一是确保消息来源的真实性,二是确保消息不会被第三方篡改。在安装Apk时,同样需要确保Apk来源的真实性,以及Apk没有被第三方篡改。如何解决这两个问题呢?方法就是开发者对Apk进行签名:在Apk中写入一个“指纹”。指纹写入以后,Apk中有任何修改,都会导致这个指纹无效,Android系统在安装Apk进行签名校验时就会不通过,从而保证了安全性。
要了解如何实现签名,需要了解两个基本概念:数字摘要和数字证书。
简单来说,就是对一个任意长度的数据,通过一个Hash算法计算后,都可以得到一个固定长度的二进制数据,这个数据就称为“摘要”。摘要具有下面的几个特征:
前面已经说到,可以通过签名来确保数据来源的可靠性和数据的不可篡改性。签名就是在摘要的基础上再进行一次加密,对摘要加密后的数据就可以当作数字签名,在安装Apk需要对签名进行验证,验证通过才能继续安装。
这里有两个过程:签名过程 和 校验过程。
先来说 签名过程:
再来看 校验过程:
这里有一个前提:接收方必须要知道发送方的公钥和所使用的算法。如果数字签名和公钥一起被篡改,接收方无法得知,还是会校验通过。如何保证公钥的可靠性呢?答案是数字证书,数字证书是身份认证机构(Certificate Authority)颁发的,包含了以下信息:
接收方收到消息后,先向CA验证证书的合法性(根据证书的签名、绑定的域名等信息。CA机构是权威的,可以保证这个过程的可靠性。)再进行签名校验。
需要注意的是,Apk的证书通常的自签名的,也就是由开发者自己制作,没有向CA机构申请。Android在安装Apk时并没有校验证书本身的合法性,只是从证书中提取公钥和加密算法,这也正是对第三方Apk重新签名后,还能够继续在没有安装这个Apk的系统中继续安装的原因。
我们在对Apk签名时并没有直接指定私钥、公钥和数字证书,而是使用keystore文件,这些信息都包含在了keystore文件中。根据编码不同,keystore文件分为很多种,Android使用的是Java标准keystore格式JKS(Java Key Storage),所以通过Android Studio导出的keystore文件是以.jks结尾的。
keystore使用的证书标准是X.509,X.509标准也有多种编码格式,常用的有两种:pem(Privacy Enhanced Mail)和der(Distinguished Encoding Rules)。jks使用的是der格式,Android也支持直接使用pem格式的证书进行签名,我们下面会介绍。
两种证书编码格式的区别:
X.509证书格式:
Android提供了两种对Apk的签名方式,一种是基于JAR的签名方式,另一种是基于Apk的签名方式,它们的主要区别在于使用的签名文件不一样:jarsigner使用keystore文件进行签名;apksigner除了支持使用keystore文件进行签名外,还支持直接指定pem证书文件和私钥进行签名。
不知道大家有没有注意一个问题,我们通过keytool或者AS生成一个keystore的时候( 签署您的应用 ),除了要输入keystore的密码外,还要输入一个alias和key的密码。在签名时,除了要指定keystore文件和密码外,也要指定alias和key的密码,这是为什么呢?
原因是keystore是一个密钥库,也就是说它可以存储多对密钥和证书,keystore的密码是用于保护keystore本身的,一对密钥和证书是通过alias来区分的。从这里可以看出jarsigner是支持使用多个证书对Apk进行签名的。apksigner也同样支持,关于apksigner的使用介绍可以参考官方文档 apksigner 。
ok,签名的基本概念和校验过程就介绍到这里,关于JAR签名和V2签名机制的详细介绍,参考下面两篇文章:
Android V1及V2签名原理简析
Android为了保证系统及应用的安全性,在安装APK的时候需要校验包的完整性,同时,对于覆盖安装的场景还要校验新旧是否匹配,这两者都是通过Android签名机制来进行保证的,本文就简单看下Android的签名与校验原理,分一下几个部分分析下:
签名是摘要与非对称密钥加密相相结合的产物,摘要就像内容的一个指纹信息,一旦内容被篡改,摘要就会改变,签名是摘要的加密结果,摘要改变,签名也会失效。Android APK签名也是这个道理,如果APK签名跟内容对应不起来,Android系统就认为APK内容被篡改了,从而拒绝安装,以保证系统的安全性。目前Android有三种签名V1、V2(N)、V3(P),本文只看前两种V1跟V2,对于V3的轮密先不考虑。先看下只有V1签名后APK的样式:
再看下只有V2签名的APK包样式:
同时具有V1 V2签名:
可以看到,如果只有V2签名,那么APK包内容几乎是没有改动的,META_INF中不会有新增文件,按Google官方文档:在使用v2签名方案进行签名时,会在APK文件中插入一个APK签名分块,该分块位于zip中央目录部分之前并紧邻该部分。在APK签名分块内, 签名和签名者身份信息会存储在APK签名方案v2分块中,保证整个APK文件不可修改 ,如下图:
而V1签名是通过META-INF中的三个文件保证签名及信息的完整性:
V1签名是如何保证信息的完整性呢?V1签名主要包含三部分内容,如果狭义上说签名跟公钥的话,仅仅在.rsa文件中,V1签名的三个文件其实是一套机制,不能单单拿一个来说事,
如果对APK中的资源文件进行了替换,那么该资源的摘要必定发生改变,如果没有修改MANIFEST.MF中的信息,那么在安装时候V1校验就会失败,无法安装,不过如果篡改文件的同时,也修改其MANIFEST.MF中的摘要值,那么MANIFEST.MF校验就可以绕过。
CERT.SF个人觉得有点像冗余,更像对文件完整性的二次保证,同绕过MANIFEST.MF一样,.SF校验也很容易被绕过。
CERT.RSA与CERT.SF是相互对应的,两者名字前缀必须一致,不知道算不算一个无聊的标准。看下CERT.RSA文件内容:
CERT.RSA文件里面存储了证书公钥、过期日期、发行人、加密算法等信息,根据公钥及加密算法,Android系统就能计算出CERT.SF的摘要信息,其严格的格式如下:
从CERT.RSA中,我们能获的证书的指纹信息,在微信分享、第三方SDK申请的时候经常用到,其实就是公钥+开发者信息的一个签名:
除了CERT.RSA文件,其余两个签名文件其实跟keystore没什么关系,主要是文件自身的摘要及二次摘要,用不同的keystore进行签名,生成的MANIFEST.MF与CERT.SF都是一样的,不同的只有CERT.RSA签名文件。也就是说前两者主要保证各个文件的完整性,CERT.RSA从整体上保证APK的来源及完整性,不过META_INF中的文件不在校验范围中,这也是V1的一个缺点。V2签名又是如何保证信息的完整性呢?
前面说过V1签名中文件的完整性很容易被绕过,可以理解 单个文件完整性校验的意义并不是很大 ,安装的时候反而耗时,不如采用更加简单的便捷的校验方式。V2签名就不针对单个文件校验了,而是 针对APK进行校验 ,将APK分成1M的块,对每个块计算值摘要,之后针对所有摘要进行摘要,再利用摘要进行签名。
也就是说,V2摘要签名分两级,第一级是对APK文件的1、3 、4 部分进行摘要,第二级是对第一级的摘要集合进行摘要,然后利用秘钥进行签名。安装的时候,块摘要可以并行处理,这样可以提高校验速度。
APK是先摘要,再签名,先看下摘要的定义:Message Digest:摘要是对消息数据执行一个单向Hash,从而生成一个固定长度的Hash值,这个值就是消息摘要,至于常听到的MD5、SHA1都是摘要算法的一种。理论上说,摘要一定会有碰撞,但只要保证有限长度内碰撞率很低就可以,这样就能利用摘要来保证消息的完整性,只要消息被篡改,摘要一定会发生改变。但是,如果消息跟摘要同时被修改,那就无从得知了。
而数字签名是什么呢(公钥数字签名),利用非对称加密技术,通过私钥对摘要进行加密,产生一个字符串,这个字符串+公钥证书就可以看做消息的数字签名,如RSA就是常用的非对称加密算法。在没有私钥的前提下,非对称加密算法能确保别人无法伪造签名,因此数字签名也是对发送者信息真实性的一个有效证明。不过由于Android的keystore证书是自签名的,没有第三方权威机构认证,用户可以自行生成keystore,Android签名方案无法保证APK不被二次签名。
知道了摘要跟签名的概念后,再来看看Android的签名文件怎么来的?如何影响原来APK包?通过sdk中的apksign来对一个APK进行签名的命令如下:
其主要实现在 android/platform/tools/apksig 文件夹中,主体是ApkSigner.java的sign函数,函数比较长,分几步分析
先来看这一步,ApkUtils.findZipSections,这个函数主要是解析APK文件,获得ZIP格式的一些简单信息,并返回一个ZipSections,
ZipSections包含了ZIP文件格式的一些信息,比如中央目录信息、中央目录结尾信息等,对比到zip文件格式如下:
获取到 ZipSections之后,就可以进一步解析APK这个ZIP包,继续走后面的签名流程,
可以看到先进行了一个V2签名的检验,这里是用来签名,为什么先检验了一次?第一次签名的时候会直接走这个异常逻辑分支,重复签名的时候才能获到取之前的V2签名,怀疑这里获取V2签名的目的应该是为了排除V2签名,并获取V2签名以外的数据块,因为签名本身不能被算入到签名中,之后会解析中央目录区,构建一个DefaultApkSignerEngine用于签名
先解析中央目录区,获取AndroidManifest文件,获取minSdkVersion(影响签名算法),并构建DefaultApkSignerEngine,默认情况下V1 V2签名都是打开的。
第五步与第六步的主要工作是:apk的预处理,包括目录的一些排序之类的工作,应该是为了更高效处理签名,预处理结束后,就开始签名流程,首先做的是V1签名(默认存在,除非主动关闭):
步骤7、8、9都可以看做是V1签名的处理逻辑,主要在V1SchemeSigner中处理,其中包括创建META-INFO文件夹下的一些签名文件,更新中央目录、更新中央目录结尾等,流程不复杂,不在赘述,简单流程就是:
这里特殊提一下重复签名的问题: 对一个已经V1签名的APK再次V1签名不会有任何问题 ,原理就是:再次签名的时候,会排除之前的签名文件。
可以看到目录、META-INF文件夹下的文件、sf、rsa等结尾的文件都不会被V1签名进行处理,所以这里不用担心多次签名的问题。接下来就是处理V2签名。
V2SchemeSigner处理V2签名,逻辑比较清晰,直接对V1签名过的APK进行分块摘要,再集合签名,V2签名不会改变之前V1签名后的任何信息,签名后,在中央目录前添加V2签名块,并更新中央目录结尾信息,因为V2签名后,中央目录的偏移会再次改变:
签名校验的过程可以看做签名的逆向,只不过覆盖安装可能还要校验公钥及证书信息一致,否则覆盖安装会失败。签名校验的入口在PackageManagerService的install里,安装官方文档,7.0以上的手机优先检测V2签名,如果V2签名不存在,再校验V1签名,对于7.0以下的手机,不存在V2签名校验机制,只会校验V1,所以,如果你的App的miniSdkVersion<24(N),那么你的签名方式必须内含V1签名:
校验流程就是签名的逆向,了解签名流程即可,本文不求甚解,有兴趣自己去分析,只是额外提下覆盖安装,覆盖安装除了检验APK自己的完整性以外,还要校验证书是否一致只有证书一致(同一个keystore签名),才有可能覆盖升级。覆盖安装同全新安装相比较多了几个校验
这里只关心证书部分:
Android V1及V2签名签名原理简析
仅供参考,欢迎指正
如何判断 Android 应用的 Apk 签名是否一致
方法如下:
1.FILE="yourapp.apk"
cert_XSA=`jar tf $FILE | grep SA`
此时得到的cert_XSA可能是META-INF/*.RSA或者META-INF/*.DSA。
2.apk中提取具体的签名文件。
jar xf $FILE $cert_XSA
此时会在当前目录得到cert_XSA文件。
3.对于得到的签名文件,提取其中签名的MD5值
keytool -printcert -file $cert_XSA | grep MD5 > "$FILE.certMD5"
这时候yourapp.certMD5这个文件中就保存了yourapp.apkk中的签名MD5值。
4.最后比较两个app的签名可以用diff
FILE1="yourapp1.apk"
FILE2="yourapp2.apk"
//经过上述步骤得到$FILE1.certMD5和$FILE2.certMD5
certMD5_diff=`diff $FILE1.certMD5 $FILE2.certMD5`
if [ "$certMD5_diff" = "" ]; then
echo "$FILE1.certMD5 == $FILE2.certMD5"
fi
若输出yourapp1.apk.certMD5 == yourapp2.apk.certMD5那么这两个应用的签名就一致。
Android Studio 之签名
通过签名可以确保数据来源的可靠性和数据的不可篡改性
对 Apk 进行签名,也就是在 Apk 中写入一个指纹,写入指纹后,Apk 中有任何修改,都会导致这个指纹无效,Android 系统在安装 Apk 进行签名校验时就会不通过,进而无法安装该 Apk
如上图:
通常的签名验签过程中,接收方收到消息后,会先向 CA 机构验证证书的合法性,再进行签名校验。但 Apk 的证书通常由开发者自己制作,没有向 CA 机构申请,Android 系统在安装 Apk 时也并没有校验证书本身的合法性,只是从证书中提取公钥和加密算法,因此,如果对第三方 Apk 重新签名,也能安装到没有安装过这个 Apk 的系统中
keystore 文件包含私钥、公钥和数字证书,分为很多种,Android 使用的是 Java 标准 keystore 格式 JKS(Java Key Storage)
Android App Bundle:用于通过 Google Play 发布的应用,需要升级到AS 3.2 以上版本才支持App Bundle 格式; APK:用于创建可部署到设备上的签名 APK
点击 Finish 就会生成签名文件与签名后的 Apk
当我们需要升级 Apk 版本的时候,需要再次对 Apk 文件进行签名,可以通过配置 build.gradle 让其自动生成签名后的 Apk
如果你的项目是开源的,需要把你的签名信息写在 local.properties 中,然后在 .gitignore 配置文件中加入 local.properties ,这样 local.properties 就不会提交到开源项目中,签名信息也就不会被人获取
local.properties:
app/build.gradle:
有时候我们的 apk 中某些功能需要系统签名,例如静默安装。测试系统签名的 apk,需要 root 权限,而带 Google APIs 的模拟器不能 root,因此要注意不能选择带 Google APIs 的模拟器
下面执行的操作都是在 Linux 中,如果 apk 是 window 中生成的,需要拷贝到 linux 操作,再将生成的系统签名过得 apk 再拷贝到 window,比较麻烦,可以考虑后面的自动系统签名,还是需要在 linux 操作一次,不过之后就可以只在 window 操作了
这两个文件在目录 aosp/build/target/product/security 下,如下图
在目录 aosp/prebuilts/sdk/tools/lib 下,如下图
将前面获取的 platform.pk8 、 platform.x509.pem 和 signapk.jar 文件放到需要签名的 apk 同一个目录,执行以下命令
如果出现上面的错误:Failed to load any of the given libraries: [conscrypt_openjdk_jni-linux-x86_64, conscrypt_openjdk_jni-linux-x86_64-fedora, conscrypt_openjdk_jni]
解决方法:
到目录 aosp/prebuilts/sdk/tools/linux/lib64 下,复制 libconscrypt_openjdk_jni.so 文件到需要签名 apk 的同一个目录,并将命令改为
自动进行系统签名的原理是:先生成一个 system.jks 文件,使用 keytool-importkeypair 对 system.jks 文件进行系统签名,再 build.gradle 和 local.properties 进行配置,直接使用带有系统签名的 system.jks 对 apk 进行签名,这样编译生成的apk文件就自带系统签名了
按照前面的方法,生成一个 system.jks 文件,此时是在 window 系统中操作的
进入 keytool-importkeypair 目录,将 system.jks、platform.pk8、platform.x509.pem 文件拷贝进来,拷贝之后的目录结构为
使用 linux 中修改过的带有系统签名的 system.jks 文件将 window 中最开始生成的 system.jks 覆盖掉,再像前面的自动签名部分一样,修改 build.gradle 和 local.properties 的配置,之后生成的 apk 就是系统签名过的了
测试方法是,在 AndroidManifest.xml 中添加 android:sharedUserId="android.uid.system" 后安装到 非 Google APIs 的模拟器上 , Google APIs 的模拟器不能 root,无法安装
会发现只有使用 system.jks 文件签名后才能安装,否则安装失败,会报以下的错误:
Android基础『V1V2V3签名』
基础概念 签名:在 APK 中写入一个「指纹」。指纹写入以后,APK 中有任何修改,都会导致这个指纹无效,Android 系统在安装 APK 进行签名校验时就会不通过,从而保证了安全性。 摘要算法: 使用一段简单的看上去随机的不可逆向的固定长度的字符串来表示一个文件的唯一性。 常见的摘要算法如MD5(128个比特位)、SHA-1算法(160/192/256个比特位)。 公钥密码体制:也称非对称算法,特点是 公钥是公开的 ,私钥是保密的。常见的如:RSA。 展开讨论一下RSA:
Android中的签名方案 V1 :基于jarsigner(JDK自带工具,使用keystore文件进行签名) 或 apksigner(Android专门提供的,使用pk8、x509.pem进行签名)。keystore和pk8/x509.pem可以相互转换。 签名原理:首先keystore文件包含一个MD5和一个SHA1摘要。 这也是很多开放平台需要我们上传的摘要数据 。 签名APK后会在META-INF文件夹下生产CERT.RSA、CERT.SF、MANIFEST.MF三个文件。
在apk中,/META-INF文件夹中保存着apk的签名信息,一般至少包含三个文件,[CERT].RSA,[CERT].SF和MANIFEIST.MF文件。这三个文件就是对apk的签名信息。 MANIFEST.MF中包含对apk中除了/META-INF文件夹外所有文件的签名值,签名方法是先SHA1()(或其他hash方法)在base64()。存储形式是:Name加[SHA1]-Digest。 [CERT].SF是对MANIFEST.MF文件整体签名以及其中各个条目的签名。一般地,如果是使用工具签名,还多包括一项。就是对MANIFEST.MF头部信息的签名,关于这一点前面源码分析中已经提到。 [CERT].RSA包含用私钥对[CERT].SF的签名以及包含公钥信息的数字证书。 ??是否存在签名伪造可能: 修改(含增删改)了apk中的文件,则:校验时计算出的文件的摘要值与MANIFEST.MF文件中的条目不匹配,失败。 修改apk中的文件+MANIFEST.MF,则:MANIFEST.MF修改过的条目的摘要与[CERT].SF对应的条目不匹配,失败。 修改apk中的文件+MANIFEST.MF+[CERT].SF,则:计算出的[CERT].SF签名与[CERT].RSA中记录的签名值不匹配,失败。 修改apk中的文件+MANIFEST.MF+[CERT].SF+[CERT].RSA,则:由于证书不可伪造,[CERT].RSA无法伪造。
V2 :7.0新增的 签名后的包会被分为四部分 1. Contents of ZIP entries(from offset 0 until the start of APK Signing Block) 2. APK Signing Block 3. ZIP Central Directory 4. ZIP End of Central Directory 新应用签名方案的签名信息会被保存在区块2(APK Signing Block) 中, 而区块1( Contents of ZIP entries )、区块3( ZIP Central Directory )、区块4( ZIP End of Central Directory )是受保护的, 在签名后任何对区块1、3、4的修改都逃不过新的应用签名方案的检查 。
V3 :9.0新增的 格式大体和 v2 类似,在 v2 插入的签名块(Apk Signature Block v2)中,又添加了一个新快(Attr块) 。 在这个新块中,会记录我们之前的签名信息以及新的签名信息,以 密钥转轮的方案,来做签名的替换和升级。这意味着,只要旧签名证书在手,我们就可以通过它在新的 APK 文件中,更改签名 。 v3 签名新增的新块(attr)存储了所有的签名信息,由更小的 Level 块,以 链表 的形式存储。 其中每个节点都包含用于为之前版本的应用签名的签名证书,最旧的签名证书对应根节点,系统会让每个节点中的证书为列表中下一个证书签名,从而为每个新密钥提供证据来证明它应该像旧密钥一样可信。 这个过程有点类似 CA 证书的证明过程,已安装的 App 的旧签名,确保覆盖安装的 APK 的新签名正确,将信任传递下去。 注意: 签名方式只支持升级不支持降级,如安装了V2的包,不能覆盖替换为V1的包。
参考 Android App签名(证书)校验过程源码分析 新一代开源Android渠道包生成工具Walle Android 签名机制 v1、v2、v3
如何判断 Android 应用的 Apk 签名是否一致
如果你仅仅是想验证app是否签名一致的话,方法很多,我说一种:就是两个apk(同一款app),其中他们的versionCode不一样(只是为了更好的区分,因为一般企业开发的app都能查看版本号,版本号就是versionCode。其实versionCode一样也无所谓),先安装versionCode低的那个,然后再安装高的,如果能把高的安装上的话,就证明签名一致。
很高兴能帮您回答这个问题:这个问题不难。
1: 为了维护开发者的利益,防止别人篡改和盗用开发者的应用,在发布android apk之前,都需要给应用程序部署签名,签名可以保证软件升级的一致性。
2: 对于您提出的问题,我们可以根据这一点:相同签名的应用可以实现覆盖安装,而不一致的签名将无法共享使用数据,也即是无法覆盖安装。
3: 将android应用程序签名后,看能不能覆盖安装,如果能覆盖安装,确定以及肯定,android 应用的apk签名一定一致。
如果不能覆盖安装,那就可能android应用的apk签名不一致。
Android应用的发布形式apk中包含的签名加密方法除了RSA还有DSA,所以不能只从apk中提取常见的META-INF/CERT.RSA,应该是检查apk中具体的签名文件。
1.FILE="yourapp.apk"
cert_XSA=`jar tf $FILE | grep SA`
此时得到的cert_XSA可能是META-INF/*.RSA或者META-INF/*.DSA。
2.apk中提取具体的签名文件。
jar xf $FILE $cert_XSA
此时会在当前目录得到cert_XSA文件。
3.对于得到的签名文件,提取其中签名的MD5值
keytool -printcert -file $cert_XSA | grep MD5 > "$FILE.certMD5"
这时候yourapp.certMD5这个文件中就保存了yourapp.apkk中的签名MD5值。
4.最后比较两个app的签名可以用diff
FILE1="yourapp1.apk"
FILE2="yourapp2.apk"
//经过上述步骤得到$FILE1.certMD5和$FILE2.certMD5
certMD5_diff=`diff $FILE1.certMD5 $FILE2.certMD5`
if [ "$certMD5_diff" = "" ]; then
echo "$FILE1.certMD5 == $FILE2.certMD5"
fi
若输出yourapp1.apk.certMD5 == yourapp2.apk.certMD5那么这两个应用的签名就一致。
Android应用的发布形式apk中包含的签名加密方法除了RSA还有DSA,所以不能只从apk中提取常见的META-INF/CERT.RSA,应该是检查apk中具体的签名文件。
1.FILE="yourapp.apk"
cert_XSA=`jar tf $FILE | grep SA`
此时得到的cert_XSA可能是META-INF/*.RSA或者META-INF/*.DSA。
2.apk中提取具体的签名文件。
jar xf $FILE $cert_XSA
此时会在当前目录得到cert_XSA文件。
3.对于得到的签名文件,提取其中签名的MD5值
keytool -printcert -file $cert_XSA | grep MD5 > "$FILE.certMD5"
这时候yourapp.certMD5这个文件中就保存了yourapp.apkk中的签名MD5值。
4.最后比较两个app的签名可以用diff
FILE1="yourapp1.apk"
FILE2="yourapp2.apk"
//经过上述步骤得到$FILE1.certMD5和$FILE2.certMD5
certMD5_diff=`diff $FILE1.certMD5 $FILE2.certMD5`
if [ "$certMD5_diff" = "" ]; then
echo "$FILE1.certMD5 == $FILE2.certMD5"
fi
若输出yourapp1.apk.certMD5 == yourapp2.apk.certMD5那么这两个应用的签名就一致。
1. 查找apk里的rsa文件
2. 从apk中解压rsa文件
3. 获取签名的fingerprints
4. 清理工作,删除rsa文件
如果你想知道两个apk是不是用的同一个签名,那比一下它们签名的MD5码(或SHA1码)是不是一样就行了。
Android应用的发布形式apk中包含的签名加密方法除了RSA还有DSA,所以不能只从apk中提取常见的META-INF/CERT.RSA,第一步应该是检查apk中具体的签名文件是什么。
FILE="yourapp.apk"
cert_XSA=`jar tf $FILE | grep SA`
此时得到的cert_XSA可能是META-INF/*.RSA或者META-INF/*.DSA。
接下来从apk中提取具体的签名文件。
jar xf $FILE $cert_XSA
此时会在当前目录得到cert_XSA文件。
然后对于得到的签名文件,提取其中签名的MD5值
keytool -printcert -file $cert_XSA | grep MD5 > "$FILE.certMD5"
这时候yourapp.certMD5这个文件中就保存了yourapp.apkk中的签名MD5值。
最后比较两个app的签名可以用diff
FILE1="yourapp1.apk"
FILE2="yourapp2.apk"
# ...
# ... 经过上述步骤得到$FILE1.certMD5和$FILE2.certMD5
# ...
certMD5_diff=`diff $FILE1.certMD5 $FILE2.certMD5`
if [ "$certMD5_diff" = "" ]; then
echo "$FILE1.certMD5 == $FILE2.certMD5"
fi
若输出yourapp1.apk.certMD5 == yourapp2.apk.certMD5那么这两个应用的签名就一致。
apk签名是什么意思?
apk是安卓应用软件包,apk签名是软件包在安装的时候进行的安全性验证机制。
这种签名机制目的是为了确保Apk来源的真实性,以及Apk没有被第三方篡改。开发者通过对Apk进行签名:在Apk中写入一个“指纹”。指纹写入以后,Apk中有任何修改,都会导致这个指纹无效,Android系统在安装Apk进行签名校验时就会不通过,从而保证了安全性。
扩展资料:
1、APK的格式定义
在Android平台中,dalvikvm的执行文件被打包为apk格式,最终运行时加载器会解压,然后获取编译后的androidmanifest.xml文件中的permission分支相关的安全访问,但仍然存在很多安全限制,如果你将apk文件传到/system/app文件夹下,会发现执行是不受限制的。安装的文件可能不是这个文件夹,而在androidrom中,系统的apk文件默认会放入这个文件夹,它们拥有着root权限。
2、APK的开发环境
Android是一个基于Java的开发环境,Google也在API文档的书写和样例的提供上做了很出色的工作。
3、获取SDK
下载并安装android的SDK[软件开发套件],这套SDK主要包括有核心库文件,一个模拟器,开发工具和一些示范的样例文件。推荐使用Eclipse 和androideclipse 扩展。如果只是使用android,Eclipse IDE就已经足够了,但如果是第一次开发Java应用,建议下载完整的Java SE 开发工具 (JDK) 因为它包括签发应用程序所需要的工具。
4、APK应用架构
android应用架构很关键,如果不学习它,设计出来的游戏将是一种很难修复bug的产品。 需要了解应用程序、活动、Intents以及它们是如何互相联系交互的,Google在这儿提供了良好的信息架构。真正重要的是,要理解为什么在设计的游戏中,需要不止一个的活动进程,以及如何设计一个用户体验良好的游戏。这些都应当配合到应用的生命周期中。
5、APK应用的生命周期
应用的生命周期是由Android OS操作系统进行管理的,活动进程都将作为系统命令进行创建,正确处理这些事件对一个应用程序来说是极为重要的,因为终端用户不会知道什么是正确的。最好在开始设计游戏之前搞明白这些,因为这有助于节省调试时间以及避免代价高昂的重新设计。
对大多数应用而言,默认设置即可开始工作,但对游戏而言,可能需要调整单态实例的信号为打开。在默认情况下,Android会新建一个活动实例进程,因为它认为这是比较合适的,而游戏,可能只希望有一个活动的实例进程,这有一点儿影响,它需要了解一些系统状态的管理。
参考资料来源:百度百科-apk
参考资料来源:百度百科-android软件开发
Android中APK签名工具之jarsigner和apksigner详解
转自 https://www.cnblogs.com/slysky/p/9780015.html
一.工具介绍
jarsigner是JDK提供的针对jar包签名的通用工具,
位于JDK/bin/jarsigner.exe
apksigner是Google官方提供的针对Android apk签名及验证的专用工具,
位于Android SDK/build-tools/SDK版本/apksigner.bat
不管是apk包,还是jar包,本质都是zip格式的压缩包,所以它们的签名过程都差不多(仅限V1签名),
以上两个工具都可以对Android apk包进行签名.
1.V1和V2签名的区别
在Android Studio中点击菜单 Build->Generate signed apk... 打包签名有两种签名选项 V1(Jar Signature) V2(Full APK Signature),
从Android 7.0开始, 谷歌增加新签名方案 V2 Scheme (APK Signature);
但Android 7.0以下版本, 只能用旧签名方案 V1 scheme (JAR signing)
V1签名:
V2签名:
V2签名优点很明显:
注意: apksigner工具默认同时使用V1和V2签名,以兼容Android 7.0以下版本
2.zipalign和V2签名
位于Android SDK/build-tools/SDK版本/zipalign.exe
zipalign 是对zip包对齐的工具,使APK包内未压缩的数据有序排列对齐,从而减少APP运行时内存消耗
zipalign -v 4 in.apk out.apk //4字节对齐优化
zipalign -c -v 4 in.apk //检查APK是否对齐
zipalign可以在V1签名后执行
但zipalign不能在V2签名后执行,只能在V2签名之前执行!!!
二.签名步骤
1.生成密钥对(已有密钥库,可忽略)
Android Studio在Debug时,对App签名都会使用一个默认的密钥库:
1.生成密钥对
进入JDK/bin, 输入命令
参数:
提示: 可重复使用此条命令,在同一密钥库中创建多条密钥对 例如: 在debug.keystore中新增一对密钥,别名是release
keytool -genkeypair -keystore debug.keystore -alias release -validity 30000
2.查看密钥库
进入JDK/bin, 输入命令
keytool -list -v -keystore 密钥库名
参数:
例如: keytool -list -v -keystore debug.keystore
现在debug.keystore密钥库中有两对密钥, 别名分别是androiddebugkey release
2.签名
1.方法一(jarsigner,只支持V1签名)
进入JDK/bin, 输入命令
从JDK7开始, jarsigner默认算法是SHA256, 但Android 4.2以下不支持该算法,
所以需要修改算法, 添加参数 -digestalg SHA1 -sigalg SHA1withRSA
参数:
例如:
用JDK7及以上jarsigner签名,不支持Android 4.2 以下
jarsigner -keystore debug.keystore MyApp.apk androiddebugkey
用JDK7及以上jarsigner签名,兼容Android 4.2 以下
jarsigner -keystore debug.keystore -digestalg SHA1 -sigalg SHA1withRSA MyApp.apk androiddebugkey
2.方法二(apksigner,默认同时使用V1和V2签名)
进入Android SDK/build-tools/SDK版本, 输入命令
若密钥库中有多个密钥对,则必须指定密钥别名
禁用V2签名
apksigner sign --v2-signing-enabled false --ks 密钥库名 xxx.apk
参数:
例如:
在debug.keystore密钥库只有一个密钥对
apksigner sign --ks debug.keystore MyApp.apk
在debug.keystore密钥库中有多个密钥对,所以必须指定密钥别名
apksigner sign --ks debug.keystore --ks-key-alias androiddebugkey MyApp.apk
3.签名验证
1.方法一(keytool,只支持V1签名校验)
进入JDK/bin, 输入命令
keytool -printcert -jarfile MyApp.apk (显示签名证书信息)
参数:
2.方法二(apksigner,支持V1和V2签名校验)
进入Android SDK/build-tools/SDK版本, 输入命令
apksigner verify -v --print-certs xxx.apk
参数:
例如:
apksigner verify -v MyApp.apk
Android微信支付签名错误这个问题,你是怎么解决的?
有以下几种可能原因及解决办法:
body字段为中文字符串,但编码不合适,导致传输过程中中文成乱码
解决办法:统一改成其他编码如utf8字符形式传输
API密钥问题
在商户平台把API密钥重新设置就ok
参数名ASCII码未按升序排列,或者是生成MD5字符串没有toUpperCase转换为大写。
到微信官网上用校验工具校验即可。
key错误。这里特别注意,公众平台的密钥和商户号的密钥是不一样的!
微信支付审核成功之后会收到一封邮件,邮件中有appid 商户号,商户后台登录上号和密码,登录到商户后台:账户设置-安全设置-切换到API安全,下载证书,下面有一个api密匙,进去填写一个字符串 ,保存,后续两次签名都是用的这个手动设置的key
timeStamp在后台签名的时候S大写,前台上传的时候S小写
这个应该不会再出现了,因为微信已更正