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

AWT*_*AWT 2 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.
Run Code Online (Sandbox Code Playgroud)

那里没有投诉,对吧?它看起来像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
Run Code Online (Sandbox Code Playgroud)

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

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

AWT*_*AWT 5

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

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

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

曾经签名的apk文件

现在,我们修改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
Run Code Online (Sandbox Code Playgroud)

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

jarsigner.exe -verify -verbose -certs C:\apk\AndroidWorld-release-signed.apk
jarsigner: java.lang.SecurityException: invalid SHA1 signature file digest for classes.dex
Run Code Online (Sandbox Code Playgroud)

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

两次签名的apk文件

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

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

Name: classes.dex (Cert.sf)
SHA1-Digest: hkAsCEcLyM52Q6gq2uQIqc/7Gh8=
Run Code Online (Sandbox Code Playgroud)

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