Get public Key from imported certificate in Keysto

2020-07-23 06:48发布

问题:

I have created and downloaded a certificate from sales force, as per the instructions in PicketLink document.

I downloaded the certificate and its name is mysample.crt and I imported the certificate into a keysotre.

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

To check, I exported the public key also

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

I have a Java code to get the Public Key, but it is not working. This is my Code

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;
    }

}

But when I run the code, I get the following exception

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

Line 28 refers to PublicKey pubKey = kp.getPublic();. Because the method returns null instead of the Key Pair. Why is that? And how to get the Public Key?

UPDATE 1

I updated the code to

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

Then I am getting folowing Key

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

Nut actual key is different. In public,cert, the key is different from what I am getting through Java code.

回答1:

To get the certificates associated with a private key, you should be calling getCertificateChain(), and using the zeroth element of the returned array. Not getCertificate().



回答2:

What about

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

Edit

After being downvoted, here some more detail how I see it:

The OP provided this link: https://docs.jboss.org/author/display/PLINK/Picketlink+as+SP,+Salesforce+as+IDP?_sscc=t where it says:

After certificate will be generated in Salesforce, you can download it to your computer.

and

This certificate will be used to sign SAMLResponse messages sent from Salesforce IDP.

Type self-signed

after that, OP is told to import that cert, from which he would now like to retrieve the public key:

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

So it seems obvious that

  • OP does not have the private key for that cert
  • There is no chain for this cert