Esta traducción fue generada mediante aprendizaje automático y puede no ser 100% precisa. Ver versión en inglés

Transporte NTCP2

Transporte TCP basado en Noise para enlaces entre routers

Descripción general

NTCP2 es un protocolo de acuerdo de claves autenticado que mejora la resistencia de NTCP a diversas formas de identificación automatizada y ataques.

NTCP2 está diseñado para la flexibilidad y coexistencia con NTCP. Puede ser soportado en el mismo puerto que NTCP, o en un puerto diferente, o sin soporte simultáneo de NTCP en absoluto. Ver la sección de Información de Router Publicada a continuación para más detalles.

Al igual que con otros transportes I2P, NTCP2 se define únicamente para el transporte punto a punto (router a router) de mensajes I2NP. No es una tubería de datos de propósito general.

NTCP2 es compatible desde la versión 0.9.36. Consulta Prop111 para la propuesta original, incluyendo la discusión de antecedentes e información adicional.

Marco del Protocolo Noise

NTCP2 utiliza el Noise Protocol Framework NOISE (Revisión 33, 2017-10-04). Noise tiene propiedades similares al protocolo Station-To-Station STS , que es la base del protocolo SSU . En la terminología de Noise, Alice es el iniciador y Bob es el respondedor.

NTCP2 se basa en el protocolo Noise Noise_XK_25519_ChaChaPoly_SHA256. (El identificador real para la función de derivación de clave inicial es “Noise_XKaesobfse+hs2+hs3_25519_ChaChaPoly_SHA256” para indicar las extensiones de I2P - ver la sección KDF 1 más abajo) Este protocolo Noise utiliza las siguientes primitivas:

  • Patrón de Handshake: XK Alice transmite su clave a Bob (X) Alice ya conoce la clave estática de Bob (K)
  • Función DH: X25519 X25519 DH con una longitud de clave de 32 bytes como se especifica en RFC-7748 .
  • Función de Cifrado: ChaChaPoly AEAD_CHACHA20_POLY1305 como se especifica en RFC-7539 sección 2.8. Nonce de 12 bytes, con los primeros 4 bytes establecidos en cero.
  • Función Hash: SHA256 Hash estándar de 32 bytes, ya utilizado extensamente en I2P.

Adiciones al Framework

NTCP2 define las siguientes mejoras a Noise_XK_25519_ChaChaPoly_SHA256. Estas generalmente siguen las pautas en NOISE sección 13.

  1. Las claves efímeras en texto plano se ofuscan con cifrado AES usando una clave e IV conocidos. 2) Se añade relleno aleatorio en texto plano a los mensajes 1 y 2. El relleno en texto plano se incluye en el cálculo del hash del handshake (MixHash). Ver las secciones KDF a continuación para el mensaje 2 y la parte 1 del mensaje 3. Se añade relleno AEAD aleatorio al mensaje 3 y a los mensajes de la fase de datos. 3) Se añade un campo de longitud de trama de dos bytes, como se requiere para Noise sobre TCP, y como en obfs4. Esto se usa solo en los mensajes de la fase de datos. Las tramas AEAD de los mensajes 1 y 2 tienen longitud fija. La trama AEAD de la parte 1 del mensaje 3 tiene longitud fija. La longitud de la trama AEAD de la parte 2 del mensaje 3 se especifica en el mensaje 1. 4) El campo de longitud de trama de dos bytes se ofusca con SipHash-2-4, como en obfs4. 5) El formato de carga útil se define para los mensajes 1, 2, 3 y la fase de datos. Por supuesto, estos no están definidos en el framework.

Mensajes

Todos los mensajes NTCP2 tienen una longitud menor o igual a 65537 bytes. El formato del mensaje se basa en mensajes Noise, con modificaciones para el encuadre y la indistinguibilidad. Las implementaciones que utilizan bibliotecas Noise estándar pueden necesitar preprocesar los mensajes recibidos hacia/desde el formato de mensaje Noise. Todos los campos cifrados son textos cifrados AEAD.

La secuencia de establecimiento es la siguiente:

Alice Bob

SessionRequest -------------------> <------------------- SessionCreated SessionConfirmed ----------------->

Usando la terminología de Noise, la secuencia de establecimiento y datos es la siguiente: (Propiedades de Seguridad del Payload desde Noise )

XK(s, rs): Authentication Confidentiality

<- s \... -> e, es 0 2 <- e, ee 2 1 -> s, se 2 5 <- 2 5

Una vez que se ha establecido una sesión, Alice y Bob pueden intercambiar mensajes de datos.

Todos los tipos de mensaje (SessionRequest, SessionCreated, SessionConfirmed, Data y TimeSync) se especifican en esta sección.

Algunas notaciones:

- RH_A = Router Hash for Alice (32 bytes)
- RH_B = Router Hash for Bob (32 bytes)

Cifrado Autenticado

Hay tres instancias separadas de cifrado autenticado (CipherStates). Una durante la fase de handshake, y dos (transmisión y recepción) para la fase de datos. Cada una tiene su propia clave de una KDF.

Los datos cifrados/autenticados se representarán como

+----+----+----+----+----+----+----+----+

|                                       |

    + + | Encrypted and authenticated data | ~ . . . ~ | | +----+----+----+----+----+----+----+----+

ChaCha20/Poly1305

Formato de datos cifrado y autenticado.

Entradas a las funciones de cifrado/descifrado:

k :: 32 byte cipher key, as generated from KDF



nonce :: Counter-based nonce, 12 bytes.

Starts at 0 and incremented for each message. First four bytes are always zero. Last eight bytes are the counter, little-endian encoded. Maximum value is 2**64 - 2. Connection must be dropped and restarted after it reaches that value. The value 2**64 - 1 must never be sent.

ad :: In handshake phase:

Associated data, 32 bytes. The SHA256 hash of all preceding data. In data phase: Zero bytes

data :: Plaintext data, 0 or more bytes

Salida de la función de cifrado, entrada de la función de descifrado:

+----+----+----+----+----+----+----+----+

[|Obfs Len |](##SUBST##|Obfs Len |) | +----+----+ + | ChaCha20 encrypted data | ~ . . . ~ | | +----+----+----+----+----+----+----+----+ | Poly1305 Message Authentication Code | + (MAC) + | 16 bytes | +----+----+----+----+----+----+----+----+

    Obfs Len :: Length of (encrypted data + MAC) to follow, 16 - 65535

    :   Obfuscation using SipHash (see below) Not used in message 1 or 2, or message 3 part 1, where the length is fixed Not used in message 3 part 1, as the length is specified in message 1

    encrypted data :: Same size as plaintext data, 0 - 65519 bytes

    MAC :: Poly1305 message authentication code, 16 bytes

Para ChaCha20, lo que se describe aquí corresponde a RFC-7539 , que también se usa de manera similar en TLS RFC-7905 .

Notas

  • Dado que ChaCha20 es un cifrado de flujo, los textos planos no necesitan ser rellenados. Los bytes adicionales del flujo de claves se descartan.
  • La clave para el cifrado (256 bits) se acuerda mediante el KDF SHA256. Los detalles del KDF para cada mensaje están en secciones separadas a continuación.
  • Los marcos ChaChaPoly para los mensajes 1, 2 y la primera parte del mensaje 3, son de tamaño conocido. Comenzando con la segunda parte del mensaje 3, los marcos son de tamaño variable. El tamaño de la parte 1 del mensaje 3 se especifica en el mensaje 1. Comenzando con la fase de datos, los marcos van precedidos por una longitud de dos bytes ofuscada con SipHash como en obfs4.
  • El relleno está fuera del marco de datos autenticados para los mensajes 1 y 2. El relleno se usa en el KDF para el siguiente mensaje, por lo que se detectará cualquier manipulación. Comenzando en el mensaje 3, el relleno está dentro del marco de datos autenticados.

Manejo de Errores AEAD

  • En los mensajes 1, 2, y partes 1 y 2 del mensaje 3, el tamaño del mensaje AEAD se conoce de antemano. Ante un fallo de autenticación AEAD, el destinatario debe detener el procesamiento posterior de mensajes y cerrar la conexión sin responder. Este debe ser un cierre anormal (TCP RST).
  • Para resistencia al sondeo, en el mensaje 1, después de un fallo AEAD, Bob debe establecer un tiempo de espera aleatorio (rango por determinar) y luego leer un número aleatorio de bytes (rango por determinar) antes de cerrar el socket. Bob debe mantener una lista negra de IPs con fallos repetidos.
  • En la fase de datos, el tamaño del mensaje AEAD está “cifrado” (ofuscado) con SipHash. Se debe tener cuidado de evitar crear un oráculo de descifrado. Ante un fallo de autenticación AEAD en la fase de datos, el destinatario debe establecer un tiempo de espera aleatorio (rango por determinar) y luego leer un número aleatorio de bytes (rango por determinar). Después de la lectura, o al agotar el tiempo de lectura, el destinatario debe enviar una carga útil con un bloque de terminación que contenga un código de razón “fallo AEAD”, y cerrar la conexión.
  • Tomar la misma acción de error para un valor de campo de longitud inválido en la fase de datos.

Función de Derivación de Claves (KDF) (para mensaje de handshake 1)

El KDF genera una clave de cifrado de fase de handshake k a partir del resultado DH, utilizando HMAC-SHA256(key, data) como se define en RFC-2104 . Estas son las funciones InitializeSymmetric(), MixHash(), y MixKey(), exactamente como se definen en la especificación Noise.

This is the "e" message pattern:

// Define protocol_name. Set protocol_name = "Noise_XKaesobfse+hs2+hs3_25519_ChaChaPoly_SHA256" (48 bytes, US-ASCII encoded, no NULL termination).

// Define Hash h = 32 bytes h = SHA256(protocol_name);

Define ck = 32 byte chaining key. Copy the h data to ck. Set ck = h

Define rs = Bob's 32-byte static key as published in the RouterInfo

// MixHash(null prologue) h = SHA256(h);

// up until here, can all be precalculated by Alice for all outgoing connections

// Alice must validate that Bob's static key is a valid point on the curve here.

// Bob static key // MixHash(rs) // || below means append h = SHA256(h || rs);

// up until here, can all be precalculated by Bob for all incoming connections

This is the "e" message pattern:

Alice generates her ephemeral DH key pair e.

// Alice ephemeral key X // MixHash(e.pubkey) // || below means append h = SHA256(h || e.pubkey);

// h is used as the associated data for the AEAD in message 1 // Retain the Hash h for the message 2 KDF

End of "e" message pattern.

This is the "es" message pattern:

// DH(e, rs) == DH(s, re) Define input_key_material = 32 byte DH result of Alice's ephemeral key and Bob's static key Set input_key_material = X25519 DH result

// MixKey(DH())

Define temp_key = 32 bytes Define HMAC-SHA256(key, data) as in [RFC-2104](https://tools.ietf.org/html/rfc2104) // Generate a temp key from the chaining key and DH result // ck is the chaining key, defined above temp_key = HMAC-SHA256(ck, input_key_material) // overwrite the DH result in memory, no longer needed input_key_material = (all zeros)

// Output 1 // Set a new chaining key from the temp key // byte() below means a single byte ck = HMAC-SHA256(temp_key, byte(0x01)).

// Output 2 // Generate the cipher key k Define k = 32 bytes // || below means append // byte() below means a single byte k = HMAC-SHA256(temp_key, ck || byte(0x02)). // overwrite the temp_key in memory, no longer needed temp_key = (all zeros)

// retain the chaining key ck for message 2 KDF

End of "es" message pattern.

1) SessionRequest

Alice envía a Bob.

Contenido Noise: clave efímera X de Alice Carga útil Noise: bloque de opciones de 16 bytes Carga útil no-noise: Relleno aleatorio

(Propiedades de Seguridad del Payload de Noise )

XK(s, rs): Authentication Confidentiality

-> e, es 0 2

    Authentication: None (0). This payload may have been sent by any party, including an active attacker.

    Confidentiality: 2. Encryption to a known recipient, forward secrecy for sender compromise only, vulnerable to replay. This payload is encrypted based only on DHs involving the recipient's static key pair. If the recipient's static private key is compromised, even at a later date, this payload can be decrypted. This message can also be replayed, since there's no ephemeral contribution from the recipient.

    "e": Alice generates a new ephemeral key pair and stores it in the e

    :   variable, writes the ephemeral public key as cleartext into the message buffer, and hashes the public key along with the old h to derive a new h.

    "es": A DH is performed between the Alice's ephemeral key pair and the

    :   Bob's static key pair. The result is hashed along with the old ck to derive a new ck and k, and n is set to zero.

El valor X se cifra para garantizar la indistinguibilidad y unicidad de la carga útil, que son contramedidas DPI necesarias. Utilizamos cifrado AES para lograr esto, en lugar de alternativas más complejas y lentas como elligator2. El cifrado asimétrico con la clave pública del router de Bob sería demasiado lento. El cifrado AES utiliza el hash del router de Bob como clave y el IV de Bob tal como se publica en la base de datos de red.

El cifrado AES es solo para resistencia a DPI. Cualquier parte que conozca el hash del router de Bob y el IV, que se publican en la base de datos de red, puede descifrar el valor X en este mensaje.

El relleno no está cifrado por Alice. Puede ser necesario que Bob descifre el relleno para inhibir ataques de temporización.

Contenidos en bruto:

+----+----+----+----+----+----+----+----+

|                                       |

    + obfuscated with RH_B + | AES-CBC-256 encrypted X | + (32 bytes) + | | + + | | +----+----+----+----+----+----+----+----+ | | + + | ChaChaPoly frame | + (32 bytes) + | k defined in KDF for message 1 | + n = 0 + | see KDF for associated data | +----+----+----+----+----+----+----+----+ | unencrypted authenticated | ~ padding (optional) ~ | length defined in options block | +----+----+----+----+----+----+----+----+

    X :: 32 bytes, AES-256-CBC encrypted X25519 ephemeral key, little endian

    :   key: RH_B iv: As published in Bobs network database entry

    padding :: Random data, 0 or more bytes.

    :   Total message length must be 65535 bytes or less. Total message length must be 287 bytes or less if Bob is publishing his address as NTCP (see Version Detection section below). Alice and Bob will use the padding data in the KDF for message 2. It is authenticated so that any tampering will cause the next message to fail.

Datos no cifrados (etiqueta de autenticación Poly1305 no mostrada):

+----+----+----+----+----+----+----+----+

|                                       |

    + + | X | + (32 bytes) + | | + + | | +----+----+----+----+----+----+----+----+ | options | + (16 bytes) + | | +----+----+----+----+----+----+----+----+ | unencrypted authenticated | + padding (optional) + | length defined in options block | ~ . . . ~ | | +----+----+----+----+----+----+----+----+

    X :: 32 bytes, X25519 ephemeral key, little endian

    options :: options block, 16 bytes, see below

    padding :: Random data, 0 or more bytes.

    :   Total message length must be 65535 bytes or less. Total message length must be 287 bytes or less if Bob is publishing his address as "NTCP" (see Version Detection section below) Alice and Bob will use the padding data in the KDF for message 2. It is authenticated so that any tampering will cause the next message to fail.

Bloque de opciones: Nota: Todos los campos están en big-endian.

+----+----+----+----+----+----+----+----+

| id | ver| padLen | m3p2len | Rsvd(0) |

    +-------------------------------+-------------------------------+
    | > tsA                         | > Reserved (0)                |
    +-------------------------------+-------------------------------+

    id :: 1 byte, the network ID (currently 2, except for test networks)

    :   As of 0.9.42. See proposal 147.

    ver :: 1 byte, protocol version (currently 2)

    padLen :: 2 bytes, length of the padding, 0 or more

    :   Min/max guidelines TBD. Random size from 0 to 31 bytes minimum? (Distribution is implementation-dependent)

    m3p2Len :: 2 bytes, length of the the second AEAD frame in SessionConfirmed

    :   (message 3 part 2) See notes below

    Rsvd :: 2 bytes, set to 0 for compatibility with future options

    tsA :: 4 bytes, Unix timestamp, unsigned seconds.

    :   Wraps around in 2106

    Reserved :: 4 bytes, set to 0 for compatibility with future options

Notas

  • Cuando la dirección publicada es “NTCP”, Bob soporta tanto NTCP como NTCP2 en el mismo puerto. Por compatibilidad, cuando inicia una conexión a una dirección publicada como “NTCP”, Alice debe limitar el tamaño máximo de este mensaje, incluyendo el relleno, a 287 bytes o menos. Esto facilita la identificación automática del protocolo por parte de Bob. Cuando se publica como “NTCP2”, no hay restricción de tamaño. Ver las secciones Direcciones Publicadas y Detección de Versión más abajo.

  • El valor X único en el bloque AES inicial asegura que el texto cifrado sea diferente para cada sesión.

  • Bob debe rechazar las conexiones donde el valor de timestamp esté demasiado alejado del tiempo actual. Llama al delta de tiempo máximo “D”. Bob debe mantener una caché local de valores de handshake previamente utilizados y rechazar duplicados, para prevenir ataques de repetición. Los valores en la caché deben tener un tiempo de vida de al menos 2*D. Los valores de caché dependen de la implementación, sin embargo, el valor X de 32 bytes (o su equivalente cifrado) puede ser utilizado.

  • Las claves efímeras Diffie-Hellman nunca deben reutilizarse, para prevenir ataques criptográficos, y la reutilización será rechazada como un ataque de repetición.

  • Las opciones “KE” y “auth” deben ser compatibles, es decir, el secreto compartido K debe tener el tamaño apropiado. Si se agregan más opciones “auth”, esto podría cambiar implícitamente el significado de la bandera “KE” para usar un KDF diferente o un tamaño de truncamiento diferente.

  • Bob debe validar que la clave efímera de Alice es un punto válido en la curva aquí.

  • El padding debería limitarse a una cantidad razonable. Bob puede rechazar conexiones con padding excesivo. Bob especificará sus opciones de padding en el mensaje 2. Directrices mín/máx por determinar. ¿Tamaño aleatorio de 0 a 31 bytes mínimo? (La distribución depende de la implementación) Las implementaciones de Java actualmente limitan el padding a 256 bytes máximo.

  • Ante cualquier error, incluyendo AEAD, DH, timestamp, aparente replay, o falla de validación de clave, Bob debe detener el procesamiento adicional de mensajes y cerrar la conexión sin responder. Esto debería ser un cierre anormal (TCP RST). Para resistencia a sondeos, después de una falla AEAD, Bob debería establecer un timeout aleatorio (rango por determinar) y luego leer un número aleatorio de bytes (rango por determinar), antes de cerrar el socket.

  • Bob puede hacer una verificación rápida de MSB para una clave válida (X[31] & 0x80 == 0) antes de intentar el descifrado. Si el bit alto está establecido, implementar resistencia al sondeo como para fallas AEAD.

  • Mitigación de DoS: DH es una operación relativamente costosa. Al igual que con el protocolo NTCP anterior, los routers deben tomar todas las medidas necesarias para prevenir el agotamiento de CPU o conexiones. Establecer límites en las conexiones activas máximas y configuraciones de conexión máximas en progreso. Aplicar timeouts de lectura (tanto por lectura como total para “slowloris”). Limitar conexiones repetidas o simultáneas desde la misma fuente. Mantener listas negras para fuentes que fallan repetidamente. No responder a fallos de AEAD.

  • Para facilitar la detección rápida de versión y el handshaking, las implementaciones deben asegurar que Alice almacena en buffer y luego envía todo el contenido del primer mensaje de una vez, incluyendo el padding. Esto aumenta la probabilidad de que los datos se contengan en un solo paquete TCP (a menos que sean segmentados por el SO o middleboxes), y sean recibidos de una vez por Bob. Adicionalmente, las implementaciones deben asegurar que Bob almacena en buffer y luego envía todo el contenido del segundo mensaje de una vez, incluyendo el padding, y que Bob almacena en buffer y luego envía todo el contenido del tercer mensaje de una vez. Esto también es por eficiencia y para asegurar la efectividad del padding aleatorio.

  • Campo “ver”: El protocolo Noise general, extensiones y protocolo NTCP incluyendo especificaciones de carga útil, indicando NTCP2. Este campo puede usarse para indicar soporte para cambios futuros.

  • Longitud de la parte 2 del mensaje 3: Este es el tamaño del segundo frame AEAD (incluyendo MAC de 16 bytes) que contiene la Router Info de Alice y relleno opcional que se enviará en el mensaje SessionConfirmed. Como los routers regeneran y republican periódicamente su Router Info, el tamaño de la Router Info actual puede cambiar antes de que se envíe el mensaje 3. Las implementaciones deben elegir una de dos estrategias:

a) guardar la información actual del Router para ser enviada en el mensaje 3, de modo que se conozca el tamaño, y opcionalmente agregar espacio para relleno;

b) aumentar el tamaño especificado lo suficiente para permitir un posible incremento en el tamaño del Router Info, y siempre agregar relleno cuando el mensaje 3 sea realmente enviado. En cualquier caso, la longitud “m3p2len” incluida en el mensaje 1 debe ser exactamente el tamaño de ese marco cuando se envíe en el mensaje 3.

  • Bob debe fallar la conexión si queda algún dato entrante después de validar el mensaje 1 y leer el relleno. No debería haber datos adicionales de Alice, ya que Bob aún no ha respondido con el mensaje 2.

  • El campo de ID de red se utiliza para identificar rápidamente conexiones entre redes diferentes. Si este campo es distinto de cero y no coincide con el ID de red de Bob, Bob debería desconectarse y bloquear futuras conexiones. Cualquier conexión desde redes de prueba debería tener un ID diferente y fallará la prueba. Desde la versión 0.9.42. Consulte la propuesta 147 para más información.

Función de Derivación de Claves (KDF) (para mensaje de handshake 2 y mensaje 3 parte 1)

// take h saved from message 1 KDF
// MixHash(ciphertext)
h = SHA256(h || 32 byte encrypted payload from message 1)

// MixHash(padding)
// Only if padding length is nonzero
h = SHA256(h || random padding from message 1)

This is the "e" message pattern:

Bob generates his ephemeral DH key pair e.

// h is from KDF for handshake message 1
// Bob ephemeral key Y
// MixHash(e.pubkey)
// || below means append
h = SHA256(h || e.pubkey);

// h is used as the associated data for the AEAD in message 2
// Retain the Hash h for the message 3 KDF

End of "e" message pattern.

This is the "ee" message pattern:

// DH(e, re)
Define input_key_material = 32 byte DH result of Alice's ephemeral key and Bob's ephemeral key
Set input_key_material = X25519 DH result
// overwrite Alice's ephemeral key in memory, no longer needed
// Alice:
e(public and private) = (all zeros)
// Bob:
re = (all zeros)

// MixKey(DH())

Define temp_key = 32 bytes
Define HMAC-SHA256(key, data) as in [RFC-2104]_
// Generate a temp key from the chaining key and DH result
// ck is the chaining key, from the KDF for handshake message 1
temp_key = HMAC-SHA256(ck, input_key_material)
// overwrite the DH result in memory, no longer needed
input_key_material = (all zeros)

// Output 1
// Set a new chaining key from the temp key
// byte() below means a single byte
ck =       HMAC-SHA256(temp_key, byte(0x01)).

// Output 2
// Generate the cipher key k
Define k = 32 bytes
// || below means append
// byte() below means a single byte
k =        HMAC-SHA256(temp_key, ck || byte(0x02)).
// overwrite the temp_key in memory, no longer needed
temp_key = (all zeros)

// retain the chaining key ck for message 3 KDF

End of "ee" message pattern.

2) SessionCreated

Bob envía a Alice.

Contenido de Noise: clave efímera Y de Bob Carga útil de Noise: bloque de opción de 16 bytes Carga útil no-Noise: Relleno aleatorio

(Propiedades de Seguridad de Carga Útil de Noise )

XK(s, rs): Authentication Confidentiality

<- e, ee 2 1

    Authentication: 2. Sender authentication resistant to key-compromise impersonation (KCI). The sender authentication is based on an ephemeral-static DH ("es" or "se") between the sender's static key pair and the recipient's ephemeral key pair. Assuming the corresponding private keys are secure, this authentication cannot be forged.

    Confidentiality: 1. Encryption to an ephemeral recipient. This payload has forward secrecy, since encryption involves an ephemeral-ephemeral DH ("ee"). However, the sender has not authenticated the recipient, so this payload might be sent to any party, including an active attacker.

    "e": Bob generates a new ephemeral key pair and stores it in the e variable, writes the ephemeral public key as cleartext into the message buffer, and hashes the public key along with the old h to derive a new h.

    "ee": A DH is performed between the Bob's ephemeral key pair and the Alice's ephemeral key pair. The result is hashed along with the old ck to derive a new ck and k, and n is set to zero.

El valor Y se cifra para garantizar la indistinguibilidad y unicidad de la carga útil, que son contramedidas DPI necesarias. Utilizamos cifrado AES para lograr esto, en lugar de alternativas más complejas y lentas como elligator2. El cifrado asimétrico con la clave pública del router de Alice sería demasiado lento. El cifrado AES utiliza el hash del router de Bob como clave y el estado AES del mensaje 1 (que se inicializó con el IV de Bob tal como se publicó en el netDb).

El cifrado AES es solo para resistencia a DPI. Cualquier parte que conozca el hash del router de Bob y el IV, que se publican en la base de datos de red, y haya capturado los primeros 32 bytes del mensaje 1, puede descifrar el valor Y en este mensaje.

Contenido sin procesar:

+----+----+----+----+----+----+----+----+

|                                       |

    + obfuscated with RH_B + | AES-CBC-256 encrypted Y | + (32 bytes) + | | + + | | +----+----+----+----+----+----+----+----+ | ChaChaPoly frame | + Encrypted and authenticated data + | 32 bytes | + k defined in KDF for message 2 + | n = 0; see KDF for associated data | + + | | +----+----+----+----+----+----+----+----+ | unencrypted authenticated | + padding (optional) + | length defined in options block | ~ . . . ~ | | +----+----+----+----+----+----+----+----+

    Y :: 32 bytes, AES-256-CBC encrypted X25519 ephemeral key, little endian

    :   key: RH_B iv: Using AES state from message 1

Datos sin cifrar (etiqueta de autenticación Poly1305 no mostrada):

+----+----+----+----+----+----+----+----+

|                                       |

    + + | Y | + (32 bytes) + | | + + | | +----+----+----+----+----+----+----+----+ | options | + (16 bytes) + | | +----+----+----+----+----+----+----+----+ | unencrypted authenticated | + padding (optional) + | length defined in options block | ~ . . . ~ | | +----+----+----+----+----+----+----+----+

    Y :: 32 bytes, X25519 ephemeral key, little endian

    options :: options block, 16 bytes, see below

    padding :: Random data, 0 or more bytes.

    :   Total message length must be 65535 bytes or less. Alice and Bob will use the padding data in the KDF for message 3 part 1. It is authenticated so that any tampering will cause the next message to fail.

Notas

  • Alice debe validar que la clave efímera de Bob es un punto válido en la curva aquí.
  • El padding debe limitarse a una cantidad razonable. Alice puede rechazar conexiones con padding excesivo. Alice especificará sus opciones de padding en el mensaje 3. Pautas mín/máx por determinar. ¿Tamaño aleatorio de 0 a 31 bytes mínimo? (La distribución depende de la implementación)
  • En cualquier error, incluyendo AEAD, DH, timestamp, aparente replay, o fallo en validación de clave, Alice debe detener el procesamiento adicional de mensajes y cerrar la conexión sin responder. Esto debería ser un cierre anormal (TCP RST).
  • Para facilitar el handshaking rápido, las implementaciones deben asegurar que Bob almacene en buffer y luego vacíe todo el contenido del primer mensaje de una vez, incluyendo el padding. Esto aumenta la probabilidad de que los datos se contengan en un solo paquete TCP (a menos que sean segmentados por el SO o middleboxes), y sean recibidos todos de una vez por Alice. Esto también es por eficiencia y para asegurar la efectividad del padding aleatorio.
  • Alice debe fallar la conexión si quedan datos entrantes después de validar el mensaje 2 y leer el padding. No debería haber datos adicionales de Bob, ya que Alice no ha respondido con el mensaje 3 todavía.

Bloque de opciones: Nota: Todos los campos están en big-endian.

+----+----+----+----+----+----+----+----+

| Rsvd(0) | padLen | Reserved (0) |

    +-------------------------------+-------------------------------+
    | > tsB                         | > Reserved (0)                |
    +-------------------------------+-------------------------------+

    Reserved :: 10 bytes total, set to 0 for compatibility with future options

    padLen :: 2 bytes, big endian, length of the padding, 0 or more

    :   Min/max guidelines TBD. Random size from 0 to 31 bytes minimum? (Distribution is implementation-dependent)

    tsB :: 4 bytes, big endian, Unix timestamp, unsigned seconds.

    :   Wraps around in 2106

Notas

  • Alice debe rechazar conexiones donde el valor del timestamp esté demasiado alejado del tiempo actual. Llama al delta de tiempo máximo “D”. Alice debe mantener una caché local de valores de handshake utilizados previamente y rechazar duplicados, para prevenir ataques de repetición. Los valores en la caché deben tener un tiempo de vida de al menos 2*D. Los valores de la caché dependen de la implementación, sin embargo, el valor Y de 32 bytes (o su equivalente encriptado) puede ser utilizado.

Problemas

  • ¿Incluir aquí opciones de relleno mín/máx?

Cifrado para el mensaje de handshake 3 parte 1, usando KDF del mensaje 2)

// take h saved from message 2 KDF
// MixHash(ciphertext)
h = SHA256(h || 24 byte encrypted payload from message 2)

// MixHash(padding)
// Only if padding length is nonzero
h = SHA256(h || random padding from message 2)
// h is used as the associated data for the AEAD in message 3 part 1, below

This is the "s" message pattern:

Define s = Alice's static public key, 32 bytes

// EncryptAndHash(s.publickey)
// EncryptWithAd(h, s.publickey)
// AEAD_ChaCha20_Poly1305(key, nonce, associatedData, data)
// k is from handshake message 1
// n is 1
ciphertext = AEAD_ChaCha20_Poly1305(k, n++, h, s.publickey)
// MixHash(ciphertext)
// || below means append
h = SHA256(h || ciphertext);

// h is used as the associated data for the AEAD in message 3 part 2

End of "s" message pattern.

Función de Derivación de Clave (KDF) (para el mensaje de handshake 3 parte 2)

This is the "se" message pattern:

// DH(s, re) == DH(e, rs) Define input_key_material = 32 byte DH result of Alice's static key and Bob's ephemeral key Set input_key_material = X25519 DH result // overwrite Bob's ephemeral key in memory, no longer needed // Alice: re = (all zeros) // Bob: e(public and private) = (all zeros)

// MixKey(DH())

Define temp_key = 32 bytes Define HMAC-SHA256(key, data) as in [RFC-2104](https://tools.ietf.org/html/rfc2104) // Generate a temp key from the chaining key and DH result // ck is the chaining key, from the KDF for handshake message 1 temp_key = HMAC-SHA256(ck, input_key_material) // overwrite the DH result in memory, no longer needed input_key_material = (all zeros)

// Output 1 // Set a new chaining key from the temp key // byte() below means a single byte ck = HMAC-SHA256(temp_key, byte(0x01)).

// Output 2 // Generate the cipher key k Define k = 32 bytes // || below means append // byte() below means a single byte k = HMAC-SHA256(temp_key, ck || byte(0x02)).

// h from message 3 part 1 is used as the associated data for the AEAD in message 3 part 2

// EncryptAndHash(payload) // EncryptWithAd(h, payload) // AEAD_ChaCha20_Poly1305(key, nonce, associatedData, data) // n is 0 ciphertext = AEAD_ChaCha20_Poly1305(k, n++, h, payload) // MixHash(ciphertext) // || below means append h = SHA256(h || ciphertext);

// retain the chaining key ck for the data phase KDF // retain the hash h for the data phase Additional Symmetric Key (SipHash) KDF

End of "se" message pattern.

// overwrite the temp_key in memory, no longer needed temp_key = (all zeros)

3) SessionConfirmed

Alice envía a Bob.

Contenido Noise: clave estática de Alice Carga útil Noise: RouterInfo de Alice y relleno aleatorio Carga útil no-noise: ninguna

(Propiedades de Seguridad de Carga Útil de Noise )

XK(s, rs): Authentication Confidentiality

-> s, se 2 5

    Authentication: 2. Sender authentication resistant to key-compromise impersonation (KCI). The sender authentication is based on an ephemeral-static DH ("es" or "se") between the sender's static key pair and the recipient's ephemeral key pair. Assuming the corresponding private keys are secure, this authentication cannot be forged.

    Confidentiality: 5. Encryption to a known recipient, strong forward secrecy. This payload is encrypted based on an ephemeral-ephemeral DH as well as an ephemeral-static DH with the recipient's static key pair. Assuming the ephemeral private keys are secure, and the recipient is not being actively impersonated by an attacker that has stolen its static private key, this payload cannot be decrypted.

    "s": Alice writes her static public key from the s variable into the message buffer, encrypting it, and hashes the output along with the old h to derive a new h.

    "se": A DH is performed between the Alice's static key pair and the Bob's ephemeral key pair. The result is hashed along with the old ck to derive a new ck and k, and n is set to zero.

Esto contiene dos tramas ChaChaPoly. La primera es la clave pública estática cifrada de Alice. La segunda es la carga útil Noise: el RouterInfo cifrado de Alice, opciones opcionales y relleno opcional. Utilizan claves diferentes, porque la función MixKey() se llama entre ellas.

Contenidos sin procesar:

+----+----+----+----+----+----+----+----+

|                                       |

    + ChaChaPoly frame (48 bytes) + | Encrypted and authenticated | + Alice static key S + | (32 bytes) | + + | k defined in KDF for message 2 | + n = 1 + | see KDF for associated data | + + | | +----+----+----+----+----+----+----+----+ | | + Length specified in message 1 + | | + ChaChaPoly frame + | Encrypted and authenticated | + + | Alice RouterInfo | + using block format 2 + | Alice Options (optional) | + using block format 1 + | Arbitrary padding | + using block format 254 + | | + + | k defined in KDF for message 3 part 2 | + n = 0 + | see KDF for associated data | ~ . . . ~ | | +----+----+----+----+----+----+----+----+

    S :: 32 bytes, ChaChaPoly encrypted Alice's X25519 static key, little endian

    :   inside 48 byte ChaChaPoly frame

Datos no cifrados (etiquetas de autenticación Poly1305 no mostradas):

+----+----+----+----+----+----+----+----+

|                                       |

    + + | S | + Alice static key + | (32 bytes) | + + | | + + +----+----+----+----+----+----+----+----+ | | + + | | + + | Alice RouterInfo block | ~ . . . ~ | | +----+----+----+----+----+----+----+----+ | | + Optional Options block + | | ~ . . . ~ | | +----+----+----+----+----+----+----+----+ | | + Optional Padding block + | | ~ . . . ~ | | +----+----+----+----+----+----+----+----+

    S :: 32 bytes, Alice's X25519 static key, little endian

Notas

  • Bob debe realizar la validación habitual de Router Info. Asegurar que el tipo de firma sea compatible, verificar la firma, verificar que la marca de tiempo esté dentro de los límites, y cualquier otra verificación necesaria.

  • Bob debe verificar que la clave estática de Alice recibida en el primer marco coincida con la clave estática en la Router Info. Bob debe primero buscar en la Router Info una Router Address NTCP o NTCP2 con una opción de versión (v) coincidente. Consulte las secciones Published Router Info y Unpublished Router Info a continuación.

  • Si Bob tiene una versión más antigua del RouterInfo de Alice en su netDb, verificar que la clave estática en el router info sea la misma en ambos, si está presente, y si la versión más antigua tiene menos de XXX de antigüedad (ver tiempo de rotación de clave más abajo)

  • Bob debe validar que la clave estática de Alice es un punto válido en la curva aquí.

  • Se deben incluir opciones para especificar parámetros de relleno.

  • En caso de cualquier error, incluyendo fallas de validación de AEAD, RI, DH, timestamp, o clave, Bob debe detener el procesamiento adicional de mensajes y cerrar la conexión sin responder. Esto debería ser un cierre anormal (TCP RST).

  • Para facilitar el handshaking rápido, las implementaciones deben asegurar que Alice almacene en buffer y luego envíe de una vez todo el contenido del tercer mensaje, incluyendo ambos frames AEAD. Esto aumenta la probabilidad de que los datos se contengan en un solo paquete TCP (a menos que sean segmentados por el SO o middleboxes), y sean recibidos todos a la vez por Bob. Esto también es por eficiencia y para asegurar la efectividad del padding aleatorio.

  • Longitud del marco de la parte 2 del mensaje 3: La longitud de este marco (incluyendo MAC) es enviada por Alice en el mensaje 1. Ver ese mensaje para notas importantes sobre permitir suficiente espacio para el relleno.

  • Contenido del marco de la parte 2 del mensaje 3: El formato de este marco es el mismo que el formato de los marcos de la fase de datos, excepto que la longitud del marco es enviada por Alice en el mensaje 1. Ver más abajo el formato del marco de la fase de datos. El marco debe contener de 1 a 3 bloques en el siguiente orden:

  1. Bloque de información del router de Alice (requerido) 2) Bloque de opciones (opcional)

3) Bloque de relleno (opcional) Este frame nunca debe contener ningún otro tipo de bloque.

  • El relleno de la parte 2 del mensaje 3 no es necesario si Alice añade una trama de fase de datos (opcionalmente conteniendo relleno) al final del mensaje 3 y envía ambos a la vez, ya que aparecerá como un gran flujo de bytes para un observador. Como Alice generalmente, pero no siempre, tendrá un mensaje I2NP para enviar a Bob (por eso se conectó a él), esta es la implementación recomendada, por eficiencia y para asegurar la efectividad del relleno aleatorio.

  • La longitud total de ambos marcos AEAD del Mensaje 3 (partes 1 y 2) es de 65535 bytes; la parte 1 es de 48 bytes, por lo que la longitud máxima del marco de la parte 2 es de 65487; la longitud máxima de texto plano de la parte 2 excluyendo MAC es de 65471.

Función de Derivación de Claves (KDF) (para la fase de datos)

La fase de datos utiliza una entrada de datos asociados de longitud cero.

El KDF genera dos claves de cifrado k_ab y k_ba a partir de la clave de encadenamiento ck, utilizando HMAC-SHA256(key, data) como se define en RFC-2104 . Esta es la función Split(), exactamente como se define en la especificación Noise.

ck = from handshake phase

// k_ab, k_ba = HKDF(ck, zerolen) // ask_master = HKDF(ck, zerolen, info="ask")

// zerolen is a zero-length byte array temp_key = HMAC-SHA256(ck, zerolen) // overwrite the chaining key in memory, no longer needed ck = (all zeros)

// Output 1 // cipher key, for Alice transmits to Bob (Noise doesn't make clear which is which, but Java code does) k_ab = HMAC-SHA256(temp_key, byte(0x01)).

// Output 2 // cipher key, for Bob transmits to Alice (Noise doesn't make clear which is which, but Java code does) k_ba = HMAC-SHA256(temp_key, k_ab || byte(0x02)).

KDF for SipHash for length field: Generate an Additional Symmetric Key (ask) for SipHash SipHash uses two 8-byte keys (big endian) and 8 byte IV for first data.

// "ask" is 3 bytes, US-ASCII, no null termination ask_master = HMAC-SHA256(temp_key, "ask" || byte(0x01)) // sip_master = HKDF(ask_master, h || "siphash") // "siphash" is 7 bytes, US-ASCII, no null termination // overwrite previous temp_key in memory // h is from KDF for message 3 part 2 temp_key = HMAC-SHA256(ask_master, h || "siphash") // overwrite ask_master in memory, no longer needed ask_master = (all zeros) sip_master = HMAC-SHA256(temp_key, byte(0x01))

Alice to Bob SipHash k1, k2, IV: // sipkeys_ab, sipkeys_ba = HKDF(sip_master, zerolen) // overwrite previous temp_key in memory temp_key = HMAC-SHA256(sip_master, zerolen) // overwrite sip_master in memory, no longer needed sip_master = (all zeros)

sipkeys_ab = HMAC-SHA256(temp_key, byte(0x01)). sipk1_ab = sipkeys_ab[0:7], little endian sipk2_ab = sipkeys_ab[8:15], little endian sipiv_ab = sipkeys_ab[16:23]

Bob to Alice SipHash k1, k2, IV:

sipkeys_ba = HMAC-SHA256(temp_key, sipkeys_ab || byte(0x02)). sipk1_ba = sipkeys_ba[0:7], little endian sipk2_ba = sipkeys_ba[8:15], little endian sipiv_ba = sipkeys_ba[16:23]

// overwrite the temp_key in memory, no longer needed temp_key = (all zeros)

4) Fase de Datos

Carga útil de ruido: Como se define a continuación, incluyendo relleno aleatorio Carga útil sin ruido: ninguna

Comenzando con la segunda parte del mensaje 3, todos los mensajes están dentro de un “frame” ChaChaPoly autenticado y encriptado con una longitud ofuscada de dos bytes antepuesta. Todo el relleno está dentro del frame. Dentro del frame hay un formato estándar con cero o más “bloques”. Cada bloque tiene un tipo de un byte y una longitud de dos bytes. Los tipos incluyen fecha/hora, mensaje I2NP, opciones, terminación y relleno.

Nota: Bob puede, pero no está obligado a, enviar su RouterInfo a Alice como su primer mensaje a Alice en la fase de datos.

(Propiedades de Seguridad de Carga Útil de Noise )

XK(s, rs): Authentication Confidentiality

<- 2 5 -> 2 5

    Authentication: 2. Sender authentication resistant to key-compromise impersonation (KCI). The sender authentication is based on an ephemeral-static DH ("es" or "se") between the sender's static key pair and the recipient's ephemeral key pair. Assuming the corresponding private keys are secure, this authentication cannot be forged.

    Confidentiality: 5. Encryption to a known recipient, strong forward secrecy. This payload is encrypted based on an ephemeral-ephemeral DH as well as an ephemeral-static DH with the recipient's static key pair. Assuming the ephemeral private keys are secure, and the recipient is not being actively impersonated by an attacker that has stolen its static private key, this payload cannot be decrypted.

Notas

  • Por eficiencia y para minimizar la identificación del campo de longitud, las implementaciones deben asegurar que el remitente almacene en búfer y luego envíe todo el contenido de los mensajes de datos de una vez, incluyendo el campo de longitud y el marco AEAD. Esto aumenta la probabilidad de que los datos estén contenidos en un solo paquete TCP (a menos que sean segmentados por el SO o middleboxes), y sean recibidos de una sola vez por la otra parte. Esto también es por eficiencia y para asegurar la efectividad del relleno aleatorio.
  • El router puede elegir terminar la sesión en caso de error AEAD, o puede continuar intentando las comunicaciones. Si continúa, el router debería terminar después de errores repetidos.

Longitud ofuscada de SipHash

Referencia: SipHash

Una vez que ambos lados han completado el handshake, transfieren payloads que luego son encriptados y autenticados en “frames” de ChaChaPoly.

Cada frame está precedido por una longitud de dos bytes, big endian. Esta longitud especifica el número de bytes de frame cifrados que siguen, incluyendo el MAC. Para evitar transmitir campos de longitud identificables en el stream, la longitud del frame se ofusca mediante XOR con una máscara derivada de SipHash, tal como se inicializa desde el KDF de la fase de datos. Nótese que las dos direcciones tienen claves e IVs únicos de SipHash del KDF.

sipk1, sipk2 = The SipHash keys from the KDF.  (two 8-byte long integers)
    IV[0] = sipiv = The SipHash IV from the KDF. (8 bytes)
    length is big endian.
    For each frame:
      IV[n] = SipHash-2-4(sipk1, sipk2, IV[n-1])
      Mask[n] = First 2 bytes of IV[n]
      obfuscatedLength = length ^ Mask[n]

    The first length output will be XORed with with IV[1].

El receptor tiene las mismas claves SipHash e IV. La decodificación de la longitud se realiza derivando la máscara utilizada para ofuscar la longitud y aplicando XOR al digest truncado para obtener la longitud del frame. La longitud del frame es la longitud total del frame cifrado incluyendo el MAC.

Notas

  • Si usas una función de biblioteca SipHash que devuelve un entero largo sin signo, usa los dos bytes menos significativos como la Máscara. Convierte el entero largo al siguiente IV como little endian.

Contenidos sin procesar

+----+----+----+----+----+----+----+----+

[|obf size |](##SUBST##|obf size |) | +----+----+ + | | + ChaChaPoly frame + | Encrypted and authenticated | + key is k_ab for Alice to Bob + | key is k_ba for Bob to Alice | + as defined in KDF for data phase + | n starts at 0 and increments | + for each frame in that direction + | no associated data | + 16 bytes minimum + | | ~ . . . ~ | | +----+----+----+----+----+----+----+----+

    obf size :: 2 bytes length obfuscated with SipHash

    :   when de-obfuscated: 16 - 65535

    Minimum size including length field is 18 bytes. Maximum size including length field is 65537 bytes. Obfuscated length is 2 bytes. Maximum ChaChaPoly frame is 65535 bytes.

Notas

  • Como el receptor debe obtener todo el frame para verificar el MAC, se recomienda que el emisor limite los frames a unos pocos KB en lugar de maximizar el tamaño del frame. Esto minimizará la latencia en el receptor.

Datos no cifrados

Hay cero o más bloques en la trama cifrada. Cada bloque contiene un identificador de un byte, una longitud de dos bytes y cero o más bytes de datos.

Para extensibilidad, los receptores deben ignorar bloques con identificadores desconocidos, y tratarlos como relleno.

Los datos cifrados tienen un máximo de 65535 bytes, incluyendo un encabezado de autenticación de 16 bytes, por lo que los datos sin cifrar máximos son de 65519 bytes.

(etiqueta de autenticación Poly1305 no mostrada):

+----+----+----+----+----+----+----+----+

[|blk |](##SUBST##|blk |) size | data | +----+----+----+ + | | ~ . . . ~ | | +----+----+----+----+----+----+----+----+ [|blk |](##SUBST##|blk |) size | data | +----+----+----+ + | | ~ . . . ~ | | +----+----+----+----+----+----+----+----+ ~ . . . ~

    blk :: 1 byte

    :   0 for datetime 1 for options 2 for RouterInfo 3 for I2NP message 4 for termination 224-253 reserved for experimental features 254 for padding 255 reserved for future extension

    size :: 2 bytes, big endian, size of data to follow, 0 - 65516 data :: the data

    Maximum ChaChaPoly frame is 65535 bytes. Poly1305 tag is 16 bytes Maximum total block size is 65519 bytes Maximum single block size is 65519 bytes Block type is 1 byte Block length is 2 bytes Maximum single block data size is 65516 bytes.

Reglas de Ordenamiento de Bloques

En el mensaje de handshake 3 parte 2, el orden debe ser: RouterInfo, seguido de Options si está presente, seguido de Padding si está presente. No se permiten otros bloques.

En la fase de datos, el orden no está especificado, excepto por los siguientes requisitos: El relleno, si está presente, debe ser el último bloque. La terminación, si está presente, debe ser el último bloque excepto por el relleno.

Puede haber múltiples bloques I2NP en un solo frame. No se permiten múltiples bloques de relleno en un solo frame. Otros tipos de bloques probablemente no tendrán múltiples bloques en un solo frame, pero no está prohibido.

DateTime

Caso especial para la sincronización de tiempo:

+----+----+----+----+----+----+----+

| 0 | 4 | timestamp |

    +----+----+----+----+----+----+----+

    blk :: 0 size :: 2 bytes, big endian, value = 4 timestamp :: Unix timestamp, unsigned seconds. Wraps around in 2106

NOTA: Las implementaciones deben redondear al segundo más cercano para prevenir el sesgo de reloj en la red.

Opciones

Pasar opciones actualizadas. Las opciones incluyen: Relleno mínimo y máximo.

El bloque de opciones tendrá longitud variable.

+----+----+----+----+----+----+----+----+

| 1 | size [|tmin|](##SUBST##|tmin|)tmax[|rmin|](##SUBST##|rmin|)rmax[|tdmy|](##SUBST##|tdmy|)

    +----+----+----+----+----+----+----+----+ [|tdmy|](##SUBST##|tdmy|) rdmy | tdelay | rdelay | | ~----+----+----+----+----+----+----+ ~ | more_options | ~ . . . ~ | | +----+----+----+----+----+----+----+----+

    blk :: 1 size :: 2 bytes, big endian, size of options to follow, 12 bytes minimum

    tmin, tmax, rmin, rmax :: requested padding limits

    :   tmin and rmin are for desired resistance to traffic analysis. tmax and rmax are for bandwidth limits. tmin and tmax are the transmit limits for the router sending this options block. rmin and rmax are the receive limits for the router sending this options block. Each is a 4.4 fixed-point float representing 0 to 15.9375 (or think of it as an unsigned 8-bit integer divided by 16.0). This is the ratio of padding to data. Examples: Value of 0x00 means no padding Value of 0x01 means add 6 percent padding Value of 0x10 means add 100 percent padding Value of 0x80 means add 800 percent (8x) padding Alice and Bob will negotiate the minimum and maximum in each direction. These are guidelines, there is no enforcement. Sender should honor receiver's maximum. Sender may or may not honor receiver's minimum, within bandwidth constraints.

    tdmy: Max dummy traffic willing to send, 2 bytes big endian, bytes/sec average rdmy: Requested dummy traffic, 2 bytes big endian, bytes/sec average tdelay: Max intra-message delay willing to insert, 2 bytes big endian, msec average rdelay: Requested intra-message delay, 2 bytes big endian, msec average

    Padding distribution specified as additional parameters? Random delay specified as additional parameters?

    more_options :: Format TBD

Problemas de Opciones

  • El formato de opciones está por definir.
  • La negociación de opciones está por definir.

RouterInfo

Pasar el RouterInfo de Alice a Bob. Usado en el mensaje de handshake 3 parte 2. Pasar el RouterInfo de Alice a Bob, o el de Bob a Alice. Usado opcionalmente en la fase de datos.

+----+----+----+----+----+----+----+----+

| 2 | size [|flg |](##SUBST##|flg |) RouterInfo |

    +----+----+----+----+ + | (Alice RI in handshake msg 3 part 2) | ~ (Alice, Bob, or third-party ~ | RI in data phase) | ~ . . . ~ | | +----+----+----+----+----+----+----+----+

    blk :: 2 size :: 2 bytes, big endian, size of flag + router info to follow flg :: 1 byte flags bit order: 76543210 bit 0: 0 for local store, 1 for flood request bits 7-1: Unused, set to 0 for future compatibility routerinfo :: Alice's or Bob's RouterInfo

Notas

  • Cuando se usa en la fase de datos, el receptor (Alice o Bob) debe validar que es el mismo Router Hash que se envió originalmente (para Alice) o al que se envió (para Bob). Luego, tratarlo como un Mensaje I2NP DatabaseStore local. Validar la firma, validar marca de tiempo más reciente, y almacenar en la netdb local. Si el bit de bandera 0 es 1, y la parte receptora es floodfill, tratarlo como un Mensaje DatabaseStore con un token de respuesta no cero, y enviarlo por flood a los floodfills más cercanos.
  • El Router Info NO está comprimido con gzip (a diferencia de un Mensaje DatabaseStore, donde sí lo está)
  • El flooding no debe solicitarse a menos que haya RouterAddresses publicadas en el RouterInfo. El router receptor no debe hacer flood del RouterInfo a menos que tenga RouterAddresses publicadas en él.
  • Los implementadores deben asegurar que al leer un bloque, datos malformados o maliciosos no causarán que las lecturas se desborden al siguiente bloque.
  • Este protocolo no proporciona un acuse de recibo de que el RouterInfo fue recibido, almacenado, o enviado por flood (ya sea en la fase de handshake o de datos). Si se desea acuse de recibo, y el receptor es floodfill, el remitente debería en su lugar enviar un DatabaseStoreMessage I2NP estándar con un token de respuesta.

Problemas

  • También podría usarse en la fase de datos, en lugar de un I2NP DatabaseStoreMessage. Por ejemplo, Bob podría usarlo para iniciar la fase de datos.
  • ¿Está permitido que esto contenga el RI para routers distintos al originador, como reemplazo general para DatabaseStoreMessages, por ejemplo para flooding por floodfills?

Mensaje I2NP

Un solo mensaje I2NP con un encabezado modificado. Los mensajes I2NP no pueden ser fragmentados a través de bloques o a través de tramas ChaChaPoly.

Esto utiliza los primeros 9 bytes del encabezado I2NP estándar de NTCP, y elimina los últimos 7 bytes del encabezado, de la siguiente manera: acorta la expiración de 8 a 4 bytes (segundos en lugar de milisegundos, igual que para SSU), elimina la longitud de 2 bytes (usa el tamaño del bloque - 9), y elimina la suma de verificación SHA256 de un byte.

+----+----+----+----+----+----+----+----+

| 3 | size [|type|](##SUBST##|type|) msg id |

    +-------------------------------+
    | > short exp                   |
    +-------------------------------+

    ~ . . . ~ | | +----+----+----+----+----+----+----+----+

    blk :: 3 size :: 2 bytes, big endian, size of type + msg id + exp + message to follow I2NP message body size is (size - 9). type :: 1 byte, I2NP msg type, see I2NP spec msg id :: 4 bytes, big endian, I2NP message ID short exp :: 4 bytes, big endian, I2NP message expiration, Unix timestamp, unsigned seconds. Wraps around in 2106 message :: I2NP message body

Notas

  • Los implementadores deben asegurar que al leer un bloque, los datos malformados o maliciosos no causarán que las lecturas se desborden hacia el siguiente bloque.

Terminación

Noise recomienda un mensaje de terminación explícito. El NTCP original no tiene uno. Cerrar la conexión. Este debe ser el último bloque no de relleno en el frame.

+----+----+----+----+----+----+----+----+

| 4 | size | valid data frames |

    +----+----+----+----+----+----+----+----+

    :   received | rsn| addl data |

    +----+----+----+----+ + ~ . . . ~ +----+----+----+----+----+----+----+----+

    blk :: 4 size :: 2 bytes, big endian, value = 9 or more valid data frames received :: The number of valid AEAD data phase frames received (current receive nonce value) 0 if error occurs in handshake phase 8 bytes, big endian rsn :: reason, 1 byte: 0: normal close or unspecified 1: termination received 2: idle timeout 3: router shutdown 4: data phase AEAD failure 5: incompatible options 6: incompatible signature type 7: clock skew 8: padding violation 9: AEAD framing error 10: payload format error 11: message 1 error 12: message 2 error 13: message 3 error 14: intra-frame read timeout 15: RI signature verification fail 16: s parameter missing, invalid, or mismatched in RouterInfo 17: banned addl data :: optional, 0 or more bytes, for future expansion, debugging, or reason text. Format unspecified and may vary based on reason code.

Notas

No todas las razones pueden ser utilizadas realmente, depende de la implementación. Las fallas de handshake generalmente resultarán en un cierre con TCP RST en su lugar. Ver notas en las secciones de mensajes de handshake anteriores. Las razones adicionales listadas son para consistencia, registro, depuración, o si cambian las políticas.

Relleno

Esto es para el relleno dentro de tramas AEAD. El relleno para los mensajes 1 y 2 está fuera de las tramas AEAD. Todo el relleno para el mensaje 3 y la fase de datos está dentro de las tramas AEAD.

El relleno dentro de AEAD debería adherirse aproximadamente a los parámetros negociados. Bob envió sus parámetros mín/máx tx/rx solicitados en el mensaje 2. Alice envió sus parámetros mín/máx tx/rx solicitados en el mensaje 3. Las opciones actualizadas pueden enviarse durante la fase de datos. Consulte la información del bloque de opciones arriba.

Si está presente, este debe ser el último bloque en la trama.

+----+----+----+----+----+----+----+----+

[|254 |](##SUBST##|254 |) size | padding | +----+----+----+ + | | ~ . . . ~ | | +----+----+----+----+----+----+----+----+

    blk :: 254 size :: 2 bytes, big endian, size of padding to follow padding :: random data

Notas

  • Se permite Tamaño = 0.
  • Estrategias de padding por determinar.
  • Padding mínimo por determinar.
  • Se permiten tramas que contengan solo padding.
  • Valores predeterminados de padding por determinar.
  • Ver bloque de opciones para negociación de parámetros de padding
  • Ver bloque de opciones para parámetros de padding mín/máx
  • Noise limita los mensajes a 64KB. Si es necesario más padding, enviar múltiples tramas.
  • La respuesta del router ante violaciones del padding negociado depende de la implementación.

Otros tipos de bloques

Las implementaciones deben ignorar los tipos de bloque desconocidos para compatibilidad futura, excepto en el mensaje 3 parte 2, donde no se permiten bloques desconocidos.

Trabajo futuro

  • La longitud del padding debe decidirse por mensaje individual basándose en estimaciones de la distribución de longitudes, o se deben agregar retrasos aleatorios. Estas contramedidas deben incluirse para resistir DPI, ya que los tamaños de mensajes de otro modo revelarían que el tráfico I2P está siendo transportado por el protocolo de transporte. El esquema exacto de padding es un área de trabajo futuro.

5) Terminación

Las conexiones pueden terminarse mediante el cierre normal o anormal del socket TCP, o, como recomienda Noise, un mensaje de terminación explícito. El mensaje de terminación explícito se define en la fase de datos anterior.

En cualquier terminación normal o anormal, los routers deben poner a cero cualquier dato efímero en memoria, incluyendo claves efímeras de handshake, claves criptográficas simétricas e información relacionada.

Información del Router Publicada

Capacidades

A partir de la versión 0.9.50, la opción “caps” es compatible en direcciones NTCP2, similar a SSU. Una o más capacidades pueden publicarse en la opción “caps”. Las capacidades pueden estar en cualquier orden, pero “46” es el orden recomendado, para mantener consistencia entre implementaciones. Hay dos capacidades definidas:

4: Indica capacidad IPv4 saliente. Si se publica una IP en el campo host, esta capacidad no es necesaria. Si el router está oculto, o NTCP2 es solo saliente, ‘4’ y ‘6’ pueden combinarse en una sola dirección.

6: Indica capacidad IPv6 saliente. Si se publica una IP en el campo host, esta capacidad no es necesaria. Si el router está oculto, o NTCP2 es solo saliente, ‘4’ y ‘6’ pueden combinarse en una sola dirección.

Direcciones Publicadas

La RouterAddress publicada (parte del RouterInfo) tendrá un identificador de protocolo de “NTCP” o “NTCP2”.

El RouterAddress debe contener las opciones “host” y “port”, como en el protocolo NTCP actual.

El RouterAddress debe contener tres opciones para indicar soporte para NTCP2:

  • s=(Clave Base64) La clave pública estática Noise actual (s) para esta RouterAddress. Codificada en Base 64 usando el alfabeto estándar I2P Base 64. 32 bytes en binario, 44 bytes codificados en Base 64, clave pública X25519 little-endian.
  • i=(IV Base64) El IV actual para cifrar el valor X en el mensaje 1 para esta RouterAddress. Codificado en Base 64 usando el alfabeto estándar I2P Base 64. 16 bytes en binario, 24 bytes codificados en Base 64, big-endian.
  • v=2 La versión actual (2). Cuando se publica como “NTCP”, se implica soporte adicional para la versión 1. El soporte para versiones futuras será con valores separados por comas, por ejemplo v=2,3. La implementación debe verificar la compatibilidad, incluyendo múltiples versiones si hay una coma presente. Las versiones separadas por comas deben estar en orden numérico.

Alice debe verificar que las tres opciones estén presentes y sean válidas antes de conectarse usando el protocolo NTCP2.

Cuando se publica como “NTCP” con las opciones “s”, “i” y “v”, el router debe aceptar conexiones entrantes en ese host y puerto para ambos protocolos NTCP y NTCP2, y detectar automáticamente la versión del protocolo.

Cuando se publica como “NTCP2” con las opciones “s”, “i” y “v”, el router acepta conexiones entrantes en ese host y puerto solo para el protocolo NTCP2.

Si un router admite conexiones tanto NTCP1 como NTCP2 pero no implementa detección automática de versión para conexiones entrantes, debe anunciar tanto direcciones “NTCP” como “NTCP2”, e incluir las opciones NTCP2 solo en la dirección “NTCP2”. El router debería establecer un valor de costo más bajo (mayor prioridad) en la dirección “NTCP2” que en la dirección “NTCP”, para que NTCP2 sea preferido.

Si múltiples RouterAddresses NTCP2 (ya sea como “NTCP” o “NTCP2”) son publicadas en el mismo RouterInfo (para direcciones IP o puertos adicionales), todas las direcciones que especifiquen el mismo puerto deben contener opciones y valores NTCP2 idénticos. En particular, todas deben contener la misma clave estática e iv.

Dirección NTCP2 No Publicada

Si Alice no publica su dirección NTCP2 (como “NTCP” o “NTCP2”) para conexiones entrantes, debe publicar una dirección de router “NTCP2” que contenga únicamente su clave estática y la versión NTCP2, para que Bob pueda validar la clave después de recibir el RouterInfo de Alice en la parte 2 del mensaje 3.

  • s=(clave Base64) Como se define arriba para las direcciones publicadas.
  • v=2 Como se define arriba para las direcciones publicadas.

Esta dirección de router no contendrá las opciones “i”, “host” o “port”, ya que no son necesarias para las conexiones NTCP2 salientes. El costo publicado para esta dirección no importa estrictamente, ya que es solo de entrada; sin embargo, puede ser útil para otros routers si el costo se establece más alto (menor prioridad) que otras direcciones. El valor sugerido es 14.

Alice también puede simplemente agregar las opciones “s” y “v” a una dirección “NTCP” publicada existente.

Rotación de Clave Pública e IV

Debido al almacenamiento en caché de RouterInfos, los routers no deben rotar la clave pública estática o IV mientras el router esté funcionando, ya sea en una dirección publicada o no. Los routers deben almacenar de forma persistente esta clave e IV para reutilización después de un reinicio inmediato, para que las conexiones entrantes continúen funcionando y los tiempos de reinicio no se expongan. Los routers deben almacenar de forma persistente, o determinar de otra manera, el tiempo de último apagado, para que el tiempo de inactividad anterior pueda calcularse en el inicio.

Sujeto a preocupaciones sobre exponer los tiempos de reinicio, los routers pueden rotar esta clave o IV al inicio si el router estuvo previamente inactivo por algún tiempo (al menos un par de horas).

Si el router tiene alguna RouterAddress NTCP2 publicada (como NTCP o NTCP2), el tiempo mínimo de inactividad antes de la rotación debería ser mucho más largo, por ejemplo un mes, a menos que la dirección IP local haya cambiado o el router haga un “rekey”.

Si el router tiene RouterAddresses SSU publicadas, pero no NTCP2 (como NTCP o NTCP2), el tiempo de inactividad mínimo antes de la rotación debería ser mayor, por ejemplo un día, a menos que la dirección IP local haya cambiado o el router “rekeys”. Esto aplica incluso si la dirección SSU publicada tiene introducers.

Si el router no tiene ninguna RouterAddress publicada (NTCP, NTCP2, o SSU), el tiempo mínimo de inactividad antes de la rotación puede ser tan corto como dos horas, incluso si la dirección IP cambia, a menos que el router haga un “rekey” (regeneración de claves).

Si el router “rekeys” a un Router Hash diferente, también debería generar una nueva clave noise y un IV nuevo.

Las implementaciones deben tener en cuenta que cambiar la clave pública estática o el IV prohibirá las conexiones NTCP2 entrantes de routers que hayan almacenado en caché un RouterInfo más antiguo. La publicación de RouterInfo, la selección de peers de túnel (incluyendo tanto OBGW como el salto más cercano IB), la selección de túneles de cero saltos, la selección de transporte y otras estrategias de implementación deben tomar esto en cuenta.

La rotación de IV está sujeta a reglas idénticas a la rotación de claves, excepto que los IV no están presentes excepto en RouterAddresses publicadas, por lo que no hay IV para routers ocultos o con firewall. Si algo cambia (versión, clave, opciones?) se recomienda que el IV también cambie.

Nota: El tiempo mínimo de inactividad antes del recambio de claves puede modificarse para garantizar la salud de la red y prevenir la resiembra por parte de un router inactivo durante un período moderado de tiempo.

Detección de Versión

Cuando se publica como “NTCP”, el router debe detectar automáticamente la versión del protocolo para las conexiones entrantes.

Esta detección depende de la implementación, pero aquí tienes algunas pautas generales.

Para detectar la versión de una conexión NTCP entrante, Bob procede de la siguiente manera:

  • Esperar al menos 64 bytes (tamaño mínimo del mensaje 1 de NTCP2)

  • Si los datos recibidos inicialmente son de 288 o más bytes, la conexión entrante es versión 1.

  • Si es menor de 288 bytes, ya sea

  • Esperar un corto tiempo por más datos (buena estrategia antes de la adopción generalizada de NTCP2) si al menos se han recibido 288 en total, es NTCP 1. > > - Probar las primeras etapas de decodificación como versión 2, si falla, esperar un corto tiempo por más datos (buena estrategia después de la adopción generalizada de NTCP2) > > > - Descifrar los primeros 32 bytes (la clave X) del paquete SessionRequest usando AES-256 con la clave RH_B. > > - Verificar un punto válido en la curva. Si falla, esperar un corto tiempo por más datos para NTCP 1 > > - Verificar el frame AEAD. Si falla, esperar un corto tiempo por más datos para NTCP 1

Ten en cuenta que pueden recomendarse cambios o estrategias adicionales si detectamos ataques activos de segmentación TCP en NTCP 1.

Para facilitar la detección rápida de versiones y el handshaking, las implementaciones deben asegurar que Alice almacene en buffer y luego envíe todo el contenido del primer mensaje de una vez, incluyendo el padding. Esto aumenta la probabilidad de que los datos estén contenidos en un solo paquete TCP (a menos que sean segmentados por el SO o middleboxes), y sean recibidos de una sola vez por Bob. Esto también es por eficiencia y para asegurar la efectividad del padding aleatorio. Esto aplica tanto a handshakes NTCP como NTCP2.

Variantes, Respaldos y Problemas Generales

  • Si tanto Alice como Bob soportan NTCP2, Alice debería conectarse con NTCP2.
  • Si Alice falla al conectarse a Bob usando NTCP2 por cualquier razón, la conexión falla. Alice no puede reintentar usando NTCP 1.

Directrices de Desviación de Reloj

Las marcas de tiempo de los peers se incluyen en los dos primeros mensajes del handshake, Session Request y Session Created. Una diferencia de reloj entre dos peers mayor a +/- 60 segundos es generalmente fatal. Si Bob piensa que su reloj local está mal, puede ajustar su reloj usando la diferencia calculada, o alguna fuente externa. De lo contrario, Bob debería responder con un Session Created incluso si se excede la diferencia máxima, en lugar de simplemente cerrar la conexión. Esto permite que Alice obtenga la marca de tiempo de Bob y calcule la diferencia, y tome acción si es necesario. Bob no tiene la identidad del router de Alice en este punto, pero para conservar recursos, puede ser deseable que Bob prohíba las conexiones entrantes desde la IP de Alice por algún período de tiempo, o después de intentos de conexión repetidos con una diferencia excesiva.

Alice debería ajustar la desviación de reloj calculada restando la mitad del RTT. Si Alice piensa que su reloj local está mal, puede ajustar su reloj usando la desviación calculada, o alguna fuente externa. Si Alice piensa que el reloj de Bob está mal, puede prohibir a Bob por algún período de tiempo. En cualquier caso, Alice debería cerrar la conexión.

Si Alice responde con Session Confirmed (probablemente porque el desfase está muy cerca del límite de 60s, y los cálculos de Alice y Bob no son exactamente iguales debido al RTT), Bob debería ajustar el desfase de reloj calculado restando la mitad del RTT. Si el desfase de reloj ajustado excede el máximo, Bob debería entonces responder con un mensaje Disconnect que contenga un código de razón de desfase de reloj, y cerrar la conexión. En este punto, Bob tiene la identidad del router de Alice, y puede prohibir a Alice por algún período de tiempo.

Referencias

Was this page helpful?