

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 未加工的 ECDH 钥匙圈
<a name="use-raw-ecdh-keyring"></a>


****  

|  | 
| --- |
| 我们的客户端加密库已重命名为 AWS 数据库加密 SDK。本开发人员指南仍提供有关 [DynamoDB 加密客户端](legacy-dynamodb-encryption-client.md)的信息。 | 

**重要**  
Raw ECDH 密钥环仅在材质提供者库的 1.5.0 版本中可用。

Raw ECDH 密钥环使用您提供的椭圆曲线公私钥对来派生出双方之间的共享包装密钥。首先，密钥环使用发送者的私钥、收件人的公钥和 Elliptic Curve Diffie-Hellman (ECDH) 密钥协议算法派生出共享密钥。然后，密钥环使用共享密钥来派生用于保护您的数据加密密钥的共享包装密钥。 AWS 数据库加密 SDK 使用 (`KDF_CTR_HMAC_SHA384`) 派生共享包装密钥的密钥派生函数符合 [NIST 关于密钥派生的建议](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-108r1-upd1.pdf)。

密钥派生函数返回 64 字节的密钥材料。为确保双方使用正确的密钥材料， AWS 数据库加密 SDK 使用前 32 字节作为承诺密钥，使用最后 32 字节作为共享封装密钥。解密时，如果密钥环无法复制存储在加密记录材料描述字段中的相同承诺密钥和共享包装密钥，则操作将失败。例如，如果您使用配置有 **Alice 私钥和 **Bob** 公钥的**密钥环对记录进行加密，则使用 B **ob 的私钥和 Alice 的****公钥配置的**密钥环将复制相同的承诺密钥和共享包装密钥，并能够解密该记录。如果 Bob 的公钥来自一 AWS KMS key 对，那么 Bob 可以创建 [AWS KMS ECDH 密钥环](use-kms-ecdh-keyring.md)来解密记录。

Raw ECDH 密钥环使用 AES-GCM 使用对称密钥对记录进行加密。然后使用 AES-GCM 使用派生的共享包装密钥对数据密钥进行信封加密。[每个 Raw ECDH 密钥环只能有一个共享包装密钥，但您可以在多密钥环中单独或与其他密钥环一起包含多个 Raw ECDH 密钥环。](use-multi-keyring.md)

您负责生成、存储和保护您的私钥，最好是在硬件安全模块 (HSM) 或密钥管理系统中。发件人和收件人的密钥对在相同的椭圆曲线上。 AWS 数据库加密 SDK 支持以下椭圆曲线规格：
+ `ECC_NIST_P256`
+ `ECC_NIST_P384`
+ `ECC_NIST_P512`

## 创建原始的 ECDH 密钥环
<a name="raw-ecdh-create"></a>

Raw ECDH 密钥环支持三种密钥协议架构：`RawPrivateKeyToStaticPublicKey`、`EphemeralPrivateKeyToStaticPublicKey`和。`PublicKeyDiscovery`您选择的密钥协议架构决定了您可以执行哪些加密操作以及密钥材料的组装方式。

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

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

使用`RawPrivateKeyToStaticPublicKey`密钥协议架构在密钥环中静态配置发送者的私钥和收件人的公钥。此密钥协议架构可以加密和解密记录。

要使用密钥协议架构初始化 Raw ECDH `RawPrivateKeyToStaticPublicKey` 密钥环，请提供以下值：
+ **发件人的私钥**

  [您必须提供发件人的 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`密钥环在本地创建新的密钥对，并为每个加密调用派生一个唯一的共享包装密钥。

此密钥协议架构只能加密记录。要解密使用密`EphemeralPrivateKeyToStaticPublicKey`钥协议架构加密的记录，必须使用配置有相同收件人公钥的发现密钥协议架构。要解密，您可以使用带有密钥协议算法的原始 ECDH 密钥环，或者，如果接收者的公[`PublicKeyDiscovery`](#raw-ecdh-PublicKeyDiscovery)钥来自非对称密钥协议 KMS 密钥对，则可以将 AWS KMS ECDH 密钥环与密钥协议架构一起使用。[KmsPublicKeyDiscovery](use-kms-ecdh-keyring.md#kms-ecdh-discovery)

要使用密钥协议架构初始化 Raw ECDH `EphemeralPrivateKeyToStaticPublicKey` 密钥环，请提供以下值：
+ **收件人的公钥**

  [您必须提供收件人的 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 ]

以下示例使用密钥协议架构创建一个 Raw ECDH `EphemeralPrivateKeyToStaticPublicKey` 密钥环。加密后，密钥环将在指定`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 ]

以下示例使用密钥协议架构创建一个 Raw ECDH `EphemeralPrivateKeyToStaticPublicKey` 密钥环。加密后，密钥环将在指定`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 ]

以下示例使用密钥协议架构创建一个 Raw ECDH `ephemeral_raw_ecdh_static_configuration` 密钥环。加密后，密钥环将在指定曲线上本地创建一个新的密钥对。

```
// 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 密钥环。但是，您也可以创建原始ECDH发现密钥环，即原始ECDH密钥环，该密钥环可以解密任何记录，其中指定密钥的公钥与存储在加密记录的材料描述字段中的接收者的公钥相匹配。此密钥协议架构只能解密记录。

**重要**  
使用密`PublicKeyDiscovery`钥协议架构解密记录时，无论谁拥有所有公钥，都将接受所有公钥。

要使用密钥协议架构初始化 Raw ECDH `PublicKeyDiscovery` 密钥环，请提供以下值：
+ **收件人的静态私钥**

  [您必须提供收件人的 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 ]

以下示例使用密钥协议架构创建一个 Raw ECDH `PublicKeyDiscovery` 密钥环。该密钥环可以解密任何记录，其中指定私钥的公钥与存储在加密记录的材料描述字段中的接收者的公钥相匹配。

```
// 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 ]

以下示例使用密钥协议架构创建一个 Raw ECDH `PublicKeyDiscovery` 密钥环。该密钥环可以解密任何记录，其中指定私钥的公钥与存储在加密记录的材料描述字段中的接收者的公钥相匹配。

```
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 ]

以下示例使用密钥协议架构创建一个 Raw ECDH `discovery_raw_ecdh_static_configuration` 密钥环。此密钥环可以解密任何消息，其中指定私钥的公钥与存储在消息密文中的收件人的公钥相匹配。

```
// 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?;
```

------