签名 android 应用程序抛出 IOException:发现冗余长度字节
Signing android app throws IOException: Redundant length bytes found
我们正在开发 Cordova 应用程序,但在签署 Android 版本的应用程序时遇到困难。
使用命令
jarsigner -keystore keystore.p12 -storetype pkcs12 android-release-unsigned.apk 1
给出以下异常
java.io.IOException: DerInputStream.getLength(): Redundant length bytes found
来自 this line in OpenJDK apparently this was added to fix CVE-2016-5546 虽然我对加密的了解还不够,无法真正理解它。
使用 openssl 导出证书并从中创建新的 p12 工作正常,但更改了签名,这意味着 play 商店拒绝上传。
我们的密钥库来自我们最初将应用程序开发外包给的另一家公司。
任何 jarsigner 或 keytool 命令都会抛出相同的异常,我认为这是有道理的,因为它们都使用相同的 Java lib
我们遇到了同样的问题。我们发现 JDK 1.8.0_112 没有您所说的错误。于是我们就这样解决了问题:
起初我们使用以下命令将temp_keystore.p12
转换为mycert.keystore
(Java\jdk1.8.0_112\bin\keytool.exe
):
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
。
我花了几个小时来寻找这个问题的解决方案。尝试了五个不同的 JDKs,但没有任何效果。我有一个非常流行的 playstore 应用程序的旧 PKCS12 证书,我从以前的开发人员那里“继承”了它,JDK 8 + 9 不会使用它。 Olexandr 的解决方案也没有帮助。
最后,几乎是侥幸,我在 Weijung Wang 的回复中找到了解决方案 here。它涉及使用 openssl 导出和重新导入证书。然后我在 JKS 密钥库中重新导入了 P12 密钥库,它现在可以与 JDK 8.
一起使用
引用:
weijun Weijun Wang added a comment - 2017-02-28 15:55
Openssl is able to remove the redundant 0s when extracting the private key. We can use the following 2 commands to normalize an affected pkcs12 file:
openssl pkcs12 -in pkcs12-file -out key-and-cert -nodes -passin pass:abcXYZ
openssl pkcs12 -in key-and-cert -export -out new-pkcs12-file -passout pass:abcXYZ
我一直有同样的错误,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
我有使用 JDK6 生成的密钥库。
作为解决方法,我一直在使用 JDK 1.8.0_112,方法是在 [项目结构] - [SDK 位置] - [JDK 位置] 下设置 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
@Water 的解决方案对我不起作用。生成的 apk 的签名与原始的不同。
我终于通过上传使用 pepk 工具生成的私钥升级到 Google 的新应用程序签名来让它工作,并请求他们的支持重置上传密钥。
我找到了一个很棒的解决方案
因此,我也手动签署了我的 APK,但现在 Google 要求 targetSDK=30,它也要求使用 V2 签名方案。这是我不知道如何手动完成的事情。
但我找到了修复方法!
只需在文件 -> 项目结构 -> JDK 位置中将 Android Studio 使用的 JDK 设置为稍旧的内容。默认情况下,它使用其嵌入的 JDK 但您可以将其指向任何内容。例如,我使用 1.8.0_45。我现在可以再次直接使用旧的“损坏的”密钥库直接使用构建 -> 生成签名的 APK!
有一天 Android Studio 可能再次需要最新的“错误”JDK,但现在我已经准备好了。
我们正在开发 Cordova 应用程序,但在签署 Android 版本的应用程序时遇到困难。
使用命令
jarsigner -keystore keystore.p12 -storetype pkcs12 android-release-unsigned.apk 1
给出以下异常
java.io.IOException: DerInputStream.getLength(): Redundant length bytes found
来自 this line in OpenJDK apparently this was added to fix CVE-2016-5546 虽然我对加密的了解还不够,无法真正理解它。
使用 openssl 导出证书并从中创建新的 p12 工作正常,但更改了签名,这意味着 play 商店拒绝上传。
我们的密钥库来自我们最初将应用程序开发外包给的另一家公司。
任何 jarsigner 或 keytool 命令都会抛出相同的异常,我认为这是有道理的,因为它们都使用相同的 Java lib
我们遇到了同样的问题。我们发现 JDK 1.8.0_112 没有您所说的错误。于是我们就这样解决了问题:
起初我们使用以下命令将temp_keystore.p12
转换为mycert.keystore
(Java\jdk1.8.0_112\bin\keytool.exe
):
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
。
我花了几个小时来寻找这个问题的解决方案。尝试了五个不同的 JDKs,但没有任何效果。我有一个非常流行的 playstore 应用程序的旧 PKCS12 证书,我从以前的开发人员那里“继承”了它,JDK 8 + 9 不会使用它。 Olexandr 的解决方案也没有帮助。
最后,几乎是侥幸,我在 Weijung Wang 的回复中找到了解决方案 here。它涉及使用 openssl 导出和重新导入证书。然后我在 JKS 密钥库中重新导入了 P12 密钥库,它现在可以与 JDK 8.
一起使用引用:
weijun Weijun Wang added a comment - 2017-02-28 15:55
Openssl is able to remove the redundant 0s when extracting the private key. We can use the following 2 commands to normalize an affected pkcs12 file:
openssl pkcs12 -in pkcs12-file -out key-and-cert -nodes -passin pass:abcXYZ
openssl pkcs12 -in key-and-cert -export -out new-pkcs12-file -passout pass:abcXYZ
我一直有同样的错误,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
我有使用 JDK6 生成的密钥库。 作为解决方法,我一直在使用 JDK 1.8.0_112,方法是在 [项目结构] - [SDK 位置] - [JDK 位置] 下设置 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
@Water 的解决方案对我不起作用。生成的 apk 的签名与原始的不同。
我终于通过上传使用 pepk 工具生成的私钥升级到 Google 的新应用程序签名来让它工作,并请求他们的支持重置上传密钥。
我找到了一个很棒的解决方案
因此,我也手动签署了我的 APK,但现在 Google 要求 targetSDK=30,它也要求使用 V2 签名方案。这是我不知道如何手动完成的事情。
但我找到了修复方法!
只需在文件 -> 项目结构 -> JDK 位置中将 Android Studio 使用的 JDK 设置为稍旧的内容。默认情况下,它使用其嵌入的 JDK 但您可以将其指向任何内容。例如,我使用 1.8.0_45。我现在可以再次直接使用旧的“损坏的”密钥库直接使用构建 -> 生成签名的 APK!
有一天 Android Studio 可能再次需要最新的“错误”JDK,但现在我已经准备好了。