View a markdown version of this page

AWS KMS Llaveros jerárquicos - AWS Encryption SDK

Las traducciones son generadas a través de traducción automática. En caso de conflicto entre la traducción y la version original de inglés, prevalecerá la version en inglés.

AWS KMS Llaveros jerárquicos

Con el conjunto de claves AWS KMS jerárquicas, puede proteger su material criptográfico con una clave KMS de cifrado simétrico sin tener que llamar AWS KMS cada vez que cifra o descifra datos. Es una buena opción para las aplicaciones que necesitan reducir al mínimo las llamadas a determinados materiales criptográficos y para AWS KMS las aplicaciones que pueden reutilizar algunos materiales criptográficos sin infringir sus requisitos de seguridad.

El conjunto de claves jerárquicas es una solución de almacenamiento en caché de materiales criptográficos que reduce el número de AWS KMS llamadas mediante el uso de claves de rama AWS KMS protegidas que permanecen en una tabla de Amazon DynamoDB y, a continuación, el almacenamiento local en caché de las claves de rama utilizadas en las operaciones de cifrado y descifrado. La tabla de DynamoDB sirve como almacén de claves que administra y protege las claves de las sucursales. Almacena la clave de rama activa y todas las versiones anteriores de la clave de rama. La clave de rama activa es la versión más reciente de la clave de rama. El conjunto de claves jerárquicas utiliza una clave de datos única para cifrar cada mensaje y cifra cada clave de cifrado de datos para cada solicitud de cifrado y cifra cada clave de cifrado de datos con una clave de encapsulado única derivada de la clave de sucursal activa. El conjunto de claves jerárquico depende de la jerarquía establecida entre las claves de ramificación activas y las claves de encapsulamiento derivadas.

El conjunto de claves jerárquico suele utilizar cada versión de clave de rama para satisfacer múltiples solicitudes. Sin embargo, usted controla el grado en que se reutilizan las claves de rama activas y determina la frecuencia con la que se gira la clave de rama activa. La versión activa de la clave de rama permanece activa hasta que la gire. Las versiones anteriores de la clave de rama activa no se utilizarán para realizar operaciones de cifrado, pero sí se pueden consultar y utilizar en las operaciones de descifrado.

Al crear una instancia del conjunto de claves jerárquico, se crea una caché local. Se especifica un límite de caché que define el tiempo máximo durante el que los materiales de las claves de ramificación se almacenan en la caché local antes de que caduquen y se expulsen de la caché. El conjunto de claves jerárquico realiza una sola AWS KMS llamada para descifrar la clave de sucursal y reunir los materiales de la clave de sucursal la primera vez que se especifica a en una operación. branch-key-id A continuación, los materiales de la clave de rama se almacenan en la memoria caché local y se reutilizan para todas las operaciones de cifrado y descifrado que la branch-key-id especifique hasta que caduque el límite de la memoria caché. El almacenamiento del material de las claves de la sucursal en la memoria caché local reduce las llamadas. AWS KMS Por ejemplo, considere un límite de caché de 15 minutos. Si realizas 10 000 operaciones de cifrado dentro de ese límite de caché, el conjunto de AWS KMS claves tradicional necesitaría realizar 10 000 AWS KMS llamadas para cumplir con las 10 000 operaciones de cifrado. Si tiene una activabranch-key-id, el conjunto de claves jerárquicas solo necesita realizar una AWS KMS llamada para realizar 10 000 operaciones de cifrado.

La memoria caché local separa los materiales de cifrado de los de descifrado. Los materiales de cifrado se ensamblan a partir de la clave de sucursal activa y se reutilizan para todas las operaciones de cifrado hasta que caduque el límite de la caché. Los materiales de descifrado se ensamblan a partir del identificador y la versión de la clave de sucursal identificados en los metadatos del campo cifrado, y se reutilizan para todas las operaciones de descifrado relacionadas con el identificador y la versión de la clave de sucursal hasta que caduque el límite de la caché. La caché local puede almacenar varias versiones de la misma clave de sucursal a la vez. Cuando la caché local está configurada para usar unabranch key ID supplier, también puede almacenar materiales de claves de sucursal de varias claves de sucursal activas a la vez.

nota

Todas las menciones del conjunto de claves jerárquicas en la página AWS Encryption SDK hacen referencia al conjunto de claves AWS KMS jerárquicas.

Compatibilidad con lenguajes de programación

El conjunto de claves jerárquico es compatible con los siguientes lenguajes y versiones de programación:

  • Versión 3. x del SDK de cifrado de AWS para Java

  • Versión 4. x y versiones posteriores del AWS Encryption SDK para.NET

  • Versión 4. x de SDK de cifrado de AWS para Python, cuando se usa con la dependencia MPL opcional.

  • Versión 1. x del AWS Encryption SDK para Rust

  • Versión 0.1. x o posterior del AWS Encryption SDK for Go

  • Versión 4.1. x y versiones posteriores del SDK de cifrado de AWS para JavaScript for JavaScript Node.js.

    • El conjunto de claves AWS KMS jerárquico no es compatible con el navegador SDK de cifrado de AWS para JavaScript for JavaScript . Para conocer el estado actual y las limitaciones, consulte el repositorio https://github.com/aws/aws-encryption-sdk-javascript/ aws-encryption-sdk-javascript en. GitHub

Funcionamiento

Los siguientes tutoriales describen cómo el conjunto de claves jerárquico reúne los materiales de cifrado y descifrado, y las diferentes llamadas que realiza el conjunto de claves para las operaciones de cifrado y descifrado. Para obtener detalles técnicos sobre los procesos de derivación de claves de ajuste y cifrado de claves de datos de texto no cifrado, consulte Detalles técnicos del conjunto de claves jerárquico de AWS KMS.

Cifra y firma

El siguiente tutorial describe cómo el conjunto de claves jerárquico reúne los materiales de cifrado y obtiene una clave de encapsulamiento única.

  1. El método de cifrado solicita materiales de cifrado al conjunto de claves jerárquico. El conjunto de claves genera una clave de datos de texto no cifrado y, a continuación, comprueba si hay materiales de derivación válidos en la memoria caché local para generar la clave de encapsulamiento. Si hay materiales de claves de sucursal válidos, el conjunto de claves continúa con el paso 4.

  2. Si no hay materiales de clave de bifurcación válidos, el conjunto de claves jerárquico busca en el almacén de claves la clave de bifurcación activa.

    1. El almacén de claves llama AWS KMS para descifrar la clave de bifurcación activa y devuelve la clave de bifurcación activa en texto plano. Los datos que identifican la clave de rama activa se serializan para proporcionar datos autenticados adicionales (AAD) en la llamada de descifrado a AWS KMS.

    2. El almacén de claves devuelve la clave de sucursal en texto plano y los datos que la identifican, como la versión de la clave de sucursal.

  3. El conjunto de claves jerárquico reúne los materiales de las claves de rama (las versiones de las claves de rama y las claves de rama en texto no cifrado) y guarda una copia de los mismos en la memoria caché local.

  4. El conjunto de claves jerárquico obtiene una clave de ajuste única de la clave de rama de texto simple y de una sal aleatoria de 16 bytes. Utiliza la clave de encapsulamiento derivada para cifrar una copia de la clave de datos de texto no cifrado.

El método de cifrado utiliza los materiales de cifrado para cifrar los datos. Para obtener más información, consulta Cómo se AWS Encryption SDK cifran los datos.

Descifrar y verificar

El siguiente tutorial describe cómo el conjunto de claves jerárquico reúne los materiales de descifrado y descifra la clave de datos cifrados.

  1. El método de descifrado identifica la clave de datos cifrados del mensaje cifrado y la pasa al conjunto de claves jerárquico.

  2. El conjunto de claves jerárquico deserializa los datos que identifican la clave de datos cifrada, incluida la versión de la clave de rama, la sal de 16 bytes y otra información que describe cómo se cifró la clave de datos.

    Para obtener más información, consulte AWS KMS Detalles técnicos del conjunto de claves jerárquicas.

  3. El conjunto de claves jerárquico comprueba si hay materiales de clave de rama válidos en la caché local que coincidan con la versión de clave de rama identificada en el paso 2. Si hay materiales de clave de rama válidos, el conjunto de claves continúa con el paso 6.

  4. Si no hay ningún material de clave de sucursal válido, el conjunto de claves jerárquico busca en el almacén de claves la clave de sucursal que coincida con la versión de la clave de sucursal identificada en el paso 2.

    1. El almacén de claves llama AWS KMS para descifrar la clave de bifurcación y devuelve la clave de bifurcación activa en texto plano. Los datos que identifican la clave de rama activa se serializan para proporcionar datos autenticados adicionales (AAD) en la llamada de descifrado a AWS KMS.

    2. El almacén de claves devuelve la clave de sucursal en texto plano y los datos que la identifican, como la versión de la clave de sucursal.

  5. El conjunto de claves jerárquico reúne los materiales de las claves de rama (las versiones de las claves de rama y las claves de rama en texto no cifrado) y guarda una copia de los mismos en la memoria caché local.

  6. El conjunto de claves jerárquico utiliza los materiales de clave de rama ensamblados y la sal de 16 bytes identificada en el paso 2 para reproducir la clave de encapsulamiento única que cifró la clave de datos.

  7. El conjunto de claves jerárquico utiliza la clave de encapsulamiento para descifrar la clave de datos y devuelve la clave de datos en texto no cifrado.

El método de descifrado utiliza los materiales de descifrado y la clave de datos en texto no cifrado para descifrar el mensaje cifrado. Para obtener más información, consulta Cómo se AWS Encryption SDK descifra un mensaje cifrado.

Requisitos previos

Antes de crear y utilizar un conjunto de claves jerárquicas, asegúrese de que se cumplen los siguientes requisitos previos.

Permisos necesarios

AWS Encryption SDK No requiere una Cuenta de AWS y no depende de ninguna Servicio de AWS. Sin embargo, para usar un conjunto de claves jerárquicas, necesitas uno Cuenta de AWS y los siguientes permisos mínimos sobre los AWS KMS key cifrados simétricos de tu almacén de claves.

Los permisos de Amazon DynamoDB necesarios en la tabla de almacenamiento de claves

Los principales que interactúan con su almacén de claves también necesitan permisos en la tabla de DynamoDB. El conjunto de permisos depende del rol.

Usuario del almacén de claves

Un usuario del almacén de claves es el principal que utiliza el conjunto de claves jerárquicas para cifrar y descifrar los datos. Un usuario del almacén de claves necesita dynamodb: GetItem en la tabla del almacén de claves.

Administrador del almacén de claves

El administrador del almacén de claves es el responsable que crea y rota las claves de las sucursales. Un administrador del almacén de claves necesita los siguientes permisos en la tabla del almacén de claves:

  • Para leer: dynamodb: GetItem y dynamodb:. ConditionCheckItem

  • Para escrituras transaccionales: dynamodb: y dynamodb:. ConditionCheckItem PutItem El almacén de claves del conjunto de claves jerárquico realiza las escrituras TransactWriteItems; puede establecer una condición para los permisos de escritura de esa operación. dynamodb:EnclosingOperation

Para obtener más información sobre cómo controlar el acceso a las claves de la sucursal y al almacén de claves, consulte. Implementación de permisos de privilegio mínimo

Elige una caché

El conjunto de claves jerárquicas reduce el número de llamadas al AWS KMS almacenar en caché local el material de las claves de sucursal utilizado en las operaciones de cifrado y descifrado. Antes de crear tu conjunto de claves jerárquicas, debes decidir qué tipo de caché quieres usar. Puedes usar la caché predeterminada o personalizarla para que se adapte mejor a tus necesidades.

El conjunto de claves jerárquicas admite los siguientes tipos de caché:

importante

Todos los tipos de caché compatibles están diseñados para soportar entornos con subprocesos múltiples.

Sin embargo, cuando se usa con SDK de cifrado de AWS para Python, el conjunto de claves jerárquicas no admite entornos con subprocesos múltiples. Para obtener más información, consulte el README.rst archivo Python del repositorio aws-cryptographic-material-providers-library en. https://github.com/aws/aws-cryptographic-material-providers-library/tree/main GitHub

Caché predeterminada

La mayoría de usuarios no necesitará modificar sus requisitos de subprocesamiento. La caché predeterminada está diseñada para admitir entornos con muchos subprocesos múltiples. Cuando caduca una entrada de materiales clave de rama, la caché predeterminada evita que varios subprocesos AWS KMS llamen al notificar a un hilo que la entrada de materiales clave de la sucursal caducará con 10 segundos de antelación. Esto garantiza que solo un subproceso envíe una solicitud AWS KMS para actualizar la caché.

La caché predeterminada y la StormTracking caché admiten el mismo modelo de subprocesamiento, pero solo es necesario especificar la capacidad de entrada para usar la caché predeterminada. Para personalizaciones de caché más detalladas, utilice el. StormTracking caché

A menos que desee personalizar el número de entradas de materiales clave de la rama que se pueden almacenar en la caché local, no es necesario especificar un tipo de caché al crear el conjunto de claves jerárquicas. Si no especificas un tipo de caché, el conjunto de claves jerárquicas utiliza el tipo de caché predeterminado y establece la capacidad de entrada en 1000.

Para personalizar la caché predeterminada, especifique los valores siguientes:

  • Capacidad de entrada: limita el número de entradas de materiales clave de rama que se pueden almacenar en la caché local.

Java
.cache(CacheType.builder() .Default(DefaultCache.builder() .entryCapacity(100) .build())
C# / .NET
CacheType defaultCache = new CacheType { Default = new DefaultCache{EntryCapacity = 100} };
Python
default_cache = CacheTypeDefault( value=DefaultCache( entry_capacity=100 ) )
Rust
let cache: CacheType = CacheType::Default( DefaultCache::builder() .entry_capacity(100) .build()?, );
Go
cache := mpltypes.CacheTypeMemberDefault{ Value: mpltypes.DefaultCache{ EntryCapacity: 100, }, }

MultiThreaded caché

La MultiThreaded caché se puede usar de forma segura en entornos con subprocesos múltiples, pero no proporciona ninguna funcionalidad para minimizar AWS KMS las llamadas a Amazon DynamoDB. Como resultado, cuando una entrada de materiales clave de rama caduque, se notificará a todos los subprocesos al mismo tiempo. Esto puede provocar varias AWS KMS llamadas para actualizar la caché.

Para usar la MultiThreaded caché, especifique los valores siguientes:

  • Capacidad de entrada: limita el número de entradas de materiales clave de rama que se pueden almacenar en la caché local.

  • Tamaño de la cola de poda de entrada: define el número de entradas que se deben podar si se alcanza la capacidad de entrada.

Java
.cache(CacheType.builder() .MultiThreaded(MultiThreadedCache.builder() .entryCapacity(100) .entryPruningTailSize(1) .build())
C# / .NET
CacheType multithreadedCache = new CacheType { MultiThreaded = new MultiThreadedCache { EntryCapacity = 100, EntryPruningTailSize = 1 } };
Python
multithreaded_cache = CacheTypeMultiThreaded( value=MultiThreadedCache( entry_capacity=100, entry_pruning_tail_size=1 ) )
Rust
CacheType::MultiThreaded( MultiThreadedCache::builder() .entry_capacity(100) .entry_pruning_tail_size(1) .build()?)
Go
var entryPruningTailSize int32 = 1 cache := mpltypes.CacheTypeMemberMultiThreaded{ Value: mpltypes.MultiThreadedCache{ EntryCapacity: 100, EntryPruningTailSize: &entryPruningTailSize, }, }

StormTracking caché

La StormTracking memoria caché está diseñada para soportar entornos con muchos subprocesos múltiples. Cuando una entrada de materiales clave de sucursal caduca, la StormTracking caché evita que varios subprocesos llamen AWS KMS al notificar a un subproceso que la entrada de materiales clave de sucursal va a caducar por adelantado. Esto garantiza que solo un subproceso envíe una solicitud AWS KMS para actualizar la caché. Para obtener más información, consulte Storm Tracking Cryptographic Materials Cache en el repositorio GitHub aws-encryption-sdk-specification.

Para usar la caché, especifique los valores siguientes StormTracking :

  • Capacidad de entrada: limita el número de entradas de materiales clave de rama que se pueden almacenar en la caché local.

    Valor predeterminado: 1000 entradas

  • Tamaño de la cola de poda de entrada: define el número de entradas de materiales clave para la rama que se deben podar a la vez.

    Valor predeterminado: 1 entrada

  • Período de gracia: define el número de segundos antes de la caducidad durante los que se intenta actualizar los materiales clave de la rama.

    Valor predeterminado: 10 segundos

  • Intervalo de gracia: define el número de segundos entre los intentos de actualizar los materiales clave de la rama.

    Valor predeterminado: 1 segundo

  • Amplificador: define el número de intentos simultáneos que se pueden realizar para actualizar los materiales clave de la rama.

    Valor predeterminado: 20 intentos

  • En tiempo de vuelo hasta la vida útil (TTL): define el número de segundos hasta que se agota el tiempo de espera para intentar actualizar los materiales clave de la rama. Cada vez que la caché devuelve NoSuchEntry en respuesta a un GetCacheEntry, se considera que esa clave de rama está en tránsito hasta que se escribe la misma clave con una entrada PutCache.

    Valor predeterminado: 10 segundos

  • Suspensión: define la cantidad de milisegundos que un subproceso debe permanecer en reposo si fanOut se supera.

    Valor predeterminado: 20 milisegundos

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

Caché compartida

De forma predeterminada, el conjunto de claves jerárquico crea una nueva memoria caché local cada vez que se crea una instancia del conjunto de claves. Sin embargo, la caché compartida puede ayudar a conservar la memoria al permitirte compartir una caché entre varios conjuntos de claves jerárquicos. En lugar de crear una nueva caché de materiales criptográficos para cada conjunto de claves jerárquicas que instancie, la caché compartida solo almacena una caché en la memoria, que pueden utilizar todos los conjuntos de claves jerárquicas que hacen referencia a ella. La caché compartida ayuda a optimizar el uso de la memoria al evitar la duplicación de materiales criptográficos en los conjuntos de claves. En cambio, los conjuntos de claves jerárquicos pueden acceder a la misma memoria caché subyacente, lo que reduce el consumo total de memoria.

Cuando creas tu caché compartida, sigues definiendo el tipo de caché. Puede especificar un tipo de caché Caché predeterminadaMultiThreaded caché, o StormTracking caché sustituirlo por cualquier caché personalizada compatible.

Particiones

Varios conjuntos de claves jerárquicos pueden usar una sola caché compartida. Al crear un conjunto de claves jerárquicas con una caché compartida, puede definir un ID de partición opcional. El ID de partición distingue qué conjunto de claves jerárquicas se está escribiendo en la caché. Si dos conjuntos de claves jerárquicos hacen referencia al mismo identificador de partición y al identificador de clave de ramalogical key store name, los dos conjuntos de claves compartirán las mismas entradas de caché en la memoria caché. Si crea dos conjuntos de claves jerárquicos con la misma caché compartida, pero con diferentes identificadores de partición, cada conjunto de claves solo accederá a las entradas de la caché desde su propia partición designada dentro de la caché compartida. Las particiones actúan como divisiones lógicas dentro de la caché compartida, lo que permite que cada conjunto de claves jerárquicas funcione de forma independiente en su propia partición designada, sin interferir con los datos almacenados en la otra partición.

Si tiene la intención de reutilizar o compartir las entradas de la caché de una partición, debe definir su propio ID de partición. Cuando pasas el identificador de partición a tu conjunto de claves jerárquicas, este puede reutilizar las entradas de la caché que ya están presentes en la caché compartida, en lugar de tener que recuperar y volver a autorizar el material de las claves de la sucursal. Si no especificas un identificador de partición, cada vez que instancies el conjunto de claves jerárquico, se asigna automáticamente un identificador de partición único al conjunto de claves.

Los procedimientos siguientes muestran cómo crear una caché compartida con el tipo de caché predeterminado y pasarla a un conjunto de claves jerárquico.

  1. Cree una CryptographicMaterialsCache (CMC) mediante la biblioteca de proveedores de materiales (MPL).

    Java
    // Instantiate the MPL final MaterialProviders matProv = MaterialProviders.builder() .MaterialProvidersConfig(MaterialProvidersConfig.builder().build()) .build(); // Create a CacheType object for the Default cache final CacheType cache = CacheType.builder() .Default(DefaultCache.builder().entryCapacity(100).build()) .build(); // Create a CMC using the default cache final CreateCryptographicMaterialsCacheInput cryptographicMaterialsCacheInput = CreateCryptographicMaterialsCacheInput.builder() .cache(cache) .build(); final ICryptographicMaterialsCache sharedCryptographicMaterialsCache = matProv.CreateCryptographicMaterialsCache(cryptographicMaterialsCacheInput);
    C# / .NET
    // Instantiate the MPL var materialProviders = new MaterialProviders(new MaterialProvidersConfig()); // Create a CacheType object for the Default cache var cache = new CacheType { Default = new DefaultCache{EntryCapacity = 100} }; // Create a CMC using the default cache var cryptographicMaterialsCacheInput = new CreateCryptographicMaterialsCacheInput {Cache = cache}; var sharedCryptographicMaterialsCache = materialProviders.CreateCryptographicMaterialsCache(cryptographicMaterialsCacheInput);
    Python
    # Instantiate the MPL mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( config=MaterialProvidersConfig() ) # Create a CacheType object for the default cache cache: CacheType = CacheTypeDefault( value=DefaultCache( entry_capacity=100, ) ) # Create a CMC using the default cache cryptographic_materials_cache_input = CreateCryptographicMaterialsCacheInput( cache=cache, ) shared_cryptographic_materials_cache = mat_prov.create_cryptographic_materials_cache( cryptographic_materials_cache_input )
    Rust
    // Instantiate the MPL let mpl_config = MaterialProvidersConfig::builder().build()?; let mpl = mpl_client::Client::from_conf(mpl_config)?; // Create a CacheType object for the default cache let cache: CacheType = CacheType::Default( DefaultCache::builder() .entry_capacity(100) .build()?, ); // Create a CMC using the default cache let shared_cryptographic_materials_cache: CryptographicMaterialsCacheRef = mpl. create_cryptographic_materials_cache() .cache(cache) .send() .await?;
    Go
    import ( "context" mpl "aws/aws-cryptographic-material-providers-library/releases/go/mpl/awscryptographymaterialproviderssmithygenerated" mpltypes "aws/aws-cryptographic-material-providers-library/releases/go/mpl/awscryptographymaterialproviderssmithygeneratedtypes" ) // Instantiate the MPL matProv, err := mpl.NewClient(mpltypes.MaterialProvidersConfig{}) if err != nil { panic(err) } // Create a CacheType object for the default cache cache := mpltypes.CacheTypeMemberDefault{ Value: mpltypes.DefaultCache{ EntryCapacity: 100, }, } // Create a CMC using the default cache cmcCacheInput := mpltypes.CreateCryptographicMaterialsCacheInput{ Cache: &cache, } sharedCryptographicMaterialsCache, err := matProv.CreateCryptographicMaterialsCache(context.Background(), cmcCacheInput) if err != nil { panic(err) }
  2. Cree un CacheType objeto para la caché compartida.

    Pase el sharedCryptographicMaterialsCache que creó en el paso 1 al nuevo CacheType objeto.

    Java
    // Create a CacheType object for the sharedCryptographicMaterialsCache final CacheType sharedCache = CacheType.builder() .Shared(sharedCryptographicMaterialsCache) .build();
    C# / .NET
    // Create a CacheType object for the sharedCryptographicMaterialsCache var sharedCache = new CacheType { Shared = sharedCryptographicMaterialsCache };
    Python
    # Create a CacheType object for the shared_cryptographic_materials_cache shared_cache: CacheType = CacheTypeShared( value=shared_cryptographic_materials_cache )
    Rust
    // Create a CacheType object for the shared_cryptographic_materials_cache let shared_cache: CacheType = CacheType::Shared(shared_cryptographic_materials_cache);
    Go
    // Create a CacheType object for the shared_cryptographic_materials_cache shared_cache := mpltypes.CacheTypeMemberShared{sharedCryptographicMaterialsCache}
  3. Pase el sharedCache objeto del paso 2 a su conjunto de claves jerárquicas.

    Al crear un conjunto de claves jerárquicas con una caché compartida, si lo desea, puede definir una opción partitionID para compartir las entradas de la caché en varios conjuntos de claves jerárquicos. Si no especificas un identificador de partición, el conjunto de claves jerárquico asigna automáticamente al conjunto de claves un identificador de partición único.

    nota

    Sus conjuntos de claves jerárquicos compartirán las mismas entradas de caché en una caché compartida si crea dos o más conjuntos de claves que hagan referencia al mismo identificador de partición y al mismo identificador de clave de rama. logical key store name Si no quieres que varios conjuntos de claves compartan las mismas entradas de la caché, debes usar un identificador de partición único para cada conjunto de claves jerárquico.

    En el siguiente ejemplo, se crea un conjunto de claves jerárquico con un límite branch key ID supplier de caché de 600 segundos. Para obtener más información sobre los valores definidos en la siguiente configuración del conjunto de claves jerárquicas, consulte. Crear un conjunto de claves jerárquico

    Java
    // Create the Hierarchical keyring final CreateAwsKmsHierarchicalKeyringInput keyringInput = CreateAwsKmsHierarchicalKeyringInput.builder() .keyStore(keystore) .branchKeyIdSupplier(branchKeyIdSupplier) .ttlSeconds(600) .cache(sharedCache) .partitionID(partitionID) .build(); final IKeyring hierarchicalKeyring = matProv.CreateAwsKmsHierarchicalKeyring(keyringInput);
    C# / .NET
    // Create the Hierarchical keyring var createKeyringInput = new CreateAwsKmsHierarchicalKeyringInput { KeyStore = keystore, BranchKeyIdSupplier = branchKeyIdSupplier, Cache = sharedCache, TtlSeconds = 600, PartitionId = partitionID }; var keyring = materialProviders.CreateAwsKmsHierarchicalKeyring(createKeyringInput);
    Python
    # Create the Hierarchical keyring keyring_input: CreateAwsKmsHierarchicalKeyringInput = CreateAwsKmsHierarchicalKeyringInput( key_store=keystore, branch_key_id_supplier=branch_key_id_supplier, ttl_seconds=600, cache=shared_cache, partition_id=partition_id ) hierarchical_keyring: IKeyring = mat_prov.create_aws_kms_hierarchical_keyring( input=keyring_input )
    Rust
    // Create the Hierarchical keyring let keyring1 = mpl .create_aws_kms_hierarchical_keyring() .key_store(key_store1) .branch_key_id(branch_key_id.clone()) // CryptographicMaterialsCacheRef is an Rc (Reference Counted), so if you clone it to // pass it to different Hierarchical Keyrings, it will still point to the same // underlying cache, and increment the reference count accordingly. .cache(shared_cache.clone()) .ttl_seconds(600) .partition_id(partition_id.clone()) .send() .await?;
    Go
    // Create the Hierarchical keyring hkeyringInput := mpltypes.CreateAwsKmsHierarchicalKeyringInput{ KeyStore: keyStore1, BranchKeyId: &branchKeyId, TtlSeconds: 600, Cache: &shared_cache, PartitionId: &partitionId, } keyring, err := matProv.CreateAwsKmsHierarchicalKeyring(context.Background(), hkeyringInput) if err != nil { panic(err) }

Crear un conjunto de claves jerárquico

Para crear un conjunto de claves jerárquico, debe proporcionar los siguientes valores:

  • Un nombre de almacén de claves

    El nombre de la tabla de DynamoDB que usted o el administrador del almacén de claves crearon para que sirviera de almacén de claves.

  • Un tiempo de vida límite de la memoria caché (TTL)

    La cantidad de tiempo en segundos que se puede utilizar una entrada de material de clave de la memoria caché local antes de que caduque. El TTL del límite de caché determina la frecuencia con la que el cliente llama AWS KMS para autorizar el uso de las claves de sucursal. El valor debe ser mayor que cero. Una vez que caduque el TTL del límite de caché, la entrada nunca se publicará y se expulsará de la caché local.

  • Un identificador de clave de rama

    Puedes configurar de forma estática la branch-key-id que identifica una única clave de sucursal activa en tu almacén de claves o proporcionar un proveedor de ID de clave de sucursal.

    El proveedor del identificador de clave de sucursal utiliza los campos almacenados en el contexto de cifrado para determinar qué clave de sucursal es necesaria para descifrar un registro.

    Recomendamos encarecidamente utilizar un proveedor de ID de clave de sucursal para las bases de datos con varios inquilinos en las que cada inquilino tenga su propia clave de sucursal. Puedes usar el proveedor de las claves de sucursal para crear un nombre sencillo para las claves de tu sucursal, a fin de que sea más fácil reconocer la ID de clave de sucursal correcta para un inquilino específico. Por ejemplo, el nombre descriptivo le permite hacer referencia a una clave de rama como tenant1 en lugar deb3f61619-4d35-48ad-a275-050f87e15122.

    Para las operaciones de descifrado, puede configurar de forma estática un único conjunto de claves jerárquicas para restringir el descifrado a un único usuario, o puede utilizar el proveedor del identificador de clave de sucursal para identificar qué inquilino es responsable de descifrar un registro.

  • (Opcional) Una caché

    Si desea personalizar el tipo de caché o el número de entradas de materiales clave de rama que se pueden almacenar en la caché local, especifique el tipo de caché y la capacidad de entrada al inicializar el conjunto de claves.

    El conjunto de claves jerárquicas admite los siguientes tipos de caché: predeterminada MultiThreaded StormTracking, y compartida. Para obtener más información y ejemplos que demuestren cómo definir cada tipo de caché, consulte. Elige una caché

    Si no especifica una caché, el conjunto de claves jerárquico utiliza automáticamente el tipo de caché predeterminado y establece la capacidad de entrada en 1000.

  • (Opcional) Un identificador de partición

    Si especifica elCaché compartida, si lo desea, puede definir un ID de partición. El identificador de partición distingue qué conjunto de claves jerárquicas se está escribiendo en la caché. Si tiene la intención de reutilizar o compartir las entradas de la caché de una partición, debe definir su propio ID de partición. Puede especificar cualquier cadena para el identificador de partición. Si no especifica un identificador de partición, se asigna automáticamente un identificador de partición único al conjunto de claves en el momento de la creación.

    Para obtener más información, consulte Partitions.

    nota

    Sus conjuntos de claves jerárquicos compartirán las mismas entradas de caché en una caché compartida si crea dos o más conjuntos de claves que hagan referencia al mismo identificador de partición y al mismo identificador de clave de logical key store name rama. Si no quieres que varios conjuntos de claves compartan las mismas entradas de la caché, debes usar un identificador de partición único para cada conjunto de claves jerárquico.

  • (Opcional) Una lista de tokens de concesión

    Si controla el acceso a la clave KMS de su conjunto de claves jerárquico mediante concesiones, debe proporcionar todos los tokens de concesión necesarios al inicializar el conjunto de claves.

Los siguientes ejemplos muestran cómo crear un conjunto de claves jerárquicas con un identificador de clave de rama estática y un TTL Caché predeterminada límite de caché de 600 segundos.

Java
final MaterialProviders matProv = MaterialProviders.builder() .MaterialProvidersConfig(MaterialProvidersConfig.builder().build()) .build(); final CreateAwsKmsHierarchicalKeyringInput keyringInput = CreateAwsKmsHierarchicalKeyringInput.builder() .keyStore(branchKeyStoreName) .branchKeyId(branch-key-id) .ttlSeconds(600) .build(); final Keyring hierarchicalKeyring = matProv.CreateAwsKmsHierarchicalKeyring(keyringInput);
C# / .NET
var matProv = new MaterialProviders(new MaterialProvidersConfig()); var keyringInput = new CreateAwsKmsHierarchicalKeyringInput { KeyStore = keystore, BranchKeyId = branch-key-id, TtlSeconds = 600 }; var hierarchicalKeyring = matProv.CreateAwsKmsHierarchicalKeyring(keyringInput);
Python
mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( config=MaterialProvidersConfig() ) keyring_input: CreateAwsKmsHierarchicalKeyringInput = CreateAwsKmsHierarchicalKeyringInput( key_store=keystore, branch_key_id=branch_key_id, ttl_seconds=600 ) hierarchical_keyring: IKeyring = mat_prov.create_aws_kms_hierarchical_keyring( input=keyring_input )
Rust
let mpl_config = MaterialProvidersConfig::builder().build()?; let mpl = mpl_client::Client::from_conf(mpl_config)?; let hierarchical_keyring = mpl .create_aws_kms_hierarchical_keyring() .key_store(key_store.clone()) .branch_key_id(branch_key_id) .ttl_seconds(600) .send() .await?;
Go
matProv, err := mpl.NewClient(mpltypes.MaterialProvidersConfig{}) if err != nil { panic(err) } hkeyringInput := mpltypes.CreateAwsKmsHierarchicalKeyringInput{ KeyStore: keyStore, BranchKeyId: &branchKeyID, TtlSeconds: 600, } hKeyRing, err := matProv.CreateAwsKmsHierarchicalKeyring(context.Background(), hkeyringInput) if err != nil { panic(err) }

Los siguientes procedimientos muestran cómo crear un conjunto de claves jerárquico con un proveedor de ID de clave de sucursal.

  1. Cree un proveedor de ID de clave de sucursal

    En el siguiente ejemplo, se define un proveedor de ID de clave de sucursal que utiliza el contexto de cifrado en el momento de cifrar o descifrar para seleccionar el ID de clave de sucursal para cada inquilino. Para ver una implementación que funcione en cada idioma, consulte:

    Java
    // Define a branch key ID supplier that uses the encryption context to // select a branch key ID for each tenant. public class ExampleBranchKeyIdSupplier implements IBranchKeyIdSupplier { private static String branchKeyIdForTenantA; private static String branchKeyIdForTenantB; public ExampleBranchKeyIdSupplier(String tenant1Id, String tenant2Id) { this.branchKeyIdForTenantA = tenant1Id; this.branchKeyIdForTenantB = tenant2Id; } @Override public GetBranchKeyIdOutput GetBranchKeyId(GetBranchKeyIdInput input) { Map<String, String> encryptionContext = input.encryptionContext(); if (!encryptionContext.containsKey("tenant")) { throw new IllegalArgumentException( "EncryptionContext invalid, does not contain expected tenant key value pair."); } String tenantKeyId = encryptionContext.get("tenant"); String branchKeyId; if (tenantKeyId.equals("TenantA")) { branchKeyId = branchKeyIdForTenantA; } else if (tenantKeyId.equals("TenantB")) { branchKeyId = branchKeyIdForTenantB; } else { throw new IllegalArgumentException("Item does not contain valid tenant ID"); } return GetBranchKeyIdOutput.builder().branchKeyId(branchKeyId).build(); } } // Create the branch key ID supplier final IBranchKeyIdSupplier branchKeyIdSupplier = new ExampleBranchKeyIdSupplier( branch-key-ID-tenantA, branch-key-ID-tenantB);
    C# / .NET
    // Define a branch key ID supplier that uses the encryption context to // select a branch key ID for each tenant. public class ExampleBranchKeySupplier : BranchKeyIdSupplierBase { private string branchKeyTenantA; private string branchKeyTenantB; public ExampleBranchKeySupplier(string branchKeyTenantA, string branchKeyTenantB) { this.branchKeyTenantA = branchKeyTenantA; this.branchKeyTenantB = branchKeyTenantB; } // The encryption context is used to determine the Branch Key ID. protected override GetBranchKeyIdOutput _GetBranchKeyId(GetBranchKeyIdInput input) { Dictionary<string, string> encryptionContext = input.EncryptionContext; if (!encryptionContext.ContainsKey("tenant")) { throw new Exception("EncryptionContext invalid, does not contain expected tenant key value pair."); } string tenant = encryptionContext["tenant"]; if (tenant.Equals("TenantA")) { return new GetBranchKeyIdOutput { BranchKeyId = branchKeyTenantA }; } if (tenant.Equals("TenantB")) { return new GetBranchKeyIdOutput { BranchKeyId = branchKeyTenantB }; } throw new Exception("Item does not have a valid tenantID."); } } // Create the branch key ID supplier var branchKeyIdSupplier = new ExampleBranchKeySupplier( branch-key-ID-tenantA, branch-key-ID-tenantB);
    Python
    # Define a branch key ID supplier that uses the encryption context to # select a branch key ID for each tenant. class ExampleBranchKeyIdSupplier(IBranchKeyIdSupplier): branch_key_id_for_tenant_A: str branch_key_id_for_tenant_B: str def __init__(self, tenant_1_id, tenant_2_id): self.branch_key_id_for_tenant_A = tenant_1_id self.branch_key_id_for_tenant_B = tenant_2_id def get_branch_key_id( self, param: GetBranchKeyIdInput ) -> GetBranchKeyIdOutput: encryption_context = param.encryption_context if "tenant" not in encryption_context: raise ValueError("EncryptionContext invalid, does not contain expected tenant key value pair.") tenant_key_id = encryption_context.get("tenant") if tenant_key_id == "TenantA": branch_key_id = self.branch_key_id_for_tenant_A elif tenant_key_id == "TenantB": branch_key_id = self.branch_key_id_for_tenant_B else: raise ValueError(f"Item does not contain valid tenant ID: {tenant_key_id=}") return GetBranchKeyIdOutput(branch_key_id=branch_key_id) # Create the branch key ID supplier branch_key_id_supplier: IBranchKeyIdSupplier = ExampleBranchKeyIdSupplier( tenant_1_id=branch_key_id_a, tenant_2_id=branch_key_id_b, )
    Rust
    // Define a branch key ID supplier that uses the encryption context to // select a branch key ID for each tenant. pub struct ExampleBranchKeyIdSupplier { branch_key_id_for_tenant_a: String, branch_key_id_for_tenant_b: String, } impl ExampleBranchKeyIdSupplier { pub fn new(tenant_a_id: &str, tenant_b_id: &str) -> Self { Self { branch_key_id_for_tenant_a: tenant_a_id.to_string(), branch_key_id_for_tenant_b: tenant_b_id.to_string(), } } } // The encryption context is used to determine the Branch Key ID. impl BranchKeyIdSupplier for ExampleBranchKeyIdSupplier { fn get_branch_key_id(&self, input: GetBranchKeyIdInput) -> Result<GetBranchKeyIdOutput, Error> { let encryption_context: HashMap<String, String> = input.encryption_context.unwrap(); if !encryption_context.contains_key("tenant") { return Err(Error::AwsCryptographicMaterialProvidersException { message: "EncryptionContext invalid, does not contain expected tenant key value pair.".to_string(), }); } let tenant_key_id: &str = encryption_context["tenant"].as_str(); if tenant_key_id == "TenantA" { Ok(GetBranchKeyIdOutput::builder() .branch_key_id(self.branch_key_id_for_tenant_a.clone()) .build() .unwrap()) } else if tenant_key_id == "TenantB" { Ok(GetBranchKeyIdOutput::builder() .branch_key_id(self.branch_key_id_for_tenant_b.clone()) .build() .unwrap()) } else { Err(Error::AwsCryptographicMaterialProvidersException { message: "Item does not contain valid tenant ID.".to_string(), }) } } } // Create the branch key ID supplier let branch_key_id_supplier = ExampleBranchKeyIdSupplier::new( &branch_key_id_a, &branch_key_id_b, );
    Go
    // Define a branch key ID supplier that uses the encryption context to // select a branch key ID for each tenant. type branchKeySupplier struct { branchKeyA string branchKeyB string } // The encryption context is used to determine the Branch Key ID. func (b *branchKeySupplier) GetBranchKeyId(input mpltypes.GetBranchKeyIdInput) (*mpltypes.GetBranchKeyIdOutput, error) { ec := input.EncryptionContext if value, exists := ec["tenant"]; !exists || value == "" { return nil, fmt.Errorf("EncryptionContext invalid, does not contain expected tenant key value pair.") } branchKeyIdentifier := ec["tenant"] if branchKeyIdentifier == "TenantA" { return &mpltypes.GetBranchKeyIdOutput{BranchKeyId: b.branchKeyA}, nil } else if branchKeyIdentifier == "TenantB" { return &mpltypes.GetBranchKeyIdOutput{BranchKeyId: b.branchKeyB}, nil } else { return &mpltypes.GetBranchKeyIdOutput{}, fmt.Errorf("unknown branch key identifier") } } // Create the branch key ID supplier keySupplier := branchKeySupplier{branchKeyA: branchKeyA, branchKeyB: branchKeyB}
  2. Crear un conjunto de claves jerárquico

    En los siguientes ejemplos, se inicializa un conjunto de claves jerárquicas con el identificador de la clave de sucursal que el proveedor creó en el paso 1, un TLL máximo de 600 segundos y un tamaño máximo de caché de 1000.

    Java
    final MaterialProviders matProv = MaterialProviders.builder() .MaterialProvidersConfig(MaterialProvidersConfig.builder().build()) .build(); final CreateAwsKmsHierarchicalKeyringInput keyringInput = CreateAwsKmsHierarchicalKeyringInput.builder() .keyStore(keystore) .branchKeyIdSupplier(branchKeyIdSupplier) .ttlSeconds(600) .cache(CacheType.builder() //OPTIONAL .Default(DefaultCache.builder() .entryCapacity(100) .build()) .build(); final Keyring hierarchicalKeyring = matProv.CreateAwsKmsHierarchicalKeyring(keyringInput);
    C# / .NET
    var matProv = new MaterialProviders(new MaterialProvidersConfig()); var keyringInput = new CreateAwsKmsHierarchicalKeyringInput { KeyStore = keystore, BranchKeyIdSupplier = branchKeyIdSupplier, TtlSeconds = 600, Cache = new CacheType { Default = new DefaultCache { EntryCapacity = 100 } } }; var hierarchicalKeyring = matProv.CreateAwsKmsHierarchicalKeyring(keyringInput);
    Python
    mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders( config=MaterialProvidersConfig() ) keyring_input: CreateAwsKmsHierarchicalKeyringInput = CreateAwsKmsHierarchicalKeyringInput( key_store=keystore, branch_key_id_supplier=branch_key_id_supplier, ttl_seconds=600, cache=CacheTypeDefault( value=DefaultCache( entry_capacity=100 ) ), ) hierarchical_keyring: IKeyring = mat_prov.create_aws_kms_hierarchical_keyring( input=keyring_input )
    Rust
    let mpl_config = MaterialProvidersConfig::builder().build()?; let mpl = mpl_client::Client::from_conf(mpl_config)?; let hierarchical_keyring = mpl .create_aws_kms_hierarchical_keyring() .key_store(key_store.clone()) .branch_key_id_supplier(branch_key_id_supplier) .ttl_seconds(600) .send() .await?;
    Go
    hkeyringInput := mpltypes.CreateAwsKmsHierarchicalKeyringInput{ KeyStore: keyStore, BranchKeyIdSupplier: &keySupplier, TtlSeconds: 600, } hKeyRing, err := matProv.CreateAwsKmsHierarchicalKeyring(context.Background(), hkeyringInput) if err != nil { panic(err) }