我正在尝试从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客户端中使用它?
答案 0 :(得分:1)
有点晚了,但我想提出一个我在从 Azure Keyvault 检索证书然后将其放入 java Keystore 时练习过的解决方案。
我使用的依赖项如下。
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 证书的解决方案,可以从中受益。
答案 1 :(得分:0)
在我看来,导入是一项“一次性工作”,不需要以编程方式解决。 我建议您(与@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
选择路径+文件名:keystore.p12
就绪-您的私人和证书将导入到新创建的密钥库keystore.p12
答案 2 :(得分:0)
当通过Google搜索并“ azure key Vault获取私钥”时,我发现了一个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机密中(包括公共证书),我们可以使用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-密钥库,如示例所示, 。