All Products
Search
Document Center

Key Management Service:Use an HSM instance cluster

Last Updated:Dec 04, 2025

Cloud Hardware Security Module (CloudHSM) offers an HSM instance cluster feature that lets you group HSM instances from the same region but different zones. If these instances are used for the same business, your application can use a polling algorithm to select an HSM to perform cryptographic operations with the same key. This architecture provides business continuity, high availability for cryptographic computations, load balancing, and horizontal scaling for your applications. This topic describes how to use an HSM instance cluster.

Note

For more information about how to create an HSM cluster for a KMS hardware key management instance, see Configure an HSM cluster for a KMS instance of the hardware key management type.

Cluster synchronization methods

Cluster synchronization copies data, such as keys, configured SSL Certificates, and user information, from the master HSM to child HSMs. The synchronization method depends on when you purchased the HSMs:

  • For HSMs purchased on or after January 9, 2025: When you create a cluster, the synchronization method defaults to automatic synchronization. You do not need to manually synchronize cluster data after the data on the master HSM changes.

  • For HSMs purchased before January 9, 2025: When you create a cluster, the synchronization method defaults to manual synchronization. You must manually synchronize the cluster after the data on the master HSM changes. To upgrade the cluster to automatic synchronization, contact us.

    Warning

    The upgrade cannot be rolled back. The following risks may occur during the upgrade. We recommend that you perform the upgrade during off-peak hours.

    • For users of KMS hardware key management instances:

      • Control plane operations: Operations such as creating and deleting keys are not supported during the upgrade. These operations automatically resume after the upgrade is complete.

      • Data plane operations: Operations such as encryption and decryption are not affected during the upgrade.

    • For other users: You need to upgrade the HSM software development kit (SDK) version that your application depends on.

      • Control plane operations: Operations such as creating and deleting keys are not supported during the upgrade. These operations automatically resume after the upgrade is complete.

      • Data plane operations: In some business architectures, there is a risk of service interruption during the upgrade.

Prerequisites

  • A hardware security module (HSM) is purchased. For more information, see Purchase an HSM instance.

  • A Windows Elastic Compute Service (ECS) instance is purchased. The ECS instance and the HSM reside in the same VPC. For more information, see Get started with Windows instances.

    Note

    The ECS instance is used to install the HSM management tool, not to serve as a business server.

Step 1: Create and activate a cluster

A cluster consists of one master HSM and multiple child HSMs. All HSMs within a cluster must share the same VPC, but they can be deployed in the same or different subnets.

Note

If you configured cluster information when you purchased a GVSM instance, CloudHSM automatically creates a cluster. You can skip this step.

  1. Enable the master HSM instance.

    1. Go to the VSMs page of the Cloud Hardware Security Module console. In the top navigation bar, select a region.

    2. On the VSMs page, find the created HSM and click Enable in the Actions column.

    3. In the Configure HSM Instance dialog box, configure parameters and click OK. If the configuration is successful, the value of Status for the HSM changes to Enabled.

      Parameter

      Description

      VPC ID

      The VPC that you want to bind to the HSM.

      Important

      The VPC must be the same as the VPC of your ECS instance.

      VPC Subnet

      The subnet that you want to assign to the HSM in the VPC.

      Private IP Address

      The private IP address that you want to assign to the HSM.

      Important
      • The private IP address must belong to the subnet that is assigned to the HSM. Otherwise, the configuration fails.

      • The system reserves IP addresses whose last octet is 253, 254, or 255. Do not use the reserved IP addresses.

      Configure HSM Whitelist

      The range of the IP addresses that are allowed to access the HSM. IP addresses and CIDR blocks are supported. You can specify one IP address or one CIDR block in each row. You can specify up to 10 rows in total.

      • If you do not configure the whitelist, all IP addresses are allowed to access the HSM.

      • If you configure a whitelist, only the IP addresses in the whitelist are allowed to access the HSM.

      Important
      • If you create a cluster, add an HSM to the cluster, and configure a whitelist for the cluster, the whitelist of the cluster takes precedence over the whitelist of the HSM. For example, if you add 10.10.10.10 to the whitelist of an HSM and add 172.16.0.1 to the whitelist of the cluster that includes the HSM, you can access the HSM only from 172.16.0.1.

      • The whitelist configuration of 0.0.0.0/0 is not supported. If you enter 0.0.0.0/0, requests from all IP addresses are allowed.

        For security reasons, we recommend that you do not allow requests from all IP addresses. If you need to allow requests from all IP addresses, do not configure the whitelist.

  2. Create an HSM cluster.

    1. Find the master HSM instance and click Create Cluster in the Actions column.

    2. In the Create and Activate Cluster panel, create a cluster.

      Parameter

      Description

      Cluster Name

      The name of the cluster. The name must be unique and cannot exceed 24 characters in length.

      Configure Whitelist

      The range of the IP addresses that are allowed to access the cluster. If you do not configure a whitelist, all IP addresses are allowed to access the cluster. If you configure a whitelist, only the IP addresses in the whitelist are allowed to access the cluster.

      IP addresses and CIDR blocks are supported. You can specify one IP address or one CIDR block in each row. You can specify up to 10 rows in total.

      Important
      • The whitelist of a cluster has a higher priority than the whitelist of an HSM in the cluster. For example, if you add 10.10.10.10 to the whitelist of an HSM and add 172.16.0.1 to the whitelist of the cluster that includes the HSM, you can access the HSM only from 172.16.0.1.

      • The whitelist configuration of 0.0.0.0/0 is not supported. If you enter 0.0.0.0/0, requests from all IP addresses are allowed.

        For security reasons, we recommend that you do not allow requests from all IP addresses. If you need to allow requests from all IP addresses, do not configure the whitelist.

      Specify vSwitches

      The vSwitches that you need to select based on your business requirements.

      In an HSM cluster, you must configure at least two vSwitches to create and activate the cluster.

    3. Initialize the HSM instance, and then click Next.

      You can activate the cluster only when the status of the master HSM is Initialized. To initialize the master HSM, perform the following operations:

      Initialization method

      Operation

      Method 1: Initialize an HSM in the Cloud Hardware Security Module console with a few clicks

      Important

      This initialization method requires a GVSM and no UKEY.

      1. In the Create and Activate Cluster panel, click Initialize the master HSM with a few clicks.

      2. In the Tips dialog box, click OK.

      The initialization is expected to take one to five minutes. After the initialization, click the update icon next to Selected Master HSM:. The system displays Initialized for the HSM. Do not re-initialize an HSM in this state.

      Method 2: Use the HSM management tool to initialize an HSM

      Important

      The HSM management tool runs only on a Windows operating system.

      In the Create and Activate Cluster panel, click Download HSM Management Tool.

      Unzip the package to obtain the HSM software package. Complete the initialization process by following the "3.2.1 Initial Setup" chapter in the included user manual.

    4. Follow the prompts on the page to add child HSMs to the cluster, and then click Complete.

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

Scenario 1: HSM automatically generates certificates during purchase

Only GVSM instances support automatic certificate generation during purchase. In this scenario, CloudHSM automatically generates the certificates. You only need to configure the certificates on the client SDK because CloudHSM automatically deploys the certificates to the server-side HSM.

  1. Deploy the certificate 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, including 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 (Password for the PKCS12 format certificate with the .p12 suffix)
    2. Deploy client.p12 and rootca.pem to the client. In the client configuration file, you must also configure the file paths for client.p12 and rootca.pem, and the passphrase. For more information, refer to the documents in the package that you downloaded from the console.

  2. Deploy the certificate on the server.

    CloudHSM automatically deploys the certificate to the HSM. No action is required from you.

Important

The certificate is valid for 10 years by default. Before it expires, CloudHSM automatically generates a new certificate and rotates the server-side certificate. We recommend that you do not use the HSM management tool to create a UKEY administrator, because this will cause the certificate rotation to fail.

Scenario 2: HSM does not automatically generate certificates during purchase

GVSM supports automatic certificate generation by CloudHSM. However, if you did not enable this option during purchase, follow these steps to manually generate and deploy the certificates.

  1. Generate certificates.

    1. Download the certificate generation tool (dkms_cert_tool).

    2. Unzip the downloaded file and run the certificate generation tool to generate a CA certificate, a client certificate, and a server certificate.

      Note
      • There are no restrictions on the tool's operating environment. You can run it on a local computer, an ECS instance, or any other environment that meets the tool's running conditions.

      • Alibaba Cloud provides this tool as an auxiliary tool. If you have the technical ability to generate these certificate files, you do not need to use this tool.

      Windows

      • Method 1: In the Windows folder, double-click the hsm_certificate_generate.exe file to run the tool. The certificate files are generated in the certs folder.

        Note

        With this method, the password for the PKCS12 certificate file (.p12) and the CA private key file (.key) is the default value 12345678. To specify a password, use Method 2.

      • Method 2: Switch to the directory that contains the Windows folder and run the following command. The certificate files are generated in the certs folder.

        ./hsm_certificate_generate -dir ./certs -pswd 12345678

        -dir specifies the path in which to save the generated certificate files. -pswd specifies the password for the generated PKCS12 certificate file (.p12) and CA private key file (.key).

      Linux

      Switch to the directory that contains the Linux folder and run the following command. The certificate files are generated in the certs folder.

      ./hsm_certificate_generate -dir ./certs -pswd 12345678

      -dir specifies the path in which to save the generated certificate files. -pswd specifies the password for the generated PKCS12 certificate file (.p12) and CA private key file (.key).

      macOS

      Switch to the directory that contains the darwin folder and run the following command. The certificate files are generated in the certs folder.

      ./hsm_certificate_generate -dir ./certs -pswd 12345678

      -dir specifies the path in which to save the generated certificate files. -pswd specifies the password for the generated PKCS12 certificate file (.p12) and CA private key file (.key).

      After the command runs successfully, the following files are generated in the certs folder:

      certs/
      ├── client.p12 (Client certificate in PKCS12 format, including 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)
      └── server.pem (Server certificate in PEM format)
  2. Deploy the certificate on the client.

    Deploy client.p12 and rootca.pem to the client. In the client configuration file, you must also configure the file paths for client.p12 and rootca.pem, and the password that you specified when you generated the certificates. For more information, refer to the documents in the package that you downloaded from the console.

  3. Deploy the certificate on the server.

    1. Install the HSM instance management tool on the ECS instance.

      Important

      The HSM instance management tool runs on Windows only.

      1. Click the download icon image in the Specifications column of the master HSM instance to download the HSM instance management tool.image

      2. Unzip the downloaded HSM package, find PKIManager-X.X.X.X.exe, and upload it to the ECS instance. For more information, see Transfer files to a Windows instance using Remote Desktop Connection.

    2. Use the HSM instance management tool to configure the master HSM.

      1. Use the HSM instance management tool on the ECS instance to connect to the master GVSM.

        1. Double-click PKIManager-X.X.X.X.exe to open the HSM instance management tool. Choose System > TCP/IP Connection.

        2. In the TCP/IP Connection dialog box, enter the IP Address and Port of the master HSM. The port is 8020.

          You can find the IP address in the console.image

        3. Click Connect. In the PKIManager dialog box that appears, click OK, and then click Login.

          Note

          After you log on successfully, we recommend that you register an administrator account and use it to log on for higher security. For more information, see 2.1.3. Register Administrator and 2.1.2. Administrator Logon in the GVSM User Management Manual that is included with the HSM instance management tool.

      2. Use the HSM instance management tool to complete the following configurations.

        Configuration Item

        Procedure

        Configure the client certificate (client.pem)

        1. Choose Key Management > Client Management.

        2. In the Client Certificate Management dialog box, click Import Certificate.

        3. In the Import Certificate dialog box, set Certificate Type to International TLS Client RSA Certificate [pem]. Select the client certificate (client.pem) generated by the certificate generation tool, and click Import.

        Configure the server certificate (server.p12)

        1. Choose Key Management > Server Management.

        2. In the Server P12 Certificate Management dialog box, click Import Certificate.

        3. In the Import Certificate dialog box, set Certificate Type to International TLS Server RSA Certificate [p12]. Select the server certificate (server.p12) generated by the certificate generation tool, and enter the Certificate Password (the password you set when generating the certificate file; if you did not set one, the default is 12345678).

        4. Click Import.

        Configure GVSM device port properties for the master HSM

        1. Choose Device Management > Host Port Properties.

        2. In the Host Port Properties dialog box, configure the following parameters:

          • Socket KeepAlive Time: 60.

          • Message Header Length: 0.

          • Message Encoding Format: ASCII.

          • Host Service Communication Mode: Bidirectional Communication.

          • Host Service Communication Protocol: TLSv1.2.

        3. Click Reset.

        4. Click Restart Now, and then click OK.

Step 3: Synchronize cluster data

  • If the Cluster Type is Manual Cluster Synchronization: You must synchronize the cluster after you create and activate it for the first time, or after data on the master HSM changes. You do not need to synchronize the cluster when you scale it out.

  • If the Cluster Type is Automatic Cluster Synchronization: You do not need to synchronize the cluster. New keys, configured SSL certificates, and user information on the master HSM are automatically synchronized to the child HSMs.

Warning

Cluster synchronization takes about 5 minutes. Perform the synchronization during off-peak hours to avoid affecting your business.

  1. On the VSMs page, find the target master HSM instance and check the cluster synchronization method.

    If the cluster type is Manual Cluster Synchronization, perform the synchronization.

    image

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

Step 4: Create and use keys for encryption and decryption

The HSM software package contains the developer guide and SDK test program. You can call API operations to use HSMs based on the developer guide.

Note

You can go to the VSMs page of the Cloud Hardware Security Module console, find the required HSM, click image next to the Specifications column to download the package, and decompress the package to obtain the HSM software package.

In this example, GVSMs are used. Decompress the package, choose Alibaba Cloud GVSM software package > SDK > JAVA > Server HSM interface material > Test demo directory > Test case APITest.java, and then use the test case to test GVSMs.

Sample code

Note

Replace 192.168.XX.XX in the example with the private IP address assigned to the HSM.

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 keys encrypted by local master keys (LMKs)
     */
    byte[] symmetricKey = Forms.hexStringToByteArray("669C1CEDDAFA267CC5D727EA727558B5");
    byte[] verifyValue = Forms.hexStringToByteArray("BD8596C22E5A4D88");

    byte[] symmetricKey1 = Forms.hexStringToByteArray("93EF12C95813586FEC3EFDBC7B37642D");
    byte[] verifyValue1 = Forms.hexStringToByteArray("78306FD68851B8E6");
    /**
     * Ciphertext of session keys encrypted by LMKs
     */
    byte[] symmetricKeyKEK = Forms.hexStringToByteArray("2E80A42018F186BCCBCF639F644629E8");
    /**
     * Checksum values of session keys
     */
    byte[] verifyValueMAC = Forms.hexStringToByteArray("734D092CD8C23E38");
    /**
     * Ciphertext protected by protection keys
     */
    byte[] protectionKey = Forms.hexStringToByteArray("2EACE685C5EB2638D1208742F3BE60CD44210B43C894A77C");
    /**
     * Message Authentication Codes (MACs) of ciphertext protected by protection keys
     */
    byte[] protectionMAC = Forms.hexStringToByteArray("0CB8702D41CBE487");

    /**
     * RSA DER-encoded public keys
     */
    byte[] publicKeyRSA = Forms.hexStringToByteArray("308186028180E14CAAFFCEC6D014457D7CA3E943DBABA1299BDBC17690C8E70F7BFA10EA02450805DA4C6CDC38BFBF1349C95B81A88177BA31C08E366EF965CA41EB36A2DACE611B80A752615A094B8291AAB6F8BB3A5894E72842371F34FA04C10DF42C2FEA95C51B9D49BE8B795E10474954FE01BAAC63532520069465FA62EDB266AADEBB020103");
    /**
     * Private keys encrypted by RSA LMKs
    byte[] privateKeyRSA = Forms.hexStringToByteArray("000202703D0652C7027B7D94B45A896646A9DC7CA89825FB12121B3CC00E37BE933055D5C00E37BE933055D54718ADDAA677519BD9C054CA249B43888FE000B8AAC33BA87A2C326985704335EA54D7F171CABCAD5531B3ADF33255A24075EFFF62691D4375E6280A9442CA36AA46AC59FAB16D9A9A7A283440BB14BAB1E78DBE887AE93A2C94C547779190D3FA801379BA948537281EFEFE567FD963E5D6E5D442D908A68BB6E26F3776EA30B1136A3804844035E26308E9B44BE154E1D09382E5A72BD711A6936373A8C32B62AF88134690C30D8B5505004F3BA01D11D0D791C8FF53D0E0786ED192CF1105FCF82160921EEF23E7BD72F13587B316BD9A771CEABBD0186B45E09C86E718AD4E5444EFFE747FE0C39E85D6190F3347656E72F486C321D5EA0D42127149C99F4F799A31F91E5826B74FF720A6E3CC2BCBBF645DD3D4A6A7D0BC953B4CFEE4E0D2BABFD606292F9F2395464484C306FBD60E4DD293E5F56C60BF1482A05775F0EEBAFBF9B70841DDDCFC974DD4D87E54D6A6A7A1A585EF0F42B0763D5DD7B5ECA83AFE610C26C9EF559B7883AC4716240BDFDC91C6EA19A0C01BB9C053F2A9C7EBCAE7D0AA8FB0DB88EFCF9C50A134E04649DAFF21D724E5C3CC043DE950C2CF246392DC4CA592D28C5A959BEB80B304E3BD949AD33178C06209FE6EB7130A381DFFD80F916AE0E0DD8FFDD9C8C9895BC483993D6011754FAD3C9F83A59C31F47810F8B2B22E5F25EF13671DFF34ECB65DE71D5B13DC5880595BC60B18D4711AE4613C739E2A48B516F6233E9AA9834075CE58975907F06FBA3B85C97E2E90B60BFEF0F23527E770798B571BC7CE29B67920538D509C58B1D8F966AF7E5321CDB2386164844D2BCB");
    /**
     * Private keys encrypted by RSA protection keys
     */
    byte[] privateKeyRSAKEK = Forms.hexStringToByteArray("6B2FB2BCC75604ABF5761FFA1027FF16324E3038B580C9F63AD3B57BD89059D5799974B4E5E9453763D94E682C629C4617C4E5393E9DDBFB0CFA2A4EA0E832F5C6A30F3EE63C327F6E044F3CB630D0C7DD96D93581835AA529797EB11CF3535650E431181717FDD1D7BBD9FB675FB027134BBF7F10F65245D9A82251A9171DAA439C175895904A2BB74F31BD94FF550023F6245C01DF83B2FCEDDF241307DDC831162AD2203BA3EBC4FD99EAE93C3208F16B0AAF85146ACE5FF06B11D7C81215708AA5C2651D380573F0EDA0984A73F5CE38E21541D50AACF5C5BCD42B6C94D064065ECAED4684E7A40C15904A73A801F2697AF6F3E32C3D7E156A1D1085CA32C7A002FA4AEAD439271E6E5904FC9AC3E65EEBAC51399F60DF3C61AF82BDA04D5E28B587382F8EB751096BC970B7A7DF26D997324F2D002D01A4C8F77C37BB65DBD1DED3B4545323DAE9489A08351507224574A2206FA7EAF8EF0A120D23D6B34E84645E95C3B58187BC91B8F6C04EF15075D6AF38B7E7DD77F6D2B8E66F11960C401BCE56BB4C157DAA26234678A37ACCFC7729CB5018449F7B6A23C0B16CA0B6A5FBE9FC7C8F9A3801A4159822DDDE8D9D7B7233CC3F77E7391DE720A2BFC69F6B938B565A28EBC6B4B665C553A9E1F32A17CC66CB8A2D7FE3EF6CB5112815D562F18EB34987B57DCFF064C7C24E97C3DCF3FD9BD50B351A2DD7CF03DA1F2DDA7A1BD2013C8339AFC4D22C135C49859C9C4CA4C9F730D2EE09A779D244C13FB5C3835F2FF04EE12537B01795D0ABE2D9695208542DC2FF8161AFD6F774E8D524B1DE6096530783");
    /**
     * RSA MACs
     */
    byte[] privateKeyRSAKEKMAC = Forms.hexStringToByteArray("701A4D3572D09760");

    /**
     * RSA private keys encrypted by key encryption keys (KEKs)
     */
    byte[] privateKeyKEK = Forms.hexStringToByteArray("7A833CC0FAFBA6EC063DF4827B8FD91FF4B9A69FB0C44FD972173C09E9E56F6918730269561A497403F9478D7BB64FE527F748AF86E3CE7C762A92A07D9C8BBCE0731F9F07C5889AE8B0FF7A31FCCCD76CD20A1AFB95B4D12BEA5DB84059B9CB1FB8F778989FD11CB7F8D84D812190F2EE0F479A4020FEB32C634528FBF660B3AD5AB0BA497B932902294C28B02807DC1AC28E8213BA39582AA677050F9E9256879935484B49D1CD115B39C0A41AE2B18263F78EA4CB781C931EA3C638097D1A7D4245C30ADA1B7C7793FD798EFAB86C3A91F573D4D2ECFA188588A31983320052901CC5AECAEDC5296506442546614B3DFDECA958B5E3A659EC8B52C5818E22F8E50C216264B560073F47E07B07E38CEF2DF4F6E4A458665FD31E6AA1C7B2FB5C4A15405C09E5F2B814FB260C1FFC560A2B6F3370C9DD96BA0A15BA72AB3622FE172F847D60383307C936246B977665CAB5E68EFA6E4EE1F9008FAE7A90D4A2A10AB70969714041707D4AD05F96027FA62FC916C81BA3C8601F7FF3115F17A117AD1B9A3D8438A731707A2D3B65BDA3846D293939CF94EBCC681E8115400454CF2CEA3769A614A9098CA62356B131EA22F4D634B56B365D7A430A3703967B50C6FCA93D11BD5ACC60048B5E00EAF353723D6DE878F8E5E4EA03BD43DF7229E6146DE307F9CC51B7F359F07042500AB5C24EE6F80EA8E1E50961BEC347949E5DD1918027A17196BABEE5790332B76D4AFFCD19143D7462177CDF72DE09BE64320C330090C1C6F1B059E81E02C312ABFC68F454D11EFCF1E0609584D06B09A08599D7A0BF5D63BB9F");
    /**
     * MACs of RSA private keys encrypted by KEKs
     */
    byte[] privateKeyRSAMAC = Forms.hexStringToByteArray("06E5A11D968C36DE");

    /**
     * SM2 private keys encrypted by KEKs
     */
    byte[] privateKeySM2KEK = Forms.hexStringToByteArray("D3C5F579038C8BF3469879DD7F79C2E1B7FF47D7F2D5EFF5B01EFCE51C081D8067E06C0290F8EF6044210B43C894A77C");
    /**
     * MACs of SM2 private keys encrypted by KEKs
     */
    byte[] privateKeySM2MAC = Forms.hexStringToByteArray("83E413861F0C0D15");


    /**
     * SM2 DER-encoded public keys
     */
    byte[] privateKeySM2DER = Forms.hexStringToByteArray("3059301306072A8648CE3D020106082A811CCF5501822D03420004B33D8A2F9E1E1FCA2E8CECCFFB166F52CC2ED0589C25464D0EF85DC87E0537DC16C0D542A53790967A1368B7084F6EFED51FC848D1E3B5370A99BDCB64D17C2F");
    /**
     * Private keys encrypted by SM2 LMKs
     */
    byte[] privateKeySM2 = Forms.hexStringToByteArray("66C9DDB0D6400EE059474F5C7339A296D5AA88F02AF031174F212EB6538C21908C4F5CA6457B435F");
    /**
     * Private keys protected by SM2 protection keys
     */
    byte[] privateKeyKEKSM2 = Forms.hexStringToByteArray("D3C5F579038C8BF3A1624E7DC142A863240A42642337355921C70A7547001B21A0C59D4E0800F99644210B43C894A77C");
    /**
     * SM2 MACs
     */
    byte[] privateKeyKEKSM2MAC = Forms.hexStringToByteArray("B9827812C2E18232");

    /**
     * Randomly generated SM2 key 1002
     */
    byte[] publicSM2 = Forms.hexStringToByteArray("3059301306072A8648CE3D020106082A811CCF5501822D03420004D93204DF6335BEF43A90F8566CFB6FB5F7B10BE8082E9C0D9A5AA731F994AF07990FCB6913D902C4C9B8A84A3F96ADDD7BEF537D61404D56E58A68C756AEFD40");
    byte[] privateSM2 = Forms.hexStringToByteArray("6F26783DCE6D45B84D3FF39FFBDB365FE93B94EF15C39E00A09DE07212472FA68D1A3B721C09BB28");

    /**
     * MD5-generated data digest
     */
    byte[] md5 = Forms.hexStringToByte("D41D8CD98F00B204E9800998ECF8427E");
    /**
     * SM3-generated data digest
     */
    byte[] sm3 = Forms.hexStringToByte("E559D3DE421E81967DD68B28B55E0C26B03FCE10B8A8E5C4E6067497729D40D3");

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

    public APITest() throws TAException, ConfigurationException {
    }


    /**
     * Symmetric key generation
     *
     * @throws TAException
     */
    @Test
    public void genSymmKey() throws TAException {
        ArrayList<byte[]> bytes = api.genSymmKey(3);
        System.out.println("Symmetric keys encrypted by LMKs:"  + Forms.byteToHexString(bytes.get(0)));
        System.out.println("Checksum values of symmetric keys:"  + Forms.byteToHexString(bytes.get(1)));

    }

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

    byte[] sm4Key = Forms.hexStringToByte("EE828FCCFAC494756468B1FECCE81192");
    byte[] sm4CV = Forms.hexStringToByte("BCC22E39C9B72764");

    byte[] sm4ProKeyCipher = Forms.hexStringToByte("7C78B0D533A10812FE9277504181C23F");
    byte[] sm4ProKeyCipherCV = Forms.hexStringToByte("8849C862448CFB73");

    byte[] newSM4 = Forms.hexStringToByte("AE62E4E90FA741090AECE0AC9923B885");
    byte[] newSM4KeyMAC = Forms.hexStringToByte("F7EBEA9FD38EBBD324E7EAAC9B7BE362");
    byte[] newSM4KeyTag = Forms.hexStringToByte("7C05A01A54B63CB90E0C8597DBED6D6D");

    byte[] sm4Key2 = Forms.hexStringToByte("40F7B1FA358855610EB13491B119A4AB");
    byte[] sm4Key2CV = Forms.hexStringToByte("955C2B5828299C51");

    /**
     * Symmetric key generated and protected by protection keys 
     *
     * @throws TAException
     */
    @Test
    public void generateProtectionKey() throws TAException {
        /**
         * SM4
         * Symmetric keys encrypted by LMKs: B36847D6E86EAB69E4EEB65558A2626C
         * Checksum values of symmetric keys: 713CA557C1FE2AAB
         */
        ArrayList<byte[]> bytes = api.proGenSymmKey(Forms.hexStringToByteArray("B36847D6E86EAB69E4EEB65558A2626C"),
                TACryptConst.KEY_ALG_SM4, Forms.hexStringToByteArray("713CA557C1FE2AAB"), TACryptConst.KEY_ALG_SM4, b,
                TACryptConst.ENC_MODE_GCM,b, b);
        System.out.println("Ciphertext of session keys encrypted by LMKs:" + Forms.byteToHexString(bytes.get(0)));
        System.out.println("Checksum values of session keys:" + Forms.byteToHexString(bytes.get(1)));
        System.out.println("Ciphertext of session keys encrypted by protection keys:" + Forms.byteToHexString(bytes.get(2)));
        System.out.println("MACs of session keys:" + Forms.byteToHexString(bytes.get(3)));
        System.out.println("Tags:" + Forms.byteToHexString(bytes.get(4)));

    }

    /**
     * Data encryption and decryption by symmetric keys
     *
     * @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 results:" + 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 results:" + new String(bytes1));
//        byte[] paddingData = Padding.PKCS5Padding(Forms.hexStringToByte("30820122300D06092A864886F70D01010105000382010F003082010A0282010100A636C484374F9F039EB4318952B6BA5ABBE096F2B37B12DBC71A09F3B7BEEB83EB4A4BBBBDBBCC9332168E336981C919EF8BB734B3671DFEDCB79459401F95DDAA4EACECB36599451F9F77F5B01BF6B6AA1F94DE8BE5ED8B7BD52CA94929F7B0D3E8F5FDAFA322538AE32F89D7E3C1E4203120EDE6F213A3848F8ECF9E6836BE369A4658B6EB14D2FD3681488A3207CE0A5A9088011B2DA893C7F2C674843BB5254C30CB67D9C8182FEF284BB5CD8A239D6411EA199AD8B93EBE3442716FDAB44FB3932248C076C8794725CEEB5B76674B2B6DC605DC0F9835C6CCBBE4807A4F925065E02C65CAFE2D80A275BF5D096D2E07BA9ED5A75A10D425B03B84BB57990203010001"), 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 results:" + Forms.byteToHexString(bytes));
        byte[] bytes1 = api.generalDataDec(Forms.hexStringToByte("789F01F9CC1BE0FF7429D7EAB215ABA1"),TACryptConst.ENC_MODE_CBC, TACryptConst.KEY_TYPE_RULE, TACryptConst.KEY_ALG_AES128,
                Forms.hexStringToByte("AE6BA9133D0D4BB0090882E33F03D905D779785299F12C241936CB6AE45B9D2CB5C6B4E6C96D74BEB7D4A53684A18E0764DBE6A2383FB43C8CCCBDC1E84DF4D593141B302CB0F96074B32E06924F54AC342584EF47D41EF0022362A89F07B96071D3D0910C7A581FE0F7BC564F28107C9EBDD060AB11DC0700E3577606BCD666C93207E2AFDCF84E6FA7FE84A60BB39B0B0489EDDBEFB1C95768EA9010C993B2D51B8A752396FE585422F766CBAC3CCC7301C92483D726DEF325A685D861ABFFABF2C91022DB984D8E606CAA8AEE01DA969C72F81F0D13E96DCDE0DEAAF4309517618FB4C5BA6281F262C511E3A90F9ED952FD6D0ACEB6CCD4F5FA96DD6C15A2A2B848C1A224AAE1081102FC7313EB233112B1C0079352310E974EB1155A759374004095E2256B0ADC3BFFFF150AF071"), b);
        System.out.println("AES decryption results:" + Forms.byteToHexString(bytes1));
    }




    /**
     * Data encryption and decryption by symmetric keys (protected by protection keys)
     *
     * @throws TAException
     */
    @Test
    public void protectionKeyEncrypt() throws TAException {
        ArrayList<byte[]> bytes = api.proKeyEncData(sm4Key, TACryptConst.KEY_ALG_SM4, sm4CV,
                Forms.hexStringToByte("C0C64CD82E3B2DC8C8F4D5A33F0EF6B4F5942AF6B880EE6A6AAB159C90C3F46175F2C068A54CF5BA4F0BCF7AC04E08E8"),
                b, Forms.hexStringToByte("75F2C068A54CF5BA4F0BCF7AC04E08E8"), 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("Tags:" + Forms.byteToHexString(bytes.get(1)));

        byte[] bytes1 = api.proKeyDecData(sm4Key, TACryptConst.KEY_ALG_SM4, sm4CV, Forms.hexStringToByte("C0C64CD82E3B2DC8C8F4D5A33F0EF6B4F5942AF6B880EE6A6AAB159C90C3F46175F2C068A54CF5BA4F0BCF7AC04E08E8"), b, Forms.hexStringToByte("75F2C068A54CF5BA4F0BCF7AC04E08E8"), 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("83E265207D4566C7704DF9E6170181378CA028FB1EAA0BCB771DFD188CF5BEA899ECEF9213CA98D6D698CCE6072237768F514B04D68DA6B01400F69F93601976DCDFAE8F2EDDAA4F01BA8CE5E76A77AEB01BAB9D6E59A32B4E30B2B8D21D13B5C3510A1622190621BD3B0B5838A2CCBE423F4D3A7613CB69BBC9857E4BF5D08AAD77DDB96ECDD88989B885D44B909F502DC53A2FB4200FA714ECCFF100E7E986D76B68BD0BEFF5CA33CA698DA42F8B74FFBC09FB8F30483E416D0D2EAC6AF2B2A309F6762B5D292DA619C92428D1AB11A6931C81A859C79D8C01B441B1902ABE001BFF501DEE0E1E241E4567ECC74F9D4665AEA77C4F93AC312347A5087B686DC8361415A85197DB69CEEFD6D00CE94C34C290B8F79F10CC27A79D7C4D8F43736223576649E93457C75BA8C637927EC780A56B45163142DE1483777B4C8222C92B3C82AB372B3B0223D4EE246938EB85A7EC536DC77A291E152CF94E02465137DF2F25140669071913F868E58F379472235564F125B6C71C2705FE895ABEEFE33C656ACA7D489AD5C432B80AB9D8F732C03519F2E99F0DEAC4A7312FC351C059877BA09FB6455EFCB0D0DFE9F597416A5E1D88A7326C64D5539D91519935FADD5BE76EBB4D60FC57103CB8960890B4B1EC822C8D9781CF67B6DD1BE15E87406A0B0B5C06A69F6B07991C95B13CC0C4DBEA91589425E7C8D4E7CFE2CBBEC34D7705E8B52939D2E154B3435B7B4B8E41CD4DCEDF3892EF0F3352C8467CA46DB08A7DC93969E18B405F44508F919F4C0B3F2F7C0B79E661001B79FB0F0205A97CECFBE25DC4C711EA");

    byte[] srcRSACipherMAC = Forms.hexStringToByte("948D9944793CAFAB372E54468349B3E5");

    byte[] srcRSACipherTag = Forms.hexStringToByte("9C8A7CB4C6D1AE08775F0681ED497EDF");

    byte[] srcRSApublicKey = Forms.hexStringToByteArray("308186028180E14CAAFFCEC6D014457D7CA3E943DBABA1299BDBC17690C8E70F7BFA10EA02450805DA4C6CDC38BFBF1349C95B81A88177BA31C08E366EF965CA41EB36A2DACE611B80A752615A094B8291AAB6F8BB3A5894E72842371F34FA04C10DF42C2FEA95C51B9D49BE8B795E10474954FE01BAAC63532520069465FA62EDB266AADEBB020103");
    /**
     * Private keys encrypted by RSA LMKs
     */
    byte[] srcRSAprivateKey = Forms.hexStringToByteArray("000202703D0652C7027B7D94B45A896646A9DC7CA89825FB12121B3CC00E37BE933055D5C00E37BE933055D54718ADDAA677519BD9C054CA249B43888FE000B8AAC33BA87A2C326985704335EA54D7F171CABCAD5531B3ADF33255A24075EFFF62691D4375E6280A9442CA36AA46AC59FAB16D9A9A7A283440BB14BAB1E78DBE887AE93A2C94C547779190D3FA801379BA948537281EFEFE567FD963E5D6E5D442D908A68BB6E26F3776EA30B1136A3804844035E26308E9B44BE154E1D09382E5A72BD711A6936373A8C32B62AF88134690C30D8B5505004F3BA01D11D0D791C8FF53D0E0786ED192CF1105FCF82160921EEF23E7BD72F13587B316BD9A771CEABBD0186B45E09C86E718AD4E5444EFFE747FE0C39E85D6190F3347656E72F486C321D5EA0D42127149C99F4F799A31F91E5826B74FF720A6E3CC2BCBBF645DD3D4A6A7D0BC953B4CFEE4E0D2BABFD606292F9F2395464484C306FBD60E4DD293E5F56C60BF1482A05775F0EEBAFBF9B70841DDDCFC974DD4D87E54D6A6A7A1A585EF0F42B0763D5DD7B5ECA83AFE610C26C9EF559B7883AC4716240BDFDC91C6EA19A0C01BB9C053F2A9C7EBCAE7D0AA8FB0DB88EFCF9C50A134E04649DAFF21D724E5C3CC043DE950C2CF246392DC4CA592D28C5A959BEB80B304E3BD949AD33178C06209FE6EB7130A381DFFD80F916AE0E0DD8FFDD9C8C9895BC483993D6011754FAD3C9F83A59C31F47810F8B2B22E5F25EF13671DFF34ECB65DE71D5B13DC5880595BC60B18D4711AE4613C739E2A48B516F6233E9AA9834075CE58975907F06FBA3B85C97E2E90B60BFEF0F23527E770798B571BC7CE29B67920538D509C58B1D8F966AF7E5321CDB2386164844D2BCB");


    byte[] srcSM2Cipher = Forms.hexStringToByte("83E260209C09CEF21E1AD68B09EC5FA762164497DB6D7C6EEA5D58D14F7C0B8D670537112DFB030F");

    byte[] srcSM2CipherMAC = Forms.hexStringToByte("7DF725131F3E67547F029550F2F073E9");

    byte[] srcSM2CipherTag = Forms.hexStringToByte("A2181C58228D7A32AE37C072987D1B7E");

    byte[] srcSM2publicKey = Forms.hexStringToByteArray("3059301306072A8648CE3D020106082A811CCF5501822D03420004549EAF3A09B4F486171FF320B81C4037286FC68026AA6E0101D3108C0573CFB0FF431DF8D3F9E5A31C7DE80940637E036B2D6FD36A0F586D4CDC3A610A269E89");

    byte[] srcSM2privateKey = Forms.hexStringToByteArray("79E62264C314D1D3279D9B7752CD137AD4095864801607EB52B6AB9C6ADBF2BC777F8CBE7EC55699");


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

    }

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

    /**
     * Hash-based Message Authentication Code (HMAC) computing
     */
    @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)));
        }
    }

    /**
     * RSA key pairs generated and private keys encrypted by LMKs
     */
    @Test
    public void generateRSAKeyPair() throws TAException, IOException {
        ArrayList<byte[]> bytes = api.genRSAKey(2048, 65537);

        System.out.println("DER-encoded public keys:" + Forms.byteToHexString(bytes.get(0)));
        System.out.println("Private keys encrypted by LMKs:" + Forms.byteToHexString(bytes.get(1)));
    }


    /**
     * RSA key pairs generated and encrypted by protection keys
     */
    @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("DER-encoded public keys:" + Forms.byteToHexString(bytes.get(0)));
        System.out.println("Private keys encrypted by LMKs:" + Forms.byteToHexString(bytes.get(1)));
        System.out.println("Ciphertext of private keys encrypted by protection keys:" + Forms.byteToHexString(bytes.get(2)));
        System.out.println("MAC length of asymmetric private keys:" + Forms.byteToHexString(bytes.get(3)));
    }

    /**
     * Signature generation and verification of RSA private keys
     */
    byte[] privateRSA = Forms.hexStringToByte("000204B07672172F114E8E847A5FB9EC3DD32CD1F063E78FE16508F3E13DDCEE227447EBE13DDCEE227447EB80D3FD7BAFF9D6FD4DE2225C31BAFF7C626E7DEFD52ED1EEF9195F538F89B902AF389CF4277EADC1FA18BED9044C4CBCDD6801DA9C8762A3E6715D93AF02D4665D1AE5669288EF9E429C46EDC366C4F60724DED14AE4A3870E6D75DA22CFC304C38B50394BC09F833D3A6A663F0E0863FB7DDBC0C83CD24690BF54B8A45053CAE10C22018D11C10F112B4EECA416D39FCEA9276C93DAE83D8B300E67545B897DCAAC0CF064C9A2F8EE61362AE90694EF300DC7B901F1F093BA167DA76CD5F1432024C8C8FC420BB182B3944F7E104DBAE51BD859F36E92AB32E21754B711288643FB3399B363F776CB614C5EC08569A0E457507D3CA53A56065ECEA0AC7A467E88C4A7D2B63BBF933FE69B64E8F43F766D3D5B219FF00882E85F4C8A9CAD86EE65ACE2129DB6B4EC760E6687DE96B9AFB6F2A98D3C4AFE0F05D4485ADC055580242DD1FAF07808FA75E85E102B879E680004F992979ACA6B6C54885B5A52FF1EA55B3EF9F787D395E2E500D1A8CDE83D7FC05DB124441F2234BC88B9286CA142B22601C5225F8E679CFD3F612E37CA39E67736175B4A298BD69625658664AF8A9B8045A4E3FE2CEF770BD6BF2CE7D6B7C0C72B55C23FA6D0437E2D4DEDE89BCFC77AC90EA1F5B72910A4449EED91BCB778CD86DA88DE8341940E7F4677EB7D322722876A893926326E19D32DF6653EB4068D3C05F24B854F4B77EB0059C7EECD4283CC65F31300FE0EEEA87E97CC39F74B2929847D1A7B5DC2C6281CB8FCB30AEB605155ACF0C3EBE0BFD5E652CCE11C7D59CF89929F2DAE619CB21C7F4E148436951E1EAC41508A51DE2835103892D0FEE9913E82C673470F764CED04F4A3F7512E7BCB38C11685ED5A03D9D3F82977F3D36D53E0E3116D424CFA246E8954136DA20B666C4CBE532CF177A48AD1F6BBA626240D032569FA4CC7158DDD94E800213FC2072A24389757CD97B3CF511D240DC8171593C8F1BCEE73D32A13C894BE1C3F03FC2A3098579D3E0F45F64C3E9E9846F11B3436664B5D591E9F4EF0F96A00AC6CA793215865404C9AB0424E3F5488B5A3AA87D57D90CC56ED5B9C647A38CBD41968AF759961F9B8D8048E1E93AD063199B8D75875578AA8E8409D7837B61C6D56B82A690E08BDF24FAE143BDC4FA8314881ACFCD6EE66F8158F3E446527CE883E1391901DD192B6859625FF2F77B2E22EE9CC3E97FBD4455DF2F4A772FB2962F9A3BCFF7ADA30D07BB53BB2B3C1F60AA4FBE541D2A02457342666FB560906BCD21C701488E6D4548505776190CB0CC79E1B9D1014D70ECE5A9E104608E7940C570960ACA0C6CAFBA80D0FB95E99B52D2E9FDAFE92A6786F14EF387AFF54F3607908408BFC1C31FDE0FFF8C75D1DF431F5275941F665005DD89F6E3F48CEFFD3746E33F63D0F616BA559A292095690B59B907907A41D69281CC90E3A2D68D66E74D44FF7A36AD370693883B9B6440A3674F94B42CC594CB9A56D37FA1C4D76F9A7DDA71D8CEA31D1397678B33A0ECCFE5095FCC98A8B6D30A3DE7EF1963D68A4B15EE45060FDA7EA3DBA42C936CBCDA2C99FBAD98F12DE1A4523A12F2F8D0C7818A1C5B6377A8499AE837EB0B233D98470234F3EAD29C2DAB368CF5463151BCB266DEF496D8E");
    byte[] publicRSA = Forms.hexStringToByte("3082010902820100EED2CF3C2E3624D65718E0F1CCE74F3D5CB93B4C1B3737161E7154AE0027FD911A901B040040FAE50F586AC6E3CC653ADA75F7CF7A36E18C3D662AA81AE25D05CBE5486ED432BCC3925324ADE4592E4577DC004503BC05F9D67AFCFAB58D14E294A8AC3979AE8DC0319F8E180BF948E9E3BE9527546999120EB88DEEF36EE5C589E00421B309145377730AD99337FDB8A1F01F191ED7F761854B86BAAA61253DF821B2C72FDD138134A848278FF94B660C47DEF24EB23163919F199D1637FC1B4E2AB0683CB17B07706D5D307F17D6A8916EAA92AB80B07E9F723C5A96AB382B90F4718E18A620556D927F5DA9529C22D5C701B8B1BB7836D351A815A69116110203010001");
    byte[] publicR77 = Forms.hexStringToByte("3082010A0282010100A636C484374F9F039EB4318952B6BA5ABBE096F2B37B12DBC71A09F3B7BEEB83EB4A4BBBBDBBCC9332168E336981C919EF8BB734B3671DFEDCB79459401F95DDAA4EACECB36599451F9F77F5B01BF6B6AA1F94DE8BE5ED8B7BD52CA94929F7B0D3E8F5FDAFA322538AE32F89D7E3C1E4203120EDE6F213A3848F8ECF9E6836BE369A4658B6EB14D2FD3681488A3207CE0A5A9088011B2DA893C7F2C674843BB5254C30CB67D9C8182FEF284BB5CD8A239D6411EA199AD8B93EBE3442716FDAB44FB3932248C076C8794725CEEB5B76674B2B6DC605DC0F9835C6CCBBE4807A4F925065E02C65CAFE2D80A275BF5D096D2E07BA9ED5A75A10D425B03B84BB57990203010001");
    @Test
    public void RSApriSign() throws TAException, IOException {
        byte[] bytes = api.RSAPriKeySign(privateRSA,TACryptConst.PADDING_MODE_NO, 4, 0,
                0, 0, Forms.hexStringToByte("9ECA5459BA0B5CA0CCBB2A01EA05DE319C9E97DF730F0E2A55E9DC2B6FFA85CE"));
        System.out.println("Signature generation results:" + Forms.byteToHexString(bytes));
        boolean b = api.RSAPubVerify(publicRSA,TACryptConst.PADDING_MODE_PKCS15, TACryptConst.DIGEST_ALG_SHA256, 0,
                0, 0, bytes, Forms.hexStringToByte("9ECA5459BA0B5CA0CCBB2A01EA05DE319C9E97DF730F0E2A55E9DC2B6FFA85CE"));
        System.out.println("Signature verification results:" + 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 generation results:" + 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 results:" + 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 results:" + Forms.byteToHexString(bytes));
        byte[] bytes1 = api.RSAPriDecData(11, 1, TACryptConst.DIGEST_ALG_SHA256,new byte[0], bytes);
        System.out.println("Private-key decryption results:" + Forms.byteToHexString(bytes1));
    }

    /**
     *  Decryption by RSA private keys protected by protection keys
     */
    @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("BFA03DB9BD0A4DE4809B59B04BF663E8E541B0CF0017E0337342B8F7CDEB210C86429D87A51A7E2B4ED760C4BB49A1AD1DE0353B3204D39C8F6FF9DB789C8DEDCDD84012DDB532F3E4554F0C85DCEF1C7241C98888F9CC57D04E902ABD2F422884235FD9E0A80116771AC436ED1EDE46CF272FD1DD4D3A5174D2D178D9A21F3D"));
        System.out.println("Plaintext after decryption:" + Forms.byteToHexString(bytes));
    }

    /**
     * Signature generation by RSA private keys protected by protection keys
     */
    @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 generation results:" + 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 results:" + b);
    }

    /**
     * Encryption key of RSA asymmetric keys changed from Protection Key 1 to Protection Key 1
     */
    @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("No.:" + i + "===" + Forms.byteToHexString(bytes.get(i)));
        }
    }

    /**
     * Import symmetric keys to protect RSA asymmetric keys.
     */
    @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("5C59EBCD0A48E51038853E490C76AD83122964E3AA3EAB660966F67DE56722D02E3B477D257BDDB90CA2F901254544933BD0852BCF6E466CE91813AACF8A4AD2C65F2B78888AE249A948BCDCF3E2D0CDCC70DC3BA9445D3237B6D56A701D17E95576AD4FCF0A1D20DC5A0AAB878DADC04903CCE5B3D06219FDB4497905FBEA9E"), "916-zjl".getBytes());
        System.out.println("Symmetric keys encrypted by LMKs:" + Forms.byteToHexString(bytes.get(0)));
        System.out.println("Checksum values of symmetric keys:" + Forms.byteToHexString(bytes.get(1)));
    }

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

    /**
     * SM2 and Elliptic Curve Cryptography (ECC) key pairs generated and encrypted by protection keys
     */
    @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("DER-encoded public keys:" + Forms.byteToHexString(bytes.get(0)));
        System.out.println("Private keys encrypted by LMKs:" + Forms.byteToHexString(bytes.get(1)));
        System.out.println("Ciphertext of private keys encrypted by protection keys:" + Forms.byteToHexString(bytes.get(2)));
        System.out.println("MACs of asymmetric private keys:" + Forms.byteToHexString(bytes.get(3)));
        System.out.println("Tags:" + Forms.byteToHexString(bytes.get(4)));

    }

    /**
     * SM2 key pairs generated and private keys encrypted by LMKs
     */
    @Test
    public void generateSM2Key() throws TAException {
        ArrayList<byte[]> bytes = api.genSM2Key();
        System.out.println("DER-encoded public keys:" + Forms.byteToHexString(bytes.get(0)));
        System.out.println("Private keys encrypted by LMKs:" + Forms.byteToHexString(bytes.get(1)));
    }

    /**
     * ECC key pairs generated and private keys encrypted by LMKs
     */
    @Test
    public void generateECCKey() throws TAException {
        ArrayList<byte[]> bytes = api.genECCKey(0x0007);
        System.out.println("DER-encoded public keys:" + Forms.byteToHexString(bytes.get(0)));
        System.out.println("Private keys encrypted by LMKs:" + Forms.byteToHexString(bytes.get(1)));
 
    }

    byte[] data = Forms.hexStringToByte("20D90A83A4654FB89AD97E7FF9B178BAA58E12CE8E5C16DE0371B374F76DEFA5");

    /**
     * ECC signature generation and verification
     */
    @Test
    public void ECCPrivateKeySign() throws TAException {

        byte[] bytes = api.priKeySign(0x0007, Forms.hexStringToByteArray("61971383CD4D760CF77CCA48C187592ACE2375BB54CA886724EE230AE7D94C1C935F18B4CCCFBF3A"), data);
        System.out.println("ECC signature generation results:" + Forms.byteToHexString(bytes));

        boolean b = api.pubKeyVerify(0x0007, Forms.hexStringToByteArray("3059301306072A8648CE3D020106082A811CCF5501822D03420004E6BFD64E16F9FDE831FC2483A703F32D2925C126C435CF4FF0BC0187351E34F627E3421ACA51CB99CD452FA11B5B6BBB4AA31C2DBCC696FC57C8F9F8F01948FE"), data, bytes);
        System.out.println("ECC signature verification results:" + b);
    }

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


    @Test
    public void SM2Sign() throws TAException {
        byte[] baInData = "2222222222222222".getBytes();
        //7. SM3 digest computing
        System.out.println("Data digest: SM3");
        String sAlg = "SM3";
        byte[] baUserId = new byte[0];
        byte[] baPubKey = Forms.hexStringToByteArray("3059301306072A8648CE3D020106082A811CCF5501822D03420004A45246028D1FE13EAA9BAE7F47929AE6F9993CEEFEA16EB1358526C8D85277BD63F2EB9A1AD40BEEE37267F8F1F97E67BCE29A4E1CCAB0979A1E85F81010E042");
        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. Signature generation and verification of asymmetric keys
        System.out.println("Signature generation and verification by using asymmetric encryption: 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 generation: %s", Forms.byteToHexString(baSignatureSm2)));
        boolean blVerifyResSm2 = api.pubKeyVerify(iCurveId, baPubKey, baHashSm3, baSignatureSm2);
        System.out.println(blVerifyResSm2);
    }


    byte[] sm2 = Forms.hexStringToByte("3059301306072A8648CE3D020106082A811CCF5501822D03420004E70CB95894768A69B5A184C17B31251710B2B870BB99E0BE150EA2FAF1F4CEECF6B48055A4C790CDE94A1B179CC12A39A856755F6677E87905BD903987425AF3");

    byte[] sm2PrivateKey = Forms.hexStringToByte("4F23C664B68C8A38B31F52727C856211D8D21B1AC76F300D2CD027E5AFD566976CEA234A749F031D");

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

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



    byte[] sm2Key = Forms.hexStringToByte("3059301306072A8648CE3D020106082A811CCF5501822D03420004E70CB95894768A69B5A184C17B31251710B2B870BB99E0BE150EA2FAF1F4CEECF6B48055A4C790CDE94A1B179CC12A39A856755F6677E87905BD903987425AF3");
    byte[] sm2Cipher = Forms.hexStringToByte("83E260209C09CC3F010349772852D7CD2C3C77DAEBA956791067754DA7FCFD8880E68AC28BFFF0F3");
    byte[] sm2CipherMAC = Forms.hexStringToByte("8184BE3669B2D12AEB673814E59E7700");
    byte[] sm2CipherTag = Forms.hexStringToByte("8FD638CA4D7640BDE213F5777253D192");
    byte[] sm2PriKey = Forms.hexStringToByte("4F23C664B68C8A38B31F52727C856211D8D21B1AC76F300D2CD027E5AFD566976CEA234A749F031D");


    /**
     * Decryption by ECC and SM2 private keys protected by protection keys
     */
    @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("E9C17D82604F992BB3AB8FE0F766441DACC05EB779D1D1CC9C5FEFF671739A87274713242CBBA04161C3994EA264C30D82BB6DAF8E688D3BADC8768A18226D8EAEB984E5EA739C2E8792921F02AA612F5AB732FACEC8316B880499E6E70260333E9F29CEBCF3F8E10C151F79445276F6"));
        System.out.println("Plaintext after decryption: " + Forms.byteToHexString(bytes));
    }

    /**
     *  Signature generation by ECC and SM2 private keys protected by protection keys
     */
    @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("20D90A83A4654FB89AD97E7FF9B178BAA58E12CE8E5C16DE0371B374F76DEFA5"));
        System.out.println("Results of signature generation by ECC and SM2 private keys protected by protection keys: " + Forms.byteToHexString(bytes));

        boolean b = api.pubKeyVerify(7, sm2Key, Forms.hexStringToByteArray("20D90A83A4654FB89AD97E7FF9B178BAA58E12CE8E5C16DE0371B374F76DEFA5"), bytes);
        System.out.println("Results of signature verification by ECC and SM2 public keys (private keys protected by protection keys): " + b);
    }

    /**
     * Import symmetric keys to protect SM2 asymmetric keys.
     */
    @Test
    public void SM2ImplKEK() throws TAException {
        ArrayList<byte[]> bytes = api.SM2ImplKEK(sm2PriKey, 300, TACryptConst.KEY_ALG_SM4, Forms.hexStringToByteArray("9A9161F87BCBD3E9BC8866B8706E8F75B682DA2712E7E32A5D0E4867700D8233284BF4EA98E352BE74817D240D92347F969809BA54626192102086000756E2CFD98A3CC8923513B3BF72FA33B39CB999E15613440F2DAD9AE786E3D73349D78FA7915B3CB633EFD9A88E638D93297934"), "914-zjl".getBytes());
        System.out.println("Symmetric keys encrypted by LMKs: " + Forms.byteToHexString(bytes.get(0)));
        System.out.println("Checksum values of symmetric keys: " + Forms.byteToHexString(bytes.get(1)));
    }

    /**
     * Encryption key of SM2 and ECC asymmetric keys changed
     */
    @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("No.:" + i + "===" + Forms.byteToHexString(bytes.get(i)));
        }
    }

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

        // Digest result verification
        String string = "704423DF78242B08E821F7F8FA05A5325AA1BD842BE4EB9827C765DFFF434C1A";

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

        String wrongHash = "669523DF78242B08E821F7F8FA05A5325AA1KD842BE4EB9827C765DFFF434C1A";

        System.out.println("Invalid result verification: " + 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;
    }


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

    /**
     * HSM status obtaining
     */
    @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("Ciphertext of keys encrypted by protection keys: " + Forms.byteToHexString(bytes.get(0)));
        System.out.println("MACs: " + Forms.byteToHexString(bytes.get(1)));
        System.out.println("Tags: " + Forms.byteToHexString(bytes.get(2)));
        System.out.println("Checksum values of keys: " + Forms.byteToHexString(bytes.get(3)));
    }

    /**
     * Switch from encryption based on other keys to LMK-based encryption
     * @throws TAException
     */
    @Test
    public void otherEncKeyToLMLEncKey() throws TAException {
        ArrayList<byte[]> bytes = api.otherEncKeyToLMLEncKey(0, 7, 6,
                Forms.hexStringToByteArray("00000000000000000000000000000000"),
                Forms.hexStringToByteArray("00000000000000000000000000000000"),
                Forms.hexStringToByteArray("71802E75BD4D99E90996A9B9DA6616E9"),
                0,  Forms.hexStringToByteArray("B36847D6E86EAB69E4EEB65558A2626C"),
                new byte[0], new byte[0], 5, -1,-1, new byte[0], 0, 7,
                Forms.hexStringToByte("994056800038295C09C7F45977D291AA"));
        System.out.println("=============Protection keys are symmetric keys.============");
        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("7C78EAFE26890D48096AB8141B1D5890BF1921DD899664A7E224C05DC30A7392CAA4BB0E518CBE5721DAC409F85B736A1DAEC40FAB410CA007C114574BAEAD1227560F1D2AE148884814872F0305F821F7245329ADED546F44C52C8F49EAC46647650D9B983224E9E005CFCAA88B019D"));

        System.out.println("=============Protection keys are ECC keys.============");
        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("6149EE02F14EE6420BC2B462003CCCE2413CE4911F5C36F720DD123DA9A432EEA17C534A8662F9B1E813C8A5FA929E9A06AC2CFDB2AAB68E66A58C9A4E0C76AF5126785160A665C23F22309ECBF48B8BAFA8BE9D41F334852649D5D204937A4EDA3B0A9B1A7B3054E1D9AE3BA2173028C3A0E2CE400522E06DCBAB44213A85B668764EC33EE71D372F5A904252A539AA"));

        System.out.println("=============Protection keys are RSA keys.============");
        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 sealing results: " + Forms.byteToHexString(bytes));
        byte[] bytes1 = api.enveopDec(sm2PriKey, bytes);
        System.out.println("Digital envelope unsealing results: " + new String(bytes1));
    }

    /**
     * Change to the encryption keys of symmetric keys & Change to the encryption keys of asymmetric keys
     */
    @Test
    public void symmetryConversionEncryptionAES256() throws TAException {
        ArrayList<byte[]> bytes = api.conversionEncryption(0, TACryptConst.KEY_ALG_AES256,
                Forms.hexStringToByteArray("5BD90CDDBC8645B41AB901DDD8EFE9956755D9560C9FAEB096B6E52CC003D04F"),
                Forms.hexStringToByteArray("F8B6B9D8BB7E4FD3"),
                TACryptConst.KEY_TYPE_SYMMETRY,
                TACryptConst.KEY_ALG_AES256,
                Forms.hexStringToByteArray("CFE8E3D44F753D3F065962462AA9C9E1FE295BC835E4A1FB88EF70B54E65E232"), b,
                Forms.hexStringToByteArray("8F2440B22092CA8757D8D807A832A19F"), TACryptConst.ENC_MODE_GCM, b, new byte[22],
                Forms.hexStringToByteArray("B5294D591009E19E780774B61BA48FA4"),
                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("No." + i + "===" + Forms.byteToHexString(bytes.get(i)));
        }
    }

    /**
     * Change to the encryption keys of symmetric keys & Change to the encryption keys of asymmetric keys
     */
    @Test
    public void symmetryConversionEncryption() throws TAException {
        ArrayList<byte[]> bytes = api.conversionEncryption(0, TACryptConst.KEY_ALG_SM4,
                Forms.hexStringToByteArray("CBDCCE33784FA93FBE0B3BAA46CF3557"),
                Forms.hexStringToByteArray("F6684895E1ABC2AD"),
                0,TACryptConst.KEY_ALG_SM4,
                Forms.hexStringToByteArray("6BFC84C39CB9277C06C7FA2A30C912A1"), b,
                Forms.hexStringToByteArray("AB75C62580061710B39327B45881F589"), TACryptConst.ENC_MODE_GCM,
                b, new byte[0], Forms.hexStringToByteArray("4A501743FA4B906244A0A8705192C1C8"),0,
                TACryptConst.KEY_ALG_SM4,
                Forms.hexStringToByteArray("CBDCCE33784FA93FBE0B3BAA46CF3557"),
                Forms.hexStringToByteArray("F6684895E1ABC2AD"), b, TACryptConst.ENC_MODE_GCM, b, new byte[0]);
        for (int i = 0; i < bytes.size(); i++) {
            System.out.println("No." + i + "===" + Forms.byteToHexString(bytes.get(i)));
        }
    }

    /**
     * Change to the encryption keys of symmetric keys & Change to the encryption keys of asymmetric keys
     */
    @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("83E260209C09CC3FEFDEFE7F4B620157A3F25E0B3098A4677DAF3A8E9DC327A17AEB2C8919E1E4CF"), b,
                Forms.hexStringToByteArray("E60EFC48823B17C51F68D0EB622298FB"),
                TACryptConst.ENC_MODE_GCM, b, new byte[16],
                Forms.hexStringToByteArray("B200ED220D49D855EC4438649057EB02"),
                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("No." + i + "===" + Forms.byteToHexString(bytes.get(i)));
        }
    }


    /**
     * Import asymmetric customer master keys (CMKs) to protect symmetric CMKs.
     */
    @Test
    public void importCMKByCMK() throws TAException {
        ArrayList<byte[]> bytes = api.importCMKByCMK("zjlimpl".getBytes(), 7,
                6,  //Identifiers of algorithm modes used by DomainKeys to encrypt CMKs
                new byte[16],     //Initialization Vector (IV) data used during decryption in Electronic Code Book (ECB) mode 
                new byte[16],      //Authentication data used during decryption in Galois/Counter Mode (GCM) mode
                Forms.hexStringToByteArray("566F7CE9E52CCA87FF02D7A7667E3F7C"), //MACs during decryption in GCM mode
                Forms.hexStringToByteArray("DA23B170CEA626F4C772B3F2AE2CCA97"),//Key ciphertext
                Forms.hexStringToByteArray("7192C7C6F1EAAB72BFE8A51BA9256C87"),  //GCM tags
                6, //Encryption modes of protection keys
                new byte[16],//IVs of protection keys 
                new byte[16], //Additional Authenticated Data (AAD)
                Forms.hexStringToByteArray("8DE9DFEE4BE10827C1C08A38BDD8A92F"), //Tags
                5,// Padding methods of protection key-based encryption
                12, //Types of session keys
                7,  //Identifiers of algorithms of asymmetric session CMKs
                Forms.hexStringToByteArray("420B9FE23A2B162F3C4574919E9EBD44040F7C5338CDE0C8311C88495D2F3604E9AFC80B18990EF5C6F3A93AB80B41458311EA9F9A1890752427E24F5062AD4A"),//Ciphertext of session private key
                "32-1".getBytes(),//Tags of session DomainKeys
                6,//Identifiers of algorithm modes used by session DomainKeys to encrypt CMKs
                new byte[16],//Session encryption context (IV data used during encryption in non-ECB mode)
                new byte[16]//Session authentication context data (authentication data during encryption in GCM mode)
        );
        System.out.println("Ciphertext of keys encrypted by protection keys: " + Forms.byteToHexString(bytes.get(0)));
        System.out.println("MACs: " + Forms.byteToHexString(bytes.get(1)));
        System.out.println("Tags: " + Forms.byteToHexString(bytes.get(2)));
        System.out.println("Checksum values of keys: " + Forms.byteToHexString(bytes.get(3)));
    }

    @Test
    public void testData() throws TAException {
        //Symmetric keys generated and protected by protection keys
        ArrayList<byte[]> bytes = api.proGenSymmKey(603,
                -1, null, TACryptConst.KEY_ALG_SM4, b,
                TACryptConst.ENC_MODE_GCM,b, b);
        System.out.println("Ciphertext of session keys encrypted by LMKs: " + Forms.byteToHexString(bytes.get(0)));
        System.out.println("Checksum values of session keys: " + Forms.byteToHexString(bytes.get(1)));
        System.out.println("Ciphertext of session keys encrypted by protection keys: " + Forms.byteToHexString(bytes.get(2)));
        System.out.println("MACs of session keys: " + Forms.byteToHexString(bytes.get(3)));
        System.out.println("Tags: " + Forms.byteToHexString(bytes.get(4)));
        System.out.println("-------------------------------------------------");
        //Data encrypted by symmetric keys protected by protection keys
        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("0000000000000000000000000000000000000000000000000000000000000000E43101353F49C7164DAE6C691FC25CD494D9A28D0F6C4B51F3BB9DC85ADDBE09"), 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("3076301006072A8648CE3D020106052B8104002203620004491995797F5C99C17726E4841BE04D333C5BD3511819720388BD7264112905D3073FC25743EED2AE7D1448C2D2D9E014C640FC395CF19650A61D0ABC616D521050C45645477442F9BF8BE9BF81EAD69CDA6C63FCF5244A383C57DDB62465E63B"));
//        System.out.println("secp384r1 Negotiation results: " + Forms.byteToHexString(bytes));
//        byte[] bytes1 = api.agreementKey(0x0007, 3, 6, Forms.hexStringToByte("3059301306072A8648CE3D020106082A811CCF5501822D03420004AC3DC24CE9883F26278E97A04D5409AA2A94D57FCE84E7630F4E46CFBED036A6B89791DF9A3DF50D67073CF246FC3406337B50E987F2AC3943D2FF5C7ECAD197"));
//        System.out.println("0x0007 Negotiation results: " + Forms.byteToHexString(bytes1));
//        byte[] bytes2 = api.agreementKey(0x0007, 3, Forms.hexStringToByte("E59842CEEC68775E6AD78C7276AD2ADE0E27405E8B60FE02F7DF23E08F7F6B8D"), Forms.hexStringToByte("3059301306072A8648CE3D020106082A811CCF5501822D034200040EF69FB0C3739C3FDC16499AB96985EAD5CBEB4178A985A8FC10145979C315A5519C50B972EB19EA77A6AB74F345688B8458F1015885FCE435A4E3679DE0E34F"));
//        System.out.println("0x0007 Plaintext negotiation results of external private keys: " + Forms.byteToHexString(bytes2));
//        byte[] bytes3 = api.agreementKey(0x039B, 0, 5, Forms.hexStringToByte("304A301406072A8648CE3D020106092B24030302080101030332000448D5FAD9CD434E60EF661B65289867B395461D868F7D34BABEEB5A20F7DF5543091DD740DD3780B5EBEF631615571ADC"));
//        System.out.println("0x039B Negotiation results: " + Forms.byteToHexString(bytes3));
        byte[] bytesA = api.agreementKey(0x019F, 3, 13, Forms.hexStringToByte("3059301306072A8648CE3D020106082A8648CE3D030107034200048D912010F06A7D4B5062F6DC192EEDC8C88FCB2D2830AB8573F0FB30532041D0788F227558F1DA9AC8CDF5E7FA72C9931FA90EE06B3CE07E13A7845A05BA7C73"));
        System.out.println(bytesA.length);
        System.out.println("0x0007 Negotiation results: " + Forms.byteToHexString(bytesA));
        byte[] bytesB = api.agreementKey(0x019F, 3, 15, Forms.hexStringToByte("3059301306072A8648CE3D020106082A8648CE3D0301070342000481022BD6C8FFBBD2EC4B5A53F7000920D1581C0BC17B4C781627894B0979FFCA115C85C7AB0964E53872FBF0511FF6E7661CF94B7D82C8BF78D211B1FA73F271"));
        System.out.println("0x0007 Negotiation results: " + Forms.byteToHexString(bytesB));

    }

    /**
     * Obtain symmetric key details based on key indexes.
     */
    @Test
    public void getKeyInfo() throws TAException {
        String[] keyInfo = api.getKeyInfo(66);
        System.out.println(keyInfo[0]);
    }
    /**
     * Obtain RSA public keys based on key indexes.
     */
    @Test
    public void exportRSAPublicKey() throws TAException, IOException {
        ArrayList<byte[]> keyInfo = api.exportRSAPublicKey(77,0);
        System.out.println(Forms.byteToHexString(keyInfo.get(0)));
    }
    /**
     * Obtain ECC public keys based on key indexes.
     */
    @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("RSA key pairs generated and saved" + (b ? "Success":"Failure"));
        boolean b1 = api.generateECCKey(0x019F, 8);
        System.out.println("ECC key pairs generated and saved" + (b1 ? "Success":"Failure"));

    }


}

Other operations

Scale out a cluster

You can add HSMs in different zones to the same cluster and manage the HSMs in a centralized manner. This helps ensure the high availability of Cloud Hardware Security Module. HSMs can be added to a cluster only when the following requirements are met:

  • HSMs are not initialized.

  • HSMs are in the Enabled or New state.

  • HSMs are of the same type as the master HSM of the cluster.

  • No vSwitches are configured for HSMs, or the HSMs use the same vSwitch as the master HSM.

Important
  • If a whitelist is configured for an HSM, the whitelist of the cluster prevails after the HSM is added to the cluster. The whitelist of the HSM is cleared.

  • If you want to scale out an HSM cluster for a KMS instance of the hardware key management type, make sure that cluster data synchronization is automated. If cluster data synchronization is manual, contact Alibaba Clloud technical support to upgrade the synchronization method to automated synchronization.

  1. On the VSMs page, find the required master HSM and click Expand Cluster in the Actions column.

  2. Add HSMs to the cluster by using one of the following methods.

    • If no HSMs are available, click Purchase an HSM instance in the Add HSM dialog box to purchase HSMs.

      The purchased HSMs are automatically added to the cluster. Cloud Hardware Security Module automatically assigns IP addresses to the HSMs and synchronizes data in the cluster.

    • If HSMs are available, perform the following operations: In the Add HSM dialog box, select the HSMs that you want to add, click the 添加 icon, and then click OK.

Remove an instance from a cluster

To remove an HSM instance from a cluster, remove the child instances first, and then remove the master instance. If the cluster contains only the master instance, you can remove it directly. The cluster is automatically deleted after the master instance is removed.

  1. Disable the HSM. You must disable an HSM before you can remove it from the cluster.

    1. On the VSMs page, find the target HSM instance and click Disable in the Actions column.

    2. In the dialog box that appears, click Disable again.

  2. On the VSMs page, find the target HSM instance and click Remove from Cluster in the Actions column.

  3. In the dialog box that appears, click Remove from Cluster again.

Modify the cluster name and access whitelist

If no whitelist is set, all IP addresses can access the cluster. If a whitelist is set, access requests from IP addresses not in the whitelist are denied.

  1. On the VSMs page, click the instance ID of the master or a child HSM.

  2. On the Details tab, edit the cluster name and access whitelist.

    You can enter a single IP address or a CIDR block. Enter one entry per line. You can enter up to 10 entries.

    Important
    • The whitelist of a cluster has a higher priority than the whitelist of an HSM in the cluster. For example, if you add 10.10.10.10 to the whitelist of an HSM and add 172.16.0.1 to the whitelist of the cluster that includes the HSM, you can access the HSM only from 172.16.0.1.

    • The whitelist configuration of 0.0.0.0/0 is not supported. If you enter 0.0.0.0/0, requests from all IP addresses are allowed.

      For security reasons, we recommend that you do not allow requests from all IP addresses. If you need to allow requests from all IP addresses, do not configure the whitelist.

Switch the master and child HSMs

You can manually switch a child HSM to be the master HSM in the cluster. This operation is supported only when the cluster's synchronization method is manual synchronization.

  1. On the VSMs page, find the target child HSM instance and click Switch to Master in the Actions column.

  2. In the dialog box that appears, click Switch.