Java 憑證 API(java.security.cert、javax.security.auth.x500 等)提供了豐富的功能來處理 X.509 數位憑證與金鑰庫。本文系統整理十大常見操作場景,附帶可直接參考的代碼片段,幫助開發者快速實現憑證管理功能。
CertificateFactory:憑證工廠,支援 X.509 格式生成 Certificate 物件。KeyStore:金鑰庫抽象,預設類型 JKS(Java KeyStore),亦支援 PKCS12。X509Certificate:X.509 憑證介面,提供版本、序號、主體、簽發者、有效期、公鑰、簽名驗證等方法。X509CertImpl、X509CertInfo(Sun 內部類):用於構建、修改憑證細節(如簽發者、序號、演算法、有效期)並簽名。CertificateFactory cf = CertificateFactory.getInstance("X.509");
try (FileInputStream in = new FileInputStream("out.csr")) {
Certificate cert = cf.generateCertificate(in);
System.out.println(cert.toString());
}
String password = "123456";
try (FileInputStream in = new FileInputStream(".keystore")) {
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(in, password.toCharArray());
Certificate cert = ks.getCertificate("myAlias"); // 別名
}
X509Certificate x509 = (X509Certificate) cert;
System.out.println("版本號: " + x509.getVersion());
System.out.println("序列號: " + x509.getSerialNumber().toString(16));
System.out.println("主體名: " + x509.getSubjectX500Principal());
System.out.println("簽發者: " + x509.getIssuerX500Principal());
System.out.println("有效期起: " + x509.getNotBefore());
System.out.println("有效期迄: " + x509.getNotAfter());
System.out.println("簽名演算法: " + x509.getSigAlgName());
// 公鑰編碼
byte[] pkEnc = x509.getPublicKey().getEncoded();
System.out.println("公鑰 (Base64): " + Base64.getEncoder().encodeToString(pkEnc));
try (FileInputStream in = new FileInputStream(".keystore")) {
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(in, "123456".toCharArray());
Enumeration aliases = ks.aliases();
while (aliases.hasMoreElements()) {
String alias = aliases.nextElement();
Certificate c = ks.getCertificate(alias);
System.out.println("Alias: " + alias + ", Type: " + c.getType());
}
}
try (FileInputStream in = new FileInputStream(".keystore")) {
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(in, "123456".toCharArray());
}
try (FileOutputStream out = new FileOutputStream(".keystore")) {
ks.store(out, "654321".toCharArray());
}
String storePass = "123456";
String oldKeyPass = "123456";
String newKeyPass = "654321";
String alias = "myAlias";
try (FileInputStream in = new FileInputStream(".keystore")) {
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(in, storePass.toCharArray());
Certificate[] chain = ks.getCertificateChain(alias);
PrivateKey pk = (PrivateKey) ks.getKey(alias, oldKeyPass.toCharArray());
// 修改密碼或新增條目(若 alias 不存在則新增)
ks.setKeyEntry(alias, pk, newKeyPass.toCharArray(), chain);
try (FileOutputStream out = new FileOutputStream(".keystore")) {
ks.store(out, storePass.toCharArray());
}
}
try (FileInputStream in = new FileInputStream(".keystore")) {
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(in, storePass.toCharArray());
if (ks.containsAlias("sage")) {
ks.deleteEntry("sage");
try (FileOutputStream out = new FileOutputStream(".keystore")) {
ks.store(out, storePass.toCharArray());
}
}
}
caroot 條目的憑證鏈與私鑰。X500Name 類型的主體名作為新憑證的簽發者。CertificateFactory 讀取 user.csr 獲取 X509CertInfo。CertificateValidity(如 3000 天)CertificateSerialNumber(可用時間戳)X500NameAlgorithmId.md5WithRSAEncryption_oid(建議改用 SHA256withRSA)X509CertImpl newCert = new X509CertImpl(certInfo);
newCert.sign(caPrivateKey, "SHA256withRSA"); // 推薦更安全演算法
ks.setCertificateEntry("user_signed", newCert);
ks.store(new FileOutputStream("newstore"), "newpass".toCharArray());
X509Certificate cert = (X509Certificate) cf.generateCertificate(new FileInputStream("aa.crt"));
try {
cert.checkValidity(new Date()); // 當前時間
System.out.println("憑證在有效期內");
} catch (CertificateExpiredException e) {
System.out.println("憑證已過期: " + e.getMessage());
} catch (CertificateNotYetValidException e) {
System.out.println("憑證尚未生效: " + e.getMessage());
}
Certificate caCert = cf.generateCertificate(new FileInputStream("caroot.crt"));
PublicKey caPubKey = caCert.getPublicKey();
try {
cert.verify(caPubKey);
System.out.println("簽名驗證通過");
} catch (Exception e) {
System.out.println("簽名驗證失敗: " + e.getMessage());
}
sun.security.x509.*),優先考慮 Bouncy Castle 等標準庫構建/解析憑證,確保跨 JDK 版本相容。SHA256withRSA 或 SHA384withECDSA,棄用 MD5/SHA1。PKCS12(業界標準,跨平台),而非專有的 JKS。掌握上述操作,即可應對絕大多數 Java 憑證管理需求。實際專案中建議封裝為工具類或引入成熟庫(如 Keycloak、Bouncy Castle)提升安全性與維護性。