How to use Java to perform ECC operations with an ellipticSecure HSM module

Last updated 2019-08-31

This example demonstrates how to use the Java programming language in order to perform elliptic curve cryptography with a MIRkey or eHSM device using the standard SunPKCS11 provider.

For the full source code, refer to the github repository.

Prerequisites
  1. Follow the Quick Start Guide to configure the device.
  2. Install the eHSM shared library for your platform.
Step by Step guide
  1. Configure the SunPKCS11 provider with a .cfg file:

     name = eHSM
        
     # Modify the path of the eHSM shared library for your system
     library = /usr/local/lib/libehsm.dylib
     #library = /usr/local/lib/libehsm.so
     #library = ehsm.dll
        
     # if you have multiple devices, change to the slot you want to use
     slot = 0
        
    
  2. Setup the PKCS#11 provider and login to the HSM:

         ...
         // Create PKCS11 Provider
         SunPKCS11 p = new SunPKCS11(configFileName);
         Security.addProvider(p);
        
         // Login to the eHSM
         KeyStore ks = KeyStore.getInstance("PKCS11", p);
         ks.load(null,"password".toCharArray());
         ...
    
  3. Generate a test key pair:

         // Generate an EC key pair
         // Notice the use of the provider to force generation on the eHSM instead of software.
         KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC", p);
         ECGenParameterSpec kpgparams = new ECGenParameterSpec(curve);
         keyPairGenerator.initialize(kpgparams);
         System.out.println("Generating key pair.");
         KeyPair keyPair = keyPairGenerator.generateKeyPair();
        
    

    The curve parameter is one of the many supported curves, in this example it’s the NIST curves secp256r1 and secp384r1.

  4. The java provider does not set the CKA_TOKEN attribute by default, so at this point the key pair is generated but only in session data (volatile memory in the device). This default behaviour can be changed by adding a configuration entry to the provider config file (but it might not always be desirable - especially when using ephemeral keys):

     attributes(generate, CKO_PRIVATE_KEY, *) = {
         CKA_TOKEN = true
     }
        
    

    Instead, the preferred way is to optionally use the keystore.setKeyEntry() method to store the key pair in permanent non-volatile storage when required. The java keystore requires a certificate to be stored with key pair entries in order to be found by the java keystore,
    so here we create a self-signed certificate for this purpose:

         // Create a selfsigned certificate to store with the public key. This is a java keystore requirement.
         // the certificate is signed using the eHSM
         System.out.println("Creating self signed certificate.");
         X509Certificate cert = generateCert(
                 keyPair,
                 1,
                 "SHA256withECDSA",
                 "CN=example, L=Town, C=ZZ",
                 null);
         ks.setKeyEntry(alias, keyPair.getPrivate(), null, new X509Certificate[]{cert});
        
    
  5. Once the key pair is generated we can perform signing and verification operations:

         // sign some data
         Signature sig = Signature.getInstance(algo, p);
         sig.initSign(keyPair.getPrivate());
         byte[] data = "test".getBytes();
         sig.update(data);
         byte[] s = sig.sign();
         System.out.println("Signed with hardware key.");
        
         // verify the signature
         sig.initVerify(keyPair.getPublic());
         sig.update(data);
         if (!sig.verify(s)) {
             throw new Exception("signature did not verify");
         }
         System.out.println("Verified with hardware key.");
    

Questions or suggestions? Please contact us using the Support widget or submit a ticket.

Subscribe to receive updates

* indicates required