![](/img/trans.png)
[英]how to determine the algorithm used to generate a private key from a .pem file using java
[英]From certificate Alias to PEM File with private key included using Java
我有以下代碼使用別名生成CER文件:
public class TestFromAliasToCER {
public static final int KEY_SIZE = 1024;
public static final String BEGIN_CERT = "-----BEGIN CERTIFICATE-----";
public static final String END_CERT = "-----END CERTIFICATE-----";
public final static String LINE_SEPARATOR = System.getProperty("line.separator");
public static void main(String[] args) throws FileNotFoundException, IOException, NoSuchAlgorithmException, NoSuchProviderException, KeyStoreException, CertificateException {
KeyStore keyStore = KeyStore.getInstance ("Windows-MY");
keyStore.load (null, null);
Enumeration<String> aux = keyStore.aliases();
String alias = aux.nextElement();
X509Certificate certificate = (X509Certificate) keyStore.getCertificate (alias);
String certString = formatCrtFileContents(certificate);
PrintWriter out = new PrintWriter("cert.CER");
out.println(certString);
out.close();
}
public static String formatCrtFileContents(final Certificate certificate) throws CertificateEncodingException {
final Base64.Encoder encoder = Base64.getMimeEncoder(64, LINE_SEPARATOR.getBytes());
final byte[] rawCrtText = certificate.getEncoded();
final String encodedCertText = new String(encoder.encode(rawCrtText));
final String prettified_cert = BEGIN_CERT + LINE_SEPARATOR + encodedCertText + LINE_SEPARATOR + END_CERT;
return prettified_cert;
}
}
這將創建cer文件
-----BEGIN CERTIFICATE-----
data
-----END CERTIFICATE-----
我希望能夠創建一個包含私鑰的PEM證書,這可能嗎? 如果沒有,為什么?
我不僅限於Java,而且可以自由使用任何Java API,但最好是盡可能減少用戶交互。
盡管我沒有看到它的文檔,但是根據消息來源,SunMSCAPI提供程序僅實現getEncoded
的存根,並且無法導出Windows私鑰,因此您無法使用JCA進行此操作。
您當然可以編寫JNI或JNA來調用Windows CAPI,但這並不簡單。
要在沒有用戶交互的情況下使用現有工具,可以使用Runtime
或ProcessBuilder
使用參數-exportpfx -user -p password certid filename
運行certutil
運行powershell
並告訴它在cert:\\currentuser\\my
選擇一個對象,然后調用Export('PFX','password')
方法- 這里是計算機而非用戶cert的示例
或僅在最近Export-PFXCertificate
使用Export-PFXCertificate
cmdlet 文檔在此處
然后,使用openssl pkcs12
從pkcs12提取到PEM,或者如果您更喜歡Java,則通過以下方式:
加載PKCS12密鑰庫並獲取PrivateKey條目
調用getEncoded
並像使用證書一樣將結果編碼為折疊(MIME)base64,除了使用-----BEGIN/END PRIVATE KEY-----
警告:Java會生成未加密的(PKCS8)私鑰,因此請確保沒有未經授權的用戶或程序可以訪問此文件,您的磁盤/文件系統或任何備份。
數字證書內部沒有私鑰(私鑰不是證書字段的一部分)。 證書和私鑰是相互獨立的實體,盡管它們是相關的 (一個沒有另一個就不可能存在)。
如果查看RFC 5280中的證書字段,您會發現只有公鑰是其中的一部分:
Certificate ::= SEQUENCE {
tbsCertificate TBSCertificate,
signatureAlgorithm AlgorithmIdentifier,
signatureValue BIT STRING }
TBSCertificate ::= SEQUENCE {
... lots of fields
subjectPublicKeyInfo SubjectPublicKeyInfo,
... lots of other fields
}
subjectPublicKeyInfo
是公鑰,沒有用於私鑰的字段。
這是因為證書本來就是公開的(您可以查看公鑰基礎結構的工作原理,以了解為什么公開證書的更多詳細信息)。
盡管證書是公開的,但在某處始終有一個對應的私鑰,通常由證書的所有者(最好是沒有其他人)持有。
無論如何,您獲得的文件(帶有BEGIN CERTIFICATE和END CERTIFICATE標頭)僅存在於數字證書中(而不是私鑰中)。
如果您具有私鑰和相應的證書,則可以創建一個包含兩者的文件。 此類文件的最常見格式為: JKS (也稱為Keystore)和PFX 。
還有另一種“格式”:Windows存儲庫(執行KeyStore.getInstance("Windows-MY")
時正在讀取的存儲庫)。 我不知道文件的格式是什么,但是KeyStore
類對其進行了抽象。
如果存在私鑰,則該私鑰將與它的相應證書一起使用同一別名。 您可以使用以下代碼檢查密鑰是否存在:
String alias = aux.nextElement();
if (keyStore.isKeyEntry(alias)) { // alias contains a private key
Key key = keyStore.getKey(alias, "password".toCharArray()); // need to know the password
// key is the private key
// cert is the key's corresponding certificate
X509Certificate cert = (X509Certificate) keyStore.getCertificate(alias);
} else if (keyStore.isCertificateEntry(alias)) { // alias doesn't contain a key
X509Certificate cert = (X509Certificate) keyStore.getCertificate(alias);
}
獲得密鑰后,可以使用以下代碼將其保存到另一個密鑰庫中:
// create another keystore
KeyStore output = KeyStore.getInstance("JKS");
// "alias" - choose to whatever name you want
// privateKey is the object you've got from keyStore.getKey()
// "password" is the password for this alias
// cert will be stored in the same alias
output.setKeyEntry("alias", privateKey, "password".toCharArray(), new Certificate[] { cert });
// save the keystore to a file
output.store(new FileOutputStream("outputfile.jks"), "keystore password".toCharArray());
上面的代碼創建包含證書和私鑰的文件outputfile.jks
。
如果您希望文件為PFX ,則可以將上面的代碼更改為:
// PKCS12 == PFX format
KeyStore output = KeyStore.getInstance("PKCS12");
// alternative: in pfx, I think that alias can't have specific passwords
// so you can use this as it doesn't require a password for the alias entry
output.setKeyEntry("alias", privateKey.getEncoded(), new Certificate[] { cert });
// change file extension to ".pfx"
output.store(new FileOutputStream("outputfile.pfx"), "keystore password".toCharArray());
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.