【问题标题】:Signing android app throws IOException: Redundant length bytes found签署 android 应用程序会引发 IOException:发现冗余长度字节
【发布时间】:2017-07-22 02:35:35
【问题描述】:

我们正在开发一个 Cordova 应用,但在签署该应用的 Android 版本时遇到了困难。

使用命令

jarsigner -keystore keystore.p12 -storetype pkcs12 android-release-unsigned.apk 1

给出以下异常

java.io.IOException: DerInputStream.getLength(): Redundant length bytes found

它来自 OpenJDK 中的 this line apparently 这是为了修复 CVE-2016-5546 而添加的,尽管我对加密的了解还不够,无法真正理解它。

使用 openssl 导出证书并从中创建一个新的 p12 工作正常,但会更改签名,这意味着 Play 商店拒绝上传。

我们的密钥库来自我们最初将应用程序开发外包给的另一家公司。

任何 jarsigner 或 keytool 命令都会引发相同的异常,我认为这是有道理的,因为它们都使用相同的 Java lib

【问题讨论】:

  • 你试过Oracle的JDK吗?
  • 给出与 Oracle 8 和 9 相同的信息 :(
  • OpenJDK JIRA 上存在这个问题,似乎非常相关bugs.openjdk.java.net/browse/JDK-8175251
  • JDK 1.8.0_111 没有这个问题,我在 Android Studio 中遇到了同样的错误,设置 JDK_1.8.0_111 对我有用

标签: java android cordova signing pkcs#12


【解决方案1】:

我们遇到了同样的问题。我们发现 JDK 1.8.0_112 没有您所说的错误。于是我们就这样解决了问题:

首先,我们使用以下命令(Java\jdk1.8.0_112\bin\keytool.exe)将temp_keystore.p12 转换为mycert.keystore

keytool -importkeystore -srckeystore temp_keystore.p12 -destkeystore mycert.keystore -srcstoretype pkcs12

然后我们使用下面的命令(Java\jdk1.8.0_112\bin\jarsigner.exe):

jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore mycert.keystore ReadyForSigning.apk 1

签名apk。 (命令末尾的“1”是别名)

PS.:从.p12 转换为.keystore 可能没有必要。

【讨论】:

  • 是的,你是对的,现在我们在 131 上,它似乎正在神奇地工作。从提交看来,他们设置了一个标志来跳过新的检查。
【解决方案2】:

我花了几个小时寻找解决这个问题的方法。尝试了五种不同的 JDK,但没有任何效果。我有一个旧的 PKCS12 证书,用于一个非常流行的 playstore 应用程序,我从以前的开发人员那里“继承”了它,JDK 8 + 9 不会使用它。 Olexandr 的解决方案也没有帮助。

最后,在 Weijung Wang 的回复中,几乎是靠运气,我设法找到了解决方案here。它涉及使用 openssl 导出和重新导入证书。然后我在 JKS 密钥库中重新导入了 P12 密钥库,它现在可以与 JDK 8 一起使用。

引用:

weijun Weijun Wang 发表评论 - 2017-02-28 15:55
Openssl 能够在提取私钥时去除多余的 0。我们可以使用以下 2 个命令来规范化受影响的 pkcs12 文件:

  1. openssl pkcs12 -in pkcs12-file -out key-and-cert -nodes -passin pass:abcXYZ

  2. openssl pkcs12 -in key-and-cert -export -out new-pkcs12-file -passout pass:abcXYZ

【讨论】:

    【解决方案3】:

    我遇到了同样的错误,并且 Olexandr 的解决方案不起作用,因为在 JDK8(更新 151)上使用 keytool 会在读取使用 JDK7 生成的证书时引发错误。 正如 Anders 的回答,使用 OpenSSL 可以使用(粘贴命令行以供将来参考):

    openssl pkcs12 -in android.p12 -out android_fixed.cert -nodes -passin pass:your_p12_password
    openssl pkcs12 -in android_fixed.cert -export -out android_cert.p12 -passout pass:your_p12_password
    

    【讨论】:

      【解决方案4】:

      我有使用 JDK6 生成的密钥库。 作为解决方法,我一直在使用 JDK 1.8.0_112,方法是在 [Project Structure] - [SDK Location] - [JDK location] 下设置 JDK。

      我已经通过以下步骤解决了(使用 macOS)。

      使用 JDK 1.8.0_112 转换为 PKCS12

      /Library/Java/JavaVirtualMachines/jdk1.8.0_112.jdk/Contents/Home/bin/keytool -importkeystore -srckeystore original.keystore -destkeystore 1.8.0_112.p12 -deststoretype PKCS12 -storepass ***** -destkeypass *****
      

      使用 OpenSSL 进行处理(感谢 Weijung Wang 和 Anders Emil)

      openssl pkcs12 -in 1.8.0_112.p12 -out 1.8.0_112.cert -nodes -passin pass:*****
      openssl pkcs12 -in 1.8.0_112.cert -export -out 1.8.0_112.export.p12 -passout pass:*****
      

      使用 JDK 1.8.0_161 转换为 JKS。

      这里我需要指定-destkeypass、-srcalias 和-destalias。 注意openSSL命令后的别名为“1”,所以需要设置别名。

      /Library/Java/JavaVirtualMachines/jdk1.8.0_161.jdk/Contents/Home/bin/keytool -importkeystore -srckeystore 1.8.0_112.export.p12 -srcstoretype pkcs12 -destkeystore 1.8.0_112.keystore -deststoretype jks -deststorepass ***** -destkeypass ***** -srcalias 1 -destalias youralias
      

      所以指纹的结果是这样的。

      Original keystore:
           SHA1: 6C:9E:...:C5:8A
      
      Original apk:
           SHA1: DA:4C:...:3F:02
      
      Modified keystore:
           SHA1: C8:4A:...:2A:23
      
      Modified apk:
           SHA1: DA:4C:...:3F:02
      

      【讨论】:

      • 如果密钥库指纹不同,那么它将如何被接受为有效版本? Google Play 控制台提示我指纹不同。
      • @Vas JDK6 错误地制作了原始密钥库,原始 apk 显示不同的指纹,似乎不匹配,但是修改后的密钥库和 apk 的指纹匹配。 Google play 应该接受修改后的 apk,因为指纹是一样的。
      • @JanineKroser 实际上他们确实接受了我的 apk 并且更新已在 Google play 上发布。
      • @Water 您如何获得 APK 的 SHA1 来验证这是否有效?
      • @anthonylawson 在设备上安装使用 JDK6 签名的旧应用,然后尝试安装使用 JDK 1.8.0_161 签名的新应用。如果应用程序被覆盖并且运行没有错误,则意味着成功。
      【解决方案5】:

      @Water 的解决方案对我不起作用。生成的 apk 的签名与原始的不同。

      我终于通过上传使用 pepk 工具生成的私钥升级到 Google 的新应用签名来让它工作,并请求他们的支持来重置上传密钥。

      【讨论】:

      • 您是说您设法说服他们为您更改签名密钥?或者“重置上传密钥”是什么意思
      • 如果您使用谷歌应用签名,您可以要求重置上传密钥。
      【解决方案6】:

      我找到了一个很棒的解决方案

      因此,我也手动签署了我的 APK,但现在 Google 要求 targetSDK=30,它也要求使用 V2 签名方案。这是我不知道如何手动完成的事情。

      但我找到了解决办法!

      只需在文件 -> 项目结构 -> JDK 位置中将 Android Studio 使用的 JDK 设置为稍旧的东西。默认情况下,它使用其嵌入式 JDK,但您可以将其指向任何内容。例如,我使用的是 1.8.0_45。现在我可以再次使用 Build -> Generate Signed APK 直接与我旧的“损坏”密钥库!

      有一天,Android Studio 可能会再次需要最新的“错误”JDK,但现在我已经准备好了。

      【讨论】:

        猜你喜欢
        • 2018-01-03
        • 1970-01-01
        • 2023-03-31
        • 1970-01-01
        • 2011-06-24
        • 2012-10-21
        • 1970-01-01
        • 1970-01-01
        • 2014-01-28
        相关资源
        最近更新 更多