31

As I don't know the openssl command's arguments by heart, I am used to referring to the same SO answer whenever I need to create self-signed certificates (for testing environments). The command looks like:

openssl req -x509 -nodes -newkey rsa:2048 -keyout mysite.key -out mysite.crt -days 365

And it usually works, for instance on my current Ubuntu 15.10. Today I'm on a fresh install of Debian Jessie and it doesn't. Apache warns at startup that:

[ssl:warn] [pid 1040] AH01906: www.mysite.com:443:0 server certificate is a CA certificate (BasicConstraints: CA == TRUE !?)

I looked for a solution to the problem and found an answer in a linux forum stating that the following should be used instead:

openssl genrsa -des3 -passout pass:x -out mysite.pass.key 2048
openssl rsa -passin pass:x -in mysite.pass.key -out mysite.key
openssl req -new -key mysite.key -out mysite.csr
openssl x509 -req -days 365 -in mysite.csr -signkey mysite.key -out mysite.crt

And it's true, this way the Apache warning disappears.

As far as I understand, this creates a passphrase-protected key, then removes the passphrase, then creates a CSR, then generates the certificate with both the CSR and the key.

So the question is: what does this longer version do that the shorter doesn't, and why is it necessary in some cases (like today for me)?

Community
  • 1
  • 1
marcv
  • 1,874
  • 4
  • 24
  • 45

5 Answers5

27

Short way (e.g. with OpenSSL 1.1.0f and Apache 2.4.37):

openssl genrsa -out notEncodedPk.key 3072
openssl req -new -out website.csr -sha256 -key notEncodedPk.key
openssl x509 -req -in website.csr -days 365 -signkey notEncodedPk.key -out website.cert -outform PEM

genrsa generates a 3072 bit RSA-Key. (The system should be online for some time to have good data in /dev/(u)random for seeding.) There is no need to generate an encrypted PK (1) and then use rsa to remove the password afterwards. (Maybe earlier versions of the tools required a password?)
req creates the certificate signing request and uses the PK for the signature. Providing something like -sha256 for the digest is optional. (3) Provide your infos in the interactive questionare. Ensure to put your site domain in "Common name:", otherwise the Apache will throw a warning (AH01909) and browsers will throw an "invalid certificate" message because the URL/domain does not match the certificate data (2). Leave "A challange password:" empty.
Use x509 to create a self-signed certificate with -signkey (the subject is copied to issuer). Normally the command works on certificates but with -req it accepts a CSR as an input. Then use your PK for signing the certificate. (-outform and -days are optional, with 30 days as the default value for the latter.)

Problem source:

As user207421 already stated: req creates a CSR OR it creates a self-signed root-CA-like certificate, therefore the typical tutorial tip

openssl req -x509 -nodes -days 365 -newkey rsa:3072 -sha256 -keyout website.key -out website.cert

is short but normally not what you want. You can also compare created certificates with

openssl x509 -text -noout -in website.cert

In the certificate, created with the single-line command, you see a section "X509v3 extensions:" with "X509v3 Basic Constraints: critical CA:TRUE". This is exactly the Apache warning message.
Instead, if you create the certificate with the three steps, the "X509v3 extensions:" section is not included into the certificate.

Appendix:

(1) Securing the PK with a password is a good idea in most cases. If the PK is stored without encryption, make sure to restrict access to root. If you use a password, you have to use the -passout/-passin options, but be aware that a simple "x" does not work anymore because some OpenSSL tools require at least 4 characters (otherwise: "result too small/bad password read"). Additionally in Apache you have to use something like SSLPassPhraseDialog buildin to manually enter the required password for the PK (or even for all PKs/certs) during Apache startup.

(2) Anyway, browsers will display a warning for self-signed certificates.

(3) Using SHA-1 would be inadequate for such a large RSA-key. In general, it is a good idea to review your openssl.conf, e.g. in Debian 9 in /etc/ssl/openssl.conf, which contains various defaults, for example signer_digest = sha256.
In the Debian 9 file, you also find in the [req] section a line x509_extensions=v3_ca and this is the reason, why the req command in combination with the -x509 option adds the CA-related extension (basicContraints=critical,CA:true), if used in the single-line style to create a self-signed certificate.

Addidionally you might notice a comment-line # req_extensions=v3_req. Because this line is commented out (in Debian 9 default openssl.cnf), the simple usage of the req command does not include any extensions.
Note that you might use this line in a modified file to add Subject Alternative Name's to the certificate, e.g. so it can handle multiple (sub-)domains (normally a much better choice than using e wildcard in CN, e.g. *.example.com).

GerryH
  • 296
  • 3
  • 5
  • I have tried the first 3 lines of code and it worked! – lewis4u Apr 08 '19 at 11:44
  • around 50 tab open in my browers and non of them give me a good solution , but your first 3 lines code did it for me, i just had to change .csr to .crt because im working on a local server on windows 10, amazing explanation as well btw , thank you a lot – The Doctor Feb 07 '23 at 21:57
2

Figure out which openssl.cnf you are using.

Select the correct section name that is doing your request.

Take out the CA:TRUE part (or change it to CA:FALSE) from the basicConstraint in the openssl.cnf that you are using.

Recreate the certificate the exact same way you did.

Your Apache webserver will no longer see a CA, much less a self-signed CA but just an ordinary self-signed certificate.

John Greene
  • 2,239
  • 3
  • 26
  • 37
  • There are a bunch of these already set to FALSE in my config. I did find one where it is 'true: It is under PKIX Recommendations - basicConstraints = critical, CA:true. – TASC Solutions Dec 28 '22 at 17:50
1

complete CA and SSL creation / setup help:

I created my own CA cert and used it to load into browser (as CA authority) and sign my self-created SSL cert for my Apache_on_ubuntu website.

steps:

  1. generate my CA private key:

    # openssl genrsa -des3 -out /etc/ssl/private/myCA.key 2048
    
  2. generate root certificate: *****send myCA.pem to all desktop/client browsers.

    # openssl req -x509 -days 5475 -new -nodes -key /etc/ssl/private/myCA.key -sha256 -out /etc/ssl/certs/myCA.pem
    
  3. Install the root CA in firefox. (cp myCA.pem to windows box) in firefox: options -> privacy_&_security -> view_certificates -> certificate_manager -> Authorities -> import

  4. Creating CA-Signed Certificates for Your Sites

4.1: create website private key:

# openssl genrsa -out /etc/ssl/private/www.mywebsite.com.key 2048

4.2: create website CSR: Note: answers don’t need to match the CA cert ans.

# openssl req -new -key /etc/ssl/private/www.mywebsite.com.key -out /etc/ssl/private/www.mywebsite.com.csr

4.3: Create config file: config file is needed to define the Subject Alternative Name (SAN) extension. "method to match a domain name against a certificate – using the available names within the subjectAlternativeName extension"

# vi /etc/ssl/private/www.mywebsite.com.ext

...............I have not used the ext file option.....(for hosting multiple SSL sites and certs on same host)

4.4: Create the certificate:

# openssl x509 -req -in /etc/ssl/private/www.mywebsite.com.csr -CA /etc/ssl/certs/myCA.pem -CAkey /etc/ssl/private/myCA.key -CAcreateserial -out /etc/ssl/certs/www.mywebsite.com.crt -days 5475 -sha256
  1. create ssl-conf file:

    # cat /etc/apache2/conf-available/ssl-params.conf
    # modern configuration, tweak to your needs
    

    SSLProtocol -all +TLSv1.2 +TLSv1.3 SSLCipherSuite ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256 SSLHonorCipherOrder on SSLCompression off SSLSessionTickets off

  2. restart apache:

    # systemctl restart apache2
    
rajeev
  • 1,275
  • 7
  • 27
  • 45
0

I had the same problem just today on Debian 9 stretch and I tried your solution to generate a new certificate using your method and it did not work. The warning in Apache was exactly the same.

I found out that the problem was that in my browser were stored other 6 certificates with the same FQDN. I erased the certificates and the problem has gone.

EDIT: Well, there's still the warning actually but at least everything is working.

petezurich
  • 9,280
  • 9
  • 43
  • 57
0

openssl req creates a CSR or a CA root certificate. See the man page. It is not what you want. The second set of steps is correct.

user207421
  • 305,947
  • 44
  • 307
  • 483