Danadata 001 - Encriptación asimétrica con GTM y Google Cloud Platform
Añade la capa de privacidad más potente posible a la recogida y gestión de tus datos
Quizá este artículo tenía más sentido en visiondefunnel que aquí, porque puede que sea lo más técnico que he escrito nunca. Pero también es el post con mayor impacto en la privacidad que puedo haber hecho, así que le veía sentido dejarlo por aquí. Además, ya sabéis que estoy intentando recolectar la mayor cantidad de donaciones posibles para ayudar a mi alrededor por el desastre de la DANA, así que todo lo que pueda proporcionaros en recompensa bienvenido sea. Y antes de que se me olvide:
Lo que vamos a ver hoy aquí es un sistema seguro para la transmisión de información bancaria (como ejemplo) desde el cliente hacia un servidor en Google Tag Manager (GTM) Server-Side utilizando encriptación asimétrica y GCP. Este flujo garantiza que la información bancaria o de salud enviada desde el cliente se mantenga protegida y solo pueda ser descifrada por el servidor, protegiendo los datos de accesos no autorizados.
El proceso incluye los siguientes pasos:
Generación de claves públicas y privadas para encriptación asimétrica.
Encriptación de la información en el cliente utilizando AES y RSA.
Desencriptación de los datos en el servidor mediante Google Cloud Function.
Configuración de un cliente personalizado en GTM Server-Side para interpretar y procesar los datos.
1. Generación de claves públicas y privadas
Cuando se trabaja con información altamente sensible, como datos bancarios, es fundamental implementar métodos de encriptación robustos para proteger los datos tanto en tránsito como en el almacenamiento. Utilizaremos encriptación asimétrica con un par de claves RSA para garantizar que solo el servidor pueda descifrar la información enviada desde el cliente. La clave pública se utilizará en el lado del cliente para cifrar los datos, mientras que la clave privada, que nunca se expone públicamente, permanecerá en el servidor para descifrar la información. Este método es ideal para proteger detalles financieros como números de cuenta, montos de transacciones, y otra información bancaria que deba mantenerse segura.
1.1 Generación de Claves RSA
Para generar el par de claves RSA, podemos utilizar openssl
, una herramienta de criptografía popular que permite generar claves de manera segura. RSA es un algoritmo de encriptación asimétrica ampliamente utilizado que permite cifrar y descifrar datos mediante dos claves diferentes: una clave pública y una clave privada. La clave pública, como su nombre lo indica, se distribuye abiertamente y se usa para cifrar los datos. Sin embargo, solo la clave privada puede descifrar la información cifrada, lo que garantiza que los datos solo puedan ser leídos en el servidor donde reside esta clave.
Ejecuta estos comandos en tu terminal para generar el par de claves RSA:
# Genera una clave privada de 2048 bits (puedes ajustar el tamaño si deseas más seguridad)
openssl genpkey -algorithm RSA -out private_key.pem -pkeyopt rsa_keygen_bits:2048
# Genera la clave pública asociada a partir de la clave privada
openssl rsa -pubout -in private_key.pem -out public_key.pem
Con el primer comando, generamos la clave privada, que se guarda en un archivo llamado private_key.pem
. Esta clave privada tiene una longitud de 2048 bits, lo cual es una longitud estándar que ofrece un buen equilibrio entre seguridad y rendimiento. El segundo comando toma la clave privada y genera su clave pública correspondiente, que se guarda en un archivo llamado public_key.pem
. Asegúrate de no compartir la clave privada y de protegerla adecuadamente.
1.2 Almacenamiento seguro de claves
Para maximizar la seguridad de la clave privada, es recomendable almacenarla en un servicio de administración de secretos, como Google Secret Manager de Google Cloud Platform. Secret Manager permite gestionar claves y otros secretos de manera segura, proporcionando acceso controlado desde aplicaciones en la nube y asegurando que la clave privada nunca se exponga directamente en el servidor. Puedes subir la clave privada a Google Secret Manager utilizando el siguiente comando de gcloud
:
# Guarda la clave privada en Google Secret Manager
gcloud secrets create PRIVATE_KEY --data-file="private_key.pem"
También lo puedes hacer en la interfaz dentro de Secret Manager:
Una vez almacenada, la clave privada estará disponible solo para el servidor y solo podrá ser accedida cuando el servidor tenga las credenciales adecuadas. Esto es crucial cuando trabajamos con información bancaria o de salud, ya que una fuga de la clave privada permitiría a terceros descifrar los datos sensibles.
En cuanto a la clave pública, esta se coloca en el cliente, en un lugar de fácil acceso dentro del código JavaScript que se ejecutará en el navegador. La clave pública no necesita el mismo nivel de protección que la clave privada, ya que solo se usa para cifrar y no permite descifrar los datos. Esta característica de las claves RSA es lo que permite la transmisión segura de información sensible.
1.3 Por qué utilizar encriptación asimétrica
El principal beneficio de usar encriptación asimétrica es la seguridad añadida que proporciona en comparación con los métodos de encriptación simétrica, donde la misma clave se utiliza para cifrar y descifrar. Con RSA, solo el servidor que tiene la clave privada puede descifrar los datos cifrados con la clave pública, lo que hace que el método sea ideal para aplicaciones web que deben proteger datos sensibles en tránsito. En este caso, como estamos tratando con información bancaria, es fundamental que los datos estén protegidos tanto en el lado del cliente como durante el tránsito al servidor.
Casos de uso para encriptación asimétrica
El uso de encriptación asimétrica RSA es especialmente útil en casos donde se deben transmitir datos de alta sensibilidad. Algunos ejemplos de casos de uso comunes incluyen:
Información bancaria: Números de cuentas, tarjetas de crédito, montos de transacciones, y otros datos relacionados con transacciones financieras.
Datos médicos: Información sobre la historia clínica del paciente, resultados de laboratorio o cualquier otro dato confidencial relacionado con la salud.
Contraseñas y credenciales: Aunque no es tan común como otros métodos, la encriptación asimétrica puede utilizarse para proteger credenciales y contraseñas sensibles.
Una vez que tenemos el par de claves RSA, estamos listos para continuar con el siguiente paso: cifrar los datos en el cliente usando la clave pública y enviar de forma segura los datos bancarios al servidor.
2. Encriptación de datos bancarios en el Cliente
Para proteger la transmisión de datos bancarios desde el cliente hasta el servidor, usaremos una combinación de AES y RSA. Esta combinación proporciona una seguridad adicional al aprovechar los puntos fuertes de cada algoritmo: AES se usa para cifrar los datos rápidamente y RSA para proteger la clave AES. Con este enfoque, los datos bancarios, como números de cuenta, identificadores de transacción y montos, se cifran con AES, y luego la clave AES se cifra con RSA usando la clave pública generada previamente.
2.1 Preparación y configuración de encriptación en el Cliente
Para implementar este proceso en el cliente, emplearemos la biblioteca Forge para JavaScript, que es popular para realizar encriptaciones en aplicaciones web. Forge nos permite implementar tanto AES como RSA, por lo que es una herramienta práctica para este tipo de implementación.
Código de encriptación en el cliente
A continuación, se muestra un ejemplo de código que realiza los siguientes pasos:
Generación de la clave AES: Forge genera una clave de 16 bytes (AES-128) y un IV (vector de inicialización) único. La clave AES se utiliza para cifrar el mensaje de forma rápida y segura.
Cifrado de datos bancarios: El payload de datos sensibles, en este caso la información bancaria, se cifra con AES.
Cifrado de la clave AES con RSA: Usamos la clave pública para cifrar la clave AES con RSA, lo que garantiza que solo el servidor pueda descifrar la clave y, en consecuencia, los datos cifrados.
Transmisión de los datos cifrados: Finalmente, los datos cifrados, la clave AES cifrada y el IV se envían al servidor.
Este es el script completo en el cliente:
<script src="https://cdnjs.cloudflare.com/ajax/libs/forge/0.10.0/forge.min.js"></script>
<script>
// 1. Genera una clave AES y un IV de 16 bytes
var aesKey = forge.random.getBytesSync(16);
var iv = forge.random.getBytesSync(16);
// 2. Define el payload de información bancaria sensible
var payload = JSON.stringify({
transaction_id: "TX123456789",
account_number: "1234 5678 9012 3456",
transaction_amount: 250.75
});
// 3. Cifra el payload con AES
var cipher = forge.cipher.createCipher('AES-CBC', aesKey);
cipher.start({ iv: iv });
cipher.update(forge.util.createBuffer(payload));
cipher.finish();
var encryptedPayload = forge.util.encode64(cipher.output.bytes());
// 4. Cifra la clave AES con RSA y la clave pública
var publicKeyPem = "-----BEGIN PUBLIC KEY-----MIIBIjANBgkq...END PUBLIC KEY-----";
var publicKey = forge.pki.publicKeyFromPem(publicKeyPem);
var encryptedKey = forge.util.encode64(publicKey.encrypt(aesKey, 'RSA-OAEP'));
// 5. Envía los datos cifrados al servidor
fetch("https://<tu-servidor-gtm>/encrypted", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
data: encryptedPayload,
key: encryptedKey,
iv: forge.util.encode64(iv)
})
});
</script>
Beneficios
Usar una combinación de AES y RSA proporciona una capa de seguridad adicional. AES es un algoritmo de cifrado rápido y eficiente para datos de gran tamaño, como registros bancarios. RSA, en cambio, es ideal para cifrar pequeños fragmentos de datos (como claves) y garantiza que solo el servidor puede desencriptar la clave AES. Esta configuración asegura que los datos bancarios, incluso si son interceptados en tránsito, no se puedan leer o manipular sin la clave privada del servidor.
Casos de uso para la encriptación en el Cliente
Esta configuración es especialmente útil en aplicaciones bancarias o financieras, donde el cliente necesita enviar información confidencial al servidor. Ejemplos incluyen:
Aplicaciones bancarias móviles: Donde los usuarios envían información sobre transferencias, balances y detalles de cuentas.
Portales de pago en línea: Para proteger los datos de tarjetas de crédito o débito durante el procesamiento de pagos.
Aplicaciones de salud: Donde se envían datos sensibles de salud que deben permanecer seguros.
Esta implementación permite enviar los datos con la seguridad de que solo el servidor puede descifrarlos, protegiendo así la confidencialidad y la integridad de la información. En la siguiente sección, configuraremos una función de Google Cloud que actúe como un intermediario seguro para recibir estos datos cifrados y descifrarlos utilizando la clave privada.
3. Desencriptación de datos bancarios en Google Cloud
Una vez que los datos cifrados llegan al servidor, necesitamos un proceso para descifrarlos y extraer la información bancaria. Para ello, configuraremos una Google Cloud Function que actuará como el punto de entrada en el servidor. Esta función recibirá la solicitud de datos cifrados, recuperará la clave privada almacenada en Google Secret Manager y la usará para descifrar la clave AES con RSA. Luego, utilizaremos la clave AES para descifrar el payload original que contiene los datos bancarios.
3.1 Configuración de la Cloud Function
La Cloud Function se encargará de tres tareas principales:
Recuperar la clave privada almacenada de forma segura en Google Secret Manager.
Descifrar la clave AES usando RSA y la clave privada.
Descifrar el payload cifrado con la clave AES y el IV enviado desde el cliente.
Este es el código de la Cloud Function que ejecutará estos pasos:
import base64
import json
import functions_framework
from google.cloud import secretmanager
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP, AES
# Configura el cliente de Google Secret Manager
client = secretmanager.SecretManagerServiceClient()
# Recupera la clave privada del Secret Manager
def get_private_key():
secret_name = "projects/<PROJECT_ID>/secrets/PRIVATE_KEY/versions/latest"
response = client.access_secret_version(name=secret_name)
return response.payload.data.decode("UTF-8")
# Función principal que procesa la solicitud HTTP
@functions_framework.http
def decrypt_and_process_banking_data(request):
# Recupera el JSON de la solicitud
request_json = request.get_json()
# Descifra la clave AES usando RSA y la clave privada
encrypted_key = base64.b64decode(request_json['key'])
private_key = RSA.import_key(get_private_key())
cipher_rsa = PKCS1_OAEP.new(private_key)
aes_key = cipher_rsa.decrypt(encrypted_key)
# Descifra el payload con AES y el IV
iv = base64.b64decode(request_json['iv'])
encrypted_data = base64.b64decode(request_json['data'])
cipher_aes = AES.new(aes_key, AES.MODE_CBC, iv)
decrypted_data = cipher_aes.decrypt(encrypted_data)
# Remueve el padding PKCS7 del payload
unpadded_data = decrypted_data[:-decrypted_data[-1]]
# Convertir los datos desencriptados a JSON
banking_data = json.loads(unpadded_data)
# Procesa la información bancaria recibida (ej. guarda en la base de datos o envía al GTM Server-Side)
print("Datos bancarios procesados:", banking_data)
# Devuelve una respuesta de éxito
return {"success": True, "data": banking_data}
3.2 Seguridad en el Proceso de desencriptación
Este enfoque de desencriptación asegura que los datos confidenciales solo puedan ser leídos por el servidor que posee la clave privada. Además, al almacenar la clave privada en Google Secret Manager, se garantiza que no esté expuesta directamente en el código o en el entorno de ejecución. Este diseño asegura que incluso en caso de interceptación de los datos en tránsito, estos sean ilegibles para cualquier tercero.
Con esta Cloud Function configurada, ahora estamos listos para enviar los datos descifrados a GTM Server-Side para un procesamiento adicional y posterior almacenamiento o uso en la lógica de negocio.
4. GTM Server-Side como distribuidor
Para capturar los datos que llegan al path /encrypted
y procesarlos como Event Data en Google Tag Manager Server-Side (GTM SS), usaremos una plantilla de cliente existente que permite convertir cualquier solicitud en datos de evento en el contenedor GTM. En este caso, adaptaremos la plantilla basada en el artículo de este enlace, que ya está diseñada para procesar datos de solicitudes personalizadas y transformarlas en eventos GTM.
Esta plantilla en GTM SS es clave, ya que:
Captura las solicitudes entrantes en un path específico (
/encrypted
).Transforma los datos recibidos en Event Data, para que puedan ser usados en etiquetas y activadores dentro del contenedor GTM.
4.1 Configuración del Cliente en GTM Server-Side
Descargar la plantilla de cliente: La plantilla está diseñada para parsear datos de solicitudes personalizadas y transformarlos en datos de evento. Si no está disponible, puedes copiar el código directamente desde el artículo y añadirlo como una plantilla en GTM SS.
Personalización de la plantilla: Asegúrate de que la plantilla esté configurada para escuchar en el path
/encrypted
. Esto permite que el cliente capture solo las solicitudes dirigidas a este path, lo cual es útil para asegurar que solo se procesen los datos bancarios cifrados enviados desde el cliente.Event Data en SSGTM: La plantilla convertirá automáticamente los datos recibidos en un evento GTM que contendrá los campos de la solicitud. Los datos se transformarán en variables de evento (
Event Data
) en el contenedor GTM, haciendo que cada campo del JSON recibido esté disponible para usarse en etiquetas y variables.
4.2 Configuración de variables y triggers
Una vez que el cliente convierte los datos en Event Data, puedes configurar variables y activadores para manejar los datos dentro del contenedor GTM:
Variables personalizadas: Crea variables dentro de GTM SS para extraer información específica, como
transaction_id
,account_number
otransaction_amount
, usando los nombres de los campos en Event Data. Estas variables permiten un acceso sencillo a los datos y la posibilidad de usarlos en etiquetas o activadores.Triggers personalizados: Define activadores que se activen solo cuando los datos específicos estén presentes o cumplan ciertas condiciones. Por ejemplo, un activador puede configurarse para ejecutarse solo cuando el evento contiene
transaction_id
, asegurando que las etiquetas solo se activen con datos válidos.
4.3 Envío de datos
Con los datos disponibles en Event Data, puedes crear etiquetas para enviarlos a sistemas externos. Por ejemplo:
Etiqueta de registro de transacciones: Configura una etiqueta que envíe los datos de la transacción a una API de análisis financiero, o a un sistema de almacenamiento seguro. La etiqueta puede configurarse para enviar un
POST
con los datos bancarios recibidos.Etiqueta de confirmación de seguridad: Puedes crear una etiqueta que confirme que los datos bancarios se han procesado correctamente y responder con un mensaje de éxito o seguimiento en el sistema de origen.
5. Mantenimiento y seguridad en el sistema de encriptación
Finalmente, es crucial implementar un plan de mantenimiento y monitoreo para asegurar la continuidad y la seguridad del sistema de transmisión de datos. Dado que los datos bancarios son altamente sensibles, cualquier vulnerabilidad podría tener implicaciones significativas.
5.1 Revisiones y auditorías de seguridad
Implementa revisiones de seguridad periódicas para asegurarte de que todas las claves de encriptación y procesos de transmisión de datos funcionan de forma segura y conforme a los estándares. Algunas medidas recomendadas son:
Rotación de claves: Programa una rotación periódica de las claves RSA (tanto pública como privada) almacenadas en Google Secret Manager. Esto ayuda a mitigar riesgos en caso de que una clave esté comprometida.
Auditoría de secretos: Verifica el acceso y uso de los secretos en Google Secret Manager, asegurándote de que solo el servidor autorizado tenga acceso a la clave privada. Google Secret Manager ofrece auditoría detallada, lo que facilita la supervisión y el cumplimiento normativo.
Revisión de permisos: Asegúrate de que las funciones y el contenedor de GTM Server-Side tengan permisos mínimos y limitados únicamente a las operaciones necesarias. Esto reduce el riesgo de exposición accidental de datos sensibles.
5.2 Monitoreo de Logs
Es importante configurar un sistema de monitoreo de logs que permita rastrear cualquier acceso o error relacionado con la transmisión de datos bancarios. Google Cloud ofrece herramientas como Cloud Logging para monitorizar la actividad en la Cloud Function. Configura alertas automáticas para cualquier evento inusual, como:
Errores de desencriptación repetidos, que pueden indicar intentos de acceso no autorizados.
Fallos en el envío de datos a sistemas externos, lo que podría señalar problemas de red o de autorización.
5.3 Mejora continua
Mantener el sistema actualizado con las últimas prácticas de seguridad es esencial para prevenir posibles vulnerabilidades. Realiza pruebas periódicas para evaluar la robustez del cifrado y el sistema de transmisión de datos. Además, mantente al tanto de actualizaciones en las bibliotecas de encriptación utilizadas, como Forge en el cliente y PyCrypto en la Cloud Function, ya que las nuevas versiones pueden ofrecer mejoras en seguridad y rendimiento.
5.4 Cumplimiento regulatorio
Para asegurar el cumplimiento con las normativas financieras y de privacidad de datos, como GDPR o PCI DSS, es importante documentar y auditar el flujo de datos bancarios. Esto incluye mantener un registro claro de:
Quién tiene acceso a las claves de encriptación.
Cuándo y cómo se transmiten los datos.
Las políticas de retención y eliminación de datos.
Mantener una documentación actualizada del flujo de datos, configuraciones de seguridad y revisiones es fundamental para el cumplimiento normativo y facilita las auditorías.
Conclusión
Este sistema asegura que la información bancaria enviada desde el cliente esté protegida mediante encriptación asimétrica, garantizando que solo el servidor tenga la capacidad de descifrar y procesar los datos. Al combinar encriptación RSA y AES en el cliente, desencriptación segura en Google Cloud Function y una estructura robusta de GTM Server-Side, se logra un flujo de datos seguro y escalable para aplicaciones bancarias o de salud.
Este enfoque proporciona una solución segura y confiable que permite la transmisión de datos bancarios y otros tipos de información sensible de una manera que cumple con altos estándares de seguridad y privacidad. Este sistema también se adapta a la integración con herramientas de análisis y otros sistemas externos, lo que facilita su aplicación en diversas plataformas empresariales sin comprometer la seguridad de los datos sensibles.