

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

# パブリックキーを使用してオフラインオペレーションを実行する
<a name="offline-public-key"></a>

非対称 KMS キーでは、プライベートキーは に作成 AWS KMS され、暗号化されていないままになる AWS KMS ことはありません。プライベートキーを使用するには、 を呼び出す必要があります AWS KMS。API AWS KMS オペレーションを呼び出す AWS KMS ことで、 内でパブリックキーを使用できます。または、[パブリックキーをダウンロード](download-public-key.md)して、 の外部で使用するために共有することもできます AWS KMS。

パブリックキーを共有して、プライベートキーでのみ復号 AWS KMS できる 以外のデータを他のユーザーに暗号化させることができます。または、プライベートキーを使用して生成した AWS KMS の外部にあるデジタル署名を他のユーザーが確認できるようにすることができます。または、パブリックキーをピアと共有して共有シークレットを取得することもできます。

 AWS KMS内の非対称 KMS キーでパブリックキーを使用すると、すべての AWS KMS オペレーションの一部である認証、認可、ロギングの利点を得ることができます。また、復号できないデータを暗号化するリスクも軽減します。これらの機能は、 の外部では有効ではありません AWS KMS。詳細については、「[パブリックキーのダウンロードに関する特別な考慮事項](#download-public-key-considerations)」を参照してください。

**ヒント**  
データキーまたは SSH キーをお探しですか。このトピックでは、プライベートキーをエクスポートすることができない AWS Key Management Serviceでの非対称キーの管理方法を説明しています。プライベートキーが対称暗号化 KMS キーで保護されているエクスポート可能なデータキーペアについては、「[GenerateDataKeyPair](https://docs.aws.amazon.com/kms/latest/APIReference/API_GenerateDataKeyPair.html)」を参照してください。Amazon EC2 インスタンスに関連付けられたパブリックキーのダウンロード方法については、「[Amazon EC2 ユーザーガイド](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/describe-keys.html#retrieving-the-public-key)」内の「*パブリックキーの取得*」および「[Amazon EC2 ユーザーガイド](https://docs.aws.amazon.com/AWSEC2/latest/WindowsGuide/describe-keys.html#retrieving-the-public-key)」を参照してください。

**Topics**
+ [パブリックキーのダウンロードに関する特別な考慮事項](#download-public-key-considerations)
+ [パブリックキーをダウンロードする](download-public-key.md)
+ [オフラインオペレーションの例](offline-operations.md)

## パブリックキーのダウンロードに関する特別な考慮事項
<a name="download-public-key-considerations"></a>

KMS キーを保護するために、 はすべてのオペレーションのアクセスコントロール、認証された暗号化、および詳細なログ AWS KMS を提供します。 AWS KMS また、 では、KMS キーの使用を一時的または永続的に防止することもできます。最後に、 AWS KMS オペレーションは、復号できないデータを暗号化するリスクを最小限に抑えるように設計されています。これらの機能は、ダウンロードしたパブリックキーを の外部で使用する場合は使用できません AWS KMS。

**Authorization**  
内の [KMS キーへのアクセスを制御するキーポリシー](key-policies.md)と [IAM ポリシー](iam-policies.md) AWS KMS は、 の外部で実行されるオペレーションには影響しません AWS。パブリックキーを取得できるユーザーは、KMS キーを使用してデータを暗号化したり、署名を検証したりするアクセス許可がない場合 AWS KMS でも、 の外部で使用できます。

**キーの用途の制限**  
キーの使用制限は、 の外部では有効ではありません AWS KMS。`KeyUsage` の を持つ KMS キーを使用して [Encrypt](https://docs.aws.amazon.com/kms/latest/APIReference/API_Encrypt.html) オペレーションを呼び出すと`SIGN_VERIFY`、 AWS KMS オペレーションは失敗します。ただし、 `SIGN_VERIFY`または `KeyUsage`の KMS キーからパブリックキー AWS KMS を使用して の外部でデータを暗号化する場合`KEY_AGREEMENT`、データを復号することはできません。

**アルゴリズムの制限**  
 AWS KMS がサポートする暗号化アルゴリズムと署名アルゴリズムの制限は、 の外部では有効ではありません AWS KMS。外部で KMS キーからパブリックキーを使用してデータを暗号化し AWS KMS、 AWS KMS がサポートしていない暗号化アルゴリズムを使用する場合、データを復号することはできません。

**KMS キーの無効化と削除**  
内の暗号化オペレーションで KMS キーが使用されないようにするために実行できるアクション AWS KMS は、誰も の外部でパブリックキーを使用することを妨げません AWS KMS。例えば、KMS キーの無効化、KMS キーの削除のスケジューリング、KMS キーの削除、KMS キーからのキーマテリアルの削除は、 AWS KMSの外部のパブリックキーには影響しません。非対称 KMS キーを削除した場合、またはそのキーマテリアルを削除または紛失した場合、 の外部にあるパブリックキーで暗号化したデータは AWS KMS 回復できません。

**ログ記録**  
AWS CloudTrail リクエスト、レスポンス、日付、時刻、承認されたユーザーなど、すべての AWS KMS オペレーションを記録する ログは、 の外部でのパブリックキーの使用を記録しません AWS KMS。

**SM2 キーペアによるオフライン検証 (中国リージョンのみ)**  
SM2 パブリックキー AWS KMS を使用して の外部の署名を検証するには、識別 ID を指定する必要があります。デフォルトでは、 AWS KMS を識別 ID `1234567812345678`として使用します。詳細については、「[SM2 キーペアによるオフライン検証](offline-operations.md#key-spec-sm-offline-verification)」(中国リージョンのみ) を参照してください。

# パブリックキーをダウンロードする
<a name="download-public-key"></a>

コンソールの非対称 KMS キーペアから、 AWS KMS または [GetPublicKey](https://docs.aws.amazon.com/kms/latest/APIReference/API_GetPublicKey.html) オペレーションを使用して、パブリックキーをダウンロードできます。パブリックキーをダウンロードするには、非対称 KMS キーに対する `kms:GetPublicKey` アクセス許可が必要です。

が AWS KMS 返すパブリックキーは、RFC 5280 で定義されているように、 `SubjectPublicKeyInfo` (SPKI) とも呼ばれる DER エンコードされた X.509 パブリックキーです。 [https://datatracker.ietf.org/doc/html/rfc5280](https://datatracker.ietf.org/doc/html/rfc5280)HTTP API または を使用する場合 AWS CLI、値は Base64-encodedされます。それ以外の場合は、値は Base64 エンコードされていません。

非対称 KMS キーペアからパブリックキーをダウンロードするには、`kms:GetPublicKey` アクセス許可が必要です。アクセス AWS KMS 許可の詳細については、「」を参照してください[アクセス許可に関するリファレンス](kms-api-permissions-reference.md)。

## AWS KMS コンソールの使用
<a name="download-public-key-console"></a>

を使用して、 の非対称 KMS キーからパブリックキー AWS マネジメントコンソール を表示、コピー、ダウンロードできます AWS アカウント。異なる の非対称 KMS キーからパブリックキーをダウンロードするには AWS アカウント、 AWS KMS API を使用します。

1. にサインイン AWS マネジメントコンソール し、[https://console.aws.amazon.com/kms](https://console.aws.amazon.com/kms) で AWS Key Management Service (AWS KMS) コンソールを開きます。

1. を変更するには AWS リージョン、ページの右上隅にあるリージョンセレクターを使用します。

1. ナビゲーションペインで、**[カスタマーマネージドキー]** を選択します。

1. 非対称 KMS キーのエイリアスまたはキー ID を選択します。

1. **[Cryptographic configuration]** (暗号化の設定) タブを選択します。**[キーの仕様]**、**[キーの使用]**、**[暗号化アルゴリズム]**、または **[署名アルゴリズム]** フィールドの値を記録します。外部でパブリックキーを使用するには、これらの値を使用する必要があります AWS KMS。パブリックキーを共有するときは、必ずこの情報を共有してください。

1. **[Public key]** (パブリックキー) タブを選択します。

1. パブリックキーをクリップボードにコピーするには、**[Copy]** (コピー) を選択します。パブリックキーをファイルにダウンロードするには、**[Download]** (ダウンロード) を選択します。

## AWS KMS API の使用
<a name="download-public-key-api"></a>

[GetPublicKey](https://docs.aws.amazon.com/kms/latest/APIReference/API_GetPublicKey.html) オペレーションは、非対称 KMS キーでパブリックキーを返します。また、キーの使用法や暗号化アルゴリズムなど AWS KMS、 の外部でパブリックキーを正しく使用するために必要な重要な情報も返します。これらの値を保存し、パブリックキーを共有する場合は必ず共有してください。

このセクションの例では [AWS Command Line Interface (AWS CLI)](https://aws.amazon.com/cli/) を使用しますが、サポートされている任意のプログラミング言語を使用することができます。

KMS キーを指定するには、その[キー ID](concepts.md#key-id-key-id)、[キー ARN](concepts.md#key-id-key-ARN)、[エイリアス名](concepts.md#key-id-alias-name)、[エイリアス ARN](concepts.md#key-id-alias-ARN) を使用します。エイリアス名を使用する場合は、接頭辞として **alias/** を付けます。別の で KMS キーを指定するには AWS アカウント、そのキー ARN またはエイリアス ARN を使用する必要があります。

このコマンドを実行する前に、サンプルのエイリアス名を KMS キーの有効な識別子に置き換えます。このコマンドを実行するには、KMS キーに対する `kms:GetPublicKey` アクセス許可が必要です。

```
$ aws kms get-public-key --key-id alias/example_RSA_3072

{
    "KeySpec": "RSA_3072",
    "KeyId": "arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab",
    "KeyUsage": "ENCRYPT_DECRYPT",
    "EncryptionAlgorithms": [
        "RSAES_OAEP_SHA_1",
        "RSAES_OAEP_SHA_256"
    ],
    "PublicKey": "MIIBojANBgkqhkiG..."
}
```

# オフラインオペレーションの例
<a name="offline-operations"></a>

非対称 KMS キーペアの[パブリックキーをダウンロード](download-public-key.md)したら、それを他のユーザーと共有し、オフラインオペレーションの実行に使用することができます。

AWS CloudTrail リクエスト、レスポンス、日付、時刻、承認されたユーザーなど、すべての AWS KMS オペレーションを記録する ログは、 の外部でパブリックキーの使用を記録しません AWS KMS。

このトピックでは、オフラインオペレーションの例と、オフラインオペレーションを簡単にするためにツール AWS KMS が提供する詳細について説明します。

**Topics**
+ [オフラインで共有シークレットを取得する](#key-spec-ecc-offline)
+ [ML-DSA キーペアによるオフライン検証](#mldsa-offline-verification)
+ [SM2 キーペアによるオフライン検証 (中国リージョンのみ)](#key-spec-sm-offline-verification)

## オフラインで共有シークレットを取得する
<a name="key-spec-ecc-offline"></a>

ECC キーペアの[パブリックキーをダウンロード](download-public-key.md)し、オフラインオペレーション、つまり AWS KMSの外部でのオペレーションに使用することができます。

次の [OpenSSL](https://openssl.org/) チュートリアルでは、ECC KMS キーペアのパブリックキーと OpenSSL で作成されたプライベートキー AWS KMS を使用して、 外で共有シークレットを取得する 1 つの方法を示します。

1. OpenSSL で ECC キーペアを作成し、 で使用する準備をします AWS KMS。

   ```
   // Create an ECC key pair in OpenSSL and save the private key in openssl_ecc_key_priv.pem
   export OPENSSL_CURVE_NAME="P-256"
   export KMS_CURVE_NAME="ECC_NIST_P256"
   
   export OPENSSL_KEY1_PRIV_PEM="openssl_ecc_key1_priv.pem"
   openssl ecparam -name ${OPENSSL_CURVE_NAME} -genkey -out ${OPENSSL_KEY1_PRIV_PEM}                    
                       
   // Derive the public key from the private key                    
   export OPENSSL_KEY1_PUB_PEM="openssl_ecc_key1_pub.pem"
   openssl ec -in ${OPENSSL_KEY1_PRIV_PEM} -pubout -outform pem \
       -out ${OPENSSL_KEY1_PUB_PEM}                    
                       
   // View the PEM file containing the public key and extract the public key as a 
   // Base64 encoded string into OPENSSL_KEY1_PUB_BASE64 for use with AWS KMS
   export OPENSSL_KEY1_PUB_BASE64=`cat ${OPENSSL_KEY1_PUB_PEM} | \
       tee /dev/stderr | grep -v "PUBLIC KEY" | tr -d "\n"`
   ```

1. で ECC キーアグリーメントキーペアを作成し AWS KMS 、OpenSSL で使用する準備をします。

   ```
   // Create a KMS key on the same curve as the key pair from step 1 
   // with a key usage of KEY_AGREEMENT
   // Save its ARN in KMS_KEY1_ARN.
   export KMS_KEY1_ARN=`aws kms create-key --key-spec ${KMS_CURVE_NAME} \
       --key-usage KEY_AGREEMENT | tee /dev/stderr | jq -r .KeyMetadata.Arn`
   
   // Download the public key and save the Base64-encoded version in KMS_KEY1_PUB_BASE64        
   export KMS_KEY1_PUB_BASE64=`aws kms get-public-key --key-id ${KMS_KEY1_ARN} | \
       tee /dev/stderr | jq -r .PublicKey`                    
                       
   // Create a PEM file for the public KMS key for use with OpenSSL   
   export KMS_KEY1_PUB_PEM="aws_kms_ecdh_key1_pub.pem"
   echo "-----BEGIN PUBLIC KEY-----" > ${KMS_KEY1_PUB_PEM}
   echo ${KMS_KEY1_PUB_BASE64} | fold -w 64 >> ${KMS_KEY1_PUB_PEM}
   echo "-----END PUBLIC KEY-----" >> ${KMS_KEY1_PUB_PEM}
   ```

1. OpenSSL のプライベートキーとパブリック KMS キーを使用して、OpenSSL で共有シークレットを取得します。

   ```
   export OPENSSL_SHARED_SECRET1_BIN="openssl_shared_secret1.bin"
   openssl pkeyutl -derive -inkey ${OPENSSL_KEY1_PRIV_PEM} \
       -peerkey ${KMS_KEY1_PUB_PEM} -out ${OPENSSL_SHARED_SECRET1_BIN}
   ```

## ML-DSA キーペアによるオフライン検証
<a name="mldsa-offline-verification"></a>

AWS KMS は、最大 4 KB バイトのメッセージについて[連邦情報処理規格 (FIPS) 204 標準](https://csrc.nist.gov/pubs/fips/204/final)セクション 3.4 で説明されているように、ML-DSA 署名のヘッジされたバリアントをサポートします。

4 KB を超えるメッセージに署名するには、メッセージの前処理ステップを の外部で実行します AWS KMS。このハッシュステップでは、NIST FIPS 204 セクション 6.2 で定義されているように、64 バイトのメッセージ表現 μ を作成します。

AWS KMS には、4 KB を超えるメッセージ`EXTERNAL_MU`に対して というメッセージタイプがあります。`RAW` メッセージタイプの代わりにこれを使用すると、次のようになります AWS KMS。
+ ハッシュステップが既に実行されていることが前提となります。
+ 内部ハッシュプロセスがスキップされます。
+ 任意のサイズのメッセージで機能します。

メッセージを検証する場合、使用する方法は、外部システムまたはライブラリのサイズ制限と、64 バイトのメッセージ表現 μ をサポートしているかどうかに応じて異なります。
+ メッセージがサイズ制限より小さい場合は、`RAW` メッセージタイプを使用します。
+ メッセージがサイズ制限より大きい場合は、外部システムで表現 μ を使用します。

以下のセクションでは、 を使用してメッセージに署名 AWS KMS し、OpenSSL を使用してメッセージを検証する方法を示します。によって課される 4 KB のメッセージサイズ制限の下と上の両方のメッセージの例を示します AWS KMS。OpenSSL では、検証のためのメッセージサイズ制限は適用されません。

どちらの例でも、まずパブリックキーを取得します AWS KMS。次の AWS CLI コマンドを使用します。

```
aws kms get-public-key \
    --key-id _<1234abcd-12ab-34cd-56ef-1234567890ab>_ \
    --output text \
    --query PublicKey | base64 --decode > public_key.der
```

### メッセージサイズが 4KB 未満の場合
<a name="mldsa-offline-verification-less-than-4KB"></a>

4 KB 未満のメッセージの場合は、 で`RAW`メッセージタイプを使用します AWS KMS。`EXTERNAL_MU` を使用できますが、サイズ制限内のメッセージには必要ありません。

次の AWS CLI コマンドを使用してメッセージに署名します。

```
aws kms sign \
    --key-id _<1234abcd-12ab-34cd-56ef-1234567890ab>_ \
    --message 'your message' \
    --message-type RAW \
    --signing-algorithm ML_DSA_SHAKE_256 \
    --output text \
    --query Signature | base64 --decode > ExampleSignature.bin
```

OpenSSL を使用してこのメッセージを確認するには、次のコマンドを使用します。

```
echo -n 'your message' | ./openssl dgst -verify public_key.der -signature ExampleSignature.bin
```

### 4KB を超えるメッセージサイズの場合
<a name="mldsa-offline-verification-more-than-4KB"></a>

4KB を超えるメッセージに署名するには、`EXTERNAL_MU` メッセージタイプを使用します。`EXTERNAL_MU` を使用する場合は、NIST FIPS 204 セクション 6.2 で定義されている 64 バイトの表現 μ にメッセージを外部で事前にハッシュし、署名または検証オペレーションに渡します。これは、NIST FIPS 204 セクション 5.4 で定義されている「Pre-hash MLDSA」(HashML-DSA) とは異なることに注意してください。

1. まず、メッセージプレフィックスを作成します。プレフィックスには、ドメイン区切り文字、コンテキストの長さ、コンテキストが含まれます。ドメイン区切り文字とコンテキストの長さのデフォルトは 0 です。

1. メッセージプレフィックスをメッセージの先頭に追加します。

1. SHAKE256 を使用してパブリックキーをハッシュし、ステップ 2 の結果の先頭に追加します。

1. 最後に、ステップ 3 の結果をハッシュして 64 バイトの `EXTERNAL_MU` を生成します。

次の例では、OpenSSL 3.5 を使用して `EXTERNAL_MU` を構築します。

```
{
    openssl asn1parse -inform DER -in public_key.der -strparse 17 -noout -out - 2>/dev/null |
    openssl dgst -provider default -shake256 -xoflen 64 -binary;
    printf '\x00\x00';
    echo -n "your message"
} | openssl dgst -provider default -shake256 -xoflen 64 -binary > mu.bin
```

`mu.bin` ファイルを作成したら、次のコマンドを使用して AWS KMS API を呼び出し、メッセージに署名します。

```
aws kms sign \
    --key-id _<1234abcd-12ab-34cd-56ef-1234567890ab>_ \
    --message fileb://mu.bin \
    --message-type EXTERNAL_MU \
    --signing-algorithm ML_DSA_SHAKE_256 \
    --output text \
    --query Signature | base64 --decode > ExampleSignature.bin
```

結果の署名は、元のメッセージの `RAW` 署名と同じです。同じ OpenSSL 3.5 コマンドを使用してメッセージを検証できます。

```
echo -n 'your message' | ./openssl dgst -verify public_key.der -signature ExampleSignature.bin
```

## SM2 キーペアによるオフライン検証 (中国リージョンのみ)
<a name="key-spec-sm-offline-verification"></a>

SM2 パブリックキー AWS KMS を使用して の外部の署名を検証するには、識別 ID を指定する必要があります。未加工のメッセージ を [Sign](https://docs.aws.amazon.com/kms/latest/APIReference/API_Sign.html) API [https://docs.aws.amazon.com/kms/latest/APIReference/API_Sign.html#KMS-Sign-request-MessageType](https://docs.aws.amazon.com/kms/latest/APIReference/API_Sign.html#KMS-Sign-request-MessageType)に渡すと、 AWS KMS は `1234567812345678`GM/T 0009-2012 の OSCCA で定義されたデフォルトの識別 ID を使用します。独自の識別 ID を AWS KMSで指定することはできません。

ただし、 の外部でメッセージダイジェストを生成する場合は AWS、独自の識別 ID を指定し、メッセージダイジェスト を [https://docs.aws.amazon.com/kms/latest/APIReference/API_Sign.html#API_Sign_RequestSyntax](https://docs.aws.amazon.com/kms/latest/APIReference/API_Sign.html#API_Sign_RequestSyntax)に渡 AWS KMS して署名できます。これを行うには、`SM2OfflineOperationHelper` クラスの `DEFAULT_DISTINGUISHING_ID` 値を変更します。指定する識別 ID は、最大 8,192 文字の任意の文字列です。がメッセージダイジェスト AWS KMS に署名したら、メッセージダイジェストまたはメッセージ、およびダイジェストを計算してオフラインで検証するために使用される識別 ID のいずれかが必要です。

**重要**  
`SM2OfflineOperationHelper` リファレンスコードは [Bouncy Castle](https://www.bouncycastle.org/documentation/documentation-java/) バージョン 1.68 と互換性があるように設計されています。他のバージョンに関するヘルプについては、[bouncycastle.org](https://www.bouncycastle.org) にアクセスしてください。

### `SM2OfflineOperationHelper` クラス
<a name="key-spec-sm-offline-helper"></a>

SM2 キーのオフライン操作の支援向けに、Java の `SM2OfflineOperationHelper` クラスにはいくつかのタスク実行メソッドが用意されています。このヘルパークラスは、他の暗号化プロバイダのモデルとして使用できます。

内では AWS KMS、raw 暗号文変換と SM2DSA メッセージダイジェスト計算が自動的に行われます。どの暗号化プロバイダーも同じ方法で SM2 を実装しているとは限りません。[OpenSSL](https://openssl.org/) バージョン 1.1.1 以降などの一部のライブラリは、これらのアクションを自動的に実行します。 は、OpenSSL バージョン 3.0 でのテストでこの動作 AWS KMS を確認しました。変換と計算を手動で実行するには、[Bouncy Castle](https://www.bouncycastle.org/java.html) などのライブラリを持つ以下の `SM2OfflineOperationHelper` クラスを使用します。

`SM2OfflineOperationHelper` クラスは、次のオフラインオペレーションのためのメソッドを提供します。
+   
**メッセージダイジェストの計算**  
オフライン検証に使用できる、または に渡 AWS KMS して署名できるメッセージダイジェストをオフラインで生成するには、 `calculateSM2Digest`メソッドを使用します。`calculateSM2Digest` メソッドは SM3 ハッシュアルゴリズムでメッセージダイジェストを生成します。[GetPublicKey](https://docs.aws.amazon.com/kms/latest/APIReference/API_GetPublicKey.html) API は、パブリックキーをバイナリ形式で返します。バイナリキーを解析して Java PublicKey にする必要があります。解析されたパブリックキーをメッセージとともに提供します。このメソッドは、メッセージをデフォルトの識別 ID、`1234567812345678` と自動的に組み合わせますが、`DEFAULT_DISTINGUISHING_ID` 値を変更して、独自の識別 ID を設定することもできます。
+   
**検証**  
署名をオフラインで検証するには、`offlineSM2DSAVerify` メソッドを使用します。`offlineSM2DSAVerify` メソッドは、指定された識別 ID から計算されたメッセージダイジェストと、指定された元のメッセージを使用してデジタル署名を検証します。[GetPublicKey](https://docs.aws.amazon.com/kms/latest/APIReference/API_GetPublicKey.html) API は、パブリックキーをバイナリ形式で返します。バイナリキーを解析して Java PublicKey にする必要があります。解析されたパブリックキーに、元のメッセージと検証する署名を指定します。詳細については、「[SM2 キーペアによるオフライン検証](#key-spec-sm-offline-verification)」を参照してください。
+   
**暗号化**  
プレーンテキストをオフラインで暗号化するには、`offlineSM2PKEEncrypt` メソッドを使用します。この方法では、暗号文が復号 AWS KMS できる形式になります。`offlineSM2PKEEncrypt` メソッドは、プレーンテキストを暗号化し、生成された生の暗号文を SM2PKE によって ASN.1 形式に変換します。[GetPublicKey](https://docs.aws.amazon.com/kms/latest/APIReference/API_GetPublicKey.html) API は、パブリックキーをバイナリ形式で返します。バイナリキーを解析して Java PublicKey にする必要があります。解析したパブリックキーに、暗号化するプレーンテキストを指定します。  
変換を実行する必要があるかどうかわからない場合は、次の OpenSSL オペレーション使用して暗号文の形式をテストします。オペレーションが失敗した場合は、暗号文を ASN.1 形式に変換する必要があります。  

  ```
  openssl asn1parse -inform DER -in ciphertext.der
  ```

デフォルトでは、SM2DSA オペレーションのメッセージダイジェストを生成するとき、`SM2OfflineOperationHelper` クラスはデフォルトの識別 ID、`1234567812345678` を使用します。

```
package com.amazon.kms.utils;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.IOException;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.PublicKey;

import org.bouncycastle.crypto.CryptoException;
import org.bouncycastle.jce.interfaces.ECPublicKey;

import java.util.Arrays;

import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.gm.GMNamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.params.ParametersWithID;
import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.crypto.signers.SM2Signer;
import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil;

public class SM2OfflineOperationHelper {
    // You can change the DEFAULT_DISTINGUISHING_ID value to set your own distinguishing ID,
    // the DEFAULT_DISTINGUISHING_ID can be any string up to 8,192 characters long.
    private static final byte[] DEFAULT_DISTINGUISHING_ID = "1234567812345678".getBytes(StandardCharsets.UTF_8);
    private static final X9ECParameters SM2_X9EC_PARAMETERS = GMNamedCurves.getByName("sm2p256v1");

    // ***calculateSM2Digest***
    // Calculate message digest
    public static byte[] calculateSM2Digest(final PublicKey publicKey, final byte[] message) throws
            NoSuchProviderException, NoSuchAlgorithmException {
        final ECPublicKey ecPublicKey = (ECPublicKey) publicKey;

        // Generate SM3 hash of default distinguishing ID, 1234567812345678
        final int entlenA = DEFAULT_DISTINGUISHING_ID.length * 8;
        final byte [] entla = new byte[] { (byte) (entlenA & 0xFF00), (byte) (entlenA & 0x00FF) };
        final byte [] a = SM2_X9EC_PARAMETERS.getCurve().getA().getEncoded();
        final byte [] b = SM2_X9EC_PARAMETERS.getCurve().getB().getEncoded();
        final byte [] xg = SM2_X9EC_PARAMETERS.getG().getXCoord().getEncoded();
        final byte [] yg = SM2_X9EC_PARAMETERS.getG().getYCoord().getEncoded();
        final byte[] xa = ecPublicKey.getQ().getXCoord().getEncoded();
        final byte[] ya = ecPublicKey.getQ().getYCoord().getEncoded();
        final byte[] za = MessageDigest.getInstance("SM3", "BC")
                .digest(ByteBuffer.allocate(entla.length + DEFAULT_DISTINGUISHING_ID.length + a.length + b.length + xg.length + yg.length +
                        xa.length + ya.length).put(entla).put(DEFAULT_DISTINGUISHING_ID).put(a).put(b).put(xg).put(yg).put(xa).put(ya)
                        .array());

        // Combine hashed distinguishing ID with original message to generate final digest
        return MessageDigest.getInstance("SM3", "BC")
                .digest(ByteBuffer.allocate(za.length + message.length).put(za).put(message)
                        .array());
    }

    // ***offlineSM2DSAVerify***
    // Verify digital signature with SM2 public key
    public static boolean offlineSM2DSAVerify(final PublicKey publicKey, final byte [] message,
            final byte [] signature) throws InvalidKeyException {
        final SM2Signer signer = new SM2Signer();
        CipherParameters cipherParameters = ECUtil.generatePublicKeyParameter(publicKey);
        cipherParameters = new ParametersWithID(cipherParameters, DEFAULT_DISTINGUISHING_ID);
        signer.init(false, cipherParameters);
        signer.update(message, 0, message.length);
        return signer.verifySignature(signature);
    }

    // ***offlineSM2PKEEncrypt***
    // Encrypt data with SM2 public key
    public static byte[] offlineSM2PKEEncrypt(final PublicKey publicKey, final byte [] plaintext) throws
            NoSuchPaddingException, NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException,
            BadPaddingException, IllegalBlockSizeException, IOException {
        final Cipher sm2Cipher = Cipher.getInstance("SM2", "BC");
        sm2Cipher.init(Cipher.ENCRYPT_MODE, publicKey);

        // By default, Bouncy Castle returns raw ciphertext in the c1c2c3 format
        final byte [] cipherText = sm2Cipher.doFinal(plaintext);

        // Convert the raw ciphertext to the ASN.1 format before passing it to AWS KMS
        final ASN1EncodableVector asn1EncodableVector = new ASN1EncodableVector();
        final int coordinateLength = (SM2_X9EC_PARAMETERS.getCurve().getFieldSize() + 7) / 8 * 2 + 1;
        final int sm3HashLength = 32;
        final int xCoordinateInCipherText = 33;
        final int yCoordinateInCipherText = 65;
        byte[] coords = new byte[coordinateLength];
        byte[] sm3Hash = new byte[sm3HashLength];
        byte[] remainingCipherText = new byte[cipherText.length - coordinateLength - sm3HashLength];

        // Split components out of the ciphertext
        System.arraycopy(cipherText, 0, coords, 0, coordinateLength);
        System.arraycopy(cipherText, cipherText.length - sm3HashLength, sm3Hash, 0, sm3HashLength);
        System.arraycopy(cipherText, coordinateLength, remainingCipherText, 0,cipherText.length - coordinateLength - sm3HashLength);

        // Build standard SM2PKE ASN.1 ciphertext vector
        asn1EncodableVector.add(new ASN1Integer(new BigInteger(1, Arrays.copyOfRange(coords, 1, xCoordinateInCipherText))));
        asn1EncodableVector.add(new ASN1Integer(new BigInteger(1, Arrays.copyOfRange(coords, xCoordinateInCipherText, yCoordinateInCipherText))));
        asn1EncodableVector.add(new DEROctetString(sm3Hash));
        asn1EncodableVector.add(new DEROctetString(remainingCipherText));

        return new DERSequence(asn1EncodableVector).getEncoded("DER");
    }
}
```