Cryptography in Java. KeyStore Class
- Transfer
Hello, Habr! I present to you the translation of article 9 of the "Java KeyStore" by Jakob Jenkov from a series of articles for beginners who want to learn the basics of cryptography in Java.
Table of contents:
- Java cryptography
- Java cipher
- Messagedigest
- Mac
- Signature
- Keypair
- Keygenerator
- KeyPairGenerator
- Keystore
- Keytool
- Certificate
- CertificateFactory
- CertPath
Keystore
Java KeyStore is a database-style key store provided by the KeyStore class ( java.security.KeyStore ). The storage can be written to disk and read again, it can be password protected, and each key record in the key store can be protected with its own password, which makes the class a KeyStore
useful mechanism for working with encryption keys safely. A keystore can contain keys of the following types:
- Private keys
- Public keys and certificates (Public keys + certificates)
- Secret keys
Private and public keys are used in asymmetric encryption. The public key may have an associated certificate. A certificate is a document proving the identity of a person, organization, or device claiming to own a public key. The certificate is usually digitally signed by the relying party as evidence. Private keys are used in symmetric encryption. In most cases, when setting up a secure connection, symmetric keys are inferior to asymmetric ones, so most often you will store public and private keys in the keystore.
Creating a keystore
You can create an instance KeyStore
by calling its method getInstance()
. Here is an example of creating an instance of a class:
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
This example creates a KeyStore
default instance . You can also create KeyStore instances with a different key storage format by passing a parameter to the method getInstance()
. For example, creating an instance of a keystore PKCS12
:
KeyStore keyStore = KeyStore.getInstance("PKCS12");
Download keystore
Before you can use an instance of a keystore, you must download it. Instances of a class KeyStore
are often written to disk or other storage for later use, because the class KeyStore
assumes that you must read its data before you can use it. However, you can initialize an empty instance KeyStore
without data, as you will see later.
Data is loaded from a file or other storage by calling a method load()
that takes two parameters:
InputStream
from which data will be loaded.char[]
An array of characters containing the password from the keystore.
Here is an example of loading a keystore:
char[] keyStorePassword = "123abc".toCharArray();
try(InputStream keyStoreData = new FileInputStream("keystore.ks")){
keyStore.load(keyStoreData, keyStorePassword);
}
This example loads the keystore.ks keystore file. If you do not want to load any data into the keystore, just pass the value null
for the parameter InputStream
. This is how loading an empty keystore looks like:
keyStore3.load(null, keyStorePassword);
A class instance KeyStore
must always be loaded either with data or with null
. Otherwise, the keystore is not initialized, and all calls to its methods will throw exceptions.
Receiving keys
You can get the keys of an instance of a class KeyStore
through its method getEntry()
. The keystore record is mapped to an alias that identifies the key and is password protected. Thus, in order to access the key, you must pass the key alias and password to the method getEntry()
. Here is an example of write access to an instance KeyStore
:
char[] keyPassword = "789xyz".toCharArray();
KeyStore.ProtectionParameter entryPassword =
new KeyStore.PasswordProtection(keyPassword);
KeyStore.Entry keyEntry = keyStore3.getEntry("keyAlias", entryPassword);
If you know that the record you want to access is the private key, you can convert the instance KeyStore.Entry
to KeyStore.PrivateKeyEntry
. Here's what it looks like:
KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry)
keyStore3.getEntry("keyAlias", entryPassword);
After casting to, KeyStore.PrivateKeyEntry
you can access the private key, certificate, and certificate chain using the following methods:
getPrivateKey()
getCertificate()
getCertificateChain()
Key storage
You can also put the keys in an instance of the class KeyStore
. An example of placing a secret key (symmetric key) in an instance KeyStore
:
SecretKey secretKey = getSecretKey();
KeyStore.SecretKeyEntry secretKeyEntry = new KeyStore.SecretKeyEntry(secretKey);
keyStore3.setEntry("keyAlias2", secretKeyEntry, entryPassword);
Storage
Sometimes you may want to save the keystore to some kind of storage (disk, database, etc.) so that you can load it again another time. A class instance is KeyStore
saved by a method call store()
. Example:
char[] keyStorePassword = "123abc".toCharArray();
try (FileOutputStream keyStoreOutputStream = new FileOutputStream("data/keystore.ks")) {
keyStore3.store(keyStoreOutputStream, keyStorePassword);
}