如何将.pfx文件转换为带有私钥的密钥库?

142

我需要签名 Android 应用 (.apk)。
我有 .pfx 文件。我通过 Internet Explorer 将其转换为 .cer 文件,然后使用 keytool 将 .cer 转换为 .keystore。然后我尝试使用 jarsigner 对 .apk 进行签名,但它说 .keystore 没有私钥内容。

我做错了什么?


这可能很有用:如何在Windows中找到并运行keytool https://dev59.com/V2035IYBdhLWcg3wVebn - Peter Barbanyaga
7个回答

324

使用JDK 1.6或更高版本

正如下面评论中Justin所指出的那样,仅使用keytool就能够执行以下命令来完成此项任务(但是仅适用于JDK 1.6及以上版本):

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

使用JDK 1.5或更低版本

OpenSSL可以做到这一切。这个JGuru上的回答是目前我发现的最好的方法。

首先确保你已经安装了OpenSSL。许多操作系统已经预先安装了它,就像我在Mac OS X中发现的那样。

下面的两个命令将把pfx文件转换为一个能够作为Java PKCS12密钥库打开的格式:

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

33
请执行以下命令:keytool -importkeystore -srckeystore mykeystore.pxf -destkeystore clientcert.jks -srcstoretype pkcs12 -deststoretype JKS。 - JustinMorris
我认为旧版本的keytool不允许你这样做。我记得8年前我必须运行openssl,但现在在Oracle JDK 6和7中使用keytool就像Justin说的那样完美运行。 - David Brossard
2
请注意,我在一年之前就以更详细的形式给出了比Justin更简单的答案。 - gjpc
@gjpc 已经注意到了。你的回答非常完整,值得得到很多赞 :) - MikeD
好的,对于大多数人来说这可能很明显。但是让我为像我这样的人添加一下我的评论。如果你在Mac上,这个命令是要在终端上运行的。 - aye2m
显示剩余5条评论

34

我发现这个页面告诉你如何将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

我有一个问题,这个 pfx 没有密码,所以 -srcstorepass 是我的问题。这个 PFX 是由一个适用于 Windows 的 LetsEncrypt 客户端创建的。 - FiruzzZ
@FiruzzZ,这里也有类似的PFX密码丢失问题。这个方法对我有效:... -srcstorepass "" ... - mshikaji

26

jarsigner可以使用您的pfx文件作为签署jar文件的密钥库,确保在导出时您的pfx文件具有私钥和证书链。无需转换为其他格式,关键是要获取您的pfx文件的 Alias

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

一旦您拥有了别名,签名就很容易了

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

上述两个命令将提示您输入在pfx导出时指定的密码。如果您想让密码以明文形式出现,请在-keystore开关之前使用-storepass开关

签名后,欣赏您的作品:

jarsigner.exe -verify -verbose -certs  yourjarfile

2
+1,不需要转换密钥库文件(我已经有足够多的格式了!) - Hakanai

2
贾斯汀(上文)的说法是准确的。然而,请记住,根据您从谁那里获取证书(中间CA,是否涉及根CA)或pfx的创建/导出方式,有时可能会缺少证书链。导入后,您将拥有一个PrivateKeyEntry类型的证书,但链长度为1。
要解决这个问题,有几个选项。我认为更容易的选择是在IE中导入和导出pfx文件(选择包括所有证书链的选项)。在IE中导入和导出证书的过程应该非常简单,并已在其他地方得到很好的记录。
导出后,按照贾斯汀上面的提示导入密钥库。 现在,您将拥有一个类型为PrivateKeyEntry的密钥库,并且证书链长度超过1。
如果不执行上述操作,则某些基于.Net的Web服务客户端会出现错误(无法建立信任关系)。

这似乎在 IE11 上不起作用。 尽管我告诉它要包含证书链,但它仍然失败了。 我知道以前这是有效的。 - Brian Knoblauch

1

你的PFX文件应该包含私钥。从PFX文件中直接导出私钥和证书(例如使用OpenSSL),然后将它们导入到Java keystore中。

编辑

更多信息:

  • 在Windows上下载OpenSSL,点击这里
  • 导出私钥: openssl pkcs12 -in filename.pfx -nocerts -out key.pem
  • 导出证书: openssl pkcs12 -in filename.pfx -clcerts -nokeys -out cert.pem
  • 使用keytool将私钥和证书导入Java keystore。

1
请问如何使用keytool导入key.pem和cert.pem文件? - Sad Al Abdullah
1
小提示:导出私钥时必须在结尾添加“-nodes”。 - morgan_il

0

如果您使用的是JDK 1.5或更低版本,则keytool实用程序将没有-importkeystore选项(请参见JDK 1.5 keytool文档),而MikeD的解决方案仅适用于将.pfx转移到具有更新JDK(1.6或更高版本)的计算机上。

JDK 1.5或更低版本的另一个选择(如果您拥有Oracle WebLogic产品)是按照此Oracle文档的说明操作:在密钥库中使用PFX和PEM证书格式。它描述了如何将其转换为.pem格式,如何从此文本格式中提取证书信息,并使用java utils.ImportPrivateKey实用程序(这是WebLogic产品附带的实用程序)将其导入.jks格式。


0

这是我在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的输出(例如,保存到文本文件并执行文件差异)。 内容应完全相同(即证书链、指纹等;标题和页脚文本将不同)。

现在,您应该能够在使用 Visual Studio 中的 Ad-Hoc 分发选项时看到并使用导入的密钥库。当提示时,请提供签名密码。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接