Different types of keystore in Java -- BKS

English 简体中文 繁体中文 ภาษาไทย Tiếng Việt
Summary

BKS is a keystore format from the BouncyCastle cryptographic library, serving as an alternative to Oracle's JKS for Java applications. Developers can use BKS to securely store various cryptographic assets, including secret keys, private keys alongside their certificate chains, and individual X.509 certificates for trust stores. The process involves installing the BouncyCastle provider, then creating, loading, storing, and deleting entries using standard KeyStore API calls with the "BKS" type. Operations like storing private keys require an associated certificate chain, while certificates can be stored independently. BouncyCastle also provides other keystore implementations like BouncyCastle (UBER) and PKCS12, each with specific encryption and password handling characteristics.

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 还提供了另外两种密钥库实现:BouncyCastlePKCS12

Keystore.BouncyCastle 或 Keystore.UBER 只有在命令行提供密码时才能与 keytool 一起使用,因为整个密钥库都使用基于 SHA1 和 Twofish 的 PBE 进行加密。PBEWithSHAAndTwofish-CBC。这使得整个密钥库能够抵抗篡改和检查,并强制进行验证。Sun JDK 提供的 keytool 即使没有给出密码也会尝试加载密钥库,但这对于此版本来说是不可能的。

PKCS12 提供了与常规密钥库略有不同的情况,密钥库密码当前是用于存储密钥的唯一密码。否则,它支持所有使其能够与 keytool 一起使用的功能。在某些情况下,其他库始终期望处理 Sun 证书,如果是这种情况,请使用 PKCS12-DEF,并且密钥库生成的证书将使用默认提供商。

JAVA KEYSTORE BOUNCYCASTLE BKS

  RELATED

  COMMENTS

0

No comment for this article.