Consigna y contexto
Un servicio de configuración multi-inquilino debe cifrar valores confidenciales de base de datos. Cada inquilino tiene una clave lógica independiente; la plataforma debe rotar las claves raíz, leer textos cifrados antiguos y detectar textos cifrados copiados entre inquilinos o registros. Utiliza crypto/hpke de Go 1.26 para diseñar el sobre, el flujo de cifrado/descifrado, las versiones de clave, la vinculación de contexto y la migración. La habilidad principal es la composición correcta de la API criptográfica y el diseño del ciclo de vida, por lo que esta es una pregunta de coding.
Qué evalúa el entrevistador
Primero, si comprendes los roles de HPKE KEM, KDF y AEAD y distingues la encapsulación de clave pública del cifrado simétrico de datos.
Segundo, si puedes elegir el modo Base, PSK o Auth y explicar el límite entre las claves de autenticación y las claves de confidencialidad.
Tercero, si el inquilino, el propósito, el conjunto de algoritmos (suite) y la versión están vinculados en info o AAD para evitar el descifrado cruzado de contextos.
Cuarto, si la rotación, las lecturas de versiones antiguas, la revocación y el recifrado están diseñados sin tratar un número de versión como secreto.
Quinto, si las pruebas de alteración, reproducción (replay), aleatoriedad, información de fallos e interoperabilidad validan la implementación.
Preguntas para aclarar primero
- ¿Es suficiente la confidencialidad o el remitente debe estar autenticado criptográficamente?
- ¿Quién posee la clave pública del destinatario y existen requisitos de KMS, HSM y auditoría?
- ¿Cuánto tiempo permanecen los textos cifrados antiguos y se requiere un recifrado en segundo plano?
- ¿Se permite que las relaciones entre el inquilino y la clave de configuración sean metadatos visibles?
- ¿Se requiere descifrado en otros lenguajes o recuperación fuera de línea?
- ¿Deben poder distinguirse las claves faltantes, las versiones no admitidas y los fallos de autenticación?
Una respuesta en 30 segundos
“Fijo una suite de RFC 9180 y Go 1.26. El servicio conserva la clave privada del destinatario de cada inquilino, mientras que las aplicaciones encapsulan con su clave pública. El sobre almacena la suite y la versión de la clave; el inquilino y el propósito se vinculan en info y el inquilino, la clave y la versión del registro en el AAD de AEAD. El descifrado selecciona la clave privada antigua según la versión del sobre. Las nuevas escrituras utilizan la versión rotada y un trabajo en segundo plano recifra los datos antiguos. Elijo Auth solo cuando se requiere una prueba del remitente. Las pruebas cubren alteraciones, intercambios entre inquilinos, reproducción, aleatoriedad, versiones antiguas y vectores entre lenguajes.”
Solución detallada
Paso 1: Separar las capas del sobre
HPKE establece un secreto compartido con KEM, deriva claves con KDF y cifra el mensaje con AEAD. El sobre almacena la suite, la versión de la clave, el material encapsulado, el nonce o texto cifrado serializado y los metadatos públicos. Las claves raíz y privadas del destinatario permanecen en KMS o HSM, nunca en el texto cifrado ni en los registros de la aplicación.
Paso 2: Elegir el modo y la semántica de identidad
El modo Base proporciona cifrado de clave pública del destinatario sin autenticación del remitente. PSK agrega una clave precompartida. Auth utiliza una clave del remitente para autenticar el origen. Una identidad de inicio de sesión de la plataforma no significa que HPKE haya autenticado al remitente; la autorización y el modo criptográfico son capas separadas.
Paso 3: Vincular el contexto
Vincula el protocolo, el servicio, la versión y el propósito en info. Vincula el ID de inquilino, la clave de configuración y la versión del registro en el AAD de AEAD cuando esos campos viajen con el sobre y deban permanecer intactos. El descifrado vuelve a calcular las mismas entradas, por lo que un intercambio de inquilino, propósito o versión fallará la autenticación.
envelope = suite_id | key_version | encapsulated_key | aad_fields | ciphertext
info = "config-envelope/v1" | tenant_scope | purpose
aad = tenant_id | config_key | record_versionPaso 4: Diseñar el ciclo de vida de las claves
Cada versión de clave tiene tiempo de creación, estado, alcance de descifrado y política de destrucción. Publica la nueva clave pública antes de cambiar las escrituras; las lecturas seleccionan la clave privada antigua según la versión del sobre. Mantén las versiones antiguas en modo de solo lectura hasta que se completen el recifrado y las comprobaciones de auditoría, luego revócalas.
Paso 5: Gestionar la reproducción y la serialización
AEAD detecta alteraciones pero no impide que se vuelva a enviar un texto cifrado antiguo válido. Si la configuración tiene una versión o una secuencia monotónica, la capa de negocio comprueba la versión esperada. Utiliza campos explícitos de longitud, versión y suite, y rechaza suites desconocidas, truncamientos o campos duplicados.
Paso 6: Definir el límite de error
Devuelve externamente un fallo de descifrado uniforme. Audita internamente el motivo estructurado y la versión de la clave, nunca las claves privadas, el texto en plano o el texto cifrado completo. Distinguir una clave faltante, un formato no admitido y un fallo de autenticación ayuda a las operaciones, pero los llamadores que no sean de confianza no deben inferir la existencia del inquilino o de la clave a partir del tiempo de respuesta o de los mensajes.
Paso 7: Crear pruebas y migración
Prueba vectores fijos de RFC, aleatoriedad, alteración de un solo byte, AAD entre inquilinos, lecturas de versiones antiguas, rotación concurrente, fallos tras la revocación y fragmentación de mensajes grandes. Los sistemas en varios lenguajes necesitan serialización y vectores compartidos. Los servicios anteriores a 1.26 utilizan un envoltorio de compatibilidad o una compuerta de actualización; las API experimentales no deben entrar en producción por accidente.
Una respuesta de muestra de alta calidad
“Utilizo HPKE como capa de sobre: KEM y KDF establecen y derivan una clave compartida, y AEAD protege el texto en plano de la configuración. El sobre contiene la suite, la versión de la clave, el material encapsulado y el texto cifrado; el inquilino, el propósito, la clave y la versión del registro se vinculan a través de info y AAD para detener las copias entre inquilinos. Base proporciona únicamente confidencialidad para el destinatario; elijo Auth o una firma externa cuando se requiere una prueba del remitente. La rotación escribe primero la nueva versión, mantiene la antigua en solo lectura, recifra en segundo plano y luego la revoca tras la verificación. AEAD no previene la reproducción, por lo que se comprueba la versión del negocio. Las claves privadas permanecen en KMS/HSM, y las pruebas incluyen alteraciones, revocaciones, errores y vectores entre lenguajes.”
Errores comunes
- Tratar Base como autenticación del remitente → el destinatario no puede probar quién lo envió → utiliza Auth o una firma externa.
- Colocar el inquilino solo en metadatos visibles → un atacante puede intercambiar el texto cifrado entre inquilinos → vincúlalo en
infoo AAD. - Eliminar la clave antigua inmediatamente después de la rotación → los datos históricos se vuelven ilegibles → mantén una ventana de solo lectura y recifra primero.
- Asumir que AEAD previene la reproducción → se puede volver a enviar un texto cifrado antiguo válido → comprueba una versión de negocio o secuencia.
- Almacenar claves privadas en configuraciones o registros → se rompe el límite de cifrado → utiliza KMS/HSM y el principio de privilegio mínimo.
- Inventar un formato binario sin versión → la migración y el rechazo de suites se vuelven inseguros → codifica explícitamente versión, longitud y suite.
- Devolver errores de descifrado detallados → puede filtrarse la existencia del inquilino o la clave → errores externos uniformes y auditoría interna.
- Probar solo el caso exitoso → las fallas de alteración y de versiones antiguas llegan a producción → agrega pruebas de vectores, contextos cruzados y revocación.
Preguntas de seguimiento
Pregunta de seguimiento 1: ¿Por qué no cifrar todo el texto en plano directamente con RSA o ECDH?
HPKE compone explícitamente KEM, KDF y AEAD, lo cual resulta adecuado para encapsular una clave de sesión simétrica y manejar mensajes grandes. El cifrado directo de clave pública para texto en plano arbitrario propicia un uso indebido de longitud, aleatoriedad y modos.
Pregunta de seguimiento 2: ¿Cuándo es apropiado el modo Auth?
Utiliza Auth cuando el destinatario necesite una prueba criptográfica de que participó una clave de remitente conocida. Si solo se requiere la confidencialidad del destinatario, no agregues una clave de autenticación no administrada.
Pregunta de seguimiento 3: ¿Cuál es la diferencia entre info y AAD?
info participa en la derivación de claves y define el contexto del protocolo. AAD permanece visible pero está protegido en integridad por AEAD, lo que lo hace adecuado para metadatos del sobre que deben coincidir durante el descifrado.
Pregunta de seguimiento 4: ¿Cómo se recifra de manera segura?
Lee la versión antigua y escribe la nueva en una transacción idempotente o un flujo de trabajo reintentable. Solo revoca la clave antigua después de que el nuevo texto cifrado supere las verificaciones de auditoría y de descifrado con lectura de comprobación.
Pregunta de seguimiento 5: ¿Cómo se evita que un texto cifrado se mueva a otro registro?
Coloca el inquilino, la clave de configuración, la versión del registro y el propósito en AAD, y reconstruye AAD a partir de los valores actuales de la base de datos durante las lecturas. Un sobre copiado fallará entonces su etiqueta de autenticación.
Pregunta de seguimiento 6: ¿Proporciona HPKE confidencialidad directa (forward secrecy)?
La propiedad depende del ciclo de vida de la clave y del modo. Con una clave privada de destinatario estática y de larga duración, la protección histórica del texto cifrado depende de esa clave. Una confidencialidad directa más sólida necesita claves efímeras, rotación, destrucción y sesiones a nivel de protocolo; el nombre de la API por sí solo no la proporciona.