設定信標 - AWS 資料庫加密 SDK

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

設定信標

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

支援可搜尋加密的信標有兩種類型。標準信標會執行相等性搜尋。它們是在資料庫中實作可搜尋加密的最簡單方法。複合信標結合純文字字串和標準信標,以執行更複雜的查詢。

信標旨在於新的未填入資料庫中實作。在現有資料庫中設定的任何信標只會映射寫入資料庫的新記錄。信標是根據欄位的純文字值計算,一旦欄位加密,信標就無法映射現有資料。使用信標寫入新記錄後,您就無法更新信標的組態。不過,您可以為新增至記錄的新欄位新增新信標。

確定您的存取模式後,設定信標應該是資料庫實作的第二個步驟。然後,在設定所有信標之後,您需要建立AWS KMS 階層式 keyring、定義信標版本、為每個信標設定次要索引、定義密碼編譯動作,以及設定資料庫和 AWS 資料庫加密 SDK 用戶端。如需詳細資訊,請參閱使用信標

為了更輕鬆地定義信標版本,我們建議您建立標準信標和複合信標的清單。設定每個您建立的信標時,將它們新增至各自的標準或複合信標清單。

設定標準信標

標準信標是在資料庫中實作可搜尋加密的最簡單方法。他們只能對單一加密或虛擬欄位執行平等搜尋。

組態語法範例

Java
List<StandardBeacon> standardBeaconList = new ArrayList<>(); StandardBeacon exampleStandardBeacon = StandardBeacon.builder() .name("beaconName") .length(beaconLengthInBits) .build(); standardBeaconList.add(exampleStandardBeacon);
C# / .NET
var standardBeaconList = new List<StandardBeacon>(); StandardBeacon exampleStandardBeacon = new StandardBeacon { Name = "beaconName", Length = 10 }; standardBeaconList.Add(exampleStandardBeacon);
Rust
let standard_beacon_list = vec![ StandardBeacon::builder().name("beacon_name").length(beacon_length_in_bits).build()?,

若要設定標準信標,請提供下列值。

指標名稱

您在查詢加密欄位時使用的名稱。

信標名稱可與加密欄位或虛擬欄位的名稱相同,但不能與未加密欄位的名稱相同。我們強烈建議盡可能使用標準信標建構的加密欄位或虛擬欄位的名稱。兩個不同的信標不能有相同的信標名稱。如需判斷實作最佳信標名稱的協助,請參閱選擇信標名稱

信標長度

截斷後保留的信標雜湊值位元數。

信標長度會決定指定信標產生的平均誤報數。如需詳細資訊並協助判斷實作的適當信標長度,請參閱判斷信標長度

指標來源 (選用)

標準信標的建構來源欄位。

信標來源必須是欄位名稱或參考巢狀欄位值的索引。當您的信標名稱與信標來源相同時,您可以從組態省略信標來源,而 AWS 資料庫加密 SDK 會自動使用信標名稱做為信標來源。

建立虛擬欄位

若要建立虛擬欄位,您必須提供虛擬欄位的名稱和來源欄位清單。您新增來源欄位至虛擬零件清單的順序,會決定它們串連以建置虛擬欄位的順序。下列範例會串連兩個來源欄位,以建立虛擬欄位。

注意

我們建議您在填入資料庫之前,先驗證您的虛擬欄位是否產生預期結果。如需詳細資訊,請參閱測試信標輸出

Java

請參閱完整的程式碼範例VirtualBeaconSearchableEncryptionExample.java

List<VirtualPart> virtualPartList = new ArrayList<>(); virtualPartList.add(sourceField1); virtualPartList.add(sourceField2); VirtualField virtualFieldName = VirtualField.builder() .name("virtualFieldName") .parts(virtualPartList) .build(); List<VirtualField> virtualFieldList = new ArrayList<>(); virtualFieldList.add(virtualFieldName);
C# / .NET

請參閱完整的程式碼範例VirtualBeaconSearchableEncryptionExample.cs

var virtualPartList = new List<VirtualPart> { sourceField1, sourceField2 }; var virtualFieldName = new VirtualField { Name = "virtualFieldName", Parts = virtualPartList }; var virtualFieldList = new List<VirtualField> { virtualFieldName };
Rust

請參閱完整的程式碼範例virtual_beacon_searchable_encryption.rs

let virtual_part_list = vec![source_field_one, source_field_two]; let state_and_has_test_result_field = VirtualField::builder() .name("virtual_field_name") .parts(virtual_part_list) .build()?; let virtual_field_list = vec![virtual_field_name];

若要使用來源欄位的特定區段建立虛擬欄位,您必須先定義轉換,才能將來源欄位新增至虛擬部分清單。

虛擬欄位的安全考量

信標不會變更 欄位的加密狀態。不過,當您使用信標時,查詢的效率與資料分佈的公開資訊量之間存在固有權衡。您設定信標的方式會決定該信標所保留的安全層級。

避免使用與現有標準信標重疊的來源欄位建立虛擬欄位。建立包含已用於建立標準信標之來源欄位的虛擬欄位,可能會降低兩個信標的安全層級。安全性降低的程度取決於其他來源欄位新增的熵層級。熵程度取決於其他來源欄位中唯一值的分佈,以及其他來源欄位對虛擬欄位整體大小的貢獻位元數。

您可以使用人口和信標長度來判斷虛擬欄位的來源欄位是否保留資料集的安全性。人口是欄位中唯一值的預期數量。您的人口不需要精確。如需估算欄位人口的說明,請參閱估算人口

檢閱虛擬欄位的安全性時,請考慮下列範例。

  • Beacon1 由 建構FieldAFieldA 的人口大於 2 (Beacon1 長度)

  • Beacon2 由 建構VirtualField,其由 FieldAFieldCFieldB和 建構FieldD。、FieldBFieldC、 和 FieldD的人口總和大於 2N

如果下列陳述式為 true,Beacon2 會同時保留 Beacon1 和 Beacon2 的安全性:

N ≥ (Beacon1 length)/2

以及

N ≥ (Beacon2 length)/2

定義信標樣式

標準信標可用於對加密或虛擬欄位執行平等搜尋。或者,它們可用來建構複合信標,以執行更複雜的資料庫操作。為了協助您組織和管理標準信標, AWS 資料庫加密 SDK 提供下列選用信標樣式,可定義標準信標的預期用途。

注意

若要定義信標樣式,您必須使用 3.2 版或更新版本的 AWS 資料庫加密 SDK。將信標樣式新增至信標組態之前,先將新版本部署至所有讀取器。

PartOnly

定義為 的標準信標PartOnly只能用來定義複合信標的加密部分。您無法直接查詢PartOnly標準信標。

Java
List<StandardBeacon> standardBeaconList = new ArrayList<>(); StandardBeacon exampleStandardBeacon = StandardBeacon.builder() .name("beaconName") .length(beaconLengthInBits) .style( BeaconStyle.builder() .partOnly(PartOnly.builder().build()) .build() ) .build(); standardBeaconList.add(exampleStandardBeacon);
C# / .NET
new StandardBeacon { Name = "beaconName", Length = beaconLengthInBits, Style = new BeaconStyle { PartOnly = new PartOnly() } }
Rust
StandardBeacon::builder() .name("beacon_name") .length(beacon_length_in_bits) .style(BeaconStyle::PartOnly(PartOnly::builder().build()?)) .build()?
Shared

根據預設,每個標準信標都會產生唯一的 HMAC 金鑰,以進行信標計算。因此,您無法從兩個單獨的標準信標對加密的欄位執行等式搜尋。定義為 的標準信標Shared會使用來自另一個標準信標的 HMAC 金鑰進行計算。

例如,如果您需要將beacon1欄位與beacon2欄位進行比較,請將 beacon2定義為使用來自 的 HMAC 金鑰beacon1進行計算的Shared信標。

注意

在設定任何Shared信標之前,請考慮您的安全和效能需求。 Shared信標可能會增加可識別的有關資料集分佈的統計資訊量。例如,它們可能會顯示哪些共用欄位包含相同的純文字值。

Java
List<StandardBeacon> standardBeaconList = new ArrayList<>(); StandardBeacon exampleStandardBeacon = StandardBeacon.builder() .name("beacon2") .length(beaconLengthInBits) .style( BeaconStyle.builder() .shared(Shared.builder().other("beacon1").build()) .build() ) .build(); standardBeaconList.add(exampleStandardBeacon);
C# / .NET
new StandardBeacon { Name = "beacon2", Length = beaconLengthInBits, Style = new BeaconStyle { Shared = new Shared { Other = "beacon1" } } }
Rust
StandardBeacon::builder() .name("beacon2") .length(beacon_length_in_bits) .style(BeaconStyle::Shared( Shared::builder().other("beacon1").build()?, )) .build()?
AsSet

根據預設,如果欄位值為集合, AWS 資料庫加密 SDK 會計算集合的單一標準信標。因此,您無法執行 CONTAINS(a, :value) a 為加密欄位的查詢。定義為 的標準信標會AsSet計算集合中每個個別元素的個別標準信標值,並將信標值以集合形式存放在項目中。這可讓 AWS Database Encryption SDK 執行查詢 CONTAINS(a, :value)

若要定義AsSet標準信標,集合中的元素必須來自相同的人口,以便它們都可以使用相同的信標長度。如果在計算信標值時發生衝突,信標集的元素可能比純文字集少。

注意

在設定任何AsSet信標之前,請考慮您的安全和效能需求。 AsSet信標可能會增加可識別的有關資料集分佈的統計資訊量。例如,它們可能會顯示純文字集的大小。

Java
List<StandardBeacon> standardBeaconList = new ArrayList<>(); StandardBeacon exampleStandardBeacon = StandardBeacon.builder() .name("beaconName") .length(beaconLengthInBits) .style( BeaconStyle.builder() .asSet(AsSet.builder().build()) .build() ) .build(); standardBeaconList.add(exampleStandardBeacon);
C# / .NET
new StandardBeacon { Name = "beaconName", Length = beaconLengthInBits, Style = new BeaconStyle { AsSet = new AsSet() } }
Rust
StandardBeacon::builder() .name("beacon_name") .length(beacon_length_in_bits) .style(BeaconStyle::AsSet(AsSet::builder().build()?)) .build()?
SharedSet

定義為 的標準信標SharedSet結合 SharedAsSet函數,讓您可以對集合和欄位的加密值執行相等性搜尋。這可讓 AWS Database Encryption SDK 執行查詢,CONTAINS(a, b)其中 a 是加密集,而 b是加密欄位。

注意

在設定任何Shared信標之前,請考慮您的安全和效能需求。 SharedSet信標可能會增加可識別的有關資料集分佈的統計資訊量。例如,它們可能會顯示純文字集的大小,或哪些共用欄位包含相同的純文字值。

Java
List<StandardBeacon> standardBeaconList = new ArrayList<>(); StandardBeacon exampleStandardBeacon = StandardBeacon.builder() .name("beacon2") .length(beaconLengthInBits) .style( BeaconStyle.builder() .sharedSet(SharedSet.builder().other("beacon1").build()) .build() ) .build(); standardBeaconList.add(exampleStandardBeacon);
C# / .NET
new StandardBeacon { Name = "beacon2", Length = beaconLengthInBits, Style = new BeaconStyle { SharedSet = new SharedSet { Other = "beacon1" } } }
Rust
StandardBeacon::builder() .name("beacon2") .length(beacon_length_in_bits) .style(BeaconStyle::SharedSet( SharedSet::builder().other("beacon1").build()?, )) .build()?

設定複合信標

複合信標結合純文字字串和標準信標來執行複雜的資料庫操作,例如從單一索引查詢兩種不同的記錄類型,或查詢欄位與排序索引鍵的組合。複合信標可以從 ENCRYPT_AND_SIGNSIGN_ONLYSIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT 欄位建構。您必須為複合信標中包含的每個加密欄位建立標準信標。

注意

我們建議您在填入資料庫之前,先驗證您的複合信標是否產生預期結果。如需詳細資訊,請參閱測試信標輸出

組態語法範例

Java

複合信標組態

下列範例會在 複合信標組態中於本機定義加密和簽章的組件清單。

List<CompoundBeacon> compoundBeaconList = new ArrayList<>(); CompoundBeacon exampleCompoundBeacon = CompoundBeacon.builder() .name("compoundBeaconName") .split(".") .encrypted(encryptedPartList) .signed(signedPartList) .constructors(constructorList) .build(); compoundBeaconList.add(exampleCompoundBeacon);

指標版本定義

下列範例會在信標版本中全域定義加密和簽章的組件清單。如需定義信標版本的詳細資訊,請參閱使用信標

List<BeaconVersion> beaconVersions = new ArrayList<>(); beaconVersions.add( BeaconVersion.builder() .standardBeacons(standardBeaconList) .compoundBeacons(compoundBeaconList) .encryptedParts(encryptedPartList) .signedParts(signedPartList) .version(1) // MUST be 1 .keyStore(keyStore) .keySource(BeaconKeySource.builder() .single(SingleKeyStore.builder() .keyId(branchKeyId) .cacheTTL(6000) .build()) .build()) .build() );
C# / .NET

請參閱完整的程式碼範例BeaconConfig.cs

複合信標組態

下列範例會在 複合信標組態中於本機定義加密和簽章的組件清單。

var compoundBeaconList = new List<CompoundBeacon>(); var exampleCompoundBeacon = new CompoundBeacon { Name = "compoundBeaconName", Split = ".", Encrypted = encryptedPartList, Signed = signedPartList, Constructors = constructorList }; compoundBeaconList.Add(exampleCompoundBeacon);

指標版本定義

下列範例會在信標版本中全域定義加密和簽章的組件清單。如需定義信標版本的詳細資訊,請參閱使用信標

var beaconVersions = new List<BeaconVersion> { new BeaconVersion { StandardBeacons = standardBeaconList, CompoundBeacons = compoundBeaconList, EncryptedParts = encryptedPartsList, SignedParts = signedPartsList, Version = 1, // MUST be 1 KeyStore = keyStore, KeySource = new BeaconKeySource { Single = new SingleKeyStore { KeyId = branchKeyId, CacheTTL = 6000 } } } };
Rust

請參閱完整的程式碼範例beacon_config.rs

複合信標組態

下列範例會在 複合信標組態中於本機定義加密和簽章的組件清單。

let compound_beacon_list = vec![ CompoundBeacon::builder() .name("compound_beacon_name") .split(".") .encrypted(encrypted_parts_list) .signed(signed_parts_list) .constructors(constructor_list) .build()?

指標版本定義

下列範例會在信標版本中全域定義加密和簽章的組件清單。如需定義信標版本的詳細資訊,請參閱使用信標

let beacon_versions = BeaconVersion::builder() .standard_beacons(standard_beacon_list) .compound_beacons(compound_beacon_list) .encrypted_parts(encrypted_parts_list) .signed_parts(signed_parts_list) .version(1) // MUST be 1 .key_store(key_store.clone()) .key_source(BeaconKeySource::Single( SingleKeyStore::builder() .key_id(branch_key_id) .cache_ttl(6000) .build()?, )) .build()?; let beacon_versions = vec![beacon_versions];

您可以在本機或全域定義的清單中定義加密的組件已簽章的組件。我們建議您盡可能在信標版本中的全域清單中定義加密和簽署的組件。透過全域定義加密和簽章的組件,您可以定義每個組件一次,然後在多個複合信標組態中重複使用這些組件。如果您只打算使用加密或簽章的 部分一次,您可以在複合信標組態的本機清單中定義它。您可以在建構器清單中參考本機和全域部分。

如果您全域定義加密和簽章的組件清單,則必須提供建構組件清單,以識別複合信標可以組合複合信標組態中欄位的所有可能方式。

注意

若要全域定義加密和已簽章的組件清單,您必須使用 AWS 資料庫加密 SDK 的 3.2 版或更新版本。先將新版本部署至所有讀者,再全域定義任何新組件。

您無法更新現有的信標組態,以定義全域加密和已簽章的組件清單。

若要設定複合信標,請提供下列值。

指標名稱

您在查詢加密欄位時使用的名稱。

信標名稱可與加密欄位或虛擬欄位的名稱相同,但不能與未加密欄位的名稱相同。兩個信標不能具有相同的信標名稱。如需判斷實作最佳信標名稱的協助,請參閱選擇信標名稱

分割字元

用來分隔組成複合信標之部分的字元。

分割字元不能出現在複合信標建構來源之任何欄位的純文字值中。

加密的組件清單

識別複合信標中包含ENCRYPT_AND_SIGN的欄位。

每個部分都必須包含名稱和字首。部分名稱必須是從加密欄位建構的標準信標名稱。字首可以是任何字串,但必須是唯一的。加密的部分不能具有與已簽章部分相同的字首。我們建議使用短值來區分部分與複合信標提供的其他部分。

我們建議您盡可能全域定義加密的組件。如果您只打算在一個複合信標中使用加密部分,您可以考慮在本機定義加密部分。本機定義的加密部分不能具有與全域定義的加密部分相同的字首或名稱。

Java
List<EncryptedPart> encryptedPartList = new ArrayList<>); EncryptedPart encryptedPartExample = EncryptedPart.builder() .name("standardBeaconName") .prefix("E-") .build(); encryptedPartList.add(encryptedPartExample);
C# / .NET
var encryptedPartList = new List<EncryptedPart>(); var encryptedPartExample = new EncryptedPart { Name = "compoundBeaconName", Prefix = "E-" }; encryptedPartList.Add(encryptedPartExample);
Rust
let encrypted_parts_list = vec![ EncryptedPart::builder() .name("standard_beacon_name") .prefix("E-") .build()? ];
已簽章的組件清單

識別複合信標中包含的簽署欄位。

注意

簽章部分是選用的。您可以設定不參考任何已簽章部分的複合信標。

每個部分都必須包含名稱、來源和字首。來源是 部分識別的 SIGN_ONLYSIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT 欄位。來源必須是欄位名稱或參照巢狀欄位值的索引。如果您的部分名稱識別來源,您可以省略來源,而 AWS 資料庫加密 SDK 會自動使用該名稱做為來源。我們建議您盡可能指定來源做為零件名稱。字首可以是任何字串,但必須是唯一的。已簽章的部分不能具有與加密部分相同的字首。我們建議使用短值來區分部分與複合信標提供的其他部分。

我們建議您盡可能全域定義您的已簽署組件。如果您只打算在一個複合信標中使用已簽署的部分,您可以考慮在本機定義。本機定義的已簽章部分不能具有與全域定義的已簽章部分相同的字首或名稱。

Java
List<SignedPart> signedPartList = new ArrayList<>); SignedPart signedPartExample = SignedPart.builder() .name("signedFieldName") .prefix("S-") .build(); signedPartList.add(signedPartExample);
C# / .NET
var signedPartsList = new List<SignedPart> { new SignedPart { Name = "signedFieldName1", Prefix = "S-" }, new SignedPart { Name = "signedFieldName2", Prefix = "SF-" } };
Rust
let signed_parts_list = vec![ SignedPart::builder() .name("signed_field_name_1") .prefix("S-") .build()?, SignedPart::builder() .name("signed_field_name_2") .prefix("SF-") .build()?, ];
建構器清單

識別建構函式,其定義了加密和簽章的元件可由複合信標組合的不同方式。您可以在建構器清單中參考本機和全域組件。

如果您從全域定義的加密和簽章部分建構複合信標,則必須提供建構器清單。

如果您未使用任何全域定義的加密或簽章部分來建構複合信標,則建構器清單是選用的。如果您未指定建構器清單, AWS 資料庫加密 SDK 會將複合信標與下列預設建構器組合。

  • 所有已簽章的組件,依其新增至已簽章的組件清單的順序排列

  • 所有加密的組件,其順序會新增至加密的組件清單

  • 所有組件都是必要的

建構函式

每個建構函式都是建構函式的排序清單,可定義組合複合信標的一種方式。建構函式部分會依新增至清單的順序聯結在一起,每個部分以指定的分割字元分隔。

每個建構函式部分都會命名加密的組件或已簽章的組件,並定義該組件在建構函式中是必要還是選用。例如,如果您想要在 Field1Field1.Field2和 上查詢複合信標Field1.Field2.Field3,請將 Field2和 標記為Field3選用,並建立一個建構器。

每個建構器必須至少有一個必要的部分。我們建議在每個建構函數中,先做第一部分,以便您可以在查詢中使用BEGINS_WITH運算子。

如果記錄中存在所有必要的部分,建構器就會成功。當您撰寫新記錄時,複合信標會使用建構器清單來判斷信標是否可以從提供的值組合。它會嘗試依建構器新增至建構器清單的順序組合信標,並使用第一個成功的建構器。如果沒有建構器成功,則不會將信標寫入記錄。

所有讀取器和寫入器都應指定相同的建構器順序,以確保其查詢結果正確。

使用下列程序來指定您自己的建構器清單。

  1. 為每個加密的組件和已簽章的組件建立建構組件,以定義是否需要該組件。

    建構函式部分名稱必須是其代表的標準信標或已簽章欄位的名稱。

    Java
    ConstructorPart field1ConstructorPart = ConstructorPart.builder() .name("Field1") .required(true) .build();
    C# / .NET
    var field1ConstructorPart = new ConstructorPart { Name = "Field1", Required = true };
    Rust
    let field_1_constructor_part = ConstructorPart::builder() .name("field_1") .required(true) .build()?;
  2. 使用您在步驟 1 中建立的建構函式部分,為每個可能的複合信標組合方式建立建構函式。

    例如,如果您想要在 Field1.Field2.Field3和 上查詢 Field4.Field2.Field3,則必須建立兩個建構函數。 Field1Field4都可能是必要的,因為它們是在兩個不同的建構函數中定義。

    Java
    // Create a list for Field1.Field2.Field3 queries List<ConstructorPart> field123ConstructorPartList = new ArrayList<>(); field123ConstructorPartList.add(field1ConstructorPart); field123ConstructorPartList.add(field2ConstructorPart); field123ConstructorPartList.add(field3ConstructorPart); Constructor field123Constructor = Constructor.builder() .parts(field123ConstructorPartList) .build(); // Create a list for Field4.Field2.Field1 queries List<ConstructorPart> field421ConstructorPartList = new ArrayList<>(); field421ConstructorPartList.add(field4ConstructorPart); field421ConstructorPartList.add(field2ConstructorPart); field421ConstructorPartList.add(field1ConstructorPart); Constructor field421Constructor = Constructor.builder() .parts(field421ConstructorPartList) .build();
    C# / .NET
    // Create a list for Field1.Field2.Field3 queries var field123ConstructorPartList = new Constructor { Parts = new List<ConstructorPart> { field1ConstructorPart, field2ConstructorPart, field3ConstructorPart } }; // Create a list for Field4.Field2.Field1 queries var field421ConstructorPartList = new Constructor { Parts = new List<ConstructorPart> { field4ConstructorPart, field2ConstructorPart, field1ConstructorPart } };
    Rust
    // Create a list for field1.field2.field3 queries let field1_field2_field3_constructor = Constructor::builder() .parts(vec![ field1_constructor_part, field2_constroctor_part.clone(), field3_constructor_part, ]) .build()?; // Create a list for field4.field2.field1 queries let field4_field2_field1_constructor = Constructor::builder() .parts(vec![ field4_constructor_part, field2_constroctor_part.clone(), field1_constructor_part, ]) .build()?;
  3. 建立建構器清單,其中包含您在步驟 2 中建立的所有建構器。

    Java
    List<Constructor> constructorList = new ArrayList<>(); constructorList.add(field123Constructor) constructorList.add(field421Constructor)
    C# / .NET
    var constructorList = new List<Constructor> { field123Constructor, field421Constructor };
    Rust
    let constructor_list = vec![ field1_field2_field3_constructor, field4_field2_field1_constructor, ];
  4. 當您建立複合信標constructorList時,請指定 。