14

Could anyone suggest a modern way of generating self-signed certificates to be implemented on localhost, which would be accepted by Chrome and Mozilla?

I tried the openssl generation, however Mozilla complains that the issuer is untrusted.

Centos 7, nginx

Jeff Schaller
  • 66,199
  • 35
  • 114
  • 250
Tarlan Mammadzada
  • 245
  • 1
  • 2
  • 8

1 Answers1

11

Warning: Before you dive into the minefield of running your own Certification Authority, you may need to study the security implications!

But if you must, read on for a quick and dirty CA that will give you https://localhost/ without a warning message...

Create the following text file:

# OpenSSL configuration for Root CA

[ req ]

prompt             = no
string_mask        = default

# The size of the keys in bits:
default_bits       = 2048
distinguished_name = req_distinguished_name
x509_extensions    = x509_ext

[ req_distinguished_name ]

# Note that the following are in 'reverse order' to what you'd expect to see.

countryName = gb
organizationName = Test
commonName = Test Root CA

[ x509_ext ]

basicConstraints=critical,CA:true,pathlen:0
keyUsage=critical,keyCertSign,cRLSign

Save as root.cnf then generate the request with:

$ openssl req -x509 -new -keyout root.key -out root.cer -config root.cnf

This will create your Root CA certificate (root.cer) and your Root CA private key (root.key) which you must keep private. It will prompt for a password for the private key - ensure you choose a strong one.

Now create a config file for the server certificate:

# OpenSSL configuration for end-entity cert

[ req ]

prompt             = no
string_mask        = default

# The size of the keys in bits:
default_bits       = 2048
distinguished_name = req_distinguished_name

x509_extensions    = x509_ext

[ req_distinguished_name ]

# Note that the following are in 'reverse order' to what you'd expect to see.

countryName = gb
organizationName = Test
commonName = localhost

[ x509_ext ]

keyUsage=critical,digitalSignature,keyAgreement

subjectAltName = @alt_names

# Multiple Alternate Names are possible
[alt_names]
DNS.1 = localhost
# DNS.2 = altName.example.com

Save it as server.cnf and generate the request with:

openssl req -nodes -new -keyout server.key -out server.csr -config server.cnf

The above will generate another private key (server.key) which you must protect. In this case, the key is not password protected, but you may add a password by removing the -nodes option.

Finally, sign the request with your new Root CA and extensions from the server.cnf file (for convenience):

$ openssl x509 -req -in server.csr -CA root.cer -CAkey root.key -set_serial 123 -out server.cer -extfile server.cnf -extensions x509_ext

Note: pick any random number for the -set_serial option.

It will ask for the password you entered when you generated the Root CA.

A server certificate (server.cer) will be generated.

Now, add the Root CA certificate (root.cer) to Firefox's trust-anchor store so that the browser trusts your new CA.

Run a test by using OpenSSL as a temporary web-server with:

$ sudo openssl s_server -key server.key -cert server.cer -accept 443 -www

Note: You may get errors if you already have a sever running on port 443. In which case, either stop the running server or change the port number above to another unused port by changing the ending to (for example) -accept 8443 -www

When you naviate to https://localhost (or https://localhost:8443 if you changed the port number above) with Firefox, you should now see no warning and be presented with a list of ciphers your installation of OpenSSL can offer.

Once you're happy with the results, add the server.key and server.cer to your original webserver and configure accordingly.

garethTheRed
  • 33,289
  • 4
  • 92
  • 101
  • 1
    There's a typo; `stinguished_name` should be `distinguished_name` – user281357 Mar 18 '18 at 16:33
  • you say: (or https://localhost: if you changed the port number above)... where can i set the port number? – a.l.e May 26 '20 at 15:25
  • ok, sorry, then i did not correctly understand the final part of your explanations. anyway, i could add the root certificate through the firefox preferences and now it works correctly. – a.l.e May 26 '20 at 16:59
  • my issue is: what does "sudo openssl ... -accept 443 -www"? does it open a browser? just check if it can correctly access localhost on port 443? it's close to "add root CA to firefox" so it was not clear to me if it would add the certificate or just test it. (i did took notes on my process, but i don't know how to share them... 80% of it is your reply, so i won't post it as an answer in here : - ) – a.l.e May 26 '20 at 18:09
  • i wonder why you're testing it with openssl and not with firefox directly... but, yes, if that is your goal, than it's better. – a.l.e May 27 '20 at 17:58
  • @a.l.e - Because `opnessl` provides the a quick server for testing the certificates, while Firefox provides the client. You can skip running `openssl` as a server if you wish and add the new certs/key to your main server; but if it doesn't work you won't know if the issue is this configuration of the main server, or the generation of the certificates, or the configuration of Firefox's trust-anchor store! – garethTheRed May 27 '20 at 18:06
  • ok, i think i got it now. what about first getting the reader to test with openssl and then add the certificate to firefox? (the next step being to test the https localhost.) – a.l.e May 27 '20 at 19:00
  • @a.l.e - because the reader can't test with Firefox until the certificate is added to Firefox :-) – garethTheRed May 27 '20 at 19:05