

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à.

# Caching della chiave dei dati
<a name="data-key-caching"></a>

Il *caching della chiave di dati* memorizza le [chiavi di dati](concepts.md#DEK) e i [relativi materiali crittografici](data-caching-details.md#cache-entries) in una cache. Quando si crittografano o decrittografano i dati, AWS Encryption SDK cerca una chiave dati corrispondente nella cache. Se trova una corrispondenza, utilizza la chiave di dati memorizzata nella cache anziché generarne una nuova. Il caching della chiave di dati è in grado di migliorare le prestazioni, ridurre i costi e consentirti di rimanere entro limiti di servizio durante il dimensionamento dell'applicazione. 

La tua applicazione è in grado di sfruttare i vantaggi offerti dal caching della chiave dei dati se:
+ Può riutilizzare le chiavi di dati.
+ Genera numerose chiavi di dati. 
+ Le operazioni di crittografia sono troppo lente, costose, limitate o utilizzano una quantità eccessiva di risorse.

La memorizzazione nella cache può ridurre l'uso di servizi crittografici, come (). AWS Key Management Service AWS KMS Se state raggiungendo il [AWS KMS requests-per-secondlimite](https://docs.aws.amazon.com/kms/latest/developerguide/limits.html#requests-per-second), la memorizzazione nella cache può aiutarvi. L'applicazione può utilizzare le chiavi memorizzate nella cache per soddisfare alcune delle richieste di chiavi di dati anziché chiamare. AWS KMS(Puoi anche creare un caso nel [AWS Support Center](https://console.aws.amazon.com/support/home#/) per aumentare il limite per il tuo account.)

Ti AWS Encryption SDK aiuta a creare e gestire la cache delle chiavi di dati. [Fornisce una [cache locale](data-caching-details.md#simplecache) e un [gestore di materiali crittografici per la memorizzazione](data-caching-details.md#caching-cmm) nella cache (caching CMM) che interagisce con la cache e applica le soglie di sicurezza impostate.](thresholds.md) Lavorando insieme, questi componenti consentono di trarre vantaggio dall'efficienza di riutilizzare le chiavi dei dati, mantenendo, al contempo, la sicurezza del sistema.

La memorizzazione nella cache delle chiavi di dati è una funzionalità opzionale che è necessario utilizzare con cautela. AWS Encryption SDK Per impostazione predefinita, AWS Encryption SDK genera una nuova chiave dati per ogni operazione di crittografia. Questa tecnica supporta le best practice di crittografia, che scoraggiano il riutilizzo eccessivo delle chiavi di dati. In generale, è possibile usare il caching delle chiavi dei dati solo quando è necessario per soddisfare gli obiettivi di performance. Quindi, utilizza le [soglie di sicurezza](thresholds.md) del caching della chiave di dati per assicurarti di utilizzare la quantità minima di caching necessaria per soddisfare i tuoi obiettivi di costi e prestazioni. 

Versione 3. *x* of the SDK di crittografia AWS per Java only supporta la memorizzazione nella cache della CMM con l'interfaccia legacy dei provider di chiavi principali, non l'interfaccia keyring. Tuttavia, la versione 4. *x* e versioni successive di AWS Encryption SDK for .NET, versione 3. *x* della SDK di crittografia AWS per Java versione 4. *x* della SDK di crittografia AWS per Python, versione 1. *x* del AWS Encryption SDK per Rust e versione 0.1. *x* o versioni successive di AWS Encryption SDK for Go supportano il [portachiavi AWS KMS Hierarchical](use-hierarchical-keyring.md), una soluzione alternativa per la memorizzazione nella cache dei materiali crittografici. I contenuti crittografati con il portachiavi AWS KMS gerarchico possono essere decrittografati solo con il portachiavi gerarchico. AWS KMS 

Per una discussione dettagliata di questi compromessi in materia di sicurezza, vedi [AWS Encryption SDK: Come decidere se la memorizzazione nella cache delle chiavi di dati è adatta alla](https://aws.amazon.com/blogs/security/aws-encryption-sdk-how-to-decide-if-data-key-caching-is-right-for-your-application/) tua applicazione nel blog sulla sicurezza. AWS 

**Topics**
+ [Come utilizzare il caching della chiave di dati](implement-caching.md)
+ [Impostazione delle soglie di sicurezza della cache](thresholds.md)
+ [Dettagli di caching della chiave dei dati](data-caching-details.md)
+ [Esempio di caching della chiave dei dati](sample-cache-example.md)

# Come utilizzare il caching della chiave di dati
<a name="implement-caching"></a>

Questo argomento illustra come utilizzare il caching della chiave di dati all'interno dell'applicazione. Questo argomento consente di eseguire il processo passo per passo. Quindi, combina i passaggi in un semplice esempio che utilizza il caching della chiave dei dati in un'operazione per crittografare una stringa.

Gli esempi in questa sezione mostrano come utilizzare la [versione 2.0. ](about-versions.md)*x* e versioni successive di AWS Encryption SDK. Per esempi che utilizzano versioni precedenti, trova la tua versione nell'elenco [Releases](https://github.com/aws/aws-encryption-sdk-c/releases) del GitHub repository per il tuo [linguaggio di programmazione](programming-languages.md).

Per esempi completi e testati di utilizzo della memorizzazione nella cache delle chiavi di dati in AWS Encryption SDK, consulta:
+ C/C\$1\$1: [caching\$1cmm.cpp](https://github.com/aws/aws-encryption-sdk-c/blob/master/examples/caching_cmm.cpp)
+ [Java: SimpleDataKeyCachingExample .java](https://github.com/aws/aws-encryption-sdk-java/blob/master/src/examples/java/com/amazonaws/crypto/examples/v2/SimpleDataKeyCachingExample.java)
+ JavaScript [Browser: caching\$1cmm.ts](https://github.com/aws/aws-encryption-sdk-javascript/blob/master/modules/example-browser/src/caching_cmm.ts)
+ JavaScript Node.js: [caching\$1cmm.ts](https://github.com/aws/aws-encryption-sdk-javascript/blob/master/modules/example-node/src/caching_cmm.ts)
+ Python: [data\$1key\$1caching\$1basic.py](https://github.com/aws/aws-encryption-sdk-python/blob/master/examples/src/legacy/data_key_caching_basic.py)

The [AWS Encryption SDK for .NET](dot-net.md) non supporta la memorizzazione nella cache delle chiavi di dati.

**Topics**
+ [Utilizzo della memorizzazione nella cache delle chiavi dati: Step-by-step](#implement-caching-steps)
+ [Esempio di caching della chiave di dati: crittografare una stringa](#caching-example-encrypt-string)

## Utilizzo della memorizzazione nella cache delle chiavi dati: Step-by-step
<a name="implement-caching-steps"></a>

Queste step-by-step istruzioni mostrano come creare i componenti necessari per implementare la memorizzazione nella cache delle chiavi di dati.
+ [Creare una cache della chiave di dati](data-caching-details.md#simplecache). In questi esempi, utilizziamo la cache locale AWS Encryption SDK fornita da loro. Limitiamo la cache a 10 chiavi di dati.

   

------
#### [ C ]

  ```
  // Cache capacity (maximum number of entries) is required
  size_t cache_capacity = 10; 
  struct aws_allocator *allocator = aws_default_allocator();
  
  struct aws_cryptosdk_materials_cache *cache = aws_cryptosdk_materials_cache_local_new(allocator, cache_capacity);
  ```

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

  L'esempio seguente utilizza la versione 2. *x* di SDK di crittografia AWS per Java. Versione 3. *x* of the SDK di crittografia AWS per Java depreca la chiave dati che memorizza nella cache CMM. Con la versione 3. *x*, puoi anche usare il [portachiavi AWS KMS Hierarchical](use-hierarchical-keyring.md), una soluzione alternativa per la memorizzazione nella cache dei materiali crittografici.

  ```
  // Cache capacity (maximum number of entries) is required
  int MAX_CACHE_SIZE = 10; 
  
  CryptoMaterialsCache cache = new LocalCryptoMaterialsCache(MAX_CACHE_SIZE);
  ```

------
#### [ JavaScript Browser ]

  ```
  const capacity = 10
  
  const cache = getLocalCryptographicMaterialsCache(capacity)
  ```

------
#### [ JavaScript Node.js ]

  ```
  const capacity = 10
  
  const cache = getLocalCryptographicMaterialsCache(capacity)
  ```

------
#### [ Python ]

  ```
  # Cache capacity (maximum number of entries) is required
  MAX_CACHE_SIZE = 10
  
  cache = aws_encryption_sdk.LocalCryptoMaterialsCache(MAX_CACHE_SIZE)
  ```

------

   
+ Crea un [provider di chiavi principali](concepts.md#master-key-provider) (Java e Python) o un [portachiavi](concepts.md#keyring) (C e). JavaScript [Questi esempi utilizzano un provider di chiavi master AWS Key Management Service (AWS KMS) o un portachiavi compatibile AWS KMS .](use-kms-keyring.md)

   

------
#### [ C ]

  ```
  // Create an AWS KMS keyring
  //   The input is the Amazon Resource Name (ARN) 
  //   of an AWS KMS key
  struct aws_cryptosdk_keyring *kms_keyring = Aws::Cryptosdk::KmsKeyring::Builder().Build(kms_key_arn);
  ```

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

  L'esempio seguente utilizza la versione 2. *x* di SDK di crittografia AWS per Java. Versione 3. *x* of the SDK di crittografia AWS per Java depreca la chiave dati che memorizza nella cache CMM. Con la versione 3. *x*, puoi anche usare il [portachiavi AWS KMS Hierarchical](use-hierarchical-keyring.md), una soluzione alternativa per la memorizzazione nella cache dei materiali crittografici.

  ```
  // Create an AWS KMS master key provider
  //   The input is the Amazon Resource Name (ARN) 
  //   of an AWS KMS key
  MasterKeyProvider<KmsMasterKey> keyProvider = KmsMasterKeyProvider.builder().buildStrict(kmsKeyArn);
  ```

------
#### [ JavaScript Browser ]

  Nel browser, inserisci le credenziali in modo sicuro. Questo esempio definisce le credenziali in un webpack (kms.webpack.config) che risolve le credenziali in fase di esecuzione. Crea un'istanza AWS KMS del provider client da un AWS KMS client e dalle credenziali. Quindi, quando crea il portachiavi, passa il provider del client al costruttore insieme a (. AWS KMS key `generatorKeyId)`

  ```
  const { accessKeyId, secretAccessKey, sessionToken } = credentials
  
  const clientProvider = getClient(KMS, {
      credentials: {
        accessKeyId,
        secretAccessKey,
        sessionToken
      }
    })
  
  /*  Create an AWS KMS keyring
   *  You must configure the AWS KMS keyring with at least one AWS KMS key
  *  The input is the Amazon Resource Name (ARN) 
   */ of an AWS KMS key
  const keyring = new KmsKeyringBrowser({
      clientProvider,
      generatorKeyId,
      keyIds,
    })
  ```

------
#### [ JavaScript Node.js ]

  ```
  /* Create an AWS KMS keyring
   *   The input is the Amazon Resource Name (ARN) 
  */   of an AWS KMS key
  const keyring = new KmsKeyringNode({ generatorKeyId })
  ```

------
#### [ Python ]

  ```
  # Create an AWS KMS master key provider
  #  The input is the Amazon Resource Name (ARN) 
  #  of an AWS KMS key
  key_provider = aws_encryption_sdk.StrictAwsKmsMasterKeyProvider(key_ids=[kms_key_arn])
  ```

------

   
+ [Crea un gestore di materiali crittografici con memorizzazione nella cache (memorizzazione nella cache CMM](data-caching-details.md#caching-cmm)). 

   

  Associate la CMM per la memorizzazione nella cache alla cache e al vostro provider di chiavi principali o portachiavi. Quindi, [imposta le soglie di sicurezza della cache sulla CMM che memorizza nella cache.](thresholds.md) 

   

------
#### [ C ]

  In SDK di crittografia AWS per C, è possibile creare una CMM memorizzata nella cache da una CMM sottostante, ad esempio la CMM predefinita, o da un portachiavi. Questo esempio crea il CMM di caching da un keyring.

  Dopo aver creato la CMM con memorizzazione nella cache, è possibile rilasciare i riferimenti al portachiavi e alla cache. Per informazioni dettagliate, vedi [Conteggio dei riferimenti](c-language-using.md#c-language-using-release).

  ```
  // Create the caching CMM
  //   Set the partition ID to NULL.
  //   Set the required maximum age value to 60 seconds.
  struct aws_cryptosdk_cmm *caching_cmm = aws_cryptosdk_caching_cmm_new_from_keyring(allocator, cache, kms_keyring, NULL, 60, AWS_TIMESTAMP_SECS);
  
  // Add an optional message threshold
  //   The cached data key will not be used for more than 10 messages.
  aws_status = aws_cryptosdk_caching_cmm_set_limit_messages(caching_cmm, 10);
  
  // Release your references to the cache and the keyring.
  aws_cryptosdk_materials_cache_release(cache);
  aws_cryptosdk_keyring_release(kms_keyring);
  ```

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

  L'esempio seguente utilizza la versione 2. *x* di SDK di crittografia AWS per Java. Versione 3. *x* of the SDK di crittografia AWS per Java non supporta la memorizzazione nella cache delle chiavi di dati, ma supporta il [portachiavi AWS KMS Hierarchical](use-hierarchical-keyring.md), una soluzione alternativa di memorizzazione nella cache dei materiali crittografici.

  ```
  /*
   * Security thresholds
   *   Max entry age is required. 
   *   Max messages (and max bytes) per entry are optional
   */
  int MAX_ENTRY_AGE_SECONDS = 60;
  int MAX_ENTRY_MSGS = 10;
         
  //Create a caching CMM
  CryptoMaterialsManager cachingCmm =
      CachingCryptoMaterialsManager.newBuilder().withMasterKeyProvider(keyProvider)
                                   .withCache(cache)
                                   .withMaxAge(MAX_ENTRY_AGE_SECONDS, TimeUnit.SECONDS)
                                   .withMessageUseLimit(MAX_ENTRY_MSGS)
                                   .build();
  ```

------
#### [ JavaScript Browser ]

  ```
  /*
   * Security thresholds
   *   Max age (in milliseconds) is required.
   *   Max messages (and max bytes) per entry are optional.
   */
  const maxAge = 1000 * 60
  const maxMessagesEncrypted = 10
  
  /* Create a caching CMM from a keyring  */
  const cachingCmm = new WebCryptoCachingMaterialsManager({
    backingMaterials: keyring,
    cache,
    maxAge,
    maxMessagesEncrypted
  })
  ```

------
#### [ JavaScript Node.js ]

  ```
  /*
   * Security thresholds
   *   Max age (in milliseconds) is required.
   *   Max messages (and max bytes) per entry are optional.
   */
  const maxAge = 1000 * 60
  const maxMessagesEncrypted = 10
  
  /* Create a caching CMM from a keyring  */
  const cachingCmm = new NodeCachingMaterialsManager({
    backingMaterials: keyring,
    cache,
    maxAge,
    maxMessagesEncrypted
  })
  ```

------
#### [ Python ]

  ```
  # Security thresholds
  #   Max entry age is required. 
  #   Max messages (and max bytes) per entry are optional
  #
  MAX_ENTRY_AGE_SECONDS = 60.0
  MAX_ENTRY_MESSAGES = 10
         
  # Create a caching CMM
  caching_cmm = CachingCryptoMaterialsManager(
      master_key_provider=key_provider,
      cache=cache,
      max_age=MAX_ENTRY_AGE_SECONDS,
      max_messages_encrypted=MAX_ENTRY_MESSAGES
  )
  ```

------

Questo è tutto ciò che occorre fare. Quindi, lascia che AWS Encryption SDK gestiscano la cache per te o aggiungi la tua logica di gestione della cache.

Se desideri utilizzare la memorizzazione nella cache delle chiavi di dati in una chiamata per crittografare o decrittografare i dati, specifica la CMM per la memorizzazione nella cache anziché un provider di chiavi master o un'altra CMM.

**Nota**  
Se stai crittografando flussi di dati o qualsiasi tipo di dato di dimensioni sconosciute, assicurati di specificare la dimensione dei dati nella richiesta. AWS Encryption SDK Non utilizza la memorizzazione nella cache delle chiavi di dati per crittografare dati di dimensioni sconosciute.

------
#### [ C ]

In SDK di crittografia AWS per C, si crea una sessione con la CMM di memorizzazione nella cache e quindi si elabora la sessione. 

Per impostazione predefinita, quando la dimensione del messaggio è sconosciuta e illimitata, le chiavi di dati AWS Encryption SDK non vengono memorizzate nella cache. Per consentire il caching quando non si conoscono le dimensioni dei dati esatte, utilizza il metodo `aws_cryptosdk_session_set_message_bound` per impostare una dimensione massima per il messaggio. Imposta il limite su un valore superiore rispetto alle dimensioni stimate. Se le dimensioni effettive del messaggio superano il limite, l'operazione di crittografia non riuscirà.

```
/* Create a session with the caching CMM. Set the session mode to encrypt. */
struct aws_cryptosdk_session *session = aws_cryptosdk_session_new_from_cmm_2(allocator, AWS_CRYPTOSDK_ENCRYPT, caching_cmm);

/* Set a message bound of 1000 bytes */
aws_status = aws_cryptosdk_session_set_message_bound(session, 1000);

/* Encrypt the message using the session with the caching CMM */
aws_status = aws_cryptosdk_session_process(
             session, output_buffer, output_capacity, &output_produced, input_buffer, input_len, &input_consumed);

/* Release your references to the caching CMM and the session. */
aws_cryptosdk_cmm_release(caching_cmm);
aws_cryptosdk_session_destroy(session);
```

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

L'esempio seguente utilizza la versione 2. *x* di SDK di crittografia AWS per Java. Versione 3. *x* of the SDK di crittografia AWS per Java depreca la chiave dati che memorizza nella cache CMM. Con la versione 3. *x*, puoi anche usare il [portachiavi AWS KMS Hierarchical](use-hierarchical-keyring.md), una soluzione alternativa per la memorizzazione nella cache dei materiali crittografici.

```
// When the call to encryptData specifies a caching CMM,
// the encryption operation uses the data key cache
final AwsCrypto encryptionSdk = AwsCrypto.standard();
return encryptionSdk.encryptData(cachingCmm, plaintext_source).getResult();
```

------
#### [ JavaScript Browser ]

```
const { result } = await encrypt(cachingCmm, plaintext)
```

------
#### [ JavaScript Node.js ]

Quando si utilizza la CMM SDK di crittografia AWS per JavaScript per la memorizzazione nella cache di Node.js, il `encrypt` metodo richiede la lunghezza del testo in chiaro. Se non la fornisci, la chiave di dati non viene memorizzata nella cache. Se fornisci una lunghezza, ma i dati di testo normale forniti superano tale lunghezza, l'operazione di crittografia non riesce. Se non conosci la lunghezza esatta del testo normale, ad esempio per un flusso di dati, specifica il valore massimo previsto.

```
const { result } = await encrypt(cachingCmm, plaintext, { plaintextLength: plaintext.length })
```

------
#### [ Python ]

```
# Set up an encryption client
client = aws_encryption_sdk.EncryptionSDKClient()

# When the call to encrypt specifies a caching CMM,
# the encryption operation uses the data key cache
#
encrypted_message, header = client.encrypt(
    source=plaintext_source,
    materials_manager=caching_cmm
)
```

------

## Esempio di caching della chiave di dati: crittografare una stringa
<a name="caching-example-encrypt-string"></a>

Questo semplice esempio di codice utilizza il caching della chiave di dati per crittografare una stringa. Combina il codice della [step-by-step procedura](#implement-caching-steps) nel codice di test che è possibile eseguire.

L'esempio crea una [cache locale](data-caching-details.md#simplecache) e un [provider](concepts.md#master-key-provider) o [portachiavi principale](concepts.md#keyring) per un AWS KMS key. [Quindi, utilizza la cache locale e il provider o portachiavi principale per creare una CMM con memorizzazione nella cache con soglie di sicurezza appropriate.](thresholds.md) [In Java e Python, la richiesta di crittografia specifica la CMM di memorizzazione nella cache, i dati in chiaro da crittografare e un contesto di crittografia.](data-caching-details.md#caching-encryption-context) In C, il CMM di caching è specificato nella sessione e la sessione viene fornita alla richiesta di crittografia.

Per eseguire questi esempi, devi fornire l'[Amazon Resource Name (ARN) di](https://docs.aws.amazon.com/kms/latest/developerguide/viewing-keys.html) un. AWS KMS key Assicurati di avere le [autorizzazioni per utilizzare la AWS KMS key](https://docs.aws.amazon.com/kms/latest/developerguide/key-policies.html#key-policy-default-allow-users) e generare una chiave di dati.

Per esempi più dettagliati e reali di creazione e utilizzo di una cache di chiavi di dati, consulta. [Codice di esempio di memorizzazione nella cache delle chiavi dati](sample-cache-example-code.md)

------
#### [ C ]

```
/*
 * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"). You may not use
 * this file except in compliance with the License. A copy of the License is
 * located at
 *
 *     http://aws.amazon.com/apache2.0/
 *
 * or in the "license" file accompanying this file. This file is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 * implied. See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <aws/cryptosdk/cache.h>
#include <aws/cryptosdk/cpp/kms_keyring.h>
#include <aws/cryptosdk/session.h>

void encrypt_with_caching(
    uint8_t *ciphertext,     // output will go here (assumes ciphertext_capacity bytes already allocated)
    size_t *ciphertext_len,  // length of output will go here
    size_t ciphertext_capacity,
    const char *kms_key_arn,
    int max_entry_age,
    int cache_capacity) {
    const uint64_t MAX_ENTRY_MSGS = 100;

    struct aws_allocator *allocator = aws_default_allocator();
    
    // Load error strings for debugging
    aws_cryptosdk_load_error_strings();

    // Create a keyring
    struct aws_cryptosdk_keyring *kms_keyring = Aws::Cryptosdk::KmsKeyring::Builder().Build(kms_key_arn);

    // Create a cache
    struct aws_cryptosdk_materials_cache *cache = aws_cryptosdk_materials_cache_local_new(allocator, cache_capacity);

    // Create a caching CMM
    struct aws_cryptosdk_cmm *caching_cmm = aws_cryptosdk_caching_cmm_new_from_keyring(
        allocator, cache, kms_keyring, NULL, max_entry_age, AWS_TIMESTAMP_SECS);
    if (!caching_cmm) abort();

    if (aws_cryptosdk_caching_cmm_set_limit_messages(caching_cmm, MAX_ENTRY_MSGS)) abort();

    // Create a session
    struct aws_cryptosdk_session *session =        
        aws_cryptosdk_session_new_from_cmm_2(allocator, AWS_CRYPTOSDK_ENCRYPT, caching_cmm);
    if (!session) abort();

    // Encryption context
    struct aws_hash_table *enc_ctx = aws_cryptosdk_session_get_enc_ctx_ptr_mut(session);
    if (!enc_ctx) abort();
    AWS_STATIC_STRING_FROM_LITERAL(enc_ctx_key, "purpose");
    AWS_STATIC_STRING_FROM_LITERAL(enc_ctx_value, "test");
    if (aws_hash_table_put(enc_ctx, enc_ctx_key, (void *)enc_ctx_value, NULL)) abort();

    // Plaintext data to be encrypted
    const char *my_data = "My plaintext data";
    size_t my_data_len  = strlen(my_data);
    if (aws_cryptosdk_session_set_message_size(session, my_data_len)) abort();

    // When the session uses a caching CMM, the encryption operation uses the data key cache
    // specified in the caching CMM.
    size_t bytes_read;
    if (aws_cryptosdk_session_process(
            session,
            ciphertext,
            ciphertext_capacity,
            ciphertext_len,
            (const uint8_t *)my_data,
            my_data_len,
            &bytes_read))
        abort();
    if (!aws_cryptosdk_session_is_done(session) || bytes_read != my_data_len) abort();

    aws_cryptosdk_session_destroy(session);
    aws_cryptosdk_cmm_release(caching_cmm);
    aws_cryptosdk_materials_cache_release(cache);
    aws_cryptosdk_keyring_release(kms_keyring);
}
```

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

L'esempio seguente utilizza la versione 2. *x* di SDK di crittografia AWS per Java. Versione 3. *x* of the SDK di crittografia AWS per Java depreca la chiave dati che memorizza nella cache CMM. Con la versione 3. *x*, puoi anche usare il [portachiavi AWS KMS Hierarchical](use-hierarchical-keyring.md), una soluzione alternativa per la memorizzazione nella cache dei materiali crittografici.

```
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package com.amazonaws.crypto.examples;

import com.amazonaws.encryptionsdk.AwsCrypto;
import com.amazonaws.encryptionsdk.CryptoMaterialsManager;
import com.amazonaws.encryptionsdk.MasterKeyProvider;
import com.amazonaws.encryptionsdk.caching.CachingCryptoMaterialsManager;
import com.amazonaws.encryptionsdk.caching.CryptoMaterialsCache;
import com.amazonaws.encryptionsdk.caching.LocalCryptoMaterialsCache;
import com.amazonaws.encryptionsdk.kmssdkv2.KmsMasterKey;
import com.amazonaws.encryptionsdk.kmssdkv2.KmsMasterKeyProvider;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * Encrypts a string using an &KMS; key and data key caching
 *
 * <p>
 * Arguments:
 * <ol>
 * <li>KMS Key ARN: To find the Amazon Resource Name of your &KMS; key,
 *     see 'Find the key ID and ARN' at https://docs.aws.amazon.com/kms/latest/developerguide/find-cmk-id-arn.html
 * <li>Max entry age: Maximum time (in seconds) that a cached entry can be used
 * <li>Cache capacity: Maximum number of entries in the cache
 * </ol>
 */
public class SimpleDataKeyCachingExample {

    /*
     * Security thresholds
     *   Max entry age is required.
     *   Max messages (and max bytes) per data key are optional
     */
    private static final int MAX_ENTRY_MSGS = 100;

    public static byte[] encryptWithCaching(String kmsKeyArn, int maxEntryAge, int cacheCapacity) {
        // Plaintext data to be encrypted
        byte[] myData = "My plaintext data".getBytes(StandardCharsets.UTF_8);

        // Encryption context
        // Most encrypted data should have an associated encryption context
        // to protect integrity. This sample uses placeholder values.
        // For more information see:
        // blogs.aws.amazon.com/security/post/Tx2LZ6WBJJANTNW/How-to-Protect-the-Integrity-of-Your-Encrypted-Data-by-Using-AWS-Key-Management
        final Map<String, String> encryptionContext = Collections.singletonMap("purpose", "test");

        // Create a master key provider
        MasterKeyProvider<KmsMasterKey> keyProvider = KmsMasterKeyProvider.builder()
            .buildStrict(kmsKeyArn);

        // Create a cache
        CryptoMaterialsCache cache = new LocalCryptoMaterialsCache(cacheCapacity);

        // Create a caching CMM
        CryptoMaterialsManager cachingCmm =
            CachingCryptoMaterialsManager.newBuilder().withMasterKeyProvider(keyProvider)
                .withCache(cache)
                .withMaxAge(maxEntryAge, TimeUnit.SECONDS)
                .withMessageUseLimit(MAX_ENTRY_MSGS)
                .build();

        // When the call to encryptData specifies a caching CMM,
        // the encryption operation uses the data key cache
        final AwsCrypto encryptionSdk = AwsCrypto.standard();
        return encryptionSdk.encryptData(cachingCmm, myData, encryptionContext).getResult();
    }
}
```

------
#### [ JavaScript Browser ]

```
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

/* This is a simple example of using a caching CMM with a KMS keyring
 * to encrypt and decrypt using the AWS Encryption SDK for Javascript in a browser.
 */

import {
  KmsKeyringBrowser,
  KMS,
  getClient,
  buildClient,
  CommitmentPolicy,
  WebCryptoCachingMaterialsManager,
  getLocalCryptographicMaterialsCache,
} from '@aws-crypto/client-browser'
import { toBase64 } from '@aws-sdk/util-base64-browser'

/* This builds the client with the REQUIRE_ENCRYPT_REQUIRE_DECRYPT commitment policy,
 * which enforces that this client only encrypts using committing algorithm suites
 * and enforces that this client
 * will only decrypt encrypted messages
 * that were created with a committing algorithm suite.
 * This is the default commitment policy
 * if you build the client with `buildClient()`.
 */
const { encrypt, decrypt } = buildClient(
  CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT
)

/* This is injected by webpack.
 * The webpack.DefinePlugin or @aws-sdk/karma-credential-loader will replace the values when bundling.
 * The credential values are pulled from @aws-sdk/credential-provider-node
 * Use any method you like to get credentials into the browser.
 * See kms.webpack.config
 */
declare const credentials: {
  accessKeyId: string
  secretAccessKey: string
  sessionToken: string
}

/* This is done to facilitate testing. */
export async function testCachingCMMExample() {
  /* This example uses an &KMS; keyring. The generator key in a &KMS; keyring generates and encrypts the data key.
   * The caller needs kms:GenerateDataKey permission on the &KMS; key in generatorKeyId.
   */
  const generatorKeyId =
    'arn:aws:kms:us-west-2:658956600833:alias/EncryptDecrypt'

  /* Adding additional KMS keys that can decrypt.
   * The caller must have kms:Encrypt permission for every &KMS; key in keyIds.
   * You might list several keys in different AWS Regions.
   * This allows you to decrypt the data in any of the represented Regions.
   * In this example, the generator key
   * and the additional key are actually the same &KMS; key.
   * In `generatorId`, this &KMS; key is identified by its alias ARN.
   * In `keyIds`, this &KMS; key is identified by its key ARN.
   * In practice, you would specify different &KMS; keys,
   * or omit the `keyIds` parameter.
   * This is *only* to demonstrate how the &KMS; key ARNs are configured.
   */
  const keyIds = [
    'arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f',
  ]

  /* Need a client provider that will inject correct credentials.
   * The credentials here are injected by webpack from your environment bundle is created
   * The credential values are pulled using @aws-sdk/credential-provider-node.
   * See kms.webpack.config
   * You should inject your credential into the browser in a secure manner
   * that works with your application.
   */
  const { accessKeyId, secretAccessKey, sessionToken } = credentials

  /* getClient takes a KMS client constructor
   * and optional configuration values.
   * The credentials can be injected here,
   * because browsers do not have a standard credential discovery process the way Node.js does.
   */
  const clientProvider = getClient(KMS, {
    credentials: {
      accessKeyId,
      secretAccessKey,
      sessionToken,
    },
  })

  /* You must configure the KMS keyring with your &KMS; keys */
  const keyring = new KmsKeyringBrowser({
    clientProvider,
    generatorKeyId,
    keyIds,
  })

  /* Create a cache to hold the data keys (and related cryptographic material).
   * This example uses the local cache provided by the Encryption SDK.
   * The `capacity` value represents the maximum number of entries
   * that the cache can hold.
   * To make room for an additional entry,
   * the cache evicts the oldest cached entry.
   * Both encrypt and decrypt requests count independently towards this threshold.
   * Entries that exceed any cache threshold are actively removed from the cache.
   * By default, the SDK checks one item in the cache every 60 seconds (60,000 milliseconds).
   * To change this frequency, pass in a `proactiveFrequency` value
   * as the second parameter. This value is in milliseconds.
   */
  const capacity = 100
  const cache = getLocalCryptographicMaterialsCache(capacity)

  /* The partition name lets multiple caching CMMs share the same local cryptographic cache.
   * By default, the entries for each CMM are cached separately. However, if you want these CMMs to share the cache,
   * use the same partition name for both caching CMMs.
   * If you don't supply a partition name, the Encryption SDK generates a random name for each caching CMM.
   * As a result, sharing elements in the cache MUST be an intentional operation.
   */
  const partition = 'local partition name'

  /* maxAge is the time in milliseconds that an entry will be cached.
   * Elements are actively removed from the cache.
   */
  const maxAge = 1000 * 60

  /* The maximum number of bytes that will be encrypted under a single data key.
   * This value is optional,
   * but you should configure the lowest practical value.
   */
  const maxBytesEncrypted = 100

  /* The maximum number of messages that will be encrypted under a single data key.
   * This value is optional,
   * but you should configure the lowest practical value.
   */
  const maxMessagesEncrypted = 10

  const cachingCMM = new WebCryptoCachingMaterialsManager({
    backingMaterials: keyring,
    cache,
    partition,
    maxAge,
    maxBytesEncrypted,
    maxMessagesEncrypted,
  })

  /* Encryption context is a *very* powerful tool for controlling
   * and managing access.
   * When you pass an encryption context to the encrypt function,
   * the encryption context is cryptographically bound to the ciphertext.
   * If you don't pass in the same encryption context when decrypting,
   * the decrypt function fails.
   * The encryption context is ***not*** secret!
   * Encrypted data is opaque.
   * You can use an encryption context to assert things about the encrypted data.
   * The encryption context helps you to determine
   * whether the ciphertext you retrieved is the ciphertext you expect to decrypt.
   * For example, if you are are only expecting data from 'us-west-2',
   * the appearance of a different AWS Region in the encryption context can indicate malicious interference.
   * See: https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html#encryption-context
   *
   * Also, cached data keys are reused ***only*** when the encryption contexts passed into the functions are an exact case-sensitive match.
   * See: https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/data-caching-details.html#caching-encryption-context
   */
  const encryptionContext = {
    stage: 'demo',
    purpose: 'simple demonstration app',
    origin: 'us-west-2',
  }

  /* Find data to encrypt. */
  const plainText = new Uint8Array([1, 2, 3, 4, 5])

  /* Encrypt the data.
   * The caching CMM only reuses data keys
   * when it know the length (or an estimate) of the plaintext.
   * However, in the browser,
   * you must provide all of the plaintext to the encrypt function.
   * Therefore, the encrypt function in the browser knows the length of the plaintext
   * and does not accept a plaintextLength option.
   */
  const { result } = await encrypt(cachingCMM, plainText, { encryptionContext })

  /* Log the plain text
   * only for testing and to show that it works.
   */
  console.log('plainText:', plainText)
  document.write('</br>plainText:' + plainText + '</br>')

  /* Log the base64-encoded result
   * so that you can try decrypting it with another AWS Encryption SDK implementation.
   */
  const resultBase64 = toBase64(result)
  console.log(resultBase64)
  document.write(resultBase64)

  /* Decrypt the data.
   * NOTE: This decrypt request will not use the data key
   * that was cached during the encrypt operation.
   * Data keys for encrypt and decrypt operations are cached separately.
   */
  const { plaintext, messageHeader } = await decrypt(cachingCMM, result)

  /* Grab the encryption context so you can verify it. */
  const { encryptionContext: decryptedContext } = messageHeader

  /* Verify the encryption context.
   * If you use an algorithm suite with signing,
   * the Encryption SDK adds a name-value pair to the encryption context that contains the public key.
   * Because the encryption context might contain additional key-value pairs,
   * do not include a test that requires that all key-value pairs match.
   * Instead, verify that the key-value pairs that you supplied to the `encrypt` function are included in the encryption context that the `decrypt` function returns.
   */
  Object.entries(encryptionContext).forEach(([key, value]) => {
    if (decryptedContext[key] !== value)
      throw new Error('Encryption Context does not match expected values')
  })

  /* Log the clear message
   * only for testing and to show that it works.
   */
  document.write('</br>Decrypted:' + plaintext)
  console.log(plaintext)

  /* Return the values to make testing easy. */
  return { plainText, plaintext }
}
```

------
#### [ JavaScript Node.js ]

```
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

import {
  KmsKeyringNode,
  buildClient,
  CommitmentPolicy,
  NodeCachingMaterialsManager,
  getLocalCryptographicMaterialsCache,
} from '@aws-crypto/client-node'

/* This builds the client with the REQUIRE_ENCRYPT_REQUIRE_DECRYPT commitment policy,
 * which enforces that this client only encrypts using committing algorithm suites
 * and enforces that this client
 * will only decrypt encrypted messages
 * that were created with a committing algorithm suite.
 * This is the default commitment policy
 * if you build the client with `buildClient()`.
 */
const { encrypt, decrypt } = buildClient(
  CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT
)

export async function cachingCMMNodeSimpleTest() {
  /* An &KMS; key is required to generate the data key.
   * You need kms:GenerateDataKey permission on the &KMS; key in generatorKeyId.
   */
  const generatorKeyId =
    'arn:aws:kms:us-west-2:658956600833:alias/EncryptDecrypt'

  /* Adding alternate &KMS; keys that can decrypt.
   * Access to kms:Encrypt is required for every &KMS; key in keyIds.
   * You might list several keys in different AWS Regions.
   * This allows you to decrypt the data in any of the represented Regions.
   * In this example, the generator key
   * and the additional key are actually the same &KMS; key.
   * In `generatorId`, this &KMS; key is identified by its alias ARN.
   * In `keyIds`, this &KMS; key is identified by its key ARN.
   * In practice, you would specify different &KMS; keys,
   * or omit the `keyIds` parameter.
   * This is *only* to demonstrate how the &KMS; key ARNs are configured.
   */
  const keyIds = [
    'arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f',
  ]

  /* The &KMS; keyring must be configured with the desired &KMS; keys
   * This example passes the keyring to the caching CMM
   * instead of using it directly.
   */
  const keyring = new KmsKeyringNode({ generatorKeyId, keyIds })

  /* Create a cache to hold the data keys (and related cryptographic material).
   * This example uses the local cache provided by the Encryption SDK.
   * The `capacity` value represents the maximum number of entries
   * that the cache can hold.
   * To make room for an additional entry,
   * the cache evicts the oldest cached entry.
   * Both encrypt and decrypt requests count independently towards this threshold.
   * Entries that exceed any cache threshold are actively removed from the cache.
   * By default, the SDK checks one item in the cache every 60 seconds (60,000 milliseconds).
   * To change this frequency, pass in a `proactiveFrequency` value
   * as the second parameter. This value is in milliseconds.
   */
  const capacity = 100
  const cache = getLocalCryptographicMaterialsCache(capacity)

  /* The partition name lets multiple caching CMMs share the same local cryptographic cache.
   * By default, the entries for each CMM are cached separately. However, if you want these CMMs to share the cache,
   * use the same partition name for both caching CMMs.
   * If you don't supply a partition name, the Encryption SDK generates a random name for each caching CMM.
   * As a result, sharing elements in the cache MUST be an intentional operation.
   */
  const partition = 'local partition name'

  /* maxAge is the time in milliseconds that an entry will be cached.
   * Elements are actively removed from the cache.
   */
  const maxAge = 1000 * 60

  /* The maximum amount of bytes that will be encrypted under a single data key.
   * This value is optional,
   * but you should configure the lowest value possible.
   */
  const maxBytesEncrypted = 100

  /* The maximum number of messages that will be encrypted under a single data key.
   * This value is optional,
   * but you should configure the lowest value possible.
   */
  const maxMessagesEncrypted = 10

  const cachingCMM = new NodeCachingMaterialsManager({
    backingMaterials: keyring,
    cache,
    partition,
    maxAge,
    maxBytesEncrypted,
    maxMessagesEncrypted,
  })

  /* Encryption context is a *very* powerful tool for controlling
   * and managing access.
   * When you pass an encryption context to the encrypt function,
   * the encryption context is cryptographically bound to the ciphertext.
   * If you don't pass in the same encryption context when decrypting,
   * the decrypt function fails.
   * The encryption context is ***not*** secret!
   * Encrypted data is opaque.
   * You can use an encryption context to assert things about the encrypted data.
   * The encryption context helps you to determine
   * whether the ciphertext you retrieved is the ciphertext you expect to decrypt.
   * For example, if you are are only expecting data from 'us-west-2',
   * the appearance of a different AWS Region in the encryption context can indicate malicious interference.
   * See: https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html#encryption-context
   *
   * Also, cached data keys are reused ***only*** when the encryption contexts passed into the functions are an exact case-sensitive match.
   * See: https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/data-caching-details.html#caching-encryption-context
   */
  const encryptionContext = {
    stage: 'demo',
    purpose: 'simple demonstration app',
    origin: 'us-west-2',
  }

  /* Find data to encrypt.  A simple string. */
  const cleartext = 'asdf'

  /* Encrypt the data.
   * The caching CMM only reuses data keys
   * when it know the length (or an estimate) of the plaintext.
   * If you do not know the length,
   * because the data is a stream
   * provide an estimate of the largest expected value.
   *
   * If your estimate is smaller than the actual plaintext length
   * the AWS Encryption SDK will throw an exception.
   *
   * If the plaintext is not a stream,
   * the AWS Encryption SDK uses the actual plaintext length
   * instead of any length you provide.
   */
  const { result } = await encrypt(cachingCMM, cleartext, {
    encryptionContext,
    plaintextLength: 4,
  })

  /* Decrypt the data.
   * NOTE: This decrypt request will not use the data key
   * that was cached during the encrypt operation.
   * Data keys for encrypt and decrypt operations are cached separately.
   */
  const { plaintext, messageHeader } = await decrypt(cachingCMM, result)

  /* Grab the encryption context so you can verify it. */
  const { encryptionContext: decryptedContext } = messageHeader

  /* Verify the encryption context.
   * If you use an algorithm suite with signing,
   * the Encryption SDK adds a name-value pair to the encryption context that contains the public key.
   * Because the encryption context might contain additional key-value pairs,
   * do not include a test that requires that all key-value pairs match.
   * Instead, verify that the key-value pairs that you supplied to the `encrypt` function are included in the encryption context that the `decrypt` function returns.
   */
  Object.entries(encryptionContext).forEach(([key, value]) => {
    if (decryptedContext[key] !== value)
      throw new Error('Encryption Context does not match expected values')
  })

  /* Return the values so the code can be tested. */
  return { plaintext, result, cleartext, messageHeader }
}
```

------
#### [ Python ]

```
# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"). You
# may not use this file except in compliance with the License. A copy of
# the License is located at
#
# http://aws.amazon.com/apache2.0/
#
# or in the "license" file accompanying this file. This file is
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
# ANY KIND, either express or implied. See the License for the specific
# language governing permissions and limitations under the License.
"""Example of encryption with data key caching."""
import aws_encryption_sdk
from aws_encryption_sdk import CommitmentPolicy


def encrypt_with_caching(kms_key_arn, max_age_in_cache, cache_capacity):
    """Encrypts a string using an &KMS; key and data key caching.

    :param str kms_key_arn: Amazon Resource Name (ARN) of the &KMS; key
    :param float max_age_in_cache: Maximum time in seconds that a cached entry can be used
    :param int cache_capacity: Maximum number of entries to retain in cache at once
    """
    # Data to be encrypted
    my_data = "My plaintext data"

    # Security thresholds
    #   Max messages (or max bytes per) data key are optional
    MAX_ENTRY_MESSAGES = 100

    # Create an encryption context
    encryption_context = {"purpose": "test"}

    # Set up an encryption client with an explicit commitment policy. Note that if you do not explicitly choose a
    # commitment policy, REQUIRE_ENCRYPT_REQUIRE_DECRYPT is used by default.
    client = aws_encryption_sdk.EncryptionSDKClient(commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT)

    # Create a master key provider for the &KMS; key
    key_provider = aws_encryption_sdk.StrictAwsKmsMasterKeyProvider(key_ids=[kms_key_arn])

    # Create a local cache
    cache = aws_encryption_sdk.LocalCryptoMaterialsCache(cache_capacity)

    # Create a caching CMM
    caching_cmm = aws_encryption_sdk.CachingCryptoMaterialsManager(
        master_key_provider=key_provider,
        cache=cache,
        max_age=max_age_in_cache,
        max_messages_encrypted=MAX_ENTRY_MESSAGES,
    )

    # When the call to encrypt data specifies a caching CMM,
    # the encryption operation uses the data key cache specified
    # in the caching CMM
    encrypted_message, _header = client.encrypt(
        source=my_data, materials_manager=caching_cmm, encryption_context=encryption_context
    )

    return encrypted_message
```

------

# Impostazione delle soglie di sicurezza della cache
<a name="thresholds"></a>

Quando si implementa la memorizzazione nella cache delle chiavi di dati, è necessario configurare le soglie di sicurezza applicate dalla CMM di memorizzazione nella [cache](data-caching-details.md#caching-cmm). 

Le soglie di sicurezza consentono di limitare per quanto tempo viene utilizzata ciascuna chiave di dati memorizzata nella cache e la quantità di dati protetta in ciascuna chiave di dati. La CMM con memorizzazione nella cache restituisce le chiavi di dati memorizzate nella cache solo quando l'immissione nella cache è conforme a tutte le soglie di sicurezza. Se la voce della cache supera qualsiasi soglia, non viene utilizzata per l'operazione corrente e viene esclusa immediatamente dalla cache. Il primo utilizzo di ciascuna chiave di dati (prima del caching) è esente da queste soglie. 

In generale, è possibile usare la quantità minima di caching obbligatoria per soddisfare gli obiettivi in termini di costi e prestazioni. 

[L' AWS Encryption SDK unica memorizza nella cache le chiavi di dati crittografate utilizzando una funzione di derivazione delle chiavi.](https://en.wikipedia.org/wiki/Key_derivation_function) Inoltre, stabilisce i limiti massimi per alcuni valori di soglia. Queste restrizioni assicurano che le chiavi dei dati non vengano riutilizzate oltre i limiti crittografici. Tuttavia, poiché le chiavi di dati di testo non crittografato vengono memorizzate nella cache (in memoria, per impostazione predefinita), prova a ridurre al minimo il tempo durante il quale le chiavi vengono salvate. Inoltre, prova a limitare i dati che potrebbero essere esposti se una chiave è compromessa.

Per esempi di impostazione delle soglie di sicurezza della cache, vedi [AWS Encryption SDK: Come decidere se la memorizzazione nella cache delle chiavi di dati è adatta alla tua applicazione](https://aws.amazon.com/blogs/security/aws-encryption-sdk-how-to-decide-if-data-key-caching-is-right-for-your-application/) nel blog sulla sicurezza. AWS 

**Nota**  
Il CMM del caching applica tutte le seguenti soglie. Se non si specifica un valore opzionale, il CMM del caching usa il valore predefinito.  
Per disabilitare temporaneamente la memorizzazione nella cache delle chiavi di dati, le implementazioni Java e Python forniscono *una cache di AWS Encryption SDK materiali crittografici nulli (cache null*). La cache null restituisce un vuoto per ogni richiesta `GET` e non risponde alle richieste `PUT`. È consigliabile utilizzare la cache null invece di impostare la [capacità della cache](data-caching-details.md#simplecache) o le soglie di sicurezza su 0. Per ulteriori informazioni, consulta gli argomenti relativi alla cache null in [Java](https://aws.github.io/aws-encryption-sdk-java/com/amazonaws/encryptionsdk/caching/NullCryptoMaterialsCache.html) e [Python](https://aws-encryption-sdk-python.readthedocs.io/en/latest/generated/aws_encryption_sdk.caches.null.html).

**Età massima (obbligatoria)**  
Stabilisce per quanto tempo può essere utilizzata una voce di cache, dal momento in cui è stata aggiunta. Questo valore è obbligatorio. Immetti un valore superiore a 0. AWS Encryption SDK Non limita il valore massimo di età.  
Tutte le implementazioni linguistiche di AWS Encryption SDK definiscono l'età massima in secondi, ad eccezione di SDK di crittografia AWS per JavaScript, che utilizza millisecondi.  
Utilizza l'intervallo più breve che consente ancora alla tua applicazione di trarre vantaggio dalla cache. È possibile usare la soglia dell'età massima come una policy di rotazione delle chiavi. Utilizzala per limitare il riutilizzo delle chiavi dei dati, ridurre al minimo l'esposizione di materiali crittografici ed eliminare le chiavi di dati le cui policy potrebbero essere cambiate mentre sono state memorizzate nella cache.

**Il numero massimo di messaggi crittografati (opzionale)**  
Stabilisce il numero massimo di messaggi che una chiave di dati nella cache è in grado di crittografare. Questo valore è facoltativo. Inserisci un valore tra 1 e 2^32 messaggi. Il valore predefinito è 2^32 messaggi.  
Imposta il numero di messaggi protetti da ciascuna chiave memorizzata nella cache in modo che sia sufficiente per ottenere valore dal riutilizzo, ma abbastanza contenuto per limitare il numero di messaggi che potrebbero essere esposti se una chiave è compromessa.

**Il numero massimo di byte crittografati (opzionale)**  
Stabilisce il numero massimo di byte che una chiave di dati nella cache è in grado di crittografare. Questo valore è facoltativo. Inserisci un valore tra 0 e 2^63 - 1. Il valore predefinito è 2^63 - 1. Il valore 0 consente di utilizzare il caching della chiave di dati solo quando stai crittografando stringhe di messaggio vuote.  
I byte nella richiesta corrente sono inclusi durante la valutazione di questa soglia. Se i byte elaborati, più i byte attuali, superano la soglia, la chiave di dati memorizzata viene rimossa dalla cache, anche se è possibile che sia stata utilizzata per una richiesta di dimensioni ridotte. 

# Dettagli di caching della chiave dei dati
<a name="data-caching-details"></a>

La maggior parte delle applicazioni possono utilizzare l'impostazione predefinita del caching della chiavi dei dati senza la necessità di scrivere codice personalizzato. Questa sezione descrive l'implementazione predefinita e alcuni dettagli sulle opzioni. 

**Topics**
+ [In che modo funziona il caching della chiave dei dati](#how-caching-works)
+ [Creazione di una cache di materiali crittografici](#simplecache)
+ [Creazione di un responsabile della cache di materiali crittografici](#caching-cmm)
+ [Cosa c'è in una voce della cache della chiave di dati?](#cache-entries)
+ [Contesto di crittografia: come selezionare le voci di cache](#caching-encryption-context)
+ [La mia applicazione utilizza chiavi dati memorizzate nella cache?](#caching-effect)

## In che modo funziona il caching della chiave dei dati
<a name="how-caching-works"></a>

Quando utilizzi il caching della chiave dei dati in una richiesta di crittografia o decrittografia dei dati, AWS Encryption SDK prima cerca la cache per una chiave di dati in grado di soddisfare la richiesta. Se trova una corrispondenza valida, utilizza la chiave di dati memorizzati per crittografare i dati. In caso contrario, genera una nuova chiave di dati, come farebbe in assenza della cache. 

Il caching della chiave di dati non viene utilizzato per i dati di dimensione sconosciuta, come, ad esempio i dati in streaming. Ciò consente alla CMM di memorizzazione nella cache di applicare correttamente la soglia [massima](thresholds.md) di byte. Per evitare questo comportamento, aggiungi le dimensioni del messaggio alla richiesta di crittografia. 

Oltre alla cache, la memorizzazione nella cache delle chiavi di dati utilizza un gestore di materiali [crittografici per la memorizzazione nella cache (caching CMM](#caching-cmm)). [[Il CMM con memorizzazione nella cache è un [gestore specializzato di materiali crittografici (CMM) che interagisce con una cache e una CMM sottostante.](concepts.md#crypt-materials-manager)](concepts.md#crypt-materials-manager)](#simplecache) (Quando specificate un [provider di chiavi master](concepts.md#master-key-provider) o un portachiavi, AWS Encryption SDK crea automaticamente una CMM predefinita.) La CMM con funzionalità di memorizzazione nella cache memorizza nella cache le chiavi di dati restituite dalla CMM sottostante. La CMM con memorizzazione nella cache applica anche le soglie di sicurezza della cache impostate dall'utente. 

Per evitare che dalla cache venga selezionata la chiave di dati errata, tutte le operazioni di caching compatibili CMMs richiedono che le seguenti proprietà dei materiali crittografici memorizzati nella cache corrispondano alla richiesta dei materiali.
+ [Suite di algoritmi](concepts.md#crypto-algorithm)
+ [Contesto di crittografia](#caching-encryption-context) (anche se vuoto)
+ Nome della partizione (una stringa che identifica la CMM memorizzata nella cache)
+ (Solo decrittazione) Chiavi di dati crittografate

**Nota**  
[Memorizza nella AWS Encryption SDK cache le chiavi di dati solo quando la [suite di algoritmi](concepts.md#crypto-algorithm) utilizza una funzione di derivazione delle chiavi.](https://en.wikipedia.org/wiki/Key_derivation_function)

I seguenti flussi di lavoro mostrano il modo in cui una richiesta di crittografia dei dati viene elaborata con e senza il caching della chiave dei dati. Mostrano come i componenti di memorizzazione nella cache creati, tra cui la cache e la CMM di memorizzazione nella cache, vengono utilizzati nel processo.

### Crittografia dei dati senza caching
<a name="workflow-wo-cache"></a>

Per ottenere i materiali di crittografia senza caching:

1. Un'applicazione chiede loro di AWS Encryption SDK crittografare i dati. 

   La richiesta specifica un fornitore o un portachiavi principale. AWS Encryption SDK crea una CMM predefinita che interagisce con il provider o il portachiavi principale.

1.  AWS Encryption SDK Richiede alla CMM il materiale di crittografia (procurati materiale crittografico).

1. La CMM richiede materiale crittografico al suo [portachiavi](concepts.md#keyring) (C e JavaScript) o al [provider di chiavi master](concepts.md#master-key-provider) (Java e Python). Ciò potrebbe comportare una chiamata a un servizio crittografico, come (). AWS Key Management Service AWS KMS La CMM restituisce i materiali di crittografia a. AWS Encryption SDK

1.  AWS Encryption SDK Utilizza la chiave dati in testo semplice per crittografare i dati. Archivia i dati crittografati e le chiavi di dati crittografate in un [messaggio crittografato](concepts.md#message) che viene restituito all'utente.

![\[Crittografia dei dati senza caching\]](http://docs.aws.amazon.com/it_it/encryption-sdk/latest/developer-guide/images/encrypt-workflow-no-cache.png)


### Crittografia dei dati con il caching
<a name="workflow-with-cache"></a>

Per ottenere i materiali di crittografia con il caching della chiave di dati:

1. Un'applicazione chiede loro di AWS Encryption SDK crittografare i dati. 

   La richiesta specifica un gestore di [materiali crittografici per la memorizzazione nella cache (caching CMM) associato a un gestore](#caching-cmm) di materiali crittografici (CMM) sottostante. Quando specificate un fornitore di chiavi master o un portachiavi, crea automaticamente una CMM predefinita. AWS Encryption SDK 

1. L'SDK richiede alla CMM di memorizzazione nella cache specificata i materiali di crittografia.

1. La CMM che memorizza nella cache richiede materiali di crittografia dalla cache.

   1. Se la cache trova una corrispondenza, aggiorna la data e i valori di utilizzo della voce della cache corrispondente e restituisce i materiali di crittografia memorizzati nella cache alla CMM che memorizza nella cache. 

      Se la voce della cache è conforme alle [relative soglie di sicurezza, la CMM inserita nella cache la restituisce all'SDK](thresholds.md). In caso contrario, comunica alla cache di eliminare la voce e di procedere come se non ci fossero corrispondenze.

   1. Se la cache non riesce a trovare una corrispondenza valida, la CMM inserita nella cache chiede alla CMM sottostante di generare una nuova chiave di dati. 

      La CMM sottostante ottiene i materiali crittografici dal suo portachiavi (C e JavaScript) o dal provider di chiavi master (Java e Python). Questo potrebbe comportare una chiamata a un servizio, come AWS Key Management Service. La CMM sottostante restituisce il testo semplice e le copie crittografate della chiave dati alla CMM memorizzata nella cache. 

      La CMM con memorizzazione nella cache salva i nuovi materiali di crittografia nella cache.

1. La CMM con memorizzazione nella cache restituisce i materiali di crittografia a. AWS Encryption SDK

1.  AWS Encryption SDK Utilizza la chiave dati in testo semplice per crittografare i dati. Archivia i dati crittografati e le chiavi di dati crittografate in un [messaggio crittografato](concepts.md#message) che viene restituito all'utente.

![\[Crittografia dei dati con il caching della chiave dei dati\]](http://docs.aws.amazon.com/it_it/encryption-sdk/latest/developer-guide/images/encrypt-workflow-with-cache.png)


## Creazione di una cache di materiali crittografici
<a name="simplecache"></a>

 AWS Encryption SDK Definisce i requisiti per una cache di materiali crittografici utilizzata nella memorizzazione nella cache delle chiavi di dati. Fornisce inoltre una cache locale, che è una cache configurabile, in memoria, [usata meno di recente (](https://en.wikipedia.org/wiki/Cache_replacement_policies#Least_Recently_Used_.28LRU.29)LRU). Per creare un'istanza della cache locale, usa il `LocalCryptoMaterialsCache` costruttore in Java e Python, getLocalCryptographic MaterialsCache la funzione JavaScript in o `aws_cryptosdk_materials_cache_local_new` il costruttore in C.

La cache locale include la logica per la gestione di base della cache, tra cui l'aggiunta, l'eliminazione e la corrispondenza delle voci memorizzate nella cache e la manutenzione della cache. Non è necessario scrivere una logica di gestione della cache personalizzata. È possibile utilizzare la cache locale così com'è, personalizzarla o sostituirla con qualsiasi cache compatibile. 

Quando si crea una cache locale, si imposta la *capacità*, ovvero il numero massimo di voci che la cache può contenere. Questa impostazione consente di progettare una cache efficiente con un riutilizzo della chiave dei dati limitato.

 SDK di crittografia AWS per Python Inoltre forniscono una *cache di materiali crittografici nulli* ()NullCryptoMaterialsCache. SDK di crittografia AWS per Java NullCryptoMaterialsCache Restituisce un errore per tutte le `GET` operazioni e non risponde alle `PUT` operazioni. È possibile utilizzarlo NullCryptoMaterialsCache in fase di test o per disabilitare temporaneamente la memorizzazione nella cache in un'applicazione che include codice di memorizzazione nella cache. 

In AWS Encryption SDK, ogni cache di materiali crittografici è associata a un [gestore di materiali crittografici per la memorizzazione nella cache (caching CMM](#caching-cmm)). [La CMM con memorizzazione nella cache ottiene le chiavi di dati dalla cache, inserisce le chiavi di dati nella cache e applica le soglie di sicurezza impostate dall'utente.](thresholds.md) Quando si crea una CMM con memorizzazione nella cache, si specifica la cache utilizzata e la CMM sottostante o il provider di chiavi master che genera le chiavi di dati memorizzate nella cache.

## Creazione di un responsabile della cache di materiali crittografici
<a name="caching-cmm"></a>

Per abilitare la memorizzazione nella cache delle chiavi di dati, create una [cache e un gestore di materiali crittografici per la memorizzazione nella cache](#simplecache) *(caching CMM*). [[Quindi, nelle richieste di crittografia o decrittografia dei dati, specificate una CMM con memorizzazione nella cache, anziché un [gestore di materiali crittografici](concepts.md#crypt-materials-manager) (CMM) standard o un provider di chiavi master o un portachiavi.](concepts.md#keyring)](concepts.md#master-key-provider)

Esistono due tipi di. CMMs Entrambi ottengono le chiavi dei dati (e relativo materiale crittografico), ma in modi diversi, come segue:
+ Una CMM è associata a un portachiavi (C o JavaScript) o a un provider di chiavi master (Java e Python). Quando l'SDK richiede alla CMM materiali di crittografia o decrittografia, la CMM ottiene i materiali dal suo portachiavi o dal fornitore della chiave principale. In Java e Python, il CMM utilizza le chiavi master per generare, crittografare o decrittare le chiavi di dati. In C e JavaScript, il portachiavi genera, crittografa e restituisce i materiali crittografici.
+ Una CMM con memorizzazione nella cache è associata a una cache, ad esempio una [cache locale](#simplecache), e a una CMM sottostante. Quando l'SDK richiede alla CMM di memorizzazione nella cache i materiali crittografici, la CMM che memorizza nella cache tenta di recuperarli dalla cache. Se non riesce a trovare una corrispondenza, la CMM inserita nella cache chiede i materiali alla CMM sottostante. Quindi, memorizza nella cache i nuovi materiali crittografici prima di restituirli all'intermediario. 

La CMM con memorizzazione nella cache applica anche le [soglie di sicurezza impostate](thresholds.md) per ogni voce della cache. Poiché le soglie di sicurezza sono impostate e applicate dalla CMM di memorizzazione nella cache, è possibile utilizzare qualsiasi cache compatibile, anche se la cache non è progettata per materiale sensibile.

## Cosa c'è in una voce della cache della chiave di dati?
<a name="cache-entries"></a>

Il caching della chiave di dati memorizza le chiavi di dati e i relativi materiali crittografici in una cache. Ogni voce include gli elementi elencati di seguito. Queste informazioni potrebbero essere utili quando decidi se utilizzare la funzionalità di memorizzazione nella cache delle chiavi di dati e quando imposti le soglie di sicurezza su un gestore di materiali crittografici che memorizza nella cache (memorizzazione nella cache CMM).

**Voci nella cache per le richieste di crittografia**  
Le voci che vengono aggiunte a una cache della chiave di dati in seguito a un'operazione di crittografia includono i seguenti elementi:
+ Chiave di dati di testo non crittografato
+ Chiavi di dati crittografati (una o più)
+ [Contesto di crittografia](#caching-encryption-context) 
+ Chiave di firma del messaggio (se ne viene utilizzata una)
+ [Suite di algoritmi](concepts.md#crypto-algorithm)
+ Metadati, inclusi i contatori di utilizzo per applicare le soglie di sicurezza

**Voci nella cache per le richieste di decrittografia**  
Le voci che vengono aggiunte a una cache della chiave di dati in seguito a un'operazione di decrittografia includono i seguenti elementi:
+ Chiave di dati di testo non crittografato
+ Chiave di verifica della firma (se ne viene utilizzata una)
+ Metadati, inclusi i contatori di utilizzo per applicare le soglie di sicurezza

## Contesto di crittografia: come selezionare le voci di cache
<a name="caching-encryption-context"></a>

È possibile specificare un contesto di crittografia in qualsiasi richiesta per crittografare i dati. Tuttavia, il contesto di crittografia svolge un ruolo speciale nel contesto del caching della chiave dei dati. Consente di creare sottogruppi di chiavi di dati nella cache, anche quando le chiavi dati provengono dalla stessa CMM con memorizzazione nella cache.

Un [contesto di crittografia](concepts.md#encryption-context) è un set di coppie chiave-valore che contiene dati arbitrari non segreti. Durante la crittografia, il contesto di crittografia è legato ai dati crittografati, in modo che lo stesso contesto di crittografia è necessario per decrittografare i dati. Nel AWS Encryption SDK, il contesto di crittografia viene archiviato nel [messaggio crittografato](concepts.md#message) con i dati e le chiavi di dati crittografati. 

Quando utilizzi una cache di chiavi di dati, è anche possibile utilizzare il contesto di crittografia per selezionare chiavi di dati specifiche nella cache per le tue operazioni di crittografia. Il contesto di crittografia viene salvato nella voce della cache con la chiave dei dati (fa parte dell'ID della voce della cache). Le chiavi dei dati nella cache vengono riutilizzate solo quando i contesti di crittografia corrispondono. Se desideri riutilizzare alcune chiavi dei dati per una richiesta di crittografia, specificare lo stesso contesto di crittografia. Se desideri evitare tali chiavi di dati, specifica un contesto di crittografia diverso. 

Il contesto di crittografia è sempre facoltativo, ma consigliato. Se non specifichi un contesto di crittografia nella tua richiesta, un contesto di crittografia vuoto è incluso nell'identificatore della voce di cache e corrisponde a ogni richiesta.

## La mia applicazione utilizza chiavi dati memorizzate nella cache?
<a name="caching-effect"></a>

La memorizzazione nella cache delle chiavi dati è una strategia di ottimizzazione molto efficace per determinate applicazioni e carichi di lavoro. Tuttavia, poiché comporta un certo rischio, è importante determinare quanto sia efficace per la propria situazione e quindi decidere se i benefici superano i rischi.

Poiché la memorizzazione nella cache delle chiavi dati riutilizza le chiavi dati, l'effetto più evidente è ridurre il numero di chiamate per generare nuove chiavi dati. Quando viene implementata la memorizzazione nella cache delle chiavi dati, AWS Encryption SDK richiama l' AWS KMS `GenerateDataKey`operazione solo per creare la chiave dati iniziale e quando manca la cache. Tuttavia, la memorizzazione nella cache migliora sensibilmente le prestazioni solo nelle applicazioni che generano numerose chiavi dati con le stesse caratteristiche, tra cui lo stesso contesto di crittografia e suite di algoritmi.

Per determinare se l'implementazione di utilizza effettivamente le chiavi di dati della cache, prova le seguenti tecniche. AWS Encryption SDK 
+ Nei registri della tua infrastruttura a chiave principale, controlla la frequenza delle chiamate per creare nuove chiavi dati. Quando la memorizzazione nella cache delle chiavi dati è efficace, il numero di chiamate per creare nuove chiavi dovrebbe diminuire sensibilmente. Ad esempio, se utilizzi un provider di chiavi AWS KMS master o un portachiavi, cerca le chiamate nei CloudTrail registri. [GenerateDataKey](https://docs.aws.amazon.com/kms/latest/APIReference/API_GenerateDataKey.html) 
+ Confrontare i [messaggi crittografati](concepts.md#message) restituiti da AWS Encryption SDK in risposta a diverse richieste di crittografia. Ad esempio, se utilizzate il SDK di crittografia AWS per Java, confrontate l'[ParsedCiphertext](https://aws.github.io/aws-encryption-sdk-java/com/amazonaws/encryptionsdk/ParsedCiphertext.html)oggetto con diverse chiamate di crittografia. In SDK di crittografia AWS per JavaScript, confronta il contenuto della `encryptedDataKeys` proprietà di [MessageHeader](https://github.com/aws/aws-encryption-sdk-javascript/blob/master/modules/serialize/src/types.ts#L21). Quando le chiavi dati vengono riutilizzate, le chiavi dati crittografate nel messaggio crittografato sono identiche.

# Esempio di caching della chiave dei dati
<a name="sample-cache-example"></a>

Questo esempio utilizza la [memorizzazione nella cache delle chiavi di dati](data-key-caching.md) con una [cache locale](data-caching-details.md#simplecache) per velocizzare un'applicazione in cui i dati generati da più dispositivi vengono crittografati e archiviati in regioni diverse.

In questo scenario, più produttori di dati generano dati, li crittografano e scrivono su un flusso [Kinesis](https://aws.amazon.com/kinesis/streams/) in ogni regione. [AWS Lambda](https://aws.amazon.com/lambda/)le funzioni (consumatori) decrittografano i flussi e scrivono dati in testo semplice in una tabella DynamoDB nella regione. [I produttori di dati e i consumatori utilizzano un fornitore di chiavi principali. AWS Encryption SDKAWS KMS](concepts.md#master-key-provider) Per ridurre le chiamate a KMS, ogni produttore e consumatore dispone della propria cache locale.

Puoi trovare il codice sorgente di questi esempi in [Java e Python](sample-cache-example-code.md). L'esempio include anche un CloudFormation modello che definisce le risorse per gli esempi.

![\[Questo diagramma mostra come produttori e consumatori di dati utilizzano Amazon Kinesis Data Streams e Amazon DynamoDB. AWS KMS\]](http://docs.aws.amazon.com/it_it/encryption-sdk/latest/developer-guide/images/simplecache-example.png)


## Risultati della cache locale
<a name="caching-example-impact"></a>

La tabella seguente mostra che una cache locale riduce il totale delle chiamate a KMS (al secondo per regione) in questo esempio all'1% del valore originale.


**Richieste del produttore**  
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/it_it/encryption-sdk/latest/developer-guide/sample-cache-example.html)


**Richieste dei consumatori**  
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/it_it/encryption-sdk/latest/developer-guide/sample-cache-example.html)

# Codice di esempio di memorizzazione nella cache delle chiavi dati
<a name="sample-cache-example-code"></a>

Questo esempio di codice crea una semplice implementazione della memorizzazione nella cache delle chiavi di dati con una [cache locale](data-caching-details.md#simplecache) in Java e Python. Il codice crea due istanze di una cache locale: una per [i produttori di dati](#caching-producer) che crittografano i dati e l'altra per i [consumatori di dati (AWS Lambda funzioni) che decifrano i dati](#caching-consumer). Per i dettagli sull'implementazione della memorizzazione nella cache delle chiavi di dati in ogni lingua, consulta la documentazione di [Javadoc e](https://aws.github.io/aws-encryption-sdk-java/) [Python](https://aws-encryption-sdk-python.readthedocs.io/en/latest/) per. AWS Encryption SDK

La memorizzazione nella cache delle chiavi dati è disponibile per tutti i [linguaggi di programmazione](programming-languages.md) supportati da. AWS Encryption SDK 

Per esempi completi e testati di utilizzo della memorizzazione nella cache delle chiavi di dati in AWS Encryption SDK, consulta:
+ C/C\$1\$1: [caching\$1cmm.cpp](https://github.com/aws/aws-encryption-sdk-c/blob/master/examples/caching_cmm.cpp) 
+ [Java: SimpleDataKeyCachingExample .java](https://github.com/aws/aws-encryption-sdk-java/blob/master/src/examples/java/com/amazonaws/crypto/examples/v2/SimpleDataKeyCachingExample.java)
+ JavaScript [Browser: caching\$1cmm.ts](https://github.com/aws/aws-encryption-sdk-javascript/blob/master/modules/example-browser/src/caching_cmm.ts) 
+ JavaScript Node.js: [caching\$1cmm.ts](https://github.com/aws/aws-encryption-sdk-javascript/blob/master/modules/example-node/src/caching_cmm.ts) 
+ Python: [data\$1key\$1caching\$1basic.py](https://github.com/aws/aws-encryption-sdk-python/blob/master/examples/src/legacy/data_key_caching_basic.py)

## Producer
<a name="caching-producer"></a>

[Il produttore ottiene una mappa, la converte in JSON, usa la per crittografarla AWS Encryption SDK e invia il record di testo cifrato a un flusso Kinesis in ciascuna di esse.](https://aws.amazon.com/kinesis/streams/) Regione AWS

[[Il codice definisce un [gestore di materiali crittografici per la memorizzazione nella cache (caching](data-caching-details.md#caching-cmm) CMM) e lo associa a una cache locale e a un provider di chiavi master sottostante.AWS KMS](concepts.md#master-key-provider)](data-caching-details.md#simplecache) La CMM con memorizzazione nella cache memorizza nella cache le chiavi di dati (e i [relativi materiali crittografici](data-caching-details.md#cache-entries)) del fornitore della chiave principale. Interagisce inoltre con la cache per conto di SDK e applica le soglie di sicurezza impostate. 

Poiché la chiamata al metodo di crittografia specifica una CMM memorizzata nella cache, anziché un normale [gestore di materiali crittografici (CMM) o un fornitore di chiavi master, la crittografia](concepts.md#crypt-materials-manager) utilizzerà la memorizzazione nella cache delle chiavi di dati.

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

L'esempio seguente utilizza la versione 2. *x* di SDK di crittografia AWS per Java. Versione 3. *x* of the SDK di crittografia AWS per Java depreca la chiave dati che memorizza nella cache CMM. Con la versione 3. *x*, puoi anche usare il [portachiavi AWS KMS Hierarchical](use-hierarchical-keyring.md), una soluzione alternativa per la memorizzazione nella cache dei materiali crittografici.

```
/*
 * Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except
 * in compliance with the License. A copy of the License is located at
 *
 * http://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 */
package com.amazonaws.crypto.examples.kinesisdatakeycaching;

import com.amazonaws.encryptionsdk.AwsCrypto;
import com.amazonaws.encryptionsdk.CommitmentPolicy;
import com.amazonaws.encryptionsdk.CryptoResult;
import com.amazonaws.encryptionsdk.MasterKeyProvider;
import com.amazonaws.encryptionsdk.caching.CachingCryptoMaterialsManager;
import com.amazonaws.encryptionsdk.caching.LocalCryptoMaterialsCache;
import com.amazonaws.encryptionsdk.kmssdkv2.KmsMasterKey;
import com.amazonaws.encryptionsdk.kmssdkv2.KmsMasterKeyProvider;
import com.amazonaws.encryptionsdk.multi.MultipleProviderFactory;
import com.amazonaws.util.json.Jackson;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider;
import software.amazon.awssdk.core.SdkBytes;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.kinesis.KinesisClient;
import software.amazon.awssdk.services.kms.KmsClient;

/**
 * Pushes data to Kinesis Streams in multiple Regions.
 */
public class MultiRegionRecordPusher {

    private static final long MAX_ENTRY_AGE_MILLISECONDS = 300000;
    private static final long MAX_ENTRY_USES = 100;
    private static final int MAX_CACHE_ENTRIES = 100;
    private final String streamName_;
    private final ArrayList<KinesisClient> kinesisClients_;
    private final CachingCryptoMaterialsManager cachingMaterialsManager_;
    private final AwsCrypto crypto_;

    /**
     * Creates an instance of this object with Kinesis clients for all target Regions and a cached
     * key provider containing KMS master keys in all target Regions.
     */
    public MultiRegionRecordPusher(final Region[] regions, final String kmsAliasName,
        final String streamName) {
        streamName_ = streamName;
        crypto_ = AwsCrypto.builder()
            .withCommitmentPolicy(CommitmentPolicy.RequireEncryptRequireDecrypt)
            .build();
        kinesisClients_ = new ArrayList<>();

        AwsCredentialsProvider credentialsProvider = DefaultCredentialsProvider.builder().build();

        // Build KmsMasterKey and AmazonKinesisClient objects for each target region
        List<KmsMasterKey> masterKeys = new ArrayList<>();
        for (Region region : regions) {
            kinesisClients_.add(KinesisClient.builder()
                .credentialsProvider(credentialsProvider)
                .region(region)
                .build());

            KmsMasterKey regionMasterKey = KmsMasterKeyProvider.builder()
                .defaultRegion(region)
                .builderSupplier(() -> KmsClient.builder().credentialsProvider(credentialsProvider))
                .buildStrict(kmsAliasName)
                .getMasterKey(kmsAliasName);

            masterKeys.add(regionMasterKey);
        }

        // Collect KmsMasterKey objects into single provider and add cache
        MasterKeyProvider<?> masterKeyProvider = MultipleProviderFactory.buildMultiProvider(
            KmsMasterKey.class,
            masterKeys
        );

        cachingMaterialsManager_ = CachingCryptoMaterialsManager.newBuilder()
            .withMasterKeyProvider(masterKeyProvider)
            .withCache(new LocalCryptoMaterialsCache(MAX_CACHE_ENTRIES))
            .withMaxAge(MAX_ENTRY_AGE_MILLISECONDS, TimeUnit.MILLISECONDS)
            .withMessageUseLimit(MAX_ENTRY_USES)
            .build();
    }

    /**
     * JSON serializes and encrypts the received record data and pushes it to all target streams.
     */
    public void putRecord(final Map<Object, Object> data) {
        String partitionKey = UUID.randomUUID().toString();
        Map<String, String> encryptionContext = new HashMap<>();
        encryptionContext.put("stream", streamName_);

        // JSON serialize data
        String jsonData = Jackson.toJsonString(data);

        // Encrypt data
        CryptoResult<byte[], ?> result = crypto_.encryptData(
            cachingMaterialsManager_,
            jsonData.getBytes(),
            encryptionContext
        );
        byte[] encryptedData = result.getResult();

        // Put records to Kinesis stream in all Regions
        for (KinesisClient regionalKinesisClient : kinesisClients_) {
            regionalKinesisClient.putRecord(builder ->
                builder.streamName(streamName_)
                    .data(SdkBytes.fromByteArray(encryptedData))
                    .partitionKey(partitionKey));
        }
    }
}
```

------
#### [ Python ]

```
"""
Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 
Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except
in compliance with the License. A copy of the License is located at
 
https://aws.amazon.com/apache-2-0/
 
or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
specific language governing permissions and limitations under the License.
"""
import json
import uuid
 
from aws_encryption_sdk import EncryptionSDKClient, StrictAwsKmsMasterKeyProvider, CachingCryptoMaterialsManager, LocalCryptoMaterialsCache, CommitmentPolicy
from aws_encryption_sdk.key_providers.kms import KMSMasterKey
import boto3
 
 
class MultiRegionRecordPusher(object):
    """Pushes data to Kinesis Streams in multiple Regions."""
    CACHE_CAPACITY = 100
    MAX_ENTRY_AGE_SECONDS = 300.0
    MAX_ENTRY_MESSAGES_ENCRYPTED = 100
 
    def __init__(self, regions, kms_alias_name, stream_name):
        self._kinesis_clients = []
        self._stream_name = stream_name
 
        # Set up EncryptionSDKClient
        _client = EncryptionSDKClient(CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT)
 
        # Set up KMSMasterKeyProvider with cache
        _key_provider = StrictAwsKmsMasterKeyProvider(kms_alias_name)
 
        # Add MasterKey and Kinesis client for each Region
        for region in regions:
            self._kinesis_clients.append(boto3.client('kinesis', region_name=region))
            regional_master_key = KMSMasterKey(
                client=boto3.client('kms', region_name=region),
                key_id=kms_alias_name
            )
            _key_provider.add_master_key_provider(regional_master_key)
 
        cache = LocalCryptoMaterialsCache(capacity=self.CACHE_CAPACITY)
        self._materials_manager = CachingCryptoMaterialsManager(
            master_key_provider=_key_provider,
            cache=cache,
            max_age=self.MAX_ENTRY_AGE_SECONDS,
            max_messages_encrypted=self.MAX_ENTRY_MESSAGES_ENCRYPTED
        )
 
    def put_record(self, record_data):
        """JSON serializes and encrypts the received record data and pushes it to all target streams.
 
        :param dict record_data: Data to write to stream
        """
        # Kinesis partition key to randomize write load across stream shards
        partition_key = uuid.uuid4().hex
 
        encryption_context = {'stream': self._stream_name}
 
        # JSON serialize data
        json_data = json.dumps(record_data)
 
        # Encrypt data
        encrypted_data, _header = _client.encrypt(
            source=json_data,
            materials_manager=self._materials_manager,
            encryption_context=encryption_context
        )
 
        # Put records to Kinesis stream in all Regions
        for client in self._kinesis_clients:
            client.put_record(
                StreamName=self._stream_name,
                Data=encrypted_data,
                PartitionKey=partition_key
            )
```

------

## Consumer
<a name="caching-consumer"></a>

Il data consumer è una [AWS Lambda](https://aws.amazon.com/lambda/)funzione attivata dagli eventi [Kinesis](https://aws.amazon.com/kinesis/). Decripta e deserializza ogni record e scrive il record in testo semplice in una tabella Amazon [DynamoDB](https://aws.amazon.com/dynamodb/) nella stessa regione.

Come il codice del produttore, il codice consumer consente la memorizzazione nella cache delle chiavi di dati utilizzando un gestore di materiali crittografici (caching CMM) nelle chiamate al metodo di decrittografia. 

*Il codice Java crea un provider di chiavi master in modalità rigorosa con un valore specificato.* AWS KMS key[La modalità rigorosa non è richiesta per la decrittografia, ma è una buona pratica.](best-practices.md#strict-discovery-mode) Il codice Python utilizza la *modalità di rilevamento*, che consente di AWS Encryption SDK utilizzare qualsiasi chiave di wrapping che ha crittografato una chiave dati per decrittografarla.

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

L'esempio seguente utilizza la versione 2. *x* di SDK di crittografia AWS per Java. Versione 3. *x* of the SDK di crittografia AWS per Java depreca la chiave dati che memorizza nella cache CMM. Con la versione 3. *x*, puoi anche usare il [portachiavi AWS KMS Hierarchical](use-hierarchical-keyring.md), una soluzione alternativa per la memorizzazione nella cache dei materiali crittografici.

Questo codice crea un provider di chiavi principali per la decrittografia in modalità rigorosa. AWS Encryption SDK Possono utilizzare solo il codice specificato dall' AWS KMS keys utente per decrittografare il messaggio.

```
/*
 * Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except
 * in compliance with the License. A copy of the License is located at
 *
 * http://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 */
package com.amazonaws.crypto.examples.kinesisdatakeycaching;

import com.amazonaws.encryptionsdk.AwsCrypto;
import com.amazonaws.encryptionsdk.CommitmentPolicy;
import com.amazonaws.encryptionsdk.CryptoResult;
import com.amazonaws.encryptionsdk.caching.CachingCryptoMaterialsManager;
import com.amazonaws.encryptionsdk.caching.LocalCryptoMaterialsCache;
import com.amazonaws.encryptionsdk.kmssdkv2.KmsMasterKeyProvider;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.events.KinesisEvent;
import com.amazonaws.services.lambda.runtime.events.KinesisEvent.KinesisEventRecord;
import com.amazonaws.util.BinaryUtils;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeUnit;
import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient;
import software.amazon.awssdk.enhanced.dynamodb.DynamoDbTable;
import software.amazon.awssdk.enhanced.dynamodb.TableSchema;

/**
 * Decrypts all incoming Kinesis records and writes records to DynamoDB.
 */
public class LambdaDecryptAndWrite {

    private static final long MAX_ENTRY_AGE_MILLISECONDS = 600000;
    private static final int MAX_CACHE_ENTRIES = 100;
    private final CachingCryptoMaterialsManager cachingMaterialsManager_;
    private final AwsCrypto crypto_;
    private final DynamoDbTable<Item> table_;

    /**
     * Because the cache is used only for decryption, the code doesn't set the max bytes or max
     * message security thresholds that are enforced only on on data keys used for encryption.
     */
    public LambdaDecryptAndWrite() {
        String kmsKeyArn = System.getenv("CMK_ARN");
        cachingMaterialsManager_ = CachingCryptoMaterialsManager.newBuilder()
            .withMasterKeyProvider(KmsMasterKeyProvider.builder().buildStrict(kmsKeyArn))
            .withCache(new LocalCryptoMaterialsCache(MAX_CACHE_ENTRIES))
            .withMaxAge(MAX_ENTRY_AGE_MILLISECONDS, TimeUnit.MILLISECONDS)
            .build();

        crypto_ = AwsCrypto.builder()
            .withCommitmentPolicy(CommitmentPolicy.RequireEncryptRequireDecrypt)
            .build();

        String tableName = System.getenv("TABLE_NAME");
        DynamoDbEnhancedClient dynamodb = DynamoDbEnhancedClient.builder().build();
        table_ = dynamodb.table(tableName, TableSchema.fromClass(Item.class));
    }

    /**
     * @param event
     * @param context
     */
    public void handleRequest(KinesisEvent event, Context context)
        throws UnsupportedEncodingException {
        for (KinesisEventRecord record : event.getRecords()) {
            ByteBuffer ciphertextBuffer = record.getKinesis().getData();
            byte[] ciphertext = BinaryUtils.copyAllBytesFrom(ciphertextBuffer);

            // Decrypt and unpack record
            CryptoResult<byte[], ?> plaintextResult = crypto_.decryptData(cachingMaterialsManager_,
                ciphertext);

            // Verify the encryption context value
            String streamArn = record.getEventSourceARN();
            String streamName = streamArn.substring(streamArn.indexOf("/") + 1);
            if (!streamName.equals(plaintextResult.getEncryptionContext().get("stream"))) {
                throw new IllegalStateException("Wrong Encryption Context!");
            }

            // Write record to DynamoDB
            String jsonItem = new String(plaintextResult.getResult(), StandardCharsets.UTF_8);
            System.out.println(jsonItem);
            table_.putItem(Item.fromJSON(jsonItem));
        }
    }

    private static class Item {

        static Item fromJSON(String jsonText) {
            // Parse JSON and create new Item
            return new Item();
        }
    }
}
```

------
#### [ Python ]

Questo codice Python viene decrittografato con un provider di chiavi master in modalità di scoperta. Consente di AWS Encryption SDK utilizzare qualsiasi chiave di wrapping che ha crittografato una chiave di dati per decrittografarla. [La modalità rigorosa, in cui si specificano le chiavi di wrapping che possono essere utilizzate per la decrittografia, è una procedura consigliata.](best-practices.md#strict-discovery-mode)

```
"""
Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 
Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except
in compliance with the License. A copy of the License is located at
 
https://aws.amazon.com/apache-2-0/
 
or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
specific language governing permissions and limitations under the License.
"""
import base64
import json
import logging
import os
 
from aws_encryption_sdk import EncryptionSDKClient, DiscoveryAwsKmsMasterKeyProvider, CachingCryptoMaterialsManager, LocalCryptoMaterialsCache, CommitmentPolicy
import boto3
 
_LOGGER = logging.getLogger(__name__)
_is_setup = False
CACHE_CAPACITY = 100
MAX_ENTRY_AGE_SECONDS = 600.0
 
def setup():
    """Sets up clients that should persist across Lambda invocations."""
    global encryption_sdk_client
    encryption_sdk_client = EncryptionSDKClient(CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT)
 
    global materials_manager
    key_provider = DiscoveryAwsKmsMasterKeyProvider()
    cache = LocalCryptoMaterialsCache(capacity=CACHE_CAPACITY)
           
    #  Because the cache is used only for decryption, the code doesn't set
    #   the max bytes or max message security thresholds that are enforced
    #   only on on data keys used for encryption.
    materials_manager = CachingCryptoMaterialsManager(
        master_key_provider=key_provider,
        cache=cache,
        max_age=MAX_ENTRY_AGE_SECONDS
    )
    global table
    table_name = os.environ.get('TABLE_NAME')
    table = boto3.resource('dynamodb').Table(table_name)
    global _is_setup
    _is_setup = True
 
 
def lambda_handler(event, context):
    """Decrypts all incoming Kinesis records and writes records to DynamoDB."""
    _LOGGER.debug('New event:')
    _LOGGER.debug(event)
    if not _is_setup:
        setup()
    with table.batch_writer() as batch:
        for record in event.get('Records', []):
            # Record data base64-encoded by Kinesis
            ciphertext = base64.b64decode(record['kinesis']['data'])
 
            # Decrypt and unpack record
            plaintext, header = encryption_sdk_client.decrypt(
                source=ciphertext,
                materials_manager=materials_manager
            )
            item = json.loads(plaintext)
 
            # Verify the encryption context value
            stream_name = record['eventSourceARN'].split('/', 1)[1]
            if stream_name != header.encryption_context['stream']:
                raise ValueError('Wrong Encryption Context!')
 
            # Write record to DynamoDB
            batch.put_item(Item=item)
```

------

# Esempio di memorizzazione nella cache di chiavi dati: modello CloudFormation
<a name="sample-cache-example-cloudformation"></a>

Questo CloudFormation modello imposta tutte le AWS risorse necessarie per riprodurre l'esempio di memorizzazione nella [cache delle chiavi di dati](sample-cache-example.md).

------
#### [ JSON ]

```
{
    "Parameters": {
        "SourceCodeBucket": {
            "Type": "String",
            "Description": "S3 bucket containing Lambda source code zip files"
        },
        "PythonLambdaS3Key": {
            "Type": "String",
            "Description": "S3 key containing Python Lambda source code zip file"
        },
        "PythonLambdaObjectVersionId": {
            "Type": "String",
            "Description": "S3 version id for S3 key containing Python Lambda source code zip file"
        },
        "JavaLambdaS3Key": {
            "Type": "String",
            "Description": "S3 key containing Python Lambda source code zip file"
        },
        "JavaLambdaObjectVersionId": {
            "Type": "String",
            "Description": "S3 version id for S3 key containing Python Lambda source code zip file"
        },
        "KeyAliasSuffix": {
            "Type": "String",
            "Description": "Suffix to use for KMS key Alias (ie: alias/KeyAliasSuffix)"
        },
        "StreamName": {
            "Type": "String",
            "Description": "Name to use for Kinesis Stream"
        }
    },
    "Resources": {
        "InputStream": {
            "Type": "AWS::Kinesis::Stream",
            "Properties": {
                "Name": {
                    "Ref": "StreamName"
                },
                "ShardCount": 2
            }
        },
        "PythonLambdaOutputTable": {
            "Type": "AWS::DynamoDB::Table",
            "Properties": {
                "AttributeDefinitions": [
                    {
                        "AttributeName": "id",
                        "AttributeType": "S"
                    }
                ],
                "KeySchema": [
                    {
                        "AttributeName": "id",
                        "KeyType": "HASH"
                    }
                ],
                "ProvisionedThroughput": {
                    "ReadCapacityUnits": 1,
                    "WriteCapacityUnits": 1
                }
            }
        },
        "PythonLambdaRole": {
            "Type": "AWS::IAM::Role",
            "Properties": {
                "AssumeRolePolicyDocument": {
                    "Version": "2012-10-17",		 	 	 
                    "Statement": [
                        {
                            "Effect": "Allow",
                            "Principal": {
                                "Service": "lambda.amazonaws.com"
                            },
                            "Action": "sts:AssumeRole"
                        }
                    ]
                },
                "ManagedPolicyArns": [
                    "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
                ],
                "Policies": [
                    {
                        "PolicyName": "PythonLambdaAccess",
                        "PolicyDocument": {
                            "Version": "2012-10-17",		 	 	 
                            "Statement": [
                                {
                                    "Effect": "Allow",
                                    "Action": [
                                        "dynamodb:DescribeTable",
                                        "dynamodb:BatchWriteItem"
                                    ],
                                    "Resource": {
                                        "Fn::Sub": "arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${PythonLambdaOutputTable}"
                                    }
                                },
                                {
                                    "Effect": "Allow",
                                    "Action": [
                                        "dynamodb:PutItem"
                                    ],
                                    "Resource": {
                                        "Fn::Sub": "arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${PythonLambdaOutputTable}*"
                                    }
                                },
                                {
                                    "Effect": "Allow",
                                    "Action": [
                                        "kinesis:GetRecords",
                                        "kinesis:GetShardIterator",
                                        "kinesis:DescribeStream",
                                        "kinesis:ListStreams"
                                    ],
                                    "Resource": {
                                        "Fn::Sub": "arn:aws:kinesis:${AWS::Region}:${AWS::AccountId}:stream/${InputStream}"
                                    }
                                }
                            ]
                        }
                    }
                ]
            }
        },
        "PythonLambdaFunction": {
            "Type": "AWS::Lambda::Function",
            "Properties": {
                "Description": "Python consumer",
                "Runtime": "python2.7",
                "MemorySize": 512,
                "Timeout": 90,
                "Role": {
                    "Fn::GetAtt": [
                        "PythonLambdaRole",
                        "Arn"
                    ]
                },
                "Handler": "aws_crypto_examples.kinesis_datakey_caching.consumer.lambda_handler",
                "Code": {
                    "S3Bucket": {
                        "Ref": "SourceCodeBucket"
                    },
                    "S3Key": {
                        "Ref": "PythonLambdaS3Key"
                    },
                    "S3ObjectVersion": {
                        "Ref": "PythonLambdaObjectVersionId"
                    }
                },
                "Environment": {
                    "Variables": {
                        "TABLE_NAME": {
                            "Ref": "PythonLambdaOutputTable"
                        }
                    }
                }
            }
        },
        "PythonLambdaSourceMapping": {
            "Type": "AWS::Lambda::EventSourceMapping",
            "Properties": {
                "BatchSize": 1,
                "Enabled": true,
                "EventSourceArn": {
                    "Fn::Sub": "arn:aws:kinesis:${AWS::Region}:${AWS::AccountId}:stream/${InputStream}"
                },
                "FunctionName": {
                    "Ref": "PythonLambdaFunction"
                },
                "StartingPosition": "TRIM_HORIZON"
            }
        },
        "JavaLambdaOutputTable": {
            "Type": "AWS::DynamoDB::Table",
            "Properties": {
                "AttributeDefinitions": [
                    {
                        "AttributeName": "id",
                        "AttributeType": "S"
                    }
                ],
                "KeySchema": [
                    {
                        "AttributeName": "id",
                        "KeyType": "HASH"
                    }
                ],
                "ProvisionedThroughput": {
                    "ReadCapacityUnits": 1,
                    "WriteCapacityUnits": 1
                }
            }
        },
        "JavaLambdaRole": {
            "Type": "AWS::IAM::Role",
            "Properties": {
                "AssumeRolePolicyDocument": {
                    "Version": "2012-10-17",		 	 	 
                    "Statement": [
                        {
                            "Effect": "Allow",
                            "Principal": {
                                "Service": "lambda.amazonaws.com"
                            },
                            "Action": "sts:AssumeRole"
                        }
                    ]
                },
                "ManagedPolicyArns": [
                    "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
                ],
                "Policies": [
                    {
                        "PolicyName": "JavaLambdaAccess",
                        "PolicyDocument": {
                            "Version": "2012-10-17",		 	 	 
                            "Statement": [
                                {
                                    "Effect": "Allow",
                                    "Action": [
                                        "dynamodb:DescribeTable",
                                        "dynamodb:BatchWriteItem"
                                    ],
                                    "Resource": {
                                        "Fn::Sub": "arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${JavaLambdaOutputTable}"
                                    }
                                },
                                {
                                    "Effect": "Allow",
                                    "Action": [
                                        "dynamodb:PutItem"
                                    ],
                                    "Resource": {
                                        "Fn::Sub": "arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${JavaLambdaOutputTable}*"
                                    }
                                },
                                {
                                    "Effect": "Allow",
                                    "Action": [
                                        "kinesis:GetRecords",
                                        "kinesis:GetShardIterator",
                                        "kinesis:DescribeStream",
                                        "kinesis:ListStreams"
                                    ],
                                    "Resource": {
                                        "Fn::Sub": "arn:aws:kinesis:${AWS::Region}:${AWS::AccountId}:stream/${InputStream}"
                                    }
                                }
                            ]
                        }
                    }
                ]
            }
        },
        "JavaLambdaFunction": {
            "Type": "AWS::Lambda::Function",
            "Properties": {
                "Description": "Java consumer",
                "Runtime": "java8",
                "MemorySize": 512,
                "Timeout": 90,
                "Role": {
                    "Fn::GetAtt": [
                        "JavaLambdaRole",
                        "Arn"
                    ]
                },
                "Handler": "com.amazonaws.crypto.examples.kinesisdatakeycaching.LambdaDecryptAndWrite::handleRequest",
                "Code": {
                    "S3Bucket": {
                        "Ref": "SourceCodeBucket"
                    },
                    "S3Key": {
                        "Ref": "JavaLambdaS3Key"
                    },
                    "S3ObjectVersion": {
                        "Ref": "JavaLambdaObjectVersionId"
                    }
                },
                "Environment": {
                    "Variables": {
                        "TABLE_NAME": {
                            "Ref": "JavaLambdaOutputTable"
                        },
                        "CMK_ARN": {
                            "Fn::GetAtt": [
                                "RegionKinesisCMK",
                                "Arn"
                            ]
                        }
                    }
                }
            }
        },
        "JavaLambdaSourceMapping": {
            "Type": "AWS::Lambda::EventSourceMapping",
            "Properties": {
                "BatchSize": 1,
                "Enabled": true,
                "EventSourceArn": {
                    "Fn::Sub": "arn:aws:kinesis:${AWS::Region}:${AWS::AccountId}:stream/${InputStream}"
                },
                "FunctionName": {
                    "Ref": "JavaLambdaFunction"
                },
                "StartingPosition": "TRIM_HORIZON"
            }
        },
        "RegionKinesisCMK": {
            "Type": "AWS::KMS::Key",
            "Properties": {
                "Description": "Used to encrypt data passing through Kinesis Stream in this region",
                "Enabled": true,
                "KeyPolicy": {
                    "Version": "2012-10-17",		 	 	 
                    "Statement": [
                        {
                            "Effect": "Allow",
                            "Principal": {
                                "AWS": {
                                    "Fn::Sub": "arn:aws:iam::${AWS::AccountId}:root"
                                }
                            },
                            "Action": [
                                "kms:Encrypt",
                                "kms:GenerateDataKey",
                                "kms:CreateAlias",
                                "kms:DeleteAlias",
                                "kms:DescribeKey",
                                "kms:DisableKey",
                                "kms:EnableKey",
                                "kms:PutKeyPolicy",
                                "kms:ScheduleKeyDeletion",
                                "kms:UpdateAlias",
                                "kms:UpdateKeyDescription"
                            ],
                            "Resource": "*"
                        },
                        {
                            "Effect": "Allow",
                            "Principal": {
                                "AWS": [
                                    {
                                        "Fn::GetAtt": [
                                            "PythonLambdaRole",
                                            "Arn"
                                        ]
                                    },
                                    {
                                        "Fn::GetAtt": [
                                            "JavaLambdaRole",
                                            "Arn"
                                        ]
                                    }
                                ]
                            },
                            "Action": "kms:Decrypt",
                            "Resource": "*"
                        }
                    ]
                }
            }
        },
        "RegionKinesisCMKAlias": {
            "Type": "AWS::KMS::Alias",
            "Properties": {
                "AliasName": {
                    "Fn::Sub": "alias/${KeyAliasSuffix}"
                },
                "TargetKeyId": {
                    "Ref": "RegionKinesisCMK"
                }
            }
        }
    }
}
```

------
#### [ YAML ]

```
Parameters:
    SourceCodeBucket:
        Type: String
        Description: S3 bucket containing Lambda source code zip files
    PythonLambdaS3Key:
        Type: String
        Description: S3 key containing Python Lambda source code zip file
    PythonLambdaObjectVersionId:
        Type: String
        Description: S3 version id for S3 key containing Python Lambda source code zip file
    JavaLambdaS3Key:
        Type: String
        Description: S3 key containing Python Lambda source code zip file
    JavaLambdaObjectVersionId:
        Type: String
        Description: S3 version id for S3 key containing Python Lambda source code zip file
    KeyAliasSuffix:
        Type: String
        Description: 'Suffix to use for KMS CMK Alias (ie: alias/<KeyAliasSuffix>)'
    StreamName:
        Type: String
        Description: Name to use for Kinesis Stream
Resources:
    InputStream:
        Type: AWS::Kinesis::Stream
        Properties:
            Name: !Ref StreamName
            ShardCount: 2
    PythonLambdaOutputTable:
        Type: AWS::DynamoDB::Table
        Properties:
            AttributeDefinitions:
                -
                    AttributeName: id
                    AttributeType: S
            KeySchema:
                -
                    AttributeName: id
                    KeyType: HASH
            ProvisionedThroughput:
                ReadCapacityUnits: 1
                WriteCapacityUnits: 1
    PythonLambdaRole:
        Type: AWS::IAM::Role
        Properties:
            AssumeRolePolicyDocument:
                Version: 2012-10-17
                Statement:
                    -
                        Effect: Allow
                        Principal:
                            Service: lambda.amazonaws.com
                        Action: sts:AssumeRole
            ManagedPolicyArns:
                - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
            Policies:
                -
                    PolicyName: PythonLambdaAccess
                    PolicyDocument:
                        Version: 2012-10-17
                        Statement:
                            -
                                Effect: Allow
                                Action:
                                    - dynamodb:DescribeTable
                                    - dynamodb:BatchWriteItem
                                Resource: !Sub arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${PythonLambdaOutputTable}
                            -
                                Effect: Allow
                                Action:
                                    - dynamodb:PutItem
                                Resource: !Sub arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${PythonLambdaOutputTable}*
                            -
                                Effect: Allow
                                Action:
                                    - kinesis:GetRecords
                                    - kinesis:GetShardIterator
                                    - kinesis:DescribeStream
                                    - kinesis:ListStreams
                                Resource: !Sub arn:aws:kinesis:${AWS::Region}:${AWS::AccountId}:stream/${InputStream}
    PythonLambdaFunction:
        Type: AWS::Lambda::Function
        Properties:
            Description: Python consumer
            Runtime: python2.7
            MemorySize: 512
            Timeout: 90
            Role: !GetAtt PythonLambdaRole.Arn
            Handler: aws_crypto_examples.kinesis_datakey_caching.consumer.lambda_handler
            Code:
                S3Bucket: !Ref SourceCodeBucket
                S3Key: !Ref PythonLambdaS3Key
                S3ObjectVersion: !Ref PythonLambdaObjectVersionId
            Environment:
                Variables:
                    TABLE_NAME: !Ref PythonLambdaOutputTable
    PythonLambdaSourceMapping:
        Type: AWS::Lambda::EventSourceMapping
        Properties:
            BatchSize: 1
            Enabled: true
            EventSourceArn: !Sub arn:aws:kinesis:${AWS::Region}:${AWS::AccountId}:stream/${InputStream}
            FunctionName: !Ref PythonLambdaFunction
            StartingPosition: TRIM_HORIZON
    JavaLambdaOutputTable:
        Type: AWS::DynamoDB::Table
        Properties:
            AttributeDefinitions:
                -
                    AttributeName: id
                    AttributeType: S
            KeySchema:
                -
                    AttributeName: id
                    KeyType: HASH
            ProvisionedThroughput:
                ReadCapacityUnits: 1
                WriteCapacityUnits: 1
    JavaLambdaRole:
        Type: AWS::IAM::Role
        Properties:
            AssumeRolePolicyDocument:
                Version: 2012-10-17
                Statement:
                    -
                        Effect: Allow
                        Principal:
                            Service: lambda.amazonaws.com
                        Action: sts:AssumeRole
            ManagedPolicyArns:
                - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
            Policies:
                -
                    PolicyName: JavaLambdaAccess
                    PolicyDocument:
                        Version: 2012-10-17
                        Statement:
                            -
                                Effect: Allow
                                Action:
                                    - dynamodb:DescribeTable
                                    - dynamodb:BatchWriteItem
                                Resource: !Sub arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${JavaLambdaOutputTable}
                            -
                                Effect: Allow
                                Action:
                                    - dynamodb:PutItem
                                Resource: !Sub arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${JavaLambdaOutputTable}*
                            -
                                Effect: Allow
                                Action:
                                    - kinesis:GetRecords
                                    - kinesis:GetShardIterator
                                    - kinesis:DescribeStream
                                    - kinesis:ListStreams
                                Resource: !Sub arn:aws:kinesis:${AWS::Region}:${AWS::AccountId}:stream/${InputStream}
    JavaLambdaFunction:
        Type: AWS::Lambda::Function
        Properties:
            Description: Java consumer
            Runtime: java8
            MemorySize: 512
            Timeout: 90
            Role: !GetAtt JavaLambdaRole.Arn
            Handler: com.amazonaws.crypto.examples.kinesisdatakeycaching.LambdaDecryptAndWrite::handleRequest
            Code:
                S3Bucket: !Ref SourceCodeBucket
                S3Key: !Ref JavaLambdaS3Key
                S3ObjectVersion: !Ref JavaLambdaObjectVersionId
            Environment:
                Variables:
                    TABLE_NAME: !Ref JavaLambdaOutputTable
                    CMK_ARN: !GetAtt RegionKinesisCMK.Arn
    JavaLambdaSourceMapping:
        Type: AWS::Lambda::EventSourceMapping
        Properties:
            BatchSize: 1
            Enabled: true
            EventSourceArn: !Sub arn:aws:kinesis:${AWS::Region}:${AWS::AccountId}:stream/${InputStream}
            FunctionName: !Ref JavaLambdaFunction
            StartingPosition: TRIM_HORIZON
    RegionKinesisCMK:
        Type: AWS::KMS::Key
        Properties:
            Description: Used to encrypt data passing through Kinesis Stream in this region
            Enabled: true
            KeyPolicy:
                Version: 2012-10-17
                Statement:
                    -
                        Effect: Allow
                        Principal:
                            AWS: !Sub arn:aws:iam::${AWS::AccountId}:root
                        Action:
                            # Data plane actions
                            - kms:Encrypt
                            - kms:GenerateDataKey
                            # Control plane actions
                            - kms:CreateAlias
                            - kms:DeleteAlias
                            - kms:DescribeKey
                            - kms:DisableKey
                            - kms:EnableKey
                            - kms:PutKeyPolicy
                            - kms:ScheduleKeyDeletion
                            - kms:UpdateAlias
                            - kms:UpdateKeyDescription
                        Resource: '*'
                    -
                        Effect: Allow
                        Principal:
                            AWS:
                                - !GetAtt PythonLambdaRole.Arn
                                - !GetAtt JavaLambdaRole.Arn
                        Action: kms:Decrypt
                        Resource: '*'
    RegionKinesisCMKAlias:
        Type: AWS::KMS::Alias
        Properties:
            AliasName: !Sub alias/${KeyAliasSuffix}
            TargetKeyId: !Ref RegionKinesisCMK
```

------