Skip to content

Instantly share code, notes, and snippets.

@apankrat
Last active October 24, 2022 14:01
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save apankrat/612dde3d7f01c4713c9579b0a94d9547 to your computer and use it in GitHub Desktop.
Save apankrat/612dde3d7f01c4713c9579b0a94d9547 to your computer and use it in GitHub Desktop.
Securing websocket connections on iOS with self-signed certificates
Accessing a website that uses a self-signed certificate using Mobile Safari
will throw a couple of warnings but will ultimately give an option for
temporarily accepting the certificate and then using the site as usual.
The certificate can also be installed as a system-wide "Security Profile"
on an iDevice; that is, manually added to the trusted certificate list.
This will eliminate the warnings and make a self-signed certificate look
and feel as a certificate issued by a trusted CA.
This is done exposing cert's file (.pem or .crt) via the website itself,
then visiting the link, e.g. https://website.ccc/cert.pem, and following
the prompts.
However self-signed certs do NOT work for websocket connections. This is
very poorly documented (if it all), but very easy to check. An attempt
to establish a wss:// connection towards a server that uses a self-signed
certificate will result in an empty error.
Manually installing the certificate doesn't help.
The workaround for this case is to use a certificate signed by a dummy CA.
That is, first make a self-signed CA certificate, install it on a device,
enable the "full trust" for it and then use to issue the actual server
certificate. The whole thing will still be completely homebaked, but now
the websocket connections will work.
To make a self-signed CA cert:
openssl req -new -x509 -days 3650 -config self.ca.conf -keyout ca.key -out ca.crt
whereby self.ca.conf contains:
[ req ]
default_bits = 2048
encrypt_key = no
default_md = sha256
prompt = no
utf8 = yes
distinguished_name = my_dn
x509_extensions = my_ext
[ my_dn ]
C=CH
CN=Honest Ivan & Co.
[ my_ext ]
keyUsage=critical, digitalSignature, keyEncipherment, keyCertSign
basicConstraints=critical,CA:TRUE
extendedKeyUsage=critical,serverAuth
subjectKeyIdentifier = hash
To make a CA-signed certificate:
openssl req -new -key example.key -out example.csr
openssl x509 -req -in example.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out example.crt -days 365 -sha256 -extfile ext.conf
whereby ext.conf contains:
keyUsage=critical, digitalSignature, keyEncipherment
basicConstraints=critical,CA:FALSE
extendedKeyUsage=critical,serverAuth
subjectKeyIdentifier = hash
Next, use example.key and example.crt to secure SSL version of the website.
Next, expose ca.crt on the website, open it from an iDevice, e.g.
https://website.ccc/ca.crt, and follow the prompts.
Finally, go into device Settings > General > About > Certificate Trust
and toggle "full trust" for the "Honest Ivan & Co." entry.
@usmajeed
Copy link

Thanks so much for this!

For any readers: this doesn't work (any more?) on iOS without some changes. You must specify SANs in your ext.conf. Also one of the commands involves an input of "example.key", when you actually named it "ca.key" in the previous step.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment