在pem证书读取java.security.cert.CertificateParsingException: signed fields invalid

先看原代码:

            // 创建CertificateFactory对象  
            CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");  
  
            // 读取PEM证书文件并创建Certificate对象  
            FileInputStream certInputStream = new FileInputStream("pem文件的地址");  
            Certificate certificate = certificateFactory.generateCertificate(certInputStream);  
            certInputStream.close();  
  
            // 创建KeyStore对象并添加证书  
            KeyStore keyStore = KeyStore.getInstance(keyStoreType);  
            keyStore.load(null, null); // 创建一个空的KeyStore,如果不指定密码,则此方法不需要密码参数  
            keyStore.setCertificateEntry(alias, certificate);

说明:这里在运用上有问题,因为java读取是从密钥库中读取证书,不是从pem中读取证书,需要先将pem文件的证书添加密钥库,程序再从秘钥库中读取数据

即是这种

byte[] certAndKey = Files.readAllBytes(Paths.get(PEM_PATH));
byte[] certBytes = parseDERFromPEM(certAndKey, "-----BEGIN CERTIFICATE-----", "-----END CERTIFICATE-----");
byte[] keyBytes = parseDERFromPEM(certAndKey, "-----BEGIN PRIVATE KEY-----", "-----END PRIVATE KEY-----");

X509Certificate cert = generateCertificateFromDER(certBytes);
PrivateKey key  = generatePrivateKeyFromDER(keyBytes);

KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
//KeyStore keystore = KeyStore.getInstance("PKCS12");
keystore.load(null);
keystore.setCertificateEntry("alias", cert);
keystore.setKeyEntry("alias", key, PASSWORD.toCharArray(), new Certificate[] {cert});

//下面这里是上面的方法抽取出来的

private static byte[] parseDERFromPEM(byte[] pem, String beginDelimiter, String endDelimiter) {
    String data = new String(pem);
    String[] tokens = data.split(beginDelimiter);
    tokens = tokens[1].split(endDelimiter);
    return DatatypeConverter.parseBase64Binary(tokens[0]);
}
private static X509Certificate generateCertificateFromDER(byte[] certBytes) throws CertificateException {
    CertificateFactory factory = CertificateFactory.getInstance("X.509");

    return (X509Certificate)factory.generateCertificate(new ByteArrayInputStream(certBytes));
}

private static PrivateKey generatePrivateKeyFromDER(byte[] keyBytes) throws InvalidKeySpecException, NoSuchAlgorithmException {
    //PKCS#8
    PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
    KeyFactory factory = KeyFactory.getInstance("RSA");

    return factory.generatePrivate(spec);
}

如上图,将内容读取到在设置keystore内容进去,而并非下面的这种

CertificateFactory.getInstance("X.509").generateCertificate(certInputStream);

二.对于jks类型的可以直接读取

如下面这种:

String keystorePassword = "<Your KeyStore Password Here>";
final String keyPassword = "<Your Key Password Here>";
final String keystorePath = "<Path to the KeyStore.jks>";

final KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
final FileInputStream fileInputStream = new FileInputStream(new File(keystorePath));
keyStore.load(fileInputStream, keystorePassword.toCharArray());
fileInputStream.close();

final TrustStrategy trustStrategy = new TrustStrategy() {  
   public boolean isTrusted(final X509Certificate[] x509Certs, final String s) throws CertificateException {
      return true;
   }
};

final SSLContext sslContext = SSLContexts.custom()
                                       .loadKeyMaterial(keyStore, keyPassword.toCharArray())
                                       .loadTrustMaterial(keyStore, trustStrategy)
                                       .build();
final SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext);
HttpClients.custom()
                .setSSLSocketFactory(sslConnectionSocketFactory)
                .build();
这里就是直接将jks文件加入到keystore上,jks与pem的格式不同,pem可以看出内容,jks编译后只能给机器读取.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用Bouncy Castle等第三方库来将PEM格式的EC私钥转换为`java.security.interfaces.ECPrivateKey`对象,示例代码如下: ```java import java.io.File; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.security.Security; import java.security.interfaces.ECPrivateKey; import java.security.spec.PKCS8EncodedKeySpec; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.openssl.PEMKeyPair; import org.bouncycastle.openssl.PEMParser; import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter; public class PemToECPrivateKey { public static ECPrivateKey convert(File pemFile, String password) throws Exception { Security.addProvider(new BouncyCastleProvider()); PEMParser pemParser = new PEMParser(Files.newBufferedReader(pemFile.toPath(), StandardCharsets.UTF_8)); Object object = pemParser.readObject(); pemParser.close(); PEMKeyPair keyPair; if (object instanceof PEMKeyPair) { keyPair = (PEMKeyPair) object; } else { throw new IOException("Invalid PEM file: " + pemFile); } PKCS8EncodedKeySpec keySpec; if (password != null && !password.isEmpty()) { keySpec = keyPair.decryptKeyPair(password.toCharArray()).getPrivate().getEncoded(); } else { keySpec = keyPair.getPrivateKeyInfo().getEncoded(); } JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC"); return (ECPrivateKey) converter.getPrivateKey(keySpec); } } ``` 上述代码中,`pemFile`参数是一个PEM格式的密钥文件,`password`参数是密码(如果有的话)。首先需要添加Bouncy Castle提供的安全提供程序。然后使用PEMParser对象读取PEM格式的密钥文件,解析出PEMKeyPair对象。如果密钥文件有密码,需要使用`decryptKeyPair()`方法解密密钥对。然后使用JcaPEMKeyConverter对象将PKCS#8格式的EC私钥规范转换为`java.security.interfaces.ECPrivateKey`对象。最后返回ECPrivateKey对象即可。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值