Allow WebCrypto on HTTP

2,823 views
Skip to first unread message

h...@andrew.im

unread,
Jan 23, 2017, 9:57:10 AM1/23/17
to Security-dev
Reposting from my open issue (https://bugs.chromium.org/p/chromium/issues/detail?id=683864#c4)

I run a project that allows people to remotely manage their machines in any web browser.

As you may know, browsers usually refuse to load non-secure content from secure pages. We aren't able to generate an SSL certificate for each user, so our publicly hosted client is not https. But we still need to protect user data.

Whenever a connection is made to a self-hosted server (over websocket), a unique RSA key pair is generated on the server for that connection. The client then generate AES credentials, encrypts them using the server generated public key and sends them to the server. After that all traffic to and from the client is encrypted using AES.

So in our attempts to speed up our decryption, we implemented WebCrypto, only to find out its being restricted to secured pages (at least in chrome). This defeats the purpose of what we're attempting to do.

This is a very valid use case, as web technology continues to grow and more software is created using it, we should be able to protect our users information and take advantage of native cryptography outside of a https environment.

As suggest on the issue, there are a couple of challenges with mapping a users IP to sub-domains.

Our websocket server that we ship doesn't support SSL, so we'd end up routing the traffic through our server and terminating SSL at the proxy. This will cause a lot of latency and removes the need for us to have Web Crypto. If it did support SSL, I could be wrong, but wouldn't we have to ship the certificate/key with the users server? Basically the goal here is to establish a direct websocket connection between a user and their own self-hosted server. The page the static HTML is hosted on could indeed be HTTPS, but insecure websockets are not allowed on secured pages.

I would hope this is a decision that could be reviewed again, since Chrome is the only browser enforcing this rule. All it does is make development a headache and force myself and others to use Javascript based methods like asmCrypto, which is even more insecure.


Ryan Sleevi

unread,
Jan 23, 2017, 12:41:19 PM1/23/17
to h...@andrew.im, Security-dev
I closed the issue as WontFix, as the W3C Web Crypto working group extensively debated this for a number of years, with the resolution in https://github.com/w3c/webcrypto/issues/28 of requiring [SecureContext] in the spec, which is what the W3C advanced to CR and (modulo a special corner case) what Chrome implemented.

Ryan Sleevi

unread,
Jan 23, 2017, 12:41:40 PM1/23/17
to Ryan Sleevi, h...@andrew.im, Security-dev
And to clarify, that corner case is a bug that we're attempting to fix :)
Message has been deleted
Message has been deleted

h...@andrew.im

unread,
Jan 23, 2017, 1:29:30 PM1/23/17
to Security-dev, rsl...@chromium.org, h...@andrew.im
While it was heavily debated for a number of years, as I mentioned Chrome is the only browser enforcing it.

By locking people out from an API that is meant to protect information, you're forcing people to use insecure methods to achieve their goals.

As my colleague put it, you're not preventing people from using crypto in the web, you're just preventing them from using the fastest method for it. It seems a bit silly to take an "all or nothing" stance.

Anyway, thanks for the time. The simplest solution here is to inconvenience our users by making them install an extension for Chrome and just falling back to asmcrypto for those who won't.

Andrew Sampson

unread,
Jan 23, 2017, 9:42:14 PM1/23/17
to Eric Mill, Chris Palmer, Security-dev, Ryan Sleevi
You can already do that, but this isn't a one size fits all world. Not every user is going to be technical savant and going to understand the process of certificate setup. We shouldn't just forgo trying to protect less technical users information in transit. If we're going to do an all-or-nothing enforcement of HTTPS, I feel as if we should improve how we handle encryption on the web. 

Insecure websockets on HTTPS pages are disallowed, if this wasn't the case I'd be doing just that. Certificates are bound to host names so people without host cannot be protected.

So unless we suddenly come up with infrastructure and money to route every users call through ourselves, we don't really have any better options but to try and encrypt their traffic. 

Also all the client assets are delivered over HTTPS.

Ryan Sleevi

unread,
Jan 24, 2017, 11:03:29 AM1/24/17
to PhistucK, Andrew Sampson, Eric Mill, Chris Palmer, Security-dev, Ryan Sleevi
That's not spec compliant, and that's the bug we'll be closing soon.

On Mon, Jan 23, 2017 at 9:30 PM, PhistucK <phis...@gmail.com> wrote:
As a workaround, you could create a secure iFrame which does the encrypting and decrypting and pass messages from it to the rest of the system and to it from the rest of the system (since HTTP can load HTTPS and not vice versa).

(I am not advocating that, but it could be a solution. It is not really secure, just like the rest of your HTTP solution)


PhistucK

--
You received this message because you are subscribed to the Google Groups "Security-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to security-dev+unsubscribe@chromium.org.


Ryan Sleevi

unread,
Jan 24, 2017, 12:17:35 PM1/24/17
to PhistucK, Ryan Sleevi, Andrew Sampson, Eric Mill, Chris Palmer, Security-dev
Not according to https://w3c.github.io/webappsec-secure-contexts/#settings-object (meaning that in aligning our implementation to the spec, this case will thankfully break)

On Tue, Jan 24, 2017 at 8:18 AM, PhistucK <phis...@gmail.com> wrote:
What about an HTTP page that window.open an HTTPS page and passes message to it? Would that still work (I do not know if it does currently)?


PhistucK

Ryan Sleevi

unread,
Jan 25, 2017, 12:53:49 PM1/25/17
to Andrew Sampson, Ryan Sleevi, PhistucK, Eric Mill, Chris Palmer, Security-dev
Because localhost (when it resolves to the loopback IP) does not go over a network. Reserved IPs do, and are thus clearly not secure.

On Wed, Jan 25, 2017 at 9:50 AM, Andrew Sampson <h...@andrew.im> wrote:
Out of curiosity, localhost is considered a secured context, so why are other internal ip's such as 192.168.1.1 not?

For instance if I serve my client over HTTPS to a user and they attempt to connect a local instance on their network, it will fail, which leads them to using an insecure page to accomplish their goal.

kane...@gmail.com

unread,
Jan 26, 2017, 11:49:10 PM1/26/17
to Security-dev, er...@konklone.com, pal...@google.com, rsl...@chromium.org, h...@andrew.im
On Monday, January 23, 2017 at 6:42:14 PM UTC-8, Andrew Sampson wrote:
> I run a project that allows people to remotely manage their machines in any web browser.
> Whenever a connection is made to a self-hosted server (over websocket), a unique RSA key pair is generated on the server for that connection. The client then generate AES credentials, encrypts them using the server generated public key and sends them to the server. After that all traffic to and from the client is encrypted using AES.
> So unless we suddenly come up with infrastructure and money to route every users call through ourselves, we don't really have any better options but to try and encrypt their traffic. 

> The simplest solution here is to inconvenience our users by making them install an extension for Chrome and just falling back to asmcrypto for those who won't.

I believe the best solution for you is to have a HTTPS jsapp page that performs the calculations and communicates with the device using CORS.

That is, OPTIONS http://192.168.1.24/keypair_communicate replies with:

Access-Control-Allow-Origin: https://app.example.com
Access-Control-Allow-Methods: POST
#(cookies probably not needed) Access-Control-Allow-Credentials: true
#(if headers needed) Access-Control-Allow-Headers: x-keypairID
Access-Control-Max-Age: ${DEVICE_AUTO_UPDATE_INTERVAL}

Then, on the device webserver check that the Origin: is https://app.example.com or example-app-dev.localdomain ; if it's not, give a 403 and don't process the request.

The UI problem of registering and switching between devices is left as an exercise for the reader...

Ryan Sleevi

unread,
Jan 27, 2017, 12:35:34 AM1/27/17
to Kane York, Security-dev, Eric Mill, Chris Palmer, Ryan Sleevi, Andrew Sampson
On Thu, Jan 26, 2017 at 8:49 PM, <kane...@gmail.com> wrote:
I believe the best solution for you is to have a HTTPS jsapp page that performs the calculations and communicates with the device using CORS.

That is, OPTIONS http://192.168.1.24/keypair_communicate replies with:

HTTPS is blocked from communicating with HTTP like that - it's mixed content. 
Reply all
Reply to author
Forward
0 new messages