![](/img/trans.png)
[英]KeyStore and TrustStore load failed - Private key must be accompanied by certificate chain
[英]Load certificate and private key into Java KeyStore
我正在嘗試從 Azure Key Vault 獲取證書及其私鑰,然后調用遠程服務器並進行客戶端證書身份驗證。
第一部分運行良好(從 Key Vault 獲取),但是我完全堅持將公共和私有材料導入 KeyStore。
我試過了
keyStore.load(publicKey, null);
keyStore.load(new ByteArrayInputStream(privateKey.getBytes()),
"thePassphrase".toCharArray());
但這導致
java.io.IOException: DER input, Integer tag error
at java.base/sun.security.util.DerInputStream.getInteger(DerInputStream.java:192)
at java.base/sun.security.pkcs12.PKCS12KeyStore.engineLoad(PKCS12KeyStore.java:1995)
at java.base/sun.security.util.KeyStoreDelegator.engineLoad(KeyStoreDelegator.java:222)
at java.base/java.security.KeyStore.load(KeyStore.java:1479)
這是完整的東西減去我不知道如何實現的東西 -
DefaultAzureCredential credential = new DefaultAzureCredentialBuilder().build();
SecretClient secretClient = new SecretClientBuilder()
.vaultUrl("https://<myvault>.vault.azure.net")
.credential(credential)
.buildClient();
CertificateClient certClient = new CertificateClientBuilder()
.vaultUrl("https://<myvault>.vault.azure.net")
.credential(credential)
.buildClient();
// Get the public part of the cert
KeyVaultCertificateWithPolicy certificate = certClient.getCertificate("Joes-Crab-Shack");
byte[] publicKey = certificate.getCer();
// Get the private key
KeyVaultSecret secret = secretClient.getSecret(
certificate.getName(),
certificate.getProperties().getVersion());
String privateKey = secret.getValue();
// ***************
// How do i get the cert and its private key into KeyStore?
KeyStore keyStore = KeyStore.getInstance("PKCS12");
// I've also tried "JKS" but that leads to
// java.io.IOException: Invalid keystore format
keyStore.load(...)
// ***************
// Do client certificate authentication
SSLContext sslContext = SSLContexts.custom().loadKeyMaterial(keyStore, null).build();
CloseableHttpClient httpClient = HttpClients.custom().setSSLContext(sslContext).build();
response = httpClient.execute(new HttpGet("https://remote.that.asks.for.client.cert/"));
InputStream inputStream = response.getEntity().getContent();
body = IOUtils.readInputStreamToString(inputStream, Charsets.UTF_8);
我如何將證書及其私鑰放入 KeyStore,以便我可以在我的 HTTP 客戶端中使用它?
在我看來,導入是一項“一次性工作”,不需要以編程方式解決。 我建議(與@pedrofb 相同)您使用 Keystore Explorer 來完成這項工作 - 它在我的測試用例中完美運行:
這是我進行導入的步驟,所有文件都在我的 GitHub-Repo ( https://github.com/java-crypto/Stackoverflow/tree/master/Load_certificate_and_private_key_into_Java_KeyStore ) 中可用:
openssl req -x509 -days 365 -newkey rsa:2048 -keyout key.pem -out cert.pem
這將創建 2 個文件 key.pem(加密的私鑰)和 cert.pem(帶有公鑰的證書)。 我使用了一些示例數據,key.pem 的密碼是 123456。
從https://keystore-explorer.org/downloads.html下載 Keystore Explorer
運行資源管理器並創建一個新的 KeyStore
選擇路徑+文件名:keystore.p12
准備就緒 - 您的私有證書和證書已導入新創建的密鑰庫 keystore.p12
有點晚了,但我想提出一個我在從 Azure Keyvault 檢索證書然后將其放入 java 密鑰庫時實踐過的解決方案。
我使用的依賴項如下。
com.azure:azure-security-keyvault-certificates:jar:4.1.3
com.azure:azure-identity:jar:1.0.4
com.azure:azure-security-keyvault-secrets:jar:4.1.1
然后,代碼塊如下。
char[] emptyPass = {};
// Azure KeyVault Credentials
ClientSecretCredential credential = new ClientSecretCredentialBuilder()
.tenantId(tenantId)
.clientId(clientId)
.clientSecret(clientSecret)
.build();
CertificateClient certificateClient = new CertificateClientBuilder()
.vaultUrl(vaultUri)
.credential(credential)
.buildClient();
SecretClient secretClient = new SecretClientBuilder()
.vaultUrl(vaultUri)
.credential(credential)
.buildClient();
// Azure KeyVault Credentials
// Retrieving certificate
KeyVaultCertificateWithPolicy certificateWithPolicy = certificateClient.getCertificate(alias);
KeyVaultSecret secret = secretClient.getSecret(alias, certificateWithPolicy.getProperties().getVersion());
byte[] rawCertificate = certificateWithPolicy.getCer();
CertificateFactory cf = CertificateFactory.getInstance("X.509");
ByteArrayInputStream certificateStream = new ByteArrayInputStream(rawCertificate);
Certificate certificate = cf.generateCertificate(certificateStream);
// "certificateStream" should be closed
// Retrieving certificate
// Retrieving private key
String base64PrivateKey = secret.getValue();
byte[] rawPrivateKey = Base64.getDecoder().decode(base64PrivateKey);
KeyStore rsaKeyGenerator = KeyStore.getInstance(KeyStore.getDefaultType());
ByteArrayInputStream keyStream = new ByteArrayInputStream(rawPrivateKey);
rsaKeyGenerator.load(keyStream, null);
// "keyStream" should be closed as well.
Key rsaPrivateKey = rsaKeyGenerator.getKey(rsaKeyGenerator.aliases().nextElement(), emptyPass);
// Retrieving private key
// Importing certificate and private key into the KeyStore
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null);
keyStore.setKeyEntry(alias, rsaPrivateKey, emptyPass, new Certificate[] {certificate});
// Importing certificate and private key into the KeyStore
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(
new SSLContextBuilder()
.loadTrustMaterial(null, new TrustAllStrategy())
.loadKeyMaterial(keyStore, pass)
.build(),
NoopHostnameVerifier.INSTANCE);
CloseableHttpClient httpClient = HttpClients.custom()
.setSSLSocketFactory(socketFactory)
.build();
ClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
RestTemplate restTemplate = new RestTemplate(requestFactory);
我希望在 java 密鑰庫中使用 Azure Keyvault 證書尋找解決方案的人可以從中受益。
通過 Google 和“azure key vault get private key”搜索時,我發現了一個 GitHub 問題,詳細描述了如何從 Azure Key Vault 檢索私鑰:
https://github.com/Azure/azure-sdk-for-js/issues/7647
向下滾動以回答https://github.com/Azure/azure-sdk-for-js/issues/7647#issuecomment-594935307有來自開發人員之一的以下聲明:
如何獲取私鑰
知道私鑰存儲在 KeyVault Secret 中,包括公共證書,我們可以使用 KeyVault-Secrets 客戶端檢索它,如下所示:
// Using the same credential object we used before,
// and the same keyVaultUrl,
// let's create a SecretClient
const secretClient = new SecretClient(keyVaultUrl, credential);
// Assuming you've already created a KeyVault certificate,
// and that certificateName contains the name of your certificate
const certificateSecret = await secretClient.getSecret(certificateName);
// Here we can find both the private key and the public certificate, in PKCS 12 format:
const PKCS12Certificate = certificateSecret.value!;
// You can write this into a file:
fs.writeFileSync("myCertificate.p12", PKCS12Certificate);
請注意,默認情況下,證書的 contentType 是 PKCS 12 。 盡管指定證書的內容類型會使獲取 PEM 格式的密鑰變得微不足道,但讓我們首先探討如何從 PKCS 12 證書中檢索 PEM 密鑰。
Using openssl, you can retrieve the public certificate in PEM format by using the following command:
openssl pkcs12 -in myCertificate.p12 -out myCertificate.crt.pem -clcerts -nokeys
You can also use openssl to retrieve the private key, as follows:
openssl pkcs12 -in myCertificate.p12 -out myCertificate.key.pem -nocerts -nodes
簡而言之:您不需要從單獨的“文件”(私鑰-PEM 和證書-PEM)“重建”PKCS12-keystore,因為您獲得了示例中所示的 PKCS12/P12-keystore 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.