我需要使用为Adobe Air生成的现有.p12证书签署Android Native应用程序方面的帮助。申请是在几年前在Adobe Air中完成的,并签名并发布到Google Play。现在,当从Adobe Air迁移到Android Native时,为了将应用升级到商店中的新版本,需要使用相同的私钥对其进行签名。问题是在较新版本的Java上无法通过keytool打开/读取密钥。尝试读取.p12证书将返回:
java.security.cert.CertificateException: Unable to initialize, java.io.IOException: DerInputStream.getLength(): Redundant length bytes found
或
keytool error: java.io.IOException: Invalid keystore format
取决于我要执行的命令。
(1)向老朋友问Google带来的不多,但更多的是沮丧。我确实像jira ticket of openjdk中所建议的那样,我尝试使用OpenSSL以这种方式修复冗余字节:
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
此命令将成功执行,但是生成的SHA1密钥(...:F7)将与原始密钥(...:E5)不同!这实际上不足为奇,因为更改文件的任何部分(例如删除冗余字节)将以不同的SHA密钥结尾。好的,所以显然这不是解决方案。
(2)接下来,我尝试从原始的.p12证书中提取私钥和证书作为纯文本(.pem)文件,以尝试创建新的.jks。文件。因此,我设法将我的私钥和我的证书从原始的.p12证书提取为纯文本。然后使用keytools和openssl尝试使用原始数据创建新的.jks文件,如下所述: How to Creat JKS KeyStore file from existing private key and certificate 好吧,它的工作方式是创建了我的新.jks文件,但SHA1密钥(再次是...:F7)与原始密钥不相同(...:E5)。
(3)我的下一步是阅读并在互联网上查找更多内容。找到一些建议转换的最后解决方案是在Java 1.8.0_111中解决的,上面的每个Java发行版都存在相同的问题。因此,让我们安装Java 1.8.0_111并试一试。当然,它没有用。问题保持不变。在Java 1.10和Oracle版本中也尝试过,仍然无法使用
(4)最后一件事,我安装了Java 1.6并对其进行了尝试,并且没有问题,它运行正常,我设法毫无问题地读取了.p12并将其转换完全没有问题的.jks就像一个魅力。生成的SHA1密钥(...:E5)与原始密钥(...:E5)相同!!!
但是,问题是我需要使用该证书签名的应用程序是使用Java 1.8开发的,而Java 1.8无法读取该证书。所以我现在很沮丧,因为已经几天了,我在这个问题上迷失了。
因此,无法读取,无法重新生成,无法对应用程序进行签名...
所以我的问题是:是否可以,如果可以,如何使用.p12证书签署Android apk?
我不确定这个问题有多普遍,但是欢迎任何可能的帮助。
答案 0 :(得分:1)
我终于设法找到了我所面临的这个问题的最佳解决方案。实际上,解决方案就在我眼前,需要一点点努力。
我试图切换到Java 1.6版本只是为了对该应用程序进行签名,实际上我确实设法进行了签名。后记之后,我将应用程序再次转移到1.8 Java环境中,并成功完成了zipalign!当我处理完所有这些时,我真的很高兴,希望Google Play最终会接受apk。 将apk上传到商店后,我的希望就消失了。 Google Play表示并非所有文件均已签名,我需要上传所有文件均已签名的apk。您能想象出沮丧的程度吗?
我的问题是我有旧的.p12证书,无法在AndroidStudio中读取或转换为jks,但是我能够从该文件中提取我的私钥和证书。
尝试多看一遍后,我设法用apksigner tool找到了解决方案。
实际上,我所做的是,我构建了一个使用调试密钥签名的.apk,然后仅使用了提供我的私钥和证书文件的apksigner工具,最后对apk进行了签名。然后我就可以将apk顺利上传到Google Play商店。
我曾经使用apksigner工具对apk进行签名的命令是:
./apksigner sign --key <your_private_key_in_.pcks8> --cert <your_certificate_in.der> <your_debug_signed_application_in.apk>
在这里有必要注意您的密钥必须为.pcks8格式,否则该命令将无效。另外apksigner在Linux上以脚本形式运行,这就是为什么apksigner之前是“ ./”的原因。如果您在Windows上使用此工具或以其他方式安装了该工具,则最好仅使用apksigner.exe或apksigner启动命令。
如果您的密钥为纯文本(.pem)格式,则可以使用openssl命令将其传输为.pcks8格式:
openssl pkcs8 -topk8 -inform PEM -outform DER -in <your_private_key_in.pem> -out <your_private_key_in.pcks8> -nocrypt
答案 1 :(得分:0)
讨厌成为坏消息的承担者,但这是版本控制在企业环境中至关重要的原因之一。更新时,构建可能会中断。
我没有想到上面列出的三件事:
1]如果使用的是类似Android Studio或IntelliJ的IDE,则可以尝试将项目分解为Java 1.8代码和Java 1.6代码。例如,您可以创建一个密钥库签名模块,然后添加gradle命令使其使用Java 1.6进行构建,而其余项目模块则使用Java 1.8进行构建。
2]您可以尝试创建自己的签名类,并直接调用Java 1.6类,您可以将其手动添加到项目中。
3]您可以使用新的密钥库,更改软件包名称,并将以前的商店清单指向新的Java 1.8应用程序。这可能是最不优选的,因为它将被视为商店中的新应用。
答案 2 :(得分:0)
我们无法使用合法证书签署我们的应用程序。因此,我们改为使用自制证书进行发布,以编译/发布该应用程序。然后,我们使用Microsoft的Signtool(.exe)来完成这项工作。像魅力一样工作。