Android签名机制可划分为两部分:(1)ROM签名机制;(2)第三方APK签名机制。

Android APK实际上是一个jar包,而jar包又是一个zip包。APK包的签名实际上使用的是jar包的签名机制:在zip中添加一个META的子目录,其中存放签名信息;而签名方法是为zip包中的每个文件计算其HASH值,得到签名文件(*.sf),然后对签名文件(.sf)进行签名并把签名保存在签名块文件(*.dsa)中。

ROM签名机制

在编译Android源码生成ROM的过程中,会使用build/target/product/security目录中的4个key(media, platform, shared, testkey)来对apk进行签名。其中,*.pk8是二进制形式(DER)的私钥,*.x509.pem是对应的X509公钥证书(BASE64编码)。build/target/product/security目录中的这几个默认key是没有密码保护的,只能用于debug版本的ROM。

要生成Release版本的ROM,可先生成TargetFiles,再使用带密码的key对TargetFiles重新签名,最后由重签名的TargetFiles来生成最终的ROM。

可以使用Android源码树中自带的工具“development/tools/make_key”来生成带密码的RSA公私钥对(实际上是通过openssl来生成的):

$ development/tools/make_key media ‘/C=CN/ST=Sichuan/L=Chengdu/O=MyOrg/OU=MyDepartment/CN=MyName’

上面的命令将生成一个二进制形式(DER)的私钥文件“media.pk8”和一个对应的X509公钥证书文件“media.x509.pem”。其中,/C表示“Country Code”,/ST表示“State or Province”,/L表示“City or Locality”,/O表示“Organization”,/OU表示“Organizational Unit”,/CN表示“Name”。前面的命令生成的RSA公钥的e值为3,可以修改development/tools/make_key脚本来使用F4 (0×10001)作为e值(openssl genrsa的-3参数改为-f4)。

也可以使用JDK中的keytool来生成公私钥对,第三方APK签名一般都是通过keytool来生成公私钥对的。

可以使用openssl x509命令来查看公钥证书的详细信息:

$ openssl x509 -in media.x509.pem -text -noout

or,

$ openssl x509 -in media.x509.pem -inform PEM -text -noout

还可以使用JDK中的keytool来查看公钥证书内容,但其输出内容没有openssl x509全面:

$ keytool -printcert -v -file media.x509.pem

有了key之后,可以使用工具“build/tools/releasetools/sign_target_files”来对TargetFiles重新签名:

$ build/tools/releasetools/sign_target_files_apks -d new_keys_dir -o target_files.zip target_files_resigned.zip

其中,new_keys_dir目录中需要有四个key(media, platform, shared, releasekey)。注意:这里的releasekey将代替默认的testkey(请参考build/tools/releasetools/sign_target_files脚本实现),也就是说,如果某个apk的Android.mk文件中的LOCAL_CERTIFICATE为testkey,那么在生成TargetFiles时是使用的build/target/product/security/testkey来签名的,这里重新签名时将使用new_keys_dir/releasekey来签名。

build/tools/releasetools/sign_target_files_apks是通过host/linux-x86/framework/signapk.jar来完成签名的。也可以直接使用host/linux-x86/framework/signapk.jar来对某个apk进行签名:

$ java -jar signapk [-w] publickey.x509[.pem] privatekey.pk8 input.jar output.jar

其中,”-w”表示还对整个apk包(zip包)进行签名,并把签名放在zip包的comment中。

第三方APK签名机制

对于第三方应用开发者而言,对APK签名相对要简单得多。第三方应用开发一般采用JDK中的keytool和jarsigner来完成签名密钥的管理和APK的签名。

使用keytool来生成存储有公私钥对的keystore:

$ keytool -genkey -v -keystore my-release-key.keystore -alias mykey -keyalg RSA -keysize 2048 -validity 10000

查看生成的密钥信息:

$ keytool -list -keystore my-release-key.keystore -alias mykey -v

or,

$ keytool -list -keystore my-release-key.keystore -alias mykey -rfc

(注:获取Base64格式的公钥证书,RFC 1421)

导出公钥证书:

$ keytool -export -keystore mystore -alias mykey -file my.der

(注:二进制格式公钥证书,DER)

$ keytool -export -keystore mystore -alias mykey -file my.pem -rfc

(注:Base64格式公钥证书,PEM)

对APK进行签名:

$ jarsigner -verbose -keystore my-release-key.keystore my_application.apk mykey

验证签名:

$ jarsigner -verify -verbose -certs my_application.apk

在进行Android二次开发时,有时需要把build/target/product/security下面的公私钥对转换为keystore的形式,可以参考这篇文章:把Android源码中的密码对转换为keystore的方法。

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐