-
Notifications
You must be signed in to change notification settings - Fork 35
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
Networking: NOISE handshake and transport encryption #92
Comments
Some more investigations into the transport encryption after the handshake is complete: The NOISE spec states with regard to transport messages:
and also
(which in my tests was very true - the hypercore-protocol in transport uses a streaming XSalsa20 cipher from libsodium, where the docs state:
So hypercore-protocol follows NOISE for the handshake, but does not use NOISE for the transport encryption, instead it uses XSalsa20 for streaming encryption with no authentication tags and no need for length-delimited messages for the decryption. This means that by-the-spec NOISE frameworks cannot be used for the transport phase of a hypercore-protocol stream. |
@mafintosh / @emilbayes: Could you check if these findings about hypercore-protocol are correct, and clarify if there's a reason why hypercore-protocol does not stick to the NOISE spec for the transport phase? |
I pushed a client/server example of how far I got with the handshaking, see here for details. |
There are some things I did in noise-protocol that are "non-standard" but that I want to fix:
The above points I am going to remedy soon, but these are also the only parts that are noise here. The rest is how hypercore has decided to use noise under various constraints. I know that hypercore uses "dummy keys" and I think it uses "channel binding" as part of the new capabilities system. The application responsibilities also makes it more tricky to get different implementations to talk to each other: http://www.noiseprotocol.org/noise.html#application-responsibilities Maybe it's worth it to consider using a pregenerated noise implementation from https://noiseexplorer.com and modify that to how hypercore uses noise? |
@emilbayes cool, thanks for this info. With your I set up a repo to better test this: https://github.com/Frando/rust-node-noise-handshake Feel free to chime in there or help to debug :-D could also be a good base for proper integration tests, it has a one-command runner that starts both server and client. |
Now some more progress here, yeeha: https://github.com/Frando/hypercore-protocol-rs With the Also if someone would want to review the API and implementation of the repo linked above, I'd be very interested 😄 |
This is all fixed and can be closed :) See hypercore-protocol-rs. My PRs to snow got merged, and the new Hypercore 9 release switched the handshake algorithm. It also switched the handshake cipher from Anyway - the master branch of hypercore-protocol-rs can handshake, verify cabalities and exchange all messages with a nodejs hypercore now. Once snow gets a new release, I'll publish a first preview release. |
For a working Dat2 / hypercore 8 implementation in Rust, we'll have to implement the NOISE handshaking and transport encryption.
I'll document what I found out while looking into this.
I don't think there's any "official" documentation about the NOISE handshake and transport encryption in hypercore yet. Looking into the code reveals:
Noise_XX_25519_XChaChaPoly_BLAKE2
(see noise-protocol/handshake-state and simple-hypercore-protocol/handshake). The handshake uses a state machine module called simple-handshake, which then uses noise-protocol, a Javascript implementation of some parts of the NOISE spec that uses sodium-native for the actual crypto.payload
being transmitted from each side is a protocol buffers encoded message with a 24 byte nonce (random bytes), created in simple-hypercore-protocol/index.jssodium.crypto_stream_xor
(see simple-hypercore-protocol/lib/xor.js and the sodium docs), with instances for receiving and transmitting, where for each the keys are coming from thesplit
result of the NOISE handshake and the nonces are the payloads that were transmitted during the handshake.sodium.crypto_stream_xor
resolves tocrypto_stream_xsalsa20_xor
which, in sodium-native, uses crypto_stream_xsalsa20I tried to connect to a nodejs hypercore-protocol stream from Rust, however I hit a few roadblocks. I started with snow as it seems to be the most complete NOISE impl in rust. Following are, I think, what's missing to make connecting to a hypercore-protocol stream:
XChaChaPoly
cipher. I created an issue for that. There's a rust impl of XChaChaPoly in chacha20poly1305.split
results directlyThe text was updated successfully, but these errors were encountered: