package to.noc.hsm.lunasa.example; import com.safenetinc.luna.LunaUtils; import com.safenetinc.luna.provider.key.LunaKey; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import javax.crypto.spec.IvParameterSpec; import java.security.Key; import static java.lang.System.out; /* * This is similar to the other KeyWrapping example, but in this example we generate all keys * on the HSM and call LunaSlotManager::setSecretKeysExtractable. As before, the unwrapped * key is exposed to the application layer. * * Output from a sample run: * * AES Key generated on HSM: * 0x834869E03E3054C127712883B0F7CB9716E2DF619D50002F164934EB9C5C7242 * * Class of key to wrap: * class com.safenetinc.luna.provider.key.LunaSecretKey * * Key to wrap: * 0xBD8B34A1649FB3EC9AF57DD157FA8BB9C2CCDB1C35D37CC51EB32EC39533509D * * Wrapped Key: * 0xBF2DFCC8BB0679B01B03BF0CEB0F666C2C4E35A75743E39B678F1C3007E55F48E02B1DA8A90E227CF6DF6B2BBE8D1277 * * Unwrapped key (in clear same as original): * 0xBD8B34A1649FB3EC9AF57DD157FA8BB9C2CCDB1C35D37CC51EB32EC39533509D * * Plain Text ('SixteenByteClear'): * 0x5369787465656E42797465436C656172 * * Cipher Text: * 0x2F5542DA100B07AF26262A8E31050E85A6F554397AC6EAE161769C93FDC6E81A * */ public class KeyWrappingWithHsmGeneratedKeysExample { // // AES block size is 128 bits or 16 bytes. Used easy HEX values so you can plug them // into a website like http://aes.online-domain-tools.com/ to verify encrypted values. // private static final IvParameterSpec FIXED_128BIT_IV_FOR_TESTS = new IvParameterSpec( LunaUtils.hexStringToByteArray("DEADD00D8BADF00DDEADBABED15EA5ED") ); public static void main(String[] args) throws Exception { HsmManager.login(); HsmManager.setSecretKeysExtractable(true); KeyGenerator lunaKeyGenerator = KeyGenerator.getInstance("AES", "LunaProvider"); Cipher lunaAesCbcCipher = Cipher.getInstance("AES/CBC/PKCS5Padding", "LunaProvider"); // // Generate a wrapping key (KEK: Key Encryption Key) using the Luna SA HSM. // OpenJDK handles AES 256 just fine, but I had to back this down to 128 for // Oracle's JDK which, by default, has strong crypto disabled. // lunaKeyGenerator.init(128); Key kek = lunaKeyGenerator.generateKey(); // // If we hadn't set setSecretKeysExtractable(true), the key printed below would // just be an ID. Since we did make secret keys extractable, the line below will // print the actual key value in the clear. // out.println("AES Key generated on HSM: " + getHex(kek.getEncoded())); // // Generate a second AES key to be wrapped. As with the KEK above, the key printed // below will be the actual key in the clear. // SecretKey keyToWrap = lunaKeyGenerator.generateKey(); out.println("Class of key to wrap: " + keyToWrap.getClass()); out.println("Key to wrap: " + getHex(keyToWrap.getEncoded())); // // Wrap the key // // Note: If you set 'setSecretKeysExtractable' above to false, this exception // will be thrown during the call to 'wrap': // // LunaCryptokiException: function 'C_WrapKey' returns 0x6a // // 0x6a is 'CKR_KEY_UNEXTRACTABLE' // lunaAesCbcCipher.init(Cipher.WRAP_MODE, kek, FIXED_128BIT_IV_FOR_TESTS); byte[] wrappedKey = lunaAesCbcCipher.wrap(keyToWrap); out.println("Wrapped Key: " + getHex(wrappedKey)); // // Unwrap the key // lunaAesCbcCipher.init(Cipher.UNWRAP_MODE, kek, FIXED_128BIT_IV_FOR_TESTS); LunaKey unwrappedKey = (LunaKey)lunaAesCbcCipher.unwrap(wrappedKey, "AES", Cipher.SECRET_KEY); out.println("Unwrapped key (in clear same as original): " + getHex(unwrappedKey.getEncoded())); // // Encrypt data with unwrapped key // lunaAesCbcCipher.init(Cipher.ENCRYPT_MODE, unwrappedKey, FIXED_128BIT_IV_FOR_TESTS); String plainTextStr = "SixteenByteClear"; byte[] plainText = "SixteenByteClear".getBytes(); byte[] cipherText = lunaAesCbcCipher.doFinal(plainText); out.println("Plain Text ('" + plainTextStr + "'): " + getHex(plainText)); out.println("Cipher Text: " + getHex(cipherText)); unwrappedKey.DestroyKey(); HsmManager.logout(); } private static String getHex(byte array[]) { return "0x" + LunaUtils.getHexString(array, false).toUpperCase(); } }