INSTALL_PARSE_FAILED_NO_CERTIFICATES安装修改后的apk文件失败(无效的SHA1签名),即使在使用jarsigner签名后也是如此

时间:2014-04-22 15:41:03

标签: java android jar-signing android-keystore

我知道有很多其他人在忘记签名他们的apk时遇到INSTALL_PARSE_FAILED_NO_CERTIFICATES错误。这不是我所描述的问题。我将详细说明我在几个步骤中所做的事情。

我有一个zipaligned,签名的apk文件(AndroidWorld.apk)。我可以安装这个没问题。到目前为止,非常好。

接下来,我用apktool反编译apk。此外,到目前为止一切顺利。

之后,我使用asmdex修改classes.dex文件并注入一些方法记录。此时,如果我要重新打包apk并尝试安装,那肯定会失败,因为classes.dex的签名不再符合签名清单中的内容。我意识到了。所以我重新打包apk,zipalign它,然后用我自己的密钥库签名:

jarsigner -verbose -sigalg MD5withRSA -digestalg SHA1 -keystore "android_new_sample.keystore" -storepass mypass "C:\apk\AndroidWorld-release.apk" asample
Signing with keystore android_sample.keystore alias asample
   adding: META-INF/MANIFEST.MF
   adding: META-INF/ASAMPLE.SF
   adding: META-INF/ASAMPLE.RSA
  signing: assets/x.js
  signing: assets/x.css
  signing: assets/special_offers.html
  signing: res/layout/displayjourneylist.xml
  signing: res/layout/journey_row.xml
  signing: res/layout/login.xml
  signing: res/layout/searchjourney.xml
  signing: res/layout/settings.xml
  signing: res/layout/webview.xml
  signing: res/layout/window_title.xml
  signing: res/menu/option_menu.xml
  signing: AndroidManifest.xml
  signing: resources.arsc
  signing: res/drawable-hdpi/header.png
  signing: res/drawable-hdpi/ic_launcher.png
  signing: res/drawable-ldpi/header.png
  signing: res/drawable-ldpi/ic_launcher.png
  signing: res/drawable-mdpi/header.png
  signing: res/drawable-mdpi/ic_launcher.png
  signing: classes.dex
  signing: assets/x-runtime.properties
        1 file(s) copied.

没有抱怨,对吗?它似乎已经签署了classes.dex并且它没有抱怨。但是现在,如果我用jarsigner -verify检查签名apk的完整性,那就不开心了:

jarsigner.exe -verify -verbose -certs C:\apk\AndroidWorld-release-signed.apk
jarsigner: java.lang.SecurityException: invalid SHA1 signature file digest for classes.dex

我已确保卸载设备上的现有应用,但尝试安装此apk仍然会向我提供INSTALL_PARSE_FAILED_NO_CERTIFICATES消息。我已经尝试过使用Java JDK 1.6和1.7,因为我知道这些版本之间的jarsigner有一些变化(http://developer.android.com/tools/publishing/app-signing.html)。如您所见,我在签名时指定了sigalg和digestalg标志。

另一个奇怪的怪癖 - 如果我使用调试密钥库,所有这一切都可以。

2 个答案:

答案 0 :(得分:5)

好的,经过一番挖掘,这就是我发现的......

在检测以前签名的应用程序时,但使用新的密钥库对其进行签名时,会出现问题。具体来说,我们最终在\ meta-inf中有多个签名清单,这些清单都指向同一组文件。该应用无法安装错误INSTALL_PARSE_FAILED_NO_CERTIFICATES。

如果查看签名清单,您会看到两个文件:

once-signed apk file

现在,我们修改classes.dex并使用我们自己的密钥库对应用程序进行签名:

jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore android_new_sample.keystore AndroidWorld-release-final.apk asample
Enter Passphrase for keystore: mypass
 updating: META-INF/ASAMPLE.SF
 updating: META-INF/ASAMPLE.RSA
  signing: assets/x.js
  signing: assets/xx.css
  signing: assets/special_offers.html
  signing: res/layout/displayjourneylist.xml
  signing: res/layout/journey_row.xml
  signing: res/layout/login.xml
  signing: res/layout/searchjourney.xml
  signing: res/layout/settings.xml
  signing: res/layout/webview.xml
  signing: res/layout/window_title.xml
  signing: res/menu/option_menu.xml
  signing: AndroidManifest.xml
  signing: resources.arsc
  signing: res/drawable-hdpi/header.png
  signing: res/drawable-hdpi/ic_launcher.png
  signing: res/drawable-ldpi/header.png
  signing: res/drawable-ldpi/ic_launcher.png
  signing: res/drawable-mdpi/header.png
  signing: res/drawable-mdpi/ic_launcher.png
  signing: classes.dex
  signing: assets/xxx.properties

到目前为止没有问题,我们已将所有新签名添加到清单中。但是,尝试验证此apk的完整性现在失败了:

jarsigner.exe -verify -verbose -certs C:\apk\AndroidWorld-release-signed.apk
jarsigner: java.lang.SecurityException: invalid SHA1 signature file digest for classes.dex

原因是我们现在在\ meta-inf中有重复的签名信息:

twice-signed apk file

所以classes.dex有两个不同的签名,一个在Asample.sf中,另一个在Cert.sf中:

Name: classes.dex (ASample.cf) 
SHA1-Digest: mTf659/NTkTqqsAEZc3gTlbRpW8=

Name: classes.dex (Cert.sf)
SHA1-Digest: hkAsCEcLyM52Q6gq2uQIqc/7Gh8=

这会导致验证和安装失败。如果我从存档中删除Cert.rsa和Cert.sf,它将验证并安装。因此,解决方案是修改zip文件并删除原始签名证书,只留下我自己的。

答案 1 :(得分:-1)

我已删除文件CERT.SF / CERT.RSA / MANIFEST.MF,然后重新签名,一切顺利。