AEAD y nonces explicados en términos sencillos (ejemplo de cifrado simétrico utilizando Libsodium)

1

Después de casi 4 días de trabajo, finalmente conseguí que Libsodium crypto_aead_xchacha20poly1305_ietf_encrypt funcione y produzca el mismo resultado en JavaScript y PHP .

Pero estoy confundido.

El PHPDoc describe los parámetros como:

* @param string $plaintext Message to be encrypted
* @param string $assocData Authenticated Associated Data (unencrypted)
* @param string $nonce Number to be used only Once
* @param string $key Encryption key
* @return string

Mientras JSDoc solicita estos parámetros:

/**
 * @param {string | Uint8Array} message
 * @param {string | Uint8Array} additional_data
 * @param {string | Uint8Array} secret_nonce
 * @param {Uint8Array} public_nonce
 * @param {Uint8Array} key
 * @param {uint8array} outputFormat
 * @returns {Uint8Array}
 */

Mis preguntas:

  1. Parece que un nonce es un tipo de sal de un tamaño específico que solo se puede usar una vez porque, de lo contrario, pueden ocurrir ataques de repetición. ¿Puedes ayudarme a entender esto más lejos? Wikipedia y otros sitios se complicaron demasiado.
  2. Para un lego, ¿cómo describiría AEAD y cómo utilizar el parámetro "Datos asociados autenticados (sin cifrar)"?
  3. En la función PHP (que copié de enlace ), usa el nonce no solo como un nonce sino también como el Los "Datos asociados autenticados" reducen la seguridad en comparación con algún otro enfoque en el que el remitente agregaría algún valor aquí y comunicaría fuera de línea al receptor lo que el receptor debería esperar que sea este valor.
  4. ¿Por qué la versión de JavaScript acepta parámetros diferentes? JS solicita un secret_nonce separado de public_nonce, y para que los resultados coincidan con la función de PHP, debo proporcionar valores idénticos para secret_nonce y public_nonce. Entonces, ¿cuál es el punto?

P.S. Aquí están las funciones:

JavaScript:

/**
 * @param {string} message
 * @param {Uint8Array} key
 * @returns {Uint8Array}
 */
function encryptAndPrependNonce(message, key) {
    let nonce = sodium.randombytes_buf(nonceBytes);
    var encrypted = sodium.crypto_aead_xchacha20poly1305_ietf_encrypt(message, nonce, nonce, nonce, key);
    var nonce_and_ciphertext = concatTypedArray(Uint8Array, nonce, encrypted);
    return nonce_and_ciphertext;
}

PHP:

/**
 * @link https://paragonie.com/b/kIqqEWlp3VUOpRD7 (from the 'simpleEncrypt' function)
 * @param string $message
 * @param string $keyAsBinary
 * @return string
 */
public static function encryptAndPrependNonce($message, $keyAsBinary) {
    $nonce = random_bytes(self::NONCE_BYTES); // NONCE = Number to be used ONCE, for each message        
    $encrypted = ParagonIE_Sodium_Compat::crypto_aead_xchacha20poly1305_ietf_encrypt($message, $nonce, $nonce, $keyAsBinary);
    return $nonce . $encrypted;
}
    
pregunta Ryan 13.08.2018 - 15:02
fuente

1 respuesta

2
  

Parece que un nonce es un tipo de sal de un tamaño específico que solo se puede usar una vez porque de lo contrario pueden ocurrir ataques de repetición. ¿Puedes ayudarme a entender esto más lejos? Wikipedia y otros sitios se complicaron demasiado.

Se requiere un nonce para asegurarse de que el texto cifrado no filtre información. Se requiere tal nonce o IV para cualquier cifrado seguro de CPA, ya que de lo contrario el texto simple repetido puede filtrar información.

Para los cifrados de flujo, tal como lo utilizan la mayoría de las construcciones AEAD, si no todas, se requiere un nonce único; de lo contrario, filtrará todo el texto sin formato. También puede comprometer la clave hash (interna), lo que lleva a un compromiso total de la propiedad de autenticidad (!!!).

  

Para un lego, ¿cómo describiría AEAD y cómo utilizar el parámetro "Datos asociados autenticados (sin cifrar)"?

El AAD puede contener cualquier información que deba ser autenticada pero que no necesita ser o no puede ser confidencial. Por ejemplo: puede ser una buena idea proteger el campo del destinatario de un mensaje en un protocolo, pero si está oculto, es posible que la red no pueda llegar al destino en primer lugar.

  

En la función PHP (que copié de enlace ), usa el nonce no solo como un nonce sino también como los "Datos asociados autenticados" reducen la seguridad en comparación con algún otro enfoque en el que el remitente agregaría algún valor aquí y comunicaría fuera de línea al receptor lo que el receptor debería esperar que sea este valor?

Agregar el nonce a la AAD nunca aumenta la seguridad , porque los cifrados AEAD ya lo incluyen en el cálculo de la etiqueta de autenticación .

Cuánto "algún valor" agrega a la seguridad depende, por supuesto, del protocolo y los posibles vectores de ataque. Tenga en cuenta que un nonce debe ser único, pero es posible que su protocolo no lo use contra ataques de reproducción. En ese caso, agregar datos al AAD puede ayudar a prevenir tales ataques.

Tenga en cuenta que AEAD ya requiere una clave secreta y un nonce; no es necesario agregar otra clave o nonce (para asegurar el cifrado en sí). Agregar la identidad de las odas remitentes / receptoras generalmente tiene sentido.

  

¿Por qué la versión de JavaScript acepta parámetros diferentes? JS solicita un secret_nonce separado de public_nonce, y para que los resultados coincidan con la función de PHP, debo proporcionar valores idénticos para secret_nonce y public_nonce. Entonces, ¿cuál es el punto?

La biblioteca JS en realidad no usa el parámetro de nonce secreto llamado nsec . Si lea la documentación , siempre encontrará:

  

nsec no se usa en esta construcción en particular y siempre debe ser NULL.

Tenga en cuenta que poly1305 requiere dos claves , de las cuales la segunda "clave" se trata como un número. Sin embargo, la segunda clave, que generalmente se indica como r , se puede generar de forma pseudoaleatoria como se especifica aquí .

Generalmente, se prefiere usar una sola clave para el cifrado solo, por lo que las implementaciones probablemente no admitirán la versión de clave dual y generarán r internamente. Pero pienso , es por eso que el parámetro nsec existe en primer lugar.

Para GCM / GHASH, la clave también se crea internamente de manera universal.

    
respondido por el Maarten Bodewes 15.08.2018 - 16:33
fuente

Lea otras preguntas en las etiquetas