从 Java 中的 .p12 文件获取 PrivateKey 对象

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18621508/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 09:35:33  来源:igfitidea点击:

Getting a PrivateKey object from a .p12 file in Java

javagoogle-apigoogle-prediction

提问by gratsby

As the title suggests, I have .p12 file required for google service account api access. In order to get the credential to connect to the api, there's a field .setServiceAccountPrivateKey(PrivateKey privateKey). So, what's the easiest way in which I can do this? I have a resources folder which is in my classpath so if I add the p12 file there, I can get the resource from getClass().getResource() as either an inputStream or a URL. I've tried the URL method but it doesn't work (I get a "URI is not hierarchical" error trying to create a File object from URL.toURI()).

正如标题所暗示的,我有 .p12 文件,用于谷歌服务帐户 api 访问。为了获得连接到 api 的凭据,有一个字段 .setServiceAccountPrivateKey(PrivateKey privateKey)。那么,我可以做到这一点的最简单方法是什么?我有一个资源文件夹,它在我的类路径中,所以如果我在那里添加 p12 文件,我可以从 getClass().getResource() 获取资源作为 inputStream 或 URL。我已经尝试了 URL 方法,但它不起作用(尝试从 URL.toURI() 创建 File 对象时出现“URI 不是分层的”错误)。

采纳答案by Syon

You can load your .p12 file using the ClassLoader.getResourceAsStream(String)method, load it to a KeyStore and them get the key from the KeyStore.

您可以使用该ClassLoader.getResourceAsStream(String)方法加载 .p12 文件,将其加载到 KeyStore,然后他们从 KeyStore 获取密钥。

KeyStore keystore = KeyStore.getInstance("PKCS12");
keystore.load(this.getClass().getClassLoader().getResourceAsStream("keyFile.p12"), p12Password.toCharArray());
PrivateKey key = (PrivateKey)keystore.getKey(keyAlias, p12Password.toCharArray());

ClassLoader.getResourceAsStream(String)loads resources from any location provided they're already on the classpath, there's no need to specify a path to the file.

ClassLoader.getResourceAsStream(String)从任何位置加载资源,只要它们已经在类路径上,就不需要指定文件的路径。

keyAliasis the name of the entry in your p12 file that corresponds to the private key. PKCS12 files can contain multiple entries, so you need some way to indicate which entry you want to access. The alias is how this is achieved.

keyAlias是 p12 文件中与私钥对应的条目的名称。PKCS12 文件可以包含多个条目,因此您需要某种方式来指示要访问的条目。别名是如何实现的。

If you're not sure what the alias for your private key is, you can use the keytoolutility from the command line to list the contents of your p12 file. This tool is included with all JRE and JDK installations.

如果您不确定您的私钥的别名是什么,您可以keytool从命令行使用该实用程序来列出您的 p12 文件的内容。此工具包含在所有 JRE 和 JDK 安装中。

keytool -list -keystore keyFile.p12 -storepass password -storetype PKCS12

Output

输出

Keystore type: PKCS12
Keystore provider: SunJSSE

Your keystore contains 1 entry

yourKeyAlias, Sep 4, 2013, PrivateKeyEntry,
Certificate fingerprint (MD5): 48:A8:C4:12:8E:4A:8A:AD:58:81:26:90:E7:3D:C8:04

回答by Stocki

If you get nullfrom getKey()(eg. you are using BouncyCastleas a provider) you should find the last keyAliaselement:

如果您nullgetKey()(例如,您BouncyCastle用作提供者)获取,您应该找到最后一个keyAlias元素:

KeyStore keystore = KeyStore.getInstance("PKCS12", "BC");
keystore.load(this.getClass().getClassLoader().getResourceAsStream("keyFile.p12"), p12Password.toCharArray());
Enumeration aliases = keystore.aliases();
String keyAlias = "";
while (aliases.hasMoreElements()) {
    keyAlias = (String) aliases.nextElement();
}
PrivateKey key = (PrivateKey)keystore.getKey(keyAlias, pass);

回答by Robert Watts

I think it's easier to call Google's SecurityUtils directly, e.g.:

我认为直接调用 Google 的 SecurityUtils 更容易,例如:

PrivateKey privateKey = SecurityUtils.loadPrivateKeyFromKeyStore(SecurityUtils.getPkcs12KeyStore(), this.getClass().getResourceAsStream("keyFile.p12"), "notasecret", "privatekey", "notasecret")

It's one-line and you don't have to worry about aliasing.

它是单行的,您不必担心混叠。

回答by sdm

The above suggestions did not work for me. Then I tried the one at http://www.java2s.com/Code/Java/Security/RetrievingaKeyPairfromaKeyStore.htmand it worked. Copy pasting it below

以上建议对我不起作用。然后我在http://www.java2s.com/Code/Java/Security/RetrievingaKeyPairfromaKeyStore.htm尝试了一个并且它起作用了。复制粘贴在下面

import java.io.FileInputStream;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.Certificate;

public class Main {
  public static void main(String[] argv) throws Exception {
    FileInputStream is = new FileInputStream("your.keystore");

    KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
    keystore.load(is, "my-keystore-password".toCharArray());

    String alias = "myalias";

    Key key = keystore.getKey(alias, "password".toCharArray());
    if (key instanceof PrivateKey) {
      // Get certificate of public key
      Certificate cert = keystore.getCertificate(alias);

      // Get public key
      PublicKey publicKey = cert.getPublicKey();

      // Return a key pair
      new KeyPair(publicKey, (PrivateKey) key);
    }
  }
}