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密钥库中,以便使用SSL auth连接到Kafka?_Java_Ssl_Apache Kafka_Bouncycastle_Keystore - Fatal编程技术网

密钥库证书链长度错误-如何以编程方式将整个证书链加载到Java密钥库中,以便使用SSL auth连接到Kafka?

密钥库证书链长度错误-如何以编程方式将整个证书链加载到Java密钥库中,以便使用SSL auth连接到Kafka?,java,ssl,apache-kafka,bouncycastle,keystore,Java,Ssl,Apache Kafka,Bouncycastle,Keystore,我正在尝试为使用SSL身份验证的Kafka使用者设置密钥库,并且不断遇到身份验证问题。我有一个Python示例,它不使用密钥库。所以,我相信我在填充密钥库的方式上做错了什么。 (注意:我不能只在命令行上这样做,因为证书需要根据轮换时间表进行更改,所以我需要使用Java代码来自动执行此操作。) 下面是我填充密钥库的方式: String cert = "-----BEGIN CERTIFICATE-----\n" + "MIIEmTCCAoGgAwIBA

我正在尝试为使用SSL身份验证的Kafka使用者设置密钥库,并且不断遇到身份验证问题。我有一个Python示例,它不使用密钥库。所以,我相信我在填充密钥库的方式上做错了什么。 (注意:我不能只在命令行上这样做,因为证书需要根据轮换时间表进行更改,所以我需要使用Java代码来自动执行此操作。)

下面是我填充密钥库的方式:

String cert = "-----BEGIN CERTIFICATE-----\n" +
        "MIIEmTCCAoGgAwIBAgIUew1ANL9cTyhxLIo1ZpWLdKT4nOwwDQYJKoZIhvcNAQEL\n" +
        ...
        "fjv+XLmCfL1IKqcsEYmEPmyf5Knwk0mO7gtw1fg=\n" +
        "-----END CERTIFICATE-----\n" +
        "-----BEGIN CERTIFICATE-----\n" +
        "MIIFtTCCA52gAwIBAgIUe6eKhfms7ldZ78MxKiMzwFQNhsYwDQYJKoZIhvcNAQEL\n" +
        ...
        "jyDgNvJnm3g5eP6KUm9NNo7Le6lZoZhC3g==\n" +
        "-----END CERTIFICATE-----\n" +
        "-----BEGIN CERTIFICATE-----\n" +
        "MIIG5DCCBMygAwIBAgITKgAABSItHRkNBBF47gAAAAAFIjANBgkqhkiG9w0BAQsF\n" +
        ...
        "CF2TF5vdlOAUtvrJdnYgqNlSQHPAPeBP1runuwCV9ziZBTlra03cFw==\n" +
        "-----END CERTIFICATE-----\n" +
        "-----BEGIN CERTIFICATE-----\n" +
        "MIIF3TCCA8WgAwIBAgITXAAAAALRq61XLgYZigAAAAAAAjANBgkqhkiG9w0BAQ0F\n" +
        ...
        "7ulMCI8RqFm3p32fs//+8o0=\n" +
        "-----END CERTIFICATE-----\n" +
        "-----BEGIN CERTIFICATE-----\n" +
        "MIIFEzCCAvugAwIBAgIQORoOm2GoxqBGK3xSM9br+zANBgkqhkiG9w0BAQ0FADAc\n" +
        ...
        "mBSMIdx3Iw==\n" +
        "-----END CERTIFICATE-----\n";

String privateKey = "-----BEGIN RSA PRIVATE KEY-----\n" +
        "MIIEogIBAAKCAQEAstlhsvxwbG8fVawH++HXq7mrqy9xfjIWwD45JAJSlstBBoBE\n" +
        ...
        "TovqdueB5W7DR0FVYoxmLj3vcG6fy/j9f+O9fb/mo94Ma39Px3I=\n" +
        "-----END RSA PRIVATE KEY-----";

String rootCA = "-----BEGIN CERTIFICATE-----\n" +
        "MIIFEzCCAvugAwIBAgIQORoOm2GoxqBGK3xSM9br+zANBgkqhkiG9w0BAQ0FADAc\n" +
        ...
        "mBSMIdx3Iw==\n" +
        "-----END CERTIFICATE-----";

final PEMParser rootCaParser = new PEMParser(new StringReader(rootCA));
final PEMParser certParser = new PEMParser(new StringReader(certificate));
final PEMParser keyParser = new PEMParser(new StringReader(privateKey));

final X509Certificate rootCa = new JcaX509CertificateConverter().setProvider(new BouncyCastleProvider()).getCertificate((X509CertificateHolder) rootCaParser.readObject());
final X509Certificate cert = new JcaX509CertificateConverter().setProvider(new BouncyCastleProvider()).getCertificate((X509CertificateHolder) certParser.readObject());
final PrivateKey key = new JcaPEMKeyConverter().setProvider(new BouncyCastleProvider()).getKeyPair((PEMKeyPair) keyParser.readObject()).getPrivate();

KeyStore keystore = KeyStore.getInstance("jks");
char[] keyStorePass = config.getKeystorePassword().toCharArray();
char[] trustStorePass = config.getTruststorePassword().toCharArray();
keystore.load(null);

final Certificate[] chain = { cert };
keystore.setKeyEntry("privateKey", key, keyStorePass, chain); 
keystore.setCertificateEntry("CARoot",rootCa);
keystore.setCertificateEntry("localhost", cert);
try (FileOutputStream out = new FileOutputStream(config.getKeystoreLocation())) {
    keystore.store(out, keyStorePass);
}
在测试密钥库时,我注意到私钥(别名为
privatekey
)显示的证书链长度为1。这是不对的,因为实际证书链的长度应为5。因此,我认为链被截断了,就像代码没有正确地将证书链解析为5个证书,而只是一个证书

如果我通过运行以下命令将证书(带链)附加到私钥:

cat pk cert>pkWithChain.pem

并设置PKCS12记录,如:

openssl pkcs12-export-in-pkWithChain.pem-inkey pk-name pkWithChain>pkWithChain.p12

然后将其导入我的密钥库,如:

keytool-importkeystore-srckeystore pkWithChain.p12-destkeystore keystore.jks-srcstoretypkcs12-别名pkWithChain

当我检查密钥库中的密钥时,如下所示:

keytool-list-v-keystore keystore.jks

我手动放在那里的私钥的证书长度为5,但我通过Java放在那里的私钥的证书长度为1

如何以编程方式将正确的(整个)证书链放入密钥库?
(还有,要为Kafka正确设置密钥库,我还需要做些什么?我的Kafka配置/设置已被验证为正确。密钥库是问题所在。)

首先,在修复明显的修订后,您的代码不会编译。它在同一范围内有
String cert=
final X509证书cert=
,还有一个未定义的对
certificate
的引用。我假设第一个
证书
应该是
证书
。鉴于:

PEMParser.readObject()
读取一个PEM块
。这就是为什么它以单数“对象”命名,单数“对象”是一个单独的对象,而不是复数、多个或多个对象

要读取多个证书(在本例中形成链),请使用循环,例如:

/*final*/ PEMParser certParser = new PEMParser(new StringReader(certificate)); // as already
List<Certificate> certlist = new ArrayList<Certificate>();
for( X509CertificateHolder tmp; (tmp = (X509CertificateHolder) certParser.readObject()) != null; )
    certlist.add( new JcaX509CertificateConverter().getCertificate(tmp) ); // don't really need BCprov for this
// add { } if your coding style calls for it
Certificate[] chain = certlist.toArray(new Certificate[certlist.length()]);

PS:有一些方法可以在计划的基础上运行“命令行”程序,完全或部分自动运行,但这是离题的。也可以从Java运行和控制“命令行”程序,但您没有问这个问题。

对不起,我拼凑了几个代码块来创建代码段。这是在ApachePulsar源中运行的,由于数据流中断的问题,混合逻辑以按计划运行某些东西与证书的轮换方式不符。
Collection<? extends Certificate> certcoll = CertificateFactory.getInstance("X.509")
    .generateCertificates( new ByteArrayInputStream(certificate.getBytes()) );
    // note Certificates with an s meaning plural, multiple, not limited to one
    // String.getBytes(/*nocharset*/) is often dangerous, but okay FOR PEM
Certificate[] chain = certcoll.toArray(new Certificate[certcoll.length()]);