Java Cryptography Extension (JCE) Provider

Updated: Nov 30, 2017

Download

The SmartKey JCE Provider for all platforms can be downloaded here.

Installation

  • Move the Provider jar file smartkey-jce-provider.jar to ${JAVA_HOME}/jre/lib/ext directory

  • Add SdkmsJCE Provider to the list of providers in the ${JAVA_HOME}/jre/lib/security/java.security file. An example java.security file would look like
      security.provider.1=sun.security.provider.Sun
      security.provider.2=sun.security.rsa.SunRsaSign
      security.provider.3=sun.security.ec.SunEC
      security.provider.4=com.sun.net.ssl.internal.ssl.Provider
      security.provider.5=com.fortanix.sdkms.jce.provider.SdkmsJCE
      security.provider.6=com.sun.crypto.provider.SunJCE
      security.provider.7=sun.security.jgss.SunProvider
      security.provider.8=com.sun.security.sasl.Provider
      security.provider.9=org.jcp.xml.dsig.internal.dom.XMLDSigRI
      security.provider.10=sun.security.smartcardio.SunPCSC
    
  • Apply Unlimited Strength Jurisdiction Policy Files by downloading the Policy file from the Java website. Extract the downloaded zip file, and copy the following two files to ${JAVA_HOME}/jre/lib/security directory.
    • local_policy.jar
    • US_export_policy.jar

Configuration

For the JCE Provider to connect to SmartKey backend, it needs to know the server URL it can talk to, and an API key of an application that is used for authentication of the application. These can be set as environment variables. For example:

    export SDKMS_SERVER_URL=https://sdkms.fortanix.com
    export SDKMS_API_KEY=<your API key>

Keytool and Keystores

keytool utility can now use the SDKMS JCE provider for management of key pairs and certificates which are backed by SmartKey service. SDKMS JCE supports two types of keystores:

1. SDKMS-local

This KeyStore can be used by clients who expect more-or-less JKS (the default keystore) semantics. All metadata will be stored locally and imported to SmartKey when keystore.store is called.

Usage

Flags: -storetype SDKMS-local -providerName sdkms-jce -storepass passwd -keypass passwd
  • Generate Asymmetric keys
keytool -genkeypair -alias alias -keyalg RSA -keystore keystore_file -keysize 1024 -providerName sdkms-jce -storetype SDKMS-local -storepass passwd -keypass passwd -dname "CN=fortanix,OU=fortanix,O=fortanix,L=Mountain View,ST=California,C=US"
  • Import Certificate
keytool -importcert -trustcacerts -alias alias -file certificate-path -keystore keystore_file -providerName sdkms-jce -storetype SDKMS-local -storepass passwd -noprompt -trustcacerts
  • Import Keystore
keytool -importkeystore -srcstoretype SDKMS-local -deststoretype SDKMS-local -srcalias alias -srcProviderName sdkms-jce -destProviderName sdkms-jce -srckeystore source_keystore_file -destkeystore dest_keystore_file -srcstorepass passwd -deststorepass passwd -srckeypass passwd -destkeypass passwd
  • Generate AES Symmetric Keys
keytool -genseckey -alias alias -keyalg AES -keysize 256 -storepass passwd -keypass passwd -keystore keystore_file -providerName sdkms-jce -storetype SDKMS-local
  • Import password as Secret key
keytool -importpassword -alias alias -storepass passwd -keystore keystore_file -providerName sdkms-jce -storetype SDKMS-local
  • List
keytool -list -v -keystore keystore_file -providerName sdkms-jce -storetype SDKMS-local -storepass passwd
  • Delete
keytool -delete -alias alias -keystore keystore_file -providerName sdkms-jce -storetype SDKMS-local -storepass passwd

2. SmartKey

This KeyStore can be used when a user needs to interact with SmartKey directly without storing any metadata locally. SmartKey Groups is an abstraction for different keystore for a user, hence a groupId will be used while storing and retrieving the keys for this keystore type.

Usage

Flags: `-storetype SDKMS -providerName sdkms-jce -keypass <groupId> -storepass <groupId>`
  • Import Certificate
keytool -importcert -trustcacerts -alias alias -file certificate-path -keystore keystore_file -providerName sdkms-jce -storetype SDKMS -storepass 2ff36949-ee70-4145-bd57-7de1ada5c050 -noprompt -trustcacerts
  • Generate AES Symmetric Keys
keytool -genseckey -alias alias -keyalg AES -keysize 256 -storepass 2ff36949-ee70-4145-bd57-7de1ada5c050 -keypass 2ff36949-ee70-4145-bd57-7de1ada5c050 -keystore keystore_file -providerName sdkms-jce -storetype SDKMS
  • Import password as Secret key
keytool -importpassword -alias alias -storepass 2ff36949-ee70-4145-bd57-7de1ada5c050 -keystore keystore_file -providerName sdkms-jce -storetype SDKMS
  • List the above generated AES Key
keytool -list -v -keystore keystore_file -providerName sdkms-jce -storetype SDKMS -storepass 2ff36949-ee70-4145-bd57-7de1ada5c050
  • Delete the above AES Key
keytool -delete -alias alias -keystore keystore_file -providerName sdkms-jce -storetype SDKMS -storepass 2ff36949-ee70-4145-bd57-7de1ada5c050

Java Examples

Generate RSA Keys

SdkmsJCE provider = SdkmsJCE.getInstance();
String algorithm = AlgorithmParameters.RSA;
KeyPairGenerator keyGenerator = KeyPairGenerator.getInstance(algorithm, provider);
keyGenerator.initialize(2048);
KeyPair rsaKeyPair = keyGenerator.generateKeyPair();

RSA Sign and Verify

...
String algorithm = AlgorithmParameters.RSA;
KeyPair rsaKeyPair = keyGenerator.generateKeyPair();
Signature sig = Signature.getInstance(algorithm, provider);
sig.initSign(rsaKeyPair.getPrivate());

// sign
byte[] data = "testData".getBytes("UTF8");
sig.update(data);
byte[] signatureBytes = sig.sign();

//verify
sig.initVerify(keyPair.getPublic());
sig.update(data);
assertEquals(true, sig.verify(signatureBytes));

Generate AES Keys

SdkmsJCE provider = SdkmsJCE.getInstance();
String algorithm = AlgorithmParameters.AES;
KeyPairGenerator keyGenerator = KeyPairGenerator.getInstance(algorithm, provider);
keyGenerator.initialize(256);
SecretKey aesKey = keyGenerator.generateKey();

AES Cipher Encryption and Decryption

...
String algorithm = AlgorithmParameters.AES;
String mode = CipherMode.ECB.toString();
String padding = ProviderConstants.PKCS5PADDING

SecretKey secretKey = keyGenerator.generateKey();

Cipher cipher = Cipher.getInstance(algorithm, provider);
cipher.init(Cipher.ENCRYPT_MODE, secretKey);

String PLAIN = "testData";
// encryption
byte[] cipherBytes = cipher.doFinal(PLAIN.getBytes());

// decryption
cipher.init(Cipher.DECRYPT_MODE, key, params);
byte[] plainBytes = cipher.doFinal(cipherBytes);

// verify
assertEquals(new String(plainBytes), PLAIN);