Android签名概括:

在Android 系统中,所有安装到系统的应用程序都必有一个数字证书,这个数字证书就是这个应用的签名。此数字证书用于标识应用程序的作者和在应用程序之间建立信任关系,如果一个 permission的protectionLevel为signature,那么就只有那些跟该permission所在的程序拥有同一个数字证书的应 用程序才能取得该权限。这个数字证书并不需要权威的数字证书签名机构认证,它只是用来让应用程序包自我认证的。

Android签名作用:

为了保证每个应用程序开发商合法ID,防止部分开放商可能通过使用相同的Package Name来混淆替换已经安装的程序,冒充原来的应哟功能。我们需要对我们发布的APK文件进行唯一签名,保证我们每次发布的版本的一致性(如自动更新不会因为版本不一致而无法安装)。

概括起来有以下几点:

(1 )  发送者的身份认证

(2)保证输入信息的完整性

(3)防止交易中的抵赖发生

Android签名方法:

方法一: 使用keytool和jarsigner命令

创建key,需要用到 keytool,使用产生的key对apk签名用到的是jarsigner。

keytool -genkey -alias demo.keystore -keyalg RSA -validity 40000 -keystore demo.keystore

/*说明:-genkey 产生密钥

-alias demo.keystore 别名 demo.keystore

-keyalg RSA 使用RSA算法对签名加密

-validity 40000 有效期限4000天

-keystore demo.keystore */

jarsigner -verbose -keystore demo.keystore -signedjar demo_signed.apk demo.apk demo.keystore

说明:-verbose 输出签名的详细信息

-keystore  demo.keystore 密钥库位置

-signedjar demor_signed.apk demo.apk demo.keystore 正式签名,三个参数中依次为签名后产生的文件demo_signed,要签名的文件demo.apk和密钥库demo.keystore.

查看密钥信息

keytool -printcert -v -file miyao.cer 
keytool -list -keystore debug.keystore

方法二: 使用signapk 工具

java -jar signapk.jar platform.x509.pem platform.pk8 MyDemo.apk MyDemo_signed.apk

signapk的参数分别为公钥,私钥,需要签名的apk,签名后的apk

使用源码内置的签名可以获取系统的不同权限。

签名之后,可以用zipalign(压缩对齐)优化APK文件

zipalign -v 4 demo_signed.apk final.apk

Android源码打包apk分析

使用andorid源码打包apk是使用signapk签名的,我们分析一下这个过程

1、生成MANIFEST.MF文件:

程序遍历app包中的所有文件(entry),对非文件夹非签名文件的文件,逐个生成SHA1的数字签名信息,再用Base64进行编码。具体代码见这个方法:

private static Manifest addDigestsToManifest(JarFile jar)

    /** Add the SHA1 of every file to the manifest, creating it if necessary. */private static Manifest addDigestsToManifest(JarFile jar)throws IOException, GeneralSecurityException {Manifest input = jar.getManifest();Manifest output = new Manifest();Attributes main = output.getMainAttributes();if (input != null) {main.putAll(input.getMainAttributes());} else {main.putValue("Manifest-Version", "1.0");main.putValue("Created-By", "1.0 (Android SignApk)");}MessageDigest md = MessageDigest.getInstance("SHA1");byte[] buffer = new byte[4096];int num;// We sort the input entries by name, and add them to the// output manifest in sorted order.  We expect that the output// map will be deterministic.TreeMap<String, JarEntry> byName = new TreeMap<String, JarEntry>();for (Enumeration<JarEntry> e = jar.entries(); e.hasMoreElements(); ) {JarEntry entry = e.nextElement();byName.put(entry.getName(), entry);}for (JarEntry entry: byName.values()) {String name = entry.getName();if (!entry.isDirectory() &&(stripPattern == null || !stripPattern.matcher(name).matches())) {InputStream data = jar.getInputStream(entry);while ((num = data.read(buffer)) > 0) {md.update(buffer, 0, num);}Attributes attr = null;if (input != null) attr = input.getAttributes(name);attr = attr != null ? new Attributes(attr) : new Attributes();attr.putValue("SHA1-Digest",new String(Base64.encode(md.digest()), "ASCII"));output.getEntries().put(name, attr);}}return output;}

之后将生成的签名写入MANIFEST.MF文件。关键代码如下:

    private static void signFile(Manifest manifest, JarFile inputJar,X509Certificate[] publicKey, PrivateKey[] privateKey,JarOutputStream outputJar)throws Exception {// Assume the certificate is valid for at least an hour.long timestamp = publicKey[0].getNotBefore().getTime() + 3600L * 1000;JarEntry je;// Everything elsecopyFiles(manifest, inputJar, outputJar, timestamp);// MANIFEST.MFje = new JarEntry(JarFile.MANIFEST_NAME);je.setTime(timestamp);outputJar.putNextEntry(je);manifest.write(outputJar);int numKeys = publicKey.length;for (int k = 0; k < numKeys; ++k) {// CERT.SF / CERT#.SFje = new JarEntry(numKeys == 1 ? CERT_SF_NAME :(String.format(CERT_SF_MULTI_NAME, k)));je.setTime(timestamp);outputJar.putNextEntry(je);ByteArrayOutputStream baos = new ByteArrayOutputStream();writeSignatureFile(manifest, baos);byte[] signedData = baos.toByteArray();outputJar.write(signedData);// CERT.RSA / CERT#.RSAje = new JarEntry(numKeys == 1 ? CERT_RSA_NAME :(String.format(CERT_RSA_MULTI_NAME, k)));je.setTime(timestamp);outputJar.putNextEntry(je);writeSignatureBlock(new CMSProcessableByteArray(signedData),publicKey[k], privateKey[k], outputJar);}}

SHA1数字签名。简 单地说,它就是一种安全哈希算法,类似于MD5算法。它把任意长度的输入,通过散列算法变成固定长度的输出(这里我们称作“摘要信息”)。你不能仅通过这 个摘要信息复原原来的信息。另外,它保证不同信息的摘要信息彼此不同。因此,如果你改变了apk包中的文件,那么在apk安装校验时,改变后的文件摘要信息与MANIFEST.MF的检验信息不同,于是程序就不能成功安装。

2、生成CERT.SF文件:

对前一步生成的Manifest,使用SHA1-RSA算法,用私钥进行签名。关键代码如下:

  private static void writeSignatureFile(Manifest manifest, OutputStream out)throws IOException, GeneralSecurityException {Manifest sf = new Manifest();Attributes main = sf.getMainAttributes();main.putValue("Signature-Version", "1.0");main.putValue("Created-By", "1.0 (Android SignApk)");MessageDigest md = MessageDigest.getInstance("SHA1");PrintStream print = new PrintStream(new DigestOutputStream(new ByteArrayOutputStream(), md),true, "UTF-8");// Digest of the entire manifestmanifest.write(print);print.flush();main.putValue("SHA1-Digest-Manifest",new String(Base64.encode(md.digest()), "ASCII"));Map<String, Attributes> entries = manifest.getEntries();for (Map.Entry<String, Attributes> entry : entries.entrySet()) {// Digest of the manifest stanza for this entry.print.print("Name: " + entry.getKey() + "\r\n");for (Map.Entry<Object, Object> att : entry.getValue().entrySet()) {print.print(att.getKey() + ": " + att.getValue() + "\r\n");}print.print("\r\n");print.flush();Attributes sfAttr = new Attributes();sfAttr.putValue("SHA1-Digest",new String(Base64.encode(md.digest()), "ASCII"));sf.getEntries().put(entry.getKey(), sfAttr);}CountOutputStream cout = new CountOutputStream(out);sf.write(cout);// A bug in the java.util.jar implementation of Android platforms// up to version 1.6 will cause a spurious IOException to be thrown// if the length of the signature file is a multiple of 1024 bytes.// As a workaround, add an extra CRLF in this case.if ((cout.size() % 1024) == 0) {cout.write('\r');cout.write('\n');}}

RSA是一种非对称加密算法。用私钥通过RSA算法对摘要信息进行加密。在安装时只能使用公钥才能解密它。解密之后,将它与未加密的摘要信息进行对比,如果相符,则表明内容没有被异常修改。

3、生成CERT.RSA文件:

生成MANIFEST.MF没有使用密钥信息,生成CERT.SF文件使用了私钥文件。那么我们可以很容易猜测到,CERT.RSA文件的生成肯定和公钥相关。

CERT.RSA文件中保存了公钥、所采用的加密算法等信息。

生成CERT.RSA文件:核心代码如下:

            // CERT.RSA / CERT#.RSAje = new JarEntry(numKeys == 1 ? CERT_RSA_NAME :(String.format(CERT_RSA_MULTI_NAME, k)));je.setTime(timestamp);outputJar.putNextEntry(je);writeSignatureBlock(new CMSProcessableByteArray(signedData),publicKey[k], privateKey[k], outputJar);

总结分析:

分根据APK包的签名流程,我们可以意识到:

1、 Android签名机制其实是对APK包完整性和发布机构唯一性的一种校验机制。

2、 Android签名机制不能阻止APK包被修改,但修改后的再签名无法与原先的签名保持一致。(拥有私钥的情况除外)。

3、 APK包加密的公钥就打包在APK包内,且不同的私钥对应不同的公钥。换句话言之,不同的私钥签名的APK公钥也必不相同。所以我们可以根据公钥的对比,来判断私钥是否一致。

4、签名是不对META-INF的文件校验的,可以利用这个漏洞做一些事情。比如快速动态做渠道标记

签名对App的影响

1) App升级。 使用相同签名的升级软件可以正常覆盖老版本的软件,否则系统比较发现新版本的签名证书和老版本的签名证书不一致,不会允许新版本安装成功的。

2) App模块化。android系统允许多个安装包的App运行在同一个进程中,如果运行在同一个进程中,则他们相当于同一个App,但是你可以单独对他们升级更新,这是一种App级别的模块化思路。

3) 允许代码和数据共享。android中提供了一个基于签名的Permission标签。通过允许的设置,我们可以实现对不同App之间的访问和共享

签名安全性问题:

在app的AndroidManifest.xml中加上 android:sharedUserId="android.uid.system"然后使用目标系统的platform密钥来重新给apk文件签名。这首先找到密钥文件,在Android源码目录中的位置 是“build\target\product\security”,下面的platform.pk8和platform.x509.pem两个文件。然 后用Android提供的Signapk工具来签名,signapk的源代码是在“build\tools\signapk”下,用法为“signapk platform.x509.pem platform.pk8 input.apk output.apk”,文件名最好使用绝对路径防止找不到,也可以修改源代码直接使用。这样修改后的应用就会获取系统权限。

签名的验证过程

​安装apk时,通过CERT.RSA查找公钥和算法,并对CERT.SF进行解密和签名验证,确认MANIFEST.MF,最终对每个文件签名校验。

升级时,android也会进行签名验证。如果遇到以下情况,都不能完成升级:

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

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

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

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

5)     安装未签名的程序。

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

欢迎扫描二维码,相互学习。

Android签名与风险分析相关推荐

  1. android签名的应用-- 禁止未经授权签名的apk安装

    点击打开链接 最近项目有需求: 只有使用特定签名签的apk才可以安装,其他任何apk都不能安装(root版,使用adb push进去的除外).n多度娘.google之后最终实现,把实现代码罗列一下,以 ...

  2. 安装安全类软件进行了android签名漏洞修补,魅族MX3怎么升级固件体验最新比较稳定的版本...

    魅族mx3固件怎么升级?flyme os系统会持续更新,升级魅族MX3手机系统需先下载MX3的升级固件,升级固件分为体验版和稳定版.魅族MX3固件有体验版和稳定版两种,顾名思义,体验版为最新版但相比稳 ...

  3. android digest 认证,探究 Android 签名机制和原理

    背景 最近在调研一个测试工具的使用,在使用中发现被测试工具处理过的apk文件经安装后打开就会崩溃,分析崩溃日志后原因是签名不一致导致的. 说到Android中的签名,可能大家都知道签名的目的就是为了保 ...

  4. Android签名机制---签名过程

    大神文章:http://blog.csdn.net/jiangwei0910410003/article/details/50402000 一.知识点 1.数据摘要(数据指纹).签名文件,证书文件 2 ...

  5. Android签名详解(debug和release)

    Android签名详解(debug和release) 1. 为什么要签名 1) 发送者的身份认证 由于开发商可能通过使用相同的Package Name来混淆替换已经安装的程序,以此保证签名不同的包不被 ...

  6. Android签名与认证详细分析之二(CERT.RSA剖析)

    一.Android证书的格式 Android签名中证书的格式采用X.509标准的版本三,不过省略了一些内容. X.509证书格式如下图所示: 二.证书的格式示例 从Chrome浏览器中导出一个证书,打 ...

  7. Android签名打包详解

    一.      Android签名有什么作用? 应用程序升级:如果你希望用户无缝升级到新的版本,那么你必须用同一个证书进行签名.这是由于只有以同一个证书签名,系统才会允许安装升级的应用程序.如果你采用 ...

  8. Android签名证书

    在最新的Android SDK中我们看到了Android签名证书机制的出现,也就是说几乎和Symbian OS v9.x以上平台构架一样,都需要数字签名证书才可以运行,这也是考虑到平台的安全性,同样也 ...

  9. Android签名 - APK签名系统SignApk.jar

    signapk.jar是Android源码包中的一个签名工具. 代码位于:Android源码目录下,signapk.jar 可以编译build/tools/signapk/ 得到. 使用signapk ...

  10. Android签名与校验过程详解

    原文:https://blog.csdn.net/gulinxieying/article/details/78677487 目 录 一.签名与校验原理概要    2 1.数字签名简介    2 2. ...

最新文章

  1. ASP.NET Core的身份认证框架IdentityServer4(4)- 支持的规范
  2. ML之NB:利用朴素贝叶斯NB算法(TfidfVectorizer+不去除停用词)对20类新闻文本数据集进行分类预测、评估
  3. selinux会阻碍挂载嘛_为什么追求完美可能会阻碍您成为新手Web开发人员
  4. 运算符 优先级 结合性
  5. CentOS 利用Yum安装mysql后无法启动(MySQL Daemon failed to start.)
  6. 单例设计模式之间的区别
  7. 问答项目---登陆验证码点击切换及异步验证验证码
  8. 2018上半年广东省中小学教师资格认定流程
  9. python如何清屏_python如何清屏
  10. shp地图如何导入奥维地图手机_奥维地图如何导入路线数据?
  11. ERROR: Unable to access 'C:\Users\鏉庨摥\.emulator_console_auth_token': emulator consol...解决方法
  12. python修改微信和支付宝步数
  13. 关于 nscd,nslcd 和 sssd 套件的综述
  14. 520、Java Spring Cloud Alibaba -【Spring Cloud Alibaba Zuul】 2021.11.02
  15. 金立android 7.1.1,金立K30Pro正式上市:运行安卓7.1.1系统,699元起
  16. 【已解决】python读取ods:linux中ods文件内容无法访问,代码无法测试;shuffle的作用:随机从数据集里面读取大小为batch_size的数据
  17. mtk-keypad
  18. Ubuntu与WIndows桌面间切换
  19. 009仓储物流中心里的人机工程学设计
  20. vc++ 读书笔记(摘抄)

热门文章

  1. 数字臧品系统开发运行逻辑数字臧品系统开发源码搭建流程
  2. PCL RANSAC点云配准
  3. hbase常用命令及操作
  4. FFmpeg连载2-分离视频和音频
  5. linux下命令打开url,在linux命令下访问url
  6. 485接口EMC电路设计方案
  7. Sequencher_v4.1.4 DNA 序列分析的工业标准软件
  8. java并发编程电子书免费送???
  9. 软件工程导论-软件工程概论(学习笔记)
  10. 暮光之城4下高清下载地址|暮光之城4第二部高清下载地址