【问题标题】:Getting a PrivateKey object from a .p12 file in Java从 Java 中的 .p12 文件中获取 PrivateKey 对象
【发布时间】:2013-09-04 18:47:00
【问题描述】:

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

【问题讨论】:

    标签: java google-api google-prediction


    【解决方案1】:

    您可以使用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) 从任何位置加载资源,前提是它们已经在类路径中,无需指定文件路径。

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

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

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

    输出

    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
    

    【讨论】:

    • 不熟悉这种加密方式...什么是keyAlias?
    • 添加了有关如何列出密钥库内容以查找别名的信息。
    • @Syon 是否可以从其内容创建密钥库,而不是从 java.io.File?
    • 我不完全确定您所说的“从它的内容”是什么意思。 KeyStore 类有多种方法可以将密钥加载到其中。您可以使用keystore.load(new ByteArrayInputStream(someByteArray)),也可以使用SetKeyEntry 方法之一。
    • 'p12Password.toCharArray()' 来自哪里?
    【解决方案2】:

    我觉得直接调用谷歌的SecurityUtils比较容易,例如:

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

    它是单行的,您不必担心别名。

    【讨论】:

    • 感谢您也将密码放在那里,我担心我会忘记它。
    • @Robert Watts 所以在本次通话中,您使用“privatekey”作为别名。那是因为 privateKey 是 pkcs12 密钥的默认别名吗?我搜索但找不到任何关于此的文档。我运行了 keytool,我的别名实际上是“privatekey”,但我想确保它总是用于新密钥。
    • @UsmanMutawakil 我不相信 pkcs12 文件格式有任何标准的默认别名。 Keytool 可能会默认使用该别名,也许其他工具/程序也会这样做,但它并不是文件格式固有的。
    • @Robert Watts 实际上第四个参数是别名。
    • 我确实觉得一个名为 SecurityUtils 的类会接受密码作为字符串很有趣。
    【解决方案3】:

    如果您从getKey() 获得null(例如,您使用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);
    

    【讨论】:

    • 这最终帮助了我。我的密钥库有一个奇怪的别名,即 getkey 总是返回 null。使用上述方法迭代解决了这个问题。
    • 这对我帮助很大。谢谢。 keytool 表明我有一个名为“1”的别名(使用openssl 创建时的默认别名。不确定它是intstring)。但是 keystore.aliases() 为该别名返回一个很长的奇怪字符串。
    【解决方案4】:

    以上建议对我不起作用。然后我在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);
        }
      }
    }
    

    【讨论】:

      猜你喜欢
      • 2015-05-18
      • 1970-01-01
      • 2017-11-24
      • 2015-05-24
      • 1970-01-01
      • 2017-02-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多