BKS is a keystore format provided by the popular third party Java cryptographic library provider -- BouncyCastle. It is a keystore similar to the JKS provided by Oracle JDK.
Before starting to use BKS, the BouncyCastle provider has to be downloaded and installed. To download the provider, please go to BouncyCastle download page. The provider can be installed by adding an entry in the java.security file.
security.provider.N=org.bouncycastle.jce.provider.BouncyCastleProvider
N means the provider index in the provider list.
Creating BKS keystore
To create a BKS keystore, you just need to create a KeyStore instance of "BKS" and load a null input stream and null password.
KeyStore keyStore = KeyStore.getInstance("BKS", "BC"); keyStore.load(null, null); keyStore.store(new FileOutputStream("mytestkeys.bks"), "password".toCharArray());
Storing secret key
Different from JKS, secret keys can be stored in BKS keystore. Before storing keys, the unrestricted policy files may be needed.
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());
Storing private key
Instead of secret keys, private keys can also be stored in BKS. It requires the corresponding certificate chain to be stored at the same time. Otherwise, exception would be thrown.
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());
Storing certificate
Sometimes when a trust store is needed, no keys need to be stored in the keystore, only the certificates are needed. BKS supports storing certificate without corresponding private key.
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());
Note, to store a certificate, there is no password needed since a certificate no need to be protected normally.
Loading key
When loading a key from the keystore, only need to specify the alias of the key entry. If it's a private key, you may want to use the same alias to load the certificate chain.
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()); }
The output may look like
[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
Loading certificate
This is similar to loading key, the alias is needed for the certificate to be loaded.
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());
The output may look like
[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
Deleting entry
It's an easy task to delete an entry in a keystore. The entry can be a secret key, private key and certificate. The alias is the only one needs to be specified.
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());
To make the deletion effective, the keystore needs to be stored again, otherwise, the entries are not really stored.
In addition to BKS, BouncyCastle provides another two implementations of keystore : BouncyCastle and PKCS12.
Keystore.BouncyCastle, or Keystore.UBER will only work with the keytool if the password is provided on the command line, as the entire keystore is encrypted with a PBE based on SHA1 and Twofish.PBEWithSHAAndTwofish-CBC. This makes the entire keystore resistant to tampering and inspection, and forces verification. The Sun JDK provided keytool will attempt to load a keystore even if no password is given, this is impossible for this version.
PKCS12 provides a slightly different situation from the regular key store, the keystore password is currently the only password used for storing keys. Otherwise it supports all the functionality required for it to be used with the keytool. In some situations other libraries always expect to be dealing with Sun certificates, if this is the case use PKCS12-DEF, and the certificates produced by the key store will be made using the default provider.