{"schemaVersion":1,"id":"https://lucioduran.com/es/blog/homomorphic-encryption-tfhe-concrete-ml","url":"https://lucioduran.com/es/blog/homomorphic-encryption-tfhe-concrete-ml","title":"Cifrado Homomórfico en la Práctica: TFHE, Concrete-ML e Inferencia ML sobre Datos Cifrados","description":"Una guía práctica de TFHE, Concrete-ML de Zama, computación sobre datos encriptados, inferencia ML real sobre ciphertext, y la realidad honesta de la performance de encriptación homomórfica.","language":"es","datePublished":"2026-02-24","dateModified":null,"contentFormat":"text/markdown","content":"Cryptography\n\n# Cifrado Homomórfico en la Práctica: TFHE, Concrete-ML e Inferencia ML sobre Datos Cifrados\n\n2026-02-247 min lectura\n\nLucio Durán\nEngineering Manager & AI Solutions Architect\n\nTambién disponible en: [English](<https://lucioduran.com/blog/homomorphic-encryption-tfhe-concrete-ml>)\n\n## Principios del Cifrado Homomórfico\n\nLa encriptación regular es como una caja fuerte cerrada. Puede guardar cosas y sacarlas, pero no es posible modificar el contenido sin abrirla primero. La encriptación homomórfica es como una caja fuerte con brazos manipuladores incorporados, es posible hacer computaciones sobre el contenido mientras sigue encerrado adentro.\n\nFormalmente: dadas las encriptaciones E(a) y E(b), es posible computar E(a + b) y E(a × b) sin conocer a ni b. Eso es todo. Toda computación se puede descomponer en sumas y multiplicaciones, así que es Turing-completo. El catch es la performance.\n\n## TFHE: El Esquema Detrás de Concrete-ML\n\nTFHE representa datos encriptados como polinomios sobre un toro. La innovación clave es el bootstrapping rápido, TFHE puede refrescar el ruido del ciphertext en ~10ms, comparado con minutos para esquemas más viejos como BGV/BFV.\n\nEl ruido crece con cada operación:\n\n- **Suma**: El ruido crece linealmente (barato)\n- **Multiplicación**: El ruido crece exponencialmente (caro)\n- **Bootstrapping**: Resetea el ruido a un nivel fijo (~10ms pero habilita más computación)\n\n## [Concrete-ML](<https://docs.zama.ai/concrete-ml>): FHE para Machine Learning\n\n```python\nfrom concrete.ml.sklearn import LogisticRegression\nimport numpy as np\n\n# Entrenar sobre datos plaintext (este paso es ML normal)\nX_train = np.load(\"features_train.npy\")\ny_train = np.load(\"labels_train.npy\")\n\nmodel = LogisticRegression(n_bits=8) # Cuantizar a integers de 8 bits\nmodel.fit(X_train, y_train)\n\n# Evaluar en plaintext primero (sanity check)\nplaintext_accuracy = model.score(X_test, y_test)\nprint(f\"Accuracy plaintext: {plaintext_accuracy:.4f}\")\n\n# Compilar el modelo en un circuito FHE\nfhe_circuit = model.compile(X_train)\n\n# Ahora podemos hacer inferencia sobre datos encriptados\nencrypted_input = fhe_circuit.encrypt(X_test[0:1])\nencrypted_result = fhe_circuit.run(encrypted_input)\ndecrypted_result = fhe_circuit.decrypt(encrypted_result)\nprint(f\"Predicción FHE: {decrypted_result}\")\n```\n\nEl parámetro ` n_bits=8 ` es crítico. Controla la cuantización, cuántos bits representan cada valor en el modelo:\n\n| n\\_bits | Accuracy Plaintext | Tiempo Inferencia FHE | Speedup vs. 16-bit |\n| --- | --- | --- | --- |\n| 4 | 0.8912 | 45ms | 18x |\n| 6 | 0.9156 | 95ms | 8.5x |\n| 8 | 0.9234 | 180ms | 4.5x |\n| 12 | 0.9241 | 520ms | 1.6x |\n| 16 | 0.9243 | 810ms | 1x |\n\nDe 16-bit a 8-bit, perdemos 0.09% de accuracy pero ganamos 4.5x de velocidad.\n\n## El Pipeline de Scoring Crediticio\n\n```\n[App Cliente] → [Encriptar features localmente] → [Mandar ciphertext a API]\n ↓\n [Servidor Inferencia FHE (AWS)]\n ↓\n [Resultado encriptado]\n ↓\n[App Cliente] ← [Desencriptar resultado localmente] ← [Retornar predicción encriptada]\n```\n\nLos datos financieros del cliente nunca salen de su dispositivo en plaintext. Los pese es del modelo del banco están embebidos en el circuito FHE compilado, pero el cliente no puede extraerlos.\n\n```python\n# Lado servidor\nfrom concrete.ml.deployment import FHEModelServer\n\nserver = FHEModelServer(path_dir=\"./deployed_model\")\n\n@app.post(\"/predict\")\nasync def predict(request: Request):\n encrypted_input = await request.body()\n encrypted_result = server.run(\n serialized_encrypted_quantized_data=encrypted_input,\n serialized_evaluation_keys=get_evaluation_keys(request.headers[\"client-id\"]),\n )\n return Response(content=encrypted_result, media_type=\"application/octet-stream\")\n```\n\n```python\n# Lado cliente\nfrom concrete.ml.deployment import FHEModelClient\n\nclient = FHEModelClient(path_dir=\"./client_model\", key_dir=\"./keys\")\nclient.generate_private_and_evaluation_keys()\n\nclear_input = np.array([[65000, 0.32, 7, 3, 720, 12000, 0, 1]])\nencrypted_input = client.quantize_encrypt_serialize(clear_input)\nevaluation_keys = client.get_serialized_evaluation_keys()\n\n# ... mandar encrypted_input y evaluation_keys al servidor ...\n\nencrypted_result = response.content\ndecrypted_prediction = client.deserialize_decrypt_dequantize(encrypted_result)\nprint(f\"Categoría de credit score: {decrypted_prediction}\")\n```\n\n## Redes Neuronales Custom con Concrete-ML\n\n```python\nimport torch\nfrom concrete.ml.torch.compile import compile_torch_model\n\nclass CreditNet(torch.nn.Module):\n def __init__(self):\n super().__init__()\n self.fc1 = torch.nn.Linear(20, 64)\n self.fc2 = torch.nn.Linear(64, 32)\n self.fc3 = torch.nn.Linear(32, 2)\n\n def forward(self, x):\n x = torch.relu(self.fc1(x))\n x = torch.relu(self.fc2(x))\n x = self.fc3(x)\n return x\n\nmodel = CreditNet()\n# ... loop de entrenamiento ...\n\nquantized_model = compile_torch_model(\n model,\n X_train,\n n_bits=6,\n rounding_threshold_bits=6,\n)\n```\n\nLa arquitectura del modelo importa enormemente para la performance FHE. Reglas derivadas de la experiencia:\n\n1. **ReLU es caro**, cada ReLU requiere una comparación, que en FHE significa una operación de programmable bootstrapping (~10ms cada una). Una red con 96 activaciones ReLU tiene ~960ms de overhead de bootstrapping.\n2. **Profundidad sobre ancho**, una red de 3 capas con 64 neuronas por capa es mucho más lenta que una de 2 capas con 128 neuronas, porque la profundidad agrega bootstrapping secuencial.\n3. **Evitar max/min/argmax**, requieren múltiples comparaciones. Utilizar average pooling en vez de max pooling.\n4. **Batch normalization es gratis**, se fusiona en la capa lineal precedente durante compilación.\n\n## La Realidad de Performance\n\nResultados en una [AWS](<https://aws.com/>) c6i.2xlarge (8 vCPUs, sin aceleración GPU):\n\n| Modelo | Accuracy | Inferencia FHE | Plaintext | Slowdown |\n| --- | --- | --- | --- | --- |\n| Regresión Logística | 0.923 | 85ms | 0.02ms | 4,250x |\n| Árbol de Decisión (depth=5) | 0.941 | 210ms | 0.01ms | 21,000x |\n| XGBoost (10 árboles, depth=4) | 0.956 | 1,240ms | 0.08ms | 15,500x |\n| SVR Lineal | 0.917 | 72ms | 0.01ms | 7,200x |\n| NN Custom (2 capas, 64 units) | 0.948 | 3,400ms | 0.15ms | 22,667x |\n\nEse slowdown de 4,250x para regresión logística se traduce a 85ms, completamente viable para llamadas API real-time. El XGBoost en 1.2 segundos está bien para batch processing.\n\n## Lo Que NO Es Posible (Todavía)\n\nDejame ahorrarte semanas de esfuerzo tirado:\n\n- **Modelos de lenguaje grandes**: Un modelo tamaño GPT-2 tomaría horas por token.\n- **Clasificación de imágenes con CNNs profundas**: Inferencia de ResNet-50 serían ~45 minutos.\n- **Cualquier cosa con control flow dinámico**: Los circuitos FHE son estáticos.\n- **Feature spaces grandes**: 1000+ features significa 1000+ valores encriptados para procesar.\n\n## Tamaños de Claves y Transferencia de Red\n\nFHE tiene un problema de expansión de datos. Un vector de 20 features que son 160 bytes en plaintext se convierte en:\n\n```\nInput encriptado: ~42 KB\nClaves de evaluación: ~158 MB (se mandan una vez por cliente, cacheadas por el server)\nOutput encriptado: ~4 KB\n```\n\nEse es 158 MB de clave de evaluación son el elefante en la habitación. Con compresión de claves se reduce a ~40 MB, sigue siendo grande, pero manejable.\n\n## La Arquitectura que Funciona\n\n```python\n\"\"\"\n1. Cliente genera claves una vez, almacena localmente\n2. Claves de evaluación subidas al server una vez (cacheadas con TTL)\n3. Cada request de inferencia manda solo el input encriptado (~42 KB)\n4. Server retorna resultado encriptado (~4 KB)\n5. Cliente desencripta localmente\n\nTransferencia de datos total por request: ~46 KB\nBudget de latencia:\n - Red (input encriptado): 15ms\n - Inferencia FHE (server): 340ms\n - Red (resultado encriptado): 5ms\n - Desencriptación cliente: 2ms\n Total: ~362ms\n\"\"\"\n```\n\nEl tiempo de inferencia de 340ms es para el modelo XGBoost que el banco eligió, 15 árboles de profundidad 4, cuantizado a 6 bits, procesando 20 features financieros. La accuracy es 95.2% en su holdout set, comparado con 96.1% para el modelo plaintext. El banco aceptó ese tradeoff de 0.9% de accuracy porque FHE les permitió procesar datos de clientes de una institución partner sin acuerdos de compartición de datos, que hubieran tomado 8 meses de revisión legal.\n\n## Hacia Dónde Va Esto\n\nLa aceleración por hardware de TFHE viene en camino. Zama está construyendo ASICs custom que prometen 100-1000x de speedup sobre FHE en CPU. La librería HEXL de Intel ya provee 2-4x de speedup usando instrucciones AVX-512. Aceleración GPU a través de implementaciones TFHE basadas en CUDA muestra mejoras de 10-50x.\n\nCuando el hardware alcance, y va a alcanzar, porque la demanda de mercado es clara, una inferencia de 340ms va a ser 3ms. En ese punto, FHE se vuelve viable para aplicaciones real-time en general: búsqueda encriptada, sistemas de recomendación privados, diagnóstico médico confidencial.\n\nPor ahora, el punto óptimo está claro: modelos pequeños a medianos (regresión logística, gradient boosting, redes shallow) sobre datos estructurados con menos de 100 features. Si tu caso de uso encaja en ese perfil y se necesita garantías de privacidad matemáticas más fuertes que \"te prometemos que no miramos tus datos,\" la encriptación homomórfica está lista.\n\n## Preguntas frecuentes\n\n### ¿La encriptación homomórfica es realmente usable en producción?\n\nPara case es de uso específicos y acotados, sí. Inferencia ML sobre modelos pequeños (regresión logística, árboles de decisión, redes neuronales shallow) corre en el rango de 100ms-10s en hardware moderno, lo cual es aceptable para batch processing y algunos escenarios real-time. Redes neuronales grandes (BERT, clase GPT) no son factibles, tomarían horas por inferencia.\n\n### ¿Cuánto más lento es FHE comparado con computación plaintext?\n\nPara TFHE (el esquema que usa Concrete-ML), esperá 1.000x a 1.000.000x de slowdown dependiendo de la operación y el ancho de bits. La suma es barata (~1.000x). La multiplicación es cara (~10.000x). La inferencia de redes neuronales profundas compone estos costos a través de muchas multiplicaciones secuenciales.\n\n### ¿El servidor puede aprender algo sobre mis datos durante la computación FHE?\n\nNo. El servidor solo ve ciphertext durante toda la computación. No puede distinguir entre dos inputs encriptados diferentes, no puede extraer información parcial, y el resultado de la computación también está encriptado, solo el cliente con la clave secreta puede desencriptar la salida.\n\n## Tips\n\n1. **LuchoTip:** Cuantizá tu modelo a integers de 8 bits o menos antes de compilar con Concrete-ML. Las operaciones FHE sobre valores de 16 bits son ~16x más lentas que las de 8 bits porque el crecimiento del ruido es exponencial con el ancho de bits. La mayoría de los modelos ML pierden menos de 1% de accuracy yendo de float32 a int8.\n2. **LuchoTip:** Utilizar ` fhe.Compiler ` con ` show_mlir=True ` para inspeccionar la representación intermedia MLIR generada. Si ves cadenas de operaciones ` tensor.extract `, tu modelo tiene patrones de acceso a memoria que TFHE no puede paralelizar. Reestructurá para usar ops de tensor contiguos.\n3. **LuchoTip:** Comenzar con los modelos built-in de Concrete-ML (` LogisticRegression `, ` XGBClassifier `) antes de intentar redes neuronales custom. Los modelos built-in están optimizados para FHE, producen circuitos con profundidad multiplicativa mínima. Un modelo PyTorch custom compilado de forma naive va a ser 50-100x más lento.\n\n- encriptacion-homomorfica\n- tfhe\n- concrete-ml\n- zama\n- privacidad\n- computacion-encriptada\n\n[Volver al Blog](<https://lucioduran.com/es/blog>)","headings":[{"level":1,"text":"Cifrado Homomórfico en la Práctica: TFHE, Concrete-ML e Inferencia ML sobre Datos Cifrados","url":"https://lucioduran.com/es/blog/homomorphic-encryption-tfhe-concrete-ml#title"},{"level":2,"text":"Principios del Cifrado Homomórfico","url":"https://lucioduran.com/es/blog/homomorphic-encryption-tfhe-concrete-ml#principios-del-cifrado-homomrfico"},{"level":2,"text":"TFHE: El Esquema Detrás de Concrete-ML","url":"https://lucioduran.com/es/blog/homomorphic-encryption-tfhe-concrete-ml#tfhe-el-esquema-detrs-de-concrete-ml"},{"level":2,"text":"Concrete-ML: FHE para Machine Learning","url":"https://lucioduran.com/es/blog/homomorphic-encryption-tfhe-concrete-ml#concrete-ml-fhe-para-machine-learning"},{"level":2,"text":"El Pipeline de Scoring Crediticio","url":"https://lucioduran.com/es/blog/homomorphic-encryption-tfhe-concrete-ml#el-pipeline-de-scoring-crediticio"},{"level":2,"text":"Redes Neuronales Custom con Concrete-ML","url":"https://lucioduran.com/es/blog/homomorphic-encryption-tfhe-concrete-ml#redes-neuronales-custom-con-concrete-ml"},{"level":2,"text":"La Realidad de Performance","url":"https://lucioduran.com/es/blog/homomorphic-encryption-tfhe-concrete-ml#la-realidad-de-performance"},{"level":2,"text":"Lo Que NO Es Posible (Todavía)","url":"https://lucioduran.com/es/blog/homomorphic-encryption-tfhe-concrete-ml#lo-que-no-es-posible-todava"},{"level":2,"text":"Tamaños de Claves y Transferencia de Red","url":"https://lucioduran.com/es/blog/homomorphic-encryption-tfhe-concrete-ml#tamaos-de-claves-y-transferencia-de-red"},{"level":2,"text":"La Arquitectura que Funciona","url":"https://lucioduran.com/es/blog/homomorphic-encryption-tfhe-concrete-ml#la-arquitectura-que-funciona"},{"level":2,"text":"Hacia Dónde Va Esto","url":"https://lucioduran.com/es/blog/homomorphic-encryption-tfhe-concrete-ml#hacia-dnde-va-esto"},{"level":2,"text":"Preguntas frecuentes","url":"https://lucioduran.com/es/blog/homomorphic-encryption-tfhe-concrete-ml#questions"},{"level":3,"text":"¿La encriptación homomórfica es realmente usable en producción?","url":"https://lucioduran.com/es/blog/homomorphic-encryption-tfhe-concrete-ml#question-1"},{"level":3,"text":"¿Cuánto más lento es FHE comparado con computación plaintext?","url":"https://lucioduran.com/es/blog/homomorphic-encryption-tfhe-concrete-ml#question-2"},{"level":3,"text":"¿El servidor puede aprender algo sobre mis datos durante la computación FHE?","url":"https://lucioduran.com/es/blog/homomorphic-encryption-tfhe-concrete-ml#question-3"},{"level":2,"text":"Tips","url":"https://lucioduran.com/es/blog/homomorphic-encryption-tfhe-concrete-ml#article-tips"}],"sections":[{"heading":"Cifrado Homomórfico en la Práctica: TFHE, Concrete-ML e Inferencia ML sobre Datos Cifrados","level":1,"url":"https://lucioduran.com/es/blog/homomorphic-encryption-tfhe-concrete-ml","content":"Cryptography"},{"heading":"Cifrado Homomórfico en la Práctica: TFHE, Concrete-ML e Inferencia ML sobre Datos Cifrados","level":1,"url":"https://lucioduran.com/es/blog/homomorphic-encryption-tfhe-concrete-ml#title","content":"2026-02-247 min lectura\n\nLucio Durán\nEngineering Manager & AI Solutions Architect\n\nTambién disponible en: [English](<https://lucioduran.com/blog/homomorphic-encryption-tfhe-concrete-ml>)"},{"heading":"Principios del Cifrado Homomórfico","level":2,"url":"https://lucioduran.com/es/blog/homomorphic-encryption-tfhe-concrete-ml#principios-del-cifrado-homomrfico","content":"La encriptación regular es como una caja fuerte cerrada. Puede guardar cosas y sacarlas, pero no es posible modificar el contenido sin abrirla primero. La encriptación homomórfica es como una caja fuerte con brazos manipuladores incorporados, es posible hacer computaciones sobre el contenido mientras sigue encerrado adentro.\n\nFormalmente: dadas las encriptaciones E(a) y E(b), es posible computar E(a + b) y E(a × b) sin conocer a ni b. Eso es todo. Toda computación se puede descomponer en sumas y multiplicaciones, así que es Turing-completo. El catch es la performance."},{"heading":"TFHE: El Esquema Detrás de Concrete-ML","level":2,"url":"https://lucioduran.com/es/blog/homomorphic-encryption-tfhe-concrete-ml#tfhe-el-esquema-detrs-de-concrete-ml","content":"TFHE representa datos encriptados como polinomios sobre un toro. La innovación clave es el bootstrapping rápido, TFHE puede refrescar el ruido del ciphertext en ~10ms, comparado con minutos para esquemas más viejos como BGV/BFV.\n\nEl ruido crece con cada operación:\n\n- **Suma**: El ruido crece linealmente (barato)\n- **Multiplicación**: El ruido crece exponencialmente (caro)\n- **Bootstrapping**: Resetea el ruido a un nivel fijo (~10ms pero habilita más computación)"},{"heading":"Concrete-ML: FHE para Machine Learning","level":2,"url":"https://lucioduran.com/es/blog/homomorphic-encryption-tfhe-concrete-ml#concrete-ml-fhe-para-machine-learning","content":"```python\nfrom concrete.ml.sklearn import LogisticRegression\nimport numpy as np\n\n# Entrenar sobre datos plaintext (este paso es ML normal)\nX_train = np.load(\"features_train.npy\")\ny_train = np.load(\"labels_train.npy\")\n\nmodel = LogisticRegression(n_bits=8) # Cuantizar a integers de 8 bits\nmodel.fit(X_train, y_train)\n\n# Evaluar en plaintext primero (sanity check)\nplaintext_accuracy = model.score(X_test, y_test)\nprint(f\"Accuracy plaintext: {plaintext_accuracy:.4f}\")\n\n# Compilar el modelo en un circuito FHE\nfhe_circuit = model.compile(X_train)\n\n# Ahora podemos hacer inferencia sobre datos encriptados\nencrypted_input = fhe_circuit.encrypt(X_test[0:1])\nencrypted_result = fhe_circuit.run(encrypted_input)\ndecrypted_result = fhe_circuit.decrypt(encrypted_result)\nprint(f\"Predicción FHE: {decrypted_result}\")\n```\n\nEl parámetro ` n_bits=8 ` es crítico. Controla la cuantización, cuántos bits representan cada valor en el modelo:\n\n| n\\_bits | Accuracy Plaintext | Tiempo Inferencia FHE | Speedup vs. 16-bit |\n| --- | --- | --- | --- |\n| 4 | 0.8912 | 45ms | 18x |\n| 6 | 0.9156 | 95ms | 8.5x |\n| 8 | 0.9234 | 180ms | 4.5x |\n| 12 | 0.9241 | 520ms | 1.6x |\n| 16 | 0.9243 | 810ms | 1x |\n\nDe 16-bit a 8-bit, perdemos 0.09% de accuracy pero ganamos 4.5x de velocidad."},{"heading":"El Pipeline de Scoring Crediticio","level":2,"url":"https://lucioduran.com/es/blog/homomorphic-encryption-tfhe-concrete-ml#el-pipeline-de-scoring-crediticio","content":"```\n[App Cliente] → [Encriptar features localmente] → [Mandar ciphertext a API]\n ↓\n [Servidor Inferencia FHE (AWS)]\n ↓\n [Resultado encriptado]\n ↓\n[App Cliente] ← [Desencriptar resultado localmente] ← [Retornar predicción encriptada]\n```\n\nLos datos financieros del cliente nunca salen de su dispositivo en plaintext. Los pese es del modelo del banco están embebidos en el circuito FHE compilado, pero el cliente no puede extraerlos.\n\n```python\n# Lado servidor\nfrom concrete.ml.deployment import FHEModelServer\n\nserver = FHEModelServer(path_dir=\"./deployed_model\")\n\n@app.post(\"/predict\")\nasync def predict(request: Request):\n encrypted_input = await request.body()\n encrypted_result = server.run(\n serialized_encrypted_quantized_data=encrypted_input,\n serialized_evaluation_keys=get_evaluation_keys(request.headers[\"client-id\"]),\n )\n return Response(content=encrypted_result, media_type=\"application/octet-stream\")\n```\n\n```python\n# Lado cliente\nfrom concrete.ml.deployment import FHEModelClient\n\nclient = FHEModelClient(path_dir=\"./client_model\", key_dir=\"./keys\")\nclient.generate_private_and_evaluation_keys()\n\nclear_input = np.array([[65000, 0.32, 7, 3, 720, 12000, 0, 1]])\nencrypted_input = client.quantize_encrypt_serialize(clear_input)\nevaluation_keys = client.get_serialized_evaluation_keys()\n\n# ... mandar encrypted_input y evaluation_keys al servidor ...\n\nencrypted_result = response.content\ndecrypted_prediction = client.deserialize_decrypt_dequantize(encrypted_result)\nprint(f\"Categoría de credit score: {decrypted_prediction}\")\n```"},{"heading":"Redes Neuronales Custom con Concrete-ML","level":2,"url":"https://lucioduran.com/es/blog/homomorphic-encryption-tfhe-concrete-ml#redes-neuronales-custom-con-concrete-ml","content":"```python\nimport torch\nfrom concrete.ml.torch.compile import compile_torch_model\n\nclass CreditNet(torch.nn.Module):\n def __init__(self):\n super().__init__()\n self.fc1 = torch.nn.Linear(20, 64)\n self.fc2 = torch.nn.Linear(64, 32)\n self.fc3 = torch.nn.Linear(32, 2)\n\n def forward(self, x):\n x = torch.relu(self.fc1(x))\n x = torch.relu(self.fc2(x))\n x = self.fc3(x)\n return x\n\nmodel = CreditNet()\n# ... loop de entrenamiento ...\n\nquantized_model = compile_torch_model(\n model,\n X_train,\n n_bits=6,\n rounding_threshold_bits=6,\n)\n```\n\nLa arquitectura del modelo importa enormemente para la performance FHE. Reglas derivadas de la experiencia:\n\n1. **ReLU es caro**, cada ReLU requiere una comparación, que en FHE significa una operación de programmable bootstrapping (~10ms cada una). Una red con 96 activaciones ReLU tiene ~960ms de overhead de bootstrapping.\n2. **Profundidad sobre ancho**, una red de 3 capas con 64 neuronas por capa es mucho más lenta que una de 2 capas con 128 neuronas, porque la profundidad agrega bootstrapping secuencial.\n3. **Evitar max/min/argmax**, requieren múltiples comparaciones. Utilizar average pooling en vez de max pooling.\n4. **Batch normalization es gratis**, se fusiona en la capa lineal precedente durante compilación."},{"heading":"La Realidad de Performance","level":2,"url":"https://lucioduran.com/es/blog/homomorphic-encryption-tfhe-concrete-ml#la-realidad-de-performance","content":"Resultados en una [AWS](<https://aws.com/>) c6i.2xlarge (8 vCPUs, sin aceleración GPU):\n\n| Modelo | Accuracy | Inferencia FHE | Plaintext | Slowdown |\n| --- | --- | --- | --- | --- |\n| Regresión Logística | 0.923 | 85ms | 0.02ms | 4,250x |\n| Árbol de Decisión (depth=5) | 0.941 | 210ms | 0.01ms | 21,000x |\n| XGBoost (10 árboles, depth=4) | 0.956 | 1,240ms | 0.08ms | 15,500x |\n| SVR Lineal | 0.917 | 72ms | 0.01ms | 7,200x |\n| NN Custom (2 capas, 64 units) | 0.948 | 3,400ms | 0.15ms | 22,667x |\n\nEse slowdown de 4,250x para regresión logística se traduce a 85ms, completamente viable para llamadas API real-time. El XGBoost en 1.2 segundos está bien para batch processing."},{"heading":"Lo Que NO Es Posible (Todavía)","level":2,"url":"https://lucioduran.com/es/blog/homomorphic-encryption-tfhe-concrete-ml#lo-que-no-es-posible-todava","content":"Dejame ahorrarte semanas de esfuerzo tirado:\n\n- **Modelos de lenguaje grandes**: Un modelo tamaño GPT-2 tomaría horas por token.\n- **Clasificación de imágenes con CNNs profundas**: Inferencia de ResNet-50 serían ~45 minutos.\n- **Cualquier cosa con control flow dinámico**: Los circuitos FHE son estáticos.\n- **Feature spaces grandes**: 1000+ features significa 1000+ valores encriptados para procesar."},{"heading":"Tamaños de Claves y Transferencia de Red","level":2,"url":"https://lucioduran.com/es/blog/homomorphic-encryption-tfhe-concrete-ml#tamaos-de-claves-y-transferencia-de-red","content":"FHE tiene un problema de expansión de datos. Un vector de 20 features que son 160 bytes en plaintext se convierte en:\n\n```\nInput encriptado: ~42 KB\nClaves de evaluación: ~158 MB (se mandan una vez por cliente, cacheadas por el server)\nOutput encriptado: ~4 KB\n```\n\nEse es 158 MB de clave de evaluación son el elefante en la habitación. Con compresión de claves se reduce a ~40 MB, sigue siendo grande, pero manejable."},{"heading":"La Arquitectura que Funciona","level":2,"url":"https://lucioduran.com/es/blog/homomorphic-encryption-tfhe-concrete-ml#la-arquitectura-que-funciona","content":"```python\n\"\"\"\n1. Cliente genera claves una vez, almacena localmente\n2. Claves de evaluación subidas al server una vez (cacheadas con TTL)\n3. Cada request de inferencia manda solo el input encriptado (~42 KB)\n4. Server retorna resultado encriptado (~4 KB)\n5. Cliente desencripta localmente\n\nTransferencia de datos total por request: ~46 KB\nBudget de latencia:\n - Red (input encriptado): 15ms\n - Inferencia FHE (server): 340ms\n - Red (resultado encriptado): 5ms\n - Desencriptación cliente: 2ms\n Total: ~362ms\n\"\"\"\n```\n\nEl tiempo de inferencia de 340ms es para el modelo XGBoost que el banco eligió, 15 árboles de profundidad 4, cuantizado a 6 bits, procesando 20 features financieros. La accuracy es 95.2% en su holdout set, comparado con 96.1% para el modelo plaintext. El banco aceptó ese tradeoff de 0.9% de accuracy porque FHE les permitió procesar datos de clientes de una institución partner sin acuerdos de compartición de datos, que hubieran tomado 8 meses de revisión legal."},{"heading":"Hacia Dónde Va Esto","level":2,"url":"https://lucioduran.com/es/blog/homomorphic-encryption-tfhe-concrete-ml#hacia-dnde-va-esto","content":"La aceleración por hardware de TFHE viene en camino. Zama está construyendo ASICs custom que prometen 100-1000x de speedup sobre FHE en CPU. La librería HEXL de Intel ya provee 2-4x de speedup usando instrucciones AVX-512. Aceleración GPU a través de implementaciones TFHE basadas en CUDA muestra mejoras de 10-50x.\n\nCuando el hardware alcance, y va a alcanzar, porque la demanda de mercado es clara, una inferencia de 340ms va a ser 3ms. En ese punto, FHE se vuelve viable para aplicaciones real-time en general: búsqueda encriptada, sistemas de recomendación privados, diagnóstico médico confidencial.\n\nPor ahora, el punto óptimo está claro: modelos pequeños a medianos (regresión logística, gradient boosting, redes shallow) sobre datos estructurados con menos de 100 features. Si tu caso de uso encaja en ese perfil y se necesita garantías de privacidad matemáticas más fuertes que \"te prometemos que no miramos tus datos,\" la encriptación homomórfica está lista."},{"heading":"Preguntas frecuentes","level":2,"url":"https://lucioduran.com/es/blog/homomorphic-encryption-tfhe-concrete-ml#questions","content":""},{"heading":"¿La encriptación homomórfica es realmente usable en producción?","level":3,"url":"https://lucioduran.com/es/blog/homomorphic-encryption-tfhe-concrete-ml#question-1","content":"Para case es de uso específicos y acotados, sí. Inferencia ML sobre modelos pequeños (regresión logística, árboles de decisión, redes neuronales shallow) corre en el rango de 100ms-10s en hardware moderno, lo cual es aceptable para batch processing y algunos escenarios real-time. Redes neuronales grandes (BERT, clase GPT) no son factibles, tomarían horas por inferencia."},{"heading":"¿Cuánto más lento es FHE comparado con computación plaintext?","level":3,"url":"https://lucioduran.com/es/blog/homomorphic-encryption-tfhe-concrete-ml#question-2","content":"Para TFHE (el esquema que usa Concrete-ML), esperá 1.000x a 1.000.000x de slowdown dependiendo de la operación y el ancho de bits. La suma es barata (~1.000x). La multiplicación es cara (~10.000x). La inferencia de redes neuronales profundas compone estos costos a través de muchas multiplicaciones secuenciales."},{"heading":"¿El servidor puede aprender algo sobre mis datos durante la computación FHE?","level":3,"url":"https://lucioduran.com/es/blog/homomorphic-encryption-tfhe-concrete-ml#question-3","content":"No. El servidor solo ve ciphertext durante toda la computación. No puede distinguir entre dos inputs encriptados diferentes, no puede extraer información parcial, y el resultado de la computación también está encriptado, solo el cliente con la clave secreta puede desencriptar la salida."},{"heading":"Tips","level":2,"url":"https://lucioduran.com/es/blog/homomorphic-encryption-tfhe-concrete-ml#article-tips","content":"1. **LuchoTip:** Cuantizá tu modelo a integers de 8 bits o menos antes de compilar con Concrete-ML. Las operaciones FHE sobre valores de 16 bits son ~16x más lentas que las de 8 bits porque el crecimiento del ruido es exponencial con el ancho de bits. La mayoría de los modelos ML pierden menos de 1% de accuracy yendo de float32 a int8.\n2. **LuchoTip:** Utilizar ` fhe.Compiler ` con ` show_mlir=True ` para inspeccionar la representación intermedia MLIR generada. Si ves cadenas de operaciones ` tensor.extract `, tu modelo tiene patrones de acceso a memoria que TFHE no puede paralelizar. Reestructurá para usar ops de tensor contiguos.\n3. **LuchoTip:** Comenzar con los modelos built-in de Concrete-ML (` LogisticRegression `, ` XGBClassifier `) antes de intentar redes neuronales custom. Los modelos built-in están optimizados para FHE, producen circuitos con profundidad multiplicativa mínima. Un modelo PyTorch custom compilado de forma naive va a ser 50-100x más lento.\n\n- encriptacion-homomorfica\n- tfhe\n- concrete-ml\n- zama\n- privacidad\n- computacion-encriptada\n\n[Volver al Blog](<https://lucioduran.com/es/blog>)"}],"links":[{"text":"English","url":"https://lucioduran.com/blog/homomorphic-encryption-tfhe-concrete-ml"},{"text":"Concrete-ML","url":"https://docs.zama.ai/concrete-ml"},{"text":"AWS","url":"https://aws.com/"},{"text":"Volver al Blog","url":"https://lucioduran.com/es/blog"}],"structuredData":[{"@context":"https://schema.org","@graph":[{"@type":"BlogPosting","@id":"https://lucioduran.com/es/blog/homomorphic-encryption-tfhe-concrete-ml#article","mainEntityOfPage":{"@type":"WebPage","@id":"https://lucioduran.com/es/blog/homomorphic-encryption-tfhe-concrete-ml"},"headline":"Cifrado Homomórfico en la Práctica: TFHE, Concrete-ML e Inferencia ML sobre Datos Cifrados","description":"Una guía práctica de TFHE, Concrete-ML de Zama, computación sobre datos encriptados, inferencia ML real sobre ciphertext, y la realidad honesta de la performance de encriptación homomórfica.","datePublished":"2026-02-24","author":{"@type":"Person","@id":"https://lucioduran.com/#person","name":"Lucio Durán","url":"https://lucioduran.com"},"publisher":{"@type":"Person","@id":"https://lucioduran.com/#person","name":"Lucio Durán","url":"https://lucioduran.com"},"image":"https://statics.lucioduran.com/images/lucioduran-social-card.jpg","url":"https://lucioduran.com/es/blog/homomorphic-encryption-tfhe-concrete-ml","inLanguage":"es","isPartOf":{"@id":"https://lucioduran.com/blog#blog"},"articleSection":"Cryptography","keywords":"encriptacion-homomorfica, tfhe, concrete-ml, zama, privacidad, computacion-encriptada","wordCount":1152,"timeRequired":"PT7M","workTranslation":[{"@type":"BlogPosting","inLanguage":"en","url":"https://lucioduran.com/blog/homomorphic-encryption-tfhe-concrete-ml"}]},{"@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Inicio","item":"https://lucioduran.com/"},{"@type":"ListItem","position":2,"name":"Blog","item":"https://lucioduran.com/es/blog"},{"@type":"ListItem","position":3,"name":"Cifrado Homomórfico en la Práctica: TFHE, Concrete-ML e Inferencia ML sobre Datos Cifrados","item":"https://lucioduran.com/es/blog/homomorphic-encryption-tfhe-concrete-ml"}]},{"@type":"FAQPage","mainEntity":[{"@type":"Question","name":"¿La encriptación homomórfica es realmente usable en producción?","acceptedAnswer":{"@type":"Answer","text":"Para case es de uso específicos y acotados, sí. Inferencia ML sobre modelos pequeños (regresión logística, árboles de decisión, redes neuronales shallow) corre en el rango de 100ms-10s en hardware moderno, lo cual es aceptable para batch processing y algunos escenarios real-time. Redes neuronales grandes (BERT, clase GPT) no son factibles, tomarían horas por inferencia."}},{"@type":"Question","name":"¿Cuánto más lento es FHE comparado con computación plaintext?","acceptedAnswer":{"@type":"Answer","text":"Para TFHE (el esquema que usa Concrete-ML), esperá 1.000x a 1.000.000x de slowdown dependiendo de la operación y el ancho de bits. La suma es barata (~1.000x). La multiplicación es cara (~10.000x). La inferencia de redes neuronales profundas compone estos costos a través de muchas multiplicaciones secuenciales."}},{"@type":"Question","name":"¿El servidor puede aprender algo sobre mis datos durante la computación FHE?","acceptedAnswer":{"@type":"Answer","text":"No. El servidor solo ve ciphertext durante toda la computación. No puede distinguir entre dos inputs encriptados diferentes, no puede extraer información parcial, y el resultado de la computación también está encriptado, solo el cliente con la clave secreta puede desencriptar la salida."}}]}]}],"contentHash":"5cad38198efdb36970a036bbc99061de480cac5b0748d076956b3ebcce5d32c1","provenance":{"method":"Deterministic serialization of the server-rendered main element","source":"https://lucioduran.com/es/blog/homomorphic-encryption-tfhe-concrete-ml","hashAlgorithm":"sha256","hashScope":"JSON document fields before contentHash and provenance","sourceHTMLBytes":66325,"contentBytes":11744}}
