Use a GVSM (SM Cryptography) HSM Cluster

Updated at:

Get started with Cloud Hardware Security Module (Cloud HSM) by creating and activating an HSM cluster, and then using a key in the cluster to encrypt and decrypt data. This quickstart uses a GVSM instance as an example.

Usage notes

  • Applicable instances — This quickstart applies to GVSM instances. To create an HSM cluster for a KMS hardware key management instance, see Create an HSM cluster for a hardware key management instance.

  • Key material — To protect your HSM instance data, do not use test keys in production environments.

Prerequisites

  • An HSM instance is purchased. For instructions, see Purchase a Cryptographic Machine.

  • An ECS instance that runs Windows and resides in the same VPC as the HSM instance is purchased. For instructions, see Quick Start for Windows-based ECS instances.

    • You use this ECS instance to install the HSM instance management tool, not as a business server.

  • At least two vSwitches are available in the VPC. You must specify at least two vSwitches to create and activate an HSM cluster.

Step 1: Create and activate a cluster

If you configured the cluster information when you purchased the HSM instances, Cloud HSM creates the cluster automatically after you place your order. In this case, skip this step.

An HSM cluster consists of one master HSM and one or more non-master HSMs. All HSMs in the same cluster must belong to the same VPC. They can reside in the same subnet or in different subnets.

Whitelist rules — The following rules apply to both the whitelist of an individual HSM instance and the whitelist of a cluster:

  • You can enter one IP address or CIDR block per line. You can enter up to 10 entries.

  • If no whitelist is configured, all IP addresses can access the HSM instance or the cluster.

  • If a whitelist is configured, only requests from IP addresses in the whitelist are allowed. Requests from other IP addresses are denied.

  • The cluster whitelist takes precedence over the whitelists of individual HSM instances in the cluster. For example, if the whitelist of an HSM instance in the cluster is 10.10.10.10 and the cluster whitelist is 172.16.0.1, you can access the HSM instance only from 172.16.0.1.

  • You cannot configure 0.0.0.0/0 to allow all source IP addresses. For security reasons, allowing all source IP addresses is not recommended. To allow all source IP addresses for temporary testing, leave the whitelist empty.

    To create and activate a cluster, perform the following steps:

  1. Log on to the Cloud HSM console and go to the VSMs page. In the top navigation bar, select the destination region.

  2. Enable the master HSM instance.

    1. On the VSMs page, find the HSM instance that you created. In the Actions column, click Enable.

    2. In the Configure HSM Instance dialog box, configure the following parameters, and then click OK.

      Parameter

      Description

      VPC ID

      Select the VPC to which the HSM instance is attached. This VPC must be the same as the one attached to your ECS instance.

      VPC Subnet

      Select the subnet CIDR block of the VPC where the HSM instance resides.

      Private IP Address

      Assign a private IP address to the HSM instance. The private IP address must belong to the subnet CIDR block of the VPC. Otherwise, configuration fails. IP addresses ending in 253, 254, or 255 are system reserved IP addresses. Do not use them.

      Configure HSM Whitelist

      Configure the whitelist for accessing the HSM instance, based on the whitelist rules described in this step.

    3. Verify that the Status of the HSM instance changes to Enabled.

  3. Create an HSM cluster.

    1. Find the master HSM instance. In the Actions column, click Create Cluster.

    2. In the cluster creation panel, configure the following cluster information.

      Parameter

      Description

      Cluster Name

      Enter a custom name for the cluster. The name must be unique and cannot exceed 24 characters.

      Configure Whitelist

      Specify the IP addresses that can access the cluster, based on the whitelist rules described in this step.

      Specify vSwitches

      Select vSwitches in the required zones based on your business needs. You must specify at least two vSwitches to create and activate an HSM cluster.

  4. Initialize the master HSM.

    You can activate the cluster only when the master HSM is in the Initialized state. Choose an initialization method based on your HSM type and client environment.

    Initialization method

    Requirements

    One-click initialization in the Cloud HSM console

    Your HSM is a GVSM instance and you do not require UKEY support.

    Initialization with the HSM instance management tool

    A Windows client, because the HSM instance management tool runs only on Windows.

    To initialize the master HSM in the console

    1. At the bottom of the cluster creation panel, click Initialize the master HSM with a few clicks.

    2. In the Initialize Instance dialog box, click OK. Initialization is expected to take 1 to 5 minutes.

    3. After the initialization is complete, click the update icon next to Selected Master HSM:. The status changes to Initialized.

    Warning

    Do not reinitialize the master HSM when it is in the Initialized state.

    To initialize the master HSM by using the HSM instance management tool

    1. At the bottom of the cluster creation panel, click Download HSM instance management tool.

    2. Extract the HSM software package.

    3. Complete the initialization as described in the Initial Initialization section of the user manual included in the package.

  5. After the master HSM is in the Initialized state, click Next.

  6. Follow the on-screen instructions to add non-master HSMs to the cluster, and then click Complete.

Step 2: (Optional) Generate certificates and configure mutual TLS authentication

Perform this step if you enabled automatic certificate generation when you purchased the GVSM instance. In this case, Cloud HSM generates the certificates for you, and you only need to configure the certificates on the client SDK side. Cloud HSM deploys the certificates inside the server-side HSM automatically.

  1. Deploy the certificates on the client.

    Download the client certificate from the console and deploy it to your client.

    1. On the HSM details page, click Get Cluster Certificate. The downloaded folder contains the following files:

      certs/
      ├── client.p12 (Client certificate in PKCS12 format, which contains the client certificate and private key)
      ├── client.pem (Client certificate in PEM format)
      ├── rootca.key (CA private key)
      ├── rootca.pem (CA certificate in PEM format)
      ├── server.p12 (Server certificate in PKCS12 format)
      └── passphrase (Passphrase for the PKCS12 certificate with the .p12 extension)
    2. Deploy the client.p12 and rootca.pem files to the client. In the client configuration file, you must also configure the file paths for client.p12 and rootca.pem, and the passphrase value. For more information, refer to the documentation included in the package that you downloaded from the console.

  2. Deploy the certificate on the server.

    The HSM automatically deploys the certificate to the HSM instance. No action is required.

Important

The default validity period for a certificate is 10 years. Before a certificate expires, the HSM automatically generates a new certificate and rotates the server certificate. Do not use the HSM instance management tool to create a UKEY administrator. Otherwise, the certificate rotation fails.

Step 3: Synchronize cluster data

The cluster type determines whether you must synchronize cluster data manually.

  • If the Cluster Type is Manual Cluster Synchronization: You must synchronize the cluster after its initial creation and activation, or when data on the master HSM changes. Synchronization is not required when scaling out the cluster.

  • If the Cluster Type is Automatic Cluster Synchronization: Synchronization is automatic. The master HSM automatically synchronizes new keys, configured SSL certificates, and user information to the child HSMs.

Warning

Cluster synchronization takes about 5 minutes. Perform this operation during off-peak hours to avoid service disruptions.

  1. On the VSMs page, find the target master HSM instance. In the Cluster Type column of the instance list, check the synchronization type (Manual Cluster Synchronization / Automatic Cluster Synchronization).

    If the Cluster Type is Manual Cluster Synchronization, you must synchronize the cluster.

  2. In the Actions column, click Synchronize Cluster. In the dialog box that appears, click Synchronize Cluster again.

Step 4: Create a key and use the key to encrypt and decrypt data

The HSM software package includes the HSM developer guide and SDK test programs. You can use the developer guide to call API operations and manage your HSM instance.

Note

You can download the HSM software package on the VSMs page of the CloudHSM console. Find the target HSM instance, click the Specifications column, and then click Download HSM instance management tool. Extract the downloaded file to obtain the HSM software package.

For example, for a general-purpose HSM (GVSM), locate the APITest.java test case in the extracted Alibaba CloudHSM GVSM Software Package>SDK>JAVA>Server HSM Interface Documentation>Test Demo directory. You can use this test case to test the HSM instance. The following provides sample code:

Note

Replace the IP address (192.168.XX.XX) in the test case with the private IP address assigned to your HSM instance.

package cn.tass.hsm;

import cn.tass.SJJ1507.devices.RasKeyUtils;
import cn.tass.common.kits.Padding;
import cn.tass.exceptions.TAException;
import cn.tass.hsm.GHSMAPI;
import cn.tass.kits.Forms;
import cn.tass.hsm.Host;
import cn.tass.hsm.LogConfig;
import cn.tass.util.encoders.Base64;
import org.junit.Test;

import javax.naming.ConfigurationException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class APITest {
    LogConfig logConfig = new LogConfig("error", "./");
    Host host1 = new Host("GHSM", -3, "192.168.XX.XX", 8019, 5);
    List<Host> hosts = new ArrayList<Host>() {{
        add(host1);
    }};

    String config =
            "{"
                    + "[LOGGER];"
                    + "logsw=debug,error;logPath=./;"
                    + "[HOST 1];"
                    + "hsmModel=GHSM;"
                    + "host=192.168.XX.XX;linkNum=-3;"
                    + "port=8019;"
                    + "timeout=5;"
                    + "}";

//    GHSMAPI api = GHSMAPI.getInstance(hosts, logConfig);
    GHSMAPI api = GHSMAPI.getInstance(config);

    /**
     * Symmetric key encrypted by LMK
     */
    byte[] symmetricKey = Forms.hexStringToByteArray("669C1CEDDA****5D727EA727558B5");
    byte[] verifyValue = Forms.hexStringToByteArray("BD85****4D88");

    byte[] symmetricKey1 = Forms.hexStringToByteArray("93EF12C958****C3EFDBC7B37642D");
    byte[] verifyValue1 = Forms.hexStringToByteArray("7830****B8E6");
    /**
     * Ciphertext of session key encrypted by LMK
     */
    byte[] symmetricKeyKEK = Forms.hexStringToByteArray("2E80A42018****BCF639F644629E8");
    /**
     * Verification value of session key
     */
    byte[] verifyValueMAC = Forms.hexStringToByteArray("734D****3E38");
    /**
     * Ciphertext protected by protection key
     */
    byte[] protectionKey = Forms.hexStringToByteArray("2EACE685C5EB2638D120*****60CD44210B43C894A77C");
    /**
     * MAC of ciphertext protected by protection key
     */
    byte[] protectionMAC = Forms.hexStringToByteArray("0CB8****E487");

    /**
     * RSA public key in DER encoding
     */
    byte[] publicKeyRSA = Forms.hexStringToByteArray("308186028180E14CAAFFCEC6D014457D7CA3E943********BE8B795E10474954FE01BAAC63532520069465FA62EDB266AADEBB020103");
    /**
     * RSA private key encrypted by LMK
     */
    byte[] privateKeyRSA = Forms.hexStringToByteArray("000202703D0652C7027B7D94B45A896646A9DC7C********571BC7CE29B67920538D509C58B1D8F966AF7E5321CDB2386164844D2BCB");
    /**
     * RSA private key encrypted by protection key
     */
    byte[] privateKeyRSAKEK = Forms.hexStringToByteArray("6B2FB2BCC75604ABF5761FFA1027FF16324E3038********B01795D0ABE2D9695208542DC2FF8161AFD6F774E8D524B1DE6096530783");
    /**
     * RSA MAC
     */
    byte[] privateKeyRSAKEKMAC = Forms.hexStringToByteArray("701A****9760");

    /**
     * RSA private key encrypted by KEK
     */
    byte[] privateKeyKEK = Forms.hexStringToByteArray("7A833CC0FAFBA6EC063DF4827B8FD91FF4B9A69F********1E02C312ABFC68F454D11EFCF1E0609584D06B09A08599D7A0BF5D63BB9F");
    /**
     * RSA private key MAC encrypted by KEK
     */
    byte[] privateKeyRSAMAC = Forms.hexStringToByteArray("06E5****36DE");

    /**
     * SM2 private key encrypted by KEK
     */
    byte[] privateKeySM2KEK = Forms.hexStringToByteArray("D3C5F579038C8BF34698****EF6044210B43C894A77C");
    /**
     * SM2 private key MAC encrypted by KEK
     */
    byte[] privateKeySM2MAC = Forms.hexStringToByteArray("83E4****0D15");


    /**
     * SM2 public key in DER encoding
     */
    byte[] privateKeySM2DER = Forms.hexStringToByteArray("3059301306072A8648CE3D020106082A811CCF55********42A53790967A1368B7084F6EFED51FC848D1E3B5370A99BDCB64D17C2F");
    /**
     * SM2 private key encrypted by LMK
     */
    byte[] privateKeySM2 = Forms.hexStringToByteArray("66C9DDB0D6400EE05947****21908C4F5CA6457B435F");
    /**
     * SM2 private key protected by protection key
     */
    byte[] privateKeyKEKSM2 = Forms.hexStringToByteArray("D3C5F579038C8BF3A162****F99644210B43C894A77C");
    /**
     * SM2 MAC
     */
    byte[] privateKeyKEKSM2MAC = Forms.hexStringToByteArray("B982****8232");

    /**
     * Randomly generated SM2 key 1002
     */
    byte[] publicSM2 = Forms.hexStringToByteArray("3059301306072A8648CE3D020106082A811CCF55********6913D902C4C9B8A84A3F96ADDD7BEF537D61404D56E58A68C756AEFD40");
    byte[] privateSM2 = Forms.hexStringToByteArray("6F26783DCE6D45B84D3F****2FA68D1A3B721C09BB28");

    /**
     * Data digest calculated by MD5 algorithm
     */
    byte[] md5 = Forms.hexStringToByte("D41D8CD98F00B204E9800998ECF8427E");
    /**
     * Data digest calculated by SM3 algorithm
     */
    byte[] sm3 = Forms.hexStringToByte("E559D3DE421E81967DD68B28B55E0C26B03FCE10B8A8E5C4E6067497729D40D3");

    /**
     *
     */
    byte[] b = Forms.hexStringToByteArray("00000000000000000000000000000000");

    public APITest() throws TAException, ConfigurationException {
    }


    /**
     * Generate a symmetric key
     *
     * @throws TAException
     */
    @Test
    public void genSymmKey() throws TAException {
        ArrayList<byte[]> bytes = api.genSymmKey(3);
        System.out.println("LMK-encrypted symmetric key: "  + Forms.byteToHexString(bytes.get(0)));
        System.out.println("Verification value of symmetric key: "  + Forms.byteToHexString(bytes.get(1)));

    }

    ///////////////////////////////////////////////////////////////////////////
    // 1015 Test data
    ///////////////////////////////////////////////////////////////////////////

    byte[] sm4Key = Forms.hexStringToByte("EE828FCCFA****468B1FECCE81192");
    byte[] sm4CV = Forms.hexStringToByte("BCC2****2764");

    byte[] sm4ProKeyCipher = Forms.hexStringToByte("7C78B0D533****E9277504181C23F");
    byte[] sm4ProKeyCipherCV = Forms.hexStringToByte("8849****FB73");

    byte[] newSM4 = Forms.hexStringToByte("AE62E4E90F****AECE0AC9923B885");
    byte[] newSM4KeyMAC = Forms.hexStringToByte("F7EBEA9FD3****4E7EAAC9B7BE362");
    byte[] newSM4KeyTag = Forms.hexStringToByte("7C05A01A54****E0C8597DBED6D6D");

    byte[] sm4Key2 = Forms.hexStringToByte("40F7B1FA35****EB13491B119A4AB");
    byte[] sm4Key2CV = Forms.hexStringToByte("955C****9C51");

    /**
     * Generate a symmetric key and protect it with a protection key
     *
     * @throws TAException
     */
    @Test
    public void generateProtectionKey() throws TAException {
        /**
         * SM4
         * LMK-encrypted symmetric key: B36847D6E86EAB69E4EEB65558A2626C
         * Verification value of symmetric key: 713CA557C1FE2AAB
         */
        ArrayList<byte[]> bytes = api.proGenSymmKey(Forms.hexStringToByteArray("B36847D6E8****4EEB65558A2626C"),
                TACryptConst.KEY_ALG_SM4, Forms.hexStringToByteArray("713C****2AAB"), TACryptConst.KEY_ALG_SM4, b,
                TACryptConst.ENC_MODE_GCM,b, b);
        System.out.println("LMK-encrypted session key ciphertext: " + Forms.byteToHexString(bytes.get(0)));
        System.out.println("Verification value of session key: " + Forms.byteToHexString(bytes.get(1)));
        System.out.println("Session key ciphertext encrypted by protection key: " + Forms.byteToHexString(bytes.get(2)));
        System.out.println("MAC value of session key: " + Forms.byteToHexString(bytes.get(3)));
        System.out.println("Tags: " + Forms.byteToHexString(bytes.get(4)));

    }

    /**
     * Encrypt and decrypt data using a symmetric key
     *
     * @throws TAException
     */
    @Test
    public void generalDataEnc() throws TAException {
//        byte[] bytes = api.symmKeyDataEnc(sm4Key,TACryptConst.ENC_MODE_ECB,TACryptConst.KEY_TYPE_RULE, TACryptConst.KEY_ALG_SM4,
//                "0000000000000000".getBytes(), b);
//        System.out.println("SM4 encryption result: " + Forms.byteToHexString(bytes));
//        byte[] bytes1 = api.generalDataDec(sm4Key,TACryptConst.ENC_MODE_ECB, TACryptConst.KEY_TYPE_RULE, TACryptConst.KEY_ALG_SM4, bytes, b);
//        System.out.println("SM4 decryption result: " + new String(bytes1));
//        byte[] paddingData = Padding.PKCS5Padding(Forms.hexStringToByte("30820122300D06092A864886F70D010101050003********FE2D80A275BF5D096D2E07BA9ED5A75A10D425B03B84BB57990203010001"), 16);
//        byte[] bytes = api.symmKeyDataEnc(28,TACryptConst.ENC_MODE_CBC,TACryptConst.KEY_TYPE_RULE, TACryptConst.KEY_ALG_AES128,
//                paddingData, b);
//        System.out.println("AES encryption result: " + Forms.byteToHexString(bytes));
        byte[] bytes1 = api.generalDataDec(Forms.hexStringToByte("789F01F9CC****429D7EAB215ABA1"),TACryptConst.ENC_MODE_CBC, TACryptConst.KEY_TYPE_RULE, TACryptConst.KEY_ALG_AES128,
                Forms.hexStringToByte("AE6BA9133D0D4BB0090882E33F03D905D7797852********B1C0079352310E974EB1155A759374004095E2256B0ADC3BFFFF150AF071"), b);
        System.out.println("AES decryption result: " + Forms.byteToHexString(bytes1));
    }




    /**
     * Encrypt and decrypt data using a symmetric key protected by a protection key
     *
     * @throws TAException
     */
    @Test
    public void protectionKeyEncrypt() throws TAException {
        ArrayList<byte[]> bytes = api.proKeyEncData(sm4Key, TACryptConst.KEY_ALG_SM4, sm4CV,
                Forms.hexStringToByte("C0C64CD82E3B2DC8C8F4****F5BA4F0BCF7AC04E08E8"),
                b, Forms.hexStringToByte("75F2C068A5****F0BCF7AC04E08E8"), TACryptConst.ENC_MODE_CBC,
                b, new byte[0], new byte[0], TACryptConst.KEY_ALG_AES256, 1, 3,
                new byte[16], TACryptConst.KEY_ALG_SM4, TACryptConst.ENC_MODE_GCM,
                "mingwenshuju".getBytes(), new byte[12], new byte[2]);
        System.out.println("Ciphertext: " + Forms.byteToHexString(bytes.get(0)));
        System.out.println("Tag: " + Forms.byteToHexString(bytes.get(1)));

        byte[] bytes1 = api.proKeyDecData(sm4Key, TACryptConst.KEY_ALG_SM4, sm4CV, Forms.hexStringToByte("C0C64CD82E3B2DC8C8F4****F5BA4F0BCF7AC04E08E8"), b, Forms.hexStringToByte("75F2C068A5****F0BCF7AC04E08E8"), TACryptConst.ENC_MODE_CBC,
                b, new byte[0], new byte[0], TACryptConst.KEY_ALG_AES256, 1, 3, new byte[16], TACryptConst.KEY_ALG_SM4, TACryptConst.ENC_MODE_GCM,
                bytes.get(0), new byte[12], new byte[2], bytes.get(1));

        System.out.println("Plaintext after decryption: " + new String(bytes1));
    }

    byte[] srcRSACipher = Forms.hexStringToByte("83E265207D4566C7704DF9E6170181378CA028FB********508F919F4C0B3F2F7C0B79E661001B79FB0F0205A97CECFBE25DC4C711EA");

    byte[] srcRSACipherMAC = Forms.hexStringToByte("948D994479****72E54468349B3E5");

    byte[] srcRSACipherTag = Forms.hexStringToByte("9C8A7CB4C6****75F0681ED497EDF");

    byte[] srcRSApublicKey = Forms.hexStringToByteArray("308186028180E14CAAFFCEC6D014457D7CA3E943********BE8B795E10474954FE01BAAC63532520069465FA62EDB266AADEBB020103");
    /**
     * RSA private key encrypted by LMK
     */
    byte[] srcRSAprivateKey = Forms.hexStringToByteArray("000202703D0652C7027B7D94B45A896646A9DC7C********571BC7CE29B67920538D509C58B1D8F966AF7E5321CDB2386164844D2BCB");


    byte[] srcSM2Cipher = Forms.hexStringToByte("83E260209C09CEF21E1A****0B8D670537112DFB030F");

    byte[] srcSM2CipherMAC = Forms.hexStringToByte("7DF725131F****F029550F2F073E9");

    byte[] srcSM2CipherTag = Forms.hexStringToByte("A2181C5822****E37C072987D1B7E");

    byte[] srcSM2publicKey = Forms.hexStringToByteArray("3059301306072A8648CE3D020106082A811CCF55********F8D3F9E5A31C7DE80940637E036B2D6FD36A0F586D4CDC3A610A269E89");

    byte[] srcSM2privateKey = Forms.hexStringToByteArray("79E62264C314D1D3279D****F2BC777F8CBE7EC55699");


    /**
     * Encrypt and decrypt large data packets
     */
    @Test
    public void bigDataEnc() throws TAException {
        byte[] enc = api.bigDataEnc(Forms.hexStringToByteArray("6DF7292D86****81F7C94DDC967A0"), "AES/ECB/PKCS5Padding", "demaxiyazhili".getBytes(), new byte[0]);
        System.out.println(Forms.byteToHexString(enc));
        byte[] dec = api.bigDataDec(Forms.hexStringToByteArray("6DF7292D86****81F7C94DDC967A0"), "AES/ECB/PKCS5Padding", enc, new byte[0]);
        System.out.println(new String(dec));

    }

    /**
     * Calculate and verify MAC
     */
    @Test
    public void mac() throws TAException {
        byte[] bytes = api.calMac(1, 0, 2, sm4Key, 7, "1111111111111111".getBytes(),
                new byte[16]);
        System.out.println("MAC calculation result: " + Forms.byteToHexString(bytes));
        boolean b = api.verifyMAC(1, 0, 2, sm4Key, 7, "1111111111111111".getBytes(),
                new byte[16], bytes);
        System.out.println("MAC verification result: " + b);
    }

    /**
     * Calculate HMAC
     */
    @Test
    public void hmac() throws TAException {
        ArrayList<byte[]> hmac = api.hmac(20, 0, 2, sm4Key, new byte[0], "shuyaojisuandeshuju".getBytes());
        for (int i = 0; i < hmac.size(); i++) {
            System.out.println(Forms.byteToHexString(hmac.get(i)));
        }
    }

    /**
     * Generate an RSA key pair with the private key encrypted by LMK
     */
    @Test
    public void generateRSAKeyPair() throws TAException, IOException {
        ArrayList<byte[]> bytes = api.genRSAKey(2048, 65537);

        System.out.println("Public key in DER encoding: " + Forms.byteToHexString(bytes.get(0)));
        System.out.println("Private key encrypted by LMK: " + Forms.byteToHexString(bytes.get(1)));
    }


    /**
     * Generate an RSA key pair with the private key encrypted by a protection key
     */
    @Test
    public void protectionKeyRSA() throws TAException, IOException {
        ArrayList<byte[]> bytes = api.proGenRSAKey (sm4Key, TACryptConst.KEY_ALG_SM4, sm4CV, 2048, 3,
                b, TACryptConst.ENC_MODE_ECB, b, new byte[2]);
        System.out.println("Public key in DER encoding: " + Forms.byteToHexString(bytes.get(0)));
        System.out.println("Private key encrypted by LMK: " + Forms.byteToHexString(bytes.get(1)));
        System.out.println("Private key ciphertext encrypted by protection key: " + Forms.byteToHexString(bytes.get(2)));
        System.out.println("Length of asymmetric private key MAC: " + Forms.byteToHexString(bytes.get(3)));
    }

    /**
     * Sign and verify using an RSA private key
     */
    byte[] privateRSA = Forms.hexStringToByte("000204B07672172F114E8E847A5FB9EC3DD32CD1********AE837EB0B233D98470234F3EAD29C2DAB368CF5463151BCB266DEF496D8E");
    byte[] publicRSA = Forms.hexStringToByte("3082010902820100EED2CF3C2E3624D65718E0F1********556D927F5DA9529C22D5C701B8B1BB7836D351A815A69116110203010001");
    byte[] publicR77 = Forms.hexStringToByte("3082010A0282010100A636C484374F9F039EB431********FE2D80A275BF5D096D2E07BA9ED5A75A10D425B03B84BB57990203010001");
    @Test
    public void RSApriSign() throws TAException, IOException {
        byte[] bytes = api.RSAPriKeySign(privateRSA,TACryptConst.PADDING_MODE_NO, 4, 0,
                0, 0, Forms.hexStringToByte("9ECA5459BA0B5CA0****55E9DC2B6FFA85CE"));
        System.out.println("Signature result: " + Forms.byteToHexString(bytes));
        boolean b = api.RSAPubVerify(publicRSA,TACryptConst.PADDING_MODE_PKCS15, TACryptConst.DIGEST_ALG_SHA256, 0,
                0, 0, bytes, Forms.hexStringToByte("9ECA5459BA0B5CA0****55E9DC2B6FFA85CE"));
        System.out.println("Signature verification result: " + b);
//        ArrayList<byte[]> bytes1 = RasKeyUtils.loadDerRsaPublicKey(publicR77);
//        for (int i = 0; i < bytes1.size(); i++) {
//            System.out.println(Forms.byteToHexString(bytes1.get(i)));
//        }
//
//        byte[] bytes = api.RSAPriKeySign(77,TACryptConst.PADDING_MODE_PSS, TACryptConst.DIGEST_ALG_SHA256, TACryptConst.MGF,
//                TACryptConst.DIGEST_ALG_SHA256, 10, "1234567890".getBytes());
//        System.out.println("Signature result: " + Forms.byteToHexString(bytes));
//        boolean b = api.RSAPubVerify(publicR77,TACryptConst.PADDING_MODE_PSS, TACryptConst.DIGEST_ALG_SHA256, TACryptConst.MGF,
//                TACryptConst.DIGEST_ALG_SHA256, 10, bytes, "1234567890".getBytes());
//        System.out.println("Signature verification result: " + b);
    }

    /**
     * RSA encryption and decryption
     */
    @Test
    public void RSAencdata() throws TAException {
        byte[] bytes = api.RSAPubEncData(11, 1, TACryptConst.DIGEST_ALG_SHA256, new byte[0], Forms.hexStringToByte("{createTime=1606380202000, createUserId=144, ip=124.204.XX.XX, key=SYJHD202011266020179058, orderNumber=SYJHD202011266020179058, productId=161391, scene=SYJHD}"));
        System.out.println("Public key encryption result: " + Forms.byteToHexString(bytes));
        byte[] bytes1 = api.RSAPriDecData(11, 1, TACryptConst.DIGEST_ALG_SHA256,new byte[0], bytes);
        System.out.println("Private key decryption result: " + Forms.byteToHexString(bytes1));
    }

    /**
     * Decrypt using an RSA private key protected by a protection key
     */
    @Test
    public void priDecryptRSA() throws TAException {
        byte[] bytes = api.proRSAPriKeyDec (sm4Key, TACryptConst.KEY_ALG_SM4 , sm4CV, srcRSACipher, b, srcRSACipherMAC, TACryptConst.DIGEST_ALG_SHA256,
                b, new byte[2], srcRSACipherTag, 2, TACryptConst.MGF, TACryptConst.DIGEST_ALG_SHA256,new byte[0], Forms.hexStringToByteArray("BFA03DB9BD0A4DE4809B59B04BF663E8E541B0CF********5FD9E0A80116771AC436ED1EDE46CF272FD1DD4D3A5174D2D178D9A21F3D"));
        System.out.println("Plaintext after decryption: " + Forms.byteToHexString(bytes));
    }

    /**
     * Sign using an RSA private key protected by a protection key
     */
    @Test
    public void privateSignRSA() throws TAException, IOException {
        byte[] bytes = api.proRSAPriKeyDecSign(sm4Key, TACryptConst.KEY_ALG_SM4, sm4CV, srcRSACipher, b, srcRSACipherMAC, TACryptConst.DIGEST_ALG_SHA256,
                b, new byte[2], srcRSACipherTag, TACryptConst.DIGEST_ALG_SHA256, "1234567890".getBytes(), TACryptConst.PADDING_MODE_PSS, TACryptConst.MGF, TACryptConst.DIGEST_ALG_SHA256, 10);

        System.out.println("Signature result: " + Forms.byteToHexString(bytes));
        boolean b = api.RSAPubVerify(srcRSApublicKey,TACryptConst.PADDING_MODE_PSS, TACryptConst.DIGEST_ALG_SHA256, TACryptConst.MGF, TACryptConst.DIGEST_ALG_SHA256, 10, bytes, "1234567890".getBytes());
        System.out.println("Signature verification result: " + b);
    }

    /**
     * Convert RSA asymmetric key encryption from protection key 1 to protection key 2
     */
    @Test
    public void RSAConversionEncryption() throws TAException {
        ArrayList<byte[]> bytes = api.conversionEncryption(0, TACryptConst.KEY_ALG_SM4, sm4Key, sm4CV, TACryptConst.KEY_TYPE_RSA,
                -1, srcRSACipher, b, srcRSACipherMAC, TACryptConst.ENC_MODE_GCM, b, new byte[2], srcRSACipherTag,
                0,
                TACryptConst.KEY_ALG_SM4, sm4Key2, sm4Key2CV, b, TACryptConst.ENC_MODE_ECB, b, new byte[2]);
        for (int i = 0; i < bytes.size(); i++) {
            System.out.println("Item " + i + ": " + Forms.byteToHexString(bytes.get(i)));
        }
    }

    /**
     * Import a symmetric key protected by an RSA asymmetric key
     */
    @Test
    public void tets1() throws TAException {
        ArrayList<byte[]> bytes = api.RSAProImplSymm(srcRSAprivateKey, 2, TACryptConst.DIGEST_ALG_SHA256, new byte[10], 200,
                TACryptConst.KEY_ALG_SM4, Forms.hexStringToByteArray("5C59EBCD0A48E51038853E490C76AD83122964E3********AD4FCF0A1D20DC5A0AAB878DADC04903CCE5B3D06219FDB4497905FBEA9E"), "916-zjl".getBytes());
        System.out.println("LMK-encrypted symmetric key: " + Forms.byteToHexString(bytes.get(0)));
        System.out.println("Verification value of symmetric key: " + Forms.byteToHexString(bytes.get(1)));
    }

    /* ***************************************************************************************************** */

    /**
     * Generate an SM2/ECC key pair with the private key encrypted by a protection key
     */
    @Test
    public void generateProtectionKeySM2() throws TAException {
        ArrayList<byte[]> bytes = api.proGenSM2OrECCKey (sm4Key, TACryptConst.KEY_ALG_SM4, sm4CV, 0x0007,
                b, TACryptConst.ENC_MODE_GCM, b, new byte[16]);
        System.out.println("Public key in DER encoding: " + Forms.byteToHexString(bytes.get(0)));
        System.out.println("Private key encrypted by LMK: " + Forms.byteToHexString(bytes.get(1)));
        System.out.println("Private key ciphertext encrypted by protection key: " + Forms.byteToHexString(bytes.get(2)));
        System.out.println("Asymmetric private key MAC: " + Forms.byteToHexString(bytes.get(3)));
        System.out.println("Tags: " + Forms.byteToHexString(bytes.get(4)));

    }

    /**
     * Generate an SM2 key pair with the private key encrypted by LMK
     */
    @Test
    public void generateSM2Key() throws TAException {
        ArrayList<byte[]> bytes = api.genSM2Key();
        System.out.println("Public key in DER encoding: " + Forms.byteToHexString(bytes.get(0)));
        System.out.println("Private key encrypted by LMK: " + Forms.byteToHexString(bytes.get(1)));
    }

    /**
     * Generate an ECC key pair with the private key encrypted by LMK
     */
    @Test
    public void generateECCKey() throws TAException {
        ArrayList<byte[]> bytes = api.genECCKey(0x0007);
        System.out.println("Public key in DER encoding: " + Forms.byteToHexString(bytes.get(0)));
        System.out.println("Private key encrypted by LMK: " + Forms.byteToHexString(bytes.get(1)));
 
    }

    byte[] data = Forms.hexStringToByte("20D90A83A4654FB8****0371B374F76DEFA5");

    /**
     * ECC sign and verify
     */
    @Test
    public void ECCPrivateKeySign() throws TAException {

        byte[] bytes = api.priKeySign(0x0007, Forms.hexStringToByteArray("61971383CD4D760CF77C****4C1C935F18B4CCCFBF3A"), data);
        System.out.println("ECC signature result: " + Forms.byteToHexString(bytes));

        boolean b = api.pubKeyVerify(0x0007, Forms.hexStringToByteArray("3059301306072A8648CE3D020106082A811CCF55********1ACA51CB99CD452FA11B5B6BBB4AA31C2DBCC696FC57C8F9F8F01948FE"), data, bytes);
        System.out.println("ECC signature verification result: " + b);
    }

    /**
     * SM2 sign and verify
     */
    @Test
    public void TestSm2() throws TAException {
        byte[] bytes = api.priKeySign(0x0007, privateKeySM2, sm3);
        System.out.println("Signature result: " + Forms.byteToHexString(bytes));
        boolean b = api.pubKeyVerify(0x0007, privateKeySM2DER, sm3, bytes);
        System.out.println("Signature verification result: " +  b);
    }


    @Test
    public void SM2Sign() throws TAException {
        byte[] baInData = "2222222222222222".getBytes();
        //7. Calculate SM3 digest
        System.out.println("Data digest: SM3");
        String sAlg = "SM3";
        byte[] baUserId = new byte[0];
        byte[] baPubKey = Forms.hexStringToByteArray("3059301306072A8648CE3D020106082A811CCF55********9A1AD40BEEE37267F8F1F97E67BCE29A4E1CCAB0979A1E85F81010E042");
        byte[] baHashInitRes = api.HashInit(sAlg, baUserId, baPubKey);
        byte[] baHashUpdateRes = api.HashUpdate(baHashInitRes, baInData);
        byte[] baHashSm3 = api.HashFinalize(baHashUpdateRes);
        System.out.println(String.format("Data digest: %s", Forms.byteToHexString(baHashSm3)));


        //8. Asymmetric key sign and verify
        System.out.println("Asymmetric sign and verify: SM2");

        int iCurveId = 0x0007;
        System.out.println(String.format("Original data (hash value): %s", Forms.byteToHexString(baHashSm3)));

        byte[] baSignatureSm2 = api.priKeySign(iCurveId, 2, baHashSm3);
        System.out.println(String.format("Signature: %s", Forms.byteToHexString(baSignatureSm2)));
        boolean blVerifyResSm2 = api.pubKeyVerify(iCurveId, baPubKey, baHashSm3, baSignatureSm2);
        System.out.println(blVerifyResSm2);
    }


    byte[] sm2 = Forms.hexStringToByte("3059301306072A8648CE3D020106082A811CCF55********55A4C790CDE94A1B179CC12A39A856755F6677E87905BD903987425AF3");

    byte[] sm2PrivateKey = Forms.hexStringToByte("4F23C664B68C8A38B31F****66976CEA234A749F031D");

    /**
     * SM2 encryption and decryption
     */
    @Test
    public void TestSM2EncAndDec() throws TAException {
        byte[] bytes = api.SM2PubKeyEnc(888, Forms.hexStringToByte("1111111111****111111111111111"));
        System.out.println("Encryption result: " + Forms.byteToHexString(bytes));

        byte[] bytes1 = api.SM2PriKeyDec(888, bytes);
        System.out.println("Decryption result: " + Forms.byteToHexString(bytes1));
    }



    byte[] sm2Key = Forms.hexStringToByte("3059301306072A8648CE3D020106082A811CCF55********55A4C790CDE94A1B179CC12A39A856755F6677E87905BD903987425AF3");
    byte[] sm2Cipher = Forms.hexStringToByte("83E260209C09CC3F0103****FD8880E68AC28BFFF0F3");
    byte[] sm2CipherMAC = Forms.hexStringToByte("8184BE3669****B673814E59E7700");
    byte[] sm2CipherTag = Forms.hexStringToByte("8FD638CA4D****213F5777253D192");
    byte[] sm2PriKey = Forms.hexStringToByte("4F23C664B68C8A38B31F****66976CEA234A749F031D");


    /**
     * Decrypt using an ECC/SM2 private key protected by a protection key
     */
    @Test
    public void protectionPrivateKeyDecrypt() throws TAException {
        byte[] bytes = api.proPriKeyDec(sm4Key, TACryptConst.KEY_ALG_SM4, sm4CV, sm2Cipher, b, sm2CipherMAC, TACryptConst.ENC_MODE_GCM,
                b, new byte[2], sm2CipherTag, Forms.hexStringToByteArray("E9C17D82604F992BB3AB8FE0F766441DACC05EB7********32FACEC8316B880499E6E70260333E9F29CEBCF3F8E10C151F79445276F6"));
        System.out.println("Plaintext after decryption: " + Forms.byteToHexString(bytes));
    }

    /**
     * Sign using an ECC/SM2 private key protected by a protection key
     */
    @Test
    public void privateSignSM2() throws TAException {
        byte[] bytes = api.proPriKeySign(sm4Key,TACryptConst.KEY_ALG_SM4 , sm4CV, sm2Cipher, b, sm2CipherMAC, TACryptConst.ENC_MODE_GCM,
                b, new byte[2], sm2CipherTag, Forms.hexStringToByteArray("20D90A83A4654FB8****0371B374F76DEFA5"));
        System.out.println("ECC/SM2 private key signature result (private key protected by protection key): " + Forms.byteToHexString(bytes));

        boolean b = api.pubKeyVerify(7, sm2Key, Forms.hexStringToByteArray("20D90A83A4654FB8****0371B374F76DEFA5"), bytes);
        System.out.println("ECC/SM2 public key signature verification result (private key protected by protection key): " + b);
    }

    /**
     * Import a symmetric key protected by an SM2 asymmetric key
     */
    @Test
    public void SM2ImplKEK() throws TAException {
        ArrayList<byte[]> bytes = api.SM2ImplKEK(sm2PriKey, 300, TACryptConst.KEY_ALG_SM4, Forms.hexStringToByteArray("9A9161F87BCBD3E9BC8866B8706E8F75B682DA27********13440F2DAD9AE786E3D73349D78FA7915B3CB633EFD9A88E638D93297934"), "914-zjl".getBytes());
        System.out.println("LMK-encrypted symmetric key: " + Forms.byteToHexString(bytes.get(0)));
        System.out.println("Verification value of symmetric key: " + Forms.byteToHexString(bytes.get(1)));
    }

    /**
     * SM2/ECC asymmetric key conversion encryption
     */
    @Test
    public void conversionEncryption() throws TAException {
        ArrayList<byte[]> bytes = api.conversionEncryption(0, TACryptConst.KEY_ALG_SM4, sm4Key, sm4CV, 2,
                -1, sm2Cipher, b, sm2CipherMAC, TACryptConst.ENC_MODE_GCM, b, new byte[2], sm2CipherTag, 0,
                TACryptConst.KEY_ALG_SM4, sm4Key2, sm4Key2CV, b, TACryptConst.ENC_MODE_GCM, b, new byte[2]);
        for (int i = 0; i < bytes.size(); i++) {
            System.out.println("Item " + i + ": " + Forms.byteToHexString(bytes.get(i)));
        }
    }

    /**
     * Digest operation and pad digest data
     */
    @Test
    public void testGenHash() throws TAException {
        byte[] hash = genHash();
        System.out.println("Digest result: " + Forms.byteToHexString(hash));

        // Verify correct digest result
        String string = "704423DF78242B08E821F7F8FA05A5325AA1BD842BE4EB9827C765DFFF434C1A";

        byte[] bytes3 = genHash();
        System.out.println("Verification result: " + Arrays.equals(Forms.hexStringToByteArray(string),bytes3));

        String wrongHash = "669523DF78242B08E821F7F8FA05A5325AA1KD842BE4EB9827C765DFFF434C1A";

        System.out.println("Incorrect verification result: " + Arrays.equals(Forms.hexStringToByteArray(wrongHash),bytes3));
    }
    public byte[] genHash() throws TAException {
        byte[] bytes2 = api.HashInit("SM3", new byte[0], privateKeySM2DER);
        byte[] bytes = api.HashUpdate(bytes2, Forms.hexStringToByteArray("1234567890"));
        byte[] bytes1 = api.HashFinalize(bytes);
        return bytes1;
    }


    /**
     * Generate a random number
     */
    @Test
    public void genRandom() throws TAException {
        String s = api.genRandom(15);
        System.out.println(s);
    }

    /**
     * Get HSM status
     */
    @Test
    public void getHSMstatus() throws TAException {
        String hsMstatus = api.getHSMstatus();
        System.out.println(hsMstatus);
    }

    /**
     * LMK to KEK
     * @throws TAException
     */
    @Test
    public void test3() throws TAException {
        ArrayList<byte[]> bytes = api.LMKToKEK(TACryptConst.KEY_ALG_SM4, TACryptConst.ENC_MODE_GCM, b,
                new byte[2], 0, sm4Key,
                new byte[0], new byte[0], 5, 0,
                1, 0, TACryptConst.KEY_ALG_SM4,
                sm4Key2, new byte[16]);
        System.out.println("Key ciphertext encrypted by protection key: " + Forms.byteToHexString(bytes.get(0)));
        System.out.println("MAC output when generating MAC: " + Forms.byteToHexString(bytes.get(1)));
        System.out.println("Tags: " + Forms.byteToHexString(bytes.get(2)));
        System.out.println("Key verification value: " + Forms.byteToHexString(bytes.get(3)));
    }

    /**
     * Convert other encrypted keys to LMK-encrypted keys
     * @throws TAException
     */
    @Test
    public void otherEncKeyToLMLEncKey() throws TAException {
        ArrayList<byte[]> bytes = api.otherEncKeyToLMLEncKey(0, 7, 6,
                Forms.hexStringToByteArray("00000000000000000000000000000000"),
                Forms.hexStringToByteArray("00000000000000000000000000000000"),
                Forms.hexStringToByteArray("71802E75BD****996A9B9DA6616E9"),
                0,  Forms.hexStringToByteArray("B36847D6E8****4EEB65558A2626C"),
                new byte[0], new byte[0], 5, -1,-1, new byte[0], 0, 7,
                Forms.hexStringToByte("9940568000****9C7F45977D291AA"));
        System.out.println("============= Protection key is a symmetric key =============");
        for (int i = 0; i < bytes.size(); i++) {
            System.out.println(Forms.byteToHexString(bytes.get(i)));
        }

        ArrayList<byte[]> bytes2 = api.otherEncKeyToLMLEncKey(2, -1, -1,
                new byte[0], new byte[0], new byte[0],
                888,  new byte[0], new byte[0],
                new byte[0], 1,
                1, 1, new byte[0], 0, 7,
                Forms.hexStringToByte("7C78EAFE26890D48096AB8141B1D5890BF1921DD********5329ADED546F44C52C8F49EAC46647650D9B983224E9E005CFCAA88B019D"));

        System.out.println("============= Protection key is an ECC key =============");
        for (int i = 0; i < bytes2.size(); i++) {
            System.out.println(Forms.byteToHexString(bytes2.get(i)));
        }
        ArrayList<byte[]> bytes1 = api.otherEncKeyToLMLEncKey(1, -1, -1,
                new byte[0], new byte[0], new byte[0],
                11,  new byte[0], new byte[0], new byte[0], 3,
                1, 1, new byte[0], 0, 7,
                Forms.hexStringToByte("6149EE02F14EE6420BC2B462003CCCE2413CE491********E2CE400522E06DCBAB44213A85B668764EC33EE71D372F5A904252A539AA"));

        System.out.println("============= Protection key is an RSA key =============");
        for (int i = 0; i < bytes1.size(); i++) {
            System.out.println(Forms.byteToHexString(bytes1.get(i)));
        }

    }
    @Test
    public void enveopEncAndDec() throws TAException {
        byte[] bytes = api.enveopEnc(sm2Key, "1111111111111111".getBytes());
        System.out.println("Digital envelope encapsulation result: " + Forms.byteToHexString(bytes));
        byte[] bytes1 = api.enveopDec(sm2PriKey, bytes);
        System.out.println("Digital envelope decapsulation result: " + new String(bytes1));
    }

    /**
     * Symmetric key conversion encryption & asymmetric conversion encryption
     */
    @Test
    public void symmetryConversionEncryptionAES256() throws TAException {
        ArrayList<byte[]> bytes = api.conversionEncryption(0, TACryptConst.KEY_ALG_AES256,
                Forms.hexStringToByteArray("5BD90CDDBC8645B4****96B6E52CC003D04F"),
                Forms.hexStringToByteArray("F8B6****4FD3"),
                TACryptConst.KEY_TYPE_SYMMETRY,
                TACryptConst.KEY_ALG_AES256,
                Forms.hexStringToByteArray("CFE8E3D44F753D3F****88EF70B54E65E232"), b,
                Forms.hexStringToByteArray("8F2440B220****7D8D807A832A19F"), TACryptConst.ENC_MODE_GCM, b, new byte[22],
                Forms.hexStringToByteArray("B5294D5910****80774B61BA48FA4"),
                0,
                TACryptConst.KEY_ALG_SM4, sm4Key2, sm4Key2CV, b, TACryptConst.ENC_MODE_CBC, b, new byte[12]);
        for (int i = 0; i < bytes.size(); i++) {
            System.out.println("Item " + i + ": " + Forms.byteToHexString(bytes.get(i)));
        }
    }

    /**
     * Symmetric key conversion encryption & asymmetric conversion encryption
     */
    @Test
    public void symmetryConversionEncryption() throws TAException {
        ArrayList<byte[]> bytes = api.conversionEncryption(0, TACryptConst.KEY_ALG_SM4,
                Forms.hexStringToByteArray("CBDCCE3378****E0B3BAA46CF3557"),
                Forms.hexStringToByteArray("F668****C2AD"),
                0,TACryptConst.KEY_ALG_SM4,
                Forms.hexStringToByteArray("6BFC84C39C****6C7FA2A30C912A1"), b,
                Forms.hexStringToByteArray("AB75C62580****39327B45881F589"), TACryptConst.ENC_MODE_GCM,
                b, new byte[0], Forms.hexStringToByteArray("4A501743FA****4A0A8705192C1C8"),0,
                TACryptConst.KEY_ALG_SM4,
                Forms.hexStringToByteArray("CBDCCE3378****E0B3BAA46CF3557"),
                Forms.hexStringToByteArray("F668****C2AD"), b, TACryptConst.ENC_MODE_GCM, b, new byte[0]);
        for (int i = 0; i < bytes.size(); i++) {
            System.out.println("Item " + i + ": " + Forms.byteToHexString(bytes.get(i)));
        }
    }

    /**
     * Symmetric key conversion encryption & asymmetric conversion encryption
     */
    @Test
    public void symmetryConversionEncryption1() throws TAException {
        ArrayList<byte[]> bytes = api.conversionEncryption(0, TACryptConst.KEY_ALG_SM4, sm4Key, sm4CV,
                TACryptConst.KEY_TYPE_ECC_OR_SM2,
                TACryptConst.KEY_ALG_SM4,
                Forms.hexStringToByteArray("83E260209C09CC3FEFDE****27A17AEB2C8919E1E4CF"), b,
                Forms.hexStringToByteArray("E60EFC4882****F68D0EB622298FB"),
                TACryptConst.ENC_MODE_GCM, b, new byte[16],
                Forms.hexStringToByteArray("B200ED220D****C4438649057EB02"),
                0,
                TACryptConst.KEY_ALG_SM4, sm4Key, sm4CV, b, TACryptConst.ENC_MODE_GCM, b, new byte[16]);
        for (int i = 0; i < bytes.size(); i++) {
            System.out.println("Item " + i + ": " + Forms.byteToHexString(bytes.get(i)));
        }
    }


    /**
     * Import an asymmetric CMK protected by a symmetric CMK
     */
    @Test
    public void importCMKByCMK() throws TAException {
        ArrayList<byte[]> bytes = api.importCMKByCMK("zjlimpl".getBytes(), 7,
                6,  // DomainKey encryption algorithm identifier for CMK encryption
                new byte[16],     // IV data used for ECB mode decryption
                new byte[16],      // Authentication data used for GCM mode decryption
                Forms.hexStringToByteArray("566F7CE9E5****F02D7A7667E3F7C"), // MAC value used for GCM mode decryption
                Forms.hexStringToByteArray("DA23B170CE****772B3F2AE2CCA97"),// Key ciphertext
                Forms.hexStringToByteArray("7192C7C6F1****FE8A51BA9256C87"),  // GCM tags
                6, // Protection key encryption mode
                new byte[16],// Protection key IV
                new byte[16], // Authentication data AAD
                Forms.hexStringToByteArray("8DE9DFEE4B****1C08A38BDD8A92F"), // Tags
                5,// Protection key encryption padding mode
                12, // Session key type
                7,  // Algorithm identifier for session CMK asymmetric key
                Forms.hexStringToByteArray("420B9FE23A2B162F3C4574919E9EBD44040F7C53********0B18990EF5C6F3A93AB80B41458311EA9F9A1890752427E24F5062AD4A"),// Session private key ciphertext
                "32-1".getBytes(),// Session DomainKey tag
                6,// Session DomainKey encryption algorithm identifier for CMK encryption
                new byte[16],// Session encryption context (IV data used for non-ECB mode encryption)
                new byte[16]// Session authentication context data (authentication data used for GCM mode encryption)
        );
        System.out.println("Key ciphertext encrypted by protection key: " + Forms.byteToHexString(bytes.get(0)));
        System.out.println("MAC: " + Forms.byteToHexString(bytes.get(1)));
        System.out.println("Tags: " + Forms.byteToHexString(bytes.get(2)));
        System.out.println("Key verification value: " + Forms.byteToHexString(bytes.get(3)));
    }

    @Test
    public void testData() throws TAException {
        // Generate a symmetric key and protect it with a protection key
        ArrayList<byte[]> bytes = api.proGenSymmKey(603,
                -1, null, TACryptConst.KEY_ALG_SM4, b,
                TACryptConst.ENC_MODE_GCM,b, b);
        System.out.println("LMK-encrypted session key ciphertext: " + Forms.byteToHexString(bytes.get(0)));
        System.out.println("Verification value of session key: " + Forms.byteToHexString(bytes.get(1)));
        System.out.println("Session key ciphertext encrypted by protection key: " + Forms.byteToHexString(bytes.get(2)));
        System.out.println("MAC value of session key: " + Forms.byteToHexString(bytes.get(3)));
        System.out.println("Tags: " + Forms.byteToHexString(bytes.get(4)));
        System.out.println("-------------------------------------------------");
        // Encrypt data using a symmetric key protected by a protection key
        ArrayList<byte[]> bytes1 = api.proKeyEncData(603, -1, null,
                bytes.get(2),
                b, bytes.get(3), TACryptConst.ENC_MODE_GCM,
                b, b, bytes.get(4),
                TACryptConst.KEY_ALG_SM4, 0, 0,
                new byte[16], TACryptConst.KEY_ALG_SM4, TACryptConst.ENC_MODE_GCM,
                Forms.hexStringToByteArray("0000000000000000000000000000000000000000********353F49C7164DAE6C691FC25CD494D9A28D0F6C4B51F3BB9DC85ADDBE09"), new byte[16], new byte[16]);
        System.out.println("Ciphertext: " + Forms.byteToHexString(bytes1.get(0)));
        System.out.println("Tag: " + Forms.byteToHexString(bytes1.get(1)));
    }

    @Test
    public void agreementKey() throws TAException {
//        byte[] bytes = api.agreementKey(0x02CB, 4, 4, Forms.hexStringToByte("3076301006072A8648CE3D020106052B81040022********5645477442F9BF8BE9BF81EAD69CDA6C63FCF5244A383C57DDB62465E63B"));
//        System.out.println("secp384r1 agreement result: " + Forms.byteToHexString(bytes));
//        byte[] bytes1 = api.agreementKey(0x0007, 3, 6, Forms.hexStringToByte("3059301306072A8648CE3D020106082A811CCF55********DF9A3DF50D67073CF246FC3406337B50E987F2AC3943D2FF5C7ECAD197"));
//        System.out.println("0x000agreement result: " + Forms.byteToHexString(bytes1));
//        byte[] bytes2 = api.agreementKey(0x0007, 3, Forms.hexStringToByte("E59842CEEC68775E****F7DF23E08F7F6B8D"), Forms.hexStringToByte("3059301306072A8648CE3D020106082A811CCF55********B972EB19EA77A6AB74F345688B8458F1015885FCE435A4E3679DE0E34F"));
//        System.out.println("0x0007 external private key plaintext agreement result: " + Forms.byteToHexString(bytes2));
//        byte[] bytes3 = api.agreementKey(0x039B, 0, 5, Forms.hexStringToByte("304A301406072A8648CE3D020106092B24030302********868F7D34BABEEB5A20F7DF5543091DD740DD3780B5EBEF631615571ADC"));
//        System.out.println("0x039B agreement result: " + Forms.byteToHexString(bytes3));
        byte[] bytesA = api.agreementKey(0x019F, 3, 13, Forms.hexStringToByte("3059301306072A8648CE3D020106082A8648CE3D********7558F1DA9AC8CDF5E7FA72C9931FA90EE06B3CE07E13A7845A05BA7C73"));
        System.out.println(bytesA.length);
        System.out.println("0x0007 agreement result: " + Forms.byteToHexString(bytesA));
        byte[] bytesB = api.agreementKey(0x019F, 3, 15, Forms.hexStringToByte("3059301306072A8648CE3D020106082A8648CE3D********C7AB0964E53872FBF0511FF6E7661CF94B7D82C8BF78D211B1FA73F271"));
        System.out.println("0x0007 agreement result: " + Forms.byteToHexString(bytesB));

    }

    /**
     * Get symmetric key details by key index
     */
    @Test
    public void getKeyInfo() throws TAException {
        String[] keyInfo = api.getKeyInfo(66);
        System.out.println(keyInfo[0]);
    }
    /**
     * Get RSA public key by key index
     */
    @Test
    public void exportRSAPublicKey() throws TAException, IOException {
        ArrayList<byte[]> keyInfo = api.exportRSAPublicKey(77,0);
        System.out.println(Forms.byteToHexString(keyInfo.get(0)));
    }
    /**
     * Get ECC public key by key index
     */
    @Test
    public void ExportEncPublicKey() throws TAException {
        byte[] keyInfo = api.exportECCPublicKey(66,0);
        System.out.println(Forms.byteToHexString(keyInfo));
    }

    @Test
    public void generateAndSaveKey() throws Exception {
        ArrayList<byte[]> symmKey = api.generateSymmKey(7, 32);
        for (int i = 0; i < symmKey.size(); i++) {
            System.out.println(Forms.byteToHexString(symmKey.get(i)));
        }
        boolean b = api.generateRSAKey(2048, 65537, 13);
        System.out.println("Generate and save RSA key pair: " + (b ? "succeeded":"failed"));
        boolean b1 = api.generateECCKey(0x019F, 8);
        System.out.println("Generate and save ECC key pair: " + (b1 ? "succeeded":"failed"));

    }


}