Compartir a través de


Derivación de subclave y cifrado autenticado en ASP.NET Core

La mayoría de las claves del anillo de claves contendrán alguna forma de entropía y tendrán información algorítmica que indica "Cifrado en modo CBC + validación HMAC" o "Cifrado + validación de GCM". En estos casos, nos referimos a la entropía incrustada como material de clave maestra (o KM) para esta clave, y realizamos una función de derivación de claves para derivar las claves que se usarán para las operaciones criptográficas reales.

Nota:

Las claves son abstractas y es posible que una implementación personalizada no se comporte como se indica a continuación. Si la clave proporciona su propia implementación de IAuthenticatedEncryptor en lugar de usar uno de nuestros generadores integrados, el mecanismo descrito en esta sección ya no se aplica.

Derivación de subclaves y datos autenticados adicionales

La IAuthenticatedEncryptor interfaz actúa como interfaz principal para todas las operaciones de cifrado autenticadas. Su Encrypt método toma dos búferes: texto no cifrado y additionalAuthenticatedData (AAD). El flujo de contenido de texto no cifrado no ha cambiado la llamada a IDataProtector.Protect, pero el sistema genera el AAD y consta de tres componentes:

  1. Encabezado mágico de 32 bits 09 F0 C9 F0 que identifica esta versión del sistema de protección de datos.

  2. Identificador de clave de 128 bits.

  3. Cadena de longitud variable formada a partir de la secuencia de propósito que creó el IDataProtector, que está llevando a cabo esta operación.

Dado que el AAD es único para la tupla formada por los tres componentes, podemos usarlo para derivar nuevas claves a partir de KM en lugar de usar KM en todas nuestras operaciones criptográficas. Para cada llamada a IAuthenticatedEncryptor.Encrypt, se realiza el siguiente proceso de derivación de claves:

( K_E, K_H ) = SP800_108_CTR_HMACSHA512(K_M, AAD, contextHeader || keyModifier)

Aquí, llamamos al NIST SP800-108 KDF en modo de contador (consulte NIST SP800-108, Sec. 5.1) con los siguientes parámetros:

  • Clave de derivación (KDK) = K_M

  • PRF = HMACSHA512

  • label = datosAutenticadosAdicionales

  • context = contextHeader || keyModifier

El encabezado de contexto es de longitud variable y básicamente sirve como huella digital de los algoritmos para los que derivamos K_E y K_H. El modificador de clave es una cadena de 128 bits generada aleatoriamente para cada llamada a Encrypt y sirve para garantizar una probabilidad abrumadora de que KE y KH sean únicas para esta operación de cifrado de autenticación específica, incluso si todas las demás entradas de KDF son constantes.

En el caso del cifrado en modo CBC + operaciones de validación de HMAC, | K_E | es la longitud de la clave de cifrado de bloque simétrico y | K_H | es el tamaño de resumen de la rutina HMAC. Para las operaciones de cifrado y validación de GCM, | K_H | = 0.

Cifrado en modo CBC + validación de HMAC

Una vez K_E generado a través del mecanismo anterior, generamos un vector de inicialización aleatorio y ejecutamos el algoritmo de cifrado de bloques simétricos para descifrar el texto no cifrado. A continuación, el vector de inicialización y el texto cifrado se ejecutan a través de la rutina HMAC inicializada con la clave K_H para generar el MAC. Este proceso y el valor devuelto se representan gráficamente debajo.

Proceso y retorno en modo CBC

output:= keyModifier || iv || E_cbc (K_E,iv,data) || HMAC(K_H, iv || E_cbc (K_E,iv,data))

Nota:

La IDataProtector.Protect implementación anteponerá el encabezado mágico y el identificador de clave a la salida antes de devolverlo al autor de la llamada. Dado que el encabezado mágico y el identificador de clave forman parte implícita de AAD y, dado que el modificador de clave se alimenta como entrada para KDF, esto significa que cada byte de la carga final devuelta se autentica mediante el MAC.

Cifrado del modo galois/contador + validación

Una vez K_E generado a través del mecanismo anterior, generamos un nonce de 96 bits aleatorio y ejecutamos el algoritmo de cifrado de bloques simétricos para descifrar el texto no cifrado y generar la etiqueta de autenticación de 128 bits.

Proceso en modo GCM y devolución

output := keyModifier || nonce || E_gcm (K_E,nonce,data) || authTag

Nota:

Aunque GCM admite de forma nativa el concepto de AAD, seguimos enviando AAD solo al KDF original y optamos por pasar una cadena vacía a GCM como su parámetro AAD. La razón de esto es doble. En primer lugar, para apoyar la agilidad, no queremos usar K_M directamente como clave de cifrado. Además, GCM impone requisitos de unicidad muy estrictos en sus entradas. La probabilidad de que la rutina de cifrado GCM se invoque en dos o más conjuntos distintos de datos de entrada con el mismo par (clave, nonce) no debe superar 2^-32. Si corregimos K_E, no podemos realizar más de 2^32 operaciones de cifrado antes de encontrarnos con el problema del límite de 2^-32. Esto puede parecer un gran número de operaciones, pero un servidor web de alto tráfico puede manejar 4 mil millones de solicitudes en pocos días, bien dentro del ciclo de vida normal de estas claves. Para mantener la conformidad con el límite de probabilidad de 2^-32, seguimos usando un modificador de clave de 128 bits y un nonce de 96 bits, que amplía radicalmente el recuento de operaciones utilizables para cualquier determinado K_M. Para simplificar el diseño, compartimos el trayecto del código KDF entre las operaciones CBC y GCM. Dado que el AAD ya se considera en el KDF, no es necesario pasarlo a la rutina de GCM.