Closed creationix closed 7 years ago
The crypto_stream*
API is frequently misunderstood, and rarely useful now that we haverandombytes_deterministic()
.
Still, all the functions are available; what is actually missing is a bunch of high-level JS wrappers. A wrapper for a given function is defined as a JSON file in wrapper/symbols
.
You add implement new ones based on the existing crypto_stream
ones. Then, if you have emscripten installed, "make" will take forever, but will eventually rebuild the final JS files.
Thanks, I'll rebuild later to tweak the bundle for my app.
What would be the recommended way to get a TLS/SSL-like stream given a pair of shared keys (the output of key exchange)? Streams tend to be TCP, UDP, UTP, or Websocket. Websocket has message framing built in, but TCP doesn't and UDP doesn't guarantee order or reliability of messages. (I think UTP is similar to TCP in it's promises)
I could talk to the dat people and see if they'd like to evolve their protocol to use something better supported.
Also I'm still not sure I'm going to be using dat itself for my product. If I end up rolling my own protocol, then I surely have the flexibility to change the encryption.
Do you need something that would work with all these transports (TCP + UDP + UTP + Websocket) or just one of them?
The protocol priorities are probably in this order: UTP, Websocket, TCP, WebRTC DataChannel (not sure which configuration), UDP.
I'm open to suggestions. Currently in DAT, they assume something with TCP-like promises.
Also, where is this randombytes_deterministic()
? Sounds like a nice high-level version of the xor stream.
Found the randombytes, do you think this is safe?
window.sodium = { onload ({
from_string,
to_string,
randombytes_SEEDBYTES,
randombytes_buf,
randombytes_buf_deterministic,
crypto_generichash
}) {
function encryptedStream (key) {
let seed = key
return function (message) {
if (typeof message === 'string') message = from_string(message)
seed = crypto_generichash(randombytes_SEEDBYTES, seed)
let output = randombytes_buf_deterministic(message.length, seed)
for (let i = 0; i < message.length; i++) {
output[i] ^= message[i]
}
return output
}
}
let key = randombytes_buf(randombytes_SEEDBYTES)
let encrypt = encryptedStream(key)
let decrypt = encryptedStream(key)
let plain = 'Hello World\n'
console.log({plain})
let encrypted = encrypt(plain)
console.log({encrypted})
let original = to_string(decrypt(encrypted))
console.log({original})
}}
The assumption here is key
is derived from key exchange.
Just wrote some fresh documentation for you!
https://download.libsodium.org/doc/secret-key_cryptography/secretstream.html https://download.libsodium.org/doc/secret-key_cryptography/encrypted-messages.html
Your code snippet works, but the data can be modified without this being detected. Is it what you want?
You mean the stream is unauthenticated? Yes, I'm aware of that. The actual protocol over the wire uses merkle trees with blake2b hashes, and signed roots using ed25519.
But it sounds like the preferred way is to use the one-off authenticated encryption methods with counting nonces or something?
@jedisct1
I'm experimenting with writing a sub-protocol for websockets between a js client and the server being a little cpp wrapper for libsodium I'm working on. The point at which I started playing with the client-side was just after you updated the docs, and seeing this page, it sounded like crypto_aead_xchacha20poly1305_ietf_xx
was appropriate for my immediate use-case with websockets, but that secretstream
would be needed if order could not be guaranteed by the transport. But the ratcheting scheme sounds really cool so I wanted to try that out in the js client as well.
So my question is- are the noob-wrappers for js on the To-Do list?
@someburner Looks like it would be a perfect fit for your use case.
Emscripten has the equivalent of malloc
, which can be used to reserve enough space to store states, as it was already done for crypto_generichash
for example.
I added the required type and pointer here: 9bfab917928f16f4a1e885ebd151abf1b5f8e2d7
@jedisct1 awesome, much appreciated!
@someburner secretstream
has been added :)
It seems that randombytes_SEEDBYTES
is missing again, it was deleted in 4c89e4fb3198eb51df4d20aed3680918ee3fa445, alongside with:
randombytes_SEEDBYTES
crypto_pwhash_scryptsalsa208sha256_STR_VERIFY
crypto_secretstream_xchacha20poly1305_MESSAGESBYTES_MAX
The README says it supports the
crypto_stream
functions:But in the normal build, it only has the key generation functions, and in the sumo build, it has a weird subset of them.
In particular I'm trying to implement the dat protocol. Digging into the implementation, it appears to use
crypto_stream_xsalsa20_xor_ic
https://github.com/sodium-friends/sodium-native/blob/67be609dd40ea42033747605e3819d913ea290cd/src/crypto_stream_xor_wrap.cc#L36Is there a way I can make a custom build of the library with the exact set of functions I need? Or are there plans to add the missing stream functions?