1、如何对APK签名
(1)、创建数字证书,android123.keystore
keytool -genkey -alias android123.keystore -keyalg RSA -validity 20000 -keystore android123.keystore
keytool工具是Java JDK自带的证书工具
-genkey参数表示:要生成一个证书(版权、身份识别的安全证书)
-alias参数表示:证书有别名,-alias android123.keystore表示证书别名为android123.keystore
-keyalg RSA表示加密类型,RSA表示需要加密,以防止别人盗取
-validity 20000表示有效时间20000天
-keystore android123.keystore表示要生成的证书名称为android123.keystore
Enter key password for <android123.keystore>
(RETURN if same as keystore password):此时按回车
生成的数字证书android123.keystore里面包换了非对称加密的私钥、公钥和证书。
(2)、使用数字证书进行签名
jarsigner -verbose -keystore android123.keystore -signedjar test_signed.apk test.apk android123.keystore
jarsigner是Java的签名工具
-verbose参数表示:显示出签名详细信息
-keystore表示使用当前目录中的android123.keystore签名证书文件。
-signedjar test_signed.apk表示签名后生成的APK名称,test.apk表示未签名的APK Android软件, android.keystore表示别名
(3)、签名后生成了META-INT文件夹,里面包含的文件如下:
通过这三个文件,我们了解下第二步中jarsigner都做了什么事情,我们先看MANIFEST.MF,如下:
Manifest-Version: 1.0 Created-By: 1.0 (Android) Name: res/raw/aes.lua SHA1-Digest: M2O7Kjh31bRSTSaX9Kxeg9+r8t0= Name: AndroidManifest.xml SHA1-Digest: gJSLROnRQjVNfuSf9ZLQ/jcfjCQ= Name: lib/armeabi-v7a/libuencrypt.so SHA1-Digest: 60nq3GlIOFjA2qQwpD0GHF0B+fs= Name: assets/aes.lua SHA1-Digest: M2O7Kjh31bRSTSaX9Kxeg9+r8t0= Name: res/drawable-hdpi-v4/ic_launcher.png SHA1-Digest: Nq8q3HeTluE5JNCBpVvNy3BXtJI= Name: res/layout/activity_main.xml SHA1-Digest: 29xFOv25tmFws/fZywW1pnKb0/0= Name: res/layout/lv_item.xml SHA1-Digest: n+ABu8eXc8sgsr/koDg/u1UIHsk= Name: res/drawable-mdpi-v4/ic_launcher.png SHA1-Digest: RRxOSvpmhVfCwiprVV/wZlaqQpw= Name: res/menu/main.xml SHA1-Digest: FwPQ14VCI33UrtPR12pUamCNBtI= Name: lib/armeabi-v7a/libalgms.so SHA1-Digest: l6EtvZsMbYZLCRF/ym+gDCbb66A= Name: res/layout/gv_item.xml SHA1-Digest: zJG1Od3RKnHgvtNspfJoL3Gjl9c= Name: res/drawable-xhdpi-v4/ic_launcher.png SHA1-Digest: AfPh3OJoypH966MludSW6f1RHg4= Name: lib/armeabi/libluajava.so SHA1-Digest: hEXHJ2RO/N4HG7HpkvNLpwkezx8= Name: resources.arsc SHA1-Digest: xvke7fWkq3vTndO6GxJygC191Io= Name: lib/armeabi-v7a/libluajava.so SHA1-Digest: G1oHj8pHfhE6cTmiIIyLf7q3g5I= Name: res/layout/notify.xml SHA1-Digest: cwi7OQR/TBBCikvfrG1mWb/7aQ8= Name: classes.dex SHA1-Digest: ZFp/aGRiQlOrGaeCybupky6xL9w= Name: res/drawable-xxhdpi-v4/ic_launcher.png SHA1-Digest: GVIfdEOBv4gEny2T1jDhGGsZOBo= Name: lib/armeabi/libalgms.so SHA1-Digest: sThUrFV9sUiv9GDot0L92RkYBPs= Name: lib/armeabi/libuencrypt.so SHA1-Digest: 60nq3GlIOFjA2qQwpD0GHF0B+fs=
里面包含了所有apk中资源分别求Hash值。
我们再看CERT.SF,如下:
Signature-Version: 1.0 SHA1-Digest-Manifest: rpk81cwms7B69LRe8+DWDOXsXh4= Created-By: 1.0 (Android) Name: res/raw/aes.lua SHA1-Digest: 328J86FdzrMHCGbJ9zgSIL66Vhg= Name: AndroidManifest.xml SHA1-Digest: 5FgYlUZJI5rg9CliE7aY0lJvQeA= Name: lib/armeabi-v7a/libuencrypt.so SHA1-Digest: c4LKMukodajHJes+c40iIKVR5Mc= Name: assets/aes.lua SHA1-Digest: bxsaWYSVcIxoulpdWPfY0BV2PiQ= Name: res/drawable-hdpi-v4/ic_launcher.png SHA1-Digest: nVLQ/wUjf9D4KSB2I7WqoHR14JY= Name: res/layout/activity_main.xml SHA1-Digest: JW6OyAas5Wk9A3gkVFXQfnW5/xM= Name: res/layout/lv_item.xml SHA1-Digest: dNWFJFprP0T6rcGEzItXC7wCYkM= Name: res/drawable-mdpi-v4/ic_launcher.png SHA1-Digest: NBFXy1maYHW4TAiVCw6R9+EBNqI= Name: res/menu/main.xml SHA1-Digest: OKnRLZ88PSIyuOBi7mLTP2st5qo= Name: lib/armeabi-v7a/libalgms.so SHA1-Digest: FtY/V2plAUjgAuML1e13WkbAlv4= Name: res/layout/gv_item.xml SHA1-Digest: dkF+JesLgH0dGCDQ3n8xB5x27/c= Name: res/drawable-xhdpi-v4/ic_launcher.png SHA1-Digest: qLB+xSuTsdod1eS2aPJel/A5PvE= Name: lib/armeabi/libluajava.so SHA1-Digest: s4qgp8flPTMEZkF8z5QutBgFxrM= Name: resources.arsc SHA1-Digest: 541ycGJWJPTgwVyrgsxvB8pjjCM= Name: lib/armeabi-v7a/libluajava.so SHA1-Digest: Ef0wS9E2VVNlCobz+Rfus6H98sQ= Name: res/layout/notify.xml SHA1-Digest: ioOWjUP2Gg9EEwhuElzwisdCR6I= Name: classes.dex SHA1-Digest: K7z+duqJFBCe/hMgJWJQrzmLwxE= Name: res/drawable-xxhdpi-v4/ic_launcher.png SHA1-Digest: W7nSszMeL1x0eIt3K2CoCIHU6Qg= Name: lib/armeabi/libalgms.so SHA1-Digest: +F1sBBeuDvU3e9uqpFyvdOSdQAE= Name: lib/armeabi/libuencrypt.so SHA1-Digest: JToW2wKlog94dVZeNv3cGOC3CwA=
首先对MANIFEST.MF整个文件求Hash值存放在SHA1-Digest-Manifest中,然后再对MANIFEST.MF里面的Hash值再求Hash值。
最后我们再来看,CERT.RSA,它是个二进制文件。只能通过特定的工具读出来其中的内容。可参考从CERT.RSA中提取证书一文。
读出来的内容如下,参考Android签名与认证详细分析之二(CERT.RSA剖析),如下图:
我们先看最后一步的已加密的Hash值,这是对CERT.SF文件求Hash值然后使用私钥加密后的结果。
再往上看密钥,这里的密钥指的是非对称加密的公钥。这个文件中不保存对称加密的私钥。
CERT.RSA还保存了发行者名称和主体名称,生效日期和终止日期等待。
了解了这个三个文件的内容,我们也就知道了jarsigner都做了什么事情。
2、签名的作用
(1)保证内容的完整性
在安装APK时,计算APK中每个资源的Hash值与MANIFEST.MF里面的Hash值做对比;如果成功,再计算MANIFEST.MF文件的Hash值与CERT.SF的Hash值做对比;如果成功,使用公钥解密CERT.RSA已加密的Hash值,然后与对CERT.SF文件求出的Hash值做对比;如果成功,表示验证通过。
如果恶意修改代码,再恶意修改MANIFEST.MF对应的Hash值,再恶意修改CERT.SF的Hash值,但是最后无法修改CERT.RSA里面的Hash值,因为没有私钥。
1)如果当前的APK被篡改,直接放入手机中运行,第一步在计算APK中每个资源的Hash值与MANIFEST.MF里面的Hash值做对比,这一步就Failed了。
2)如果当前的APK被篡改后重新签名,由于系统中原有同样包名的apk,发现与原有签名的公钥不一致,直接被reject。除非把原应用删除,再安装新的应用。
(2)shareUid
如果两个应用shareUid,说明两个应用可以对对方的私有目录进行访问,这就造成了安全隐患。如果360和QQ,sharedUid,那么360就可以访问QQ目录下(/data/data/com.tencent/...)的私有数据。所以我们规定shardUid的两个应用必须使用同样的私钥进行签名,在CERT.RSA体现在公钥一致。
版权声明:本文为博主原创文章,未经博主允许不得转载。