mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-11-11 22:50:59 +01:00
crypto: add FSChaCha20Poly1305, rekeying wrapper around ChaCha20Poly1305
This adds the FSChaCha20Poly1305 AEAD as specified in BIP324, a wrapper around the ChaCha20Poly1305 AEAD (as specified in RFC8439 section 2.8) which automatically rekeys every N messages, and automatically increments the nonce every message.
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
#include <crypto/chacha20.h>
|
||||
#include <crypto/poly1305.h>
|
||||
#include <span.h>
|
||||
#include <support/cleanse.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <cstdint>
|
||||
@@ -99,3 +100,41 @@ bool AEADChaCha20Poly1305::Decrypt(Span<const std::byte> cipher, Span<const std:
|
||||
m_chacha20.Crypt(UCharCast(cipher.data()), UCharCast(plain.data()), plain.size());
|
||||
return true;
|
||||
}
|
||||
|
||||
void AEADChaCha20Poly1305::Keystream(Nonce96 nonce, Span<std::byte> keystream) noexcept
|
||||
{
|
||||
// Skip the first output block, as it's used for generating the poly1305 key.
|
||||
m_chacha20.Seek64(nonce, 1);
|
||||
m_chacha20.Keystream(UCharCast(keystream.data()), keystream.size());
|
||||
}
|
||||
|
||||
void FSChaCha20Poly1305::NextPacket() noexcept
|
||||
{
|
||||
if (++m_packet_counter == m_rekey_interval) {
|
||||
// Generate a full block of keystream, to avoid needing the ChaCha20 buffer, even though
|
||||
// we only need KEYLEN (32) bytes.
|
||||
std::byte one_block[64];
|
||||
m_aead.Keystream({0xFFFFFFFF, m_rekey_counter}, one_block);
|
||||
// Switch keys.
|
||||
m_aead.SetKey(Span{one_block}.first(KEYLEN));
|
||||
// Wipe the generated keystream (a copy remains inside m_aead, which will be cleaned up
|
||||
// once it cycles again, or is destroyed).
|
||||
memory_cleanse(one_block, sizeof(one_block));
|
||||
// Update counters.
|
||||
m_packet_counter = 0;
|
||||
++m_rekey_counter;
|
||||
}
|
||||
}
|
||||
|
||||
void FSChaCha20Poly1305::Encrypt(Span<const std::byte> plain, Span<const std::byte> aad, Span<std::byte> cipher) noexcept
|
||||
{
|
||||
m_aead.Encrypt(plain, aad, {m_packet_counter, m_rekey_counter}, cipher);
|
||||
NextPacket();
|
||||
}
|
||||
|
||||
bool FSChaCha20Poly1305::Decrypt(Span<const std::byte> cipher, Span<const std::byte> aad, Span<std::byte> plain) noexcept
|
||||
{
|
||||
bool ret = m_aead.Decrypt(cipher, aad, {m_packet_counter, m_rekey_counter}, plain);
|
||||
NextPacket();
|
||||
return ret;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user