Qual deve ser o valor nonce para criptografia do lado do cliente?

Oct 11 2020

Estou usando a seguinte biblioteca Rust chacha20poly1305 para criptografar alguns dados em um aplicativo de desktop. O usuário fornece a chave, que nunca sai do dispositivo, para criptografar localmente alguns dados e, em seguida, os dados criptografados são enviados a um servidor para fins de backup.

Esta biblioteca requer um nonce para criptografar os dados e não tenho certeza de qual deve ser esse valor. Idealmente, o usuário poderia recuperar esses dados criptografados apenas com sua chave. No entanto, para descriptografar quaisquer dados, o nonce também é necessário. Codificar algum nonce no aplicativo parece estranho, mas se eu gerar um nonce aleatoriamente, o usuário será solicitado a lembrar desse nonce junto com a chave fornecida para recuperar os dados criptografados.

Respostas

14 kelalaka Oct 11 2020 at 18:53

A biblioteca usa XChaCha20Poly1305e requer um nonce de 192 bits (24 bytes). É uma extensão do ChaCha20Poly1305 para aumentar o tamanho do nonce, ChaCha20 tinha nonces de 96 bits. Não existe um padrão para isso, apenas um rascunho em ietf.org

O nonce é um acrônimo para 'número usado uma vez'. O ponto crucial é que nunca se deve usar o par (Key, nonce) novamente. Nós o chamamos de uso indevido de uso não autorizado. Se isso ocorrer, a confidencialidade é perdida, pois o invasor pode usar a técnica de arrastar no berço para revelar os dois textos simples. Existe até uma abordagem automatizada para resolvê-lo:

  • Uma abordagem de linguagem natural para criptoanálise automatizada de blocos de duas vezes por Mason et al

Ou para exemplos detalhados, veja a resposta desta pergunta;

  • Aproveitando a reutilização única de teclas do teclado?

Para nonces de 192 bits, a geração aleatória de nonce é segura, pois de acordo com o paradoxo do aniversário, você precisaria criptografar $2^{96}$mensagens sob a mesma chave para atingir o mesmo nonce novamente com 50% de probabilidade, então você deve criptografar bem menos mensagens para garantir que essa probabilidade seja insignificante. Lembre-se de que você precisa usar um bom gerador de números aleatórios como /dev/urandom. Você ainda pode usar nonces baseados em contador, se quiser.

Não tenho certeza de qual deveria ser esse valor. O ideal é que o usuário possa recuperar esses dados criptografados apenas com sua chave.

O nonce não precisa ser secreto e pode ser salvo junto com o arquivo sem ser criptografado. Isso não é insegurança, apenas a chave é secreta. O nonce ajuda a usar uma chave com segurança mais de uma vez. É seguro desde que um par (chave, nonce) nunca ocorra duas vezes.

No entanto, para descriptografar quaisquer dados, o nonce também é necessário.

Isso é completamente normal, pois a descriptografia é o inverso da criptografia com a mesma chave e nonce. XChaCha20Poly1305gera um fluxo e o usamos para x ou o texto simples. Para regenerar o fluxo, precisamos usar as mesmas entradas.

Codificar algum nonce no aplicativo parece estranho, mas se eu gerar um nonce aleatoriamente, o usuário será solicitado a lembrar desse nonce junto com a chave fornecida para recuperar os dados criptografados.

A codificação permanente de um nonce não é aceitável, pois seria usado mais de uma vez. Não há problema em lembrar o nonce, é seguro. Salve-o em um arquivo como$$nonce\mathbin\|encryptedFile\|tag.$$

Nota 1: O XChaCha20Poly1305é uma criptografia autenticada , que fornecerá confidencialidade, integridade e autenticação se usado corretamente. Tags incorretas não devem ser ignoradas durante a descriptografia. Se a tag não corresponder, emita um erro.

  • Encriptação

    $$(c,tag)= XChaCha20Poly1305Enc(key,nonce,message)$$

  • Decifrar

    $$(m|\perp) = XChaCha20Poly1305Dec(key,nonce,c)$$

    Onde $\perp$( \perp) é a parada se a tag for incompatível.

Observação 2: houve uma pergunta recente sobre É perigoso criptografar muitos arquivos pequenos com a mesma chave? . Pode-se usar a ideia semelhante para gerar chaves diferentes para cada arquivo também.

Uma observação final: se você criptografar e atualizar os dados várias vezes com a mesma chave e nonce, isso também pode causar o uso incorreto de nonce e alguma parte da versão nova e antiga do arquivo pode perder a confidencialidade. Portanto, para cada atualização, use um novo nonce e criptografe o arquivo novamente.

3 IlmariKaronen Oct 11 2020 at 18:53

Você deve gerar um * nonce aleatório e armazená-lo junto com o texto cifrado, por exemplo, prefixado a ele.

Ambos ChaCha20 e Poly1305 requerem um nonce exclusivo para ser usado para cada criptografia, caso contrário, eles não serão seguros. No entanto, o nonce não precisa ser mantido em segredo , portanto, você pode simplesmente incluí-lo com o texto cifrado.


*) Tecnicamente, o nonce para ChaCha20 – Poly1305 só precisa ser único, não aleatório, mas tornar o nonce aleatório e suficientemente longo geralmente é a maneira mais fácil de garantir a exclusividade em um sistema distribuído. O uso de nonces aleatórios de 96 bits, gerado com um RNG criptograficamente seguro, permitirá que você criptografe com segurança até 2 32 mensagens por chave, tendo no máximo um risco de um em 2 32 de uma colisão de nonce.

Se você não confia 100% em seu RNG (o que poderia ser uma precaução sensata, dados os vários notáveis ​​bugs de RNG do sistema operacional no passado), uma possível abordagem de "cinto e suspensórios" poderia ser concatenar a saída do RNG (de pelo menos 96 bits) com um carimbo de data / hora de alta resolução, um ID de usuário (se houver) e qualquer outra entrada distinta que você possa imaginar, insira todos em uma função de hash criptográfica como SHA-256, trunque o resultado para 96 ​​bits e use isso como seu nonce. Dessa forma, enquanto as entradas de hash para duas criptografias não fazer tudo o jogo, as saídas quase certamente será diferente.

(Em princípio, você pode até incluir a chave de criptografia e a mensagem de texto simples como entradas hash adicionais para derivação nonce. Nesse ponto, você está prestes a reinventar o SIV .)

Guy Oct 12 2020 at 20:45

Outra opção seria armazenar o nonce no lado do servidor com os dados criptografados ou em serviço externo. Dessa forma, você não precisa que o usuário o guarde ou mesmo esteja ciente dele e seu aplicativo deve saber como buscá-lo para descriptografá-lo quando necessário.