准备知识:数据摘要

这个知识点很好理解,百度百科即可,其实他也是一种算法,就是对一个数据源进行一个算法之后得到一个摘要,也叫作数据指纹,不同的数据源,数据指纹肯定不一样,就和人一样。

消息摘要算法(Message Digest Algorithm)是一种能产生特殊输出格式的算法,其原理是根据一定的运算规则对原始数据进行某种形式的信息提取,被提取出的信息就被称作原始数据的消息摘要。
著名的摘要算法有RSA公司的MD5算法和SHA-1算法及其大量的变体。
消息摘要的主要特点有:
1)无论输入的消息有多长,计算出来的消息摘要的长度总是固定的。例如应用MD5算法摘要的消息有128个比特位,用SHA-1算法摘要的消息最终有160比特位的输出。
2)一般来说(不考虑碰撞的情况下),只要输入的原始数据不同,对其进行摘要以后产生的消息摘要也必不相同,即使原始数据稍有改变,输出的消息摘要便完全不同。但是,相同的输入必会产生相同的输出。
3)具有不可逆性,即只能进行正向的信息摘要,而无法从摘要中恢复出任何的原始消息。

一 Android签名机制及原理

Android系统在安装APK的时候,首先会检验APK的签名,如果发现签名文件不存在或者校验签名失败,则会拒绝安装,所以应用程序在发布之前一定要进行签名。给APK签名可以带来以下好处:

应用程序升级

如果想无缝升级一个应用,Android系统要求应用程序的新版本与老版本具有相同的签名与包名。若包名相同而签名不同,系统会拒绝安装新版应用。

应用程序模块化

Android系统可以允许同一个证书签名的多个应用程序在一个进程里运行,系统实际把他们作为一个单个的应用程序。此时就可以把我们的应用程序以模块的方式进行部署,而用户可以独立的升级其中的一个模块。

代码或数据共享

Android提供了基于签名的权限机制,一个应用程序可以为另一个以相同证书签名的应用程序公开自己的功能与数据,同时其它具有不同签名的应用程序不可访问相应的功能与数据。

应用程序的可认定性

签名信息中包含有开发者信息,在一定程度上可以防止应用被伪造。例如网易云加密对Android APK加壳保护中使用的“校验签名(防二次打包)”功能就是利用了这一点。

签名原理

对一个APK文件签名之后,APK文件根目录下会增加META-INF目录,该目录下增加三个文件:

MANIFEST.MF

NETEASE.RSA

NETEASE.SF

其中.RSA文件还可能是.DSA文件,RSA与SF文件的文件名可以更改,但是它们的命名必须一样。

MANIFEST.MF中保存了APK里所有文件的SHA1校验值的BASE64编码,格式如下(一个文件对应一条记录):

Name: res/anim/abc_fade_in.xml

SHA1-Digest: ohPEA4mboaFUu9LZMUwk7FmjbPI=

Name: res/anim/abc_fade_out.xml

SHA1-Digest: MTJWZc22b5LNeBboqBhxcQh5xHQ=

SF文件里保存了MANIFEST.MF文件的SHA1校验值的BASE64编码,同时还保存了MANIFEST.MF中每一条记录的SHA1检验值BASE64编码,格式如下:

SHA1-Digest-Manifest: ZRhh1HuaoEKMn6o21W1as0sMlaU=

Name: res/anim/abc_fade_in.xml

SHA1-Digest: wE1QEZhFkLBWMw4TRtxPdsiMRtA=

Name: res/anim/abc_fade_out.xml

SHA1-Digest: MfCV1efdxSKtesRMF81I08Zyvvo=

RSA文件则包含了签名的公钥、签名所有者等信息,还保存了http://my.oschina.net/u/816213/blog/685762?fromerr=RSS3IhKo用SHA1withRSA签名算法对SF文件的签名结果信息。

Android系统就是根据这三个文件的内容对APK文件进行签名检验的。

二 Android 签名方法

1、apksign、jarsinger

一般的签名过程可以由apksign.jar或者jarsinger.jar完成。apksign.jar由Android SDK提供,使用方法如下:

java -jar signapk.jar testkey.x509.pem testkey.pk8 update.apk update_signed.apk

它接受一个PEM公钥文件,PK8私钥文件,对update.apk进行签名,签名后的文件保存到update_signed.apk。

jarsinger是由JDK提供,使用方法如下:

jarsigner -verbose -keystore d:\\debug.keystore -signedjar update_signed.apk update.apk androiddebugkey -digestalg SHA1 -sigalg MD5withRSA -keypass android -storepass android

其中:

-keystore表示keystore文件的路径

androiddebugkey 表示keystore中的一个别名

-digestalg表示摘要算法

-sigalg 表示签名算法

-keypass 表示别名密码

-storepass表示keystore密码

经过测试,发现以上两个传统的签名工具存在以下缺点:

1)、jarsigner在对一个已经有META-INF目录的APK进行签名的时候,有可能会报错:

jarsigner: 无法对 jar 进行签名: java.util.zip.ZipException: invalid entry compressed size (expected 1368 but got 1379 bytes)

2)、如果APK中已经有签名文件且签名文件中的RSA(或DSA)、SF文件的命名不是CERT的时候,用这两个签名工具进行签名后,会出现:

META-INF目录下会有两个RSA/SF文件,会导致APK在安装的时候失败。

3)、签名花费时间长。这两个签名工具在生成签名后的APK时,是按Zip中一个entry接一个entry 依次拷贝的,效率十分低。因为游戏类型APK类文件数量一般比较多,所以这一缺陷在签名游戏类型APK时,体现得尤为明显。

2、极速签名工具(ApkSinger)

极速签名工具克服了signapk.jar与jarsigner在签名过程的缺点,使用方法:

java -jar ApkSigner.jar [-appname test] -keystore keystorePath -alias alias [-pswd password] [-aliaspswd aliasPassword] apkPath(or directory)

-appname 待签名的应用程序名,可选,但建议不同的APP填上对应的app名

-keystore 后跟.keystore签名文件

-alias 后跟签名别名

-pswd 后跟对应签名的密码,可选,如果不填,则签名的时候需要手动输入

-aliaspswd 对应别名alias的密码,如果没有则默认使用keystore Password

最后跟待签名的APK路径或者目录路径 ,如果跟的是目录则是批量签名.

三、为何要这么来签名

上面我们就介绍了签名apk之后的三个文件的详细内容,那么下面来总结一下,Android中为何要用这种方式进行加密签名,这种方加密是不是最安全的呢?下面我们来分析一下,如果apk文件被篡改后会发生什么。

首先,如果你改变了apk包中的任何文件,那么在apk安装校验时,改变后的文件摘要信息与MANIFEST.MF的检验信息不同,于是验证失败,程序就不能成功安装。
其次,如果你对更改的过的文件相应的算出新的摘要值,然后更改MANIFEST.MF文件里面对应的属性值,那么必定与CERT.SF文件中算出的摘要值不一样,照样验证失败。
最后,如果你还不死心,继续计算MANIFEST.MF的摘要值,相应的更改CERT.SF里面的值,那么数字签名值必定与CERT.RSA文件中记录的不一样,还是失败。
那么能不能继续伪造数字签名呢?不可能,因为没有数字证书对应的私钥。
所以,如果要重新打包后的应用程序能再Android设备上安装,必须对其进行重签名。

从上面的分析可以得出,只要修改了Apk中的任何内容,就必须重新签名,不然会提示安装失败,当然这里不会分析,后面一篇文章会注重分析为何会提示安装失败。

[转]Android APK签名原理及方法的更多相关文章

  1. Android : apk签名的多种方法以及key的配置

    方法一:使用Android SDK中的签名工具给apk签名: (1)Android源码的 build/target/product/security/ 目录下有 media.pk8.media.x50 ...

  2. android apk签名原理

    //这个md5跟腾讯的对应 public Signature getPackageSignature( ){ Context context=getContext(); String packageN ...

  3. APK签名原理

    网上已有多篇分析签名的类似文章,但是都有一个共同的问题,就是概念混乱,混乱的一塌糊涂. 在了解APK签名原理之前,首先澄清几个概念: 消息摘要 -Message Digest 简称摘要,请看英文翻译, ...

  4. Android APK 签名比对(转)

    Android apk签名的过程 1. 生成MANIFEST.MF文件: 程序遍历update.apk包中的所有文件(entry),对非文件夹非签名文件的文件,逐个生成SHA1的数字签名信息,再用Ba ...

  5. Android APK 签名 (转发)

    Cordova 3.5 为 Android APK 签名,生成可发布的 APK 程序文件  任侠  2014-06-07 00:04  移动开发  抢沙发  16,288 views  目录 [隐藏] ...

  6. Android apk签名详解——AS签名、获取签名信息、系统签名、命令行签名

    Apk签名,每一个Android开发者都不陌生.它就是对我们的apk加了一个校验参数,防止apk被掉包.一开始做Android开发,就接触到了apk签名:后来在微信开放平台.高德地图等平台注册时,需要 ...

  7. Android apk签名的两种方法

    编辑推荐:稀土掘金,这是一个针对技术开发者的一个应用,你可以在掘金上获取最新最优质的技术干货,不仅仅是Android知识.前端.后端以至于产品和设计都有涉猎,想成为全栈工程师的朋友不要错过! 为了保证 ...

  8. Android apk签名方法介绍

    还望支持个人博客站:http://www.enjoytoday.cn 参考博客:http://www.enjoytoday.cn/posts/203 为什么要签名 在介绍签名方法之前,首先我们来了解下 ...

  9. apk签名原理及实现

    发布过Android应用的朋友们应该都知道,Android APK的发布是需要签名的.签名机制在Android应用和框架中有着十分重要的作用. 例如,Android系统禁止更新安装签名不一致的APK: ...

随机推荐

  1. 百度dureos CMake Error

    CMake Error: CMAKE_C_COMPILER not set, after EnableLanguage CMake Error: CMAKE_CXX_COMPILER not set, ...

  2. iOS 如何改变表视图分割线在iOS7中的默认偏移

    - (void)viewDidLoad { [super viewDidLoad]; self.automaticallyAdjustsScrollViewInsets = NO; if ([self ...

  3. C语言一个单链表的实现

    -- 所谓链表记住一句即可:地址不连续,大家只是握个手而已: list0.c #include<stdio.h> #include<malloc.h> typedef int ...

  4. HDU4283 You Are the One —— 区间DP

    题目链接:https://vjudge.net/problem/HDU-4283 You Are the One Time Limit: 2000/1000 MS (Java/Others)    M ...

  5. MYSQL初级学习笔记六:子查询!(视频序号:初级_42 | 43)

    知识点八:子查询(42) 什么是子查询: 子查询是将一个查询语句嵌套在另一个查询语句中.内层查询语句的查询结果,可以作为外层查询语句提供条件. 引发子查询的情况: 使用[NOT] IN 的子查询 -- ...

  6. Servlet的HelloWorld

    设置好TOMCAT环境变量(如何设置?)后在命令行输入startup可以启动Tomcat,输入shutdown可以关闭Tomcat. /WEB-INF/web.xml是称为部署描述器的配置文件,Jav ...

  7. 安装ubuntu gnome 16.04后的一些操作

    好吧...其实安装了挺久了,记录一下以防忘记... 1.软件 chrome浏览器 唔..自己去官网下吧.. gnome tweak tool 不用多说,必备 sudo apt-get install  ...

  8. 在msys里进行复制和粘贴操作

    You can copy text from an MSYS window to the clipboard simply by selecting the text you want to copy ...

  9. 字体的设置 REM EM PX

    px 1 一般设置页面的字体使用px 2 优点:字体设置比较稳定和精确 3 缺点:他会修改用户浏览器中的字体大小 EM 相对于父元素的字体大小,字体大小不确定,容易混乱,“em”是相对于其父元素来设置 ...

  10. Task运行带参数的函数

    Task<Int32>   task = Task.Run(() => fun("s", 9)); 函数定义: private Int32 frun(string ...