Java Cryptography Architecture provides a way to plug a cryptography provider without modifying the client code. The client needs to register the provider for it to be available through the Security apis.
This provider leverages Vault's transit secrets for implementing KeyStore, KeyPairGenerator, and Signature algorithms.
- Java 11
- Maven 3.5.4
<dependency>
<groupId>org.honton.chas</groupId>
<artifactId>vault-jca</artifactId>
<version>1.1.0</version>
</dependency>
// Explicity specify vault address and token supplier
VaultApi.setVaultInstance(vaultAddress, () -> vaultToken);
private static final String providerName = VaultProvider.register().getName();
// Otherwise, defaul to using VAULT_ADDR and VAULT_TOKEN environment variables
private static final String NAME = VaultProvider.register().getName();
The KeyStore can fetch existing PublicKey from Vault.
// initialize KeyStore
KeyStore keyStore = KeyStore.getInstance(NAME, NAME);
keyStore.load(null, null);
// get an existing Vault public key
PublicKey publicKey = (PublicKey) keyStore.getCertificate(keyName).getPublicKey();
// get an existing Vault private key. Just a reference for use with signature.sign
PrivateKey privateKey = (PrivateKey) keyStore.getKey(keyName, null);
// list keys
Collections.list(keyStore.aliases());
The KeyPairGenerator can create a new KeyPair in Vault with the name specified in the VaultParameterSpec.
// keyAlgorithmName is from KeyPairGenerator Algorithms table below
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(keyAlgorithmName, NAME);
VaultParameterSpec keySpec;
if ("EC".equals(keyAlgorithmName)) {
// use appropriate VaultRsaKeyType
keySpec = new VaultRsaParameterSpec(keyName, VaultRsaKeyType.RSA_3072);
} else {
// use appropriate VaultEcdsaKeyAlgorithm
keySpec = new VaultEcdsaParameterSpec(keyName, VaultEcdsaKeyAlgorithm.ECDSA_P521);
}
keyPairGenerator.initialize(keySpec);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
// PublicKey is exported from vault and can be transfered out of process
PublicKey publicKey = keyPair.getPublic();
// PrivateKey remains in vault. This is a reference that can be used by signature,initSign
PrivateKey privateKey = keyPair.getPrivate();
The Signature can sign (with the PrivateKey) or verify (with the PublicKey) a message using a Vault key. The keys are obtained from the KeyStore.
// algorithm is from Signature Algorithms table below
Signature signature = Signature.getInstance(signatureAlgorithmName, NAME);
// sign
signature.initSign(privateKey);
signature.update(MESSAGE);
byte[] signatureBytes = signature.sign();
// verify
signature.initVerify(publicKey);
signature.update(MESSAGE);
if (!signature.verify(signatureBytes)) {
throw new VerificationException("");
}
The security provider leverages Vault's transit secrets for implementing the following algorithms.
Algorithm Name | Description |
---|---|
RSA | keypairs for the RSA algorithm |
RSASSA-PSS | keypairs for the RSASSA-PSS signature algorithm |
EC | keypairs for the Elliptic Curve algorithm |
Algorithm Name | Description |
---|---|
Vault | keypairs stored in Vault |
Algorithm Name | Description |
---|---|
Deterministic | RSA signatures using RSASSA-PKCS1-v1_5 |
SHA256withRSA | 2048 bit RSA |
SHA384withRSA | 3072 bit RSA |
SHA512withRSA | 4096 bit RSA |
Randomized | RSA signatures using RSASSA-PSS |
SHA256withRSAandMGF1 | 2048 bit RSA, MGF1 salt 256 bits |
SHA384withRSAandMGF1 | 3072 bit RSA, MGF1 salt 384 bits |
SHA512withRSAandMGF1 | 4096 bit RSA, MGF1 salt 512 bits |
Elliptic Curve | EC signatures |
SHA256withECDSA | 256 bit EC |
SHA384withECDSA | 384 bit EC |
SHA512withECDSA | 512 bit EC |
All private keys remain in Vault. The public key is available through the KeyStore interface. A new KeyPair is generated using the KeyPairGenerator interface.