Tokenización de Datos es una técnica de seguridad que reemplaza datos sensibles con tokens no sensibles que no tienen valor intrínseco, manteniendo la funcionalidad mientras se protege la información confidencial.

¿Qué es la Tokenización de Datos?

La tokenización es un proceso que convierte datos sensibles (como números de tarjeta de crédito, SSN, etc.) en tokens que no revelan información sobre los datos originales, pero mantienen la capacidad de referenciarlos de forma segura.

Características Principales

Protección de Datos

  • Irreversible: Los tokens no pueden ser revertidos a datos originales
  • Sin Valor: Los tokens no tienen valor intrínseco
  • Seguro: Protección robusta de datos sensibles
  • Funcional: Mantiene la funcionalidad del sistema

Cumplimiento Normativo

  • PCI DSS: Cumplimiento de estándares de tarjetas de pago
  • GDPR: Cumplimiento de regulaciones de privacidad
  • HIPAA: Cumplimiento de regulaciones de salud
  • SOX: Cumplimiento de regulaciones financieras

Escalabilidad

  • Alto Volumen: Manejo de grandes volúmenes de datos
  • Rendimiento: Alto rendimiento en procesamiento
  • Distribuido: Implementación distribuida
  • Cloud: Compatible con entornos en la nube

Tipos de Tokenización

Tokenización Reversible

  • Mapeo: Mapeo bidireccional entre datos y tokens
  • Recuperación: Posibilidad de recuperar datos originales
  • Uso: Casos donde se necesita acceso a datos originales
  • Seguridad: Menor seguridad que irreversible

Tokenización Irreversible

  • Hash: Tokens generados mediante funciones hash
  • No Recuperable: No se pueden recuperar datos originales
  • Uso: Casos donde no se necesita acceso a datos originales
  • Seguridad: Mayor seguridad

Tokenización con Formato

  • FPE: Format-Preserving Encryption
  • Formato: Mantiene el formato de los datos originales
  • Compatibilidad: Compatible con sistemas existentes
  • Uso: Sistemas que requieren formato específico

Implementación Técnica

Tokenización Simple

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import hashlib
import secrets
import base64
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC

class SimpleTokenization:
    def __init__(self, master_key):
        self.master_key = master_key
        self.token_map = {}
        self.reverse_map = {}
    
    def tokenize(self, sensitive_data):
        """Tokenizar datos sensibles"""
        # Generar token único
        token = self.generate_token()
        
        # Almacenar mapeo (en producción, usar base de datos segura)
        self.token_map[token] = sensitive_data
        self.reverse_map[sensitive_data] = token
        
        return token
    
    def detokenize(self, token):
        """Detokenizar token"""
        if token not in self.token_map:
            raise ValueError("Token no válido")
        
        return self.token_map[token]
    
    def generate_token(self):
        """Generar token único"""
        # Generar token aleatorio
        random_bytes = secrets.token_bytes(16)
        token = base64.urlsafe_b64encode(random_bytes).decode('utf-8')
        
        # Asegurar unicidad
        while token in self.token_map:
            random_bytes = secrets.token_bytes(16)
            token = base64.urlsafe_b64encode(random_bytes).decode('utf-8')
        
        return token

# Ejemplo de uso
tokenizer = SimpleTokenization("master_key_123")
credit_card = "4111-1111-1111-1111"
token = tokenizer.tokenize(credit_card)
print(f"Token: {token}")
original = tokenizer.detokenize(token)
print(f"Original: {original}")

Tokenización con Cifrado

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.primitives import padding
import os

class EncryptedTokenization:
    def __init__(self, master_key):
        self.master_key = master_key
        self.cipher = algorithms.AES(self.master_key)
    
    def tokenize(self, sensitive_data):
        """Tokenizar con cifrado"""
        # Generar IV aleatorio
        iv = os.urandom(16)
        
        # Cifrar datos
        cipher = Cipher(self.cipher, modes.CBC(iv))
        encryptor = cipher.encryptor()
        
        # Aplicar padding
        padder = padding.PKCS7(128).padder()
        padded_data = padder.update(sensitive_data.encode())
        padded_data += padder.finalize()
        
        # Cifrar
        encrypted_data = encryptor.update(padded_data) + encryptor.finalize()
        
        # Crear token (IV + datos cifrados)
        token = base64.urlsafe_b64encode(iv + encrypted_data).decode('utf-8')
        
        return token
    
    def detokenize(self, token):
        """Detokenizar con descifrado"""
        # Decodificar token
        token_data = base64.urlsafe_b64decode(token.encode('utf-8'))
        
        # Extraer IV y datos cifrados
        iv = token_data[:16]
        encrypted_data = token_data[16:]
        
        # Descifrar
        cipher = Cipher(self.cipher, modes.CBC(iv))
        decryptor = cipher.decryptor()
        
        decrypted_data = decryptor.update(encrypted_data) + decryptor.finalize()
        
        # Remover padding
        unpadder = padding.PKCS7(128).unpadder()
        unpadded_data = unpadder.update(decrypted_data)
        unpadded_data += unpadder.finalize()
        
        return unpadded_data.decode('utf-8')

# Ejemplo de uso
encrypted_tokenizer = EncryptedTokenization(os.urandom(32))
credit_card = "4111-1111-1111-1111"
token = encrypted_tokenizer.tokenize(credit_card)
print(f"Token cifrado: {token}")
original = encrypted_tokenizer.detokenize(token)
print(f"Original: {original}")

Tokenización con Formato (FPE)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
class FormatPreservingTokenization:
    def __init__(self, master_key):
        self.master_key = master_key
    
    def tokenize_credit_card(self, credit_card):
        """Tokenizar tarjeta de crédito manteniendo formato"""
        # Remover espacios y guiones
        clean_card = credit_card.replace(' ', '').replace('-', '')
        
        # Verificar formato (16 dígitos)
        if not clean_card.isdigit() or len(clean_card) != 16:
            raise ValueError("Formato de tarjeta inválido")
        
        # Generar token manteniendo formato
        token = self.generate_credit_card_token(clean_card)
        
        # Formatear como tarjeta de crédito
        formatted_token = f"{token[:4]}-{token[4:8]}-{token[8:12]}-{token[12:16]}"
        
        return formatted_token
    
    def generate_credit_card_token(self, credit_card):
        """Generar token de tarjeta de crédito"""
        # Usar hash para generar token determinístico
        hash_input = f"{credit_card}{self.master_key}".encode()
        hash_output = hashlib.sha256(hash_input).hexdigest()
        
        # Convertir a dígitos
        token_digits = []
        for i in range(0, len(hash_output), 2):
            hex_pair = hash_output[i:i+2]
            digit = int(hex_pair, 16) % 10
            token_digits.append(str(digit))
        
        # Asegurar que comience con dígito válido para tarjeta
        if token_digits[0] == '0':
            token_digits[0] = '4'  # Visa
        
        return ''.join(token_digits[:16])

# Ejemplo de uso
fpe_tokenizer = FormatPreservingTokenization("master_key_123")
credit_card = "4111-1111-1111-1111"
token = fpe_tokenizer.tokenize_credit_card(credit_card)
print(f"Token con formato: {token}")

Aplicaciones Específicas

PCI DSS Compliance

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
class PCITokenization:
    def __init__(self, pci_compliant_vault):
        self.vault = pci_compliant_vault
        self.sensitive_fields = ['pan', 'cvv', 'expiry_date']
    
    def tokenize_payment_data(self, payment_data):
        """Tokenizar datos de pago para PCI DSS"""
        tokenized_data = {}
        
        for field in self.sensitive_fields:
            if field in payment_data:
                # Tokenizar campo sensible
                token = self.vault.store_and_tokenize(
                    payment_data[field], 
                    field_type=field
                )
                tokenized_data[f"{field}_token"] = token
            else:
                tokenized_data[field] = payment_data[field]
        
        return tokenized_data
    
    def detokenize_payment_data(self, tokenized_data):
        """Detokenizar datos de pago"""
        original_data = {}
        
        for field in self.sensitive_fields:
            token_field = f"{field}_token"
            if token_field in tokenized_data:
                # Detokenizar campo
                original_value = self.vault.retrieve_from_token(
                    tokenized_data[token_field]
                )
                original_data[field] = original_value
            else:
                original_data[field] = tokenized_data[field]
        
        return original_data

# Ejemplo de uso
class PCIVault:
    def store_and_tokenize(self, data, field_type):
        # Implementar almacenamiento seguro
        token = f"tok_{field_type}_{secrets.token_hex(8)}"
        return token
    
    def retrieve_from_token(self, token):
        # Implementar recuperación segura
        return "original_data"

pci_vault = PCIVault()
pci_tokenizer = PCITokenization(pci_vault)

payment_data = {
    'pan': '4111-1111-1111-1111',
    'cvv': '123',
    'expiry_date': '12/25',
    'cardholder_name': 'John Doe'
}

tokenized = pci_tokenizer.tokenize_payment_data(payment_data)
print(f"Datos tokenizados: {tokenized}")

Tokenización de PII

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
class PIITokenization:
    def __init__(self, master_key):
        self.master_key = master_key
        self.pii_patterns = {
            'ssn': r'\d{3}-\d{2}-\d{4}',
            'email': r'[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}',
            'phone': r'\d{3}-\d{3}-\d{4}'
        }
    
    def tokenize_pii(self, text):
        """Tokenizar PII en texto"""
        import re
        
        tokenized_text = text
        
        for pii_type, pattern in self.pii_patterns.items():
            matches = re.finditer(pattern, text)
            for match in matches:
                original = match.group()
                token = self.generate_pii_token(original, pii_type)
                tokenized_text = tokenized_text.replace(original, token)
        
        return tokenized_text
    
    def generate_pii_token(self, pii_data, pii_type):
        """Generar token para PII"""
        # Generar token determinístico
        hash_input = f"{pii_data}{pii_type}{self.master_key}".encode()
        hash_output = hashlib.sha256(hash_input).hexdigest()
        
        # Crear token con formato apropiado
        if pii_type == 'ssn':
            token = f"XXX-XX-{hash_output[:4]}"
        elif pii_type == 'email':
            token = f"user_{hash_output[:8]}@example.com"
        elif pii_type == 'phone':
            token = f"XXX-XXX-{hash_output[:4]}"
        else:
            token = f"TOKEN_{hash_output[:8]}"
        
        return token

# Ejemplo de uso
pii_tokenizer = PIITokenization("master_key_123")
text_with_pii = "John Doe's SSN is 123-45-6789 and email is john@example.com"
tokenized_text = pii_tokenizer.tokenize_pii(text_with_pii)
print(f"Texto tokenizado: {tokenized_text}")

Mejores Prácticas

Seguridad

  • Almacenamiento Seguro: Almacenar tokens en sistemas seguros
  • Acceso Controlado: Control estricto de acceso a tokens
  • Auditoría: Auditoría completa de operaciones
  • Cifrado: Cifrar tokens en reposo y tránsito

Gestión

  • Políticas: Políticas claras de tokenización
  • Procedimientos: Procedimientos definidos
  • Monitoreo: Monitoreo continuo
  • Respuesta: Respuesta a incidentes

Cumplimiento

  • Estándares: Cumplimiento de estándares
  • Regulaciones: Cumplimiento de regulaciones
  • Documentación: Documentación completa
  • Verificación: Verificación regular

Herramientas Comerciales

Vault de HashiCorp

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import hvac

class VaultTokenization:
    def __init__(self, vault_url, token):
        self.client = hvac.Client(url=vault_url, token=token)
    
    def tokenize_with_vault(self, data, path="transit"):
        """Tokenizar usando Vault"""
        try:
            response = self.client.secrets.transit.encrypt_data(
                name='tokenization-key',
                plaintext=data
            )
            return response['data']['ciphertext']
        except Exception as e:
            print(f"Error tokenizando con Vault: {e}")
            return None
    
    def detokenize_with_vault(self, token, path="transit"):
        """Detokenizar usando Vault"""
        try:
            response = self.client.secrets.transit.decrypt_data(
                name='tokenization-key',
                ciphertext=token
            )
            return response['data']['plaintext']
        except Exception as e:
            print(f"Error detokenizando con Vault: {e}")
            return None

# Ejemplo de uso
vault_tokenizer = VaultTokenization('http://localhost:8200', 'my-token')
token = vault_tokenizer.tokenize_with_vault("sensitive_data")
original = vault_tokenizer.detokenize_with_vault(token)

Conceptos Relacionados

Referencias