BKS 是一種由熱門的第三方 Java 加密函式庫提供者 -- BouncyCastle 提供的金鑰庫格式。它類似於 Oracle JDK 提供的 JKS 金鑰庫。
在開始使用 BKS 之前,必須下載並安裝 BouncyCastle 提供者。若要下載提供者,請前往 BouncyCastle 下載頁面。可以透過在 java.security 檔案中新增項目來安裝提供者。
security.provider.N=org.bouncycastle.jce.provider.BouncyCastleProvider
N 代表提供者清單中的提供者索引。
建立 BKS 金鑰庫
若要建立 BKS 金鑰庫,只需建立「BKS」的 KeyStore 執行個體,並載入 null 輸入串流和 null 密碼。
KeyStore keyStore = KeyStore.getInstance("BKS", "BC"); keyStore.load(null, null); keyStore.store(new FileOutputStream("mytestkeys.bks"), "password".toCharArray());
儲存秘密金鑰
與 JKS 不同,秘密金鑰可以儲存在 BKS 金鑰庫中。在儲存金鑰之前,可能需要 不受限制的策略檔案。
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES"); keyGenerator.init(256); Key key = keyGenerator.generateKey(); KeyStore keyStore = KeyStore.getInstance("BKS", "BC"); keyStore.load(new FileInputStream("mytestkeys.bks"), "password".toCharArray()); keyStore.setKeyEntry("aeskey", key, "password".toCharArray(), null); keyStore.store(new FileOutputStream("mytestkeys.bks"), "password".toCharArray());
儲存私密金鑰
除了秘密金鑰之外,也可以將私密金鑰儲存在 BKS 中。這需要同時儲存對應的憑證鏈。否則,將會擲回例外。
CertAndKeyGen gen = new CertAndKeyGen("RSA","SHA1WithRSA"); gen.generate(1024); Key key=gen.getPrivateKey(); X509Certificate cert=gen.getSelfCertificate(new X500Name("CN=ROOT"), (long)365*24*3600); X509Certificate[] chain = new X509Certificate[1]; chain[0]=cert; KeyStore keyStore = KeyStore.getInstance("BKS", "BC"); keyStore.load(new FileInputStream("mytestkeys.bks"), "password".toCharArray()); keyStore.setKeyEntry("rsakey", key, "password".toCharArray(), chain); keyStore.store(new FileOutputStream("mytestkeys.bks"), "password".toCharArray());
儲存憑證
有時當需要信任儲存庫時,不需要在金鑰庫中儲存金鑰,只需要儲存憑證即可。BKS 支援在沒有對應私密金鑰的情況下儲存憑證。
CertAndKeyGen gen = new CertAndKeyGen("RSA","SHA1WithRSA"); gen.generate(1024); X509Certificate cert=gen.getSelfCertificate(new X500Name("CN=SINGLE_CERTIFICATE"), (long)365*24*3600); KeyStore keyStore = KeyStore.getInstance("BKS", "BC"); keyStore.load(new FileInputStream("mytestkeys.bks"), "password".toCharArray()); keyStore.setCertificateEntry("rsacert", cert); keyStore.store(new FileOutputStream("mytestkeys.bks"), "password".toCharArray());
請注意,若要儲存憑證,通常不需要密碼,因為憑證通常不需要受到保護。
載入金鑰
從金鑰庫載入金鑰時,只需要指定金鑰項目的別名。如果是私密金鑰,您可能想要使用相同的別名來載入憑證鏈。
KeyStore keyStore = KeyStore.getInstance("BKS", "BC"); keyStore.load(new FileInputStream("mytestkeys.bks"), "password".toCharArray()); Key key = keyStore.getKey("rsakey", "password".toCharArray()); Certificate[] chain = (Certificate[]) keyStore.getCertificateChain("rsakey"); for(java.security.cert.Certificate cert:chain){ System.out.println(cert.toString()); }
輸出可能如下所示
[0] Version: 3 SerialNumber: 1676692330 IssuerDN: CN=ROOT Start Date: Sun Jul 03 15:29:46 CST 2016 Final Date: Mon Jul 03 15:29:46 CST 2017 SubjectDN: CN=ROOT Public Key: RSA Public Key modulus: 813dd8db5d26940347116b4986eb7bc89fa423c9d9374a422f2951c9a258458175d97ac586a94da851885453e368e249e1c3b14751a80e8d3ec4dc6be19bfd968fa59209f7d032215946e4ad9b0e261d488a35af250e8dbcb9d0fa5c0c309a2be8fe9535950b9b4c6cdca25f9c2e50ed2786bcbce6b2971c80edef9691ae5d63 public exponent: 10001 Signature Algorithm: SHA1WITHRSA Signature: 00362e9e84c5dd02ed6cf589625257abe55d3c5c fdde5cee362222147b5870b89909e3008567e29b 9b4b5c72342219d167dd058b7d1c59ca4696db4e 28ee791989e731fba86ebb1b2caedce98af2a5e7 44a026cc01d9b4b65e0a65b19a684b1b99b71afe 4d27412e852d977a2855e9f011918ac528555469 aeb8406756185b44
載入憑證
這類似於載入金鑰,需要憑證的別名才能載入。
KeyStore keyStore = KeyStore.getInstance("BKS", "BC"); keyStore.load(new FileInputStream("mytestkeys.bks"), "password".toCharArray()); Certificate cert = (Certificate) keyStore.getCertificate("rsakey"); System.out.println(cert.toString());
輸出可能如下所示
[0] Version: 3 SerialNumber: 1676692330 IssuerDN: CN=ROOT Start Date: Sun Jul 03 15:29:46 CST 2016 Final Date: Mon Jul 03 15:29:46 CST 2017 SubjectDN: CN=ROOT Public Key: RSA Public Key modulus: 813dd8db5d26940347116b4986eb7bc89fa423c9d9374a422f2951c9a258458175d97ac586a94da851885453e368e249e1c3b14751a80e8d3ec4dc6be19bfd968fa59209f7d032215946e4ad9b0e261d488a35af250e8dbcb9d0fa5c0c309a2be8fe9535950b9b4c6cdca25f9c2e50ed2786bcbce6b2971c80edef9691ae5d63 public exponent: 10001 Signature Algorithm: SHA1WITHRSA Signature: 00362e9e84c5dd02ed6cf589625257abe55d3c5c fdde5cee362222147b5870b89909e3008567e29b 9b4b5c72342219d167dd058b7d1c59ca4696db4e 28ee791989e731fba86ebb1b2caedce98af2a5e7 44a026cc01d9b4b65e0a65b19a684b1b99b71afe 4d27412e852d977a2855e9f011918ac528555469 aeb8406756185b44
刪除項目
在金鑰庫中刪除項目是一項簡單的任務。項目可以是秘密金鑰、私密金鑰和憑證。只需要指定別名。
KeyStore keyStore = KeyStore.getInstance("BKS", "BC"); keyStore.load(new FileInputStream("mytestkeys.bks"), "password".toCharArray()); keyStore.deleteEntry("aeskey"); keyStore.store(new FileOutputStream("mytestkeys.bks"), "password".toCharArray());
若要使刪除生效,需要再次儲存金鑰庫,否則,項目不會真正儲存。
除了 BKS 之外,BouncyCastle 還提供了另外兩種金鑰庫實作:BouncyCastle 和 PKCS12。
Keystore.BouncyCastle 或 Keystore.UBER 只有在命令列提供密碼時才能與 keytool 搭配使用,因為整個金鑰庫都使用基於 SHA1 和 Twofish 的 PBE 加密。PBEWithSHAAndTwofish-CBC。這使得整個金鑰庫能夠抵抗篡改和檢查,並強制驗證。Sun JDK 提供的 keytool 即使沒有提供密碼也會嘗試載入金鑰庫,但此版本無法做到這一點。
PKCS12 提供與一般金鑰庫略有不同的情況,金鑰庫密碼目前是儲存金鑰時使用的唯一密碼。否則,它支援所有使其能夠與 keytool 搭配使用的必要功能。在某些情況下,其他函式庫始終預期處理 Sun 憑證,如果情況如此,請使用 PKCS12-DEF,並且金鑰庫產生的憑證將使用預設提供者製作。