Skip to content

Conversation

jonasschnelli
Copy link
Contributor

This PR adds encryption to the p2p communication after a slightly overhauled version of BIP151 defined here (there is the plan to change BIP151 or to propose this protocol in a new BIP)

The encryption is optional and by default disabled (-netencryption).

If enabled, a peer connecting to another peer signalling NODE_ENCRYPTED (or added via -connect=) will try to do the proposed key handshake and continue with encrypted communication.

If enabled, peers can request (and perform) encrypted communications by sending a handshake request.

Peers not supporting encryption are still accepted (no option to enforce encrypted communication).

There is a plan to make the handshake quantum resistance by adding NewHope to the key handshake (https://newhopecrypto.org). But since this PR is already very large, it's unclear wether this should be an independent patch (probably another ~600 lines of code).

Out of scope:

  • optimized ChaCha20 implementation (for review and security reasons, the implementation is extracted from openssh)
  • benchmarks added to bench (I have done comparison against the v1 protocol with dbl-SHA256 the performance seems very similar)
  • Please no discussion about the used crypto scheme or the proposal itself (better place would be the mailing list)

TODO:

  • add option to -connect= RPC addnode where it is possible to specify the expected service flags (currently -connect= will always try for encrypted coms).

src/net.cpp Outdated
CNetMessage& msg = vRecvMsg.back();
if (vRecvMsg.empty() || vRecvMsg.back()->complete()) {
if (m_encryption_handler && m_encryption_handler->shouldCryptMsg()) {
vRecvMsg.emplace_back(std::make_shared<NetCryptedMessageEnvelop>(m_encryption_handler, Params().MessageStart(), SER_NETWORK, INIT_PROTO_VERSION));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Should this be ”envelope” instead of ”envelop”? If so, change applies throughout this PR and also the BIP.

src/init.cpp Outdated
@@ -477,6 +478,7 @@ void SetupServerArgs()
gArgs.AddArg("-maxtipage=<n>", strprintf("Maximum tip age in seconds to consider node in initial block download (default: %u)", DEFAULT_MAX_TIP_AGE), true, OptionsCategory::DEBUG_TEST);
gArgs.AddArg("-maxtxfee=<amt>", strprintf("Maximum total fees (in %s) to use in a single wallet transaction or raw transaction; setting this too low may abort large transactions (default: %s)",
CURRENCY_UNIT, FormatMoney(DEFAULT_TRANSACTION_MAXFEE)), false, OptionsCategory::DEBUG_TEST);
gArgs.AddArg("-netencryptionfastrekey", "Rekeys every 10 seconds and after 10kb of data", true, OptionsCategory::DEBUG_TEST);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I’m reading the logic correct then this should be ”every 10 seconds or after 10kb of data”?

src/net.cpp Outdated
msg->nTime = nTimeMicros;
if (msg->m_type == NetMessageType::PLAINTEXT_ENCRYPTION_HANDSHAKE && !msg->verifyHeader()) {
// message contains expected network magic and "version" message command
// threat as version message
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: “treat”

LOCK(cs);
if (m_bytes_decrypted + vsize > ABORT_LIMIT_BYTES || GetTime() - m_time_last_rekey_send > ABORT_LIMIT_TIME ||
(gArgs.GetBoolArg("-netencryptionfastrekey", false) && m_bytes_decrypted + vsize > 12 * 1024)) {
// don't further decrypt and therefor abort connection when counterparty failed to respect rekey limits
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: “therefore”?

}

virtual bool complete() const = 0;
virtual uint32_t getMessageSize() const = 0; //returns 0 when message hat not yet been parsed
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: “has”?

@DrahtBot
Copy link
Contributor

DrahtBot commented Aug 23, 2018

The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

Conflicts

Reviewers, this pull request conflicts with the following ones:

  • #16362 (gui: Bilingual translation by hebasto)
  • #16324 (Get cs_main out of the critical path in ProcessMessages by TheBlueMatt)
  • #16323 (Call ProcessNewBlock() asynchronously by TheBlueMatt)
  • #16273 (refactor: Remove unused includes by practicalswift)
  • #16248 (Make whitebind/whitelist permissions more flexible by NicolasDorier)
  • #16224 (gui: Bilingual GUI error messages by hebasto)
  • #16202 (Refactor network message deserialization by jonasschnelli)
  • #16097 (WIP: Prevent meaningless negating of arguments by hebasto)
  • #16060 (Bury bip9 deployments by jnewbery)
  • #15649 (Add ChaCha20Poly1305@Bitcoin AEAD by jonasschnelli)
  • #15505 ([p2p] Request NOTFOUND transactions immediately from other outbound peers, when possible by sdaftuar)
  • #15206 (Immediately disconnect on invalid net message checksum by jonasschnelli)
  • #15197 (Refactor and slightly stricter p2p message processing by jonasschnelli)
  • #14046 (net: Refactor message parsing (CNetMessage), adds flexibility by jonasschnelli)
  • #10102 ([experimental] Multiprocess bitcoin by ryanofsky)

If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

@jonasschnelli
Copy link
Contributor Author

Fixed @practicalswift points.

@gmaxwell
Copy link
Contributor

Great work!

Although optimized crypto is certainly out of scope, we do want to be mindful of making any protocol decisions that would preclude using them. :)

@jonasschnelli
Copy link
Contributor Author

jonasschnelli commented Aug 24, 2018

Note to reviewers: please review...

@luke-jr
Copy link
Member

luke-jr commented Aug 29, 2018

What is the point of NODE_ENCRYPTED? Service bits shouldn't be used for mere protocol negotiation...

@jonasschnelli
Copy link
Contributor Author

What is the point of NODE_ENCRYPTED? Service bits shouldn't be used for mere protocol negotiation...

This has now been discussed on IRC:
https://botbot.me/freenode/bitcoin-core-dev/2018-08-29/?msg=103889728&page=3

{
// first 3 bytes are the LE uint32 message length the most significant bit
// indicates to the counterparty that the next message will be using the next
// key (rekey) with resetted nonce
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be “reset”?

@DrahtBot
Copy link
Contributor

Needs rebase

PastaPastaPasta pushed a commit to PastaPastaPasta/dash that referenced this pull request Jan 25, 2020
…ate key

8794a4b QA: add test for HKDF HMAC_SHA256 L32 (Jonas Schnelli)
551d489 Add HKDF HMAC_SHA256 L=32 implementations (Jonas Schnelli)
3b64f85 QA: add test for CKey::Negate() (Jonas Schnelli)
463921b CKey: add method to negate the key (Jonas Schnelli)

Pull request description:

  This adds a limited implementation of `HKDF` (defined by rfc5869) that supports only HMAC-SHA256  and length output of 32 bytes (will be required for v2 transport protocol).

  This PR also includes a method to negate a private key which is useful to enforce public keys starting with 0x02 (or 0x03) (a requirement for the v2 transport protocol). The new `CKey::Negate()` method is pretty much a wrapper around `secp256k1_ec_privkey_negate()`.

  Including tests.

  This is a subset of bitcoin#14032 and a pre-requirement for the v2 transport protocol.

ACKs for commit 8794a4:

Tree-SHA512: 5341929dfa29f5da766ec3612784baec6a3ad69972f08b5a985a8aafdae4dae36f104a2b888d1f5d1f33561456bd111f960d7e32c2cc4fd18e48358468f26c1a
PastaPastaPasta pushed a commit to PastaPastaPasta/dash that referenced this pull request Jan 25, 2020
…ate key

8794a4b QA: add test for HKDF HMAC_SHA256 L32 (Jonas Schnelli)
551d489 Add HKDF HMAC_SHA256 L=32 implementations (Jonas Schnelli)
3b64f85 QA: add test for CKey::Negate() (Jonas Schnelli)
463921b CKey: add method to negate the key (Jonas Schnelli)

Pull request description:

  This adds a limited implementation of `HKDF` (defined by rfc5869) that supports only HMAC-SHA256  and length output of 32 bytes (will be required for v2 transport protocol).

  This PR also includes a method to negate a private key which is useful to enforce public keys starting with 0x02 (or 0x03) (a requirement for the v2 transport protocol). The new `CKey::Negate()` method is pretty much a wrapper around `secp256k1_ec_privkey_negate()`.

  Including tests.

  This is a subset of bitcoin#14032 and a pre-requirement for the v2 transport protocol.

ACKs for commit 8794a4:

Tree-SHA512: 5341929dfa29f5da766ec3612784baec6a3ad69972f08b5a985a8aafdae4dae36f104a2b888d1f5d1f33561456bd111f960d7e32c2cc4fd18e48358468f26c1a
Signed-off-by: Pasta <pasta@dashboost.org>
CNetMessage& msg = vRecvMsg.back();
if (vRecvMsg.empty() || vRecvMsg.back()->Complete()) {
if (m_encryption_handler && m_encryption_handler->ShouldCryptMsg()) {
vRecvMsg.emplace_back(MakeUnique<NetV2Message>(m_encryption_handler, Params().MessageStart(), SER_NETWORK, INIT_PROTO_VERSION));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UdjinM6 pushed a commit to UdjinM6/dash that referenced this pull request Aug 10, 2021
…ate key

8794a4b QA: add test for HKDF HMAC_SHA256 L32 (Jonas Schnelli)
551d489 Add HKDF HMAC_SHA256 L=32 implementations (Jonas Schnelli)
3b64f85 QA: add test for CKey::Negate() (Jonas Schnelli)
463921b CKey: add method to negate the key (Jonas Schnelli)

Pull request description:

  This adds a limited implementation of `HKDF` (defined by rfc5869) that supports only HMAC-SHA256  and length output of 32 bytes (will be required for v2 transport protocol).

  This PR also includes a method to negate a private key which is useful to enforce public keys starting with 0x02 (or 0x03) (a requirement for the v2 transport protocol). The new `CKey::Negate()` method is pretty much a wrapper around `secp256k1_ec_privkey_negate()`.

  Including tests.

  This is a subset of bitcoin#14032 and a pre-requirement for the v2 transport protocol.

ACKs for commit 8794a4:

Tree-SHA512: 5341929dfa29f5da766ec3612784baec6a3ad69972f08b5a985a8aafdae4dae36f104a2b888d1f5d1f33561456bd111f960d7e32c2cc4fd18e48358468f26c1a
5tefan pushed a commit to 5tefan/dash that referenced this pull request Aug 12, 2021
…ate key

8794a4b QA: add test for HKDF HMAC_SHA256 L32 (Jonas Schnelli)
551d489 Add HKDF HMAC_SHA256 L=32 implementations (Jonas Schnelli)
3b64f85 QA: add test for CKey::Negate() (Jonas Schnelli)
463921b CKey: add method to negate the key (Jonas Schnelli)

Pull request description:

  This adds a limited implementation of `HKDF` (defined by rfc5869) that supports only HMAC-SHA256  and length output of 32 bytes (will be required for v2 transport protocol).

  This PR also includes a method to negate a private key which is useful to enforce public keys starting with 0x02 (or 0x03) (a requirement for the v2 transport protocol). The new `CKey::Negate()` method is pretty much a wrapper around `secp256k1_ec_privkey_negate()`.

  Including tests.

  This is a subset of bitcoin#14032 and a pre-requirement for the v2 transport protocol.

ACKs for commit 8794a4:

Tree-SHA512: 5341929dfa29f5da766ec3612784baec6a3ad69972f08b5a985a8aafdae4dae36f104a2b888d1f5d1f33561456bd111f960d7e32c2cc4fd18e48358468f26c1a
@fanquake
Copy link
Member

My understanding is that someone else is helping with / taking over these changes, and that the BIP is still being overhauled.
I think we'll be better off with new PRs, and clean discussion when work on the implementation resumes in this repo.
Changes from here are be cherry-picked if / when needed. So I'm going to close this PR for now.

@fanquake fanquake closed this Aug 18, 2021
@michaelfolkson
Copy link

michaelfolkson commented Aug 23, 2021

For additional context on above from @fanquake BIP 151 has been withdrawn, the replacement is BIP 324 and the point of contact for BIP 324 appears to be @dhruv from this point on.

gades pushed a commit to cosanta/cosanta-core that referenced this pull request May 8, 2022
…ate key

8794a4b QA: add test for HKDF HMAC_SHA256 L32 (Jonas Schnelli)
551d489 Add HKDF HMAC_SHA256 L=32 implementations (Jonas Schnelli)
3b64f85 QA: add test for CKey::Negate() (Jonas Schnelli)
463921b CKey: add method to negate the key (Jonas Schnelli)

Pull request description:

  This adds a limited implementation of `HKDF` (defined by rfc5869) that supports only HMAC-SHA256  and length output of 32 bytes (will be required for v2 transport protocol).

  This PR also includes a method to negate a private key which is useful to enforce public keys starting with 0x02 (or 0x03) (a requirement for the v2 transport protocol). The new `CKey::Negate()` method is pretty much a wrapper around `secp256k1_ec_privkey_negate()`.

  Including tests.

  This is a subset of bitcoin#14032 and a pre-requirement for the v2 transport protocol.

ACKs for commit 8794a4:

Tree-SHA512: 5341929dfa29f5da766ec3612784baec6a3ad69972f08b5a985a8aafdae4dae36f104a2b888d1f5d1f33561456bd111f960d7e32c2cc4fd18e48358468f26c1a
@bitcoin bitcoin locked as resolved and limited conversation to collaborators Aug 24, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
No open projects
Status: Closed unmerged (Superseded)
Development

Successfully merging this pull request may close these issues.

9 participants