Create end-to-end encrypted WebSocket channels with Extended Triple Diffie-Hellman and Double Ratchet
npm install triple-doubleCreate end-to-end encrypted WebSocket channels!
This package implements secret negotation via Extended Triple Diffie-Hellman (X3DH), allowing two peers to establish a WebSocket channel encrypted end-to-end with the Double Ratchet Algorithm and header encryption.
WARNING: this library has NOT received a formal security audit, use at your own risk.
npm i triple-double
#### Generate TLS certificate
npm run cert
This generates a private key and self-signed certificate and writes them to private/.
Note: the client will need the certificate to connect to the server.
#### Start server
[host=] [port=] npm start
#### Example
The following code snippets assume top-level async/await for readability purposes.
A secure, out-of-band channel is needed to communicate public keys and session IDs between peers.
Find the complete code in ./example.js and run it with npm run example.
##### Alice publishes bundle
Alice only has to perform this step if:
* She hasn't published her bundle yet
* She runs out of one-time prekeys
* She wants to publish a new signed prekey
We'll assume she hasn't published her bundle yet.
See here for more details.
``js
// Alice's code
const fs = require('fs')
const { Client } = require('triple-double')
const ca = fs.readFileSync('/path/to/cert')
const host = '1.2.3.4'
const port = 8888
const alice = new Client({ ca, host, port })
const pubKey = await alice.publishBundle()
// Send public key to Bob out-of-band
`
##### Bob sends initial message
See here for more details.
`js
// Bob's code
const fs = require('fs')
const { Client } = require('triple-double')
const ca = fs.readFileSync('/path/to/cert')
const host = '1.2.3.4'
const port = 8888
const bob = new Client({ ca, host, port })
const peerKey = Buffer.from(/ alice's public key /)
const plaintext = 'intial plaintext'
const sid = await bob.sendInitMessage(peerKey, plaintext)
// Send session ID to alice out-of-band
`
##### Alice receives initial message
See here for more details.
`js`
// Alice's code continued
const plaintext = await alice.recvInitMessage('
##### Connect
At this point, the peers can establish a secure WebSocket channel.
This operation won't complete until both peers are connected.
`js`
// Alice's code continued
await alice.connect('
`js`
// Bob's code continued
await bob.connect('
##### Send/receive messages
After connecting, the peers can send messages to each other!
These messages are encrypted with Double Ratchet (including header encryption).
`js
// Alice's code continued
alice.on('message', ({ sid, plaintext }) => {
if (sid === '
// handle Bob's plaintext
}
})
alice.send('
`
`js
// Bob's code continued
bob.on('message', ({ sid, plaintext }) => {
if (sid === '
// handle Alice's plaintext
}
})
bob.send('
`
Alice and Bob can establish secure channels to other peers, if they so choose.
##### Disconnect
Once a peer calls disconnect() with the session ID, the channel closes and both peers receive "disconnect" events.
`js
// Alice's code continued
alice.on('disconnect', sid => {
if (sid === '
// Disconnected from Bob
}
})
alice.disconnect('
`
`js`
// Bob's code continued
bob.on('disconnect', sid => {
if (sid === '
// Disconnected from Alice
}
})
npm run doc
This generates the documentation and writes it to out/.
Then you can open out/index.html in your browser.
npm test
npm run lint`
Go for it! Whether it's code cleanup, a bugfix, or feature request, your input is seriously appreciated.
Unsure where to start? Take a look at the code or open an issue.