Skip to content
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

Add preliminary TLS1.3 PSK-mode implementation. #24

Merged
merged 1 commit into from
Feb 14, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,12 @@ jobs:
shell: /bin/bash --login
command: |
sudo npm install -g npm@6
npm install
npm ci
DISPLAY=:99 FIREFOX_BIN=./firefox/firefox-bin npm test

- store_artifacts:
path: ./coverage/

- run: npm run lint
workflows:
version: 2
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# Build with coverage info enabled.
dist/FxAccountsPairingChannel.babel.umd.coverage.js

# Logs
logs
*.log
Expand Down
22 changes: 14 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,15 @@ It will be used by the Firefox Accounts pairing flow, with one side
of the channel being web content from https://accounts.firefox.com and
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's add a doc about running npm ci and npm run build to ensure the build is consistent and no new sub-deps show up. Maybe we can do it as a separate PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this should be a pre-commit hook or something? (TBH it kind of weirds me out checking in the build output on every commit, and I wonder if we can only do it on releases or something; but if we're going to do it we should be able to automate it)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pre-commit hooks are local only, you want something in CI ideally

the other side of the channel being a signed-in Firefox instance.

The connection will *eventually* be secured using a pre-shared key
and TLS1.3, but that code is still in progress. To parallelize
client development we've published an initial version with a
correctly-shapred API but no meaningful security.

API
===

The main abstraction is the `InsecurePairingChannel` class.
The main abstraction is the `PairingChannel` class.
One side of the connection can create a new channel like this:

```
const channel = await InsecurePairingChannel.create(CHANNEL_SERVER_URL);
const channel = await PairingChannel.create(CHANNEL_SERVER_URL);
console.log(channel.channelId, channel.channelKey);
```

Expand All @@ -29,7 +25,7 @@ the intended client, perhaps by scanning a QR code. It can then
connect to the channel like this:

```
const channel = await InsecurePairingChannel.connect(CHANNEL_SERVER_URL, channelId, channelKey);
const channel = await PairingChannel.connect(CHANNEL_SERVER_URL, channelId, channelKey);
```

Both ends of the channel can then send and receive messages using a websocket-like
Expand All @@ -46,4 +42,14 @@ channel.addEventListener("message", event => {

You can try out a more complete demo of this API by loading
`./demo/test_client.html` and `./demo/test_server.html` in
parallel webpages and watching them pass messages back and forth.
parallel webpages and watching them pass messages back and forth.


Crypto
======

Under the hood, the `PairingChannel` implements the "externally-provisioned
pre-shared key" mode of [TLS1.3](https://tools.ietf.org/html/rfc8446).
Each side of the channel can thus be assured that its peer is in posession
of the `channelKey`, and that their traffic is protected from anyone who
does not possess this key.
6 changes: 3 additions & 3 deletions demo/test_client.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,15 @@ <h2>fxa-pairing-tls demo client</h2>
<script src="../dist/FxAccountsPairingChannel.babel.umd.js"></script>
<script>
$(() => {
const {InsecurePairingChannel, hexToBytes} = FxAccountsPairingChannel;
const {PairingChannel, base64urlToBytes} = FxAccountsPairingChannel;
const CHANNEL_SERVER = 'wss://dev.channelserver.nonprod.cloudops.mozgcp.net';
$("#code-value").val("")
$("#chat-history").val("")
$("#code-value").on("keypress", async evt => {
if (evt.keyCode !== 13) { return }
const [channelId, pskHex] = $("#code-value").val().split("#");
const psk = hexToBytes(pskHex);
const channel = await InsecurePairingChannel.connect(CHANNEL_SERVER, channelId, psk);
const psk = base64urlToBytes(pskHex);
const channel = await PairingChannel.connect(CHANNEL_SERVER, channelId, psk);
channel.addEventListener("message", event => {
const {msg} = event.detail.data;
$("#chat-history").val($("#chat-history").val() + "\nthem>> " + msg)
Expand Down
7 changes: 3 additions & 4 deletions demo/test_server.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,11 @@ <h2>fxa-pairing-tls demo server</h2>
<script src="../dist/FxAccountsPairingChannel.babel.umd.js"></script>
<script>
$(async () => {
// TODO: do we want to export InsecurePairingChannel directly?
const {InsecurePairingChannel, bytesToHex} = FxAccountsPairingChannel;
const {PairingChannel, bytesToBase64url} = FxAccountsPairingChannel;
const CHANNEL_SERVER = 'wss://dev.channelserver.nonprod.cloudops.mozgcp.net';
$("#chat-history").val("");
const channel = await InsecurePairingChannel.create(CHANNEL_SERVER);
$("#code-value").text(`${channel.channelId}#${bytesToHex(channel.channelKey)}`);
const channel = await PairingChannel.create(CHANNEL_SERVER);
$("#code-value").text(`${channel.channelId}#${bytesToBase64url(channel.channelKey)}`);
channel.addEventListener("message", event => {
const {msg} = event.detail.data;
$("#chat-history").val($("#chat-history").val() + "\nthem>> " + msg);
Expand Down
Loading