All Products
Search
Document Center

Cloud Hardware Security Module (HSM):Code samples

Last Updated:Jan 04, 2023

This topic describes the code samples of the JCE Provider.

AES key with label(persisted key)

import com.cavium.cfm2.CFM2Exception;
import com.cavium.cfm2.LoginManager;
import com.cavium.cfm2.Util;
import com.cavium.key.CaviumKey;
import com.cavium.key.parameter.CaviumAESKeyGenParameterSpec;
import com.cavium.key.store.CaviumKeyStore;
import com.cavium.provider.CaviumProvider;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import javax.crypto.*;
import javax.crypto.spec.GCMParameterSpec;
import java.io.IOException;
import java.security.*;
import java.util.Arrays;
import java.util.Optional;
import java.util.Random;

public class AesKeyPersistWithLabel {
  private static final Logger logger = LogManager.getLogger("AesKeyPersistWithLabel");
  private static final String AES_KEY_LABEL = "aes_key_test";
  private static final String PLAIN_TEXT = "test_example";
  private static final int AES_KEY_SIZE = 256;

  public static void main(String[] args) {
    try {
      Security.addProvider(new CaviumProvider("Cavium", 1L, "The Cavium LiquidSecurity(tm) JCA Provider"));
      logger.info("**** Add Provider ****");
      LoginManager lm = LoginManager.getInstance();
      lm.login();
      logger.info("**** Login Success ****");
      // generate AESKey with label and persist key
      Key key = generateAesKeyAndPersist(AES_KEY_LABEL);
      Optional.ofNullable(key).orElseThrow(() -> new RuntimeException("generate key failed. "));
      // get key with label
      Key keyWithLabel = getKeyWithLabel(AES_KEY_LABEL);
      Optional.ofNullable(keyWithLabel).orElseThrow(() -> new RuntimeException("get key failed. label: " + keyWithLabel));
      // encrypt and decrypt
      encDecGcm((SecretKey) keyWithLabel);
      // delete key by label
      boolean b = deleteKeyWithLabel(AES_KEY_LABEL);
      logger.info("**** Key has been deleted? : " + b + " ****");
      lm.logout();
      logger.info("**** Logout ****");
    } catch (IOException | CFM2Exception e) {
      e.printStackTrace();
    }
  }

  private static Key getKeyWithLabel(String label) {
    logger.info("**** Get Key With Label ****");
    try {
      CaviumKeyStore keyStore = new CaviumKeyStore();
      return keyStore.engineGetKey(label, null);
    } catch (NoSuchAlgorithmException | UnrecoverableKeyException e) {
      e.printStackTrace();
    }
    return null;
  }

  private static boolean deleteKeyWithLabel(String label) {
    logger.info("**** Delete Key With Label ****");
    try {
      Key keyWithLabel = getKeyWithLabel(label);
      Util.deleteKey((CaviumKey) keyWithLabel);
      return true;
    } catch (CFM2Exception e) {
      e.printStackTrace();
    }
    return false;
  }

  private static Key generateAesKeyAndPersist(String label) {
    try {
      KeyGenerator kg = KeyGenerator.getInstance("AES", "Cavium");
      kg.init(new CaviumAESKeyGenParameterSpec(AES_KEY_SIZE, AES_KEY_LABEL, true, true));
      SecretKey secretKey = kg.generateKey();
      logger.info("**** Generate Aes Key And Persist Success ****");
      return secretKey;
    } catch (NoSuchAlgorithmException | NoSuchProviderException | InvalidAlgorithmParameterException e) {
      e.printStackTrace();
    }
    return null;
  }

  private static void encDecGcm(SecretKey k) {
    try {
      Cipher cp = Cipher.getInstance("AES/GCM/NoPadding", "Cavium");
      byte[] iv = new byte[12];
      Random r = new Random();
      r.nextBytes(iv);
      byte[] p = new byte[]{1};
      byte[] aad = new byte[]{2};
      //GCMParameterSpec specify 128-bit tag length and a 12-byte IV. 
      logger.info("**** Encrypt ****");
      cp.init(Cipher.ENCRYPT_MODE, k, new GCMParameterSpec(128, iv));
      cp.updateAAD(aad);
      byte[] c = cp.doFinal(p);
      logger.info("**** Decrypt ****");
      byte[] newiv = cp.getIV();
      cp.init(Cipher.DECRYPT_MODE, k, new GCMParameterSpec(128, newiv));
      cp.updateAAD(aad);
      byte[] v = cp.doFinal(c);
      if (Arrays.equals(p, v)) {
        logger.info("**** Encrypt And Decrypt Success ****");
      } else {
        logger.error("**** Encrypt And Decrypt Failed ****");
      }
    } catch (NoSuchAlgorithmException | NoSuchProviderException | NoSuchPaddingException | InvalidKeyException | InvalidAlgorithmParameterException | IllegalBlockSizeException | BadPaddingException e) {
      e.printStackTrace();
    }
  }
}

RSA key with label(persisted key)

import com.cavium.cfm2.LoginManager;
import com.cavium.cfm2.Util;
import com.cavium.key.CaviumKey;
import com.cavium.key.parameter.CaviumRSAKeyGenParameterSpec;
import com.cavium.key.store.CaviumKeyStore;
import com.cavium.provider.CaviumProvider;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.math.BigInteger;
import java.security.*;
import java.util.Arrays;

public class RsaKeyPersistWithLabel {
  private static final Logger logger = LogManager.getLogger("RsaKeyPersistWithLabel");
  private static final String TRANSFORMATION = "RSA/ECB/OAEPPADDING";
  private static final String SIGN_ALGORITHM = "SHA256WithRSA/PSS";
  private static final String PUBLIC_KEY_LABEL = "rsa_test_publickey";
  private static final String PRIVATE_KEY_LABEL = "rsa_test_privatekey";

  public static void main(String[] args) {
    try {
      Security.addProvider(new CaviumProvider("Cavium", 1L, "The Cavium LiquidSecurity(tm) JCA Provider"));
      logger.info("**** Add Provider ****");
      LoginManager lm = LoginManager.getInstance();
      lm.login();
      logger.info("**** Login Success ****");
      // Generate a Rsa key.
      KeyPair keyPair = generateRSAKeyPair();
      PrivateKey pk = keyPair.getPrivate();
      PublicKey puk = keyPair.getPublic();
      if (pk == null || puk == null) {
        logger.error("**** RSA Key Generate failed ****");
      }
      logger.info("**** RSA Key Generated ****");
      // pub key encrypt
      byte[] plaintext = "test".getBytes();
      CaviumKeyStore keyStore = new CaviumKeyStore();
      byte[] encryptResult = encrypt(TRANSFORMATION, puk, plaintext);
      if (encryptResult != null) {
        logger.info("**** RSA Encrypt Success ****");
      } else {
        logger.error("**** RSA Encrypt Failed ****");
        return;
      }
      // get privateKey by label
      Key privateKey = keyStore.engineGetKey(PRIVATE_KEY_LABEL, null);
      // pri key decrypt
      byte[] decryptResult = decrypt(TRANSFORMATION, privateKey, encryptResult);
      if (decryptResult != null && Arrays.equals(decryptResult, plaintext)) {
        logger.info("**** RSA Decrypt Success ****");
      } else {
        logger.error("**** RSA Decrypt Failed ****");
        return;
      }
      // sign
      byte[] signResult = sign(plaintext, (PrivateKey) privateKey, SIGN_ALGORITHM);
      // verify
      boolean verify = verify(plaintext, signResult, puk, SIGN_ALGORITHM);
      if (verify) {
        logger.info("**** Signature verified ****");
      } else {
        logger.error("**** Signature is invalid! ****");
      }
      // delete key
      Util.deleteKey((CaviumKey) privateKey);
      Util.deleteKey((CaviumKey) puk);
      KeyStore.Entry entry = keyStore.engineGetEntry(PRIVATE_KEY_LABEL, null);
      if (entry != null) {
        logger.error("**** Delete Failed ****");
      } else {
        logger.info("**** Key Deleted ****");
      }
      lm.logout();
      logger.info("**** Logout ****");
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  public static byte[] encrypt(String transformation, Key key, byte[] plainText) {
    logger.info("**** RSA Key Encrypt ****");
    try {
      Cipher encCipher = Cipher.getInstance(transformation, "Cavium");
      encCipher.init(Cipher.ENCRYPT_MODE, key);
      return encCipher.doFinal(plainText);
    } catch (NoSuchAlgorithmException | NoSuchProviderException | NoSuchPaddingException | InvalidKeyException | BadPaddingException | IllegalBlockSizeException e) {
      e.printStackTrace();
    }
    return null;
  }

  public static byte[] decrypt(String transformation, Key key, byte[] cipherText) {
    logger.info("**** RSA Key Decrypt ****");
    try {
      Cipher decCipher = Cipher.getInstance(transformation, "Cavium");
      decCipher.init(Cipher.DECRYPT_MODE, key);
      return decCipher.doFinal(cipherText);
    } catch (NoSuchAlgorithmException | NoSuchProviderException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) {
      e.printStackTrace();
    }
    return null;
  }

  public static byte[] sign(byte[] message, PrivateKey key, String signingAlgorithm) {
    logger.info("**** RSA Key Sign ****");
    try {
      Signature sig = Signature.getInstance(signingAlgorithm, "Cavium");
      sig.initSign(key);
      sig.update(message);
      return sig.sign();
    } catch (NoSuchAlgorithmException | NoSuchProviderException | InvalidKeyException | SignatureException e) {
      e.printStackTrace();
    }
    return null;
  }

  public static boolean verify(byte[] message, byte[] signature, PublicKey publicKey, String signingAlgorithm) {
    logger.info("**** RSA Key Verify ****");
    try {
      Signature sig = Signature.getInstance(signingAlgorithm, "Cavium");
      sig.initVerify(publicKey);
      sig.update(message);
      return sig.verify(signature);
    } catch (NoSuchAlgorithmException | NoSuchProviderException | InvalidKeyException | SignatureException e) {
      e.printStackTrace();
    }
    return false;
  }

  private static KeyPair generateRSAKeyPair() throws
      Exception {
    KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA", "Cavium");
    kpg.initialize(new CaviumRSAKeyGenParameterSpec(2048, new
        BigInteger("65537"), PUBLIC_KEY_LABEL, PRIVATE_KEY_LABEL, true, true));
    return kpg.generateKeyPair();
  }
}

Use SecureRandom to generate random number

import com.cavium.cfm2.CFM2Exception;
import com.cavium.cfm2.LoginManager;
import com.cavium.provider.CaviumProvider;
import com.sun.org.apache.xerces.internal.impl.dv.util.HexBin;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.security.Security;
import java.util.Arrays;

public class SecureRandomGenerateSeed {
 private static final Logger logger = LogManager.getLogger("TestSecureRandom");

 public static void main(String[] args) throws NoSuchProviderException, NoSuchAlgorithmException, IOException, CFM2Exception {
  Security.addProvider(new CaviumProvider("Cavium", 1L, "The Cavium LiquidSecurity(tm) JCA Provider"));
  logger.info("**** Add Provider ****");
  LoginManager lm = LoginManager.getInstance();
  lm.login();
  logger.info("**** Login Success ****");
  SecureRandom random = SecureRandom.getInstance("AES-CTR-DRBG", "Cavium");
  try {
   generateRandomNumberByNextBytes(random);
   generateRandomNumberByGenerateSeed(random);
   logger.info("**** AES-CTR-DRBG by Cavium generateSeed with 16 bytes ****");
  } catch (Exception e) {
   logger.error("**** Failed ****");
   e.printStackTrace();
  }
 }

 public static void generateRandomNumberByNextBytes(SecureRandom random) {
  logger.info("**** Generate Random Number With SecureRandom.nextBytes() ****");
  byte[] bytes = new byte[16];
  random.nextBytes(bytes);
  System.out.println("nextBytes: " + Arrays.toString(bytes));
  System.out.println("HexString: " + HexBin.encode(bytes));
 }

 public static void generateRandomNumberByGenerateSeed(SecureRandom random) {
  logger.info("**** Generate Random Number With SecureRandom.generateSeed() ****");
  byte[] seed = random.generateSeed(16);
  System.out.println("generateSeed: " + Arrays.toString(seed));
  System.out.println("HexString: " + HexBin.encode(seed));
 }
}

Compile and run the sample code

Run the following command to export to a library. Make sure that you change LD_LIBRARY_PATH to your library.

export LD_LIBRARY_PATH=/opt/hsm/lib/:$LD_LIBRARY_PATH

Run the following command to compile the code:

javac -classpath .:/opt/hsm/java/* AesKeyPersistWithLabel.java

If the compilation is successful, the class file AesKeyPersistWithLabel.class is created.

Run the following command to run the sample code:

java -classpath .:/opt/hsm/java/* AesKeyPersistWithLabel