View a markdown version of this page

AWS KMS Portachiavi gerarchici - AWS SDK di crittografia del database

Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.

AWS KMS Portachiavi gerarchici

La nostra libreria di crittografia lato client è stata rinominata Database Encryption SDK. AWS Questa guida per sviluppatori fornisce ancora informazioni sul DynamoDB Encryption Client.
Nota

A partire dal 24 luglio 2023, le chiavi di filiale create durante l'anteprima per sviluppatori non sono supportate. Crea nuove chiavi di filiale per continuare a utilizzare l'archivio di chiavi che hai creato durante l'anteprima per sviluppatori.

Con il portachiavi AWS KMS gerarchico, puoi proteggere i tuoi materiali crittografici con una chiave KMS di crittografia simmetrica senza chiamare AWS KMS ogni volta che crittografi o decrittografi un record. È una buona scelta per le applicazioni che devono ridurre al minimo le chiamate e per le applicazioni che possono riutilizzare alcuni materiali crittografici AWS KMS senza violare i requisiti di sicurezza.

Il keyring gerarchico è una soluzione di caching dei materiali crittografici che riduce il numero di AWS KMS chiamate utilizzando chiavi di filiale AWS KMS protette conservate in una tabella Amazon DynamoDB e quindi memorizzando localmente nella cache i materiali delle chiavi di filiale utilizzati nelle operazioni di crittografia e decrittografia. La tabella DynamoDB funge da archivio di chiavi che gestisce e protegge le chiavi di filiale. Memorizza la chiave di ramo attiva e tutte le versioni precedenti della chiave di ramo. La chiave di filiale attiva è la versione più recente della chiave di filiale. Il portachiavi gerarchico utilizza una chiave di crittografia dei dati univoca per ogni richiesta di crittografia e crittografa ogni chiave di crittografia dei dati con una chiave di wrapping univoca derivata dalla chiave di ramo attiva. Il portachiavi gerarchico dipende dalla gerarchia stabilita tra le chiavi di ramo attive e le relative chiavi di raggruppamento derivate.

Il portachiavi gerarchico utilizza in genere ogni versione della chiave di ramo per soddisfare più richieste. Tuttavia, sei tu a controllare la misura in cui le chiavi di ramo attive vengono riutilizzate e a determinare la frequenza con cui la chiave di ramo attiva viene ruotata. La versione attiva della chiave di diramazione rimane attiva finché non viene ruotata. Le versioni precedenti della chiave di diramazione attiva non verranno utilizzate per eseguire operazioni di crittografia, ma possono comunque essere interrogate e utilizzate nelle operazioni di decrittografia.

Quando si crea un'istanza del portachiavi gerarchico, viene creata una cache locale. Specificate un limite di cache che definisce il periodo massimo di tempo durante il quale i materiali delle chiavi del ramo vengono archiviati nella cache locale prima che scadano e vengano rimossi dalla cache. Il portachiavi gerarchico effettua una AWS KMS chiamata per decrittografare la chiave di diramazione e assemblare i materiali della chiave di diramazione la prima volta che viene specificato un elemento in un'operazione. branch-key-id Quindi, i materiali delle chiavi di filiale vengono archiviati nella cache locale e riutilizzati per tutte le operazioni di crittografia e decrittografia che lo specificano fino alla scadenza del limite di cache. branch-key-id L'archiviazione dei materiali relativi alle chiavi delle filiali nella cache locale riduce le chiamate. AWS KMS Ad esempio, considera un limite di cache di 15 minuti. Se esegui 10.000 operazioni di crittografia entro tale limite di cache, il AWS KMS portachiavi tradizionale dovrebbe effettuare 10.000 AWS KMS chiamate per soddisfare 10.000 operazioni di crittografia. Se ne hai uno attivobranch-key-id, il portachiavi gerarchico deve effettuare una sola AWS KMS chiamata per soddisfare 10.000 operazioni di crittografia.

La cache locale separa i materiali di crittografia dai materiali di decrittografia. I materiali di crittografia vengono raccolti dalla chiave di filiale attiva e riutilizzati per tutte le operazioni di crittografia fino alla scadenza del limite di cache. I materiali di decrittografia vengono raccolti a partire dall'ID e dalla versione della chiave di filiale identificati nei metadati del campo crittografato e vengono riutilizzati per tutte le operazioni di decrittografia relative all'ID e alla versione della chiave di filiale fino alla scadenza del limite di cache. La cache locale può memorizzare più versioni della stessa chiave di filiale contemporaneamente. Quando la cache locale è configurata per utilizzare abranch key ID supplier, può anche archiviare i materiali delle chiavi di filiale provenienti da più chiavi di filiale attive contemporaneamente.

Nota

Tutte le menzioni del portachiavi gerarchico nel AWS Database Encryption SDK si riferiscono al portachiavi gerarchico. AWS KMS

Come funziona

Le seguenti procedure dettagliate descrivono come il portachiavi gerarchico assembla i materiali di crittografia e decrittografia e le diverse chiamate effettuate dal portachiavi per le operazioni di crittografia e decrittografia. Per dettagli tecnici sui processi di derivazione della chiave di wrapping e di crittografia delle chiavi di dati in chiaro, consulta Dettagli tecnici sui keyring gerarchici. AWS KMS

Crittografa e firma

La seguente procedura dettagliata descrive come il portachiavi gerarchico assembla i materiali crittografici e ricava una chiave di wrapping univoca.

  1. Il metodo di crittografia richiede al portachiavi gerarchico i materiali crittografici. Il portachiavi genera una chiave dati in testo normale, quindi verifica se nella cache locale sono presenti materiali validi per generare la chiave di wrapping. Se sono disponibili materiali chiave di filiale validi, il portachiavi procede al passaggio 4.

  2. Se non ci sono materiali validi per le chiavi di filiale, il portachiavi gerarchico interroga l'archivio delle chiavi per la chiave di filiale attiva.

    1. L'archivio di chiavi chiama AWS KMS per decrittografare la chiave di filiale attiva e restituisce la chiave di ramo attiva in testo normale. I dati che identificano la chiave di ramo attiva vengono serializzati per fornire dati autenticati (AAD) aggiuntivi nella chiamata di decrittografia a. AWS KMS

    2. Il key store restituisce la chiave di ramo in testo normale e i dati che la identificano, ad esempio la versione della chiave di ramo.

  3. Il portachiavi gerarchico riunisce i materiali delle chiavi di ramo (la chiave di ramo in testo normale e la versione della chiave di ramo) e ne memorizza una copia nella cache locale.

  4. Il portachiavi gerarchico ricava una chiave di raggruppamento univoca dalla chiave di ramo in testo normale e da un sale casuale di 16 byte. Utilizza la chiave di wrapping derivata per crittografare una copia della chiave di dati in testo normale.

Il metodo di crittografia utilizza i materiali di crittografia per crittografare e firmare il record. Per ulteriori informazioni su come i record vengono crittografati e firmati nel AWS Database Encryption SDK, vedi Crittografa e firma.

Decifra e verifica

La seguente procedura dettagliata descrive come il portachiavi gerarchico assembla i materiali di decrittografia e decrittografa la chiave di dati crittografata.

  1. Il metodo di decrittografia identifica la chiave di dati crittografata dal campo di descrizione del materiale del record crittografato e la passa al portachiavi gerarchico.

  2. Il portachiavi gerarchico deserializza i dati che identificano la chiave di dati crittografata, inclusa la versione della chiave di derivazione, il salt a 16 byte e altre informazioni che descrivono il modo in cui la chiave dati è stata crittografata.

    Per ulteriori informazioni, consulta AWS KMS Dettagli tecnici del portachiavi gerarchico.

  3. Il portachiavi gerarchico verifica se nella cache locale sono presenti materiali validi relativi alle chiavi di filiale che corrispondono alla versione della chiave di filiale identificata nel passaggio 2. Se sono disponibili materiali chiave di filiale validi, il portachiavi procede al passaggio 6.

  4. Se non sono disponibili materiali validi per le chiavi di filiale, il portachiavi gerarchico interroga nell'archivio chiavi la chiave di filiale che corrisponde alla versione della chiave di filiale identificata nel passaggio 2.

    1. Il key store chiama AWS KMS per decrittografare la chiave di filiale e restituisce la chiave di ramo attiva in testo normale. I dati che identificano la chiave di ramo attiva vengono serializzati per fornire dati autenticati (AAD) aggiuntivi nella chiamata di decrittografia a. AWS KMS

    2. Il key store restituisce la chiave di ramo in testo normale e i dati che la identificano, ad esempio la versione della chiave di ramo.

  5. Il portachiavi gerarchico riunisce i materiali delle chiavi di ramo (la chiave di ramo in testo normale e la versione della chiave di ramo) e ne memorizza una copia nella cache locale.

  6. Il portachiavi Hierarchical utilizza i materiali delle chiavi di ramo assemblate e il codice salt a 16 byte identificato nel passaggio 2 per riprodurre la chiave di avvolgimento univoca che ha crittografato la chiave di dati.

  7. Il portachiavi gerarchico utilizza la chiave di raggruppamento riprodotta per decrittografare la chiave dati e restituisce la chiave dati in testo normale.

Il metodo di decrittografia utilizza i materiali di decrittografia e la chiave di dati in testo normale per decrittografare e verificare il record. Per ulteriori informazioni su come i record vengono decrittografati e verificati nel Database Encryption SDK, vedi Decifrare e verificare. AWS Decrittografa e verifica

Prerequisiti

Prima di creare e utilizzare un portachiavi gerarchico, assicurati che siano soddisfatti i seguenti prerequisiti.

Autorizzazioni richieste

Il AWS Database Encryption SDK non richiede Account AWS e non dipende da nessuno Servizio AWS. Tuttavia, per utilizzare un portachiavi gerarchico, sono necessarie le seguenti autorizzazioni Account AWS minime sulle AWS KMS key crittografie simmetriche nel tuo archivio di chiavi.

Per ulteriori informazioni sul controllo dell'accesso alle chiavi di filiale e al key store, consulta. Implementazione di autorizzazioni con privilegio minimo

Scegli una cache

Il portachiavi gerarchico riduce il numero di chiamate effettuate AWS KMS memorizzando localmente nella cache i materiali delle chiavi di filiale utilizzati nelle operazioni di crittografia e decrittografia. Prima di creare il portachiavi gerarchico, è necessario decidere il tipo di cache da utilizzare. È possibile utilizzare la cache predefinita o personalizzare la cache per adattarla al meglio alle proprie esigenze.

Il portachiavi gerarchico supporta i seguenti tipi di cache:

Cache predefinita

Per la maggior parte degli utenti, la cache predefinita soddisfa i requisiti di threading. La cache predefinita è progettata per supportare ambienti fortemente multithread. Quando una voce relativa ai materiali della chiave di filiale scade, la cache predefinita impedisce la chiamata di più thread AWS KMS notificando a un thread che la voce relativa ai materiali della chiave di filiale scadrà con 10 secondi di anticipo. Ciò garantisce che solo un thread invii una richiesta di aggiornamento della cache AWS KMS .

L'impostazione predefinita e StormTracking le cache supportano lo stesso modello di threading, ma è sufficiente specificare la capacità di ingresso per utilizzare la cache predefinita. Per personalizzazioni più granulari della cache, usa il. StormTracking cache

A meno che non si desideri personalizzare il numero di voci relative ai materiali chiave di filiale che possono essere archiviate nella cache locale, non è necessario specificare un tipo di cache quando si crea il portachiavi gerarchico. Se non si specifica un tipo di cache, il portachiavi gerarchico utilizza il tipo di cache predefinito e imposta la capacità di immissione su 1000.

Per personalizzare la cache predefinita, specificate i seguenti valori:

  • Capacità di ingresso: limita il numero di voci relative ai materiali chiave della filiale che possono essere archiviate nella cache locale.

Java
.cache(CacheType.builder() .Default(DefaultCache.builder() .entryCapacity(100) .build())
C# / .NET
CacheType defaultCache = new CacheType { Default = new DefaultCache{EntryCapacity = 100} };
Rust
let cache: CacheType = CacheType::Default( DefaultCache::builder() .entry_capacity(100) .build()?, );

MultiThreaded cache

La MultiThreaded cache è sicura da usare in ambienti multithread, ma non fornisce alcuna funzionalità per ridurre al minimo AWS KMS le chiamate Amazon DynamoDB. Di conseguenza, quando una voce relativa ai materiali chiave di una filiale scade, tutti i thread verranno notificati contemporaneamente. Ciò può comportare più AWS KMS chiamate per aggiornare la cache.

Per utilizzare la MultiThreaded cache, specificate i seguenti valori:

  • Capacità di ingresso: limita il numero di voci relative ai materiali chiave della filiale che possono essere archiviate nella cache locale.

  • Dimensione della coda di potatura in entrata: definisce il numero di piante da potare se viene raggiunta la capacità di ingresso.

Java
.cache(CacheType.builder() .MultiThreaded(MultiThreadedCache.builder() .entryCapacity(100) .entryPruningTailSize(1) .build())
C# / .NET
CacheType multithreadedCache = new CacheType { MultiThreaded = new MultiThreadedCache { EntryCapacity = 100, EntryPruningTailSize = 1 } };
Rust
CacheType::MultiThreaded( MultiThreadedCache::builder() .entry_capacity(100) .entry_pruning_tail_size(1) .build()?)

StormTracking cache

La StormTracking cache è progettata per supportare ambienti fortemente multithread. Quando una voce relativa ai materiali della chiave di filiale scade, la StormTracking cache impedisce la chiamata di più thread AWS KMS notificando a un thread che la voce relativa ai materiali della chiave di filiale scadrà in anticipo. Ciò garantisce che solo un thread invii una richiesta AWS KMS a per aggiornare la cache.

Per utilizzare la StormTracking cache, specifica i seguenti valori:

  • Capacità di ingresso: limita il numero di voci relative ai materiali chiave della filiale che possono essere archiviate nella cache locale.

    Valore predefinito: 1000 voci

  • Dimensione della coda di potatura in entrata: definisce il numero di materiali chiave del ramo da potare contemporaneamente.

    Valore predefinito: 1 voce

  • Periodo di tolleranza: definisce il numero di secondi prima della scadenza in cui viene effettuato un tentativo di aggiornamento dei materiali chiave della filiale.

    Valore predefinito: 10 secondi

  • Intervallo di tolleranza: definisce il numero di secondi tra i tentativi di aggiornamento dei materiali chiave della filiale.

    Valore predefinito: 1 secondi

  • Fan out: definisce il numero di tentativi simultanei che possono essere effettuati per aggiornare i materiali chiave della filiale.

    Valore predefinito: 20 tentativi

  • In flight time to live (TTL): definisce il numero di secondi che mancano al timeout del tentativo di aggiornare i materiali chiave della filiale. Ogni volta che la cache ritorna NoSuchEntry in risposta aGetCacheEntry, quella chiave di diramazione viene considerata attiva finché non viene scritta la stessa chiave insieme a una PutCache voce.

    Valore predefinito: 10 secondi

  • Sospensione: definisce il numero di secondi in cui un thread deve rimanere inattivo se fanOut viene superato.

    Valore predefinito: 20 millisecondi

Java
.cache(CacheType.builder() .StormTracking(StormTrackingCache.builder() .entryCapacity(100) .entryPruningTailSize(1) .gracePeriod(10) .graceInterval(1) .fanOut(20) .inFlightTTL(10) .sleepMilli(20) .build())
C# / .NET
CacheType stormTrackingCache = new CacheType { StormTracking = new StormTrackingCache { EntryCapacity = 100, EntryPruningTailSize = 1, FanOut = 20, GraceInterval = 1, GracePeriod = 10, InFlightTTL = 10, SleepMilli = 20 } };
Rust
CacheType::StormTracking( StormTrackingCache::builder() .entry_capacity(100) .entry_pruning_tail_size(1) .grace_period(10) .grace_interval(1) .fan_out(20) .in_flight_ttl(10) .sleep_milli(20) .build()?)

Cache condivisa

Per impostazione predefinita, il portachiavi gerarchico crea una nuova cache locale ogni volta che si crea un'istanza del portachiavi. Tuttavia, la cache condivisa può aiutare a risparmiare memoria consentendo di condividere una cache tra più portachiavi gerarchici. Anziché creare una nuova cache dei materiali crittografici per ogni keyring gerarchico creato, la cache condivisa memorizza solo una cache in memoria, che può essere utilizzata da tutti i portachiavi gerarchici che vi fanno riferimento. La cache condivisa aiuta a ottimizzare l'uso della memoria evitando la duplicazione di materiali crittografici tra i portachiavi. Invece, i portachiavi gerarchici possono accedere alla stessa cache sottostante, riducendo l'ingombro complessivo della memoria.

Quando si crea la cache condivisa, si definisce comunque il tipo di cache. È possibile specificare un Cache predefinitaMultiThreaded cache, o StormTracking cache come tipo di cache o sostituire qualsiasi cache personalizzata compatibile.

Partizioni

Più portachiavi gerarchici possono utilizzare una singola cache condivisa. Quando si crea un portachiavi gerarchico con una cache condivisa, è possibile definire un ID di partizione opzionale. L'ID di partizione distingue il portachiavi gerarchico che sta scrivendo nella cache. Se due portachiavi gerarchici fanno riferimento allo stesso ID di partizione e allo stesso ID di chiave di ramological key store name, i due portachiavi condivideranno le stesse voci della cache nella cache. Se si creano due portachiavi gerarchici con la stessa cache condivisa, ma ID di partizione diversi, ciascun portachiavi accederà alle voci della cache solo dalla propria partizione designata all'interno della cache condivisa. Le partizioni agiscono come divisioni logiche all'interno della cache condivisa, consentendo a ciascun portachiavi gerarchico di operare in modo indipendente sulla propria partizione designata, senza interferire con i dati memorizzati nell'altra partizione.

Se intendi riutilizzare o condividere le voci della cache in una partizione, devi definire il tuo ID di partizione. Quando si passa l'ID della partizione al portachiavi gerarchico, il portachiavi può riutilizzare le voci della cache già presenti nella cache condivisa, anziché dover recuperare e autorizzare nuovamente i materiali delle chiavi di ramo. Se non si specifica un ID di partizione, al portachiavi viene assegnato automaticamente un ID di partizione univoco ogni volta che si crea un'istanza del portachiavi gerarchico.

Le procedure seguenti mostrano come creare una cache condivisa con il tipo di cache predefinito e passarla a un portachiavi gerarchico.

  1. Create una CryptographicMaterialsCache (CMC) utilizzando la Material Providers Library (MPL).

    Java
    // Instantiate the MPL final MaterialProviders matProv = MaterialProviders.builder() .MaterialProvidersConfig(MaterialProvidersConfig.builder().build()) .build(); // Create a CacheType object for the Default cache final CacheType cache = CacheType.builder() .Default(DefaultCache.builder().entryCapacity(100).build()) .build(); // Create a CMC using the default cache final CreateCryptographicMaterialsCacheInput cryptographicMaterialsCacheInput = CreateCryptographicMaterialsCacheInput.builder() .cache(cache) .build(); final ICryptographicMaterialsCache sharedCryptographicMaterialsCache = matProv.CreateCryptographicMaterialsCache(cryptographicMaterialsCacheInput);
    C# / .NET
    // Instantiate the MPL var materialProviders = new MaterialProviders(new MaterialProvidersConfig()); // Create a CacheType object for the Default cache var cache = new CacheType { Default = new DefaultCache{EntryCapacity = 100} }; // Create a CMC using the default cache var cryptographicMaterialsCacheInput = new CreateCryptographicMaterialsCacheInput {Cache = cache}; var sharedCryptographicMaterialsCache = materialProviders.CreateCryptographicMaterialsCache(cryptographicMaterialsCacheInput);
    Rust
    // Instantiate the MPL let mpl_config = MaterialProvidersConfig::builder().build()?; let mpl = mpl_client::Client::from_conf(mpl_config)?; // Create a CacheType object for the default cache let cache: CacheType = CacheType::Default( DefaultCache::builder() .entry_capacity(100) .build()?, ); // Create a CMC using the default cache let shared_cryptographic_materials_cache: CryptographicMaterialsCacheRef = mpl. create_cryptographic_materials_cache() .cache(cache) .send() .await?;
  2. Crea un CacheType oggetto per la cache condivisa.

    Passa sharedCryptographicMaterialsCache ciò che hai creato nel passaggio 1 al nuovo CacheType oggetto.

    Java
    // Create a CacheType object for the sharedCryptographicMaterialsCache final CacheType sharedCache = CacheType.builder() .Shared(sharedCryptographicMaterialsCache) .build();
    C# / .NET
    // Create a CacheType object for the sharedCryptographicMaterialsCache var sharedCache = new CacheType { Shared = sharedCryptographicMaterialsCache };
    Rust
    // Create a CacheType object for the shared_cryptographic_materials_cache let shared_cache: CacheType = CacheType::Shared(shared_cryptographic_materials_cache);
  3. Passa l'sharedCacheoggetto dal passaggio 2 al tuo portachiavi gerarchico.

    Quando crei un portachiavi gerarchico con una cache condivisa, puoi facoltativamente definire una partitionID per condividere le voci della cache tra più portachiavi gerarchici. Se non si specifica un ID di partizione, il portachiavi gerarchico assegna automaticamente al portachiavi un ID di partizione univoco.

    Nota

    I portachiavi gerarchici condivideranno le stesse voci della cache in una cache condivisa se crei due o più portachiavi che fanno riferimento allo stesso ID di partizione e allo stesso ID di chiave di ramo. logical key store name Se non desideri che più portachiavi condividano le stesse voci della cache, devi utilizzare un ID di partizione univoco per ogni portachiavi gerarchico.

    L'esempio seguente crea un portachiavi gerarchico con un branch key ID supplier limite di cache e 600 secondi. Per ulteriori informazioni sui valori definiti nella seguente configurazione gerarchica del portachiavi, vedere. Crea un portachiavi gerarchico

    Java
    // Create the Hierarchical keyring final CreateAwsKmsHierarchicalKeyringInput keyringInput = CreateAwsKmsHierarchicalKeyringInput.builder() .keyStore(keystore) .branchKeyIdSupplier(branchKeyIdSupplier) .ttlSeconds(600) .cache(sharedCache) .partitionID(partitionID) .build(); final IKeyring hierarchicalKeyring = matProv.CreateAwsKmsHierarchicalKeyring(keyringInput);
    C# / .NET
    // Create the Hierarchical keyring var createKeyringInput = new CreateAwsKmsHierarchicalKeyringInput { KeyStore = keystore, BranchKeyIdSupplier = branchKeyIdSupplier, Cache = sharedCache, TtlSeconds = 600, PartitionId = partitionID }; var keyring = materialProviders.CreateAwsKmsHierarchicalKeyring(createKeyringInput);
    Rust
    // Create the Hierarchical keyring let keyring1 = mpl .create_aws_kms_hierarchical_keyring() .key_store(key_store1) .branch_key_id(branch_key_id.clone()) // CryptographicMaterialsCacheRef is an Rc (Reference Counted), so if you clone it to // pass it to different Hierarchical Keyrings, it will still point to the same // underlying cache, and increment the reference count accordingly. .cache(shared_cache.clone()) .ttl_seconds(600) .partition_id(partition_id.clone()) .send() .await?;

Crea un portachiavi gerarchico

Per creare un portachiavi gerarchico, devi fornire i seguenti valori:

  • Un archivio di chiavi

    Il key store che gestisce e protegge le chiavi delle filiali. È necessario creare e configurare il key store prima di creare il portachiavi gerarchico. Per ulteriori informazioni, consulta Archivi di chiavi nel AWS Database Encryption SDK.

  • Un limite di durata della cache (TTL)

    Il periodo di tempo, in secondi, durante il quale una chiave di filiale inserita nella cache locale può essere utilizzata prima della scadenza. Il limite di cache TTL determina la frequenza con cui il client chiama AWS KMS per autorizzare l'uso delle chiavi di filiale. Questo valore deve essere maggiore di zero. Una volta scaduto il limite di cache TTL, la voce non viene mai pubblicata e verrà rimossa dalla cache locale.

  • Un identificatore della chiave di filiale

    Puoi configurare staticamente branch-key-id quello che identifica una singola chiave di filiale attiva nel tuo key store o fornire un fornitore di ID per le chiavi di filiale.

    Il fornitore dell'ID della chiave di filiale utilizza i campi memorizzati nel contesto di crittografia per determinare quale chiave di filiale è necessaria per decrittografare un record. Per impostazione predefinita, nel contesto di crittografia sono incluse solo le chiavi di partizione e di ordinamento. Tuttavia, è possibile utilizzare l'azione SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT crittografica per includere campi aggiuntivi nel contesto di crittografia.

    Consigliamo vivamente di utilizzare un fornitore di ID di chiave di filiale per i database multitenant in cui ogni tenant ha la propria chiave di filiale. Puoi utilizzare il fornitore dell'ID della chiave di filiale per creare un nome descrittivo per gli ID delle tue chiavi di filiale in modo da facilitare il riconoscimento dell'ID della chiave di filiale corretto per un tenant specifico. Ad esempio, il nome descrittivo consente di fare riferimento a una chiave di filiale come tenant1 anzichéb3f61619-4d35-48ad-a275-050f87e15122.

    Per le operazioni di decrittografia, è possibile configurare staticamente un singolo portachiavi gerarchico per limitare la decrittografia a un singolo tenant oppure è possibile utilizzare il fornitore dell'ID della chiave di filiale per identificare quale tenant è responsabile della decrittografia di un record.

  • (Facoltativo) Una cache

    Se desideri personalizzare il tipo di cache o il numero di voci relative ai materiali delle chiavi di filiale che possono essere archiviate nella cache locale, specifica il tipo di cache e la capacità di immissione quando inizializzi il portachiavi.

    Il portachiavi gerarchico supporta i seguenti tipi di cache: predefinita,, MultiThreaded e condivisa. StormTracking Per ulteriori informazioni ed esempi che dimostrano come definire ogni tipo di cache, vedere. Scegli una cache

    Se non si specifica una cache, il portachiavi gerarchico utilizza automaticamente il tipo di cache predefinito e imposta la capacità di immissione su 1000.

  • (Facoltativo) Un ID di partizione

    Se si specifica ilCache condivisa, è possibile definire facoltativamente un ID di partizione. L'ID di partizione distingue quale portachiavi gerarchico sta scrivendo nella cache. Se si intende riutilizzare o condividere le voci della cache in una partizione, è necessario definire un ID di partizione personalizzato. È possibile specificare qualsiasi stringa per l'ID della partizione. Se non si specifica un ID di partizione, al portachiavi viene assegnato automaticamente un ID di partizione univoco al momento della creazione.

    Per ulteriori informazioni, consulta Partitions.

    Nota

    I portachiavi gerarchici condivideranno le stesse voci della cache in una cache condivisa se crei due o più portachiavi che fanno riferimento allo stesso ID di partizione e allo stesso ID della chiave di ramo. logical key store name Se non desideri che più portachiavi condividano le stesse voci della cache, devi utilizzare un ID di partizione univoco per ogni portachiavi gerarchico.

  • (Facoltativo) Un elenco di Grant Token

    Se controlli l'accesso alla chiave KMS nel tuo portachiavi gerarchico con le concessioni, devi fornire tutti i token di concessione necessari quando inizializzi il portachiavi.

Gli esempi seguenti mostrano come configurare un key store con una configurazione statica. Scegli la tua lingua preferita:

Java
import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import software.amazon.awssdk.services.kms.KmsClient; import software.amazon.cryptography.keystore.KeyStore; import software.amazon.cryptography.keystore.model.KeyStoreConfig; import software.amazon.cryptography.keystore.model.KMSConfiguration; final KeyStore keystore = KeyStore.builder() .KeyStoreConfig(KeyStoreConfig.builder() .ddbClient(DynamoDbClient.create()) .ddbTableName(keyStoreName) .logicalKeyStoreName(logicalKeyStoreName) .kmsClient(KmsClient.create()) .kmsConfiguration(KMSConfiguration.builder() .kmsKeyArn(kmsKeyArn) .build()) .build()) .build();
C# / .NET
using Amazon.DynamoDBv2; using Amazon.KeyManagementService; using AWS.Cryptography.KeyStore; var kmsConfig = new KMSConfiguration { KmsKeyArn = kmsKeyArn }; var keystoreConfig = new KeyStoreConfig { KmsClient = new AmazonKeyManagementServiceClient(), KmsConfiguration = kmsConfig, DdbTableName = keyStoreName, DdbClient = new AmazonDynamoDBClient(), LogicalKeyStoreName = logicalKeyStoreName }; var keystore = new KeyStore(keystoreConfig);
Rust
use aws_db_esdk::key_store::client as keystore_client; use aws_db_esdk::key_store::types::key_store_config::KeyStoreConfig; use aws_db_esdk::key_store::types::KmsConfiguration; let sdk_config = aws_config::load_defaults(aws_config::BehaviorVersion::latest()).await; let key_store_config = KeyStoreConfig::builder() .kms_client(aws_sdk_kms::Client::new(&sdk_config)) .ddb_client(aws_sdk_dynamodb::Client::new(&sdk_config)) .ddb_table_name(key_store_name) .logical_key_store_name(logical_key_store_name) .kms_configuration(KmsConfiguration::KmsKeyArn(kms_key_arn.to_string())) .build()?; let keystore = keystore_client::Client::from_conf(key_store_config)?;

Dopo aver configurato il key store, utilizzate l'oggetto key store risultante per creare il portachiavi gerarchico. Gli esempi di portachiavi gerarchici che seguono utilizzano l'oggetto key store configurato.

Gli esempi seguenti mostrano come creare un portachiavi gerarchico con un ID di chiave di ramo staticoCache predefinita, il e un limite di cache TTL di 600 secondi.

Java
final MaterialProviders matProv = MaterialProviders.builder() .MaterialProvidersConfig(MaterialProvidersConfig.builder().build()) .build(); final CreateAwsKmsHierarchicalKeyringInput keyringInput = CreateAwsKmsHierarchicalKeyringInput.builder() .keyStore(keystore) .branchKeyId(branch-key-id) .ttlSeconds(600) .build(); final Keyring hierarchicalKeyring = matProv.CreateAwsKmsHierarchicalKeyring(keyringInput);
C# / .NET
var matProv = new MaterialProviders(new MaterialProvidersConfig()); var keyringInput = new CreateAwsKmsHierarchicalKeyringInput { KeyStore = keystore, BranchKeyIdSupplier = branchKeyIdSupplier, TtlSeconds = 600 }; var hierarchicalKeyring = matProv.CreateAwsKmsHierarchicalKeyring(keyringInput);
Rust
let mpl_config = MaterialProvidersConfig::builder().build()?; let mpl = mpl_client::Client::from_conf(mpl_config)?; let hierarchical_keyring = mpl .create_aws_kms_hierarchical_keyring() .branch_key_id(branch_key_id) .key_store(keystore.clone()) .ttl_seconds(600) .send() .await?;

Le seguenti procedure mostrano come creare un portachiavi gerarchico con un fornitore di ID chiave di filiale.

  1. Crea un fornitore ID chiave di filiale

    L'esempio seguente crea nomi descrittivi per le due chiavi di filiale create nel passaggio 1 e chiama CreateDynamoDbEncryptionBranchKeyIdSupplier a creare un fornitore di ID di chiavi di filiale con il client AWS Database Encryption SDK per DynamoDB.

    Java
    // Create friendly names for each branch-key-id class ExampleBranchKeyIdSupplier implements IDynamoDbKeyBranchKeyIdSupplier { private static String branchKeyIdForTenant1; private static String branchKeyIdForTenant2; public ExampleBranchKeyIdSupplier(String tenant1Id, String tenant2Id) { this.branchKeyIdForTenant1 = tenant1Id; this.branchKeyIdForTenant2 = tenant2Id; } // Create the branch key ID supplier final DynamoDbEncryption ddbEnc = DynamoDbEncryption.builder() .DynamoDbEncryptionConfig(DynamoDbEncryptionConfig.builder().build()) .build(); final BranchKeyIdSupplier branchKeyIdSupplier = ddbEnc.CreateDynamoDbEncryptionBranchKeyIdSupplier( CreateDynamoDbEncryptionBranchKeyIdSupplierInput.builder() .ddbKeyBranchKeyIdSupplier(new ExampleBranchKeyIdSupplier(branch-key-ID-tenant1, branch-key-ID-tenant2)) .build()).branchKeyIdSupplier();
    C# / .NET
    // Create friendly names for each branch-key-id class ExampleBranchKeyIdSupplier : DynamoDbKeyBranchKeyIdSupplierBase { private String _branchKeyIdForTenant1; private String _branchKeyIdForTenant2; public ExampleBranchKeyIdSupplier(String tenant1Id, String tenant2Id) { this._branchKeyIdForTenant1 = tenant1Id; this._branchKeyIdForTenant2 = tenant2Id; } // Create the branch key ID supplier var ddbEnc = new DynamoDbEncryption(new DynamoDbEncryptionConfig()); var branchKeyIdSupplier = ddbEnc.CreateDynamoDbEncryptionBranchKeyIdSupplier( new CreateDynamoDbEncryptionBranchKeyIdSupplierInput { DdbKeyBranchKeyIdSupplier = new ExampleBranchKeyIdSupplier(branch-key-ID-tenant1, branch-key-ID-tenant2) }).BranchKeyIdSupplier;
    Rust
    // Create friendly names for each branch_key_id pub struct ExampleBranchKeyIdSupplier { branch_key_id_for_tenant1: String, branch_key_id_for_tenant2: String, } impl ExampleBranchKeyIdSupplier { pub fn new(tenant1_id: &str, tenant2_id: &str) -> Self { Self { branch_key_id_for_tenant1: tenant1_id.to_string(), branch_key_id_for_tenant2: tenant2_id.to_string(), } } } // Create the branch key ID supplier let dbesdk_config = DynamoDbEncryptionConfig::builder().build()?; let dbesdk = dbesdk_client::Client::from_conf(dbesdk_config)?; let supplier = ExampleBranchKeyIdSupplier::new(tenant1_branch_key_id, tenant2_branch_key_id); let branch_key_id_supplier = dbesdk .create_dynamo_db_encryption_branch_key_id_supplier() .ddb_key_branch_key_id_supplier(supplier) .send() .await? .branch_key_id_supplier .unwrap();
  2. Crea un portachiavi gerarchico

    Gli esempi seguenti inizializzano un portachiavi gerarchico con il fornitore dell'ID della chiave di filiale creato nel passaggio 1, un limite di cache TLL di 600 secondi e una dimensione massima della cache di 1000.

    Java
    final MaterialProviders matProv = MaterialProviders.builder() .MaterialProvidersConfig(MaterialProvidersConfig.builder().build()) .build(); final CreateAwsKmsHierarchicalKeyringInput keyringInput = CreateAwsKmsHierarchicalKeyringInput.builder() .keyStore(keystore) .branchKeyIdSupplier(branchKeyIdSupplier) .ttlSeconds(600) .cache(CacheType.builder() //OPTIONAL .Default(DefaultCache.builder() .entryCapacity(100) .build()) .build()) .build(); final Keyring hierarchicalKeyring = matProv.CreateAwsKmsHierarchicalKeyring(keyringInput);
    C# / .NET
    var matProv = new MaterialProviders(new MaterialProvidersConfig()); var keyringInput = new CreateAwsKmsHierarchicalKeyringInput { KeyStore = keystore, BranchKeyIdSupplier = branchKeyIdSupplier, TtlSeconds = 600, Cache = new CacheType { Default = new DefaultCache { EntryCapacity = 100 } } }; var hierarchicalKeyring = matProv.CreateAwsKmsHierarchicalKeyring(keyringInput);
    Rust
    let mpl_config = MaterialProvidersConfig::builder().build()?; let mpl = mpl_client::Client::from_conf(mpl_config)?; let hierarchical_keyring = mpl .create_aws_kms_hierarchical_keyring() .branch_key_id_supplier(branch_key_id_supplier) .key_store(keystore.clone()) .ttl_seconds(600) .send() .await?;

Utilizzo del portachiavi gerarchico per la crittografia ricercabile

La crittografia ricercabile consente di cercare record crittografati senza decrittografare l'intero database. Ciò si ottiene indicizzando il valore in chiaro di un campo crittografato con un beacon. Fari Per implementare la crittografia ricercabile, è necessario utilizzare un portachiavi gerarchico.

L'CreateKeyoperazione di archiviazione delle chiavi genera sia una chiave di filiale che una chiave beacon. La chiave di derivazione viene utilizzata nelle operazioni di crittografia e decrittografia dei record. La chiave beacon viene utilizzata per generare beacon.

La chiave di filiale e la chiave beacon sono protette dalla stessa AWS KMS key che specifichi durante la creazione del servizio di archiviazione delle chiavi. Dopo le chiamate dell'CreateKeyoperazione AWS KMS per generare la chiave di filiale, chiama kms: GenerateDataKeyWithoutPlaintext una seconda volta per generare la chiave beacon utilizzando la seguente richiesta.

{ "EncryptionContext": { "branch-key-id" : "branch-key-id", "type" : type, "create-time" : "timestamp", "tablename" : "the logical table name for your key store", "kms-arn" : the KMS key ARN, "hierarchy-version" : 1 }, "KeyId": "the KMS key ARN", "NumberOfBytes": "32" }

Dopo aver generato entrambe le chiavi, l'CreateKeyoperazione chiama ddb: TransactWriteItems per scrivere due nuovi elementi che mantengano la chiave di ramo e la chiave beacon nell'archivio delle chiavi della filiale.

Quando si configura un beacon standard, AWS Database Encryption SDK interroga l'archivio di chiavi per la chiave beacon. Quindi, utilizza una funzione di HMAC-based estrazione ed espansione della chiave (HKDF) per combinare la chiave beacon con il nome del beacon standard per creare la chiave HMAC per un determinato beacon.

A differenza delle chiavi di filiale, esiste una sola versione di chiave beacon per ogni key store. branch-key-id La chiave beacon non viene mai ruotata.

Definizione della fonte della chiave beacon

Quando si definisce la versione del beacon per i beacon standard e composti, è necessario identificare la chiave beacon e definire un limite di tempo di vita della cache (TTL) per i materiali della chiave beacon. I materiali delle chiavi beacon sono archiviati in una cache locale separata dalle chiavi di filiale. Lo snippet seguente mostra come definire il per un database single-tenant. keySource Identifica la tua chiave beacon in base alla chiave a cui è associata. branch-key-id

Java
keySource(BeaconKeySource.builder() .single(SingleKeyStore.builder() .keyId(branch-key-id) .cacheTTL(6000) .build()) .build())
C# / .NET
KeySource = new BeaconKeySource { Single = new SingleKeyStore { KeyId = branch-key-id, CacheTTL = 6000 } }
Rust
.key_source(BeaconKeySource::Single( SingleKeyStore::builder() // `keyId` references a beacon key. // For every branch key we create in the keystore, // we also create a beacon key. // This beacon key is not the same as the branch key, // but is created with the same ID as the branch key. .key_id(branch_key_id) .cache_ttl(6000) .build()?, ))
Definizione della fonte del beacon in un database multitenant

Se si dispone di un database multitenant, è necessario specificare i seguenti valori durante la configurazione di. keySource

  • keyFieldName

    Definisce il nome del campo che memorizza la chiave beacon branch-key-id associata utilizzata per generare i beacon per un determinato tenant. keyFieldNamePuò essere qualsiasi stringa, ma deve essere univoca per tutti gli altri campi del database. Quando si scrivono nuovi record nel database, in branch-key-id questo campo viene memorizzata la chiave beacon utilizzata per generare i beacon per quel record. È necessario includere questo campo nelle query sui beacon e identificare i materiali chiave beacon appropriati necessari per ricalcolare il beacon. Per ulteriori informazioni, consulta Interrogazione dei beacon in un database multi-tenant.

  • CacheTTL

    Il periodo di tempo, in secondi, durante il quale una chiave beacon può essere utilizzata per l'immissione dei materiali nella cache locale del beacon prima della scadenza. Questo valore deve essere maggiore di zero. Quando il limite TTL della cache scade, la voce viene rimossa dalla cache locale.

  • (Facoltativo) Una cache

    Se desideri personalizzare il tipo di cache o il numero di voci relative ai materiali delle chiavi di filiale che possono essere archiviate nella cache locale, specifica il tipo di cache e la capacità di immissione quando inizializzi il portachiavi.

    Il portachiavi gerarchico supporta i seguenti tipi di cache: predefinita,, MultiThreaded e condivisa. StormTracking Per ulteriori informazioni ed esempi che dimostrano come definire ogni tipo di cache, vedere. Scegli una cache

    Se non si specifica una cache, il portachiavi gerarchico utilizza automaticamente il tipo di cache predefinito e imposta la capacità di immissione su 1000.

L'esempio seguente crea un portachiavi gerarchico con un ID di filiale, un fornitore, un limite di cache (TLL) di 600 secondi e una capacità di immissione di 1000.

Java
final MaterialProviders matProv = MaterialProviders.builder() .MaterialProvidersConfig(MaterialProvidersConfig.builder().build()) .build(); final CreateAwsKmsHierarchicalKeyringInput keyringInput = CreateAwsKmsHierarchicalKeyringInput.builder() .keyStore(keystore) .branchKeyIdSupplier(branchKeyIdSupplier) .ttlSeconds(600) .cache(CacheType.builder() //OPTIONAL .Default(DefaultCache.builder() .entryCapacity(1000) .build()) .build()); final IKeyring hierarchicalKeyring = matProv.CreateAwsKmsHierarchicalKeyring(keyringInput);
C# / .NET
var matProv = new MaterialProviders(new MaterialProvidersConfig()); var keyringInput = new CreateAwsKmsHierarchicalKeyringInput { KeyStore = keystore, BranchKeyIdSupplier = branchKeyIdSupplier, TtlSeconds = 600, Cache = new CacheType { Default = new DefaultCache { EntryCapacity = 1000 } } }; var hierarchicalKeyring = matProv.CreateAwsKmsHierarchicalKeyring(keyringInput);
Rust
let provider_config = MaterialProvidersConfig::builder().build()?; let mat_prov = client::Client::from_conf(provider_config)?; let kms_keyring = mat_prov .create_aws_kms_hierarchical_keyring() .branch_key_id(branch_key_id) .key_store(keystore.clone()) .ttl_seconds(600) .send() .await?;