2

Can a client script provide to the browser a certificate to accept in a wss:// connection? The WebSocket constructor does not seem to have many options.

(I am designing an IoT server that lets the owner share access with other users by emailing them an html file that includes a connection script and credentials. To secure communications I could of course use crypto.subtle, but SSL would be more easily accepted if it can work. The users definitely do not want to do any kind of browser configuration, and operation cannot be dependent on Internet access).

personal_cloud
  • 389
  • 1
  • 8
  • OP, following the conversation between you and @mentalung below, it’s not clear to me - would the certificate provided to the browser be used to authenticate the server certificate (like certificate pinning)? Or would the certificate be used to authenticate the client (like client certificates used in TLS)? – mti2935 Dec 25 '22 at 22:57
  • 1
    usually a certificate is presented during the mechanism of authentication of a connection so I would say "no", unless you want to provide a certificate via a custom protocol (or reimplement SSL in javascript). – gipi Dec 28 '22 at 11:31

2 Answers2

1

Modern browsers support Web Crypto API. But this API does not provide the possibility to add a certificate to the trust store.

One alternative is to add certificates to the trust store manually. This requires users to have some technical background.

Another alternative would be asking users to make an exception for particular certificate in GUI. But you don't like this approach.

One more approach: You can provide a single server with a valid TLS certificate. All WSS connections to your server will be secure and users will not need to do anything about certificates. You can configure your server to use reverse proxy and forward requests to particular providers (IoT servers). Connection to every IoT server can be secured with their certificates. You would just add the certificates of IoT server to the trust store of your application. Thus connection between users and your server and connections between your server and IoT servers will be secure. Effectively you will be a man in the middle and you can read and modify the traffic. But if all participants of such system trust you (the IoT server providers and the users), this can be much easier to implement.

mentallurg
  • 10,256
  • 5
  • 28
  • 44
  • "Execution of scripts from unknown people is a huge risk." (1) the scripts aren't from unknown people, and (2) Apart from sandboxing issues in [some browsers](https://security.stackexchange.com/questions/177478/), how is running a script in an email more risk than accessing pretty much any webpage which is loaded with 3rd party scripts, or even StackOverflow snippets? And you always have the option to host the file on localhost yourself, if running it as `file://` bothers you. – personal_cloud Dec 25 '22 at 20:14
  • "That's asking users to make an exception for particular certificate in GUI can be much easier and much safer." That is the opposite of my experience. Sorry, I am done explaining `subjectAltName` and the multitude of browser certificate menus to people. And 90% of the time [name constraints](https://www.rfc-editor.org/rfc/rfc5280#section-4.2.1.10) don't get applied, and the browser ends up much *less* secure. – personal_cloud Dec 25 '22 at 20:17
  • I am trying to be a proponent of SSL here. I'm willing to create a certificate and hand it to the browser on a silver platter. The user doesn't need to be involved because it's specific to the connection (and anyway a client script can use its own crypto as an alternative in such situations... so SSL seems to be discouraging its own use here). – personal_cloud Dec 25 '22 at 20:27
  • Having said all that, upvote for explaining the process for adding certificates, which seems to confirm that a script can't do this itself... (We just disagree on what users are more comfortable with.) – personal_cloud Dec 25 '22 at 20:32
  • May be there is a typo in the title and in the question? *"Can a client script provide to the browser"* - I interpret it, that you want to create a script that needs to be executed on the client side to provide needed certificate to the browser. If you mean a script *executable by the browser*, then the answer is NO. Modern browsers support [Web Crypto API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API). But this API does not provide the possibility to add a certificate to the trust store. – mentallurg Dec 25 '22 at 22:20
  • "If you mean a script executable by the browser". Good point, I've updated the title. I also agree with "this API does not provide the possibility to add a certificate to the trust store." But I'm not trying to modify the trust store really. Just trying to tell the browser how to verify the security of a specific resource (the websocket). Basically I just need something like Subresource Integrity that also has encryption and can apply to a websocket. – personal_cloud Dec 25 '22 at 22:28
  • This changes the answer essentially. – mentallurg Dec 25 '22 at 22:53
0

You could set up an infrastructure that issues "real" certificates that are trusted by browsers, e.g. from LetsEncrypt. During setup, your IoT devices create a key pair and a certificate signing request (CSR). The user uploads this CSR to your service and specifies its (probably local) IP address. You create a DNS entry for your user's device and request a certificate using the CSR. Then you can send the certificate to the user, who sends it to the device.

As the IP address for the IoT device is likely only locally accessible, you can't use most common HTTP challenge. However, if you are in control of the DNS server, you can use special DNS entries as proof. LetsEncrypt calls this DNS-01 challenge. You would not need to host the DNS server yourself; you could use a DNS provider with an API like Cloudflare or Amazon.

However, I'm not sure if there are legal or other implications when requesting LetsEncrypt certificates on behalf of other people.

Yogu
  • 248
  • 1
  • 8