Recently, Chrome has stopped working with my self signed SSL certs, and thinks they're insecure. When I look at the cert in the DevTools | Security tab, I can see that it says
Subject Alternative Name Missing The certificate for this site does
not contain a Subject Alternative Name extension containing a domain
name or IP address.
Certificate Error There are issues with the site's certificate chain
(net::ERR_CERT_COMMON_NAME_INVALID).
How can I fix this?
To fix this, you need to supply an extra parameter to openssl when you're creating the cert, basically
-sha256 -extfile v3.ext
where v3.ext is a file like so, with %%DOMAIN%% replaced with the same name you use as your Common Name. More info here and over here. Note that typically you'd set the Common Name and %%DOMAIN%% to the domain you're trying to generate a cert for. So if it was www.mysupersite.com, then you'd use that for both.
v3.ext
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = #alt_names
[alt_names]
DNS.1 = %%DOMAIN%%
Note: Scripts that address this issue, and create fully trusted ssl certs for use in Chrome, Safari and from Java clients can be found here
Another note: If all you're trying to do is stop chrome from throwing errors when viewing a self signed certificate, you can can tell Chrome to ignore all SSL errors for ALL sites by starting it with a special command line option, as detailed here on SuperUser
Following solution worked for me on chrome 65 (ref) -
Create an OpenSSL config file (example: req.cnf)
[req]
distinguished_name = req_distinguished_name
x509_extensions = v3_req
prompt = no
[req_distinguished_name]
C = US
ST = VA
L = SomeCity
O = MyCompany
OU = MyDivision
CN = www.company.com
[v3_req]
keyUsage = critical, digitalSignature, keyAgreement
extendedKeyUsage = serverAuth
subjectAltName = #alt_names
[alt_names]
DNS.1 = www.company.com
DNS.2 = company.com
DNS.3 = company.net
Create the certificate referencing this config file
openssl req -x509 -nodes -days 730 -newkey rsa:2048 \
-keyout cert.key -out cert.pem -config req.cnf -sha256
The Issue
As others have mentioned, the NET::ERR_CERT_COMMON_NAME_INVALID error is occurring because the generated certificate does not include the SAN (subjectAltName) field.
RFC2818 has deprecated falling back to the commonName field since May of 2000. The use of the subjectAltName field has been enforced in Chrome since version 58 (see Chrome 58 deprecations).
OpenSSL accepts x509v3 configuration files to add extended configurations to certificates (see the subjectAltName field for configuration options).
Bash Script
I created a self-signed-tls bash script with straightforward options to make it easy to generate certificate authorities and sign x509 certificates with OpenSSL (valid in Chrome using the subjectAltName field).
The script will guide you through a series of questions to include the necessary information (including the subjectAltName field). You can reference the README.md for more details and options for automation.
Be sure to restart chrome after installing new certificates.
chrome://restart
Other Resources
The Docker documentation has a great straightforward example for creating a self-signed certificate authority and signing certificates with OpenSSL.
cfssl is also a very robust tool that is widely used and worth checking out.
mkcert is a tool written in GoLang. It seems simple to use and great for local development.
Here is a very simple way to create an IP certificate that Chrome will trust.
The ssl.conf file...
[ req ]
default_bits = 4096
distinguished_name = req_distinguished_name
req_extensions = req_ext
prompt = no
[ req_distinguished_name ]
commonName = 192.168.1.10
[ req_ext ]
subjectAltName = IP:192.168.1.10
Where, of course 192.168.1.10 is the local network IP we want Chrome to trust.
Create the certificate:
openssl genrsa -out key1.pem
openssl req -new -key key1.pem -out csr1.pem -config ssl.conf
openssl x509 -req -days 9999 -in csr1.pem -signkey key1.pem -out cert1.pem -extensions req_ext -extfile ssl.conf
rm csr1.pem
On Windows import the certificate into the Trusted Root Certificate Store on all client machines. On Android Phone or Tablet download the certificate to install it. Now Chrome will trust the certificate on windows and Android.
On windows dev box the best place to get openssl.exe is from "c:\Program Files\Git\usr\bin\openssl.exe"
I simply use the -subj parameter adding the machines ip address. So solved with one command only.
sudo openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -sha256 -subj '/CN=my-domain.com/subjectAltName=DNS.1=192.168.0.222/' -keyout my-domain.key -out my-domain.crt
You can add others attributes like C, ST, L, O, OU, emailAddress to generate certs without being prompted.
I had so many issues getting self-signed certificates working on macos/Chrome. Finally I found Mkcert, "A simple zero-config tool to make locally trusted development certificates with any names you'd like." https://github.com/FiloSottile/mkcert
Make a copy of your OpenSSL config in your home directory:
cp /System/Library/OpenSSL/openssl.cnf ~/openssl-temp.cnf
or on Linux:
cp /etc/ssl/openssl.cnf ~/openssl-temp.cnf
Add Subject Alternative Name to openssl-temp.cnf, under [v3_ca]:
[ v3_ca ]
subjectAltName = DNS:localhost
Replace localhost by the domain for which you want to generate that certificate.
Generate certificate:
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-config ~/openssl-temp.cnf
-keyout /path/to/your.key -out /path/to/your.crt
You can then delete openssl-temp.cnf
I was able to get rid of (net::ERR_CERT_AUTHORITY_INVALID) by changing the DNS.1 value of v3.ext file
[alt_names]
DNS.1 = domainname.com
Change domainname.com with your own domain.
on MAC
starting from chrome Version 67.0.3396.99 my self-signed certificate stopped to work.
regeneration with all what written here didn't work.
UPDATE
had a chance to confirm that my approach works today :). If it doesn't work for you make sure your are using this approach
v3.ext
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = #alt_names
[alt_names]
DNS.1 = <specify-the-same-common-name-that-you-used-while-generating-csr-in-the-last-step>
$
copied from here
https://ksearch.wordpress.com/2017/08/22/generate-and-import-a-self-signed-ssl-certificate-on-mac-osx-sierra/
END UPDATE
finally was able to see green Secure only when removed my cert from system, and added it to local keychain. (if there is one - drop it first). Not sure if it maters but in my case I downloaded certificate via chrome, and verified that create date is today - so it is the one I've just created.
hope it will be helpful for someone spend like a day on it.
never update chrome!
Updated June 2021 - Windows 10 - Chrome v91 answer is here
If you want to run your server localhost, you need to setup CN = localhost and DNS.1 = localhost.
[req]
default_bits = 2048
default_md = sha256
distinguished_name = req_distinguished_name
prompt = no
prompt = no
x509_extensions = v3_req
[req_distinguished_name]
C = BR
CN = localhost
emailAddress=contact#example.com
L = Sao Paulo
O = example.com
OU = example.com
ST = Sao Paulo
[v3_req]
authorityKeyIdentifier = keyid, issuer
basicConstraints = CA:FALSE
extendedKeyUsage = serverAuth
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = #alt_names
[alt_names]
DNS.1 = localhost
Related
I've been trying to get InfluxDB to accept a self-signed certificate, but so for, no luck. I've been following instructions from here:
https://docs.influxdata.com/influxdb/v2.3/security/enable-tls/#configure-influxdb-to-use-tls
I created the cert and key with this command:
openssl req -x509 -nodes -newkey rsa:2048 -keyout influxdb-selfsigned.key -out influxdb-selfsigned.crt -days 9999 -config "C:\OpenSSL\openssl.cnf"
The config.yml file is as follows:
http-bind-address: ":8087"
tls-cert: influxdb-selfsigned.crt
tls-key: influxdb-selfsigned.key
Note, I made the bind port 8087 to ensure it was reading the configuration.
When I start influx from the command line, there are no error messages. Initially there were some TLS handshake errors, but those disappeared, I think when I added the crt and key to the configuration.
However, when I access the URL https://localhost:8087, chrome shows a "not secure" message and I have to click through warnings to get to the site.
To try to get Chrome to trust the certificate, - I followed the instructions from this site:
https://www.pico.net/kb/how-do-you-get-chrome-to-accept-a-self-signed-certificate
I exported the cert, then re-imported it as trusted.
However, I still get the "not secure" message in Chrome.
Also, the InfluxDB console shows this message:
info http: TLS handshake error from [::1]:63065: remote error: tls: unknown certificate {"log_id": "0cKnmWB0000", "service": "http"}
Any ideas how to get the cert working?
Currently it seems this is no easy way or workaround in open source version. The community has been asking for this feature but no progress yet. See more details here.
However, in Enterprise version, you could configure the server to know you are using self-signed certificates by setting this configuration in influxdb-meta.conf file:
# If using a self-signed certificate:
https-insecure-tls = true
Since Chrome 68 certificate transparency is enforced. That's a big problem with the SSL-decryption of our corporate proxy.
The proxy's certificate is added to the system's certificate store, this worked like a charm until Chrome 68.
There's a policy called CertificateTransparencyEnforcementDisabledForLegacyCas that gives one the possibility to add such a certificate and disable the enforcement for it. Unfortunately I have no clue how to generate the mentioned hash:
A subjectPublicKeyInfo hash is specified by concatenating the hash algorithm name, the "/" character, and the Base64 encoding of that hash algorithm applied to the DER-encoded subjectPublicKeyInfo of the specified certificate. This Base64 encoding is the same format as an SPKI Fingerprint, as defined in RFC 7469, Section 2.4. Unrecognized hash algorithms are ignored. The only supported hash algorithm at this time is "sha256".
Googling didn't help and I would be glad if anyone that had the same problem could help me out.
Thank you very much!
Sven
To get the base64 hash of the subjectPublicKeyInfo (SPKI), you can use openssl with the following command line incantation:
openssl x509 -pubkey -noout -in <path to PEM cert> | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64
and to create the string you need for the policy:
printf 'sha256/%s\n' `openssl x509 -pubkey -noout -in <path to PEM cert> | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64`
However, if the certificate isn't publicly trusted but instead has been manually trusted, it shouldn't have the CT policy enforced. If you think you're getting an error when you shouldn't please file a bug at http://crbug.com/new
I have been running lighty on my development machine for some years now, have set up some vhosts, one of them is phpmyadmin and one of the others uses SSL with a self-signed certificate on certain pages; and it has been working fine for years.
But now, every time I try to access either of my vhosts, the browsers just show me an error message claiming that the server is not correctly configured and uses hsts (NET::ERR_CERT_AUTHORITY_INVALID) - but I never set that up!
http://(ip-address)/ works fine; as does http://(ip-address)/vhost-path/, and I would work with that until I throw lighty in the bin and install nginx; but the redirects render that unusable at some point in the testing.
I had the idea that the AV software on my Windows client might cause the problem; but it also shows on the Debian development machine itself.
Any ideas on how this comes and how to fix the issue?
Details:
Ubuntu 16.04.4 LTS \n \l
lighttpd/1.4.35 (ssl)
OpenSSL 1.0.2j
contents of /etc/conf/lighttpd/conf-enabled:
05-auth.conf
10-fastcgi.conf
10-ssl.conf
50-phpmyadmin.conf
10-cgi.conf
10-simple-vhost.conf
15-fastcgi-php.conf
90-javascript-alias.conf
As far as I remember, only 10-ssl.conf contains more than the default content; and they all havenĀ“t been modified in years.
lighttpd.conf (mtime two years ago) contains:
server.modules = (
"mod_access",
"mod_accesslog",
"mod_alias",
"mod_compress",
"mod_redirect",
)
... (general server setup) ...
include_shell "/usr/share/lighttpd/create-mime.assign.pl"
include_shell "/usr/share/lighttpd/include-conf-enabled.pl"
... (vhost configuration) ...
/etc/conf/lighttpd/ssl/ contains the SSL certificate for the one vhost I use https on (valid until somewhere in 2023).
Chrome own the .dev TLD and decided to preload this into the static HSTS list baked into the browser. Firefox followed suite recently. See this link for more info: https://ma.ttias.be/chrome-force-dev-domains-https-via-preloaded-hsts/
This means you cannot turn of HSTS.
Your options are:
Use a different domain (e.g. .test)
Create a self signed certificate and switch your test site to HTTPS.
Note that since HSTS will not allow you to click through certificate errors you also need to add the certificate (or the issues) to the trust store.
It's my strong opinion that development should be done on HTTPS sites. This matches production, so avoids problems with mixed content when you go live, certain powerful features will not work on HTTP-only sites, and similarly with certain new features (HTTP/2, Brotli compression, Service Workers).
Do yourself a favour and just create a self-signed cert, add it to your trust store, and move to HTTPS for development. Note also that Chrome requires certificates to have the SAN field which takes a bit more effort but can be completed with this on linux (replace the two instances of server.domain.tld):
openssl req \
-newkey rsa:2048 \
-x509 \
-nodes \
-keyout server.key \
-new \
-out server.crt \
-subj /CN=server.domain.tld\
-reqexts SAN \
-extensions SAN \
-config <(cat /etc/pki/tls/openssl.cnf\<(printf '[SAN]\nsubjectAltName=DNS:server.domain.tld')) \
-sha256 \
-days 3650
Or alternatively on MacOS where you can't use the onliner:
cat /System/Library/OpenSSL/openssl.cnf > /tmp/openssl.cnf
echo '[SAN]\nsubjectAltName=DNS:server.domain.tl'>> /tmp/openssl.cnf
openssl req \
-newkey rsa:2048 \
-x509 \
-nodes \
-keyout server.key \
-new \-out server.crt \
-subj /CN=server.domain.tl\
-reqexts SAN \
-extensions SAN \
-config /tmp/openssl.cnf\
-sha256 \
-days 3650
I've deployed Keycloak on WildFly 10 via Docker. SSL support was enabled via cli. Final standalone.xml has:
<security-realm name="UndertowRealm">
<server-identities>
<ssl>
<keystore path="keycloak.jks" relative-to="jboss.server.config.dir" keystore-password="changeit"
alias="mydomain" key-password="changeit"/>
</ssl>
</server-identities>
</security-realm>
Undertow subsystem:
<https-listener name="default-https" security-realm="UndertowRealm"
socket-binding="https"/>
Key was generated and placed in $JBOSS_HOME/standalone/configuration
keytool -genkey -noprompt -alias mydomain -dname "CN=mydomain,
OU=mydomain, O=mydomain, L=none, S=none, C=SI" -keystore
keycloak.jks -storepass changeit -keypass changeit
Port 8443 is exposed via Docker.
Accessing https://mydomain:8443/ in chrome results in ERR_CONNECTION_CLOSED. Firefox returns "Secure Connection Failed, the connection was interrupted..."
However, OpenSSL client works nicely:
openssl s_client -connect mydomain:8443
Input:
GET / HTTP/1.1
Host: https://mydomain:8443
This returns the Keycloak welcome page.
So clearly WildFly is working but I am being blocked by the browsers for whatever reason. What could this reason be? I was under the impression that I should be able to add an exception for self signed certificate in either browser. Maybe the generated key length is too short or maybe I am hitting some other security constraint imposed by Firefox/Chrome?
Using these parameters in keytool solved the problem: -keyalg RSA -keysize 2048
... -dname "CN=mydomain
The certificate is probably malformed. The Browsers and other user agents, like cURL and OpenSSL, use different policies to validate a end-entity certificate. The browser will reject a certificate if the hostname is in the Common Name (CN), while other user agents will accept it.
The short answer to this problem is, place DNS names in the Subject Alternate Name (SAN), and not the Common Name (CN).
You may still encounter other problems, but getting the names right will help immensely with browsers.
However, OpenSSL client works nicely:
openssl s_client -connect mydomain:8443
OpenSSL prior to 1.1.0 did not perform hostname validation. Prior version will accept any name.
cURL or Wget would be a better tool to test with in this case.
For reading on the verification you should perform when using OpenSSL, see:
SSL/TLS Client
For reading on the rules for hostnames and where they should appear in a X509 certificate, see:
How do you sign Certificate Signing Request with your Certification Authority?
How to create a self-signed certificate with openssl?
I need postman to connect to my server which requires client certificate. After some research, it seems that postman does not handle certificates itself but relies on Chrome certificates instead. My next step was to try to install the certificates in Chrome, my cert structure is like this:
Self-signed root CA => intermediate CA 1 => intermediate CA 2 => client cert
I have a file certchain.pem that contains client cert followed by intermediate CA 2 cert then intermediate CA 1 cert, I also have client.key file. I tried to install the chain in Chrome but it seems that Chrome requires pkcs12 so I split off certchain.pem into client.crt and middle.pem, then I convert everything to pkcs12 by:
openssl pkcs12 -in client.crt -inkey client.key -certfile middle.pem -export -out client.p12
I could install client.p12 into Chrome but it doesn't seem to retain the intermediate certs, when I choose View, it only shows info about client cert.
I've tested that client.p12 works by installing it into Firefox, there I can see info about the intermediate certs. I've tested that my certs work by doing a curl with them. Any other idea?