-
Notifications
You must be signed in to change notification settings - Fork 2.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
multi: introduce v2transport and implement BIP324 #2260
base: master
Are you sure you want to change the base?
Conversation
The BIP324 ElligatorSwift test vectors are also included.
This package introduces FSChaCha20 and FSChaCha20Poly1305 primitives that are behind the v2 encrypted handshake. Handshake code is also introduced which allows a caller to initiate a v2 handshake.
This adds the v2 software flag to the list of services btcd supports and adds functionality to optionally use v2 transport if the peer supports it.
cc: @kcalvinalvin for review |
Haven’t yet taken a look at other parts in details but seems like the PR is missing Should add
here: Lines 72 to 105 in 24eb815
And other necessary code at: Lines 2723 to 2743 in 24eb815
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Initial round of review. Went through BIP324 and compared the flows and the pseudocode provided in the BIP with the code in transport.go
and chacha.go
if err != nil { | ||
return err | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like we’re missing the check for the below which is stated in bip324.
If the first 4 received bytes do not match the network magic,
but the 12 bytes after that do match the version message
encoding above, implementations may interpret this as a v1
peer of a different network, and disconnect them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh hmm seems like this is just the pseudocode specified in the BIP. Maybe it's the BIP text that I'm confusing.
return err | ||
} | ||
|
||
var data []byte |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can allocate here instead of the append at the bottom doing the allocation for us.
data := make([]byte, 0, 64+garbageLen)
|
||
versionBytes := []byte("version\x00\x00\x00\x00\x00") | ||
|
||
v1Prefix = append(v1Prefix, magic[:]...) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can pre-allocate v1Prefix
v1Prefix := make([]byte, 0, 4+12)
|
||
// Send over our ElligatorSwift-encoded pubkey followed by our | ||
// randomly generated garbage. | ||
var data []byte |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here. Can pre-allocate.
data := make([]byte, 0, 64+garbageLen)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually maybe refactor this out into a function since it's the same exact code.
|
||
var receivedPrefix []byte | ||
if initiating { | ||
receivedPrefix = make([]byte, 0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't do anything right? Maybe something like
receivedPrefix = make([]byte, 0, 64)
Since the length is still 0 but you've now pre-allocated.
func NewFSChaCha20(initialKey []byte) (*FSChaCha20, error) { | ||
var initialNonce [12]byte | ||
numRekeys := 0 | ||
binary.LittleEndian.PutUint64(initialNonce[4:12], uint64(numRekeys)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/uint64(numRekeys)/0
? Since we're not using numRekeys
anywhere else.
|
||
header := []byte{byte(ignoreNum)} | ||
|
||
plaintext := make([]byte, 0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can pre-allocate here:
// 1 for the header
plaintext := make([]byte, 0, contentLen+1)
return nil, 0, err | ||
} | ||
|
||
encPacket := make([]byte, 0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can pre-allocate here:
encPacket := make([]byte, 0, len(encContentsLen)+len(aeadCiphertext))
return nil, err | ||
} | ||
|
||
plaintext, err := p.recvP.Decrypt(aad, aeadCiphertext) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the BIP there's a check to see if the plaintext is nil or empty. Not sure if this is a requirement or implementation specific but brining it up just to sanity check
// XOR the text with the keystream to get either the cipher or plaintext. | ||
textLen := len(text) | ||
dst := make([]byte, textLen) | ||
f.cipher.XORKeyStream(dst, text) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we not need th block_counter
that's mentioned in the BIP because the standard library handles it all for us? Was a bit confused reading the code for Crypt
since it was missing get_keystream_bytes
and was wondering if the relevant code isn't needed for us.
WriteV2MessageN should allow specify the garbage []byte, if nil default garbage is used Rationale: this will permit custom nonstandard packets communication in the protocol, while still being compatible with bitcoin. |
It would be great if v2transport wasn't promoted to go module to ease reviewing |
Depends on #2219
This PR implements the BIP324 encrypted version 2 handshake. The service flag is added to the list of supported services so that btcd will optimistically try to make v2 connections.