Adding a self-signed certificate to the «trusted list»
I’ve generated a self-signed certificate for my build server and I’d like to globally trust the certificate on my machine, as I created the key myself and I’m sick of seeing warnings. I’m on Ubuntu 12.04. How can I take the certificate and globally trust it so that browsers (Google Chrome), CLI utilities (wget, curl), and programming languages (Python, Java, etc.) trust the connection to https://example.com without asking questions?
All the TLS should be vectored through OpenSSL, so that’s the place to look for documentation. In this case: gagravarr.org/writing/openssl-certs/… looks useful.
6 Answers 6
The simple answer to this is that pretty much each application will handle it differently.
Also OpenSSL and GNUTLS (the most widely used certificate processing libraries used to handle signed certificates) behave differently in their treatment of certs which also complicates the issue. Also operating systems utilize different mechanisms to utilize «root CA» used by most websites.
That aside, giving Debian as an example. Install the ca-certificates package:
apt-get install ca-certificates
You then copy the public half of your untrusted CA certificate (the one you use to sign your CSR) into the CA certificate directory (as root):
cp cacert.crt /usr/share/ca-certificates
NOTE: Certificate needs to have .crt extension for it to be picked up.
And get it to rebuild the directory with your certificate included, run as root:
dpkg-reconfigure ca-certificates
and select the ask option, scroll to your certificate, mark it for inclusion and select ok.
Most browsers use their own CA database, and so tools like certutil have to be used to modify their contents (on Debian that is provided by the libnss3-tools package). For example, with Chrome you run something along the lines of:
certutil -d sql:$HOME/.pki/nssdb -A -t "C,," -n "My Homemade CA" -i /path/to/CA/cert.file
Firefox will allow you to browse to the certificate on disk, recognize it a certificate file and then allow you to import it to Root CA list.
Most other commands such as curl take command line switches you can use to point at your CA,
curl --cacert /path/to/CA/cert.file https://.
or drop the SSL validation altogether
The rest will need individual investigation if the ca-certificates like trick does not sort it for that particular application.
After copying the certificate to /usr/share/ca-certificates, I can’t see it in the dpkg-reconfigure ca-certificates list. What am I doing wrong?
@GeorgesDupéron That happened to me to. I resolved it by renaming the cert from whatever.pem to whatever.crt .
FYI, I had a cert file named .cer , and that didn’t work. I had to rename it to .crt for it to be recognized.
Non Interactive Approach
For use in a non-interactive context (e.g. a chef recipe) you can use the following sequence.
sudo cp my.crt /usr/local/share/ca-certificates/ sudo update-ca-certificates
- Tested and works on debian 5/6 & Ubuntu 14.04.
- For more information, see man update-ca-certificates
This method is preferred over @Drav’s method, since /usr/share/ is typically reserved for files added by the OS / apt-get .
On Fedora 23, add the .pem or .der file to /etc/pki/ca-trust/source/anchors/ and run sudo update-ca-trust extract .
See man update-ca-trust for details, e.g. whether to use /etc or /usr.
cp *.pem /etc/pki/ca-trust/source/anchors/ update-ca-trust extract
When I do openssl connect should I be specifying this /anchors folder? I’m still getting an error » self signed certs
Non Interactive Approach (Oct’18)
for recent debian based systems
There’s a distinction between adding a cert to the host’s store and activating it so that applications really utilize those. An existing cert in the store isn’t necessarily used (although i have to admit that still a lot of packages are getting it wrong anyway)
This can get confusing when you setup a package which considers /etc/ca-certificate.conf and simply refuses to use your cert although it has been added without error. You need to tell update-ca-certificates explicitly to (not just copy but) activate the cert by adding it to /etc/ca-certificate.conf or /etc/ca-certificate/update.d .
CERT=mycert.crt cp /mypath/to/$CERT /usr/share/ca-certificates/$CERT # notice the + sign which tells to activate the cert. echo "+$CERT" >/etc/ca-certificates/update.d/activate_my_cert dpkg-reconfigure ca-certificates;
Now here it gets confusing as there’s a way to implicitly trust a certificate by using a different path:
CERT=mycert.crt cp /mypath/to/$CERT /usr/local/share/ca-certificates/$CERT update-ca-certificates;
Adding a trusted SSL cert on Nginx
We will use the root certificate authority (CA) to create all the SSL certificates. But first, we need to create a root certificate. Let’s create a private key rootCA.key by running the command in the terminal:
sudo openssl genrsa -out /etc/ssl/private/rootCA.key 2048
sudo openssl genrsa -des3 -out /etc/ssl/private/rootCA.key 2048
Now let’s create the rootCA.pem certificate file using the private key rootCA.key by running the command in the terminal:
sudo openssl req -x509 -new -nodes -key /etc/ssl/private/rootCA.key -sha256 -days 3650 -out /etc/ssl/certs/rootCA.pem
3 Creating SSL certificates
It is already possible to create new certificates using the root certificate rootCA.pem. But first, we need to create a private key and a key (CSR) to request a signature by running the command in the terminal:
sudo openssl req -new -sha256 -nodes -newkey rsa:2048 -keyout /etc/ssl/private/localhost.key -out /etc/ssl/private/localhost.csr -config /tmp/openssl.cnf
Now we will create our certificate file using the root certification authority that we created earlier by running the command in the terminal:
sudo openssl x509 -req -in /etc/ssl/private/localhost.csr -CA /etc/ssl/certs/rootCA.pem -CAkey /etc/ssl/private/rootCA.key -CAcreateserial -out /etc/ssl/certs/localhost.crt -sha256 -days 3650 -extfile /tmp/openssl.cnf -extensions v3_ca
4 Configuring Nginx to use SSL
Let’s enable SSL in the Nginx server configuration. We will specify listening on port 443 (HTTPS) and the path to the certificate and private key files. Edit the server configuration file /etc/nginx/sites-available/default:
sudo nano /etc/nginx/sites-available/default
Save the changes and close the file. Check the configuration for validity by running the command in the terminal:
Now apply the configuration changes by running the command in the terminal:
sudo service nginx reload
5 Adding a certification authority to the browser
- Google Chrome
Settings -> Advanced -> Privacy and security -> Manage certificates -> Authorities -> Import (select rootCA.pem file and set all trust settings) - Mozilla Firefox
Preferences -> Privacy & Security -> Certificates -> View Certificates -> Authorities -> Import (select rootCA.pem file and set all trust settings)
6 Encryption testing
Let’s check that our Nginx server is accessible via the HTTPS protocol by entering the following address in the browser:
If you did everything correctly, you will see that the browser has begun to trust your SSL certificate. Your connection will now be encrypted using the HTTPS protocol without displaying a warning about an insecure connection
- Добавление доверенного SSL-сертификата для локальной среды в Nginx на Debian/Ubuntu (используя корневой ЦС) https://develike.com/ru/stati/dobavlenie-doverennogo-ssl-sertifikata-dlya-lokalnoj-sredy-v-nginx-na-debian-ubuntu
How to run ‘dotnet dev-certs https —trust’?
It seems that the command «dotnet dev-certs https» has no —trust options. How to resolve this problem?
That link you’ve provided to the reading tutorial seems to lead to a page in Japanese. Surely a great read but the language barrier might be an issue.
6 Answers 6
On Ubuntu the standard mechanism would be:
- dotnet dev-certs https -v to generate a self-signed cert
- convert the generated cert in ~/.dotnet/corefx/cryptography/x509stores/my from pfx to pem using openssl pkcs12 -in .pfx -nokeys -out localhost.crt -nodes
- copy localhost.crt to /usr/local/share/ca-certificates
- trust the certificate using sudo update-ca-certificates
- verify if the cert is copied to /etc/ssl/certs/localhost.pem (extension changes)
- verify if it’s trusted using openssl verify localhost.crt
Unfortunately this does not work:
- dotnet dev-certs https generates certificates that are affected by the issue described on https://github.com/openssl/openssl/issues/1418 and https://github.com/dotnet/aspnetcore/issues/7246:
$ openssl verify localhost.crt CN = localhost error 20 at 0 depth lookup: unable to get local issuer certificate error localhost.crt: verification failed
Workaround: (tested on Openssl 1.1.1c)
- manually generate self-signed cert
- trust this cert
- force your application to use this cert
- manually generate self-signed cert:
- create localhost.conf file with the following content:
[req] default_bits = 2048 default_keyfile = localhost.key distinguished_name = req_distinguished_name req_extensions = req_ext x509_extensions = v3_ca [req_distinguished_name] commonName = Common Name (e.g. server FQDN or YOUR name) commonName_default = localhost commonName_max = 64 [req_ext] subjectAltName = @alt_names [v3_ca] subjectAltName = @alt_names basicConstraints = critical, CA:false keyUsage = keyCertSign, cRLSign, digitalSignature,keyEncipherment [alt_names] DNS.1 = localhost DNS.2 = 127.0.0.1
- generate cert using openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout localhost.key -out localhost.crt -config localhost.conf
- convert cert to pfx using openssl pkcs12 -export -out localhost.pfx -inkey localhost.key -in localhost.crt
- (optionally) verify cert using openssl verify -CAfile localhost.crt localhost.crt which should yield localhost.crt: OK
- as it’s not trusted yet using openssl verify localhost.crt should fail with
CN = localhost error 18 at 0 depth lookup: self signed certificate error localhost.crt: verification failed
- trust this cert:
- copy localhost.crt to /usr/local/share/ca-certificates
- trust the certificate using sudo update-ca-certificates
- verify if the cert is copied to /etc/ssl/certs/localhost.pem (extension changes)
- verifying the cert without the CAfile option should work now
$ openssl verify localhost.crt localhost.crt: OK
- force your application to use this cert
- update your appsettings.json with the following settings:
Incredibly helpful, thank you. The only caveat for me was that this does not work with openssl 1.0.1, I had to update to 1.1.1 to succeed. Also worth mentioning this issue: github.com/dotnet/aspnetcore/issues/7246 which talks through this in detail.
Thanks. As I am using Ubuntu on WSL I also installed the .pfx file on Windows Certificate Store: «Trusted Root Certification Authorities».
Following the steps i’m getting: ▶ ls -la /etc/ssl/certs/localhost.pem | grep localhost lrwxrwxrwx 1 root root 46 Oct 18 04:19 /etc/ssl/certs/localhost.pem -> /usr/local/share/ca-certificates/localhost.crt Repositories/dotnet/TodoApi ▶ openssl verify localhost.crt CN = ubuntu-machine error 18 at 0 depth lookup: self signed certificate error localhost.crt:
@Snewedon sorry to hear it didn’t work. I followed exactly the same steps and it did work for me. Hard to debug based on the limited information available. Maybe different openssl version? Needs v1.1.1 or higher.
While the answer provided by @chrsvdb is helpful it does not solve all problems. I still had issue with service-to-service communication (HttpClient — PartialChain error) and also you must reconfigure Kestrel to use your own certificate. It is possible to create a self-signed certificate and import it to the .NET SDK. All you need is to specify the 1.3.6.1.4.1.311.84.1.1 extension in the certificate.
After that the cert can be imported into .NET Core SDK and trusted. Trusting in Linux is a bit hard as each application can have it’s own certificate store. E.g. Chromium and Edge use nssdb which can be configured with certutil as described John Duffy. Unfortunately the location to the nssdb maybe different when you install application as snap. Then each application has its own database. E.g. for Chromium Snap the path will be $HOME/snap/chromium/current/.pki/nssdb , for Postman Snap the will be $HOME/snap/postman/current/.pki/nssdb and so on.