Esta tradução foi gerada usando aprendizado de máquina e pode não ser 100% precisa. Ver versão em inglês

PQ Hybrid ECIES-X25519-AEAD-Ratchet

Variante híbrida pós-quântica do protocolo de criptografia ECIES usando ML-KEM

Nota

Implementação, testes e lançamento em andamento nas várias implementações de router. Verifique a documentação dessas implementações para obter o status.

Visão Geral

Esta é a variante PQ Hybrid do protocolo ECIES-X25519-AEAD-Ratchet ECIES . É a primeira fase da proposta geral PQ Prop169 a ser aprovada. Consulte essa proposta para objetivos gerais, modelos de ameaças, análise, alternativas e informações adicionais.

Esta especificação contém apenas as diferenças do ECIES padrão e deve ser lida em conjunto com essa especificação.

Design

Utilizamos o padrão NIST FIPS 203 FIPS203 que é baseado no, mas não é compatível com, CRYSTALS-Kyber (versões 3.1, 3 e anteriores).

Os handshakes híbridos são conforme especificado em Noise-Hybrid .

Troca de Chaves

Definimos uma troca de chaves híbrida para Ratchet. PQ KEM fornece apenas chaves efêmeras e não suporta diretamente handshakes de chave estática como Noise IK.

Definimos as três variantes ML-KEM como em FIPS203 , para um total de 3 novos tipos de criptografia. Os tipos híbridos são definidos apenas em combinação com X25519.

Os novos tipos de criptografia são:

TypeCode
MLKEM512_X255195
MLKEM768_X255196
MLKEM1024_X255197
A sobrecarga será substancial. Os tamanhos típicos das mensagens 1 e 2 (para IK) são atualmente em torno de 100 bytes (antes de qualquer payload adicional). Isso aumentará de 8x a 15x dependendo do algoritmo.

Nova Criptografia Necessária

  • ML-KEM (anteriormente CRYSTALS-Kyber) FIPS203
  • SHA3-128 (anteriormente Keccak-256) FIPS202 Usado apenas para SHAKE128
  • SHA3-256 (anteriormente Keccak-512) FIPS202
  • SHAKE128 e SHAKE256 (extensões XOF para SHA3-128 e SHA3-256) FIPS202

Vetores de teste para SHA3-256, SHAKE128, e SHAKE256 estão em NIST-VECTORS .

Note que a biblioteca Java bouncycastle suporta todos os itens acima. O suporte da biblioteca C++ está no OpenSSL 3.5 OPENSSL .

Especificação

Estruturas Comuns

Veja a especificação de estruturas comuns COMMON para comprimentos de chaves e identificadores.

Padrões de Handshake

Os handshakes utilizam padrões de handshake Noise .

O seguinte mapeamento de letras é usado:

  • e = chave efêmera de uso único
  • s = chave estática
  • p = carga útil da mensagem
  • e1 = chave PQ efêmera de uso único, enviada de Alice para Bob
  • ekem1 = o texto cifrado KEM, enviado de Bob para Alice

As seguintes modificações para XK e IK para sigilo direto híbrido (hfs) são conforme especificado em Noise-Hybrid seção 5:

IK:                         IKhfs:
<- s                        <- s
...                         ...
-> e, es, s, ss, p          -> e, es, e1, s, ss, p
<- tag, e, ee, se, p        <- tag, e, ee, ekem1, se, p
<- p                        <- p
p ->                        p ->

e1 and ekem1 are encrypted. See pattern definitions below.
NOTE: e1 and ekem1 are different sizes (unlike X25519)

O padrão e1 é definido como segue, conforme especificado na seção 4 de Noise-Hybrid :

For Alice:
    (encap_key, decap_key) = PQ_KEYGEN()

    // EncryptAndHash(encap_key)
    ciphertext = ENCRYPT(k, n, encap_key, ad)
    n++
    MixHash(ciphertext)

For Bob:
    // DecryptAndHash(ciphertext)
    encap_key = DECRYPT(k, n, ciphertext, ad)
    n++
    MixHash(ciphertext)

O padrão ekem1 é definido como segue, conforme especificado na seção 4 do Noise-Hybrid :

For Bob:
    (kem_ciphertext, kem_shared_key) = ENCAPS(encap_key)

    // EncryptAndHash(kem_ciphertext)
    ciphertext = ENCRYPT(k, n, kem_ciphertext, ad)
    MixHash(ciphertext)

    // MixKey
    MixKey(kem_shared_key)

For Alice:
    // DecryptAndHash(ciphertext)
    kem_ciphertext = DECRYPT(k, n, ciphertext, ad)
    MixHash(ciphertext)

    // MixKey
    kem_shared_key = DECAPS(kem_ciphertext, decap_key)
    MixKey(kem_shared_key)

Operações ML-KEM Definidas

Definimos as seguintes funções correspondentes aos blocos de construção criptográficos utilizados conforme definido em FIPS203 .

(encap_key, decap_key) = PQ_KEYGEN()

Alice cria as chaves de encapsulamento e desencapsulamento. A chave de encapsulamento é enviada na mensagem NS. Os tamanhos de encap_key e decap_key variam baseados na variante ML-KEM.

(ciphertext, kem_shared_key) = ENCAPS(encap_key)

Bob calcula o texto cifrado e a chave compartilhada, usando o texto cifrado recebido na mensagem NS. O texto cifrado é enviado na mensagem NSR. O tamanho do texto cifrado varia com base na variante ML-KEM. A kem_shared_key sempre tem 32 bytes.

kem_shared_key = DECAPS(ciphertext, decap_key)

Alice calcula a chave compartilhada, usando o texto cifrado recebido na mensagem NSR. A kem_shared_key sempre tem 32 bytes.

Note que tanto o encap_key quanto o ciphertext são criptografados dentro de blocos ChaCha/Poly nas mensagens 1 e 2 do handshake Noise. Eles serão descriptografados como parte do processo de handshake.

O kem_shared_key é misturado na chave de encadeamento com MixHash(). Veja abaixo para detalhes.

KDF do Handshake Noise

Visão Geral

O handshake híbrido é definido em Noise-Hybrid . A primeira mensagem, de Alice para Bob, contém e1, a chave de encapsulamento, antes da carga útil da mensagem. Isso é tratado como uma chave estática adicional; chame EncryptAndHash() nela (como Alice) ou DecryptAndHash() (como Bob). Em seguida, processe a carga útil da mensagem como de costume.

A segunda mensagem, de Bob para Alice, contém ekem1, o texto cifrado, antes da carga útil da mensagem. Isso é tratado como uma chave estática adicional; chame EncryptAndHash() nela (como Bob) ou DecryptAndHash() (como Alice). Em seguida, calcule a kem_shared_key e chame MixKey(kem_shared_key). Depois processe a carga útil da mensagem como de costume.

Identificadores Noise

Estas são as strings de inicialização do Noise:

  • “Noise_IKhfselg2_25519+MLKEM512_ChaChaPoly_SHA256”
  • “Noise_IKhfselg2_25519+MLKEM768_ChaChaPoly_SHA256”
  • “Noise_IKhfselg2_25519+MLKEM1024_ChaChaPoly_SHA256”

Alice KDF para Mensagem NS

Após o padrão de mensagem ’es’ e antes do padrão de mensagem ’s’, adicione:

This is the "e1" message pattern:

    (encap_key, decap_key) = PQ_KEYGEN()

    // EncryptAndHash(encap_key)
    // AEAD parameters
    k = keydata[32:63]
    n = 0
    ad = h
    ciphertext = ENCRYPT(k, n, encap_key, ad)
    n++

    // MixHash(ciphertext)
    h = SHA256(h || ciphertext)

End of "e1" message pattern.

NOTE: For the next section (payload for XK or static key for IK),
the keydata and chain key remain the same, and n now equals 1
(instead of 0 for non-hybrid).

Bob KDF para Mensagem NS

Após o padrão de mensagem ’es’ e antes do padrão de mensagem ’s’, adicione:

This is the "e1" message pattern:

    // DecryptAndHash(encap_key_section)
    // AEAD parameters
    k = keydata[32:63]
    n = 0
    ad = h
    encap_key = DECRYPT(k, n, encap_key_section, ad)
    n++

    // MixHash(encap_key_section)
    h = SHA256(h || encap_key_section)

End of "e1" message pattern.

NOTE: For the next section (payload for XK or static key for IK),
the keydata and chain key remain the same, and n now equals 1
(instead of 0 for non-hybrid).

Bob KDF para Mensagem NSR

Após o padrão de mensagem ’ee’ e antes do padrão de mensagem ‘se’, adicione:

This is the "ekem1" message pattern:

    (kem_ciphertext, kem_shared_key) = ENCAPS(encap_key)

    // EncryptAndHash(kem_ciphertext)
    // AEAD parameters
    k = keydata[32:63]
    n = 0
    ad = h
    ciphertext = ENCRYPT(k, n, kem_ciphertext, ad)

    // MixHash(ciphertext)
    h = SHA256(h || ciphertext)

    // MixKey(kem_shared_key)
    keydata = HKDF(chainKey, kem_shared_key, "", 64)
    chainKey = keydata[0:31]

End of "ekem1" message pattern.

Alice KDF para Mensagem NSR

Após o padrão de mensagem ’ee’ e antes do padrão de mensagem ‘ss’, adicione:

This is the "ekem1" message pattern:

    // DecryptAndHash(kem_ciphertext_section)
    // AEAD parameters
    k = keydata[32:63]
    n = 0
    ad = h
    kem_ciphertext = DECRYPT(k, n, kem_ciphertext_section, ad)

    // MixHash(kem_ciphertext_section)
    h = SHA256(h || kem_ciphertext_section)

    // MixKey(kem_shared_key)
    kem_shared_key = DECAPS(kem_ciphertext, decap_key)
    keydata = HKDF(chainKey, kem_shared_key, "", 64)
    chainKey = keydata[0:31]

End of "ekem1" message pattern.

KDF para split()

inalterado

Formato de Mensagem

Formato NS

Mudanças: O ratchet atual continha a chave estática na primeira seção ChaCha, e a carga útil na segunda seção. Com ML-KEM, agora existem três seções. A primeira seção contém a chave pública PQ criptografada. A segunda seção contém a chave estática. A terceira seção contém a carga útil.

Formato criptografado:

+----+----+----+----+----+----+----+----+
|                                       |
+         New Session Ephemeral         +
|            Public Key                 |
+            32 bytes                   +
|      Encoded with Elligator2          |
+----+----+----+----+----+----+----+----+
|                                       |
+         ML-KEM encap_key              +
|       ChaCha20 encrypted data         |
+   (see table below for length)        +
|                                       |
~                                       ~
|                                       |
+----+----+----+----+----+----+----+----+
|  Poly1305 Message Authentication Code |
+      (MAC) for encap_key Section      +
|              16 bytes                 |
+----+----+----+----+----+----+----+----+
|                                       |
+         X25519 Static Key             +
|       ChaCha20 encrypted data         |
+            32 bytes                   +
|                                       |
+----+----+----+----+----+----+----+----+
|  Poly1305 Message Authentication Code |
+     (MAC) for Static Key Section      +
|              16 bytes                 |
+----+----+----+----+----+----+----+----+
|                                       |
+          Payload Section              +
|       ChaCha20 encrypted data         |
~                                       ~
|                                       |
+----+----+----+----+----+----+----+----+
|  Poly1305 Message Authentication Code |
+      (MAC) for Payload Section        +
|              16 bytes                 |
+----+----+----+----+----+----+----+----+

Formato descriptografado:

Payload Part 1:

+----+----+----+----+----+----+----+----+
|                                       |
+         ML-KEM encap_key              +
|                                       |
+   (see table below for length)        +
|                                       |
~                                       ~
|                                       |
+----+----+----+----+----+----+----+----+

Payload Part 2:

+----+----+----+----+----+----+----+----+
|                                       |
+         X25519 Static Key             +
|            (32 bytes)                 |
+                                       +
|                                       |
+----+----+----+----+----+----+----+----+

Payload Part 3:

+----+----+----+----+----+----+----+----+
|                                       |
+          Payload Section              +
|                                       |
~                                       ~
|                                       |
+                                       +
|                                       |
+----+----+----+----+----+----+----+----+

Tamanhos:

TypeType CodeX lenNS lenNS Enc lenNS Dec lenPQ key lenpl len
X2551943296+pl64+plpl--pl
MLKEM512_X25519532912+pl880+pl800+pl800pl
MLKEM768_X255196321296+pl1360+pl1184+pl1184pl
MLKEM1024_X255197321680+pl1648+pl1568+pl1568pl
Note que o payload deve conter um bloco DateTime, então o tamanho mínimo do payload é 7. Os tamanhos mínimos de NS podem ser calculados de acordo.

Formato NSR

Alterações: O ratchet atual tem uma carga útil vazia para a primeira seção ChaCha, e a carga útil na segunda seção. Com ML-KEM, agora há três seções. A primeira seção contém o texto cifrado PQ criptografado. A segunda seção tem uma carga útil vazia. A terceira seção contém a carga útil.

Formato criptografado:

+----+----+----+----+----+----+----+----+
|       Session Tag 8 bytes             |
+----+----+----+----+----+----+----+----+
|                                       |
+       Ephemeral Public Key            +
|            32 bytes                   |
+      Encoded with Elligator2          +
|                                       |
+----+----+----+----+----+----+----+----+
|                                       |
+         ML-KEM ciphertext             +
|       ChaCha20 encrypted data         |
+   (see table below for length)        +
|                                       |
~                                       ~
|                                       |
+----+----+----+----+----+----+----+----+
|  Poly1305 Message Authentication Code |
+     (MAC) for ciphertext Section      +
|              16 bytes                 |
+----+----+----+----+----+----+----+----+
|  Poly1305 Message Authentication Code |
+   (MAC) for key Section (no data)     +
|              16 bytes                 |
+----+----+----+----+----+----+----+----+
|                                       |
+          Payload Section              +
|       ChaCha20 encrypted data         |
~                                       ~
|                                       |
+                                       +
|                                       |
+----+----+----+----+----+----+----+----+
|  Poly1305 Message Authentication Code |
+      (MAC) for Payload Section        +
|              16 bytes                 |
+----+----+----+----+----+----+----+----+

Formato descriptografado:

Payload Part 1:

+----+----+----+----+----+----+----+----+
|                                       |
+         ML-KEM ciphertext             +
|                                       |
+   (see table below for length)        +
|                                       |
~                                       ~
|                                       |
+----+----+----+----+----+----+----+----+

Payload Part 2:

empty

Payload Part 3:

+----+----+----+----+----+----+----+----+
|                                       |
+          Payload Section              +
|                                       |
~                                       ~
|                                       |
+                                       +
|                                       |
+----+----+----+----+----+----+----+----+

Tamanhos:

TypeType CodeY lenNSR lenNSR Enc lenNSR Dec lenPQ CT lenopt len
X2551943272+pl32+plpl--pl
MLKEM512_X25519532856+pl816+pl768+pl768pl
MLKEM768_X255196321176+pl1136+pl1088+pl1088pl
MLKEM1024_X255197321656+pl1616+pl1568+pl1568pl
Note que embora o NSR normalmente tenha uma carga útil diferente de zero, a especificação do ratchet [ECIES](/docs/specs/ecies/) não exige isso, então o tamanho mínimo da carga útil é 0. Os tamanhos mínimos do NSR podem ser calculados de acordo.

Análise de Sobrecarga

Troca de Chaves

Aumento de tamanho (bytes):

TypePubkey (NS)Ciphertext (NSR)
MLKEM512_X25519+816+784
MLKEM768_X25519+1200+1104
MLKEM1024_X25519+1584+1584
Velocidade:

Velocidades conforme relatadas pela CLOUDFLARE :

TypeRelative speed
X25519 DH/keygenbaseline
MLKEM5122.25x faster
MLKEM7681.5x faster
MLKEM10241x (same)
XK4x DH (keygen + 3 DH)
MLKEM512_X255194x DH + 2x PQ (keygen + enc/dec) = 4.9x DH = 22% slower
MLKEM768_X255194x DH + 2x PQ (keygen + enc/dec) = 5.3x DH = 32% slower
MLKEM1024_X255194x DH + 2x PQ (keygen + enc/dec) = 6x DH = 50% slower
## Análise de Segurança

As categorias de segurança NIST são resumidas no NIST-PQ-END slide 10. Critérios preliminares: Nossa categoria mínima de segurança NIST deve ser 2 para protocolos híbridos e 3 para PQ-only.

CategoryAs Secure As
1AES128
2SHA256
3AES192
4SHA384
5AES256
### Handshakes

Estes são todos protocolos híbridos. Provavelmente precisamos preferir MLKEM768; MLKEM512 não é seguro o suficiente.

Categorias de segurança NIST FIPS203 :

AlgorithmSecurity Category
MLKEM5121
MLKEM7683
MLKEM10245
## Preferências de Tipo

O tipo recomendado para suporte inicial, baseado na categoria de segurança e comprimento da chave, é:

MLKEM768_X25519 (tipo 6)

Notas de Implementação

Suporte de Biblioteca

As bibliotecas Bouncycastle, BoringSSL e WolfSSL agora suportam MLKEM. O suporte do OpenSSL está na versão 3.5 lançada em 8 de abril de 2025 OPENSSL .

Tunnels Compartilhados

A classificação/detecção automática de múltiplos protocolos nos mesmos túneis deve ser possível com base numa verificação do comprimento da mensagem 1 (New Session Message). Usando MLKEM512_X25519 como exemplo, o comprimento da mensagem 1 é 816 bytes maior que o protocolo ratchet atual, e o tamanho mínimo da mensagem 1 (com apenas um payload DateTime incluído) é 919 bytes. A maioria dos tamanhos da mensagem 1 com ratchet atual tem um payload inferior a 816 bytes, portanto podem ser classificados como ratchet não-híbrido. Mensagens grandes são provavelmente POSTs que são raros.

Portanto, a estratégia recomendada é:

  • Se a mensagem 1 for menor que 919 bytes, é o protocolo ratchet atual.
  • Se a mensagem 1 for maior ou igual a 919 bytes, provavelmente é MLKEM512_X25519. Tente MLKEM512_X25519 primeiro e, se falhar, tente o protocolo ratchet atual.

Isso deve nos permitir suportar eficientemente o ratchet padrão e o ratchet híbrido no mesmo destino, assim como anteriormente suportávamos ElGamal e ratchet no mesmo destino. Portanto, podemos migrar para o protocolo híbrido MLKEM muito mais rapidamente do que se não pudéssemos suportar protocolos duplos para o mesmo destino, porque podemos adicionar suporte MLKEM a destinos existentes.

As combinações suportadas obrigatórias são:

  • X25519 + MLKEM512
  • X25519 + MLKEM768
  • X25519 + MLKEM1024

As seguintes combinações podem ser complexas e NÃO são obrigatórias de serem suportadas, mas podem ser, dependendo da implementação:

  • Mais de um MLKEM
  • ElG + um ou mais MLKEM
  • X25519 + um ou mais MLKEM
  • ElG + X25519 + um ou mais MLKEM

Não é obrigatório suportar múltiplos algoritmos MLKEM (por exemplo, MLKEM512_X25519 e MLKEM_768_X25519) no mesmo destino. Escolha apenas um. Dependente da implementação.

Não é necessário suportar três algoritmos (por exemplo X25519, MLKEM512_X25519, e MLKEM769_X25519) no mesmo destino. A classificação e estratégia de repetição podem ser muito complexas. A configuração e interface de configuração podem ser muito complexas. Dependente da implementação.

Não é necessário suportar algoritmos ElGamal e híbridos no mesmo destino. ElGamal é obsoleto, e ElGamal + híbrido apenas (sem X25519) não faz muito sentido. Além disso, as mensagens de nova sessão ElGamal e híbridas são ambas grandes, então as estratégias de classificação frequentemente teriam que tentar ambas as descriptografias, o que seria ineficiente. Dependente da implementação.

Os clientes podem usar as mesmas chaves estáticas X25519 ou chaves diferentes para os protocolos X25519 e híbrido nos mesmos túneis, dependendo da implementação.

Sigilo de Encaminhamento

A especificação ECIES permite Garlic Messages no payload da New Session Message, o que permite a entrega 0-RTT do pacote de streaming inicial, geralmente um HTTP GET, juntamente com o leaseset do cliente. No entanto, o payload da New Session Message não possui forward secrecy. Como esta proposta está enfatizando forward secrecy aprimorado para ratchet, as implementações podem ou devem adiar a inclusão do payload de streaming, ou da mensagem de streaming completa, até a primeira Existing Session Message. Isso seria às custas da entrega 0-RTT. As estratégias também podem depender do tipo de tráfego ou tipo de tunnel, ou em GET vs. POST, por exemplo. Dependente da implementação.

Tamanho da Nova Sessão

MLKEM aumentará dramaticamente o tamanho da New Session Message, conforme descrito acima. Isso pode diminuir significativamente a confiabilidade da entrega da New Session Message através de tunnels, onde elas devem ser fragmentadas em múltiplas mensagens de tunnel de 1024 bytes. O sucesso da entrega é proporcional ao número exponencial de fragmentos. As implementações podem usar várias estratégias para limitar o tamanho da mensagem, à custa da entrega 0-RTT. Dependente da implementação.

Referências

Was this page helpful?