关于Android App签名和证书

关于Android app的证书和签名的相关基础知识。

1.Android系统预装App

如下图,我们可以在Android手机的system/app目录下找到手机上安装的所有预装App的安装包(.apk文件)。

2.检查App的证书和签名

META-INF文件夹

解压apk文件之后,找到META-INF文件夹,其中包含以下3个关键文件。

  • MANIFEST.MF
  • CERT.SF
  • CERT.RSA

MANIFEST.MF

公钥证书的自签名,可以用 Java JDK自带的 keytool 工具查看其中的内容,包括公钥的持有者等。

这是个X.509 V3证书。其中的信息是由 keytool工具的以下5个域组成的。

  1. Owner(持有者):这个域是用来声明公钥的持有者的。其中包含与该个体相关的国家和组织的基本信息。
  2. Issuer(颁发者):这个域是用来声明X.509证书的颁发者的,用来把公钥和声明的持有者关联起来。这里提到是能为密钥的持有者提供有效担保的人或组织。他们是为证书中列出的公钥提供可靠性保证的人。
  3. Serial number(序列号):这被用作颁发者证书的一个标示符。
  4. Valid from…, until:这个域指定了证书的有效期,其关联的属性可以由颁发者验证。
  5. Certificate fingerprints:这个域中记录的是证书的数字校验和。它被用来验证证书是不是被篡改过了的。

CERT.SF

这个文件可以直接用记事本等文本编辑器打开,包含了app中的所有资源文件,它负责对app进行签名,其中含有JAR指定的密码学意义上的签名。其中含有app中的各个资源文件的密码学意义上的hash。

在使用 Jarsigner 工具验证app的内容时,这个文件就能派上用场。它会计算CERT.SF文件中列出的、各个资源文件的密码学意义上的hash,并将其与列在各个资源文件边上的数字进行比较。

MANIFEST.MF

这个文件声明了资源,与 CERT.SF 文件非常相似。

安全隐患

数字签名的计算方法是用可信第三方的私钥加密证书。在大多数 Android app中这个“可信第三方”就是开发者。这也就意味着这个签名是用他/她的私钥(通常是和公钥相关的)加密证书而生成的。这样使用数字签名可能从功能上是正确的—它在功能上确实是使用了电子签名机制—一但并不像依赖于数字证书认证机构(Certificate Authority,CA)那样的强壮。毕竟任何一个人都可以用他自己的密钥对app签名,从而声称自己开发了推特(Twitter)的app,但是没人能够说自己有Verisign或赛门铁克的私钥!

Android包管理器在验证颁发者、持有者或证书中其他细节的有效性或实体是否真实存在这一问题上是完全无能为力的。例如:“持有者”根本无须提交任何关于开发者的有效个人信息,“颁发者”也完全有可能是凭空捏造出来的组织或个人。

在linux使用OpenSSL库查看公钥证书

3.对Android App签名

Android App中的签名,实际上就是对于JAR的签名机制的使用和改进。

如何替换App中的签名?

1.解压原apk,删除其中的META-INF文件夹。
2.依次输入以下命令完成对apk的签名。

keytool -genkey -v -keystore [keystore的名称] -alias [你密钥的别名] -keyalg RSA -keysize 2048 -validity [有效天数]
//创建一个带名字的,在它的内部安全地存放着你的新的私、公钥,自签名的证书,并被加密保护起来了的密钥存储器

jarsigner -verbose -sigalg MD5withRSA -digestalg SHA1 -keystore [你的keystore的名字] [你的.apk文件] [你密钥的别名]
//执行此命令,用上一条命令创建的新的带名字的密钥存储器去对一个app进行签名。

关于keytool所用参数

关于jarsigner所用参数

验证App的签名

4.遇到的错误情况

如果没有对apk进行签名就直接安装,那么会安装失败并报错如下图。