Encriptación a nivel de columnas con Cloud KMS

Puedes usar Cloud Key Management Service (Cloud KMS) para encriptar las claves que, a su vez, encriptan los valores dentro de las tablas de BigQuery. Puedes usar las funciones de encriptación AEAD con conjuntos de claves o conjuntos de claves unidos de Cloud KMS para proporcionar una segunda capa de protección a nivel de la columna.

Introducción

Para proporcionar una capa adicional de protección, Cloud KMS encripta tu clave de encriptación de datos (DEK) con una segunda clave de encriptación de claves (KEK). En BigQuery, hacer referencia a un conjunto de claves encriptado en lugar de a un texto sin formato ayuda a reducir el riesgo de exposición de claves. La KEK es un conjunto de claves de encriptación simétrica que se almacena de forma segura en Cloud KMS y se administra mediante funciones y permisos de Identity and Access Management (IAM).

BigQuery admite funciones de encriptación deterministas y no deterministas. Con la encriptación determinista, si los datos almacenados y los datos autenticados adicionales (opcionales) son idénticos, el texto cifrado es idéntico. Esto permite la agregación y las uniones en función de la columna encriptada. Con la encriptación no determinista, el texto cifrado almacenado es único sin importar los datos encriptados, lo que evita el agrupamiento en clústeres, la agregación y las uniones.

En el momento de la ejecución de la consulta, debes proporcionar la ruta de acceso de recursos de Cloud KMS de la KEK y el texto cifrado de la DEK unida. BigQuery llama a Cloud KMS para separar la DEK y, luego, usa esa clave a fin de desencriptar los datos en tu consulta. La versión separada de la DEK solo se almacena en la memoria durante la consulta y, luego, se destruye.

Si usas Cloud KMS en una región en la que es compatible Cloud External Key Manager, puedes usar claves basadas en Cloud EKM en Cloud KMS.

Casos de uso

A continuación, se presentan los casos de uso de encriptación con claves de Cloud KMS:

  • Datos encriptados de forma externa que deben almacenarse en BigQuery sin almacenar el conjunto de claves en texto simple. Luego, tus datos se pueden exportar desde la tabla BQ o desencriptar con una consulta de SQL.
  • “Control de acceso doble” en datos encriptados en BigQuery. Un usuario debe tener permiso tanto para la tabla como para la clave de encriptación para leer datos en el texto simple.
Matriz de permisos del usuario
Permiso en la tabla Sin permiso en la tabla
Permisos de la clave Lee y desencripta datos encriptados. Sin acceso
No hay permisos para la clave Lee los datos encriptados. Sin acceso

Si un usuario tiene permiso para acceder a la clave KMS y tiene acceso al conjunto de claves unido, las funciones de SQL pueden desunir el conjunto de claves y desencriptar el texto cifrado. Los usuarios también pueden usar la API de REST o la CLI de Cloud KMS para separar el conjunto de claves.
En la siguiente consulta de muestra, se usan funciones de SQL de KMS para desencriptar el texto cifrado no determinista:

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

Ejemplo de caso de uso

Supongamos una implementación en la que los códigos postales se consideran información sensible. Los datos de código postal se pueden insertar en la tabla de BigQuery mediante la función de encriptación AEAD, lo que encripta la columna Zipcode. En este ejemplo, usamos la función AEAD.ENCRYPT con la función de administración de conjunto de claves unida. La función KEYS.KEYSET_CHAIN encripta la clave de encriptación digital con la KEK, y la función AEAD.ENCRYPT pasa la información a KMS.

La cadena de conjunto de claves para la encriptación y desencriptación garantiza que la clave de encriptación de datos (DEK) esté encriptada o unida con una KEK y se pase con esa KEK. La DEK unida se desencripta o se separa dentro de la función de SQL y, luego, se usa para encriptar o desencriptar los datos.

La función no determinista AEAD puede desencriptar datos cuando se accede a ella mediante la función en la consulta que se ejecuta en la tabla.

imagen

La función determinista AEAD puede desencriptar datos cuando se accede a ella mediante la función en la consulta que se ejecuta en la tabla y admite la agregación y uniones mediante los datos encriptados.

imagen

Sintaxis de funciones no deterministas

La sintaxis compatible para usar funciones no deterministas incluye lo siguiente:

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)

Consulta AEAD.DECRYPT_BYTES, AEAD.ENCRYPT, AEAD.DECRYPT_STRING y KEYS.KEYSET_CHAIN.

Sintaxis de las funciones deterministas

La sintaxis compatible para usar funciones deterministas incluye lo siguiente:

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)

Consulta DETERMINISTIC_DECRYPT_BYTES, DETERMINISTIC_ENCRYPT, DETERMINISTIC_DECRYPT_STRING y KEYS.KEYSET_CHAIN.

Roles y permisos

Para obtener una lista de roles para Cloud KMS, consulta Permisos y roles de Cloud KMS.

Limitaciones

La encriptación con Cloud KMS tiene las siguientes limitaciones y restricciones:

  • Las claves de Cloud KMS están restringidas a la misma región o multirregión que la consulta. El uso de claves globales de Cloud KMS no está permitido por motivos de confiabilidad.

  • No es posible rotar un conjunto de claves unido con la función KEYS.ROTATE_KEYSET.

  • En la actualidad, los parámetros constantes en una consulta de BigQuery son visibles para los usuarios en el plan de consultas de diagnóstico. Esto puede afectar los parámetros kms_resource_name y first_level_keyset de la función KEYSET_CHAIN. Las claves nunca se exponen en texto sin formato, y se requiere el permiso para la clave de Cloud KMS a fin de desencriptar el conjunto de claves unidos. Esto garantiza que las claves no se expongan a través del plan de consulta de diagnóstico, a menos que el usuario tenga permiso para desencriptar el conjunto de claves.

  • La encriptación a nivel de columna tiene las siguientes limitaciones cuando se usa con clasificaciones de seguridad basadas en tipos:

    • Seguridad a nivel de columna: los usuarios solo pueden desencriptar o encriptar datos en columnas a las que pueden acceder.

    • Seguridad a nivel de fila: Los usuarios solo pueden desencriptar datos en las filas a las que pueden acceder.

  • Las funciones de SQL a nivel de columna no tienen un impacto significativo en el rendimiento en comparación con el rendimiento de las funciones de encriptación sin procesar en las que los datos clave se envían en texto simple.

Antes de comenzar

Para trabajar con claves de Cloud KMS, conjuntos de claves, tablas encriptadas, funciones deterministas y no deterministas, debes hacer lo siguiente si aún no lo hiciste:

  1. Crea un proyecto de Google Cloud

  2. Crea un conjunto de datos de BigQuery.

  3. Crea un llavero de claves de Cloud KMS.

  4. Crea una clave de Cloud KMS para una columna encriptada con el nivel de protección de software o Módulo de seguridad de hardware (HSM).

  5. Otorga permisos de usuario para trabajar con claves, encriptación y desencriptación de Cloud KMS.

Ten en cuenta los siguientes conceptos, ya que se hace referencia a ellos en las siguientes secciones:

  • PROJECT_ID: El nombre del proyecto de Google Cloud.

  • DATASET_NAME: El nombre del conjunto de datos de BigQuery

  • LOCATION_ID: La ubicación del conjunto de datos de BigQuery.

  • TABLE_NAME: El nombre de la tabla de BigQuery.

  • KEY_RING_ID: El nombre del llavero de claves de Cloud KMS.

  • KEY_ID: El nombre de la clave de Cloud KMS.

  • KMS_KEY: La clave de Cloud KMS (KEK) en este formato:

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

    Aquí hay un ejemplo de una clave de Cloud KMS:

    'gcp-kms://projects/myProject/locations/us/keyRings/myKeyRing/cryptoKeys/myKeyName'
    
  • KMS_KEY_SHORT: similar a KMS_KEY, pero en este formato:

    projects/PROJECT_ID/locations/LOCATION_ID/keyRings/KEY_RING_ID/cryptoKeys/KEY_ID
  • KEYSET_DECODED: Un conjunto de claves decodificado como una secuencia BYTES. El resultado es similar al de un conjunto de claves unidas decodificadas.

    Aunque las funciones de conjunto de claves muestran conjuntos de claves como bytes, el resultado del usuario se muestra como una cadena codificada. Para convertir un conjunto de claves codificado en un conjunto de claves decodificado, consulta Cómo decodificar un conjunto de claves de Cloud KMS.

  • KEYSET_ENCODED: Un conjunto de claves codificadas como STRING. El resultado es similar al de un conjunto de claves unidas codificadas.

    Para convertir un conjunto de claves codificado en un conjunto de claves decodificado, consulta Cómo decodificar un conjunto de claves de Cloud KMS.

  • WRAPPED_KEYSET_DECODED: Un conjunto de claves unidos, decodificados como una secuencia BYTES. Este es un ejemplo de cómo se ve el resultado:

    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\...'
    

    Aunque las funciones de conjunto de claves unidas muestran conjuntos de claves unidos como bytes, el resultado del usuario se muestra como una cadena codificada. Para convertir un conjunto de claves unidas codificadas en un conjunto de claves unidos, consulta Cómo decodificar un conjunto de claves de Cloud KMS.

  • WRAPPED_KEYSET_ENCODED: Un conjunto de claves unidos y codificado como STRING Este es un ejemplo de cómo se ve el resultado:

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

    Para convertir un conjunto de claves unidas codificadas en un conjunto de claves unidos, consulta Cómo decodificar un conjunto de claves de Cloud KMS.

Administración de claves

En las siguientes secciones, se incluyen tareas comunes que puedes realizar con las claves de Cloud KMS.

Crea un conjunto de claves

Puedes crear conjuntos de claves unidas o conjuntos de claves sin procesar. Para ello, completa los pasos en las siguientes secciones.

Crea un conjunto de claves sin procesar

Ejecuta la siguiente consulta para crear un conjunto de claves con una clave de tipo DETERMINISTIC_AEAD_AES_SIV_CMAC_256.

SELECT KEYS.NEW_KEYSET('DETERMINISTIC_AEAD_AES_SIV_CMAC_256') AS raw_keyset

Crear un conjunto de claves unidas

Ejecuta la siguiente consulta para crear un conjunto de claves unidas de Cloud KMS con una clave de tipo DETERMINISTIC_AEAD_AES_SIV_CMAC_256.

SELECT KEYS.NEW_WRAPPED_KEYSET(
  KMS_KEY,
  'DETERMINISTIC_AEAD_AES_SIV_CMAC_256')

Decodificar un conjunto de claves

Aunque las funciones de SQL que muestran conjuntos de claves producen los conjuntos de claves en formato BYTES, el resultado que muestra el usuario está codificado y se muestra en formato STRING. Si deseas convertir esta cadena codificada en una secuencia de bytes decodificados que puedes usar como funciones de encriptación de claves literales, usa la siguiente consulta:

Decodificar un conjunto de claves unidas

Ejecuta la siguiente consulta para decodificar un conjunto de claves unidas de Cloud KMS.

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

Decodificar un conjunto de claves sin procesar

Ejecuta la siguiente consulta para decodificar un conjunto de claves sin procesar.

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

Vuelve a unir un conjunto de claves unidas

Ejecuta la siguiente consulta para volver a unir un conjunto de claves unidos de Cloud KMS con una clave de Cloud KMS nueva. KMS_KEY_CURRENT representa el KMS_KEY nuevo que se usa para encriptar el conjunto de claves. KMS_KEY_NEW representa el KMS_KEY nuevo que se usa para encriptar el conjunto de claves.

SELECT KEYS.REWRAP_KEYSET(
  KMS_KEY_CURRENT,
  KMS_KEY_NEW,
  WRAPPED_KEYSET_DECODED)

Rota un conjunto de claves unidas.

Ejecuta la siguiente consulta para rotar un conjunto de claves unido a Cloud KMS con una clave de tipo DETERMINISTIC_AEAD_AES_SIV_CMAC_256.

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

Genera un conjunto de claves sin procesar a partir de un conjunto de claves unidas

Algunas funciones de encriptación requieren un conjunto de claves sin procesar. Para desencriptar un conjunto de claves unidas de Cloud KMS a fin de producir un conjunto de claves sin procesar, completa los siguientes pasos.

  1. Crea un conjunto de claves unidas.

  2. En la herramienta de línea de comandos de bq, ingresa los siguientes comandos para guardar un conjunto de claves unido en un archivo llamado keyset_to_unwrap, desencriptar el conjunto de claves unido y producir el resultado en formato 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 ' ' '\'

Genera un conjunto de claves unido a partir de un conjunto de claves sin procesar

Algunas funciones de encriptación requieren un conjunto de claves unidas de Cloud KMS. Si deseas encriptar un conjunto de claves sin procesar para producir un conjunto de claves unidas, completa los siguientes pasos.

  1. Crea un conjunto de claves sin procesar.

  2. En la herramienta de línea de comandos de bq, ingresa los siguientes comandos para guardar un conjunto de claves sin procesar en un archivo llamado keyset_to_wrap, encriptar su conjunto de claves sin procesar y producir el resultado en formato 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 ' ' '\'

Genera una clave unida para una función de DLP

Para las funciones de DLP, necesitas una clave criptográfica y, luego, usarla para obtener una clave unida.

  1. Para generar una clave criptográfica nueva, en la línea de comandos, ejecuta el siguiente comando. El tamaño de la clave puede ser de 16, 24 o 32 bytes. En el siguiente ejemplo, se usa una clave de 16 bytes:

    openssl rand 16 > rand.key.16.bin
    
  2. Une la clave de 16 bytes generada con una clave de KMS. Consulta el siguiente ejemplo:

    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. Ahora puedes obtener el literal BYTES de la clave unida o el formato base64 de la clave unida.

    • Literal de bytes

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

      El resultado luce de la siguiente manera:

      \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
      
    • Formato base64

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

      El resultado luce de la siguiente manera:

      CiQA1W20a6Y5elj6xUMn4u4xPwwYVmchVmgKHhCCjSS3yNkMTpsSOQDz5Jg3vAfguw6KaZY0gP/Dh0NnKrcd6ARn9am5WzKppmp/DwW4JGGJTt8jHbNS4EjbtpD/p4SNmw==
      

Obtén la cantidad de claves de un conjunto de claves

Ejecuta la siguiente consulta para obtener la cantidad de claves en un conjunto de claves sin procesar.

  1. Si trabajas con un conjunto de claves unidas, primero genera un conjunto de claves sin procesar.

  2. Ejecuta esta consulta con el conjunto de claves sin procesar:

    SELECT KEYS.KEYSET_LENGTH(KEYSET_DECODED) as key_count;

Obtener una representación JSON de un conjunto de claves

Ejecuta la siguiente consulta para ver una representación JSON de un conjunto de claves sin procesar.

  1. Si trabajas con un conjunto de claves unidas, primero genera un conjunto de claves sin procesar.

  2. Ejecuta esta consulta con el conjunto de claves sin procesar:

    SELECT KEYS.KEYSET_TO_JSON(KEYSET_DECODED);

Encriptación y desencriptación

Puedes usar conjuntos de claves sin procesar o conjuntos de claves unidas para encriptar una columna de una tabla. También puedes optar por usar la encriptación determinista o no determinista en tus columnas. En los ejemplos de esta sección, se usan conjuntos de claves unidas, pero podrías reemplazarlos con conjuntos de claves sin procesar.

Encripta de forma determinista una columna con un conjunto de claves unido

Ejecuta la siguiente consulta para crear una tabla y almacenar un conjunto de claves unidos de Cloud KMS con encriptación determinista en una columna llamada encrypted_content.

  1. Crea un conjunto de claves unidas.

  2. Encripta una columna con el conjunto de claves unidas.

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

Desencripta de una forma determinista una columna con un conjunto de claves unidos

Ejecuta la siguiente consulta para desencriptar una columna con contenido encriptado de manera determinista mediante un conjunto de claves unidos a Cloud KMS. En esta consulta, se supone que haces referencia a una tabla con una columna llamada encrypted_content.

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

Desencripta de forma no determinista una columna con un conjunto de claves unidos

Consulta Encripta de forma determinante una columna con un conjunto de claves unidas, pero reemplaza DETERMINISTIC_ENCRYPT por AEAD.ENCRYPT. Asegúrate de que tu conjunto de claves sea del tipo AEAD_AES_GCM_256.

Desencripta de forma no determinista una columna con un conjunto de claves unidas

Consulta Desencripta de manera determinista una columna con un conjunto de claves unidas, pero reemplaza DETERMINISTIC_DECRYPT_STRING por AEAD.DECRYPT_STRING. Asegúrate de que tu conjunto de claves sea del tipo AEAD_AES_GCM_256.

¿Qué sigue?

  • Obtén más información sobre Cloud KMS. En este tema, se incluye información conceptual sobre la encriptación a nivel de columnas para Google Cloud.
  • Obtén más información sobre la encriptación AEAD para BigQuery. En este tema, se incluye información conceptual sobre la encriptación a nivel de columnas específica para BigQuery.
  • Obtén más información sobre las funciones de encriptación AEAD para BigQuery. Este tema contiene todas las funciones de SQL que puedes usar para la encriptación a nivel de columna en BigQuery.