关于Android 签名

2,226 阅读8分钟

Android系统禁止更新安装签名不一致的APK 如果应用需要使用system权限,必须保证APK签名与Framework签名一致

源码签名:

1.找到系统签名文件  文件路径:在源码的\build\target\product\security目录下有platform.x509pem和platform.pk8两个文件

image.png
2.把签名文件复制到\out\host\linux-x86\framework目录下
image.png
3.把预签名的apk复制到\out\host\linux-x86\framework目录下
image.png

使用:

java -jar signapk.jar platform.x509.pem platform.pk8 in.apk(预签名的apk) out.apk(签名之后的apk)
java -jar signapk.jar testkey.x509.pem testkey.pk8 源.apk  目标.apk

这条命令的意义是:通过signapk.jar这个可执行jar包,以“testkey.x509.pem”这个证书文件和“testkey.pk8”这个私钥文件对“源.apk”进行签名,签名后的文件保存为“目标.apk”

signapk.jar做了什么

signapk.jar是Android源码包中的一个签名工具

image.png

1、 Android签名机制其实是对APK包完整性和发布机构唯一性的一种校验机制。 2、 Android签名机制不能阻止APK包被修改,但修改后的再签名无法与原先的签名保持一致。(拥有私钥的情况除外)。 3、 APK包加密的公钥就打包在APK包内,且不同的私钥对应不同的公钥。换句话言之,不同的私钥签名的APK公钥也必不相同。所以可以根据公钥的对比,来判断私钥是否一致。

签名好的APK包中会多一个叫做META-INF的文件夹。里面有三个文件,分别名为MANIFEST.MF、CERT.SF和CERT.RSA。signapk.jar就是生成了这几个文件(其他文件没有任何改变。因此我们可以很容易去掉原有签名信息)。

signapk源码

  • MANIFEST.MF

程序遍历apk包中的所有文件(entry),对非文件夹非签名文件的文件(图片、资源xml、so、.dex) 逐个生成SHA1的数字签名信息,再用Base64进行编码

之后将生成的签名写入MANIFEST.MF文件

image.png

介绍下SHA1数字签名。简单地说,它就是一种安全哈希算法,类似于MD5算法。它把任意长度的输入,通过散列算法变成固定长度的输出(这 里我们称作“摘要信息”)。

不能仅通过这个摘要信息复原原来的信息。另外,它保证不同信息的摘要信息彼此不同。

因此,如果你改变了apk包中的文件,那 么在apk安装校验时,改变后的文件摘要信息与MANIFEST.MF的检验信息不同,于是程序就不能成功安装

  • CERT.SF

对前一步生成的Manifest,使用SHA1-RSA算法,用私钥进行签名

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

  • CERT.RSA

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

生成Framework签名一致的keystore

将.x509.pem 和.pk8导入keystore文件、或者**.jks文件** 需要openssl工具 、密钥和证书管理工具keytool ,并配置好环境变量

keytool工具
参数 解释
-certreq 生成证书请求
-changealias 更改条目的别名
-delete 删除条目
-exportcert 导出证书
-genkeypair 生成密钥对
-genseckey 生成密钥
-gencert 根据证书请求生成证书
-importcert 导入证书或证书链
-importpass 导入口令
-importkeystore 从其他密钥库导入一个或所有条目
-keypasswd 更改条目的密钥口令
-list 列出密钥库中的条目
-printcert 打印证书内容
-printcertreq 打印证书请求的内容
-printcrl 打印 CRL 文件的内容
-storepasswd 更改密钥库的存储口令

脚本生成

Bluebeard.zip

附件为脚本、framework签名证书和私钥文件 ,是从Android源码拷贝,用时需要替换自己平台的

  • 修改脚本

image.png

  • 运行脚本生成
./platform-to-keystore

脚本权限需要修改成可执行权限

  • 使用

将生成的签名文件放置AS使用

image.png

Android源码证书和私钥

以上都是system app开发这要掌握的  如果我从0开始做系统呢?如何生成自己系统的**.x509.pem** 、**.pk8

证书和私钥

每个密钥都包含两个文件:一个是扩展名为 .x509.pem 的证书,另一个是扩展名为 .pk8 的私钥。私钥需要加以保密,并用于对 apk 包进行签名。密钥本身也可能受密码保护。相比之下,证书只包含公开的一半密钥,因此可以大范围地分发。证书被用于验证某个 apk 包是否由相应的私钥进行签名。

标准 Android 版本使用四个密钥,所有这些密钥都位于 build/target/product/security 中:

  • testkey(testkey.pk8)

适用于未另外指定密钥的 apk 包的通用默认密钥。

  • 平台(platform.pk8)

适用于核心平台所包含的 apk 包的测试密钥。

  • 共享(shared.pk8)

适用于家庭/联系人进程中的共享内容的测试密钥。

  • 媒体(media.pk8)

适用于媒体/下载系统所包含的 apk 包的测试密钥

单个 apk 包通过在其 Android.mk 文件中设置 LOCAL_CERTIFICATE 来指定其中一个密钥。(如果未设置此变量,则使用 testkey。)

自动生成密钥

Android 树的 build/target/product/security 目录中提供了测试密钥。使用 make 编译 Android 操作系统映像便可使用这些测试密钥对所有 .apk 文件进行签名。由于这些测试密钥是公开的,任何人都可以使用相同的密钥对他们自己的 .apk 文件签名,这样他们就能够替换或盗用您的操作系统映像中编译的系统应用。因此,必须使用只有自己才能访问的特殊“发布密钥”集对公开发布或部署的 Android 操作系统映像进行签名。

要生成自己的唯一发布密钥集,请在 Android 树的根目录下运行以下命令:

subject='/C=US/ST=California/L=Mountain View/O=Android/OU=Android/CN=Android/emailAddress=android@android.com'
mkdir ~/.android-certs
for x in releasekey platform shared media; do \
    ./development/tools/make_key ~/.android-certs/$x "$subject"; \
  done
  
  //输入自己的密码 我输入的:123456

image.png

手动生成密钥

Android 使用公开指数为 3 的 2048 位 RSA 密钥。您可以使用 openssl.org 提供的 openssl 工具来生成证书/私钥对:

  • generate RSA key
openssl genrsa -3 -out chrisli.pem 2048

image.png

  • create a certificate with the public part of the key
openssl req -new -x509 -key chrisli.pem -out chrisli.x509.pem -days 1000000 -subj '/C=US/ST=California/L=San Narciso/O=chrisli, Inc./OU=chrisli Mobility/CN=chrisli/emailAddress=chrisli@example.com'
  • create a PKCS#8-formatted version of the private key
openssl pkcs8 -in chrisli.pem -topk8 -outform DER -out chrisli.pk8 -nocrypt

上述 openssl pkcs8 命令可创建一个适用于该版本系统的 .pk8 文件,该文件未设置密码。要创建一个带有密码保护的 .pk8 文件(应当为所有实际的发布密钥执行此步骤),请将 -nocrypt 参数替换为 -passout stdin;这样 openssl 将使用从标准输入中读取的密码来加密私钥。该过程中不会输出任何提示。因此,当系统确实只是在等待您输入密码时,如果 stdin 是终端,程序将会处于挂起状态。可以对 Passout 参数使用其他值,以便从其他位置读取密码

openssl pkcs8 -in chrisli.pem -topk8 -outform DER -out chrisli.pk8 -passout stdin

image.png

  • **最后删除临时文件chrisli.pem **

chrisli.pem 中间文件包含不受任何类型的密码保护的私钥,因此在生成发布密钥时应谨慎处理该文件

shred --remove chrisli.pem

image.png

jarsigner、keytool工具

jarsigner -verbose -keystore demo.keystore -signedjar test_signed.apk test.apk mykey
#    test_signed.apk是签名之后的文件
#    test.apk是需要签名的文件

另外需要注意的是,如果你的jdk版本在1.7以上,你在对apk签名时,需要加上这个参数:

-digestalg SHA1 -sigalg MD5withRSA

否则同样会出现:Failure [INSTALL_PARSE_FAILED_NO_CERTIFICATES]的错误。

jarsigner -verbose -keystore platform.keystore -signedjar  xlog.apk  xlogging-sample-debug.apk spacebridge -digestalg SHA1 -sigalg MD5withRSA

几种常用命令

1、查看keystore的信息

keytool -list -keystore demo.keystore -alias mykey -v

image.png

2、查看keystore的公钥证书信息

keytool -list -keystore demo.keystore -alias mykey -rfc

image.png

(注:获取Base64格式的公钥证书,RFC 1421) 3、查看apk的签名信息

jarsigner -verify -verbose -certs <your_apk_path.apk>

apk安装签名解析

Android系统安装程序肯定会获取APK信息进行比对,所以]可以通过Android源码获得一些思路和帮助。  apk安装是PackageParser负责解析安装包

PackageParser负责AndroidManifest(applicationInfo、Version、mSharedUserId、permissions、四大组件等)、签名读取解析

image.png

PackageParser 源码路径:

/frameworks/base/core/java/android/content/pm

三方app开发签名

三方开发就是普通的app开发不需要系统签名,开发出来的app运行在各个厂商的Android系统上,没有特殊要求,直接使用AS生成