Open bcomnes opened 4 years ago
I started some work on the easy parts here: https://github.com/bcomnes/sodium-javascript/tree/noise-support
Those primitives will be good regardless, but I will change the primitives in noise-protocol soon so they conform with most other implementations out there. This means I will do chacha20-poly1305 soon
Since these are brand new primitives, maybe you want to split them into a separate file like we started doing on some of the newly implemented ones?
maybe you want to split them into a separate file like we started doing on some of the newly implemented ones?
Yeah agreed, I was sort of just feeling my way around. I'll split those out.
I will change the primitives in noise-protocol soon so they conform with most other implementations out there. This means I will do chacha20-poly1305 soon
You mean instead of the crypto_kx_*
primitives, switch to the chacha20-poly1305 primitives?
I'm taking a stab at a hchacha20 .wat implementation. I'll post if I can get it working.
Thank you for the input!
I started a WAT implementation in https://github.com/little-core-labs/hchacha20/blob/master/hchacha20.wat
Has anyone spotted a good way to port macro blocks?
I presume just type it out is the most straight forward option.
Completed hchacha20: https://github.com/little-core-labs/hchacha20/blob/master/hchacha20.wat
Time to see if it works.
@bcomnes did it work? :)
@cblgh had to step away from the project. 2 observations:
https://github.com/tinchoz49/workaround-hypercore8-browser
Hey everyone! this is a workaround example that I did using sodium-javascript and adding the missing crypto functions from libsodium.js.
It's just an example to check what we need to get hypercore 8 working on the browser.
libsodium.js has everything what we need but:
So I think updating sodium-javascript could be the first option.
Nice demo @tinchoz49! Even with handrolled sodium-javascript I don't know what kind of performance we can expect, but probably 2 - 4 times slower than sodium-native (just from intuition, no benchmarks to base this on)
Thank you @emilbayes ! My benchmark was very poor but it was more for investigation purpose, since I cannot test the xchacha20 functions in sodium-javascript i just run a common crypto_secretbox:
const bench = require('nanobench')
const sodium = require('sodium-native')
const sodiumjs = require('sodium-javascript')
const libsodium = require('libsodium-wrappers')
libsodium.ready.then(() => {
bench('sodium-native', function (b) {
b.start()
for (let i = 0; i < 5000; i++) {
var nonce = Buffer.alloc(sodium.crypto_secretbox_NONCEBYTES)
var key = sodium.sodium_malloc(sodium.crypto_secretbox_KEYBYTES) // secure buffer
var message = Buffer.from('Hello, World!')
var ciphertext = Buffer.alloc(message.length + sodium.crypto_secretbox_MACBYTES)
sodium.randombytes_buf(nonce) // insert random data into nonce
sodium.randombytes_buf(key) // insert random data into key
// encrypted message is stored in ciphertext.
sodium.crypto_secretbox_easy(ciphertext, message, nonce, key)
var plainText = Buffer.alloc(ciphertext.length - sodium.crypto_secretbox_MACBYTES)
sodium.crypto_secretbox_open_easy(plainText, ciphertext, nonce, key)
}
b.end()
})
bench('sodium-javascript', function (b) {
b.start()
const sodium = sodiumjs
for (let i = 0; i < 5000; i++) {
var nonce = Buffer.alloc(sodium.crypto_secretbox_NONCEBYTES)
var key = sodium.sodium_malloc(sodium.crypto_secretbox_KEYBYTES) // secure buffer
var message = Buffer.from('Hello, World!')
var ciphertext = Buffer.alloc(message.length + sodium.crypto_secretbox_MACBYTES)
sodium.randombytes_buf(nonce) // insert random data into nonce
sodium.randombytes_buf(key) // insert random data into key
// encrypted message is stored in ciphertext.
sodium.crypto_secretbox_easy(ciphertext, message, nonce, key)
var plainText = Buffer.alloc(ciphertext.length - sodium.crypto_secretbox_MACBYTES)
sodium.crypto_secretbox_open_easy(plainText, ciphertext, nonce, key)
}
b.end()
})
bench('libsodium.js', function (b) {
b.start()
const sodium = libsodium
for (let i = 0; i < 5000; i++) {
var key = Buffer.alloc(sodium.crypto_secretbox_KEYBYTES) // secure buffer
var message = Buffer.from('Hello, World!')
var nonce = sodium.randombytes_buf(sodium.crypto_secretbox_NONCEBYTES)
var ciphertext = sodium.crypto_secretbox_easy(message, nonce, key)
var plainText = sodium.crypto_secretbox_open_easy(ciphertext, nonce, key)
}
b.end()
})
})
ok ~162 ms (0 s + 161726505 ns)
ok ~101 ms (0 s + 100917442 ns)
ok ~372 ms (0 s + 372270050 ns)
If we choose to use libsodium.js we can do a wrapper to provide the same API than sodium-native have. My only concern is about the async nature of loading a wasm library, that breaks everything.
We can compile libsodium.js using the emscripten flag BINARYEN_ASYNC_COMPILATION=0 ?
If we use libsodium.js we would have full support of sodium for the browser, that's a good point I guess.
We have plans to to the remaining ciphers in wasm :) The async'ness is unfortunately a question of binary size
The async'ness is unfortunately a question of binary size
That's true.
I'm working on a minimal version of sodium in wasm based on libsodium.js that we can load sync in the browser (thinking about the 4kb limitation of chrome)
Initially, it will have only the necessary to run the missing operations that we need for noise-protocol:
But my idea is to build something that we can extend in the future to add the rest of the operations to have everything in wasm.
I will try to publish next week :crossed_fingers:
https://github.com/geut/sodium-javascript-plus
Experimental support of xchacha20 and kx for sodium-javascript.
And updated the example: https://github.com/tinchoz49/workaround-hypercore8-browser
Performance is about 3x slow than sodium-native but faster than libsodium.js
👏 👏 👏 👏 👏 👏
nice job @tinchoz49!
Great work @tinchoz49 !
It would be great if the noise-protocol module would work with sodium universal.
From what I can gather the following parts of sodium need to be ported:
The key exchange looks relatively straight forward, the
crypto_aead_xchacha20poly1305_ietf
end of things looks a bit more involved (e.g. reimplementing https://github.com/jedisct1/libsodium/blob/927dfe8e2eaa86160d3ba12a7e3258fbc322909c/src/libsodium/crypto_core/hchacha20/core_hchacha20.c or doing some kind of WAT rewrite like xsalsa20 ?@emilbayes do you have any pointers on how you would go about doing that?