すべてのプロダクト
Search
ドキュメントセンター

Key Management Service:HSM インスタンスクラスターの使用

最終更新日:Oct 16, 2025

Cloud Hardware Security Module (CloudHSM) は、同じリージョン内の異なるゾーンにある HSM インスタンスをグループ化できる HSM インスタンスクラスター機能を提供します。これらのインスタンスが同じビジネスに使用される場合、アプリケーションはポーリングアルゴリズムを使用して、同じキーで暗号化操作を実行する HSM を選択できます。このアーキテクチャは、業務継続性、暗号化計算の高可用性、負荷分散、およびアプリケーションの水平スケーリングを提供します。このトピックでは、HSM インスタンスクラスターの使用方法について説明します。

説明

KMS ハードウェアキー管理インスタンス用の HSM クラスターの作成方法の詳細については、「KMS ハードウェアキー管理インスタンス用の HSM クラスターを設定する」をご参照ください。

クラスター同期メソッド

クラスター同期は、キー、設定済みの SSL 証明書、ユーザー情報などのデータをマスター HSM から子 HSM にコピーします。同期メソッドは、HSM を購入した時期によって異なります。

  • 2025 年 1 月 9 日以降に購入した HSM の場合: クラスターを作成すると、同期メソッドはデフォルトで自動同期になります。マスター HSM のデータが変更された後、クラスターデータを手動で同期する必要はありません。

  • 2025 年 1 月 9 日より前に購入した HSM の場合: クラスターを作成すると、同期メソッドはデフォルトで手動同期になります。マスター HSM のデータが変更された後、クラスターを手動で同期する必要があります。クラスターを自動同期にアップグレードするには、お問い合わせください。

    警告

    アップグレードはロールバックできません。アップグレード中に次のリスクが発生する可能性があります。オフピーク時にアップグレードを実行することをお勧めします。

    • KMS ハードウェアキー管理インスタンスのユーザーの場合:

      • コントロールプレーン操作: キーの作成や削除などの操作は、アップグレード中はサポートされません。これらの操作は、アップグレードが完了すると自動的に再開されます。

      • データプレーン操作: 暗号化や復号などの操作は、アップグレード中に影響を受けません。

    • その他のユーザーの場合: アプリケーションが依存する HSM ソフトウェア開発キット (SDK) のバージョンをアップグレードする必要があります。

      • コントロールプレーン操作: キーの作成や削除などの操作は、アップグレード中はサポートされません。これらの操作は、アップグレードが完了すると自動的に再開されます。

      • データプレーン操作: 一部のビジネスアーキテクチャでは、アップグレード中にサービスが中断されるリスクがあります。

前提条件

  • ハードウェアセキュリティモジュール (HSM) を購入済みであること。詳細については、「HSM インスタンスの購入」をご参照ください。

  • Windows Elastic Compute Service (ECS) インスタンスを購入済みであること。ECS インスタンスと HSM は同じ VPC に存在します。詳細については、「Windows インスタンスの概要」をご参照ください。

    説明

    ECS インスタンスは、ビジネスサーバーとしてではなく、HSM 管理ツールをインストールするために使用されます。

ステップ 1: クラスターの作成とアクティベート

クラスターは、1 つのマスター HSM と複数の子 HSM で構成されます。クラスター内のすべての HSM は同じ VPC を共有する必要がありますが、同じまたは異なるサブネットにデプロイできます。

説明

GVSM インスタンスを購入したときにクラスター情報を設定した場合、CloudHSM は自動的にクラスターを作成します。このステップはスキップできます。

  1. マスター HSM インスタンスを有効にします。

    1. Cloud Hardware Security Module コンソールの [セキュリティ監査] ページに移動します。トップナビゲーションバーで、リージョンを選択します。

    2. VSMs ページで、作成した HSM を見つけ、操作 列の Enable をクリックします。

  2. HSM クラスターを作成します。

    1. マスター HSM インスタンスを見つけ、[操作] 列の [クラスターの作成] をクリックします。

    2. Create and Activate Cluster パネルで、クラスターを作成します。

      パラメーター

      説明

      クラスター名

      クラスターの名前。名前は一意である必要があり、長さは 24 文字を超えることはできません。

      Configure Whitelist

      クラスターへのアクセスが許可されている IP アドレスの範囲。ホワイトリストを設定しない場合、すべての IP アドレスがクラスターにアクセスできます。ホワイトリストを設定した場合、ホワイトリスト内の IP アドレスのみがクラスターにアクセスできます。

      IP アドレスと CIDR ブロックがサポートされています。各行に 1 つの IP アドレスまたは 1 つの CIDR ブロックを指定できます。合計で最大 10 行まで指定できます。

      重要
      • クラスターのホワイトリストは、クラスター内の HSM のホワイトリストよりも優先度が高くなります。たとえば、HSM のホワイトリストに 10.10.10.10 を追加し、HSM を含むクラスターのホワイトリストに 172.16.0.1 を追加した場合、HSM には 172.16.0.1 からのみアクセスできます。

      • 0.0.0.0/0 のホワイトリスト設定はサポートされていません。0.0.0.0/0 を入力すると、すべての IP アドレスからのリクエストが許可されます。

        セキュリティ上の理由から、すべての IP アドレスからのリクエストを許可しないことをお勧めします。すべての IP アドレスからのリクエストを許可する必要がある場合は、ホワイトリストを設定しないでください。

      Specify vSwitches

      ビジネス要件に基づいて選択する必要がある vSwitch。

      HSM クラスターでは、クラスターを作成してアクティベートするために、少なくとも 2 つの vSwitch を設定する必要があります。

    3. HSM インスタンスを初期化し、次へ をクリックします。

      マスター HSM のステータスが 初期化 の場合にのみ、クラスターをアクティベートできます。マスター HSM を初期化するには、次の操作を実行します。

    4. ページ上のプロンプトに従って子 HSM をクラスターに追加し、Complete をクリックします。

(オプション) ステップ 2: 証明書の生成と相互 TLS 認証の設定

シナリオ 1: HSM が購入時に証明書を自動的に生成する

GVSM インスタンスのみが、購入時の自動証明書生成をサポートしています。このシナリオでは、CloudHSM が自動的に証明書を生成します。CloudHSM はサーバー側の HSM に証明書を自動的にデプロイするため、クライアント SDK で証明書を設定するだけで済みます。

  1. クライアントに証明書をデプロイします。

    コンソールからクライアント証明書をダウンロードし、クライアントにデプロイします。

    1. HSM の詳細ページで、Get Cluster Certificate をクリックします。 ダウンロードしたフォルダには、次のファイルが含まれています。

      certs/
      ├── client.p12 (クライアント証明書と秘密鍵を含む PKCS12 形式のクライアント証明書)
      ├── client.pem (PEM 形式のクライアント証明書)
      ├── rootca.key (CA 秘密鍵)
      ├── rootca.pem (PEM 形式の CA 証明書)
      ├── server.p12 (PKCS12 形式のサーバー証明書)
      └── passphrase (.p12 サフィックスを持つ PKCS12 形式の証明書のパスワード)
    2. client.p12 と rootca.pem をクライアントにデプロイします。クライアント設定ファイルで、client.p12 と rootca.pem のファイルパス、およびパスフレーズも設定する必要があります。詳細については、コンソールからダウンロードしたパッケージ内のドキュメントをご参照ください。

  2. サーバーに証明書をデプロイします。

    CloudHSM は自動的に証明書を HSM にデプロイします。ユーザー側での操作は不要です。

重要

証明書の有効期間はデフォルトで 10 年です。有効期限が切れる前に、CloudHSM は自動的に新しい証明書を生成し、サーバー側の証明書をローテーションします。HSM 管理ツールを使用して UKEY 管理者を作成しないことをお勧めします。これにより、証明書のローテーションが失敗する原因となります。

シナリオ 2: HSM が購入時に証明書を自動的に生成しない

GVSM は CloudHSM による自動証明書生成をサポートしています。ただし、購入時にこのオプションを有効にしなかった場合は、これらの手順に従って証明書を手動で生成およびデプロイします。

  1. 証明書を生成します。

    1. 証明書生成ツール (dkms_cert_tool) をダウンロードします

    2. ダウンロードしたファイルを解凍し、証明書生成ツールを実行して CA 証明書、クライアント証明書、およびサーバー証明書を生成します。

      説明
      • ツールの動作環境に制限はありません。ローカルコンピューター、ECS インスタンス、またはツールの実行条件を満たすその他の環境で実行できます。

      • Alibaba Cloud はこのツールを補助ツールとして提供しています。これらの証明書ファイルを生成する技術力がある場合は、このツールを使用する必要はありません。

      Windows

      • 方法 1: Windows フォルダで、hsm_certificate_generate.exe ファイルをダブルクリックしてツールを実行します。証明書ファイルは certs フォルダに生成されます。

        説明

        この方法では、PKCS12 証明書ファイル (.p12) と CA 秘密鍵ファイル (.key) のパスワードはデフォルト値の 12345678 です。パスワードを指定するには、方法 2 を使用します。

      • 方法 2: Windows フォルダを含むディレクトリに切り替え、次のコマンドを実行します。証明書ファイルは certs フォルダに生成されます。

        ./hsm_certificate_generate -dir ./certs -pswd 12345678

        -dir は、生成された証明書ファイルを保存するパスを指定します。-pswd は、生成された PKCS12 証明書ファイル (.p12) と CA 秘密鍵ファイル (.key) のパスワードを指定します。

      Linux

      Linux フォルダを含むディレクトリに切り替え、次のコマンドを実行します。証明書ファイルは certs フォルダに生成されます。

      ./hsm_certificate_generate -dir ./certs -pswd 12345678

      -dir は、生成された証明書ファイルを保存するパスを指定します。-pswd は、生成された PKCS12 証明書ファイル (.p12) と CA 秘密鍵ファイル (.key) のパスワードを指定します。

      macOS

      darwin フォルダを含むディレクトリに切り替え、次のコマンドを実行します。証明書ファイルは certs フォルダに生成されます。

      ./hsm_certificate_generate -dir ./certs -pswd 12345678

      -dir は、生成された証明書ファイルを保存するパスを指定します。-pswd は、生成された PKCS12 証明書ファイル (.p12) と CA 秘密鍵ファイル (.key) のパスワードを指定します。

      コマンドが正常に実行されると、certs フォルダに次のファイルが生成されます。

      certs/
      ├── client.p12 (クライアント証明書と秘密鍵を含む PKCS12 形式のクライアント証明書)
      ├── client.pem (PEM 形式のクライアント証明書)
      ├── rootca.key (CA 秘密鍵)
      ├── rootca.pem (PEM 形式の CA 証明書)
      ├── server.p12 (PKCS12 形式のサーバー証明書)
      └── server.pem (PEM 形式のサーバー証明書)
  2. クライアントに証明書をデプロイします。

    client.p12 と rootca.pem をクライアントにデプロイします。クライアント設定ファイルで、client.p12 と rootca.pem のファイルパス、および証明書を生成したときに指定したパスワードも設定する必要があります。詳細については、コンソールからダウンロードしたパッケージ内のドキュメントをご参照ください。

  3. サーバーに証明書をデプロイします。

    1. ECS インスタンスに HSM インスタンス管理ツールをインストールします。

      重要

      HSM インスタンス管理ツールは Windows でのみ実行されます。

      1. マスター HSM インスタンスの [仕様] 列にあるダウンロードアイコン image をクリックして、HSM インスタンス管理ツールをダウンロードします。image

      2. ダウンロードした HSM パッケージを解凍し、PKIManager-X.X.X.X.exe を見つけて ECS インスタンスにアップロードします。詳細については、「リモートデスクトップ接続を使用して Windows インスタンスにファイルを転送する」をご参照ください。

    2. HSM インスタンス管理ツールを使用して、マスター HSM を設定します。

      1. ECS インスタンス上の HSM インスタンス管理ツールを使用して、マスター GVSM に接続します。

        1. PKIManager-X.X.X.X.exe をダブルクリックして HSM インスタンス管理ツールを開きます。[システム] > [TCP/IP 接続] を選択します。

        2. [TCP/IP 接続] ダイアログボックスで、マスター HSM の [IP アドレス][ポート] を入力します。ポートは 8020 です。

          IP アドレスはコンソールで確認できます。image

        3. [接続] をクリックします。表示される PKIManager ダイアログボックスで、[OK] をクリックし、[ログオン] をクリックします。

          説明

          正常にログインした後、セキュリティを強化するために管理者アカウントを登録し、それを使用してログインすることをお勧めします。詳細については、HSM インスタンス管理ツールに含まれている [GVSM ユーザー管理マニュアル][2.1.3. 管理者の登録] および [2.1.2. 管理者のログオン] をご参照ください。

      2. HSM インスタンス管理ツールを使用して、次の設定を完了します。

        設定項目

        手順

        クライアント証明書 (client.pem) の設定

        1. [キー管理] > [クライアント管理] を選択します。

        2. [クライアント証明書管理] ダイアログボックスで、[証明書のインポート] をクリックします。

        3. [証明書のインポート] ダイアログボックスで、[証明書タイプ][国際 TLS クライアント RSA 証明書 [pem]] に設定します。証明書生成ツールで生成されたクライアント証明書 (client.pem) を選択し、[インポート] をクリックします。

        サーバー証明書 (server.p12) の設定

        1. [キー管理] > [サーバー管理] を選択します。

        2. [サーバー P12 証明書管理] ダイアログボックスで、[証明書のインポート] をクリックします。

        3. [証明書のインポート] ダイアログボックスで、[証明書タイプ][国際 TLS サーバー RSA 証明書 [p12]] に設定します。証明書生成ツールで生成されたサーバー証明書 (server.p12) を選択し、[証明書パスワード] (証明書ファイルを生成したときに設定したパスワード。設定していない場合は、デフォルトは 12345678) を入力します。

        4. [インポート] をクリックします。

        マスター HSM の GVSM デバイスポートプロパティの設定

        1. [デバイス管理] > [ホストポートプロパティ] を選択します。

        2. [ホストポートプロパティ] ダイアログボックスで、次のパラメーターを設定します。

          • ソケットキープアライブ時間: 60。

          • メッセージヘッダー長: 0。

          • メッセージエンコーディング形式: ASCII。

          • ホストサービス通信モード: 双方向通信。

          • ホストサービス通信プロトコル: TLSv1.2。

        3. [リセット] をクリックします。

        4. [今すぐ再起動] をクリックし、[OK] をクリックします。

ステップ 3: クラスターデータの同期

  • [クラスタータイプ][手動同期クラスター] の場合: 初めて作成してアクティベートした後、またはマスター HSM のデータが変更された後にクラスターを同期する必要があります。スケールアウト時にはクラスターを同期する必要はありません。

  • [クラスタータイプ][自動同期クラスター] の場合: クラスターを同期する必要はありません。マスター HSM 上の新しいキー、設定済みの SSL 証明書、およびユーザー情報は、子 HSM に自動的に同期されます。

警告

クラスターの同期には約 5 分かかります。ビジネスに影響を与えないように、オフピーク時に同期を実行してください。

  1. インスタンス ページで、ターゲットのマスター HSM インスタンスを見つけ、クラスターの同期メソッドを確認します。

    クラスタータイプが手動同期クラスターの場合は、同期を実行します。

    image

  2. 操作 列で、同期クラスター をクリックします。表示されるダイアログボックスで、同期クラスター を再度クリックします。

ステップ 4: 暗号化と復号のためのキーの作成と使用

HSM ソフトウェアパッケージには、開発者ガイドと SDK テストプログラムが含まれています。開発者ガイドに基づいて API 操作を呼び出して HSM を使用できます。

説明

クラウドハードウェアセキュリティモジュールコンソールの [VSMs] ページに移動し、目的の HSM を見つけ、[仕様] 列の横にある image をクリックしてパッケージをダウンロードし、パッケージを解凍して HSM ソフトウェアパッケージを取得します。

この例では、GVSM が使用されます。パッケージを解凍し、Alibaba Cloud GVSM ソフトウェアパッケージ > SDK > JAVA > サーバー HSM インターフェイスマテリアル > テストデモディレクトリ > テストケース APITest.java を選択し、テストケースを使用して GVSM をテストします。

サンプルコード

説明

例の 192.168.XX.XX を HSM に割り当てられたプライベート IP アドレスに置き換えてください。

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);

    /**
     * ローカルマスターキー (LMK) によって暗号化された対称キー
     */
    byte[] symmetricKey = Forms.hexStringToByteArray("669C1CEDDAFA267CC5D727EA727558B5");
    byte[] verifyValue = Forms.hexStringToByteArray("BD8596C22E5A4D88");

    byte[] symmetricKey1 = Forms.hexStringToByteArray("93EF12C95813586FEC3EFDBC7B37642D");
    byte[] verifyValue1 = Forms.hexStringToByteArray("78306FD68851B8E6");
    /**
     * LMK によって暗号化されたセッションキーの暗号文
     */
    byte[] symmetricKeyKEK = Forms.hexStringToByteArray("2E80A42018F186BCCBCF639F644629E8");
    /**
     * セッションキーのチェックサム値
     */
    byte[] verifyValueMAC = Forms.hexStringToByteArray("734D092CD8C23E38");
    /**
     * 保護キーによって保護された暗号文
     */
    byte[] protectionKey = Forms.hexStringToByteArray("2EACE685C5EB2638D1208742F3BE60CD44210B43C894A77C");
    /**
     * 保護キーによって保護された暗号文のメッセージ認証コード (MAC)
     */
    byte[] protectionMAC = Forms.hexStringToByteArray("0CB8702D41CBE487");

    /**
     * RSA DER エンコードされた公開鍵
     */
    byte[] publicKeyRSA = Forms.hexStringToByteArray("308186028180E14CAAFFCEC6D014457D7CA3E943DBABA1299BDBC17690C8E70F7BFA10EA02450805DA4C6CDC38BFBF1349C95B81A88177BA31C08E366EF965CA41EB36A2DACE611B80A752615A094B8291AAB6F8BB3A5894E72842371F34FA04C10DF42C2FEA95C51B9D49BE8B795E10474954FE01BAAC63532520069465FA62EDB266AADEBB020103");
    /**
     * RSA LMK によって暗号化された秘密鍵
    byte[] privateKeyRSA = Forms.hexStringToByteArray("000202703D0652C7027B7D94B45A896646A9DC7CA89825FB12121B3CC00E37BE933055D5C00E37BE933055D54718ADDAA677519BD9C054CA249B43888FE000B8AAC33BA87A2C326985704335EA54D7F171CABCAD5531B3ADF33255A24075EFFF62691D4375E6280A9442CA36AA46AC59FAB16D9A9A7A283440BB14BAB1E78DBE887AE93A2C94C547779190D3FA801379BA948537281EFEFE567FD963E5D6E5D442D908A68BB6E26F3776EA30B1136A3804844035E26308E9B44BE154E1D09382E5A72BD711A6936373A8C32B62AF88134690C30D8B5505004F3BA01D11D0D791C8FF53D0E0786ED192CF1105FCF82160921EEF23E7BD72F13587B316BD9A771CEABBD0186B45E09C86E718AD4E5444EFFE747FE0C39E85D6190F3347656E72F486C321D5EA0D42127149C99F4F799A31F91E5826B74FF720A6E3CC2BCBBF645DD3D4A6A7D0BC953B4CFEE4E0D2BABFD606292F9F2395464484C306FBD60E4DD293E5F56C60BF1482A05775F0EEBAFBF9B70841DDDCFC974DD4D87E54D6A6A7A1A585EF0F42B0763D5DD7B5ECA83AFE610C26C9EF559B7883AC4716240BDFDC91C6EA19A0C01BB9C053F2A9C7EBCAE7D0AA8FB0DB88EFCF9C50A134E04649DAFF21D724E5C3CC043DE950C2CF246392DC4CA592D28C5A959BEB80B304E3BD949AD33178C06209FE6EB7130A381DFFD80F916AE0E0DD8FFDD9C8C9895BC483993D6011754FAD3C9F83A59C31F47810F8B2B22E5F25EF13671DFF34ECB65DE71D5B13DC5880595BC60B18D4711AE4613C739E2A48B516F6233E9AA9834075CE58975907F06FBA3B85C97E2E90B60BFEF0F23527E770798B571BC7CE29B67920538D509C58B1D8F966AF7E5321CDB2386164844D2BCB");
    /**
     * RSA 保護キーによって暗号化された秘密鍵
     */
    byte[] privateKeyRSAKEK = Forms.hexStringToByteArray("6B2FB2BCC75604ABF5761FFA1027FF16324E3038B580C9F63AD3B57BD89059D5799974B4E5E9453763D94E682C629C4617C4E5393E9DDBFB0CFA2A4EA0E832F5C6A30F3EE63C327F6E044F3CB630D0C7DD96D93581835AA529797EB11CF3535650E431181717FDD1D7BBD9FB675FB027134BBF7F10F65245D9A82251A9171DAA439C175895904A2BB74F31BD94FF550023F6245C01DF83B2FCEDDF241307DDC831162AD2203BA3EBC4FD99EAE93C3208F16B0AAF85146ACE5FF06B11D7C81215708AA5C2651D380573F0EDA0984A73F5CE38E21541D50AACF5C5BCD42B6C94D064065ECAED4684E7A40C15904A73A801F2697AF6F3E32C3D7E156A1D1085CA32C7A002FA4AEAD439271E6E5904FC9AC3E65EEBAC51399F60DF3C61AF82BDA04D5E28B587382F8EB751096BC970B7A7DF26D997324F2D002D01A4C8F77C37BB65DBD1DED3B4545323DAE9489A08351507224574A2206FA7EAF8EF0A120D23D6B34E84645E95C3B58187BC91B8F6C04EF15075D6AF38B7E7DD77F6D2B8E66F11960C401BCE56BB4C157DAA26234678A37ACCFC7729CB5018449F7B6A23C0B16CA0B6A5FBE9FC7C8F9A3801A4159822DDDE8D9D7B7233CC3F77E7391DE720A2BFC69F6B938B565A28EBC6B4B665C553A9E1F32A17CC66CB8A2D7FE3EF6CB5112815D562F18EB34987B57DCFF064C7C24E97C3DCF3FD9BD50B351A2DD7CF03DA1F2DDA7A1BD2013C8339AFC4D22C135C49859C9C4CA4C9F730D2EE09A779D244C13FB5C3835F2FF04EE12537B01795D0ABE2D9695208542DC2FF8161AFD6F774E8D524B1DE6096530783");
    /**
     * RSA MAC
     */
    byte[] privateKeyRSAKEKMAC = Forms.hexStringToByteArray("701A4D3572D09760");

    /**
     * キー暗号化キー (KEK) によって暗号化された RSA 秘密鍵
     */
    byte[] privateKeyKEK = Forms.hexStringToByteArray("7A833CC0FAFBA6EC063DF4827B8FD91FF4B9A69FB0C44FD972173C09E9E56F6918730269561A497403F9478D7BB64FE527F748AF86E3CE7C762A92A07D9C8BBCE0731F9F07C5889AE8B0FF7A31FCCCD76CD20A1AFB95B4D12BEA5DB84059B9CB1FB8F778989FD11CB7F8D84D812190F2EE0F479A4020FEB32C634528FBF660B3AD5AB0BA497B932902294C28B02807DC1AC28E8213BA39582AA677050F9E9256879935484B49D1CD115B39C0A41AE2B18263F78EA4CB781C931EA3C638097D1A7D4245C30ADA1B7C7793FD798EFAB86C3A91F573D4D2ECFA188588A31983320052901CC5AECAEDC5296506442546614B3DFDECA958B5E3A659EC8B52C5818E22F8E50C216264B560073F47E07B07E38CEF2DF4F6E4A458665FD31E6AA1C7B2FB5C4A15405C09E5F2B814FB260C1FFC560A2B6F3370C9DD96BA0A15BA72AB3622FE172F847D60383307C936246B977665CAB5E68EFA6E4EE1F9008FAE7A90D4A2A10AB70969714041707D4AD05F96027FA62FC916C81BA3C8601F7FF3115F17A117AD1B9A3D8438A731707A2D3B65BDA3846D293939CF94EBCC681E8115400454CF2CEA3769A614A9098CA62356B131EA22F4D634B56B365D7A430A3703967B50C6FCA93D11BD5ACC60048B5E00EAF353723D6DE878F8E5E4EA03BD43DF7229E6146DE307F9CC51B7F359F07042500AB5C24EE6F80EA8E1E50961BEC347949E5DD1918027A17196BABEE5790332B76D4AFFCD19143D7462177CDF72DE09BE64320C330090C1C6F1B059E81E02C312ABFC68F454D11EFCF1E0609584D06B09A08599D7A0BF5D63BB9F");
    /**
     * KEK によって暗号化された RSA 秘密鍵の MAC
     */
    byte[] privateKeyRSAMAC = Forms.hexStringToByteArray("06E5A11D968C36DE");

    /**
     * KEK によって暗号化された SM2 秘密鍵
     */
    byte[] privateKeySM2KEK = Forms.hexStringToByteArray("D3C5F579038C8BF3469879DD7F79C2E1B7FF47D7F2D5EFF5B01EFCE51C081D8067E06C0290F8EF6044210B43C894A77C");
    /**
     * KEK によって暗号化された SM2 秘密鍵の MAC
     */
    byte[] privateKeySM2MAC = Forms.hexStringToByteArray("83E413861F0C0D15");


    /**
     * SM2 DER エンコードされた公開鍵
     */
    byte[] privateKeySM2DER = Forms.hexStringToByteArray("3059301306072A8648CE3D020106082A811CCF5501822D03420004B33D8A2F9E1E1FCA2E8CECCFFB166F52CC2ED0589C25464D0EF85DC87E0537DC16C0D542A53790967A1368B7084F6EFED51FC848D1E3B5370A99BDCB64D17C2F");
    /**
     * SM2 LMK によって暗号化された秘密鍵
     */
    byte[] privateKeySM2 = Forms.hexStringToByteArray("66C9DDB0D6400EE059474F5C7339A296D5AA88F02AF031174F212EB6538C21908C4F5CA6457B435F");
    /**
     * SM2 保護キーによって保護された秘密鍵
     */
    byte[] privateKeyKEKSM2 = Forms.hexStringToByteArray("D3C5F579038C8BF3A1624E7DC142A863240A42642337355921C70A7547001B21A0C59D4E0800F99644210B43C894A77C");
    /**
     * SM2 MAC
     */
    byte[] privateKeyKEKSM2MAC = Forms.hexStringToByteArray("B9827812C2E18232");

    /**
     * ランダムに生成された SM2 キー 1002
     */
    byte[] publicSM2 = Forms.hexStringToByteArray("3059301306072A8648CE3D020106082A811CCF5501822D03420004D93204DF6335BEF43A90F8566CFB6FB5F7B10BE8082E9C0D9A5AA731F994AF07990FCB6913D902C4C9B8A84A3F96ADDD7BEF537D61404D56E58A68C756AEFD40");
    byte[] privateSM2 = Forms.hexStringToByteArray("6F26783DCE6D45B84D3FF39FFBDB365FE93B94EF15C39E00A09DE07212472FA68D1A3B721C09BB28");

    /**
     * MD5 で生成されたデータダイジェスト
     */
    byte[] md5 = Forms.hexStringToByte("D41D8CD98F00B204E9800998ECF8427E");
    /**
     * SM3 で生成されたデータダイジェスト
     */
    byte[] sm3 = Forms.hexStringToByte("E559D3DE421E81967DD68B28B55E0C26B03FCE10B8A8E5C4E6067497729D40D3");

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

    public APITest() throws TAException, ConfigurationException {
    }


    /**
     * 対称キーの生成
     *
     * @throws TAException
     */
    @Test
    public void genSymmKey() throws TAException {
        ArrayList<byte[]> bytes = api.genSymmKey(3);
        System.out.println("LMK によって暗号化された対称キー:"  + Forms.byteToHexString(bytes.get(0)));
        System.out.println("対称キーのチェックサム値:"  + Forms.byteToHexString(bytes.get(1)));

    }

    ///////////////////////////////////////////////////////////////////////////
    // 1015 テストデータ
    ///////////////////////////////////////////////////////////////////////////

    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");

    /**
     * 保護キーによって生成および保護された対称キー
     *
     * @throws TAException
     */
    @Test
    public void generateProtectionKey() throws TAException {
        /**
         * SM4
         * LMK によって暗号化された対称キー: B36847D6E86EAB69E4EEB65558A2626C
         * 対称キーのチェックサム値: 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 によって暗号化されたセッションキーの暗号文:" + Forms.byteToHexString(bytes.get(0)));
        System.out.println("セッションキーのチェックサム値:" + Forms.byteToHexString(bytes.get(1)));
        System.out.println("保護キーによって暗号化されたセッションキーの暗号文:" + Forms.byteToHexString(bytes.get(2)));
        System.out.println("セッションキーの MAC:" + Forms.byteToHexString(bytes.get(3)));
        System.out.println("タグ:" + Forms.byteToHexString(bytes.get(4)));

    }

    /**
     * 対称キーによるデータの暗号化と復号
     *
     * @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 暗号化結果:" + 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 復号結果:" + 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 暗号化結果:" + 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 復号結果:" + Forms.byteToHexString(bytes1));
    }




    /**
     * 対称キーによるデータの暗号化と復号 (保護キーによって保護)
     *
     * @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("暗号文:" + Forms.byteToHexString(bytes.get(0)));
        System.out.println("タグ:" + 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("復号後の平文:" + new String(bytes1));
    }

    byte[] srcRSACipher = Forms.hexStringToByte("83E265207D4566C7704DF9E6170181378CA028FB1EAA0BCB771DFD188CF5BEA899ECEF9213CA98D6D698CCE6072237768F514B04D68DA6B01400F69F93601976DCDFAE8F2EDDAA4F01BA8CE5E76A77AEB01BAB9D6E59A32B4E30B2B8D21D13B5C3510A1622190621BD3B0B5838A2CCBE423F4D3A7613CB69BBC9857E4BF5D08AAD77DDB96ECDD88989B885D44B909F502DC53A2FB4200FA714ECCFF100E7E986D76B68BD0BEFF5CA33CA698DA42F8B74FFBC09FB8F30483E416D0D2EAC6AF2B2A309F6762B5D292DA619C92428D1AB11A6931C81A859C79D8C01B441B1902ABE001BFF501DEE0E1E241E4567ECC74F9D4665AEA77C4F93AC312347A5087B686DC8361415A85197DB69CEEFD6D00CE94C34C290B8F79F10CC27A79D7C4D8F43736223576649E93457C75BA8C637927EC780A56B45163142DE1483777B4C8222C92B3C82AB372B3B0223D4EE246938EB85A7EC536DC77A291E152CF94E02465137DF2F25140669071913F868E58F379472235564F125B6C71C2705FE895ABEEFE33C656ACA7D489AD5C432B80AB9D8F732C03519F2E99F0DEAC4A7312FC351C059877BA09FB6455EFCB0D0DFE9F597416A5E1D88A7326C64D5539D91519935FADD5BE76EBB4D60FC57103CB8960890B4B1EC822C8D9781CF67B6DD1BE15E87406A0B0B5C06A69F6B07991C95B13CC0C4DBEA91589425E7C8D4E7CFE2CBBEC34D7705E8B52939D2E154B3435B7B4B8E41CD4DCEDF3892EF0F3352C8467CA46DB08A7DC93969E18B405F44508F919F4C0B3F2F7C0B79E661001B79FB0F0205A97CECFBE25DC4C711EA");

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

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

    byte[] srcRSApublicKey = Forms.hexStringToByteArray("308186028180E14CAAFFCEC6D014457D7CA3E943DBABA1299BDBC17690C8E70F7BFA10EA02450805DA4C6CDC38BFBF1349C95B81A88177BA31C08E366EF965CA41EB36A2DACE611B80A752615A094B8291AAB6F8BB3A5894E72842371F34FA04C10DF42C2FEA95C51B9D49BE8B795E10474954FE01BAAC63532520069465FA62EDB266AADEBB020103");
    /**
     * RSA 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");


    /**
     * 大容量データパケットの暗号化と復号
     */
    @Test
    public void bigDataEnc() throws TAException {
        byte[] enc = api.bigDataEnc(Forms.hexStringToByteArray("6DF7292D86B674B6B81F7C94DDC967A0"), "AES/ECB/PKCS5Padding", "demaxiyazhili".getBytes(), new byte[0]);
        System.out.println(Forms.byteToHexString(enc));
        byte[] dec = api.bigDataDec(Forms.hexStringToByteArray("6DF7292D86B674B6B81F7C94DDC967A0"), "AES/ECB/PKCS5Padding", enc, new byte[0]);
        System.out.println(new String(dec));

    }

    /**
     *MAC の計算と検証
     */
    @Test
    public void mac() throws TAException {
        byte[] bytes = api.calMac(1, 0, 2, sm4Key, 7, "1111111111111111".getBytes(),
                new byte[16]);
        System.out.println("MAC 計算結果:" + Forms.byteToHexString(bytes));
        boolean b = api.verifyMAC(1, 0, 2, sm4Key, 7, "1111111111111111".getBytes(),
                new byte[16], bytes);
        System.out.println("MAC 検証結果:" + b);
    }

    /**
     * ハッシュベースのメッセージ認証コード (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)));
        }
    }

    /**
     * RSA キーペアが生成され、秘密鍵が LMK によって暗号化される
     */
    @Test
    public void generateRSAKeyPair() throws TAException, IOException {
        ArrayList<byte[]> bytes = api.genRSAKey(2048, 65537);

        System.out.println("DER エンコードされた公開鍵:" + Forms.byteToHexString(bytes.get(0)));
        System.out.println("LMK によって暗号化された秘密鍵:" + Forms.byteToHexString(bytes.get(1)));
    }


    /**
     * RSA キーペアが生成され、保護キーによって暗号化される
     */
    @Test
    public void protectionKeyRSA() throws TAException, IOException {
        ArrayList<byte[]> bytes = api.proGenRSAKey (sm4Key, TACryptConst.KEY_ALG_SM4, sm4CV, 2048, 3,
                b, TACryptConst.ENC_MODE_ECB, b, new byte[2]);
        System.out.println("DER エンコードされた公開鍵:" + Forms.byteToHexString(bytes.get(0)));
        System.out.println("LMK によって暗号化された秘密鍵:" + Forms.byteToHexString(bytes.get(1)));
        System.out.println("保護キーによって暗号化された秘密鍵の暗号文:" + Forms.byteToHexString(bytes.get(2)));
        System.out.println("非対称秘密鍵の MAC 長:" + Forms.byteToHexString(bytes.get(3)));
    }

    /**
     * RSA 秘密鍵の署名生成と検証
     */
    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("署名生成結果:" + 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("署名検証結果:" + 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("署名生成結果:" + 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("署名検証結果:" + b);
    }

    /**
     * RSA 暗号化と復号
     */
    @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("公開鍵暗号化結果:" + Forms.byteToHexString(bytes));
        byte[] bytes1 = api.RSAPriDecData(11, 1, TACryptConst.DIGEST_ALG_SHA256,new byte[0], bytes);
        System.out.println("秘密鍵復号結果:" + Forms.byteToHexString(bytes1));
    }

    /**
     *  保護キーによって保護された RSA 秘密鍵による復号
     */
    @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("復号後の平文:" + Forms.byteToHexString(bytes));
    }

    /**
     * 保護キーによって保護された RSA 秘密鍵による署名生成
     */
    @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("署名生成結果:" + 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("署名検証結果:" + b);
    }

    /**
     * RSA 非対称キーの暗号化キーが保護キー 1 から保護キー 1 に変更される
     */
    @Test
    public void RSAConversionEncryption() throws TAException {
        ArrayList<byte[]> bytes = api.conversionEncryption(0, TACryptConst.KEY_ALG_SM4, sm4Key, sm4CV, TACryptConst.KEY_TYPE_RSA,
                -1, srcRSACipher, b, srcRSACipherMAC, TACryptConst.ENC_MODE_GCM, b, new byte[2], srcRSACipherTag,
                0,
                TACryptConst.KEY_ALG_SM4, sm4Key2, sm4Key2CV, b, TACryptConst.ENC_MODE_ECB, b, new byte[2]);
        for (int i = 0; i < bytes.size(); i++) {
            System.out.println("No.:" + i + "===" + Forms.byteToHexString(bytes.get(i)));
        }
    }

    /**
     * RSA 非対称キーを保護するために、対称キーをインポートする。
     */
    @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 によって暗号化された対称キー:" + Forms.byteToHexString(bytes.get(0)));
        System.out.println("対称キーのチェックサム値:" + Forms.byteToHexString(bytes.get(1)));
    }

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

    /**
     * SM2 および楕円曲線暗号 (ECC) キーペアが生成され、保護キーによって暗号化される
     */
    @Test
    public void generateProtectionKeySM2() throws TAException {
        ArrayList<byte[]> bytes = api.proGenSM2OrECCKey (sm4Key, TACryptConst.KEY_ALG_SM4, sm4CV, 0x0007,
                b, TACryptConst.ENC_MODE_GCM, b, new byte[16]);
        System.out.println("DER エンコードされた公開鍵:" + Forms.byteToHexString(bytes.get(0)));
        System.out.println("LMK によって暗号化された秘密鍵:" + Forms.byteToHexString(bytes.get(1)));
        System.out.println("保護キーによって暗号化された秘密鍵の暗号文:" + Forms.byteToHexString(bytes.get(2)));
        System.out.println("非対称秘密鍵の MAC:" + Forms.byteToHexString(bytes.get(3)));
        System.out.println("タグ:" + Forms.byteToHexString(bytes.get(4)));

    }

    /**
     * SM2 キーペアが生成され、秘密鍵が LMK によって暗号化される
     */
    @Test
    public void generateSM2Key() throws TAException {
        ArrayList<byte[]> bytes = api.genSM2Key();
        System.out.println("DER エンコードされた公開鍵:" + Forms.byteToHexString(bytes.get(0)));
        System.out.println("LMK によって暗号化された秘密鍵:" + Forms.byteToHexString(bytes.get(1)));
    }

    /**
     * ECC キーペアが生成され、秘密鍵が LMK によって暗号化される
     */
    @Test
    public void generateECCKey() throws TAException {
        ArrayList<byte[]> bytes = api.genECCKey(0x0007);
        System.out.println("DER エンコードされた公開鍵:" + Forms.byteToHexString(bytes.get(0)));
        System.out.println("LMK によって暗号化された秘密鍵:" + Forms.byteToHexString(bytes.get(1)));
 
    }

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

    /**
     * ECC 署名の生成と検証
     */
    @Test
    public void ECCPrivateKeySign() throws TAException {

        byte[] bytes = api.priKeySign(0x0007, Forms.hexStringToByteArray("61971383CD4D760CF77CCA48C187592ACE2375BB54CA886724EE230AE7D94C1C935F18B4CCCFBF3A"), data);
        System.out.println("ECC 署名生成結果:" + Forms.byteToHexString(bytes));

        boolean b = api.pubKeyVerify(0x0007, Forms.hexStringToByteArray("3059301306072A8648CE3D020106082A811CCF5501822D03420004E6BFD64E16F9FDE831FC2483A703F32D2925C126C435CF4FF0BC0187351E34F627E3421ACA51CB99CD452FA11B5B6BBB4AA31C2DBCC696FC57C8F9F8F01948FE"), data, bytes);
        System.out.println("ECC 署名検証結果:" + b);
    }

    /**
     * SM2 署名の生成と検証
     */
    @Test
    public void TestSm2() throws TAException {
        byte[] bytes = api.priKeySign(0x0007, privateKeySM2, sm3);
        System.out.println("署名生成結果:" + Forms.byteToHexString(bytes));
        boolean b = api.pubKeyVerify(0x0007, privateKeySM2DER, sm3, bytes);
        System.out.println("署名検証結果:" +  b);
    }


    @Test
    public void SM2Sign() throws TAException {
        byte[] baInData = "2222222222222222".getBytes();
        //7. SM3 ダイジェスト計算
        System.out.println("データダイジェスト: 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("データダイジェスト: %s", Forms.byteToHexString(baHashSm3)));


        //8. 非対称キーの署名生成と検証
        System.out.println("非対称暗号化を使用した署名生成と検証: SM2");

        int iCurveId = 0x0007;
        System.out.println(String.format("元のデータ (ハッシュ値): %s", Forms.byteToHexString(baHashSm3)));

        byte[] baSignatureSm2 = api.priKeySign(iCurveId, 2, baHashSm3);
        System.out.println(String.format("署名生成: %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 暗号化と復号
     */
    @Test
    public void TestSM2EncAndDec() throws TAException {
        byte[] bytes = api.SM2PubKeyEnc(888, Forms.hexStringToByte("11111111111111111111111111111111"));
        System.out.println("暗号化結果: " + Forms.byteToHexString(bytes));

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


    /**
     * 保護キーによって保護された ECC および SM2 秘密鍵による復号
     */
    @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("復号後の平文: " + Forms.byteToHexString(bytes));
    }

    /**
     *  保護キーによって保護された ECC および SM2 秘密鍵による署名生成
     */
    @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 秘密鍵による署名生成の結果: " + Forms.byteToHexString(bytes));

        boolean b = api.pubKeyVerify(7, sm2Key, Forms.hexStringToByteArray("20D90A83A4654FB89AD97E7FF9B178BAA58E12CE8E5C16DE0371B374F76DEFA5"), bytes);
        System.out.println("ECC および SM2 公開鍵による署名検証の結果 (秘密鍵は保護キーによって保護): " + b);
    }

    /**
     * SM2 非対称キーを保護するために、対称キーをインポートする。
     */
    @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 によって暗号化された対称キー: " + Forms.byteToHexString(bytes.get(0)));
        System.out.println("対称キーのチェックサム値: " + Forms.byteToHexString(bytes.get(1)));
    }

    /**
     * SM2 および ECC 非対称キーの暗号化キーが変更される
     */
    @Test
    public void conversionEncryption() throws TAException {
        ArrayList<byte[]> bytes = api.conversionEncryption(0, TACryptConst.KEY_ALG_SM4, sm4Key, sm4CV, 2,
                -1, sm2Cipher, b, sm2CipherMAC, TACryptConst.ENC_MODE_GCM, b, new byte[2], sm2CipherTag, 0,
                TACryptConst.KEY_ALG_SM4, sm4Key2, sm4Key2CV, b, TACryptConst.ENC_MODE_GCM, b, new byte[2]);
        for (int i = 0; i < bytes.size(); i++) {
            System.out.println("No.:" + i + "===" + Forms.byteToHexString(bytes.get(i)));
        }
    }

    /**
     * ダイジェスト計算とダイジェストデータパディング
     */
    @Test
    public void testGenHash() throws TAException {
        byte[] hash = genHash();
        System.out.println("ダイジェスト結果: " + Forms.byteToHexString(hash));

        // ダイジェスト結果の検証
        String string = "704423DF78242B08E821F7F8FA05A5325AA1BD842BE4EB9827C765DFFF434C1A";

        byte[] bytes3 = genHash();
        System.out.println("結果の検証: " + Arrays.equals(Forms.hexStringToByteArray(string),bytes3));

        String wrongHash = "669523DF78242B08E821F7F8FA05A5325AA1KD842BE4EB9827C765DFFF434C1A";

        System.out.println("無効な結果の検証: " + 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;
    }


    /**
     * 乱数の生成
     */
    @Test
    public void genRandom() throws TAException {
        String s = api.genRandom(15);
        System.out.println(s);
    }

    /**
     * HSM ステータスの取得
     */
    @Test
    public void getHSMstatus() throws TAException {
        String hsMstatus = api.getHSMstatus();
        System.out.println(hsMstatus);
    }

    /**
     * lmk から 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("保護キーによって暗号化されたキーの暗号文: " + Forms.byteToHexString(bytes.get(0)));
        System.out.println("MAC: " + Forms.byteToHexString(bytes.get(1)));
        System.out.println("タグ: " + Forms.byteToHexString(bytes.get(2)));
        System.out.println("キーのチェックサム値: " + Forms.byteToHexString(bytes.get(3)));
    }

    /**
     * 他のキーに基づく暗号化から LMK ベースの暗号化への切り替え
     * @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("=============保護キーは対称キーです。============");
        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("=============保護キーは ECC キーです。============");
        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("=============保護キーは RSA キーです。============");
        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("デジタルエンベロープのシーリング結果: " + Forms.byteToHexString(bytes));
        byte[] bytes1 = api.enveopDec(sm2PriKey, bytes);
        System.out.println("デジタルエンベロープのアンシーリング結果: " + new String(bytes1));
    }

    /**
     * 対称キーの暗号化キーへの変更 & 非対称キーの暗号化キーへの変更
     */
    @Test
    public void symmetryConversionEncryptionAES256() throws TAException {
        ArrayList<byte[]> bytes = api.conversionEncryption(0, TACryptConst.KEY_ALG_AES256,
                Forms.hexStringToByteArray("5BD90CDDBC8645B41AB901DDD8EFE9956755D9560C9FAEB096B6E52CC003D04F"),
                Forms.hexStringToByteArray("F8B6B9D8BB7E4FD3"),
                TACryptConst.KEY_TYPE_SYMMETRY,
                TACryptConst.KEY_ALG_AES256,
                Forms.hexStringToByteArray("CFE8E3D44F753D3F065962462AA9C9E1FE295BC835E4A1FB88EF70B54E65E232"), b,
                Forms.hexStringToByteArray("8F2440B22092CA8757D8D807A832A19F"), TACryptConst.ENC_MODE_GCM, b, new byte[22],
                Forms.hexStringToByteArray("B5294D591009E19E780774B61BA48FA4"),
                0,
                TACryptConst.KEY_ALG_SM4, sm4Key2, sm4Key2CV, b, TACryptConst.ENC_MODE_CBC, b, new byte[12]);
        for (int i = 0; i < bytes.size(); i++) {
            System.out.println("No." + i + "===" + Forms.byteToHexString(bytes.get(i)));
        }
    }

    /**
     * 対称キーの暗号化キーへの変更 & 非対称キーの暗号化キーへの変更
     */
    @Test
    public void symmetryConversionEncryption() throws TAException {
        ArrayList<byte[]> bytes = api.conversionEncryption(0, TACryptConst.KEY_ALG_SM4,
                Forms.hexStringToByteArray("CBDCCE33784FA93FBE0B3BAA46CF3557"),
                Forms.hexStringToByteArray("F6684895E1ABC2AD"),
                0,TACryptConst.KEY_ALG_SM4,
                Forms.hexStringToByteArray("6BFC84C39CB9277C06C7FA2A30C912A1"), b,
                Forms.hexStringToByteArray("AB75C62580061710B39327B45881F589"), TACryptConst.ENC_MODE_GCM,
                b, new byte[0], Forms.hexStringToByteArray("4A501743FA4B906244A0A8705192C1C8"),0,
                TACryptConst.KEY_ALG_SM4,
                Forms.hexStringToByteArray("CBDCCE33784FA93FBE0B3BAA46CF3557"),
                Forms.hexStringToByteArray("F6684895E1ABC2AD"), b, TACryptConst.ENC_MODE_GCM, b, new byte[0]);
        for (int i = 0; i < bytes.size(); i++) {
            System.out.println("No." + i + "===" + Forms.byteToHexString(bytes.get(i)));
        }
    }

    /**
     * 対称キーの暗号化キーへの変更 & 非対称キーの暗号化キーへの変更
     */
    @Test
    public void symmetryConversionEncryption1() throws TAException {
        ArrayList<byte[]> bytes = api.conversionEncryption(0, TACryptConst.KEY_ALG_SM4, sm4Key, sm4CV,
                TACryptConst.KEY_TYPE_ECC_OR_SM2,
                TACryptConst.KEY_ALG_SM4,
                Forms.hexStringToByteArray("83E260209C09CC3FEFDEFE7F4B620157A3F25E0B3098A4677DAF3A8E9DC327A17AEB2C8919E1E4CF"), b,
                Forms.hexStringToByteArray("E60EFC48823B17C51F68D0EB622298FB"),
                TACryptConst.ENC_MODE_GCM, b, new byte[16],
                Forms.hexStringToByteArray("B200ED220D49D855EC4438649057EB02"),
                0,
                TACryptConst.KEY_ALG_SM4, sm4Key, sm4CV, b, TACryptConst.ENC_MODE_GCM, b, new byte[16]);
        for (int i = 0; i < bytes.size(); i++) {
            System.out.println("No." + i + "===" + Forms.byteToHexString(bytes.get(i)));
        }
    }


    /**
     * 対称 CMK を保護するために、非対称カスタマーマスターキー (CMK) をインポートする。
     */
    @Test
    public void importCMKByCMK() throws TAException {
        ArrayList<byte[]> bytes = api.importCMKByCMK("zjlimpl".getBytes(), 7,
                6,  //DomainKey が CMK を暗号化するために使用するアルゴリズムモードの識別子
                new byte[16],     //Electronic Code Book (ECB) モードでの復号中に使用される初期化ベクトル (IV) データ
                new byte[16],      //Galois/Counter Mode (GCM) モードでの復号中に使用される認証データ
                Forms.hexStringToByteArray("566F7CE9E52CCA87FF02D7A7667E3F7C"), //GCM モードでの復号中の MAC
                Forms.hexStringToByteArray("DA23B170CEA626F4C772B3F2AE2CCA97"),//キー暗号文
                Forms.hexStringToByteArray("7192C7C6F1EAAB72BFE8A51BA9256C87"),  //GCM タグ
                6, //保護キーの暗号化モード
                new byte[16],//保護キーの IV
                new byte[16], //追加認証データ (AAD)
                Forms.hexStringToByteArray("8DE9DFEE4BE10827C1C08A38BDD8A92F"), //タグ
                5,// 保護キーベースの暗号化のパディング方法
                12, //セッションキーのタイプ
                7,  //非対称セッション CMK のアルゴリズムの識別子
                Forms.hexStringToByteArray("420B9FE23A2B162F3C4574919E9EBD44040F7C5338CDE0C8311C88495D2F3604E9AFC80B18990EF5C6F3A93AB80B41458311EA9F9A1890752427E24F5062AD4A"),//セッション秘密鍵の暗号文
                "32-1".getBytes(),//セッション DomainKey のタグ
                6,//セッション DomainKey が CMK を暗号化するために使用するアルゴリズムモードの識別子
                new byte[16],//セッション暗号化コンテキスト (非 ECB モードでの暗号化中に使用される IV データ)
                new byte[16]//セッション認証コンテキストデータ (GCM モードでの暗号化中の認証データ)
        );
        System.out.println("保護キーによって暗号化されたキーの暗号文: " + Forms.byteToHexString(bytes.get(0)));
        System.out.println("MAC: " + Forms.byteToHexString(bytes.get(1)));
        System.out.println("タグ: " + Forms.byteToHexString(bytes.get(2)));
        System.out.println("キーのチェックサム値: " + Forms.byteToHexString(bytes.get(3)));
    }

    @Test
    public void testData() throws TAException {
        //保護キーによって生成および保護された対称キー
        ArrayList<byte[]> bytes = api.proGenSymmKey(603,
                -1, null, TACryptConst.KEY_ALG_SM4, b,
                TACryptConst.ENC_MODE_GCM,b, b);
        System.out.println("LMK によって暗号化されたセッションキーの暗号文: " + Forms.byteToHexString(bytes.get(0)));
        System.out.println("セッションキーのチェックサム値: " + Forms.byteToHexString(bytes.get(1)));
        System.out.println("保護キーによって暗号化されたセッションキーの暗号文: " + Forms.byteToHexString(bytes.get(2)));
        System.out.println("セッションキーの MAC: " + Forms.byteToHexString(bytes.get(3)));
        System.out.println("タグ: " + Forms.byteToHexString(bytes.get(4)));
        System.out.println("-------------------------------------------------");
        //保護キーによって保護された対称キーで暗号化されたデータ
        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("暗号文: " + Forms.byteToHexString(bytes1.get(0)));
        System.out.println("タグ: " + 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 ネゴシエーション結果: " + Forms.byteToHexString(bytes));
//        byte[] bytes1 = api.agreementKey(0x0007, 3, 6, Forms.hexStringToByte("3059301306072A8648CE3D020106082A811CCF5501822D03420004AC3DC24CE9883F26278E97A04D5409AA2A94D57FCE84E7630F4E46CFBED036A6B89791DF9A3DF50D67073CF246FC3406337B50E987F2AC3943D2FF5C7ECAD197"));
//        System.out.println("0x0007 ネゴシエーション結果: " + Forms.byteToHexString(bytes1));
//        byte[] bytes2 = api.agreementKey(0x0007, 3, Forms.hexStringToByte("E59842CEEC68775E6AD78C7276AD2ADE0E27405E8B60FE02F7DF23E08F7F6B8D"), Forms.hexStringToByte("3059301306072A8648CE3D020106082A811CCF5501822D034200040EF69FB0C3739C3FDC16499AB96985EAD5CBEB4178A985A8FC10145979C315A5519C50B972EB19EA77A6AB74F345688B8458F1015885FCE435A4E3679DE0E34F"));
//        System.out.println("0x0007 外部秘密鍵の平文ネゴシエーション結果: " + Forms.byteToHexString(bytes2));
//        byte[] bytes3 = api.agreementKey(0x039B, 0, 5, Forms.hexStringToByte("304A301406072A8648CE3D020106092B24030302080101030332000448D5FAD9CD434E60EF661B65289867B395461D868F7D34BABEEB5A20F7DF5543091DD740DD3780B5EBEF631615571ADC"));
//        System.out.println("0x039B ネゴシエーション結果: " + Forms.byteToHexString(bytes3));
        byte[] bytesA = api.agreementKey(0x019F, 3, 13, Forms.hexStringToByte("3059301306072A8648CE3D020106082A8648CE3D030107034200048D912010F06A7D4B5062F6DC192EEDC8C88FCB2D2830AB8573F0FB30532041D0788F227558F1DA9AC8CDF5E7FA72C9931FA90EE06B3CE07E13A7845A05BA7C73"));
        System.out.println(bytesA.length);
        System.out.println("0x0007 ネゴシエーション結果: " + Forms.byteToHexString(bytesA));
        byte[] bytesB = api.agreementKey(0x019F, 3, 15, Forms.hexStringToByte("3059301306072A8648CE3D020106082A8648CE3D0301070342000481022BD6C8FFBBD2EC4B5A53F7000920D1581C0BC17B4C781627894B0979FFCA115C85C7AB0964E53872FBF0511FF6E7661CF94B7D82C8BF78D211B1FA73F271"));
        System.out.println("0x0007 ネゴシエーション結果: " + Forms.byteToHexString(bytesB));

    }

    /**
     * キーインデックスに基づいて対称キーの詳細を取得する。
     */
    @Test
    public void getKeyInfo() throws TAException {
        String[] keyInfo = api.getKeyInfo(66);
        System.out.println(keyInfo[0]);
    }
    /**
     * キーインデックスに基づいて RSA 公開鍵を取得する。
     */
    @Test
    public void exportRSAPublicKey() throws TAException, IOException {
        ArrayList<byte[]> keyInfo = api.exportRSAPublicKey(77,0);
        System.out.println(Forms.byteToHexString(keyInfo.get(0)));
    }
    /**
     * キーインデックスに基づいて ECC 公開鍵を取得する。
     */
    @Test
    public void ExportEncPublicKey() throws TAException {
        byte[] keyInfo = api.exportECCPublicKey(66,0);
        System.out.println(Forms.byteToHexString(keyInfo));
    }

    @Test
    public void generateAndSaveKey() throws Exception {
        ArrayList<byte[]> symmKey = api.generateSymmKey(7, 32);
        for (int i = 0; i < symmKey.size(); i++) {
            System.out.println(Forms.byteToHexString(symmKey.get(i)));
        }
        boolean b = api.generateRSAKey(2048, 65537, 13);
        System.out.println("RSA キーペアが生成され、保存されました" + (b ? "成功":"失敗"));
        boolean b1 = api.generateECCKey(0x019F, 8);
        System.out.println("ECC キーペアが生成され、保存されました" + (b1 ? "成功":"失敗"));

    }


}

その他の操作

クラスターのスケールアウト

異なるゾーンの HSM を同じクラスターに追加し、HSM を一元的に管理できます。これにより、Cloud Hardware Security Module の高可用性が確保されます。HSM は、次の要件を満たしている場合にのみクラスターに追加できます。

  • HSM が初期化されていない。

  • HSM が 有効 または New 状態である。

  • HSM がクラスターのマスター HSM と同じタイプである。

  • HSM に vSwitch が設定されていないか、HSM がマスター HSM と同じ vSwitch を使用している。

重要
  • HSM にホワイトリストが設定されている場合、HSM がクラスターに追加された後、クラスターのホワイトリストが優先されます。HSM のホワイトリストはクリアされます。

  • ハードウェアキー管理タイプの KMS インスタンス用の HSM クラスターをスケールアウトする場合、クラスターデータの同期が自動化されていることを確認してください。クラスターデータの同期が手動の場合は、Alibaba Cloud テクニカルサポートに連絡して、同期方法を自動同期にアップグレードしてください。

  1. [VSM] ページで、必要なマスター HSM を見つけ、操作 列の Expand Cluster をクリックします。

  2. 次のいずれかの方法で HSM をクラスターに追加します。

    • 利用可能な HSM がない場合は、Add HSM ダイアログボックスの Purchase an HSM instance をクリックして HSM を購入します。

      購入した HSM は自動的にクラスターに追加されます。Cloud Hardware Security Module は自動的に HSM に IP アドレスを割り当て、クラスター内のデータを同期します。

    • 利用可能な HSM がある場合は、次の操作を実行します。Add HSM ダイアログボックスで、追加する HSM を選択し、添加 アイコンをクリックして、[OK] をクリックします。

クラスターからのインスタンスの削除

クラスターから HSM インスタンスを削除するには、まず子インスタンスを削除し、次にマスターインスタンスを削除します。クラスターにマスターインスタンスのみが含まれている場合は、直接削除できます。マスターインスタンスが削除されると、クラスターは自動的に削除されます。

  1. HSM を無効にします。クラスターから HSM を削除する前に、HSM を無効にする必要があります。

    1. VSMs ページで、ターゲットの HSM インスタンスを見つけ、操作 列の Disable をクリックします。

    2. 表示されるダイアログボックスで、Disable を再度クリックします。

  2. VSMs ページで、ターゲットの HSM インスタンスを見つけ、操作 列の Remove from Cluster をクリックします。

  3. 表示されるダイアログボックスで、Remove from Cluster を再度クリックします。

クラスター名とアクセスホワイトリストの変更

ホワイトリストが設定されていない場合、すべての IP アドレスがクラスターにアクセスできます。ホワイトリストが設定されている場合、ホワイトリストにない IP アドレスからのアクセスリクエストは拒否されます。

  1. VSMs ページで、マスターまたは子 HSM のインスタンス ID をクリックします。

  2. Details タブで、クラスター名とアクセスホワイトリストを編集します。

    単一の IP アドレスまたは CIDR ブロックを入力できます。1 行に 1 つのエントリを入力します。最大 10 個のエントリを入力できます。

    重要
    • クラスターのホワイトリストは、クラスター内の HSM のホワイトリストよりも優先度が高くなります。たとえば、HSM のホワイトリストに 10.10.10.10 を追加し、HSM を含むクラスターのホワイトリストに 172.16.0.1 を追加した場合、HSM には 172.16.0.1 からのみアクセスできます。

    • 0.0.0.0/0 のホワイトリスト設定はサポートされていません。0.0.0.0/0 を入力すると、すべての IP アドレスからのリクエストが許可されます。

      セキュリティ上の理由から、すべての IP アドレスからのリクエストを許可しないことをお勧めします。すべての IP アドレスからのリクエストを許可する必要がある場合は、ホワイトリストを設定しないでください。

マスター HSM と子 HSM の切り替え

子 HSM を手動でクラスターのマスター HSM に切り替えることができます。この操作は、クラスターの同期方法が手動同期の場合にのみサポートされます。

  1. VSMs ページで、ターゲットの子 HSM インスタンスを見つけ、操作 列の Switch to Master をクリックします。

  2. 表示されるダイアログボックスで、Switch をクリックします。