首页 > 解决方案 > 从密钥库中检索 X509 证书时出错

问题描述

我正在尝试使用别名和密码检索已存储在 KeyStore 中的 X509Certificate。但是在检索用于签署证书的私钥时,我经常会遇到空指针异常。它有时有效,有时无效。会有一点帮助。谢谢!

在下面的代码中,我尝试删除条件以检查它是否是 PrivateKey 实例。它不起作用。

public X509Certificate generateCertificate(String userId, char[] password, KeyPair newKeyPair, String algorithm) throws Exception
{
    KeyPair groupManagerKeyPair = LoadKeyPair(gmPath, "EC");
    PrivateKey gmPrivateKey = groupManagerKeyPair.getPrivate();
    String dn = "CN="+userId;
    //char[] password = user.getPassword().toCharArray();
    String alias = userId;

    X509CertInfo info = new X509CertInfo();
    Date from = new Date();
    Date to = new Date(from.getTime() + 365 * 86400000l);
    CertificateValidity interval = new CertificateValidity(from, to);
    BigInteger sn = new BigInteger(64, new SecureRandom());
    X500Name owner = new X500Name(dn);

    info.set(X509CertInfo.VALIDITY, interval);
    info.set(X509CertInfo.SERIAL_NUMBER, new CertificateSerialNumber(sn));
    info.set(X509CertInfo.SUBJECT, owner);
    info.set(X509CertInfo.ISSUER, owner);
    info.set(X509CertInfo.KEY, new CertificateX509Key((PublicKey) newKeyPair.getPublic()));
    info.set(X509CertInfo.VERSION, new CertificateVersion(CertificateVersion.V1));
    AlgorithmId algo = new AlgorithmId(AlgorithmId.sha256WithECDSA_oid);
    info.set(X509CertInfo.ALGORITHM_ID, new CertificateAlgorithmId(algo));

    // Sign the cert to identify the algorithm that's used.
    X509CertImpl cert = new X509CertImpl(info);
    cert.sign(gmPrivateKey, algorithm);
    X509Certificate[] certificateChain = new X509Certificate[1];
    certificateChain[0] = cert;
    System.out.println("cert::"+cert);
    //save certificate into keyStore
    saveCertificateInKeyStore(alias, password, gmPrivateKey, certificateChain);

    // Update the algorithm, and resign.
    /*algo = (AlgorithmId)cert.get(X509CertImpl.SIG_ALG);
        info.set(CertificateAlgorithmId.NAME + "." + CertificateAlgorithmId.ALGORITHM, algo);
        cert = new X509CertImpl(info);
        cert.sign(privkey, algorithm);*/
    return cert;
}



public void storeKeyAndCertificateChain(String alias, char[] password, Key key, X509Certificate[] chain) throws Exception{
    String keystore = "D:\\testkeys.jks";
    KeyStore keyStore=KeyStore.getInstance("jks");
    keyStore.load(null,null);
    keyStore.setKeyEntry(alias, key, password, chain);
    keyStore.store(new FileOutputStream(keystore),password);
}




public X509Certificate loadAndDisplayChain(String alias,char[] password) throws Exception{
    //Reload the keystore
    String keystore = "D:\\testkeys.jks";
    KeyStore keyStore=KeyStore.getInstance("jks");
    keyStore.load(new FileInputStream(keystore),password);

    Key key=keyStore.getKey(alias, password);
    X509Certificate x509Certificate = null;
    if(key instanceof PrivateKey){
        System.out.println("Get private key : ");
        System.out.println(key.toString());

        Certificate[] certs=keyStore.getCertificateChain(alias);
        System.out.println("Certificate chain length : "+certs.length);
        for(Certificate cert:certs){
            System.out.println(cert.toString());
            if(certs.length == 1)
                x509Certificate = (X509Certificate) cert;
        }
    }else{
        System.out.println("Key is not private key");
    }
    return x509Certificate;
}


I expect that it should load the certificate using the parameters.. alias and password.

标签: javaspring-bootspring-securitykeystore

解决方案


只是要清楚一点-在正常情况下,您应该使用 X509Certificate 实例使用 KeyManagerFactory 中的 KeyManager 使用 KeyStore 来初始化 SSLContext 等等......

但是可以说你需要检查一些东西。您需要做的只是确保您的 KeyStore 已初始化:

private String keystoreType = "JKS_or_PKCS12";
private String keystoreName = "path_to_keystore";
private String keystorePassword = "your_password";

@Bean
public KeyStore keyStore() throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException {
    KeyStore keyStore = KeyStore.getInstance(keystoreType);
    try (InputStream keyStoreStream = new FileInputStream(keystoreName)) {
        keyStore.load(keyStoreStream, keystorePassword.toCharArray());
    }
    return keyStore;
}

并获取您的 X509Certificate 实例:

public X509Certificate[] x509Certificates(KeyStore keyStore) throws KeyStoreException {
    Enumeration<String> aliases = keyStore.aliases();
    List<X509Certificate> trustedIssuers = new ArrayList<>();
    while (aliases.hasMoreElements()) {
        trustedIssuers.add((X509Certificate) keyStore.getCertificate(aliases.nextElement()));
    }
    return trustedIssuers.toArray(new X509Certificate[0]);
}

要获取您的私钥:

public PrivateKey getPrivateKey(KeyStore keyStore, String keystorePassword, String alias) 
        throws UnrecoverableEntryException, NoSuchAlgorithmException, KeyStoreException {
    KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry) keyStore.getEntry(alias,
            new KeyStore.PasswordProtection(keystorePassword.toCharArray()));
    return privateKeyEntry.getPrivateKey();
}

推荐阅读