原始 ECDH 鑰匙圈 - AWS 資料庫加密 SDK

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

原始 ECDH 鑰匙圈

我們的用戶端加密程式庫已重新命名為 AWS 資料庫加密 SDK。此開發人員指南仍會提供 DynamoDB Encryption Client 的相關資訊。
重要

原始 ECDH keyring 僅適用於 Material Providers Library 的 1.5.0 版。

Raw ECDH keyring 使用您提供的橢圓曲線公有私有金鑰對,在兩方之間衍生共用包裝金鑰。首先, keyring 會使用寄件者的私有金鑰、收件人的公有金鑰和橢圓曲線 Diffie-Hellman (ECDH) 金鑰協議演算法衍生共用秘密。然後, keyring 會使用共用秘密衍生共用包裝金鑰,以保護資料加密金鑰。 AWS Database Encryption SDK 用來衍生共用包裝金鑰的金鑰衍生函數 (KDF_CTR_HMAC_SHA384) 符合金鑰衍生的 NIST 建議

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

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

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

  • ECC_NIST_P256

  • ECC_NIST_P384

  • ECC_NIST_P512

建立原始 ECDH keyring

Raw ECDH keyring 支援三個金鑰協議結構描述:RawPrivateKeyToStaticPublicKeyEphemeralPrivateKeyToStaticPublicKeyPublicKeyDiscovery。您選擇的金鑰協議結構描述會決定您可以執行哪些密碼編譯操作,以及如何組合金鑰材料。

RawPrivateKeyToStaticPublicKey

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

若要使用RawPrivateKeyToStaticPublicKey金鑰協議結構描述初始化原始 ECDH keyring,請提供下列值:

  • 寄件者的私有金鑰

    您必須提供寄件者的 PEM 編碼私有金鑰 (PKCS #8 PrivateKeyInfo 結構),如 RFC 5958 所定義。

  • 收件人的公有金鑰

    您必須提供收件人的 DER 編碼 X.509 公有金鑰,也稱為 SubjectPublicKeyInfo(SPKI),如 RFC 5280 所定義。

    您可以指定非對稱金鑰協議 KMS 金鑰對的公有金鑰,或從外部產生的金鑰對指定公有金鑰 AWS。

  • 曲線規格

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

    有效值:ECC_NIST_P256ECC_NIS_P384ECC_NIST_P512

C# / .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

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

此金鑰協議結構描述只能加密記錄。若要解密使用EphemeralPrivateKeyToStaticPublicKey金鑰協議結構描述加密的記錄,您必須使用以相同收件人的公有金鑰設定的探索金鑰協議結構描述。若要解密,您可以將原始 ECDH 金鑰環與PublicKeyDiscovery金鑰協議演算法搭配使用,或者,如果收件人的公有金鑰來自非對稱金鑰協議 KMS 金鑰對,則可以將 AWS KMS ECDH 金鑰環與 KmsPublicKeyDiscovery 金鑰協議結構描述搭配使用。

若要使用EphemeralPrivateKeyToStaticPublicKey金鑰協議結構描述初始化原始 ECDH keyring,請提供下列值:

  • 收件人的公有金鑰

    您必須提供收件人的 DER 編碼 X.509 公有金鑰,也稱為 SubjectPublicKeyInfo(SPKI),如 RFC 5280 中所定義。

    您可以指定非對稱金鑰協議 KMS 金鑰對的公有金鑰,或從外部產生的金鑰對指定公有金鑰 AWS。

  • 曲線規格

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

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

    有效值:ECC_NIST_P256ECC_NIS_P384ECC_NIST_P512

C# / .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

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

重要

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

若要使用PublicKeyDiscovery金鑰協議結構描述初始化原始 ECDH keyring,請提供下列值:

  • 收件人的靜態私有金鑰

    您必須提供收件人的 PEM 編碼私有金鑰 (PKCS #8 PrivateKeyInfo 結構),如 RFC 5958 所定義。

  • 曲線規格

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

    有效值:ECC_NIST_P256ECC_NIS_P384ECC_NIST_P512

C# / .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?;