Chiffrement au niveau des colonnes avec Cloud KMS

Vous pouvez utiliser Cloud Key Management Service (Cloud KMS) pour chiffrer les clés qui, à leur tour, chiffrent les valeurs dans les tables BigQuery. Vous pouvez utiliser les fonctions de chiffrement AEAD avec des collections de clés ou des collections de clés encapsulées Cloud KMS pour fournir une seconde couche de protection au niveau des colonnes.

Présentation

Pour fournir un niveau de protection supplémentaire, Cloud KMS chiffre votre clé de chiffrement des données (DEK) à l'aide d'une deuxième clé de chiffrement de clé (KEK). Dans BigQuery, référencer une collection de clés chiffrées au lieu d'une collection de clés en texte brut contribue à réduire le risque d'exposition des clés. La KEK est une collection de clés de chiffrement symétrique qui est stockée de manière sécurisée dans Cloud KMS et gérée à l'aide des rôles et autorisations Identity and Access Management (IAM).

BigQuery accepte les fonctions de chiffrement déterministes et non déterministes. Avec le chiffrement déterministe, si les éléments de données stockés et les données authentifiées supplémentaires (facultatives) sont identiques, le texte chiffré est identique. Cela permet la compatibilité avec l'agrégation et les jointures basées sur la colonne chiffrée. Avec le chiffrement non déterministe, le texte chiffré est unique, quelle que soit les données chiffrées, ce qui empêche le clustering, l'agrégation et les jointures.

Au moment de l'exécution de la requête, vous fournissez le chemin d'accès à la ressource Cloud KMS de la KEK et le texte chiffré à partir de la DEK encapsulée. BigQuery appelle Cloud KMS pour désencapsuler la DEK, puis utilise cette clé pour déchiffrer les données de votre requête. La version non-encapsulée de la DEK n'est stockée en mémoire que pendant la durée de la requête, puis elle est détruite.

Si vous utilisez Cloud KMS dans une régionCloud External Key Manager est disponible, vous pouvez utiliser des clés basées sur Cloud EKM dans Cloud KMS.

Cas d'utilisation

Voici quelques cas d'utilisation du chiffrement avec des clés Cloud KMS :

  • Données chiffrées en externe devant être stockées dans BigQuery sans stocker la collection de clés en texte brut. Vos données peuvent ensuite être exportées à partir de la table ou déchiffrées avec une requête SQL.
  • "Contrôle des accès double" pour les données chiffrées dans BigQuery. Un utilisateur doit disposer d'autorisations sur la table et la clé de chiffrement pour lire des données en texte clair.
Matrice d'autorisations des utilisateurs
Autorisation sur la table Aucune autorisation sur la table
Autorisations sur la clé Lire et déchiffrer les données chiffrées. Aucun accès.
Aucune autorisation sur la clé Lire les données chiffrées. Aucun accès.

Si un utilisateur est autorisé à accéder à la clé KMS et à la collection de clés encapsulée, les fonctions SQL peuvent désencapsuler la collection de clés et déchiffrer le texte chiffré. Les utilisateurs peuvent également utiliser l'API REST ou la CLI Cloud KMS pour désencapsuler la collection de clés.
L'exemple de requête suivant utilise des fonctions SQL KMS pour déchiffrer un texte chiffré non déterministe :

SELECT
  AEAD.DECRYPT_STRING(
    KEYS.KEYSET_CHAIN(@kms_resource_name, @first_level_keyset),
    ciphertext,
    additional_authenticated_data)
FROM
  ciphertext_table
WHERE
  ...

Exemple de cas d'utilisation

Prenons une implémentation où les codes postaux sont considérés comme des informations sensibles. Les données de code postal peuvent être insérées dans la table BigQuery à l'aide de la fonction de chiffrement AEAD, chiffrant ainsi la colonne Zipcode. Dans cet exemple, nous utilisons la fonction AEAD.ENCRYPT avec la fonction de gestion de collections de clés encapsulée. La fonction KEYS.KEYSET_CHAIN chiffre la clé de chiffrement numérique avec la KEK, et la fonction AEAD.ENCRYPT transmet les informations au service de gestion des clés.

La chaîne de clés de chiffrement et de déchiffrement garantit que la clé de chiffrement des données (DEK) est chiffrée ou encapsulée avec une KEK et transmise avec cette KEK. La DEK encapsulée est déchiffrée ou désencapsulée dans la fonction SQL, puis est utilisée pour chiffrer ou déchiffrer des données.

La fonction non déterministe AEAD peut déchiffrer les données lorsqu'on y accède en utilisant la fonction de la requête qui est en cours d'exécution sur la table.

image

La fonction déterministe AEAD peut déchiffrer des données lorsqu'on y accède en utilisant la fonction de la requête en cours d'exécution sur la table. Elle est également compatible avec l'agrégation et les jointures à l'aide des données chiffrées.

Image

Syntaxe des fonctions non déterministes

La syntaxe acceptée pour l'utilisation de fonctions non déterministes est la suivante :

AEAD.ENCRYPT(
  KEYS.KEYSET_CHAIN(kms_resource_name, first_level_keyset),
  plaintext,
  additional_authenticated_data)
AEAD.DECRYPT_STRING(
  KEYS.KEYSET_CHAIN(kms_resource_name, first_level_keyset),
  ciphertext,
  additional_authenticated_data)
AEAD.DECRYPT_BYTES(
  KEYS.KEYSET_CHAIN(kms_resource_name, first_level_keyset),
  ciphertext,
  additional_authenticated_data)

Voir la syntaxe des fonctions AEAD.DECRYPT_BYTES, AEAD.ENCRYPT, AEAD.DECRYPT_STRING et KEYS.KEYSET_CHAIN.

Syntaxe des fonctions déterministes

La syntaxe acceptée pour l'utilisation de fonctions déterministes est la suivante :

DETERMINISTIC_ENCRYPT(
  KEYS.KEYSET_CHAIN(kms_resource_name, first_level_keyset),
  plaintext,
  additional_data)
DETERMINISTIC_DECRYPT_STRING(
  KEYS.KEYSET_CHAIN(kms_resource_name, first_level_keyset),
  ciphertext,
  additional_data)
DETERMINISTIC_DECRYPT_BYTES(
  KEYS.KEYSET_CHAIN(kms_resource_name, first_level_keyset),
  ciphertext,
  additional_data)

Voir la syntaxe des fonctions DETERMINISTIC_DECRYPT_BYTES, DETERMINISTIC_ENCRYPT, DETERMINISTIC_DECRYPT_STRING et KEYS.KEYSET_CHAIN.

Rôles et autorisations

Pour obtenir la liste des rôles pour Cloud KMS, consultez la page Autorisations et rôles Cloud KMS.

Limites

Le chiffrement avec Cloud KMS présente les limitations et restrictions suivantes :

  • Les clés Cloud KMS sont limitées à la même région ou multirégion que la requête. L'utilisation de clés Cloud KMS globales n'est pas autorisée pour des raisons de fiabilité.

  • Il n'est pas possible d'alterner une collection de clés encapsulée à l'aide de la fonction KEYS.ROTATE_KEYSET.

  • Les paramètres constants dans une requête BigQuery sont visibles par les utilisateurs dans le plan de requête de diagnostic. Cela peut affecter les paramètres kms_resource_name et first_level_keyset de la fonction KEYSET_CHAIN. Les clés ne sont jamais exposées en texte brut, et l'autorisation d'utiliser la clé Cloud KMS est requise pour déchiffrer la collection de clés encapsulée. Cela garantit que les clés ne sont pas exposées via le plan de requête de diagnostic, sauf si l'utilisateur est autorisé à déchiffrer la collection de clés.

  • Le chiffrement au niveau des colonnes présente les limites suivantes lorsqu'il est utilisé avec des classifications de sécurité basées sur les types :

    • Sécurité au niveau des colonnes : les utilisateurs ne peuvent déchiffrer ou chiffrer des données que dans les colonnes auxquelles ils sont autorisés à accéder.

    • Sécurité au niveau des lignes : les utilisateurs ne peuvent déchiffrer des données que sur les lignes auxquelles ils sont autorisés à accéder.

  • Les fonctions SQL au niveau des colonnes n'ont aucun impact significatif sur les performances par rapport aux performances des fonctions de chiffrement brut dans lesquelles les données de clé sont envoyées en texte brut.

Avant de commencer

Pour utiliser des clés, des collections de clés, des tables chiffrées, des fonctions déterministes et des fonctions non déterministes Cloud KMS, vous devez appliquer les étapes suivantes si vous ne l'avez pas déjà fait :

  1. Créez un projet Google Cloud.

  2. Créez un ensemble de données BigQuery.

  3. Créez un trousseau de clés Cloud KMS.

  4. Créez une clé Cloud KMS pour une colonne chiffrée avec le niveau de protection Logiciel ou HSM (Hardware Security Module).

  5. Accordez des autorisations utilisateur pour utiliser les clés, le chiffrement et le déchiffrement Cloud KMS.

Notez les concepts suivants, car ils sont référencés dans les sections suivantes :

  • PROJECT_ID : nom du projet Google Cloud.

  • DATASET_NAME : nom de l'ensemble de données BigQuery.

  • LOCATION_ID : emplacement de l'ensemble de données BigQuery.

  • TABLE_NAME : nom de la table BigQuery.

  • KEY_RING_ID : nom du trousseau de clés Cloud KMS.

  • KEY_ID : nom de la clé Cloud KMS.

  • KMS_KEY : clé Cloud KMS (KEK) au format suivant :

    'gcp-kms://projects/PROJECT_ID/locations/LOCATION_ID/keyRings/KEY_RING_ID/cryptoKeys/KEY_ID'
    

    Voici un exemple de clé Cloud KMS :

    'gcp-kms://projects/myProject/locations/us/keyRings/myKeyRing/cryptoKeys/myKeyName'
    
  • KMS_KEY_SHORT : semblable à KMS_KEY, mais au format suivant :

    projects/PROJECT_ID/locations/LOCATION_ID/keyRings/KEY_RING_ID/cryptoKeys/KEY_ID
    
  • KEYSET_DECODED : collection de clés décodée sous forme de séquence BYTES. Le résultat ressemble à celui du décodage d'une collection de clés encapsulée.

    Bien que les fonctions de collections de clés renvoient des collections de clés sous forme d'octets, les résultats utilisateur sont affichés sous forme de chaîne encodée. Pour convertir une collection de clés encodée en collection de clés décodée, consultez la page Décoder une collection de clés Cloud KMS.

  • KEYSET_ENCODED : collection de clés encodée au format STRING. Le résultat ressemble à celui d'une collection de clés encapsulée encodée.

    Pour convertir une collection de clés encodée en collection de clés décodée, consultez la page Décoder une collection de clés Cloud KMS.

  • WRAPPED_KEYSET_DECODED : collection de clés encapsulée décodée en tant que séquence BYTES. Voici un exemple du résultat obtenu :

    b'\x0a$\x00\xa6\xee\x12Y\x8d|l"\xf7\xfa\xc6\xeafM\xdeefy\xe9\x7f\xf2z\xb3M\
    xf6"\xd0\xe0Le\xa8\x8e\x0fR\xed\x12\xb7\x01\x00\xf0\xa80\xbd\xc1\x07Z\\
    \xd0L<\x80A0\x9ae\xfd(9\x1e\xfa\xc8\x93\xc7\xe8\...'
    

    Bien que les fonctions de collection de clés encapsulée renvoient des collections de clés encapsulées en octets, le résultat utilisateur s'affiche sous forme de chaîne encodée. Pour convertir une collection de clés encapsulée encodée en une collection de clés encapsulée décodée, consultez la page Décoder une collection de clés Cloud KMS.

  • WRAPPED_KEYSET_ENCODED : collection de clés encapsulée et codée en tant que STRING. Voici un exemple du résultat obtenu :

    'CiQApu4SWTozQ7lNwITxpEvGlo5sT2rv1tyuSv3UAMtoTq/lhDwStwEA8KgwvX7CpVVzhWWMkRw
    WZNr3pf8uBIlzHeunCy8ZsQ6CofQYFpiBRBB6k/QqATbiFV+3opnDk/6dBL/S8OO1WoDC+DdD9
    uzEFwqt5D20lTXCkGWFv1...'
    

    Pour convertir une collection de clés encapsulée codée en une collection de clés encapsulée décodée, consultez la section Décoder une collection de clés Cloud KMS.

Gestion des clés

Les sections suivantes contiennent les tâches courantes que vous pouvez effectuer avec les clés Cloud KMS.

Créer une collection de clés

Vous pouvez créer des collections de clés encapsulées ou des collections de clés brutes. Pour ce faire, suivez les étapes décrites dans les sections suivantes.

Créer une collection de clés brute

Exécutez la requête suivante pour créer une collection de clés avec une clé de type DETERMINISTIC_AEAD_AES_SIV_CMAC_256.

SELECT KEYS.NEW_KEYSET('DETERMINISTIC_AEAD_AES_SIV_CMAC_256') AS raw_keyset

Créer une collection de clés encapsulée

Exécutez la requête suivante pour créer une collection de clés encapsulée Cloud KMS avec une clé de type DETERMINISTIC_AEAD_AES_SIV_CMAC_256.

SELECT KEYS.NEW_WRAPPED_KEYSET(
  KMS_KEY,
  'DETERMINISTIC_AEAD_AES_SIV_CMAC_256')

Décoder une collection de clés

Bien que les fonctions SQL qui renvoient des collections de clés produisent des collections de clés au format BYTES, le résultat affiché pour l'utilisateur est encodé et affiché au format STRING. Si vous souhaitez convertir cette chaîne encodée en une séquence d'octets décodés que vous pouvez utiliser comme fonctions de chiffrement de clé littérales, utilisez la requête suivante.

Décoder une collection de clés encapsulée

Exécutez la requête suivante pour décoder une collection de clés encapsulée Cloud KMS.

SELECT FORMAT('%T', FROM_BASE64(WRAPPED_KEYSET_ENCODED'))

Décoder une collection de clés brute

Exécutez la requête suivante pour décoder une collection de clés brute.

SELECT FORMAT('%T', FROM_BASE64(KEYSET_ENCODED'))

Réencapsuler une collection de clés encapsulée

Exécutez la requête suivante pour réencapsuler une collection de clés encapsulée Cloud KMS avec une nouvelle clé Cloud KMS. KMS_KEY_CURRENT représente la nouvelle classe KMS_KEY utilisée pour chiffrer la collection de clés. KMS_KEY_NEW représente la nouvelle classe KMS_KEY utilisée pour chiffrer la collection de clés.

SELECT KEYS.REWRAP_KEYSET(
  KMS_KEY_CURRENT,
  KMS_KEY_NEW,
  WRAPPED_KEYSET_DECODED)

Effectuer une rotation de collection de clés encapsulée

Exécutez la requête suivante pour effectuer une rotation de la collection de clés encapsulée Cloud KMS avec une clé de type DETERMINISTIC_AEAD_AES_SIV_CMAC_256.

SELECT KEYS.ROTATE_WRAPPED_KEYSET(
  KMS_KEY,
  WRAPPED_KEYSET_DECODED,
  'DETERMINISTIC_AEAD_AES_SIV_CMAC_256')

Générer une collection de clés brute à partir d'une collection de clés encapsulée

Certaines fonctions de chiffrement nécessitent une collection de clés brute. Pour déchiffrer une collection de clés encapsulée Cloud KMS afin de produire une collection de clés brute, procédez comme suit :

  1. Créez une collection de clés encapsulée.

  2. Dans l'outil de ligne de commande bq, saisissez les commandes suivantes pour enregistrer une collection de clés encapsulée dans un fichier nommé keyset_to_unwrap, déchiffrer les collections de clés encapsulées et produire le résultat au format KEYSET_DECODED :

    echo WRAPPED_KEYSET_ENCODED | base64 -d > /tmp/decoded_wrapped_key
    
    gcloud kms decrypt \
    --ciphertext-file=/tmp/decoded_wrapped_key \
    --key=KMS_KEY_SHORT \
    --plaintext-file=/tmp/keyset_to_unwrap.dec \
    --project=PROJECT_ID
    
    od -An --format=o1 /tmp/keyset_to_unwrap.dec | tr ' ' '\'
    

Générer une collection de clés encapsulée à partir d'une collection de clés brute

Certaines fonctions de chiffrement nécessitent une collection de clés encapsulée Cloud KMS. Pour chiffrer une collection de clés brute afin de produire une collection de clés encapsulée, procédez comme suit :

  1. Créez une collection de clés brute.

  2. Dans l'outil de ligne de commande bq, saisissez les commandes suivantes pour enregistrer une collection de clés brute dans un fichier nommé keyset_to_wrap, chiffrer la collection de clés brute et produire la sortie au format WRAPPED_KEYSET_DECODED :

    echo KEYSET_ENCODED | base64 -d > /tmp/decoded_key
    
    gcloud kms encrypt \
    --plaintext-file=/tmp/decoded_key \
    --key=KMS_KEY_SHORT \
    --ciphertext-file=/tmp/keyset_to_wrap.dec \
    --project=PROJECT_ID
    
    od -An --format=o1 /tmp/keyset_to_wrap.dec | tr ' ' '\'
    

Générer une clé encapsulée pour une fonction DLP

Pour les fonctions DLP, vous avez besoin d'une clé de chiffrement, puis vous l'utilisez pour obtenir une clé encapsulée.

  1. Pour générer une nouvelle clé cryptographique, exécutez la commande suivante dans la ligne de commande. La taille de la clé peut être de 16, 24 ou 32 octets. L'exemple suivant utilise une clé de 16 octets:

    openssl rand 16 > rand.key.16.bin
    
  2. Encapsulez la clé de 16 octets générée avec une clé KMS. Consultez l'exemple ci-dessous :

    KEYRING=projects/myproject/locations/us/keyRings/kms-test
    KEY=projects/myproject/locations/us/keyRings/kms-test/cryptoKeys/test-Kek
    PROJECT="myproject"
    
    gcloud kms encrypt --project $PROJECT --location us --keyring $KEYRING --key $KEY --plaintext-file ./rand.key.16.bin --ciphertext-file ./rand.key.16.wrapped
    
  3. Vous pouvez maintenant obtenir le littéral BYTES de la clé encapsulée ou le format base64 de la clé encapsulée.

    • Littéral d'octets

      username:~/tmp$ od -b ./rand.key.16.wrapped | cut -d ' ' -f 2- | head -n -1 | sed  -e 's/^/ /' | tr ' ' '\'
      

      La sortie ressemble à ceci :

      \012\044\000\325\155\264\153\246\071\172\130\372\305\103\047\342\356\061\077\014\030\126\147\041\126\150\012\036\020\202\215\044\267\310\331\014\116\233\022\071\000\363\344\230\067\274\007\340\273\016\212\151\226\064\200\377\303\207\103\147\052\267\035\350\004\147\365\251\271\133\062\251\246\152\177\017\005\270\044\141\211\116\337\043\035\263\122\340\110\333\266\220\377\247\204\215\233
      
    • Format Base64

      username:~/tmp$ base64 ./rand.key.16.wrapped
      

      La sortie ressemble à ceci :

      CiQA1W20a6Y5elj6xUMn4u4xPwwYVmchVmgKHhCCjSS3yNkMTpsSOQDz5Jg3vAfguw6KaZY0gP/Dh0NnKrcd6ARn9am5WzKppmp/DwW4JGGJTt8jHbNS4EjbtpD/p4SNmw==
      

Obtenir le nombre de clés dans une collection de clés

Exécutez la requête suivante pour obtenir le nombre de clés dans une collection de clés brute.

  1. Si vous utilisez une collection de clés encapsulée, commencez par générer une collection de clés brute.

  2. Exécutez la requête suivante avec la collection de clés brute :

    SELECT KEYS.KEYSET_LENGTH(KEYSET_DECODED) as key_count;
    

Obtenir une représentation JSON d'une collection de clés

Exécutez la requête suivante pour afficher une représentation JSON d'une collection de clés brute.

  1. Si vous utilisez une collection de clés encapsulée, commencez par générer une collection de clés brute.

  2. Exécutez la requête suivante avec la collection de clés brute :

    SELECT KEYS.KEYSET_TO_JSON(KEYSET_DECODED);
    

Chiffrement et déchiffrement

Vous pouvez utiliser des collections de clés brutes ou des collections de clés encapsulées pour chiffrer une colonne dans une table. Vous pouvez également choisir d'utiliser un chiffrement déterministe ou non déterministe sur vos colonnes. Les exemples de cette section utilisent des collections de clés encapsulées, mais vous pouvez les remplacer par des collections de clés brutes.

Chiffrer une colonne de façon déterministe avec une collection de clés encapsulée

Exécutez la requête suivante pour créer une table et stocker une collection de clés encapsulée Cloud KMS avec un chiffrement déterministe dans une colonne appelée encrypted_content.

  1. Créez une collection de clés encapsulée.

  2. Chiffrez une colonne avec la collection de clés encapsulée.

    CREATE OR REPLACE TABLE DATASET_NAME.TABLE_NAME AS
      SELECT DETERMINISTIC_ENCRYPT(
        KEYS.KEYSET_CHAIN(KMS_KEY, WRAPPED_KEYSET_DECODED),
        'plaintext',
        '') AS encrypted_content
    

Déchiffrer une colonne de manière déterministe avec une collection de clés encapsulée

Exécutez la requête suivante pour déchiffrer de manière déterministe une colonne contenant du contenu chiffré à l'aide d'une collection de clés encapsulée Cloud KMS. Cette requête suppose que vous référencez une table avec une colonne appelée encrypted_content.

SELECT DETERMINISTIC_DECRYPT_STRING(
  KEYS.KEYSET_CHAIN(KMS_KEY, WRAPPED_KEYSET_DECODED),
  encrypted_content,
  '')
FROM DATASET_NAME.TABLE_NAME

Chiffrer une colonne de manière non déterministe avec une collection de clés encapsulée

Consultez la section Chiffrer une colonne de manière déterministe avec une collection de clés encapsulée, mais remplacez DETERMINISTIC_ENCRYPT par AEAD.ENCRYPT. Assurez-vous que votre collection de clés est de type AEAD_AES_GCM_256.

Déchiffrer une colonne de manière non déterministe avec une collection de clés encapsulée

Consultez la section Déchiffrer une colonne de manière déterministe avec une collection de clés encapsulées, mais remplacez DETERMINISTIC_DECRYPT_STRING par AEAD.DECRYPT_STRING. Assurez-vous que votre collection de clés est de type AEAD_AES_GCM_256.

Étapes suivantes

  • Découvrez Cloud KMS. Cet article présente des informations conceptuelles sur le chiffrement au niveau des colonnes pour Google Cloud.
  • Apprenez-en plus sur le chiffrement AEAD pour BigQuery. Cet article présente des informations conceptuelles sur le chiffrement au niveau des colonnes, pour BigQuery en particulier.
  • Découvrez les fonctions de chiffrement AEAD pour BigQuery. Cette rubrique contient toutes les fonctions SQL que vous pouvez utiliser pour le chiffrement au niveau des colonnes dans BigQuery.