簡體   English   中英

將證書和私鑰加載到 Java KeyStore

[英]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 ) 中可用:

  1. 使用打開的 ssl 創建私鑰 + 證書文件:

openssl req -x509 -days 365 -newkey rsa:2048 -keyout key.pem -out cert.pem

這將創建 2 個文件 key.pem(加密的私鑰)和 cert.pem(帶有公鑰的證書)。 我使用了一些示例數據,key.pem 的密碼是 123456。

  1. https://keystore-explorer.org/downloads.html下載 Keystore Explorer

  2. 運行資源管理器並創建一個新的 KeyStore

創建新的密鑰庫

  1. select KeyStore 類型 = PKCS12

選擇密鑰存儲類型

  1. 使用“工具”導入密鑰對 - “導入密鑰對”

導入密鑰對

  1. Select 密鑰對類型為 PKCS #8

選擇密鑰對類型

  1. 設置密碼(123456)並選擇密鑰和證書文件,然后按“導入”

設置密碼

  1. 選擇密鑰的別名(默認為證書中給定的 email

選擇別名

  1. 設置密鑰對輸入密碼:kpe123456

設置密鑰對進入密碼

  1. 消息:密鑰對導入成功

消息密鑰對導入成功

保存新的密鑰庫

  1. 使用“文件”-“另存為”保存新的密鑰庫

保存新的密鑰庫

  1. 為密鑰庫設置密碼:ks123456

設置密鑰庫的密碼

  1. 選擇路徑+文件名:keystore.p12

  2. 准備就緒 - 您的私有證書和證書已導入新創建的密鑰庫 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM