使用Java从Keystore中导入证书并获取公钥

3
我已根据PicketLink文档的说明,从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而不是密钥对。这是为什么?如何获取公钥? 更新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

实际的密钥不同。在“公共,证书”中,该密钥与我通过Java代码获取的密钥不同。
2个回答

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

当我执行 keytool -list -keystore keystore.jks 命令时,它显示为 trustedCertEntry 而不是 PrivateKeyEntry。这是一个问题吗? - user2094311
getCertificateChain() 返回 null。 - user2094311
请再检查一遍。您在引用的指令中没有使用别名,而是使用了 salesforce-idp,这与指令中所说的不同。 - user207421
抱歉,我不明白。我已经给出了一个唯一的名称,并且我也将同样的名称用作别名。我有什么遗漏吗? - user2094311
getCertificate() 和获取证书链中的第一个(零)个证书是相同的。请参阅 JavaDoc:https://docs.oracle.com/javase/7/docs/api/java/security/KeyStore.html#getCertificate(java.lang.String) "如果给定的别名标识由 setKeyEntry 调用创建的条目,或由 PrivateKeyEntry 的 setEntry 调用创建的条目,则返回该条目中证书链的第一个元素。" - Darrell Teague
显示剩余3条评论

0

关于什么?

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

编辑

在被投票降级后,我想提供更多细节:

原帖提供了这个链接: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。 - pma
导出命令创建了一个名为public.cert的文件,其中包含公钥。当我执行cat public.cert时,它显示了公钥。但是当我检查两者时发现它们是不同的。 - user2094311
1
我相信_cat_应该显示“------BEGIN CERTIFICATE----”而不是“----BEGIN PUBLIC KEY------”。请参阅此处有关导出的文档:http://docs.oracle.com/javase/tutorial/security/toolsign/step5.html。要从该文件中获取公钥,请参阅此处:https://dev59.com/RWkw5IYBdhLWcg3wJXMh - pma
1
公钥只是其中的一部分。由于其他字段,您正在比较的字符串不匹配。 - pma
所以你在 https://dev59.com/RWkw5IYBdhLWcg3wJXMh 上执行了公认的答案,针对你的 public.cert 得到了 MIIeJGsddf9...? - pma
显示剩余3条评论

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