View a markdown version of this page

AWS KMS Porte-clés hiérarchiques - AWS Encryption SDK

Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.

AWS KMS Porte-clés hiérarchiques

Grâce au trousseau de clés AWS KMS hiérarchique, vous pouvez protéger vos documents cryptographiques à l'aide d'une clé KMS à chiffrement symétrique sans avoir à appeler AWS KMS chaque fois que vous chiffrez ou déchiffrez des données. C'est un bon choix pour les applications qui ont besoin de minimiser les appels et pour AWS KMS les applications qui peuvent réutiliser certains éléments cryptographiques sans enfreindre leurs exigences de sécurité.

Le trousseau de clés hiérarchique est une solution de mise en cache des matériaux cryptographiques qui réduit le nombre d' AWS KMS appels en utilisant des clés de branche AWS KMS protégées conservées dans une table Amazon DynamoDB, puis en mettant en cache localement les matériaux des clés de branche utilisés dans les opérations de chiffrement et de déchiffrement. La table DynamoDB fait office de magasin de clés qui gère et protège les clés de branche. Il stocke la clé de branche active et toutes les versions précédentes de la clé de branche. La clé de branche active est la version de clé de branche la plus récente. Le trousseau de clés hiérarchique utilise une clé de données unique pour chiffrer chaque message et chiffre chaque clé de chiffrement des données pour chaque demande de chiffrement et chiffre chaque clé de chiffrement des données avec une clé d'encapsulation unique dérivée de la clé de branche active. Le trousseau de clés hiérarchique dépend de la hiérarchie établie entre les clés de branche actives et leurs clés d'encapsulation dérivées.

Le trousseau de clés hiérarchique utilise généralement chaque version de clé de branche pour répondre à plusieurs demandes. Mais vous pouvez contrôler la mesure dans laquelle les clés de branche actives sont réutilisées et vous déterminez la fréquence de rotation de la clé de branche active. La version active de la clé de branche reste active tant que vous ne la faites pas pivoter. Les versions précédentes de la clé de branche active ne seront pas utilisées pour effectuer des opérations de chiffrement, mais elles peuvent toujours être interrogées et utilisées pour les opérations de déchiffrement.

Lorsque vous instanciez le trousseau de clés hiérarchique, il crée un cache local. Vous spécifiez une limite de cache qui définit la durée maximale pendant laquelle les éléments des clés de branche sont stockés dans le cache local avant d'expirer et d'en être expulsés. Le trousseau de clés hiérarchique effectue un AWS KMS appel pour déchiffrer la clé de branche et assembler les éléments de la clé de branche la première fois que a branch-key-id est spécifié dans une opération. Les éléments des clés de branche sont ensuite stockés dans le cache local et réutilisés pour toutes les opérations de chiffrement et de déchiffrement qui le spécifient branch-key-id jusqu'à l'expiration de la limite de cache. Le stockage des informations relatives aux clés de branche dans le cache local réduit le nombre d' AWS KMS appels. Par exemple, considérez une limite de cache de 15 minutes. Si vous effectuez 10 000 opérations de chiffrement dans cette limite de cache, le trousseau de AWS KMS clés traditionnel devra effectuer 10 000 AWS KMS appels pour effectuer 10 000 opérations de chiffrement. Si vous en avez un actifbranch-key-id, le trousseau de clés hiérarchique n'a besoin que d'un seul AWS KMS appel pour effectuer 10 000 opérations de chiffrement.

Le cache local sépare le matériel de chiffrement du matériel de déchiffrement. Les matériaux de chiffrement sont assemblés à partir de la clé de branche active et réutilisés pour toutes les opérations de chiffrement jusqu'à l'expiration de la limite de cache. Les matériaux de déchiffrement sont assemblés à partir de l'ID de clé de branche et de la version identifiés dans les métadonnées du champ chiffré, et ils sont réutilisés pour toutes les opérations de déchiffrement liées à l'ID et à la version de la clé de branche jusqu'à expiration de la limite de cache. Le cache local peut stocker plusieurs versions de la même clé de branche à la fois. Lorsque le cache local est configuré pour utiliser unbranch key ID supplier, il peut également stocker des éléments de clé de branche provenant de plusieurs clés de branche actives à la fois.

Note

Toutes les mentions du porte-clés hiérarchique dans la AWS Encryption SDK référence au porte-clés AWS KMS hiérarchique.

Compatibilité des langages de programmation

Le trousseau de clés hiérarchique est pris en charge par les langages de programmation et les versions suivants :

  • La version 3. x du Kit SDK de chiffrement AWS pour Java

  • La version 4. x et versions ultérieures du AWS Encryption SDK pour .NET

  • La version 4. x du Kit SDK de chiffrement AWS pour Python, lorsqu'il est utilisé avec la dépendance MPL optionnelle.

  • Version 1. x du AWS Encryption SDK pour Rust

  • La version 0.1. x ou version ultérieure du AWS Encryption SDK for Go

  • La version 4.1. x et versions ultérieures du Kit SDK de chiffrement AWS pour JavaScript formulaire JavaScript Node.js.

    • Le trousseau de clés AWS KMS hiérarchique n'est pas pris en charge dans le JavaScript navigateur Kit SDK de chiffrement AWS pour JavaScript for. Pour connaître l'état actuel et les limites, consultez le référentiel https://github.com/aws/aws-encryption-sdk-javascript/ aws-encryption-sdk-javascript sur. GitHub

Comment ça marche

Les procédures pas à pas suivantes décrivent comment le trousseau de clés hiérarchique assemble le matériel de chiffrement et de déchiffrement, ainsi que les différents appels qu'il effectue pour les opérations de chiffrement et de déchiffrement. Pour plus de détails techniques sur les processus de dérivation des clés d'encapsulation et de chiffrement des clés de données en texte brut, voir Détails techniques des trousses de clés AWS KMS hiérarchiques.

Chiffrez et signez

La procédure pas à pas suivante décrit comment le trousseau de clés hiérarchique assemble les matériaux de chiffrement et en déduit une clé d'encapsulation unique.

  1. La méthode de cryptage demande au trousseau de clés hiérarchique les matériaux de chiffrement. Le trousseau de clés génère une clé de données en texte brut, puis vérifie s'il existe des branches valides dans le cache local pour générer la clé d'encapsulation. S'il existe des éléments de clé de branche valides, le trousseau passe à l'étape 4.

  2. S'il n'existe aucun matériel de clé de branche valide, le trousseau de clés hiérarchique interroge le magasin de clés pour la clé de branche active.

    1. Le magasin de clés appelle AWS KMS pour déchiffrer la clé de branche active et renvoie la clé de branche active en texte brut. Les données identifiant la clé de branche active sont sérialisées pour fournir des données authentifiées supplémentaires (AAD) dans l'appel de déchiffrement à. AWS KMS

    2. Le magasin de clés renvoie la clé de branche en texte brut et les données qui l'identifient, telles que la version de la clé de branche.

  3. Le trousseau de clés hiérarchique rassemble les éléments clés de branche (la clé de branche en texte clair et la version de la clé de branche) et en stocke une copie dans le cache local.

  4. Le trousseau de clés hiérarchique dérive une clé d'encapsulation unique à partir de la clé de branche en texte brut et d'un sel aléatoire de 16 octets. Il utilise la clé d'encapsulation dérivée pour chiffrer une copie de la clé de données en texte brut.

La méthode de cryptage utilise les matériaux de cryptage pour crypter les données. Pour plus d'informations, consultez la section Comment AWS Encryption SDK crypte les données.

Décrypter et vérifier

La procédure pas à pas suivante décrit comment le trousseau de clés hiérarchique assemble le matériel de déchiffrement et déchiffre la clé de données chiffrée.

  1. La méthode de déchiffrement identifie la clé de données chiffrée à partir du message chiffré et la transmet au trousseau de clés hiérarchique.

  2. Le trousseau de clés hiérarchique désérialise les données identifiant la clé de données chiffrée, y compris la version de la clé de branche, le sel de 16 octets et d'autres informations décrivant la manière dont la clé de données a été chiffrée.

    Pour de plus amples informations, veuillez consulter AWS KMS Détails techniques du porte-clés hiérarchique.

  3. Le trousseau de clés hiérarchique vérifie si le cache local contient des éléments de clé de branche valides qui correspondent à la version de clé de branche identifiée à l'étape 2. S'il existe des éléments de clé de branche valides, le trousseau passe à l'étape 6.

  4. S'il n'existe aucun matériel de clé de branche valide, le trousseau de clés hiérarchique interroge le magasin de clés pour trouver la clé de branche qui correspond à la version de clé de branche identifiée à l'étape 2.

    1. Le magasin de clés appelle AWS KMS pour déchiffrer la clé de branche et renvoie la clé de branche active en texte brut. Les données identifiant la clé de branche active sont sérialisées pour fournir des données authentifiées supplémentaires (AAD) dans l'appel de déchiffrement à. AWS KMS

    2. Le magasin de clés renvoie la clé de branche en texte brut et les données qui l'identifient, telles que la version de la clé de branche.

  5. Le trousseau de clés hiérarchique rassemble les éléments clés de branche (la clé de branche en texte clair et la version de la clé de branche) et en stocke une copie dans le cache local.

  6. Le trousseau de clés hiérarchique utilise les matériaux de clé de branche assemblés et le sel de 16 octets identifié à l'étape 2 pour reproduire la clé d'encapsulation unique qui a chiffré la clé de données.

  7. Le trousseau de clés hiérarchique utilise la clé d'encapsulation reproduite pour déchiffrer la clé de données et renvoie la clé de données en texte brut.

La méthode de déchiffrement utilise les matériaux de déchiffrement et la clé de données en texte brut pour déchiffrer le message chiffré. Pour plus d'informations, consultez la section Comment AWS Encryption SDK décrypter un message chiffré.

Conditions préalables

Avant de créer et d'utiliser un trousseau de clés hiérarchique, assurez-vous que les conditions préalables suivantes sont remplies.

  • Vous, ou l'administrateur de votre magasin de clés, avez créé un magasin de clés et créé au moins une clé de branche active.

  • Vous avez configuré les actions de votre magasin de clés.

    Note

    La façon dont vous configurez les actions de votre magasin de clés détermine les opérations que vous pouvez effectuer et les clés KMS que le trousseau de clés hiérarchique peut utiliser. Pour plus d'informations, consultez la section Actions relatives au magasin clé.

  • Vous disposez des AWS KMS autorisations nécessaires pour accéder au magasin de clés et aux clés de succursale et les utiliser. Pour de plus amples informations, veuillez consulter Autorisations requises.

  • Vous avez examiné les types de cache pris en charge et configuré le type de cache qui correspond le mieux à vos besoins. Pour de plus amples informations, consultez Choisissez un cache.

Autorisations requises

AWS Encryption SDK Cela ne nécessite pas de Compte AWS et ne dépend d'aucun Service AWS. Toutefois, pour utiliser un trousseau de clés hiérarchique, vous devez disposer Compte AWS des autorisations minimales suivantes sur le ou les AWS KMS key chiffrements symétriques de votre magasin de clés.

Autorisations Amazon DynamoDB requises sur le tableau du magasin de clés

Les principaux acteurs qui interagissent avec votre magasin de clés ont également besoin d'autorisations sur la table DynamoDB. L'ensemble des autorisations dépend du rôle.

Utilisateur du magasin de clés

Un utilisateur du magasin de clés est le principal qui utilise le trousseau de clés hiérarchique pour chiffrer et déchiffrer les données. Un utilisateur du magasin de clés a besoin de dynamodb : dans la GetItem table du magasin de clés.

Administrateur du magasin de clés

L'administrateur du magasin de clés est le principal responsable de la création et de la rotation des clés de branche. Un administrateur du magasin de clés doit disposer des autorisations suivantes sur le tableau du magasin de clés :

  • Pour les lectures : dynamodb : GetItem et dynamodb :. ConditionCheckItem

  • Pour les écritures transactionnelles : dynamodb : ConditionCheckItem et dynamodb :. PutItem Le magasin de clés hiérarchique effectue les écritures TransactWriteItems  ; vous pouvez définir les autorisations d'écriture pour cette opération à l'aide d'une dynamodb:EnclosingOperation condition.

Pour plus d'informations sur le contrôle de l'accès aux clés de votre agence et à votre magasin de clés, consultezImplémentation des autorisations avec le moindre privilégié.

Choisissez un cache

Le trousseau de clés hiérarchique réduit le nombre d'appels en AWS KMS mettant en cache localement les éléments clés de branche utilisés dans les opérations de chiffrement et de déchiffrement. Avant de créer votre trousseau de clés hiérarchique, vous devez décider du type de cache que vous souhaitez utiliser. Vous pouvez utiliser le cache par défaut ou le personnaliser en fonction de vos besoins.

Le trousseau de clés hiérarchique prend en charge les types de cache suivants :

Important

Tous les types de cache pris en charge sont conçus pour prendre en charge les environnements multithread.

Cependant, lorsqu'il est utilisé avec le Kit SDK de chiffrement AWS pour Python, le trousseau de clés Hierarchical ne prend pas en charge les environnements multithread. Pour plus d'informations, consultez le README.rst fichier Python dans le référentiel aws-cryptographic-material-providers-library sur. GitHub

Cache par défaut

Pour la plupart des utilisateurs, le cache par défaut répond à leurs exigences en matière de thread. Le cache par défaut est conçu pour prendre en charge les environnements fortement multithread. Lorsqu'une entrée de matériel clé de branche expire, le cache par défaut empêche l'appel de plusieurs threads AWS KMS en notifiant à un thread que l'entrée de matériaux de clé de branche va expirer 10 secondes à l'avance. Cela garantit qu'un seul thread envoie une demande AWS KMS d'actualisation du cache.

Le cache par défaut et le StormTracking cache prennent en charge le même modèle de threading, mais il vous suffit de spécifier la capacité d'entrée pour utiliser le cache par défaut. Pour des personnalisations plus précises du cache, utilisez le. StormTracking cache

À moins que vous ne souhaitiez personnaliser le nombre d'entrées de matériel de clé de branche pouvant être stockées dans le cache local, vous n'avez pas besoin de spécifier de type de cache lorsque vous créez le trousseau de clés hiérarchique. Si vous ne spécifiez aucun type de cache, le trousseau de clés hiérarchique utilise le type de cache par défaut et définit la capacité d'entrée sur 1 000.

Pour personnaliser le cache par défaut, spécifiez les valeurs suivantes :

  • Capacité d'entrée  : limite le nombre d'entrées de matériel de clé de branche pouvant être stockées dans le cache 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 cache

Le MultiThreaded cache peut être utilisé en toute sécurité dans les environnements multithread, mais il ne fournit aucune fonctionnalité permettant de minimiser les appels AWS KMS Amazon DynamoDB. Par conséquent, lorsqu'une entrée de matériel clé de branche expire, tous les fils de discussion sont notifiés en même temps. Cela peut entraîner plusieurs AWS KMS appels pour actualiser le cache.

Pour utiliser le MultiThreaded cache, spécifiez les valeurs suivantes :

  • Capacité d'entrée  : limite le nombre d'entrées de matériel de clé de branche pouvant être stockées dans le cache local.

  • Taille de la queue d'élagage d'entrée  : définit le nombre d'entrées à tailler si la capacité d'entrée est atteinte.

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 cache

Le StormTracking cache est conçu pour prendre en charge les environnements fortement multithread. Lorsqu'une entrée de matériel de clé de branche expire, le StormTracking cache empêche l'appel de plusieurs threads AWS KMS en notifiant à un thread que l'entrée de matériaux de clé de branche va expirer à l'avance. Cela garantit qu'un seul thread envoie une demande AWS KMS d'actualisation du cache. Pour plus d'informations, consultez Storm Tracking Cryptographic Materials Cache dans le référentiel GitHub aws-encryption-sdk-specification.

Pour utiliser le StormTracking cache, spécifiez les valeurs suivantes :

  • Capacité d'entrée  : limite le nombre d'entrées de matériel de clé de branche pouvant être stockées dans le cache local.

    Valeur par défaut : 1000 entrées

  • Taille de la queue d'élagage d'entrée  : définit le nombre d'entrées de matériaux clés de branche à tailler à la fois.

    Valeur par défaut : 1 entrée

  • Période de grâce  : définit le nombre de secondes avant l'expiration pendant lesquelles une tentative d'actualisation des éléments clés de branche est effectuée.

    Valeur par défaut : 10 secondes

  • Intervalle de grâce  : définit le nombre de secondes entre les tentatives d'actualisation des éléments clés de la branche.

    Valeur par défaut : 1 seconde

  • Ventilation  : définit le nombre de tentatives simultanées qui peuvent être effectuées pour actualiser les éléments clés de la branche.

    Valeur par défaut : 20 tentatives

  • Durée de vie en vol (TTL)  : définit le nombre de secondes qui s'écoulent avant l'expiration d'une tentative d'actualisation du matériel clé de la branche. Chaque fois que le cache revient NoSuchEntry en réponse à aGetCacheEntry, cette clé de branche est considérée comme étant en vol jusqu'à ce que la même clé soit écrite avec une PutCache entrée.

    Valeur par défaut : 10 secondes

  • Veille  : définit le nombre de millisecondes pendant lesquelles un thread doit rester en veille s'il fanOut est dépassé.

    Valeur par défaut : 20 millisecondes

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, }, }

Cache partagé

Par défaut, le trousseau de clés hiérarchique crée un nouveau cache local chaque fois que vous instanciez le jeu de clés. Cependant, le cache partagé peut contribuer à économiser de la mémoire en vous permettant de partager un cache entre plusieurs porte-clés hiérarchiques. Plutôt que de créer un nouveau cache de matériel cryptographique pour chaque jeu de clés hiérarchique que vous instanciez, le cache partagé ne stocke qu'un seul cache en mémoire, qui peut être utilisé par tous les ensembles de clés hiérarchiques qui le référencent. Le cache partagé permet d'optimiser l'utilisation de la mémoire en évitant la duplication de documents cryptographiques entre les porte-clés. Au lieu de cela, les trousseaux de clés hiérarchiques peuvent accéder au même cache sous-jacent, réduisant ainsi l'empreinte mémoire globale.

Lorsque vous créez votre cache partagé, vous définissez toujours le type de cache. Vous pouvez spécifier un Cache par défautMultiThreaded cache, ou StormTracking cache comme type de cache, ou le remplacer par un cache personnalisé compatible.

Partitions

Plusieurs porte-clés hiérarchiques peuvent utiliser un seul cache partagé. Lorsque vous créez un porte-clés hiérarchique avec un cache partagé, vous pouvez définir un ID de partition facultatif. L'ID de partition permet de distinguer le trousseau de clés hiérarchique qui écrit dans le cache. Si deux trousseaux de clés hiérarchiques font référence au même ID de partition et au même ID de clé de branchelogical key store name, les deux porte-clés partageront les mêmes entrées de cache dans le cache. Si vous créez deux trousseaux de clés hiérarchiques avec le même cache partagé, mais des ID de partition différents, chaque jeu de clés n'accédera aux entrées du cache qu'à partir de sa propre partition désignée dans le cache partagé. Les partitions agissent comme des divisions logiques au sein du cache partagé, permettant à chaque jeu de clés hiérarchique de fonctionner indépendamment sur sa propre partition désignée, sans interférer avec les données stockées dans l'autre partition.

Si vous avez l'intention de réutiliser ou de partager les entrées du cache d'une partition, vous devez définir votre propre identifiant de partition. Lorsque vous transmettez l'ID de partition à votre trousseau de clés hiérarchique, celui-ci peut réutiliser les entrées de cache déjà présentes dans le cache partagé, au lieu de devoir récupérer et réautoriser les éléments clés de branche. Si vous ne spécifiez pas d'identifiant de partition, un identifiant de partition unique est automatiquement attribué au trousseau de clés chaque fois que vous instanciez le jeu de clés hiérarchique.

Les procédures suivantes montrent comment créer un cache partagé avec le type de cache par défaut et le transmettre à un trousseau de clés hiérarchique.

  1. Créez un CryptographicMaterialsCache (CMC) à l'aide de la Material Providers Library (MPL).

    Java
    // Instantiate the MPL final MaterialProviders matProv = MaterialProviders.builder() .MaterialProvidersConfig(MaterialProvidersConfig.builder().build()) .build(); // Create a CacheType object for the Default cache final CacheType cache = CacheType.builder() .Default(DefaultCache.builder().entryCapacity(100).build()) .build(); // Create a CMC using the default cache final CreateCryptographicMaterialsCacheInput cryptographicMaterialsCacheInput = CreateCryptographicMaterialsCacheInput.builder() .cache(cache) .build(); final ICryptographicMaterialsCache sharedCryptographicMaterialsCache = matProv.CreateCryptographicMaterialsCache(cryptographicMaterialsCacheInput);
    C# / .NET
    // Instantiate the MPL var materialProviders = new MaterialProviders(new MaterialProvidersConfig()); // Create a CacheType object for the Default cache var cache = new CacheType { Default = new DefaultCache{EntryCapacity = 100} }; // Create a CMC using the default cache var cryptographicMaterialsCacheInput = new CreateCryptographicMaterialsCacheInput {Cache = cache}; var sharedCryptographicMaterialsCache = materialProviders.CreateCryptographicMaterialsCache(cryptographicMaterialsCacheInput);
    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. Créez un CacheType objet pour le cache partagé.

    Transmettez ce sharedCryptographicMaterialsCache que vous avez créé à l'étape 1 au nouvel CacheType objet.

    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. Transmettez l'sharedCacheobjet de l'étape 2 à votre trousseau de clés hiérarchique.

    Lorsque vous créez un trousseau de clés hiérarchique avec un cache partagé, vous pouvez éventuellement en définir un partitionID pour partager les entrées du cache entre plusieurs porte-clés hiérarchiques. Si vous ne spécifiez pas d'identifiant de partition, le trousseau de clés hiérarchique attribue automatiquement au trousseau de clés un identifiant de partition unique.

    Note

    Vos trousseaux de clés hiérarchiques partageront les mêmes entrées de cache dans un cache partagé si vous créez au moins deux porte-clés qui font référence aux mêmes ID de partition et ID de clé de branche. logical key store name Si vous ne souhaitez pas que plusieurs trousseaux de clés partagent les mêmes entrées de cache, vous devez utiliser un identifiant de partition unique pour chaque porte-clés hiérarchique.

    L'exemple suivant crée un porte-clés hiérarchique avec unbranch key ID supplier, et une limite de cache de 600 secondes. Pour plus d'informations sur les valeurs définies dans la section Configuration hiérarchique des porte-clés suivante, consultezCréation d'un porte-clés hiérarchique.

    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) }

Création d'un porte-clés hiérarchique

Pour créer un porte-clés hiérarchique, vous devez fournir les valeurs suivantes :

  • Un nom de magasin clé

    Nom de la table DynamoDB que vous, ou votre administrateur de magasin de clés, avez créée pour servir de magasin de clés.

  • Une limite de durée de vie du cache (TTL)

    Durée en secondes pendant laquelle une entrée de matériel de clé de branche dans le cache local peut être utilisée avant son expiration. La limite de cache TTL détermine la fréquence à laquelle le client appelle AWS KMS pour autoriser l'utilisation des clés de branche. Cette valeur doit être supérieure à zéro. Une fois la limite de cache TTL expirée, l'entrée n'est jamais diffusée et sera expulsée du cache local.

  • Un identifiant de clé de succursale

    Vous pouvez soit configurer statiquement la clé branch-key-id qui identifie une seule clé de branche active dans votre magasin de clés, soit fournir un fournisseur d'ID de clé de branche.

    Le fournisseur d'ID de clé de branche utilise les champs stockés dans le contexte de chiffrement pour déterminer quelle clé de branche est requise pour déchiffrer un enregistrement.

    Nous vous recommandons vivement d'utiliser un fournisseur d'identifiant de clé de branche pour les bases de données multi-locataires où chaque locataire possède sa propre clé de branche. Vous pouvez utiliser le fournisseur d'ID de clé de succursale pour créer un nom convivial pour vos identifiants de clé de succursale afin de faciliter la reconnaissance de l'ID de clé de branche correct pour un locataire spécifique. Par exemple, le nom convivial vous permet de faire référence à une clé de branche au tenant1 lieu deb3f61619-4d35-48ad-a275-050f87e15122.

    Pour les opérations de déchiffrement, vous pouvez soit configurer statiquement un seul jeu de clés hiérarchique pour limiter le déchiffrement à un seul locataire, soit utiliser le fournisseur d'ID de clé de branche pour identifier le locataire responsable du déchiffrement d'un enregistrement.

  • (Facultatif) Un cache

    Si vous souhaitez personnaliser le type de cache ou le nombre d'entrées de matériel de clé de branche pouvant être stockées dans le cache local, spécifiez le type de cache et la capacité d'entrée lorsque vous initialisez le trousseau de clés.

    Le trousseau de clés hiérarchique prend en charge les types de cache suivants : Par défaut MultiThreaded, StormTracking, et partagé. Pour plus d'informations et des exemples illustrant comment définir chaque type de cache, consultezChoisissez un cache.

    Si vous ne spécifiez pas de cache, le trousseau de clés hiérarchique utilise automatiquement le type de cache par défaut et définit la capacité d'entrée sur 1 000.

  • (Facultatif) Un identifiant de partition

    Si vous le spécifiezCache partagé, vous pouvez éventuellement définir un ID de partition. L'ID de partition permet de distinguer le trousseau de clés hiérarchique qui écrit dans le cache. Si vous avez l'intention de réutiliser ou de partager les entrées du cache d'une partition, vous devez définir votre propre identifiant de partition. Vous pouvez spécifier n'importe quelle chaîne pour l'ID de partition. Si vous ne spécifiez pas d'identifiant de partition, un identifiant de partition unique est automatiquement attribué au trousseau de clés lors de sa création.

    Pour de plus amples informations, veuillez consulter Partitions.

    Note

    Vos trousseaux de clés hiérarchiques partageront les mêmes entrées de cache dans un cache partagé si vous créez au moins deux porte-clés qui font référence aux mêmes ID de partition et ID de clé de branche. logical key store name Si vous ne souhaitez pas que plusieurs trousseaux de clés partagent les mêmes entrées de cache, vous devez utiliser un identifiant de partition unique pour chaque porte-clés hiérarchique.

  • (Facultatif) Une liste de jetons de subvention

    Si vous contrôlez l'accès à la clé KMS dans votre trousseau de clés hiérarchique à l'aide d'autorisations, vous devez fournir tous les jetons d'autorisation nécessaires lorsque vous initialisez le jeu de clés.

Les exemples suivants montrent comment créer un trousseau de clés hiérarchique avec un ID de clé de branche statique, leCache par défaut, et une limite de cache TTL de 600 secondes.

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) }

Les procédures suivantes montrent comment créer un trousseau de clés hiérarchique avec un fournisseur d'identifiant de clé de branche.

  1. Créer un fournisseur d'identifiant de clé de succursale

    L'exemple suivant définit un fournisseur d'ID de clé de branche qui utilise le contexte de chiffrement au moment du chiffrement ou du déchiffrement pour sélectionner l'ID de clé de branche pour chaque locataire. Pour une implémentation fonctionnelle dans chaque langue, voir :

    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. Création d'un porte-clés hiérarchique

    Les exemples suivants initialisent un trousseau de clés hiérarchique avec le fournisseur d'ID de clé de branche créé à l'étape 1, une limite de cache TLL de 600 secondes et une taille de cache maximale de 1 000.

    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) }