

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 原始 ECDH keyring
<a name="use-raw-ecdh-keyring"></a>


****  

|  | 
| --- |
| 我們的用戶端加密程式庫已重新命名為 AWS 資料庫加密 SDK。此開發人員指南仍提供有關 [DynamoDB 加密用戶端](legacy-dynamodb-encryption-client.md)的資訊。 | 

**重要**  
原始 ECDH keyring 僅適用於材質提供者程式庫的 1.5.0 版。

原始 ECDH keyring 會使用您提供的橢圓曲線公有/私有金鑰對，在兩方之間衍生共用包裝金鑰。首先， keyring 會使用寄件者的私有金鑰、收件人的公有金鑰和橢圓曲線 Diffie-Hellman (ECDH) 金鑰協議演算法衍生共用秘密。然後， keyring 會使用共用秘密來衍生保護資料加密金鑰的共用包裝金鑰。 AWS Database Encryption SDK 用來衍生共用包裝金鑰的金鑰衍生函數 (`KDF_CTR_HMAC_SHA384`) 符合[金鑰衍生的 NIST 建議](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-108r1-upd1.pdf)。

金鑰衍生函數會傳回 64 個位元組的金鑰材料。為了確保雙方都使用正確的金鑰材料， AWS 資料庫加密 SDK 會使用前 32 個位元組做為承諾金鑰，最後 32 個位元組做為共用包裝金鑰。在解密時，如果 keyring 無法重現存放在加密記錄的材料描述欄位中的相同承諾金鑰和共用包裝金鑰，則操作會失敗。例如，如果您使用使用 **Alice** 私有金鑰和 **Bob** 公有金鑰設定的 keyring 加密記錄，則使用 **Bob **私有金鑰和 **Alice 公**有金鑰設定的 keyring 將重現相同的承諾金鑰和共用包裝金鑰，並能夠解密記錄。如果 Bob 的公有 AWS KMS key 金鑰來自 對，則 Bob 可以建立 [AWS KMS ECDH keyring](use-kms-ecdh-keyring.md) 來解密記錄。

原始 ECDH keyring 使用 AES-GCM 使用對稱金鑰加密記錄。然後，資料金鑰會使用 AES-GCM 使用衍生的共用包裝金鑰進行信封加密。每個原始 ECDH keyring 只能有一個共用包裝金鑰，但您可以在多 keyring 中單獨包含多個原始 ECDH keyring 或與其他 [keyring ](use-multi-keyring.md)一起包含。

您負責產生、儲存和保護您的私有金鑰，最好是在硬體安全模組 (HSM) 或金鑰管理系統中。寄件者和收件人的金鑰對大多位於相同的橢圓曲線上。 AWS Database Encryption SDK 支援下列橢圓立方體規格：
+ `ECC_NIST_P256`
+ `ECC_NIST_P384`
+ `ECC_NIST_P512`

## 建立原始 ECDH keyring
<a name="raw-ecdh-create"></a>

原始 ECDH keyring 支援三個金鑰協議結構描述：`RawPrivateKeyToStaticPublicKey`、 `EphemeralPrivateKeyToStaticPublicKey`和 `PublicKeyDiscovery`。您選取的金鑰協議結構描述會決定您可以執行哪些密碼編譯操作，以及如何組合金鑰材料。

**Topics**
+ [RawPrivateKeyToStaticPublicKey](#raw-ecdh-RawPrivateKeyToStaticPublicKey)
+ [EphemeralPrivateKeyToStaticPublicKey](#raw-ecdh-EphemeralPrivateKeyToStaticPublicKey)
+ [PublicKeyDiscovery](#raw-ecdh-PublicKeyDiscovery)

### RawPrivateKeyToStaticPublicKey
<a name="raw-ecdh-RawPrivateKeyToStaticPublicKey"></a>

使用`RawPrivateKeyToStaticPublicKey`金鑰協議結構描述，在 keyring 中靜態設定寄件者的私有金鑰和收件人的公有金鑰。此金鑰協議結構描述可以加密和解密記錄。

若要使用`RawPrivateKeyToStaticPublicKey`金鑰協議結構描述初始化原始 ECDH keyring，請提供下列值：
+ **寄件者的私有金鑰**

  您必須提供寄件者的 PEM 編碼私有金鑰 (PKCS \$18 PrivateKeyInfo 結構），如 [RFC 5958 ](https://tools.ietf.org/html/rfc5958#section-2)所定義。
+ **收件人的公有金鑰**

  您必須提供收件人的 DER 編碼 X.509 公有金鑰，也稱為 `SubjectPublicKeyInfo`(SPKI)，如 [RFC 5280 ](https://tools.ietf.org/html/rfc5280)所定義。

  您可以指定非對稱金鑰協議 KMS 金鑰對的公有金鑰，或從外部產生的金鑰對的公有金鑰 AWS。
+ **曲線規格**

  識別指定金鑰對中的橢圓曲線規格。寄件者和收件人的金鑰對必須具有相同的曲線規格。

  有效值：`ECC_NIST_P256`、`ECC_NIS_P384`、`ECC_NIST_P512`

------
#### [ C\$1 / .NET ]

```
// Instantiate material providers
var materialProviders = new MaterialProviders(new MaterialProvidersConfig());
	    var BobPrivateKey = new MemoryStream(new byte[] { });
	    var AlicePublicKey = new MemoryStream(new byte[] { });

	    // Create the Raw ECDH static keyring
	    var staticConfiguration = new RawEcdhStaticConfigurations()
	    {
		    RawPrivateKeyToStaticPublicKey = new RawPrivateKeyToStaticPublicKeyInput
		    {
			    SenderStaticPrivateKey = BobPrivateKey,
			    RecipientPublicKey = AlicePublicKey
		    }
	    };
	    
	    var createKeyringInput = new CreateRawEcdhKeyringInput() 
	    {
		    CurveSpec = ECDHCurveSpec.ECC_NIST_P256,
		    KeyAgreementScheme = staticConfiguration 
	    };

	    var keyring = materialProviders.CreateRawEcdhKeyring(createKeyringInput);
```

------
#### [ Java ]

下列 Java 範例使用`RawPrivateKeyToStaticPublicKey`金鑰協議結構描述來靜態設定寄件者的私有金鑰和收件人的公有金鑰。兩個金鑰對都在`ECC_NIST_P256`曲線上。

```
private static void StaticRawKeyring() {
    // Instantiate material providers
    final MaterialProviders materialProviders =
      MaterialProviders.builder()
        .MaterialProvidersConfig(MaterialProvidersConfig.builder().build())
        .build();

    KeyPair senderKeys = GetRawEccKey();
    KeyPair recipient = GetRawEccKey();

    // Create the Raw ECDH static keyring
    final CreateRawEcdhKeyringInput rawKeyringInput =
      CreateRawEcdhKeyringInput.builder()
        .curveSpec(ECDHCurveSpec.ECC_NIST_P256)
        .KeyAgreementScheme(
          RawEcdhStaticConfigurations.builder()
            .RawPrivateKeyToStaticPublicKey(
                RawPrivateKeyToStaticPublicKeyInput.builder()
                  // Must be a PEM-encoded private key
                  .senderStaticPrivateKey(ByteBuffer.wrap(senderKeys.getPrivate().getEncoded()))
                  // Must be a DER-encoded X.509 public key
                  .recipientPublicKey(ByteBuffer.wrap(recipient.getPublic().getEncoded()))
                  .build()
            )
            .build()
        ).build();

    final IKeyring staticKeyring = materialProviders.CreateRawEcdhKeyring(rawKeyringInput);
}
```

------
#### [ Rust ]

下列 Python 範例使用`raw_ecdh_static_configuration`金鑰協議結構描述來靜態設定寄件者的私有金鑰和收件人的公有金鑰。兩個金鑰對必須位於相同的曲線上。

```
// Create keyring input
let raw_ecdh_static_configuration_input =
    RawPrivateKeyToStaticPublicKeyInput::builder()
        // Must be a UTF8 PEM-encoded private key
        .sender_static_private_key(private_key_sender_utf8_bytes)
        // Must be a UTF8 DER-encoded X.509 public key
        .recipient_public_key(public_key_recipient_utf8_bytes)
        .build()?;

let raw_ecdh_static_configuration = RawEcdhStaticConfigurations::RawPrivateKeyToStaticPublicKey(raw_ecdh_static_configuration_input);

// Instantiate the material providers library
let mpl_config = MaterialProvidersConfig::builder().build()?;
let mpl = mpl_client::Client::from_conf(mpl_config)?;

// Create raw ECDH static keyring
let raw_ecdh_keyring = mpl
    .create_raw_ecdh_keyring()
    .curve_spec(ecdh_curve_spec)
    .key_agreement_scheme(raw_ecdh_static_configuration)
    .send()
    .await?;
```

------

### EphemeralPrivateKeyToStaticPublicKey
<a name="raw-ecdh-EphemeralPrivateKeyToStaticPublicKey"></a>

使用`EphemeralPrivateKeyToStaticPublicKey`金鑰協議結構描述設定的 keyring 會在本機建立新的金鑰對，並針對每個加密呼叫衍生唯一的共用包裝金鑰。

此金鑰協議結構描述只能加密記錄。若要解密使用`EphemeralPrivateKeyToStaticPublicKey`金鑰協議結構描述加密的記錄，您必須使用以相同收件人的公有金鑰設定的探索金鑰協議結構描述。若要解密，您可以使用原始 ECDH keyring 搭配[`PublicKeyDiscovery`](#raw-ecdh-PublicKeyDiscovery)金鑰協議演算法，或者，如果收件人的公有金鑰來自非對稱金鑰協議 KMS 金鑰對，您可以使用 AWS KMS ECDH keyring 搭配 [KmsPublicKeyDiscovery](use-kms-ecdh-keyring.md#kms-ecdh-discovery) 金鑰協議結構描述。

若要使用`EphemeralPrivateKeyToStaticPublicKey`金鑰協議結構描述初始化原始 ECDH keyring，請提供下列值：
+ **收件人的公有金鑰**

  您必須提供收件人的 DER 編碼 X.509 公有金鑰，也稱為 `SubjectPublicKeyInfo`(SPKI)，如 [RFC 5280 ](https://tools.ietf.org/html/rfc5280)所定義。

  您可以指定非對稱金鑰協議 KMS 金鑰對的公有金鑰，或從外部產生的金鑰對的公有金鑰 AWS。
+ **曲線規格**

  識別指定公有金鑰中的橢圓曲線規格。

  加密時， keyring 會在指定的曲線上建立新的金鑰對，並使用新的私有金鑰和指定的公有金鑰來衍生共用包裝金鑰。

  有效值：`ECC_NIST_P256`、`ECC_NIS_P384`、`ECC_NIST_P512`

------
#### [ C\$1 / .NET ]

下列範例會使用`EphemeralPrivateKeyToStaticPublicKey`金鑰協議結構描述建立原始 ECDH keyring。加密時， keyring 將在指定的`ECC_NIST_P256`曲線上於本機建立新的金鑰對。

```
// Instantiate material providers
var materialProviders = new MaterialProviders(new MaterialProvidersConfig());
	    var AlicePublicKey = new MemoryStream(new byte[] { });

	    // Create the Raw ECDH ephemeral keyring
	    var ephemeralConfiguration = new RawEcdhStaticConfigurations()
	    {
		    EphemeralPrivateKeyToStaticPublicKey = new EphemeralPrivateKeyToStaticPublicKeyInput
		    {
			    RecipientPublicKey = AlicePublicKey
		    }
	    };
	    
	    var createKeyringInput = new CreateRawEcdhKeyringInput() 
	    {
		    CurveSpec = ECDHCurveSpec.ECC_NIST_P256,
		    KeyAgreementScheme = ephemeralConfiguration
	    };

	    var keyring = materialProviders.CreateRawEcdhKeyring(createKeyringInput);
```

------
#### [ Java ]

下列範例會使用`EphemeralPrivateKeyToStaticPublicKey`金鑰協議結構描述建立原始 ECDH keyring。加密時， keyring 將在指定的`ECC_NIST_P256`曲線上於本機建立新的金鑰對。

```
private static void EphemeralRawEcdhKeyring() {
    // Instantiate material providers
    final MaterialProviders materialProviders =
      MaterialProviders.builder()
        .MaterialProvidersConfig(MaterialProvidersConfig.builder().build())
        .build();

    ByteBuffer recipientPublicKey = getPublicKeyBytes();

    // Create the Raw ECDH ephemeral keyring
    final CreateRawEcdhKeyringInput ephemeralInput =
      CreateRawEcdhKeyringInput.builder()
        .curveSpec(ECDHCurveSpec.ECC_NIST_P256)
        .KeyAgreementScheme(
          RawEcdhStaticConfigurations.builder()
            .EphemeralPrivateKeyToStaticPublicKey(
              EphemeralPrivateKeyToStaticPublicKeyInput.builder()
                .recipientPublicKey(recipientPublicKey)
                .build()
            )
            .build()
        ).build();

    final IKeyring ephemeralKeyring = materialProviders.CreateRawEcdhKeyring(ephemeralInput);
}
```

------
#### [ Rust ]

下列範例會使用`ephemeral_raw_ecdh_static_configuration`金鑰協議結構描述建立原始 ECDH keyring。加密時， keyring 會在指定的曲線上於本機建立新的金鑰對。

```
// Create EphemeralPrivateKeyToStaticPublicKeyInput
let ephemeral_raw_ecdh_static_configuration_input =
    EphemeralPrivateKeyToStaticPublicKeyInput::builder()
        // Must be a UTF8 DER-encoded X.509 public key
        .recipient_public_key(public_key_recipient_utf8_bytes)
        .build()?;

let ephemeral_raw_ecdh_static_configuration =
    RawEcdhStaticConfigurations::EphemeralPrivateKeyToStaticPublicKey(ephemeral_raw_ecdh_static_configuration_input);

// Instantiate the material providers library
let mpl_config = MaterialProvidersConfig::builder().build()?;
let mpl = mpl_client::Client::from_conf(mpl_config)?;

// Create raw ECDH ephemeral private key keyring
let ephemeral_raw_ecdh_keyring = mpl
    .create_raw_ecdh_keyring()
    .curve_spec(ecdh_curve_spec)
    .key_agreement_scheme(ephemeral_raw_ecdh_static_configuration)
    .send()
    .await?;
```

------

### PublicKeyDiscovery
<a name="raw-ecdh-PublicKeyDiscovery"></a>

解密時，最佳實務是指定 AWS 資料庫加密 SDK 可以使用的包裝金鑰。若要遵循此最佳實務，請使用指定寄件者私有金鑰和收件人公有金鑰的 ECDH keyring。不過，您也可以建立原始 ECDH 探索 keyring，也就是原始 ECDH keyring，該 keyring 可以解密指定金鑰的公有金鑰與儲存在加密記錄的資料描述欄位中的收件人公有金鑰的任何記錄。此金鑰協議結構描述只能解密記錄。

**重要**  
當您使用`PublicKeyDiscovery`金鑰協議結構描述解密記錄時，您接受所有公有金鑰，無論誰擁有它。

若要使用`PublicKeyDiscovery`金鑰協議結構描述初始化原始 ECDH keyring，請提供下列值：
+ **收件人的靜態私有金鑰**

  您必須提供收件人的 PEM 編碼私有金鑰 (PKCS \$18 PrivateKeyInfo 結構），如 [RFC 5958 ](https://tools.ietf.org/html/rfc5958#section-2)所定義。
+ **曲線規格**

  識別指定私有金鑰中的橢圓曲線規格。寄件者和收件人的金鑰對必須具有相同的曲線規格。

  有效值：`ECC_NIST_P256`、`ECC_NIS_P384`、`ECC_NIST_P512`

------
#### [ C\$1 / .NET ]

下列範例會使用`PublicKeyDiscovery`金鑰協議結構描述建立原始 ECDH keyring。此 keyring 可以解密任何記錄，其中指定的私有金鑰的公有金鑰符合存放在加密記錄的材料描述欄位中的收件人公有金鑰。

```
// Instantiate material providers
var materialProviders = new MaterialProviders(new MaterialProvidersConfig());
	    var AlicePrivateKey = new MemoryStream(new byte[] { });

	    // Create the Raw ECDH discovery keyring
	    var discoveryConfiguration = new RawEcdhStaticConfigurations()
	    {
		    PublicKeyDiscovery = new PublicKeyDiscoveryInput
		    {
			    RecipientStaticPrivateKey = AlicePrivateKey
		    }
	    };
	    
	    var createKeyringInput = new CreateRawEcdhKeyringInput() 
	    {
		    CurveSpec = ECDHCurveSpec.ECC_NIST_P256,
		    KeyAgreementScheme = discoveryConfiguration 
	    };

	    var keyring = materialProviders.CreateRawEcdhKeyring(createKeyringInput);
```

------
#### [ Java ]

下列範例會使用`PublicKeyDiscovery`金鑰協議結構描述建立原始 ECDH keyring。此 keyring 可以解密任何記錄，其中指定的私有金鑰的公有金鑰符合存放在加密記錄的材料描述欄位中的收件人公有金鑰。

```
private static void RawEcdhDiscovery() {
    // Instantiate material providers
    final MaterialProviders materialProviders =
      MaterialProviders.builder()
        .MaterialProvidersConfig(MaterialProvidersConfig.builder().build())
        .build();

    KeyPair recipient = GetRawEccKey();

    // Create the Raw ECDH discovery keyring
    final CreateRawEcdhKeyringInput rawKeyringInput =
      CreateRawEcdhKeyringInput.builder()
        .curveSpec(ECDHCurveSpec.ECC_NIST_P256)
        .KeyAgreementScheme(
          RawEcdhStaticConfigurations.builder()
            .PublicKeyDiscovery(
              PublicKeyDiscoveryInput.builder()
                // Must be a PEM-encoded private key
                .recipientStaticPrivateKey(ByteBuffer.wrap(sender.getPrivate().getEncoded()))
                .build()
            )
            .build()
        ).build();

    final IKeyring publicKeyDiscovery  = materialProviders.CreateRawEcdhKeyring(rawKeyringInput);
}
```

------
#### [ Rust ]

下列範例會使用`discovery_raw_ecdh_static_configuration`金鑰協議結構描述建立原始 ECDH keyring。此 keyring 可以解密任何訊息，其中指定的私有金鑰的公有金鑰符合存放在訊息加密文字上的收件人公有金鑰。

```
// Create PublicKeyDiscoveryInput
let discovery_raw_ecdh_static_configuration_input =
    PublicKeyDiscoveryInput::builder()
        // Must be a UTF8 PEM-encoded private key
        .recipient_static_private_key(private_key_recipient_utf8_bytes)
        .build()?;

let discovery_raw_ecdh_static_configuration =
    RawEcdhStaticConfigurations::PublicKeyDiscovery(discovery_raw_ecdh_static_configuration_input);

// Create raw ECDH discovery private key keyring
let discovery_raw_ecdh_keyring = mpl
    .create_raw_ecdh_keyring()
    .curve_spec(ecdh_curve_spec)
    .key_agreement_scheme(discovery_raw_ecdh_static_configuration)
    .send()
    .await?;
```

------