Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ssl/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java无法加载";“开始受信任证书”;格式证书_Java_Ssl_Ssl Certificate_Ca - Fatal编程技术网

Java无法加载";“开始受信任证书”;格式证书

Java无法加载";“开始受信任证书”;格式证书,java,ssl,ssl-certificate,ca,Java,Ssl,Ssl Certificate,Ca,我有一个CA证书,它是由openssl生成的,带有“trustout”,所以它以“----开始可信证书------”开头,当我试图用Java读取它时,会抛出异常。 Java支持这种证书格式吗?如果是,如何阅读 public class TestReadCerts { public static void main(String[] args) { // TODO Auto-generated method stub String sslrootcert

我有一个CA证书,它是由openssl生成的,带有“trustout”,所以它以“----开始可信证书------”开头,当我试图用Java读取它时,会抛出异常。 Java支持这种证书格式吗?如果是,如何阅读

public class TestReadCerts {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
         String sslrootcertfile = "F:\\javaworkspace\\opensource\\certs\\ca.pem";

            FileInputStream fis=null;
            try {
              fis = new FileInputStream(sslrootcertfile); // NOSONAR
            } catch (FileNotFoundException ex) {
              ex.printStackTrace();
            }
            try {
              CertificateFactory cf = CertificateFactory.getInstance("X.509");

              Object[] certs = cf.generateCertificates(fis).toArray(new Certificate[]{});

            } catch (Exception e) {
              e.printStackTrace();
            } 
    }

}
例外情况: java.security.cert.CertificateException:无法初始化

java.io.IOException: extra data given to DerValue constructor
    at java.base/sun.security.x509.X509CertImpl.<init>(X509CertImpl.java:191)
    at java.base/sun.security.provider.X509Factory.parseX509orPKCS7Cert(X509Factory.java:476)
    at java.base/sun.security.provider.X509Factory.engineGenerateCertificates(X509Factory.java:361)
    at java.base/java.security.cert.CertificateFactory.generateCertificates(CertificateFactory.java:478)
    at TestReadCerts.main(TestReadCerts.java:21)
Caused by: java.io.IOException: extra data given to DerValue constructor
    at java.base/sun.security.util.DerValue.init(DerValue.java:409)
    at java.base/sun.security.util.DerValue.<init>(DerValue.java:294)
    at java.base/sun.security.util.DerValue.<init>(DerValue.java:305)
    at java.base/sun.security.x509.X509CertImpl.<init>(X509CertImpl.java:188)
    ... 4 more
请同时查看dave_thompson_085的答案,因为它指出了我理解中的一些不准确之处,并因此给出了这个答案


您的问题是试图使用
CertificateFactory
读取
PEM
编码证书,该证书需要
DER
编码,如中所述

对于X.509证书的证书工厂 inStream中提供的证书必须采用DER编码,并且可以 以二进制或可打印(Base64)编码提供

我认为读取证书的最快方法是将证书转换为适当的编码。由于您已经提到使用
openssl
生成证书,您可以将当前证书编码为
DER

$ openssl x509 -in /F/javaworkspace/opensource/certs/ca.pem -outform DER -out /F/javaworkspace/opensource/certs/ca.der
(根据需要将路径调整为
ca.pem
ca.der

最后,不要忘记更新
sslrootcertfile
变量

String sslrootcertfile = "F:\\javaworkspace\\opensource\\certs\\ca.der";

PEM类型的“可信证书”是一种特定于OpenSSL的非标准格式,Java无法立即处理。它实际上包含标准的X.509证书,作为一个DER块加上另一个OpenSSL定义的DER信任信息块

如果您有OpenSSL,最简单的方法是使用
OpenSSL x509 out
转换为标准的“证书”格式。您可以像Misantorp那样添加
-outform DER
,但这不是必需的
CertificateFactory
可以读取DER或PEM中的标准格式,因为OpenSSL不准确地调用了它们

如果您拥有或可以从中获取并使用bcpkix和bcprov,则它们包括处理此OpenSSL PEM格式(以及许多其他格式)的例程:

否则,可以手动分解DER,但操作笨拙且不可靠:

        String in1 = new String(Files.readAllBytes(new File(args[0]).toPath()));
        byte[] both = Base64.getMimeDecoder().decode(in1.replaceAll("-----[A-Z ]*-----\\r?\\n",""));
        if( both[0]!=0x30 || both[1]!=(byte)0x82 ) throw new Exception("wrong!"); // or other handling
        byte[] cert = Arrays.copyOf(both, (both[2]<<8 | both[3]&0xFF) + 4);
        X509Certificate good = (X509Certificate) CertificateFactory.getInstance("X.509")
                .generateCertificate(new ByteArrayInputStream(cert));
        System.out.println (good.getSubjectX500Principal().getName());
String in1=新字符串(Files.readAllBytes(新文件(args[0]).toPath());
byte[]both=Base64.getMimeDecoder().decode(in1.replaceAll(“----[A-Z]*----\\r?\\n”,”);
如果(两个[0]!=0x30 | |两个[1]!=(字节)0x82)抛出新异常(“错误!”);//或其他处理

byte[]cert=Arrays.copyOf(两者,(两者[2]相关的此前提的可能重复项都是错误的;Java
CertificateFactory
可以读取OpenSSL调用DER的内容(更确切地说,Java调用binary DER)或OpenSSL调用PEM的内容(Java不准确地调用base64 DER)。但它无法读取特定于OpenSSL的非标准“受信任证书”格式。无论您使用
-outform DER
还是默认的
-outform PEM
,运行
OpenSSL x509
都会转换为标准格式。
        // assumes filename in args[0], adjust as needed
        Object both = new PEMParser(new FileReader(args[0])).readObject();
        // should close the FileReader, maybe using try-resources
        byte[] cert = ((X509TrustedCertificateBlock)both).getCertificateHolder().getEncoded();
        X509Certificate good = (X509Certificate) CertificateFactory.getInstance("X.509")
                .generateCertificate(new ByteArrayInputStream(cert));
        System.out.println (good.getSubjectX500Principal().getName());
        String in1 = new String(Files.readAllBytes(new File(args[0]).toPath()));
        byte[] both = Base64.getMimeDecoder().decode(in1.replaceAll("-----[A-Z ]*-----\\r?\\n",""));
        if( both[0]!=0x30 || both[1]!=(byte)0x82 ) throw new Exception("wrong!"); // or other handling
        byte[] cert = Arrays.copyOf(both, (both[2]<<8 | both[3]&0xFF) + 4);
        X509Certificate good = (X509Certificate) CertificateFactory.getInstance("X.509")
                .generateCertificate(new ByteArrayInputStream(cert));
        System.out.println (good.getSubjectX500Principal().getName());