我正在编写一个应用程序,用户可以通过端到端加密在设备之间进行通信。为此,我使用libsodium加密库。非对称加密函数crypto_box(...)需要一个nonce作为参数之一。
我对如何处理nonce有点困惑。是否需要使用不同的nonce加密每个人的消息?这似乎不正确,因为我必须将使用过的nonces存储在具有公共访问权限的服务器上,攻击者可以再次使用其中一个使用过的nonce。
从A到B发送的所有消息是否都有不同的nonce,或者nonce是否可以用来从A发送消息到B不用于从C发送到B?
有人可以向我解释一下。
答案 0 :(得分:5)
是否需要使用不同的nonce加密每个人的消息?
是。实际上,从不,永远对同一私钥使用多个相同的nonce。确实,您必须跟踪nonce才能完成此任务。
这似乎不正确,因为我必须将使用过的nonces存储在具有公共访问权限的服务器上,攻击者可以再次使用其中一个使用过的nonce。
为什么要将你的随机数存储在具有公共访问权限的服务器上?你怎么认为攻击者能够"使用" nonce?他们需要您的私钥才能这样做。
为什么不能将nonce存储在与私钥相同的位置?
答案 1 :(得分:4)
使用给定的共享密钥发送的每条消息都需要唯一的随机数。 nonce不必是秘密的;一个简单的柜台完全没问题;更改nonce中的单个位将使密文看起来完全不同,即使两次发送相同的消息也是如此。
共同的秘密是什么?它是根据(A&#39的秘密密钥,B&#39的公钥)或(A&#39的公钥,B&#39的秘密密钥)计算的密钥。 A和B基于它们具有的内容执行不同的计算,但最终得到相同的共享秘密。
crypto_box
中使用的共享密钥长度为256位。这是巨大的。您可以放心地认为,共享秘密对于每个"会话来说都是唯一的。
因此,(A,B),(A,C)和(C,B)可以使用相同的随机数安全地交换消息。 但是如果A使用给定的随机数向B发送消息,则B不能使用相同的随机数向A发送消息。对于在A和B之间的对话期间交换的所有内容,Nonce必须是唯一的。
所以,一个简单的计数器就可以了。有一个选择偶数,将奇数留给B,每发送一条消息后将随机数增加2,你就可以了。
但是crypto_box
构造中使用的密码实际上具有非常大的随机数。 192位。
这意味着如果你忽略我写的所有内容,并且每次发送消息时都选择一个随机的随机数,那么发生碰撞的可能性非常小,你可以放心,它在实践中永远不会发生。
Sodium中包含的一些流密码(AES128-CTR,ChaCha20,Salsa20)具有较短的随机数,并且需要计数器以避免冲突。这就是他们进入"高级"文档部分。
但是对于crypto_box
和crypto_secretbox
,只需每次选择一个随机的随机数(randombytes_buf(nonce, sizeof nonce)
),您就会安全。