特定の共有秘密鍵を使用して送信されるすべてのメッセージには、一意の nonce が必要です。nonce は秘密である必要はありません。シンプルなカウンターで十分です。ノンスの 1 ビットを変更すると、同じメッセージが 2 回送信されたとしても、暗号文がまったく異なるものに見えます。
共有シークレットとは何ですか? (A の秘密鍵、B の公開鍵) または (A の公開鍵、B の秘密鍵) から計算された鍵です。A と B は、持っているものに基づいて異なる計算を実行しますが、最終的に同じ共有シークレットになります。
で使用される共有シークレットcrypto_box
は 256 ビット長です。これは巨大です。共有シークレットは「会話」ごとに一意になると安全に考えることができます。
したがって、(A, B)、(A, C)、および (C, B) は、同じノンスを使用して安全にメッセージを交換できます。しかし、A が特定の nonce を使用して B にメッセージを送信した場合、B は同じ nonce を使用して A にメッセージを送信できません。ノンスは、A と B の間の会話中に交換されるすべてのものに対して一意である必要があります。
したがって、単純なカウンターで問題ありません。A に偶数を選択させ、奇数を B に任せ、メッセージが送信されるたびに nonce を 2 ずつ増やして、準備完了です。
しかし、構築に使用される暗号crypto_box
には、実際には非常に大きなナンスがあります。192 ビット。
つまり、私が書いたことをすべて無視して、メッセージを送信するたびにランダムなノンスを選択するだけであれば、衝突が発生する確率は非常に小さいため、実際には決して起こらないことを確信できます。
Sodium に含まれる一部のストリーム暗号 (AES128-CTR、ChaCha20、Salsa20) はナンスが短く、衝突を避けるためにカウンターが必要です。これが、ドキュメントの「高度な」セクションにある理由です。
しかし、crypto_box
と を使用するとcrypto_secretbox
、毎回 ( randombytes_buf(nonce, sizeof nonce)
) ランダムなノンスを選択するだけで安全になります。