如何用私钥将.pfx 文件转换为密钥存储库?

我需要签署 Android 应用程序(.apk)。
我有 .pfx文件。我通过 Internet Explorer 把它转换成了 .cer文件,然后用 keytool 把它转换成了 .keystore文件。然后我尝试签署 .apk与 Jarsigner,但它说。Keystore 不包含私钥。

我做错了什么?

378926 次浏览

PFX 文件中应该包含私钥。直接从 PFX 文件导出私钥和证书(例如使用 OpenSSL) ,并将它们导入到 Java 密钥存储库中。

剪辑

进一步资料:

  • 下载用于 Windows给你的 OpenSSL。
  • 导出私钥: openssl pkcs12 -in filename.pfx -nocerts -out key.pem
  • 出口证书: openssl pkcs12 -in filename.pfx -clcerts -nokeys -out cert.pem
  • 使用 keytool将私钥和证书导入 Java 密钥存储库。

使用 JDK 1.6或更高版本

Justin 在下面的评论中指出,只有 keytool 可以使用以下命令(尽管只在 JDK 1.6及更高版本中)完成这项工作:

keytool -importkeystore -srckeystore mypfxfile.pfx -srcstoretype pkcs12
-destkeystore clientcert.jks -deststoretype JKS

使用 JDK 1.5或更低版本

到目前为止,这是 JGuru 上的答案是我发现的最好的方法。

首先,确保您已经安装了 OpenSSL。许多操作系统已经安装了它,就像我在 MacOSX 上发现的那样。

以下两个命令将 pfx 文件转换为可以作为 JavaPKCS12密钥存储库打开的格式:

openssl pkcs12 -in mypfxfile.pfx -out mypemfile.pem
openssl pkcs12 -export -in mypemfile.pem -out mykeystore.p12 -name "MyCert"

注意,第二个命令中提供的名称是新密钥存储区中密钥的别名。

您可以使用 Java keytool 实用程序通过以下命令验证密钥存储的内容:

keytool -v -list -keystore mykeystore.p12 -storetype pkcs12

最后,如果您需要,您可以通过将上面创建的密钥存储导入到一个新的密钥存储来将其转换为 JKS 密钥存储:

keytool -importkeystore -srckeystore mykeystore.p12 -destkeystore clientcert.jks -srcstoretype pkcs12 -deststoretype JKS

Jarsigner 可以使用 pfx 文件作为对 jar 进行签名的密钥存储库。在导出 pfx 文件时,请确保该文件具有私钥和 cert 链。不需要转换为其他格式。诀窍是获得 pfx 文件的 化名:

 keytool -list -storetype pkcs12 -keystore your_pfx_file -v | grep Alias

一旦你有了化名,签名就很容易了

jarsigner.exe -storetype pkcs12 -keystore pfx_file jar_file "your alias"

以上两个命令将提示您输入在 pfx 导出中指定的密码。如果你想让你的密码挂在明文使用 商店通行证开关之前的 钥匙店开关

一旦签名,欣赏你的作品:

jarsigner.exe -verify -verbose -certs  yourjarfile

我发现 这个页面告诉你如何导入 PFX 到 JKS (Java 密钥存储) :

keytool -importkeystore -srckeystore PFX_P12_FILE_NAME -srcstoretype pkcs12
-srcstorepass PFX_P12_FILE -srcalias SOURCE_ALIAS -destkeystore KEYSTORE_FILE
-deststoretype jks -deststorepass PASSWORD -destalias ALIAS_NAME

如果您使用 JDK 1.5或更低版本,keytool 实用程序将不会有 -importkeystore选项(参见 JDK 1.5 keytool 文档) ,MikeD 的解决方案将只能通过在一台具有更新的 JDK (1.6或更高版本)的机器上传输 .pfx来获得。

JDK 1.5或更低版本(如果您有 Oracle WebLogic 产品)中的另一个选项是遵循 Oracle 文档 对密钥存储库使用 PFX 和 PEM 证书格式中的说明。 它描述了转换为 .pem格式,如何从这种文本格式提取证书信息,并使用 java utils.ImportPrivateKey实用程序(这是 WebLogic 产品中包含的一个实用程序)将其导入到 .jks格式。

Justin (上图)是准确的。但是,请记住,根据您从谁那里获得证书(中间 CA、根 CA 是否涉及)或者如何创建/导出 pfx,有时候它们可能会丢失证书链。Import 之后,您将拥有一个 PrivateKeyEntry 类型的证书,但是其链的长度为1。

要解决这个问题,有几个选择。在我看来,更简单的选择是在 IE 中导入和导出 pfx 文件(选择包含链中的所有证书的选项)。IE 中证书的导入和导出过程应该非常容易,并且在其他地方有很好的文档记录。

一旦导出,就像上面 Justin 指出的那样导入密钥存储库。 现在,您将拥有一个具有 PrivateKeyEntry 类型的证书并且证书链长度大于1的密钥存储库。

如果不执行上述操作,则基于.Net 的 Web 服务客户端将出错(无法建立信任关系)。

这是我针对 Visual Studio/Xamarin 环境的解决方案。

预期成果:

  • PFX (示例中的 foo.pfx)将导入到 JKS 密钥存储库(示例中的 bar.keystore)。
  • 密钥存储库将使用一个新密码进行保护(称为“签名密码”)。
  • 密钥存储库将包含单个密钥。
  • 单个密钥将有一个别名,其名称与密钥存储库的名称相匹配(示例中为 bar)。
  • 单个密钥将使用签名密码进行保护。
  • Xamarin 工具将能够使用密钥库轻松地签署应用程序。

请注意,名称和密码不一定要匹配,但这是常见的做法,也是工具所期望的。

keytool位置: %JAVA_HOME%\bin,例如:

  • C:\Program Files\Android\jdk\microsoft_dist_openjdk_1.8.0.25\bin
  • C:\Program Files (x86)\Java\jre1.8.0_331\bin

步骤:

  1. 获取内部签名的 PFX。 PFX 将临时分配密码。
  2. 从 PFX 导入 JKS 密钥存储库; 当提示时,为目标密钥存储库密码提供两次签名密码,并为源密钥存储库密码提供临时分配的密码。
    keytool -importkeystore -srckeystore foo.pfx -srcstoretype pkcs12 -destkeystore bar.keystore -deststoretype JKS
    
    生成的 JKS 密钥存储库将有一个单一的密钥别名“1”,其临时分配的密码与步骤1中的 PFX 相同。
  3. 更改密钥别名以匹配密钥存储库名称; 当出现提示时,为密钥存储库密码提供签名密码,并为密钥密码临时分配密码。
    keytool -changealias -alias 1 -destalias bar -keystore bar.keystore
    
  4. 将密钥密码更改为签名密码; 当提示时,为密钥库密码提供签名密码,为旧密钥密码临时分配密码,并为新密钥密码两次签名密码。
    keytool -keypasswd -keystore bar.keystore -alias bar
    
  5. 确保完成的密钥存储位于以下路径,或类似于您的安装:
    %LOCALAPPDATA%\Xamarin\Mono for Android\Keystore\bar\bar.keystore
    

核实内容:

  1. 查看原始 PFX 的内容; 当提示时,为密钥存储库密码提供临时分配的密码。
    keytool -list -v -keystore foo.pfx -storetype pkcs12
    
  2. 查看生成的密钥存储库的内容; 当提示时,为密钥存储库密码提供签名密码。
    keytool -list -v -keystore bar.keystore
    
  3. 比较步骤1和步骤2的输出(例如,保存到文本文件并执行文件 diff)。内容应该是相同的(即证书链、指纹等; 页眉和页脚文本不同)。

现在,您应该能够在 VisualStudio 中使用 Ad-Hoc 分发选项时查看和使用导入的密钥存储库。提示时提供签名密码。