
The Signal protocol for Node and browsers - ifelsehow
http://people.ischool.berkeley.edu/~nick/signal-protocol-js/
======
AgentME
> At the end of the day, window.crypto can be absolutely anything. ... If you
> must run the signal protocol in-browser, run it in Electron, or as a Chrome
> app ... At the end of the day, window.crypto can be absolutely anything. If
> we can bundle all primitives with the rest of the application code, we can
> verify the integrity of that one JS bundle

If the attacker is running code within the same javascript context, within the
browser's process, or within the user's operating system kernel... then you're
hosed. Anything can be anything. Other javascript within the same context
could redefine global functions, intercept objects passed through them, and
mutate function references in your JS bundle. Or it could just log the DOM! A
browser plugin or a kernel rootkit can keylog the user. The only defense an
application has against the user's own machine being compromised is
obfuscation, and that's a losing battle.

There are real issues with doing cryptography with users' keys in web pages,
but it's not "their machine might be compromised" (and Electron doesn't solve
that anyway). Even if the page javascript correctly stores user keys in
localStorage where the server can't see them, nothing stops the server from
serving you some backdoored javascript tomorrow which silently uploads your
localStorage to the server. This might be correctly solvable with
ServiceWorkers, though you'd want users to have some way to verify that they
have the correct and peer-reviewed ServiceWorker source running. The easiest
way to do that would be some kind of local application or browser plugin, but
then at that point that you've involved a local application you've missed some
of the original goal at keeping it all in a browser, and it would probably be
easier for everyone involved if the crypto just happened in the local
application to begin with.

Interestingly, some `window.crypto` functions actually solve some of the
problems with running cryptography in web pages. You can create and use a
crypto key that is handled by the browser and never has its key material
exposed to javascript. Even if an attacker injects javascript into the page or
the server serves malicious javascript the next day, there's no way to steal
the key material. `window.crypto` can effectively provide a virtual HSM from
the web page's perspective.

~~~
EGreg
HSM? What do you mean? What does it stand for? Heisenberg state machine?

How can the window.crypto API create and use a crypto key that's handled by
the browser?

~~~
AgentME
>HSM

Hardware Security Module. It's a piece of hardware that goes in a server and
manages encryption keys for the server without ever exposing the keys to the
server. Usually they're made so that it's infeasible to extract the keys even
with access to the hardware: they're made hard to open, covered in epoxy, they
erase their keys if the case is breached, etc.

>How can the window.crypto API create and use a crypto key that's handled by
the browser?

There's a function for creating a key and you get an opaque object back out.
You can pass the key to encrypt and decrypt functions. You can save the key
object into IndexedDb, but you're still just dealing with an opaque object
reference. There is an export key function, but it only works if the key was
created with the "extractable" flag turned on.

~~~
Raed667
The function is `window.crypto.subtle.generateKey`JavaScript can't access the
generated key unless you export it using `window.crypto.subtle.exportKey`.

If anyone is interested in the WebCrypto API I recommend this talk by Charles
Engelke:
[https://www.youtube.com/watch?v=D2kEViWKUh0](https://www.youtube.com/watch?v=D2kEViWKUh0)

------
johnhenry
Olm, the ratcheting algorithm used by matrix.org
[https://matrix.org/git/olm/about/](https://matrix.org/git/olm/about/) is also
worth mentioning.

------
bryanrasmussen
I love that hack:

module.exports = Module;

// Do not recurse into module and waste all day Module.inspect = function() {
return '[Module]' }

from [https://github.com/fabiosantoscode/require-
emscripten/blob/m...](https://github.com/fabiosantoscode/require-
emscripten/blob/master/post-js.postjs)

------
baby
> Where TLS can provide an encrypted channel for convincing the user they are
> talking to the right server, Signal can convince the server it is talking to
> the right user - and that it is the same user that we spoke to last time.

Same thing can be done with TLS. It's called session resumption.

~~~
jeremyw
In a weak sense. In Signal, every single volley (in the Diffie-Hellman
ratchet, at least) is testing the validity of the parties and cycling the
ephemerality. Thus the newer notion of "key continuity", that is anchored all
the way back to the initial, authenticating handshake. TLS has only the lesser
resumptive property that the server got back what it sent some time ago, so
this is probably the same thing -- but one can imagine lots of opportunity to
monkey.

~~~
baby
The ratchet is just refreshing the ephemerality. But do we need to refresh the
keys for every messages? Personally I don't think so.

~~~
jeremyw
One necessarily implies the other.

------
davej
> At the end of the day, window.crypto can be absolutely anything.

Would it be possible to toString() the function and check if it is a native
function before execution? Seems like a simple solution but perhaps I'm
missing something? I guess in theory the toString() method could also be
hijacked. :-/

~~~
tixzdk
I think the article gets this wrong. `window.crypto` should be read-only

~~~
ifelsehow
I find the following in Chrome:

> window.crypto.getRandomValues

// getRandomValues() { [native code] }

> window.crypto.getRandomValues = function () { return "aloha" }

> window.crypto.getRandomValues()

// "aloha"

Not sure if this is the case in all browsers. `window.crypto` certainly
_should_ be read-only.

~~~
niftich
In Chrome, window.crypto is read-only:

> window.crypto

< Crypto {subtle: SubtleCrypto}

> window.crypto = "hi!"

< "hi!"

> window.crypto

< Crypto {subtle: SubtleCrypto}

But not anything underneath, including getRandomValues(), as you write. A
recent issue about this [1] on the WebCrypto spec itself was closed with
'wontfix' because in their view, polyfilling web APIs is a common and accepted
practice.

[1]
[https://github.com/w3c/webcrypto/issues/107](https://github.com/w3c/webcrypto/issues/107)

~~~
flukus
Shouldn't all pollyfills check only override the functions if they're missing?

~~~
jsjohnst
What if it's present but the implementation is incomplete?

~~~
paulddraper
E.g. an extra optional parameter.

