Encriptado a nivel de columna con Cloud KMS

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

Introducción

Para proporcionar una capa adicional de protección, Cloud KMS cifra tu clave de cifrado de datos (DEK) con una segunda clave de cifrado de claves (KEK). En BigQuery, hacer referencia a un conjunto de claves cifrado en lugar de a un conjunto de claves de texto sin cifrar ayuda a reducir el riesgo de que se expongan las claves. La KEK es un conjunto de claves de cifrado simétricas que se almacena de forma segura en Cloud KMS y se gestiona mediante roles y permisos de Gestión de Identidades y Accesos (IAM).

BigQuery admite funciones de cifrado deterministas y no deterministas. Con el cifrado determinista, si tanto los fragmentos de datos almacenados como los datos autenticados adicionales (opcionales) son idénticos, el texto cifrado también lo será. Esto permite la agregación y las combinaciones basadas en la columna cifrada. Con el cifrado no determinista, el texto cifrado almacenado es único independientemente de los datos cifrados, lo que evita la agrupación, la agregación y las combinaciones.

En el momento de la ejecución de la consulta, debes proporcionar la ruta del recurso de Cloud KMS de la KEK y el texto cifrado de la DEK encapsulada. BigQuery llama a Cloud KMS para desencapsular la DEK y, a continuación, usa esa clave para descifrar los datos de tu consulta. La versión sin envolver de la DEK solo se almacena en la memoria durante la consulta y, después, se destruye.

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

Casos prácticos

Estos son algunos de los casos de uso del cifrado con claves de Cloud KMS:

  • Datos encriptados externamente que deben almacenarse en BigQuery sin almacenar el conjunto de claves en texto sin formato. A continuación, puedes exportar los datos de la tabla o descifrarlos con una consulta SQL.
  • "Doble control de acceso" en los datos cifrados de BigQuery. Un usuario debe tener permiso tanto para la tabla como para la clave de cifrado para leer los datos en texto sin cifrar.
Matriz de permisos de usuario
Permiso en la tabla No tiene permiso en la tabla
Permisos de la clave Leer y descifrar datos cifrados. Sin acceso.
No tiene permisos en la clave Leer datos cifrados. Sin acceso.

Si un usuario tiene permiso para acceder a la clave de KMS y al conjunto de claves envuelto, las funciones de SQL pueden desenvolver el conjunto de claves y descifrar el texto cifrado. Los usuarios también pueden usar la API REST o la CLI de Cloud KMS para desencapsular el conjunto de claves.
En la siguiente consulta de ejemplo se usan funciones SQL de KMS para descifrar 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 práctico

Supongamos que los códigos postales se consideran información sensible. Los datos de códigos postales se pueden insertar en la tabla de BigQuery mediante la función de cifrado AEAD, lo que cifra la columna Zipcode. En este ejemplo, usamos la función AEAD.ENCRYPT con la función de gestión de conjunto de claves envuelto. La función KEYS.KEYSET_CHAIN desencripta la clave de cifrado digital con la KEK y la función AEAD.ENCRYPT transfiere la información a KMS.

La cadena de conjunto de claves para el cifrado y el descifrado asegura que la clave de cifrado de datos (DEK) se cifre o se encapsule con una KEK y se transfiera con esa KEK. La DEK envuelta se desencripta o desencapsula en la función SQL y, a continuación, se usa para encriptar o desencriptar datos.

La función no determinista AEAD puede descifrar datos cuando se accede a ellos mediante la función de la consulta que se está ejecutando en la tabla.

imagen

La función determinista AEAD puede descifrar datos cuando se accede a ellos mediante la función de la consulta que se está ejecutando en la tabla. Además, admite agregaciones y combinaciones con los datos cifrados.

imagen

Sintaxis de función no determinista

La sintaxis admitida 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 la sintaxis de las funciones AEAD.DECRYPT_BYTES, AEAD.ENCRYPT, AEAD.DECRYPT_STRING y KEYS.KEYSET_CHAIN.

Sintaxis de funciones deterministas

La sintaxis admitida 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 la sintaxis de las funciones DETERMINISTIC_DECRYPT_BYTES, DETERMINISTIC_ENCRYPT, DETERMINISTIC_DECRYPT_STRING y KEYS.KEYSET_CHAIN.

Roles y permisos

Para ver una lista de los roles de Cloud KMS, consulta Permisos y roles de Cloud KMS.

Limitaciones

El cifrado 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. No se pueden usar claves de Cloud KMS globales por motivos de fiabilidad.

  • No se puede rotar un conjunto de claves envuelto con la función KEYS.ROTATE_KEYSET.

  • Los parámetros constantes de una consulta de BigQuery son visibles para los usuarios en el plan de consulta de diagnóstico. Este factor puede afectar a 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 necesita permiso para la clave de Cloud KMS para descifrar el conjunto de claves envuelto. De esta forma, las claves no se exponen a través del plan de consulta de diagnóstico a menos que el usuario tenga permiso para descifrar el conjunto de claves.

  • El cifrado 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 descifrar o cifrar datos de las columnas a las que tienen permiso para acceder.

    • Seguridad a nivel de fila: los usuarios solo pueden descifrar los datos de las filas a las que tienen permiso para acceder.

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

Antes de empezar

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

  1. Crea un Google Cloud proyecto.

  2. Crea un conjunto de datos de BigQuery.

  3. Crea un conjunto de claves de Cloud KMS.

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

  5. Concede permisos de usuario para trabajar con claves, encriptado y desencriptado de Cloud KMS.

Ten en cuenta los siguientes conceptos, ya que se mencionan en las secciones siguientes:

  • PROJECT_ID: el nombre del proyecto de Google Cloud.

  • DATASET_NAME: el nombre del conjunto de datos de BigQuery.

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

  • TABLE_NAME: nombre de la tabla de BigQuery.

  • KEY_RING_ID: el nombre del conjunto de claves de Cloud KMS.

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

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

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

    Este es un ejemplo de clave de Cloud KMS:

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

    projects/PROJECT_ID/locations/LOCATION_ID/keyRings/KEY_RING_ID/cryptoKeys/KEY_ID
  • KEYSET_DECODED: un conjunto de claves descodificado como una secuencia BYTES. La salida es similar a la de un conjunto de claves encapsuladas decodificado.

    Aunque las funciones de conjunto de claves devuelven conjuntos de claves como bytes, el resultado para el usuario se muestra como una cadena codificada. Para convertir un conjunto de claves codificado en un conjunto de claves decodificado, consulta Decodificar un conjunto de claves de Cloud KMS.

  • KEYSET_ENCODED: un conjunto de claves codificado como STRING. La salida es similar a la de un conjunto de claves envuelto codificado.

    Para convertir un conjunto de claves codificado en un conjunto de claves decodificado, consulta Decodificar un conjunto de claves de Cloud KMS.

  • WRAPPED_KEYSET_DECODED: un conjunto de claves encapsuladas decodificado como una secuencia BYTES. Este es un ejemplo del 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 envueltas devuelven conjuntos de claves envueltos como bytes, el resultado del usuario se muestra como una cadena codificada. Para convertir un conjunto de claves envuelto codificado en un conjunto de claves envuelto decodificado, consulta Decodificar un conjunto de claves de Cloud KMS.

  • WRAPPED_KEYSET_ENCODED: un conjunto de claves encapsulado codificado como STRING. Este es un ejemplo del resultado:

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

    Para convertir un conjunto de claves envuelto codificado en un conjunto de claves envuelto decodificado, consulta Decodificar un conjunto de claves de Cloud KMS.

Gestión de claves

En las siguientes secciones se describen las tareas habituales que puedes realizar con las claves de Cloud KMS.

Crear un conjunto de claves

Puedes crear conjuntos de claves encapsuladas o conjuntos de claves sin formato. Para ello, sigue los pasos que se indican en las siguientes secciones.

Crear 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 encapsulado

Ejecuta la siguiente consulta para crear un conjunto de claves envuelto 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 SQL que devuelven conjuntos de claves producen los conjuntos de claves en formato BYTES, el resultado que se muestra al usuario se codifica y se muestra en formato STRING. Si quiere convertir esta cadena codificada en una secuencia de bytes decodificada que pueda usar como funciones de cifrado de claves literales, utilice la siguiente consulta.

Decodificar un conjunto de claves encapsulado

Ejecuta la siguiente consulta para decodificar un conjunto de claves envuelto 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 formato.

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

Volver a envolver un conjunto de claves envueltas

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

SELECT KEYS.REWRAP_KEYSET(
  KMS_KEY_CURRENT,
  KMS_KEY_NEW,
  WRAPPED_KEYSET_DECODED)

Rotar un conjunto de claves encapsuladas

Ejecuta la siguiente consulta para rotar un conjunto de claves envuelto de 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')

Generar un conjunto de claves sin procesar a partir de un conjunto de claves encapsulado

Algunas funciones de cifrado requieren un conjunto de claves sin formato. Para descifrar un conjunto de claves envuelto en Cloud KMS y obtener un conjunto de claves sin formato, sigue estos pasos.

  1. Crea un conjunto de claves encapsulado.

  2. En la herramienta de línea de comandos bq, introduce los siguientes comandos para guardar un conjunto de claves envuelto en un archivo llamado keyset_to_unwrap, descifrar el conjunto de claves envuelto y generar la salida 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 ' ' '\'

Generar un conjunto de claves encapsulado a partir de un conjunto de claves sin procesar

Algunas funciones de cifrado requieren un conjunto de claves envuelto de Cloud KMS. Para cifrar un conjunto de claves sin formato y obtener un conjunto de claves envuelto, sigue estos pasos.

  1. Crea un conjunto de claves sin formato.

  2. En la herramienta de línea de comandos bq, introduce los siguientes comandos para guardar un conjunto de claves sin formato en un archivo llamado keyset_to_wrap, cifrar el conjunto de claves sin formato y generar la salida 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 ' ' '\'

Generar una clave encapsulada para una función de DLP

Para usar las funciones de DLP, necesitas una clave criptográfica y, a continuación, usarla para obtener una clave encapsulada.

  1. Para generar una nueva clave criptográfica, 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. Encapsula 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 envuelta o el formato base64 de la clave envuelta.

    • Literal de bytes

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

      La salida tiene este aspecto:

      \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
      

      La salida tiene este aspecto:

      CiQA1W20a6Y5elj6xUMn4u4xPwwYVmchVmgKHhCCjSS3yNkMTpsSOQDz5Jg3vAfguw6KaZY0gP/Dh0NnKrcd6ARn9am5WzKppmp/DwW4JGGJTt8jHbNS4EjbtpD/p4SNmw==
      

Obtener el número de claves de un conjunto de claves

Ejecuta la siguiente consulta para obtener el número de claves de un conjunto de claves sin formato.

  1. Si trabajas con un conjunto de claves envuelto, primero genera un conjunto de claves sin envolver.

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

  1. Si trabajas con un conjunto de claves envuelto, primero genera un conjunto de claves sin envolver.

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

    SELECT KEYS.KEYSET_TO_JSON(KEYSET_DECODED);

Cifrado y descifrado

Puedes usar conjuntos de claves sin envolver o conjuntos de claves envueltos para cifrar una columna de una tabla. También puedes elegir si quieres usar un cifrado determinista o no determinista en tus columnas. En los ejemplos de esta sección se usan conjuntos de claves envueltos, pero puedes sustituirlos por conjuntos de claves sin formato.

Cifrar de forma determinista una columna con un conjunto de claves encapsuladas

Ejecuta la siguiente consulta para crear una tabla y almacenar un conjunto de claves envuelto en Cloud KMS con cifrado determinista en una columna llamada encrypted_content.

  1. Crea un conjunto de claves encapsulado.

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

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

Descifrar de forma determinista una columna con un conjunto de claves envueltas

Ejecuta la siguiente consulta para descifrar de forma determinista una columna que contenga contenido cifrado mediante un conjunto de claves encapsulado por Cloud KMS. En esta consulta se da por hecho 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

Encriptar de forma no determinista una columna con un conjunto de claves envueltas

Consulta Cifrar de forma determinista una columna con un conjunto de claves envuelto, pero sustituye DETERMINISTIC_ENCRYPT por AEAD.ENCRYPT. Asegúrate de que tu conjunto de claves sea de tipo AEAD_AES_GCM_256.

Desencriptar de forma no determinista una columna con un conjunto de claves envuelto

Consulta Descifrar de forma determinista una columna con un conjunto de claves envuelto, pero sustituye DETERMINISTIC_DECRYPT_STRING por AEAD.DECRYPT_STRING. Asegúrate de que tu conjunto de claves sea de tipo AEAD_AES_GCM_256.

Siguientes pasos