Tous les produits
Search
Centre de documentation

Key Management Service:Utiliser un cluster d'instances HSM

Dernière mise à jour :Aug 09, 2026

La fonctionnalité de cluster d'instances HSM de Cloud Hardware Security Module (CloudHSM) vous permet d'associer des instances HSM servant un objectif métier commun, réparties dans différentes zones de disponibilité au sein d'une même région. Votre application peut ensuite utiliser un algorithme d'interrogation (polling) pour sélectionner une instance HSM appropriée et effectuer des opérations cryptographiques avec la même clé. Cette architecture garantit la continuité des activités, la haute disponibilité des calculs cryptographiques, l'équilibrage de charge et la mise à l'échelle horizontale de votre application. Cette rubrique explique comment utiliser un cluster d'instances HSM.

Remarque

Pour créer un cluster HSM destiné à une instance matérielle KMS, consultez la section Configurer un cluster HSM pour une instance matérielle KMS.

Méthodes de synchronisation du cluster

La synchronisation du cluster réplique les données, telles que les clés, les certificats SSL et les informations utilisateur, de l'instance HSM maître vers les instances HSM enfants. La méthode de synchronisation dépend de la date d'achat de vos instances HSM :

  • Pour les instances HSM achetées le 9 janvier 2025 ou après : Lors de la création d'un cluster, la méthode de synchronisation est par défaut la synchronisation automatique. Vous n'avez pas besoin de synchroniser manuellement le cluster lorsque les données de l'instance HSM maître changent.

  • Pour les instances HSM achetées avant le 9 janvier 2025 : Lors de la création d'un cluster, la méthode de synchronisation est par défaut la synchronisation manuelle. Vous devez synchroniser manuellement le cluster chaque fois que les données de l'instance HSM maître changent. Pour mettre à niveau le cluster vers la synchronisation automatique, contactez-nous.

    Avertissement

    Il s'agit d'une mise à niveau irréversible qui comporte les risques suivants. Nous vous recommandons vivement d'effectuer cette mise à niveau pendant les heures creuses.

    • Pour les utilisateurs d'instances de gestion de clés matérielles KMS :

      • Opérations sur le plan de contrôle : Les opérations telles que la création et la suppression de clés ne sont pas prises en charge pendant la mise à niveau. Elles reprendront automatiquement une fois la mise à niveau terminée.

      • Opérations sur le plan de données : Les opérations telles que le chiffrement et le déchiffrement ne sont pas affectées pendant la mise à niveau.

    • Pour les autres utilisateurs : Vous devez mettre à niveau le SDK HSM utilisé par votre application.

      • Opérations sur le plan de contrôle : Les opérations telles que la création et la suppression de clés ne sont pas prises en charge pendant la mise à niveau. Elles reprendront automatiquement une fois la mise à niveau terminée.

      • Opérations sur le plan de données : Selon certaines architectures métier, il existe un risque d'interruption de service pendant la mise à niveau.

Prérequis

  • Vous avez acheté une machine cryptographique. Pour plus d'informations, consultez la section Acheter une machine cryptographique.

  • Achetez une instance ECS exécutant Windows et déployée dans le même VPC que l'instance HSM. Pour plus d'informations, consultez la section Démarrage rapide pour les instances ECS sous Windows.

    Remarque

    Cette instance ECS sert à installer l'outil de gestion HSM, et non à héberger votre application métier.

Étape 1 : Créer et activer un cluster

Un cluster se compose d'une instance HSM maître et de plusieurs instances HSM enfants. Toutes les instances HSM d'un cluster doivent se trouver dans le même VPC, mais elles peuvent appartenir aux mêmes sous-réseaux ou à des sous-réseaux différents.

Remarque

Si vous avez configuré les paramètres du cluster lors de l'achat d'une instance GVSM, Cloud Hardware Security Module crée automatiquement un cluster selon vos paramètres. Ignorez cette étape.

  1. Activez l'instance HSM maître.

    1. Accédez à la page VSMs de la console CloudHSM. Dans la barre de navigation supérieure, sélectionnez la région cible.

    2. Sur la page VSMs, repérez l'instance HSM que vous avez créée. Dans la colonne Actions, cliquez sur Enable.

    3. Dans la boîte de dialogue Configure HSM Instance, configurez l'instance HSM et cliquez sur OK. Une fois la configuration réussie, le Status de l'instance HSM passe à Enabled.

      Paramètre

      Description

      VPC ID

      Sélectionnez le VPC auquel l'instance HSM est associée.

      Important

      Ce VPC doit être identique à celui associé à votre instance ECS.

      VPC Subnet

      Sélectionnez le bloc CIDR du sous-réseau du VPC où réside l'instance HSM.

      Private IP Address

      Attribuez une adresse IP privée à l'instance HSM.

      Important
      • L'adresse IP privée doit appartenir au bloc CIDR du sous-réseau du VPC. Sinon, la configuration échouera.

      • Les adresses IP se terminant par 253, 254 ou 255 sont réservées par le système. Ne les utilisez pas.

      Configure HSM Whitelist

      Configurez la liste d'autorisation pour accéder à l'instance HSM. Vous pouvez saisir une adresse IP ou un bloc CIDR par ligne. Vous pouvez entrer jusqu'à 10 entrées.

      • Si aucune liste d'autorisation n'est configurée, toutes les adresses IP peuvent accéder à l'instance HSM.

      • Si une liste d'autorisation est configurée, seules les requêtes provenant des adresses IP figurant dans la liste sont autorisées. Les requêtes provenant d'autres adresses IP sont refusées.

      Important
      • Si vous créez un cluster HSM et configurez une liste d'autorisation pour ce cluster, la liste du cluster prévaut sur les listes d'autorisation des instances HSM individuelles du cluster.

        Par exemple, si la liste d'autorisation d'une instance HSM du cluster est 10.10.10.10 et celle du cluster est 172.16.0.1, vous ne pourrez accéder à l'instance HSM qu'à partir de 172.16.0.1.

      • Vous ne pouvez pas configurer 0.0.0.0/0 (pour autoriser toutes les adresses IP source).

        Pour des raisons de sécurité, nous vous déconseillons d'autoriser toutes les adresses IP source. Pour autoriser temporairement toutes les adresses IP source lors de tests, laissez la liste d'autorisation vide.

  2. Créez un cluster HSM.

    1. Repérez l'instance HSM maître et cliquez sur Create Cluster dans la colonne Actions.

    2. Dans le panneau Create and Activate Cluster, configurez le cluster.

      Paramètre

      Description

      Cluster Name

      Saisissez un nom personnalisé pour le cluster. Le nom doit être unique et ne pas dépasser 24 caractères.

      Configure Whitelist

      Spécifiez les adresses IP autorisées à accéder au cluster. Si aucune liste d'autorisation n'est configurée, toutes les adresses IP peuvent accéder au cluster. Si une liste est configurée, les requêtes provenant d'adresses IP hors liste sont refusées.

      Vous pouvez saisir une adresse IP ou un bloc CIDR par ligne. Vous pouvez entrer jusqu'à 10 entrées.

      Important
      • La liste d'autorisation du cluster prévaut sur les listes d'autorisation des instances HSM individuelles du cluster. Par exemple, si la liste d'autorisation d'une instance HSM du cluster est 10.10.10.10 et celle du cluster est 172.16.0.1, vous ne pourrez accéder à l'instance HSM qu'à partir de 172.16.0.1.

      • Vous ne pouvez pas configurer 0.0.0.0/0 (pour autoriser toutes les adresses IP source).

        Pour des raisons de sécurité, nous vous déconseillons d'autoriser toutes les adresses IP source. Pour autoriser temporairement toutes les adresses IP source lors de tests, laissez la liste d'autorisation vide.

      Specify vSwitches

      Sélectionnez les vSwitches dans les zones requises en fonction de vos besoins métier.

      Vous devez configurer au moins deux vSwitches pour créer et activer un cluster HSM avec succès.

    3. Initialisez l'instance HSM, puis cliquez sur Next.

      Remarque

      Vous ne pouvez activer le cluster que lorsque le statut de l'instance HSM maître est Initialized.

      Méthode d'initialisation

      Procédure

      Méthode 1 : Initialisation en un clic depuis la console CloudHSM

      Important

      L'initialisation en un clic n'est possible que si votre HSM est un HSM polyvalent (GVSM) et que vous n'avez pas besoin de la prise en charge UKEY.

      1. En bas du panneau Create and Activate Cluster, cliquez sur Initialize the master HSM with a few clicks.

      2. Dans la boîte de dialogue Initialize Instance, cliquez sur OK.

      L'initialisation devrait prendre entre 1 et 5 minutes. Veuillez patienter. Une fois l'initialisation terminée, cliquez sur l'icône update située à côté de Selected Master HSM:. Le statut passe à Initialized. Ne réinitialisez pas l'instance HSM maître dans cet état.

      Méthode 2 : Initialisation à l'aide de l'outil de gestion d'instance HSM

      Important

      L'outil de gestion client HSM fonctionne uniquement sous Windows.

      En bas du panneau Create and Activate Cluster, cliquez sur Télécharger l'outil de gestion d'instance HSM.

      Extrayez le package logiciel HSM. Ensuite, reportez-vous à la section Initialisation initiale du manuel d'utilisation inclus dans le package pour terminer l'initialisation.

    4. Suivez les instructions affichées à l'écran pour ajouter des instances HSM enfants au cluster, puis cliquez sur Complete.

(Facultatif) Étape 2 : Configurer l'authentification TLS mutuelle

Génération automatique

Seules les instances GVSM prennent en charge la génération automatique de certificats lors de l'achat d'un HSM. Dans ce scénario, le HSM génère automatiquement les certificats. Il vous suffit de configurer les certificats sur le SDK client, car le HSM les déploie automatiquement sur le serveur.

  1. Déployez les certificats sur le client.

    Téléchargez le certificat client depuis la console et déployez-le sur votre client.

    1. Sur la page des détails de l'instance HSM, cliquez sur Get Cluster Certificate. Le dossier téléchargé contient les fichiers suivants :

      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. Déployez les fichiers client.p12 et rootca.pem sur le client. Dans le fichier de configuration du client, vous devez également configurer les chemins d'accès aux fichiers client.p12 et rootca.pem, ainsi que la valeur de la phrase secrète (passphrase). Pour plus d'informations, reportez-vous à la documentation incluse dans le package que vous avez téléchargé depuis la console.

  2. Déployez le certificat sur le serveur.

    Le HSM déploie automatiquement le certificat sur l'instance HSM. Aucune action n'est requise.

Important

La durée de validité par défaut d'un certificat est de 10 ans. Avant l'expiration d'un certificat, le HSM génère automatiquement un nouveau certificat et effectue la rotation du certificat serveur. N'utilisez pas l'outil de gestion d'instance HSM pour créer un administrateur UKEY. Sinon, la rotation du certificat échouera.

Génération manuelle

GVSM prend en charge la génération automatique de certificats. Toutefois, si vous n'avez pas activé cette option lors de l'achat, suivez les étapes ci-dessous pour générer et déployer manuellement les certificats.

  1. Générez les certificats.

    1. Téléchargez l'outil de génération de certificats (dkms_cert_tool).

    2. Décompressez le fichier téléchargé et exécutez l'outil de génération de certificats pour créer un certificat d'autorité de certification (CA), un certificat client et un certificat serveur.

      Remarque
      • L'outil est indépendant de la plateforme et peut être exécuté sur un ordinateur local, une instance ECS ou tout autre environnement pris en charge.

      • Il s'agit d'un outil utilitaire fourni par Alibaba Cloud. Si vous êtes capable de générer vous-même les fichiers de certificat requis, vous pouvez ignorer cet outil.

      Windows

      • Méthode 1 : Dans le dossier Windows, double-cliquez sur le fichier hsm_certificate_generate.exe pour l'exécuter. Les fichiers de certificat sont générés dans le dossier certs.

        Remarque

        Cette méthode définit le mot de passe par défaut des fichiers de certificat PKCS12 (.p12) et des fichiers de clé privée CA (.key) sur 12345678. Pour spécifier un mot de passe personnalisé, utilisez la méthode 2.

      • Méthode 2 : Accédez au répertoire Windows et exécutez la commande suivante. Les fichiers de certificat sont générés dans le dossier certs.

        ./hsm_certificate_generate -dir ./certs -pswd 12345678

        Le paramètre -dir spécifie le répertoire de sortie. Le paramètre -pswd spécifie le mot de passe des fichiers de certificat PKCS12 (.p12) et des fichiers de clé privée CA (.key).

      Linux

      Accédez au répertoire Linux et exécutez la commande suivante. Les fichiers de certificat sont générés dans le dossier certs.

      ./hsm_certificate_generate -dir ./certs -pswd 12345678

      Le paramètre -dir spécifie le répertoire de sortie. Le paramètre -pswd spécifie le mot de passe des fichiers de certificat PKCS12 (.p12) et des fichiers de clé privée CA (.key).

      macOS

      Accédez au répertoire darwin et exécutez la commande suivante. Les fichiers de certificat sont générés dans le dossier certs.

      ./hsm_certificate_generate -dir ./certs -pswd 12345678

      Le paramètre -dir spécifie le répertoire de sortie. Le paramètre -pswd spécifie le mot de passe des fichiers de certificat PKCS12 (.p12) et des fichiers de clé privée CA (.key).

      Une fois la commande exécutée avec succès, les fichiers suivants sont générés dans le dossier 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. Déployez les certificats sur le client.

    Déployez les fichiers client.p12 et rootca.pem sur le client. Dans le fichier de configuration du client, vous devez également configurer les chemins d'accès aux fichiers client.p12 et rootca.pem, ainsi que le mot de passe spécifié lors de la génération des certificats. Pour plus d'informations, reportez-vous à la documentation incluse dans le package téléchargé depuis la console.

  3. Déployez les certificats sur le serveur.

    1. Installez l'outil de gestion des instances HSM sur une instance ECS.

      Important

      L'outil de gestion des instances HSM fonctionne uniquement sous Windows.

      1. Cliquez sur l'icône de téléchargement image dans la colonne Specifications du HSM principal pour télécharger l'outil de gestion des instances HSM.

      2. Décompressez le package HSM téléchargé, repérez le fichier PKIManager-X.X.X.X.exe et téléchargez-le sur l'instance ECS. Pour plus d'informations, consultez Transférer des fichiers vers une instance Windows.

    2. Utilisez l'outil de gestion des instances HSM pour configurer le HSM principal.

      1. Sur l'instance ECS, utilisez l'outil de gestion des instances HSM pour vous connecter au GVSM principal.

        1. Double-cliquez sur PKIManager-X.X.X.X.exe pour ouvrir l'outil de gestion des instances HSM. Sélectionnez System > TCP/IP Connection.

        2. Dans la boîte de dialogue TCP/IP Connection, saisissez l'IP address et le Port du HSM principal. Le port est 8020.

          Trouvez l'adresse IP du HSM principal dans la colonne IP Address de la liste des instances HSM. Le HSM principal est l'instance identifiée comme Master HSM dans la colonne Cluster.

        3. Dans la boîte de dialogue PKIManager, cliquez sur Connect. Dans la boîte de dialogue PKIManager qui s'affiche, cliquez sur OK, puis cliquez sur Login.

          Remarque

          Pour améliorer la sécurité, nous vous recommandons d'enregistrer un compte administrateur pour les connexions ultérieures. Pour plus d'informations, consultez les sections 2.1.3. Register Administrator et 2.1.2. Administrator Logon du GVSM User Management Manual, inclus avec l'outil de gestion des instances HSM.

      2. Utilisez l'outil de gestion des instances HSM pour effectuer les configurations suivantes.

        Parameter

        Actions

        Configurez le certificat client (client.pem)

        1. Sélectionnez Key Management > Client Management.

        2. Dans la boîte de dialogue Client Certificate Management, cliquez sur Import Certificate.

        3. Dans la boîte de dialogue Import Certificate, définissez Certificate Type sur International TLS Client RSA Certificate [pem], sélectionnez le certificat client (client.pem) généré par l'outil, puis cliquez sur Import.

        Configurez le certificat serveur (server.p12)

        1. Sélectionnez Instance Monitoring Information > Server Management.

        2. Dans la boîte de dialogue Server p12 Certificate Management, cliquez sur Import Certificate.

        3. Dans la boîte de dialogue Import Certificate, définissez Certificate Type sur International TLS Server RSA Certificate [p12], sélectionnez le certificat serveur (server.p12) généré par l'outil et saisissez le Certificate Password. Ce mot de passe correspond à celui que vous avez défini lors de la génération du certificat. Si vous n'en avez pas défini, la valeur par défaut est 12345678.

        4. Cliquez sur Import.

        Configurez les propriétés du port de l'appareil pour le GVSM principal

        1. Sélectionnez .

        2. Dans la boîte de dialogue Host Port Properties, configurez les paramètres suivants :

          • 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. Cliquez sur Reset.

        4. Cliquez sur Restart Now, puis sur OK.

Étape 3 : Synchroniser les données du cluster

  • Si le Cluster Type est Manual Cluster Synchronization : Vous devez synchroniser le cluster après sa création et son activation initiales, ou lorsque les données du HSM principal changent. La synchronisation n'est pas requise lors de la mise à l'échelle horizontale du cluster.

  • Si le Cluster Type est Automatic Cluster Synchronization : La synchronisation est automatique. Le HSM principal synchronise automatiquement les nouvelles clés, les certificats SSL configurés et les informations utilisateur vers les HSM enfants.

Avertissement

La synchronisation du cluster prend environ 5 minutes. Effectuez cette opération pendant les heures creuses pour éviter toute interruption de service.

  1. Sur la page VSMs, recherchez l'instance HSM principale cible. Dans la colonne cluster synchronization method de la liste des instances, vérifiez le type de synchronisation (manuel ou automatique).

    Si le type de cluster est Manual Cluster Synchronization, vous devez synchroniser le cluster.

  2. Dans la colonne Actions , cliquez sur Synchronize Cluster. Dans la boîte de dialogue qui s'affiche, cliquez à nouveau sur Synchronize Cluster.

Étape 4 : Créer et utiliser une clé de chiffrement

Le package logiciel HSM inclut le guide du développeur HSM et des programmes de test SDK. Vous pouvez utiliser le guide du développeur pour appeler les opérations API et gérer votre instance HSM.

Remarque

Vous pouvez télécharger le package logiciel HSM sur la page VSMs de la console CloudHSM. Recherchez l'instance HSM cible, cliquez sur la colonne Specifications, puis cliquez sur Download HSM instance management tool. Extrayez le fichier téléchargé pour obtenir le package logiciel HSM.

Par exemple, pour un HSM polyvalent (GVSM), localisez le cas de test APITest.java dans le répertoire extrait Alibaba CloudHSM GVSM Software Package>SDK>JAVA>Server HSM Interface Documentation>Test Demo. Vous pouvez utiliser ce cas de test pour tester l'instance HSM. Le code suivant fournit un exemple :

Remarque

Remplacez l’adresse IP (192.168.XX.XX) dans le cas de test par l’adresse IP privée attribuée à votre instance 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("669C1CEDDAFA267CC5D727EA727558B5");
    byte[] verifyValue = Forms.hexStringToByteArray("BD8596C22E5A4D88");

    byte[] symmetricKey1 = Forms.hexStringToByteArray("93EF12C95813586FEC3EFDBC7B37642D");
    byte[] verifyValue1 = Forms.hexStringToByteArray("78306FD68851B8E6");
    /**
     * Ciphertext of session key encrypted by LMK
     */
    byte[] symmetricKeyKEK = Forms.hexStringToByteArray("2E80A42018F186BCCBCF639F644629E8");
    /**
     * Verification value of session key
     */
    byte[] verifyValueMAC = Forms.hexStringToByteArray("734D092CD8C23E38");
    /**
     * Ciphertext protected by protection key
     */
    byte[] protectionKey = Forms.hexStringToByteArray("2EACE685C5EB2638D1208742F3BE60CD44210B43C894A77C");
    /**
     * MAC of ciphertext protected by protection key
     */
    byte[] protectionMAC = Forms.hexStringToByteArray("0CB8702D41CBE487");

    /**
     * RSA public key in DER encoding
     */
    byte[] publicKeyRSA = Forms.hexStringToByteArray("308186028180E14CAAFFCEC6D014457D7CA3E943DBABA1299BDBC17690C8E70F7BFA10EA02450805DA4C6CDC38BFBF1349C95B81A88177BA31C08E366EF965CA41EB36A2DACE611B80A752615A094B8291AAB6F8BB3A5894E72842371F34FA04C10DF42C2FEA95C51B9D49BE8B795E10474954FE01BAAC63532520069465FA62EDB266AADEBB020103");
    /**
     * RSA private key encrypted by LMK
     */
    byte[] privateKeyRSA = Forms.hexStringToByteArray("000202703D0652C7027B7D94B45A896646A9DC7CA89825FB12121B3CC00E37BE933055D5C00E37BE933055D54718ADDAA677519BD9C054CA249B43888FE000B8AAC33BA87A2C326985704335EA54D7F171CABCAD5531B3ADF33255A24075EFFF62691D4375E6280A9442CA36AA46AC59FAB16D9A9A7A283440BB14BAB1E78DBE887AE93A2C94C547779190D3FA801379BA948537281EFEFE567FD963E5D6E5D442D908A68BB6E26F3776EA30B1136A3804844035E26308E9B44BE154E1D09382E5A72BD711A6936373A8C32B62AF88134690C30D8B5505004F3BA01D11D0D791C8FF53D0E0786ED192CF1105FCF82160921EEF23E7BD72F13587B316BD9A771CEABBD0186B45E09C86E718AD4E5444EFFE747FE0C39E85D6190F3347656E72F486C321D5EA0D42127149C99F4F799A31F91E5826B74FF720A6E3CC2BCBBF645DD3D4A6A7D0BC953B4CFEE4E0D2BABFD606292F9F2395464484C306FBD60E4DD293E5F56C60BF1482A05775F0EEBAFBF9B70841DDDCFC974DD4D87E54D6A6A7A1A585EF0F42B0763D5DD7B5ECA83AFE610C26C9EF559B7883AC4716240BDFDC91C6EA19A0C01BB9C053F2A9C7EBCAE7D0AA8FB0DB88EFCF9C50A134E04649DAFF21D724E5C3CC043DE950C2CF246392DC4CA592D28C5A959BEB80B304E3BD949AD33178C06209FE6EB7130A381DFFD80F916AE0E0DD8FFDD9C8C9895BC483993D6011754FAD3C9F83A59C31F47810F8B2B22E5F25EF13671DFF34ECB65DE71D5B13DC5880595BC60B18D4711AE4613C739E2A48B516F6233E9AA9834075CE58975907F06FBA3B85C97E2E90B60BFEF0F23527E770798B571BC7CE29B67920538D509C58B1D8F966AF7E5321CDB2386164844D2BCB");
    /**
     * RSA private key encrypted by protection key
     */
    byte[] privateKeyRSAKEK = Forms.hexStringToByteArray("6B2FB2BCC75604ABF5761FFA1027FF16324E3038B580C9F63AD3B57BD89059D5799974B4E5E9453763D94E682C629C4617C4E5393E9DDBFB0CFA2A4EA0E832F5C6A30F3EE63C327F6E044F3CB630D0C7DD96D93581835AA529797EB11CF3535650E431181717FDD1D7BBD9FB675FB027134BBF7F10F65245D9A82251A9171DAA439C175895904A2BB74F31BD94FF550023F6245C01DF83B2FCEDDF241307DDC831162AD2203BA3EBC4FD99EAE93C3208F16B0AAF85146ACE5FF06B11D7C81215708AA5C2651D380573F0EDA0984A73F5CE38E21541D50AACF5C5BCD42B6C94D064065ECAED4684E7A40C15904A73A801F2697AF6F3E32C3D7E156A1D1085CA32C7A002FA4AEAD439271E6E5904FC9AC3E65EEBAC51399F60DF3C61AF82BDA04D5E28B587382F8EB751096BC970B7A7DF26D997324F2D002D01A4C8F77C37BB65DBD1DED3B4545323DAE9489A08351507224574A2206FA7EAF8EF0A120D23D6B34E84645E95C3B58187BC91B8F6C04EF15075D6AF38B7E7DD77F6D2B8E66F11960C401BCE56BB4C157DAA26234678A37ACCFC7729CB5018449F7B6A23C0B16CA0B6A5FBE9FC7C8F9A3801A4159822DDDE8D9D7B7233CC3F77E7391DE720A2BFC69F6B938B565A28EBC6B4B665C553A9E1F32A17CC66CB8A2D7FE3EF6CB5112815D562F18EB34987B57DCFF064C7C24E97C3DCF3FD9BD50B351A2DD7CF03DA1F2DDA7A1BD2013C8339AFC4D22C135C49859C9C4CA4C9F730D2EE09A779D244C13FB5C3835F2FF04EE12537B01795D0ABE2D9695208542DC2FF8161AFD6F774E8D524B1DE6096530783");
    /**
     * RSA MAC
     */
    byte[] privateKeyRSAKEKMAC = Forms.hexStringToByteArray("701A4D3572D09760");

    /**
     * RSA private key encrypted by KEK
     */
    byte[] privateKeyKEK = Forms.hexStringToByteArray("7A833CC0FAFBA6EC063DF4827B8FD91FF4B9A69FB0C44FD972173C09E9E56F6918730269561A497403F9478D7BB64FE527F748AF86E3CE7C762A92A07D9C8BBCE0731F9F07C5889AE8B0FF7A31FCCCD76CD20A1AFB95B4D12BEA5DB84059B9CB1FB8F778989FD11CB7F8D84D812190F2EE0F479A4020FEB32C634528FBF660B3AD5AB0BA497B932902294C28B02807DC1AC28E8213BA39582AA677050F9E9256879935484B49D1CD115B39C0A41AE2B18263F78EA4CB781C931EA3C638097D1A7D4245C30ADA1B7C7793FD798EFAB86C3A91F573D4D2ECFA188588A31983320052901CC5AECAEDC5296506442546614B3DFDECA958B5E3A659EC8B52C5818E22F8E50C216264B560073F47E07B07E38CEF2DF4F6E4A458665FD31E6AA1C7B2FB5C4A15405C09E5F2B814FB260C1FFC560A2B6F3370C9DD96BA0A15BA72AB3622FE172F847D60383307C936246B977665CAB5E68EFA6E4EE1F9008FAE7A90D4A2A10AB70969714041707D4AD05F96027FA62FC916C81BA3C8601F7FF3115F17A117AD1B9A3D8438A731707A2D3B65BDA3846D293939CF94EBCC681E8115400454CF2CEA3769A614A9098CA62356B131EA22F4D634B56B365D7A430A3703967B50C6FCA93D11BD5ACC60048B5E00EAF353723D6DE878F8E5E4EA03BD43DF7229E6146DE307F9CC51B7F359F07042500AB5C24EE6F80EA8E1E50961BEC347949E5DD1918027A17196BABEE5790332B76D4AFFCD19143D7462177CDF72DE09BE64320C330090C1C6F1B059E81E02C312ABFC68F454D11EFCF1E0609584D06B09A08599D7A0BF5D63BB9F");
    /**
     * RSA private key MAC encrypted by KEK
     */
    byte[] privateKeyRSAMAC = Forms.hexStringToByteArray("06E5A11D968C36DE");

    /**
     * SM2 private key encrypted by KEK
     */
    byte[] privateKeySM2KEK = Forms.hexStringToByteArray("D3C5F579038C8BF3469879DD7F79C2E1B7FF47D7F2D5EFF5B01EFCE51C081D8067E06C0290F8EF6044210B43C894A77C");
    /**
     * SM2 private key MAC encrypted by KEK
     */
    byte[] privateKeySM2MAC = Forms.hexStringToByteArray("83E413861F0C0D15");


    /**
     * SM2 public key in DER encoding
     */
    byte[] privateKeySM2DER = Forms.hexStringToByteArray("3059301306072A8648CE3D020106082A811CCF5501822D03420004B33D8A2F9E1E1FCA2E8CECCFFB166F52CC2ED0589C25464D0EF85DC87E0537DC16C0D542A53790967A1368B7084F6EFED51FC848D1E3B5370A99BDCB64D17C2F");
    /**
     * SM2 private key encrypted by LMK
     */
    byte[] privateKeySM2 = Forms.hexStringToByteArray("66C9DDB0D6400EE059474F5C7339A296D5AA88F02AF031174F212EB6538C21908C4F5CA6457B435F");
    /**
     * SM2 private key protected by protection key
     */
    byte[] privateKeyKEKSM2 = Forms.hexStringToByteArray("D3C5F579038C8BF3A1624E7DC142A863240A42642337355921C70A7547001B21A0C59D4E0800F99644210B43C894A77C");
    /**
     * SM2 MAC
     */
    byte[] privateKeyKEKSM2MAC = Forms.hexStringToByteArray("B9827812C2E18232");

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

    /**
     * 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("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");

    /**
     * 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("B36847D6E86EAB69E4EEB65558A2626C"),
                TACryptConst.KEY_ALG_SM4, Forms.hexStringToByteArray("713CA557C1FE2AAB"), 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("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 result: " + 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 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("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("Tag: " + 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");
    /**
     * RSA private key encrypted by LMK
     */
    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");


    /**
     * Encrypt and decrypt 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));

    }

    /**
     * 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("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 result: " + 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 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("BFA03DB9BD0A4DE4809B59B04BF663E8E541B0CF0017E0337342B8F7CDEB210C86429D87A51A7E2B4ED760C4BB49A1AD1DE0353B3204D39C8F6FF9DB789C8DEDCDD84012DDB532F3E4554F0C85DCEF1C7241C98888F9CC57D04E902ABD2F422884235FD9E0A80116771AC436ED1EDE46CF272FD1DD4D3A5174D2D178D9A21F3D"));
        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("5C59EBCD0A48E51038853E490C76AD83122964E3AA3EAB660966F67DE56722D02E3B477D257BDDB90CA2F901254544933BD0852BCF6E466CE91813AACF8A4AD2C65F2B78888AE249A948BCDCF3E2D0CDCC70DC3BA9445D3237B6D56A701D17E95576AD4FCF0A1D20DC5A0AAB878DADC04903CCE5B3D06219FDB4497905FBEA9E"), "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("20D90A83A4654FB89AD97E7FF9B178BAA58E12CE8E5C16DE0371B374F76DEFA5");

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

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

        boolean b = api.pubKeyVerify(0x0007, Forms.hexStringToByteArray("3059301306072A8648CE3D020106082A811CCF5501822D03420004E6BFD64E16F9FDE831FC2483A703F32D2925C126C435CF4FF0BC0187351E34F627E3421ACA51CB99CD452FA11B5B6BBB4AA31C2DBCC696FC57C8F9F8F01948FE"), 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("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. 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("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 result: " + Forms.byteToHexString(bytes));

        byte[] bytes1 = api.SM2PriKeyDec(888, bytes);
        System.out.println("Decryption result: " + 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");


    /**
     * 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("E9C17D82604F992BB3AB8FE0F766441DACC05EB779D1D1CC9C5FEFF671739A87274713242CBBA04161C3994EA264C30D82BB6DAF8E688D3BADC8768A18226D8EAEB984E5EA739C2E8792921F02AA612F5AB732FACEC8316B880499E6E70260333E9F29CEBCF3F8E10C151F79445276F6"));
        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("20D90A83A4654FB89AD97E7FF9B178BAA58E12CE8E5C16DE0371B374F76DEFA5"));
        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("20D90A83A4654FB89AD97E7FF9B178BAA58E12CE8E5C16DE0371B374F76DEFA5"), 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("9A9161F87BCBD3E9BC8866B8706E8F75B682DA2712E7E32A5D0E4867700D8233284BF4EA98E352BE74817D240D92347F969809BA54626192102086000756E2CFD98A3CC8923513B3BF72FA33B39CB999E15613440F2DAD9AE786E3D73349D78FA7915B3CB633EFD9A88E638D93297934"), "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("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 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("7C78EAFE26890D48096AB8141B1D5890BF1921DD899664A7E224C05DC30A7392CAA4BB0E518CBE5721DAC409F85B736A1DAEC40FAB410CA007C114574BAEAD1227560F1D2AE148884814872F0305F821F7245329ADED546F44C52C8F49EAC46647650D9B983224E9E005CFCAA88B019D"));

        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("6149EE02F14EE6420BC2B462003CCCE2413CE4911F5C36F720DD123DA9A432EEA17C534A8662F9B1E813C8A5FA929E9A06AC2CFDB2AAB68E66A58C9A4E0C76AF5126785160A665C23F22309ECBF48B8BAFA8BE9D41F334852649D5D204937A4EDA3B0A9B1A7B3054E1D9AE3BA2173028C3A0E2CE400522E06DCBAB44213A85B668764EC33EE71D372F5A904252A539AA"));

        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("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("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("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("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("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("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("566F7CE9E52CCA87FF02D7A7667E3F7C"), // MAC value used for GCM mode decryption
                Forms.hexStringToByteArray("DA23B170CEA626F4C772B3F2AE2CCA97"),// Key ciphertext
                Forms.hexStringToByteArray("7192C7C6F1EAAB72BFE8A51BA9256C87"),  // GCM tags
                6, // Protection key encryption mode
                new byte[16],// Protection key IV
                new byte[16], // Authentication data AAD
                Forms.hexStringToByteArray("8DE9DFEE4BE10827C1C08A38BDD8A92F"), // Tags
                5,// Protection key encryption padding mode
                12, // Session key type
                7,  // Algorithm identifier for session CMK asymmetric key
                Forms.hexStringToByteArray("420B9FE23A2B162F3C4574919E9EBD44040F7C5338CDE0C8311C88495D2F3604E9AFC80B18990EF5C6F3A93AB80B41458311EA9F9A1890752427E24F5062AD4A"),// 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("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 agreement result: " + Forms.byteToHexString(bytes));
//        byte[] bytes1 = api.agreementKey(0x0007, 3, 6, Forms.hexStringToByte("3059301306072A8648CE3D020106082A811CCF5501822D03420004AC3DC24CE9883F26278E97A04D5409AA2A94D57FCE84E7630F4E46CFBED036A6B89791DF9A3DF50D67073CF246FC3406337B50E987F2AC3943D2FF5C7ECAD197"));
//        System.out.println("0x000agreement result: " + Forms.byteToHexString(bytes1));
//        byte[] bytes2 = api.agreementKey(0x0007, 3, Forms.hexStringToByte("E59842CEEC68775E6AD78C7276AD2ADE0E27405E8B60FE02F7DF23E08F7F6B8D"), Forms.hexStringToByte("3059301306072A8648CE3D020106082A811CCF5501822D034200040EF69FB0C3739C3FDC16499AB96985EAD5CBEB4178A985A8FC10145979C315A5519C50B972EB19EA77A6AB74F345688B8458F1015885FCE435A4E3679DE0E34F"));
//        System.out.println("0x0007 external private key plaintext agreement result: " + Forms.byteToHexString(bytes2));
//        byte[] bytes3 = api.agreementKey(0x039B, 0, 5, Forms.hexStringToByte("304A301406072A8648CE3D020106092B24030302080101030332000448D5FAD9CD434E60EF661B65289867B395461D868F7D34BABEEB5A20F7DF5543091DD740DD3780B5EBEF631615571ADC"));
//        System.out.println("0x039B agreement result: " + Forms.byteToHexString(bytes3));
        byte[] bytesA = api.agreementKey(0x019F, 3, 13, Forms.hexStringToByte("3059301306072A8648CE3D020106082A8648CE3D030107034200048D912010F06A7D4B5062F6DC192EEDC8C88FCB2D2830AB8573F0FB30532041D0788F227558F1DA9AC8CDF5E7FA72C9931FA90EE06B3CE07E13A7845A05BA7C73"));
        System.out.println(bytesA.length);
        System.out.println("0x0007 agreement result: " + Forms.byteToHexString(bytesA));
        byte[] bytesB = api.agreementKey(0x019F, 3, 15, Forms.hexStringToByte("3059301306072A8648CE3D020106082A8648CE3D0301070342000481022BD6C8FFBBD2EC4B5A53F7000920D1581C0BC17B4C781627894B0979FFCA115C85C7AB0964E53872FBF0511FF6E7661CF94B7D82C8BF78D211B1FA73F271"));
        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"));

    }


}