【问题标题】:Get public Key from imported certificate in Keystore with Java使用 Java 从 Keystore 中导入的证书中获取公钥
【发布时间】:2018-12-24 17:01:15
【问题描述】:

我已按照PicketLink document 中的说明从sales force 创建并下载了证书。

我下载了证书,它的名称是 mysample.crt 并且 我将证书导入密钥库。

keytool -import -file mysample.crt -keystore keystore.jks -alias salesforce-idp

为了检查,我还导出了公钥

keytool -export -alias salesforce-idp -keystore keystore.jks -rfc -file public.cert

我有一个获取公钥的 Java 代码,但它不起作用。这是我的代码

package com.sample.keystore;

import java.io.File;
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 org.apache.commons.codec.binary.Base64;

public class ExtractPublicKey {

    public static void main(String[] args) {

        try {
            // Load the keystore
            File file = new File("/home/user/salesforce-cert/keystore.jks");
            FileInputStream is = new FileInputStream(file);
            KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
            String alias = "salesforce-idp";
            String password = "user";
            char[] passwd = password.toCharArray();
            keystore.load(is, passwd);
            KeyPair kp = getKeyPair(keystore, alias, passwd);
            Base64 base64 = new Base64();
            PublicKey pubKey = kp.getPublic();

            String publicKeyString = base64.encodeBase64String(pubKey
                    .getEncoded());

            System.out.println(publicKeyString);
            is.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static KeyPair getKeyPair(KeyStore keystore, String alias, char[] password) throws Exception {
            // Get private key
            Key key = keystore.getKey(alias, password);
            if (key instanceof PrivateKey) {
                // Get certificate of public key
                java.security.cert.Certificate cert = keystore.getCertificate(alias);

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

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

}

但是当我运行代码时,我得到以下异常

java.lang.NullPointerException
    at com.sample.keystore.ExtractPublicKey.main(ExtractPublicKey.java:28)

第 28 行引用 PublicKey pubKey = kp.getPublic();。因为该方法返回 null 而不是 Key Pair。这是为什么?以及如何获取公钥?

更新 1

我将代码更新为

keystore.load(is, passwd);
PublicKey pubKey = keystore.getCertificate(alias).getPublicKey();
String publicKeyString = Base64.encodeBase64String(pubKey.getEncoded());
System.out.println(publicKeyString);

然后我得到以下关键

MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlKJTbmfEumDR7nAfBbfAstuUvsgKxizZ1mwGc990dSsmgldIhsrLqpAECdf7vl2q2F8DyXciOopZbJPt/UBmpl6M1TJCQ34UyZaYGI2qid8jSNxFYGApfYPxIBJAk9YOAATqqyAREL+i1mUaFfN8WULFDvz6WsuXOjuxBobqjkg4TUumyyVgZda9ksl3aJmft02AfDMw/GCT8gKPTQb3nZP9BwTo5AQkV5fy0cKZ80G4qD+fiuZJ+8IecgFgXl5agZ0y2Wri8i1OGTGw34SUP2gOO+NUd17YA5AO+ocHlH8yzlXHNH7DPQsLo+Uz8CcXV+eLyzxGTGfuiTw8qsPCCwIDAQAB

螺母实际键不同。在 public,cert 中,密钥与我通过 Java 代码得到的不同。

【问题讨论】:

    标签: java keystore public-key


    【解决方案1】:

    要获取与私钥关联的证书,您应该调用getCertificateChain(),并使用返回数组的第零个元素。不是getCertificate()

    【讨论】:

    • 当我执行 keytool -list -keystore keystore.jks 时,它显示为 trustedCertEntry 而不是 PrivateKeyEntry。有问题吗?
    • getCertificateChain() 返回 null
    • 然后你错误地构建了 KeyStore。您必须使用与创建私钥相同的别名导入签名证书。你没有。检查您链接的说明。
    • 在 Salesforce 中,有一个创建自签名证书的选项。我们只需要提供一个标签和唯一的名称。我也使用与别名相同的名称。我得到了同样的 NullPointerException。
    • 再次检查。您没有在引用的说明中使用别名。你使用了salesforce-idp,这不是它所说的。
    【解决方案2】:

    怎么样

    keystore.load(is, passwd);
    PublicKey pubKey = keystore.getCertificate(alias).getPublicKey();
    String publicKeyString = Base64.encodeBase64String(pubKey.getEncoded());
    

    编辑

    在被否决后,这里有一些我如何看待它的更多细节:

    OP 提供了这个链接:https://docs.jboss.org/author/display/PLINK/Picketlink+as+SP,+Salesforce+as+IDP?_sscc=t 上面写着:

    在 Salesforce 中生成证书后,您可以将其下载到您的计算机上。

    此证书将用于签署从 Salesforce IDP 发送的 SAMLResponse 消息。

    键入自签名

    之后,OP 被告知导入该证书,他现在想从中检索公钥:

    keytool -import -file salesforce_idp_cert.cer -keystore jbid_test_keystore.jks -alias salesforce-idp

    所以很明显

    • OP 没有该证书的私钥
    • 此证书没有链

    【讨论】:

    • 请参阅更新 1。我得到的密钥与实际的私钥不同
    • 您是如何进行比较的? keytool -export 导出证书,而不仅仅是公钥。如果你在 Windows 上,也许下载并使用 keystore-explorer。
    • 导出命令使用公钥创建了一个 public.cert 文件。当我执行 cat public.cert 时,它显示了公钥。当我检查时两者都不同。
    • 我相信 cat 显示 "-----BEGIN CERTIFICATE----" 而不是 "----BEGIN PUBLIC KEY-----" .在此处查看有关导出的文档:docs.oracle.com/javase/tutorial/security/toolsign/step5.html。要从该文件中获取公钥,请参阅:stackoverflow.com/questions/10103657/…
    • 公钥只是其中的一部分。由于其他字段,您正在比较的字符串不匹配
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-15
    • 1970-01-01
    • 2021-05-21
    • 2016-01-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多