Todos os produtos
Search
Central de documentação

Key Management Service:Uso de um cluster de instâncias HSM

Última atualização: Aug 25, 2026

O recurso de cluster de instâncias HSM do Cloud Hardware Security Module (CloudHSM) permite associar instâncias HSM com uma finalidade comercial comum em diferentes zonas de disponibilidade na mesma região. Sua aplicação pode usar um algoritmo de polling para selecionar o HSM adequado e executar operações criptográficas com a mesma chave. Essa arquitetura garante continuidade dos negócios, alta disponibilidade para computações criptográficas, balanceamento de carga e dimensionamento horizontal da aplicação. Este tópico descreve como usar um cluster de instâncias HSM.

Nota

Para criar um cluster HSM para uma instância de hardware do KMS, consulte Configure an HSM cluster for a KMS hardware instance.

Métodos de sincronização de cluster

A sincronização de cluster replica dados, como chaves, certificados SSL e informações de usuário, do HSM mestre para os HSMs filhos. O método de sincronização depende da data de compra dos HSMs:

  • Para HSMs adquiridos em ou após 9 de janeiro de 2025: Ao criar um cluster, o método padrão é a sincronização automática. Não é necessário sincronizar manualmente o cluster quando houver alterações nos dados do HSM mestre.

  • Para HSMs adquiridos antes de 9 de janeiro de 2025: Ao criar um cluster, o método padrão é a sincronização manual. Sincronize manualmente o cluster sempre que houver alterações nos dados do HSM mestre. Para atualizar o cluster para sincronização automática, contact us.

    Aviso

    Esta é uma atualização irreversível que envolve os seguintes riscos. Recomendamos fortemente realizar essa atualização fora do horário de pico.

    • Para usuários de instâncias de gerenciamento de chaves de hardware do KMS:

      • Operações do plano de controle: Operações como criação e exclusão de chaves não são suportadas durante a atualização. Elas serão retomadas automaticamente após a conclusão.

      • Operações do plano de dados: Operações como criptografia e descriptografia não são afetadas durante a atualização.

    • Para outros usuários: Atualize o SDK do HSM utilizado pela sua aplicação.

      • Operações do plano de controle: Operações como criação e exclusão de chaves não são suportadas durante a atualização. Elas serão retomadas automaticamente após a conclusão.

      • Operações do plano de dados: Em algumas arquiteturas de negócios, há risco de interrupção do service durante a atualização.

Pré-requisitos

  • Você adquiriu uma máquina criptográfica. Para mais informações, consulte Purchase a Cryptographic Machine.

  • Adquira uma instância ECS com Windows implantada na mesma VPC da instância HSM. Para mais informações, consulte Quick Start for Windows-based ECS instances.

    Nota

    Essa instância ECS serve apenas para instalar a ferramenta de gerenciamento do HSM, não como servidor de negócios.

Etapa 1: Criar e ativar um cluster

Um cluster consiste em um HSM mestre e vários HSMs filhos. Todos os HSMs em um cluster devem estar na mesma VPC, mas podem estar na mesma sub-rede ou em sub-redes diferentes.

Nota

Se você definiu configurações de cluster ao adquirir uma instância GVSM, o Cloud Hardware Security Module cria automaticamente um cluster com base nessas configurações. Pule esta etapa.

  1. Ative a instância HSM mestre.

    1. Acesse a página VSMs no console do CloudHSM. Na barra de navegação superior, selecione a região de destino.

    2. Na página VSMs, localize a instância HSM criada. Na coluna Actions, clique em Enable.

    3. Na caixa de diálogo Configure HSM Instance, configure a instância HSM e clique em OK. Após a configuração bem-sucedida, o Status da instância HSM muda para Enabled.

      Parâmetro

      Descrição

      VPC ID

      Selecione a VPC à qual a instância HSM está anexada.

      Importante

      Esta VPC deve ser a mesma à qual sua instância ECS está anexada.

      VPC Subnet

      Selecione o bloco CIDR da sub-rede da VPC onde a instância HSM reside.

      Private IP Address

      Atribua um endereço IP privado à instância HSM.

      Importante
      • O endereço IP privado deve pertencer ao bloco CIDR da sub-rede da VPC. Caso contrário, a configuração falhará.

      • Endereços IP terminados em 253, 254 ou 255 são reservados pelo sistema. Não os utilize.

      Configure HSM Whitelist

      Configure a lista de permissões para acessar a instância HSM. Insira um endereço IP ou bloco CIDR por linha, até o limite de 10 entradas.

      • Sem uma lista de permissões configurada, todos os endereços IP podem acessar a instância HSM.

      • Com uma lista de permissões configurada, apenas solicitações originadas dos endereços IP listados são permitidas. Solicitações de outros endereços IP são negadas.

      Importante
      • Ao criar um cluster HSM e configurar uma lista de permissões para ele, a lista do cluster tem precedência sobre as listas das instâncias HSM individuais que o compõem.

        Por exemplo, se a lista de permissões de uma instância HSM no cluster for 10.10.10.10 e a lista do cluster for 172.16.0.1, o acesso à instância HSM só será possível a partir de 172.16.0.1.

      • Não é possível configurar 0.0.0.0/0 (para permitir todos os endereços IP de source).

        Por motivos de segurança, não recomendamos permitir todos os endereços IP de source. Para testes temporários que exijam acesso irrestrito, deixe a lista de permissões vazia.

  2. Crie um cluster HSM.

    1. Localize a instância HSM mestre e clique em Create Cluster na coluna Actions.

    2. No painel Create and Activate Cluster, configure o cluster.

      Parâmetro

      Descrição

      Cluster Name

      Insira um nome personalizado para o cluster. O nome deve ser único e não pode exceder 24 caracteres.

      Configure Whitelist

      Especifique os endereços IP que podem acessar o cluster. Se nenhuma lista de permissões for configurada, todos os endereços IP poderão acessar o cluster. Caso contrário, solicitações de endereços IP fora da lista serão negadas.

      Insira um endereço IP ou bloco CIDR por linha, até o limite de 10 entradas.

      Importante
      • A lista de permissões do cluster tem precedência sobre as listas das instâncias HSM individuais. Por exemplo, se a lista de uma instância HSM no cluster for 10.10.10.10 e a lista do cluster for 172.16.0.1, o acesso à instância HSM só será possível a partir de 172.16.0.1.

      • Não é possível configurar 0.0.0.0/0 (para permitir todos os endereços IP de source).

        Por motivos de segurança, não recomendamos permitir todos os endereços IP de source. Para testes temporários que exijam acesso irrestrito, deixe a lista de permissões vazia.

      Specify vSwitches

      Selecione vSwitches nas zonas necessárias conforme suas necessidades de negócios.

      É obrigatório configurar pelo menos dois vSwitches para criar e ativar um cluster HSM com sucesso.

    3. Inicialize a instância HSM e clique em Next.

      Nota

      A ativação do cluster só é possível quando o status do HSM mestre for Initialized.

      Método de inicialização

      Procedimento

      Método 1: Inicialização com um clique no console do CloudHSM

      Importante

      A inicialização com um clique só está disponível se o seu HSM for de uso geral (GVSM) e você não precisar de suporte a UKEY.

      1. Na parte inferior do painel Create and Activate Cluster, clique em Initialize the master HSM with a few clicks.

      2. Na caixa de diálogo Initialize Instance, clique em OK.

      A inicialização leva de 1 a 5 minutos. Aguarde a conclusão. Depois disso, clique no ícone update ao lado de Selected Master HSM:. O status mudará para Initialized. Não reinicialize o HSM mestre neste estado.

      Método 2: Inicialização via ferramenta de gerenciamento de instância HSM

      Importante

      A ferramenta de gerenciamento de cliente HSM executa apenas no Windows.

      Na parte inferior do painel Create and Activate Cluster, clique em Download HSM instance management tool.

      Extraia o pacote de software do HSM. Em seguida, consulte a seção Initial Initialization no manual do usuário incluído no pacote para concluir a inicialização.

    4. Siga as instruções na tela para adicionar HSMs filhos ao cluster e clique em Complete.

(Opcional) Etapa 2: Configurar autenticação TLS mútua

Geração automática

Somente instâncias GVSM suportam geração automática de certificados na aquisição do HSM. Nesse cenário, o HSM gera os certificados automaticamente. Basta configurar os certificados no SDK do cliente, pois o HSM os implanta automaticamente no servidor.

  1. Implante os certificados no cliente.

    Baixe o certificado do cliente no console e implante-o em seu cliente.

    1. Na página de detalhes do HSM, clique em Get Cluster Certificate. A pasta baixada contém os seguintes arquivos:

      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. Implante os arquivos client.p12 e rootca.pem no cliente. No arquivo de configuração do cliente, especifique também os caminhos para client.p12 e rootca.pem, além do valor da senha (passphrase). Para mais informações, consulte a documentação incluída no pacote baixado do console.

  2. Implante o certificado no servidor.

    O HSM implanta automaticamente o certificado na instância HSM. Nenhuma ação é necessária.

Importante

O período de validade padrão de um certificado é de 10 anos. Antes da expiração, o HSM gera automaticamente um novo certificado e realiza a rotação do certificado do servidor. Não use a ferramenta de gerenciamento de instância HSM para criar um administrador UKEY, caso contrário, a rotação do certificado falhará.

Geração manual

O GVSM suporta geração automática de certificados. No entanto, se você não ativou essa opção durante a compra, siga estas etapas para gerar e implantar os certificados manualmente.

  1. Gere os certificados.

    1. Baixe a ferramenta de geração de certificados (dkms_cert_tool).

    2. Descompacte o arquivo baixado e execute a ferramenta de geração de certificados para criar um certificado CA, um certificado de cliente e um certificado de servidor.

      Nota
      • A ferramenta é independente de plataforma e pode ser executada em um computador local, uma instância ECS ou qualquer outro ambiente suportado.

      • Trata-se de uma ferramenta auxiliar da Alibaba Cloud. Se você já consegue gerar os arquivos de certificado necessários, pode pular o uso desta ferramenta.

      Windows

      • Método 1: Na pasta Windows, clique duas vezes no arquivo hsm_certificate_generate.exe para executá-lo. Os arquivos de certificado serão gerados na pasta certs.

        Nota

        Este método define a senha padrão para os arquivos de certificado PKCS12 (.p12) e arquivos de chave privada CA (.key) como 12345678. Para especificar uma senha personalizada, use o Método 2.

      • Método 2: Navegue até o diretório Windows e execute o comando a seguir. Os arquivos de certificado serão gerados na pasta certs.

        ./hsm_certificate_generate -dir ./certs -pswd 12345678

        O parâmetro -dir especifica o diretório de saída. O parâmetro -pswd define a senha para os arquivos de certificado PKCS12 (.p12) e arquivos de chave privada CA (.key).

      Linux

      Navegue até o diretório Linux e execute o comando a seguir. Os arquivos de certificado serão gerados na pasta certs.

      ./hsm_certificate_generate -dir ./certs -pswd 12345678

      O parâmetro -dir especifica o diretório de saída. O parâmetro -pswd define a senha para os arquivos de certificado PKCS12 (.p12) e arquivos de chave privada CA (.key).

      macOS

      Navegue até o diretório darwin e execute o comando a seguir. Os arquivos de certificado serão gerados na pasta certs.

      ./hsm_certificate_generate -dir ./certs -pswd 12345678

      O parâmetro -dir especifica o diretório de saída. O parâmetro -pswd define a senha para os arquivos de certificado PKCS12 (.p12) e arquivos de chave privada CA (.key).

      Após a execução bem-sucedida do comando, os seguintes arquivos são gerados na pasta certs:

      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)
      └── server.pem (Server certificate in PEM format)
  2. Implante os certificados no cliente.

    Implante os arquivos client.p12 e rootca.pem no cliente. No arquivo de configuração do cliente, especifique também os caminhos para client.p12 e rootca.pem, além da senha definida durante a geração dos certificados. Para mais informações, consulte a documentação incluída no pacote baixado do console.

  3. Implante os certificados no servidor.

    1. Instale a ferramenta de gerenciamento de instância HSM em uma instância ECS.

      Importante

      A ferramenta de gerenciamento de instância HSM executa apenas no Windows.

      1. Clique no ícone de download image na coluna Specifications do HSM mestre para baixar a ferramenta de gerenciamento de instância HSM.

      2. Descompacte o pacote HSM baixado, localize o arquivo PKIManager-X.X.X.X.exe e faça o upload para a instância ECS. Para mais informações, consulte Transfer files to a Windows instance.

    2. Use a ferramenta de gerenciamento de instância HSM para configurar o HSM mestre.

      1. Na instância ECS, use a ferramenta de gerenciamento de instância HSM para conectar-se ao GVSM mestre.

        1. Clique duas vezes em PKIManager-X.X.X.X.exe para abrir a ferramenta de gerenciamento de instância HSM. Escolha System > TCP/IP Connection.

        2. Na caixa de diálogo TCP/IP Connection, insira o IP address e a Port do HSM mestre. A porta é 8020.

          Encontre o endereço IP do HSM mestre na coluna IP Address da lista de instâncias HSM. O HSM mestre é a instância identificada como Master HSM na coluna Cluster.

        3. Na caixa de diálogo PKIManager, clique em Connect. Na caixa de diálogo PKIManager exibida, clique em OK e, em seguida, clique em Login.

          Nota

          Para maior segurança, recomendamos registrar uma conta de administrador para logins subsequentes. Para mais informações, consulte as seções 2.1.3. Register Administrator e 2.1.2. Administrator Logon no GVSM User Management Manual, incluído na ferramenta de gerenciamento de instância HSM.

      2. Utilize a ferramenta de gerenciamento de instância HSM para concluir as configurações abaixo.

        Parâmetro

        Ações

        Configurar o certificado do cliente (client.pem)

        1. Escolha Key Management > Client Management.

        2. Na caixa de diálogo Client Certificate Management, clique em Import Certificate.

        3. Na caixa de diálogo Import Certificate, defina Certificate Type como International TLS Client RSA Certificate [pem], selecione o certificado do cliente (client.pem) gerado pela ferramenta e clique em Import.

        Configurar o certificado do servidor (server.p12)

        1. Escolha Instance Monitoring Information > Server Management.

        2. Na caixa de diálogo Server p12 Certificate Management, clique em Import Certificate.

        3. Na caixa de diálogo Import Certificate, defina Certificate Type como International TLS Server RSA Certificate [p12], selecione o certificado do servidor (server.p12) gerado pela ferramenta e insira a Certificate Password. Esta é a senha definida durante a geração do certificado. Se nenhuma senha foi definida, o padrão é 12345678.

        4. Clique em Import.

        Configurar propriedades da porta do dispositivo para o GVSM mestre

        1. Escolha .

        2. Na caixa de diálogo Host Port Properties, configure os seguintes parâmetros:

          • 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. Clique em Reset.

        4. Clique em Restart Now e, em seguida, clique em OK.

Etapa 3: Sincronizar dados do cluster

  • Se o Cluster Type for Manual Cluster Synchronization: Sincronize o cluster após sua criação e ativação iniciais, ou sempre que houver alterações nos dados do HSM mestre. A sincronização não é necessária ao escalar horizontalmente o cluster.

  • Se o Cluster Type for Automatic Cluster Synchronization: A sincronização ocorre automaticamente. O HSM mestre sincroniza novas chaves, certificados SSL configurados e informações de usuário com os HSMs filhos.

Aviso

A sincronização do cluster leva cerca de 5 minutos. Execute esta operação fora do horário de pico para evitar interrupções no service.

  1. Na página VSMs, localize a instância HSM mestre de destino. Na coluna Cluster Type da lista de instâncias, verifique o tipo de sincronização (Manual Cluster Synchronization / Automatic Cluster Synchronization).

    Caso o Cluster Type seja Manual Cluster Synchronization, a sincronização do cluster é obrigatória.

  2. Na coluna Actions, clique em Synchronize Cluster. Na caixa de diálogo exibida, clique novamente em Synchronize Cluster.

Etapa 4: Criar e usar uma chave de criptografia

O pacote de software do HSM inclui o guia do desenvolvedor e programas de teste do SDK. Utilize o guia do desenvolvedor para chamar operações de API e gerencie sua instância HSM.

Nota

Baixe o pacote de software do HSM na página VSMs do console CloudHSM. Localize a instância HSM de destino, clique na coluna Specifications e, em seguida, clique em Download HSM instance management tool. Extraia o arquivo baixado para obter o pacote de software do HSM.

Por exemplo, para um HSM de uso geral (GVSM), localize o caso de teste APITest.java no diretório extraído Alibaba CloudHSM GVSM Software Package>SDK>JAVA>Server HSM Interface Documentation>Test Demo. Use este caso de teste para validar a instância HSM. O código de exemplo é fornecido abaixo:

Nota

Substitua o endereço IP (192.168.XX.XX) no caso de teste pelo endereço IP privado atribuído à sua instância 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 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"));

    }

}