Self signed SSL certificate on private IP is invalid in Chrome
Asked Answered
A

3

12

I want to create a Self Signed certificate for a nodejs server. I run it from macOS. I want to be able to visit pages rendered by that server over https from another device (Android) on the same wifi network through "https://192.9.200.77:8005" on Chrome. 192.9.200.77 being the IP of the server.

I managed to create a key and a certificate with OpenSSL with SAN. I installed the certificate on the Android device and on macOS.

On MacOS, the certificate is working on Safari, but not in Chrome 71.

On Android the certificate is not working either.

app.js (node server) :

const fs = require('fs');
const https = require('https');

const credentials = {
  key: fs.readFileSync('keys/priv_and_pub.pem'),
  cert: fs.readFileSync('keys/CA.crt')
};
const express = require('express');
const app = express();
const port = 3000;

app.get('/', (req, res) => res.send('Hello World!'));

const httpsServer = https.createServer(credentials, app);

httpsServer.listen(8005, () => console.log(`Example app listening on port 8005 in https!`));

To create the certificate, I use a configuration file :

ssl.conf

[ req ]
x509_extensions     = x509_ext
distinguished_name  = subject


[ subject ]
countryName         = Country Name (2 letter code)
countryName_default     = US

stateOrProvinceName     = State or Province Name (full name)
stateOrProvinceName_default = California

localityName            = Locality Name (eg, city)
localityName_default    = SF

organizationName         = Organization Name (eg, company)
organizationName_default    = my company

commonName          = Common Name (e.g. server FQDN or YOUR name)
commonName_default      = 192.9.200.77

emailAddress            = Email Address
emailAddress_default        = [email protected]

[ x509_ext ]
basicConstraints        = CA:TRUE
subjectAltName          = @alternate_names

[ alternate_names ]

DNS.1       = 192.9.200.77

And Openssl with these commands:

openssl genrsa -out priv_and_pub.key 2048

openssl req -config ssl.conf -new -x509 -sha256 -key priv_and_pub.key -subj "/C=US/ST=California/L=BSF/O=myCompany/OU=Prod/CN=192.9.200.77"  -out CA.crt 

Then I convert the certificate to the DER format for the Android device as recommended here:

openssl x509 -inform PEM -outform DER -in CA.crt -out CA.der.crt

And converted the priv_and_pub.key to a .pem for the node server :

cp priv_and_pub.key priv_and_pub.pem

The app.js is working fine. I installed the .cert in macOS and everything's fine on Safari (green lock and all), but doesn't work on Chrome : (net::ERR_CERT_COMMON_NAME_INVALID). In the browser console, in the Security tab, I get green signs for Connection (Connection - secure (strong TLS 1.2)) and Resources (Resources - all served securely), but red flag for Certificate (Certificate - missing) and this error : 'Can not verify on the server that this is the domain 192.9.200.77, because its security certificate comes from the domain 192.9.200.77. This may be due to a misconfiguration or a connection by your hacker.' (Google Traduction from French)

Any help appreciated, spent the day on the problem ! Thks !

Afford answered 7/1, 2019 at 20:18 Comment(1)
I'm facing exactly the same problem. Only difference is that I specify the SAN as IP.1 = ... instead of DNS.1 = ... because I read that Chrome expects the former for IP addresses. Furthermore, I get a NET:ERR_CERT_AUTHORITY_INVALID. I'm surprised that you get an error concerning the common name as it should not be taken into account in modern browsers (?)Svend
I
8

To clean up and reduce this solution to its core elements, the following is required to create an IP certificate that will be trusted by Chrome.

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.

Thus, the CA:True basic constraint is not required.

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"

Individual answered 2/10, 2019 at 22:27 Comment(1)
2021 here, still getting a ERR_CERT_AUTHORITY_INVALID error after trying this.Kerguelen
A
5

I resolved my problem by changing the subjectAltName in the ssl.conf file, by adding IP: in front of the IP adress :

ssl.conf file :

[ x509_ext ]
basicConstraints        = CA:TRUE
subjectAltName          = IP:192.9.200.77

and I also removed the [ alternate_names ] section.

Afford answered 18/2, 2019 at 12:35 Comment(1)
What is missing from this answer is that the openssl x509 command must include the switches -extensions x509_ext -extfile ssl.confIndividual
C
0

After a lot of non working solutions, this set did the job for me.

I created a config file name: openssl.cnf with this content:

######################################################
# OpenSSL config to generate a self-signed certificate
#
# Create certificate with:
# openssl req -x509 -new -nodes -days 720 -keyout selfsigned.key -out selfsigned.pem -config openssl.cnf
#
# Remove the -nodes option if you want to secure your private key with a passphrase
#
######################################################

################ Req Section ################
# This is used by the `openssl req` command
# to create a certificate request and by the
# `openssl req -x509` command to create a
# self-signed certificate.

[ req ]

# The size of the keys in bits:
default_bits       = 4096

# The message digest for self-signing the certificate
# sha1 or sha256 for best compatability, although most
# OpenSSL digest algorithm can be used.
# md4,md5,mdc2,rmd160,sha1,sha256
default_md = sha256

# Don't prompt for the DN, use configured values instead
# This saves having to type in your DN each time.

prompt             = no
string_mask        = default
distinguished_name = req_distinguished_name
req_extensions     = req_ext

# Extensions added while singing with the `openssl req -x509` command
x509_extensions = x509_ext

[ req_dn ]

countryName            = US
stateOrProvinceName    = NY
organizationName       = Organization
commonName             = Name

[ x509_ext ]

subjectKeyIdentifier    = hash
authorityKeyIdentifier  = keyid:always

# No basicConstraints extension is equal to CA:False
# basicConstraints      = critical, CA:False

keyUsage = critical, digitalSignature, keyEncipherment

extendedKeyUsage = serverAuth

subjectAltName = IP:192.168.1.3

[ req_distinguished_name ]
commonName         = 192.168.1.3

[ req_ext ]
subjectAltName = IP:192.168.1.3

And then I ran this command (each line as a single command) in powershell:

openssl genrsa -out key1.pem
openssl req -new -key key1.pem -out csr1.pem -config openssl.cnf
openssl x509 -req -days 9999 -in csr1.pem -signkey key1.pem -out cert1.pem -extensions req_ext -extfile openssl.cnf
rm csr1.pem

It created these files for me:

  • cert1.pem
  • key1.pem

And I installed the cert1.pem in chrome in 6 steps

enter image description here

In step 5 notice to change file types to All Files (*.*) or your file wont show in the folder

Countryandwestern answered 5/12, 2023 at 19:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.