Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
251x->input[13] = j13;252return;253}254bytes -= 64;255c += 64;256m += 64;257}258}260void ECRYPT_keystream_bytes(ECRYPT_ctx* x, u8* stream, u32 bytes)261{262u32 i;263for (i = 0; i < bytes; ++i)264stream[i] = 0;265ECRYPT_encrypt_bytes(x, stream, stream, bytes);266}268FUZZ_TARGET(crypto_diff_fuzz_chacha20)269{270FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};272ECRYPT_ctx ctx;274const std::vector<unsigned char> key = ConsumeFixedLengthByteVector(fuzzed_data_provider, 32);275ChaCha20 chacha20{MakeByteSpan(key)};276ECRYPT_keysetup(&ctx, key.data(), key.size() * 8, 0);278// ECRYPT_keysetup() doesn't set the counter and nonce to 0 while SetKey() does279static const uint8_t iv[8] = {0, 0, 0, 0, 0, 0, 0, 0};280ChaCha20::Nonce96 nonce{0, 0};281uint32_t counter{0};282ECRYPT_ivsetup(&ctx, iv);284LIMITED_WHILE (fuzzed_data_provider.ConsumeBool(), 3000) {285CallOneOf(286fuzzed_data_provider,287[&] {288const std::vector<unsigned char> key = ConsumeFixedLengthByteVector(fuzzed_data_provider, 32);289chacha20.SetKey(MakeByteSpan(key));290nonce = {0, 0};291counter = 0;292ECRYPT_keysetup(&ctx, key.data(), key.size() * 8, 0);293// ECRYPT_keysetup() doesn't set the counter and nonce to 0 while SetKey() does294uint8_t iv[8] = {0, 0, 0, 0, 0, 0, 0, 0};295ECRYPT_ivsetup(&ctx, iv);296},297[&] {298uint32_t iv_prefix = fuzzed_data_provider.ConsumeIntegral<uint32_t>();299uint64_t iv = fuzzed_data_provider.ConsumeIntegral<uint64_t>();300nonce = {iv_prefix, iv};301counter = fuzzed_data_provider.ConsumeIntegral<uint32_t>();302chacha20.Seek(nonce, counter);303ctx.input[12] = counter;304ctx.input[13] = iv_prefix;305ctx.input[14] = iv;306ctx.input[15] = iv >> 32;307},308[&] {309uint32_t integralInRange = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 4096);310std::vector<uint8_t> output(integralInRange);311chacha20.Keystream(MakeWritableByteSpan(output));312std::vector<uint8_t> djb_output(integralInRange);313ECRYPT_keystream_bytes(&ctx, djb_output.data(), djb_output.size());314assert(output == djb_output);315// DJB's version seeks forward to a multiple of 64 bytes after every operation. Correct for that.316uint32_t old_counter = counter;317counter += (integralInRange + 63) >> 6;318if (counter < old_counter) ++nonce.first;319if (integralInRange & 63) {320chacha20.Seek(nonce, counter);321}322assert(counter == ctx.input[12]);323},324[&] {325uint32_t integralInRange = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 4096);326std::vector<uint8_t> output(integralInRange);327const std::vector<uint8_t> input = ConsumeFixedLengthByteVector(fuzzed_data_provider, output.size());328chacha20.Crypt(MakeByteSpan(input), MakeWritableByteSpan(output));329std::vector<uint8_t> djb_output(integralInRange);330ECRYPT_encrypt_bytes(&ctx, input.data(), djb_output.data(), input.size());331assert(output == djb_output);332// DJB's version seeks forward to a multiple of 64 bytes after every operation. Correct for that.333uint32_t old_counter = counter;334counter += (integralInRange + 63) >> 6;335if (counter < old_counter) ++nonce.first;336if (integralInRange & 63) {337chacha20.Seek(nonce, counter);338}339assert(counter == ctx.input[12]);340});341}342}
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.