How to make self-signed certificate for localhost

certificatesopenssl

I did with a password and with the following fields
as root

openssl req -x509 -days 365 -newkey rsa:2048 -keyout /etc/ssl/apache.key \
    -out /etc/ssl/apache.crt

Fields

Country: FI
State: Pirkanmaa
Locality: Tampere
Organization: masi
Organizational Unit Name: SSL Certificate Test
CommonName: 192.168.1.107/owncloud
EmailAddress: masi@gmail.com

Output: SSL handshake error in HTTPS. Expected output: HTTPS connection.
HTTP works.

The CommonName should include the URL where you want to go, owncloud's thread here.
I have tried unsuccessfully in commonname

  • 192.168.1.107/owncloud
  • 192.168.1.107/

Test OS for server: Debian 8.5.
Server: Raspberry Pi 3b.
Owncloud-server: 8.2.5.
Owncloud-client: 2.1.1.
Systems-client: Debian 8.5.

Best Answer

openssl req -x509 -days 365 -newkey rsa:2048 -keyout /etc/ssl/apache.key -out /etc/ssl/apache.crt

You can't use this command to generate a well formed X.509 certificate. It will be malformed because the hostname is placed in the Common Name (CN). Placing a hostname or IP Address in the CN is deprecated by both the IETF (most tools, like wget and curl) and CA/B Forums (CA's and Browsers).

According to both the IETF and CA/B Forums, Server names and IP Addresses always go in the Subject Alternate Name (SAN). For the rules, see RFC 5280, Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile and CA/Browser Forum Baseline Requirements.

You mostly need to use an OpenSSL configuration file and tailor it to suit your needs. Below is an example of one I use. It's called example-com.conf, and it's passed to the OpenSSL command via -config example-com.conf.


Also note well: all machines claim to be localhost, localhost.localdomain, etc. Be careful about issuing certificates for localhost. I'm not saying don't do it; just understand there are some risks involved.

Alternatives to localhost are: (1) run DNS and issue certificates to the machine's DNS name. Or, (2) use static IP and include the static IP address.


The Browsers will still give you warnings about a self signed certificate that does not chain back to a trusted root. Tools like curl and wget will not complain, but you still need to trust you self signed with an option like cURL's --cafile. To overcome the Browser trust issue, you have to become your own CA.

"Becoming your own CA" is known as running a Private PKI. There's not much to it. You can do everything a Public CA can do. The only thing different is you will need to install your Root CA Certificate in the various stores. It's no different than, say, using cURL's cacerts.pm. cacerts.pm is just a collection of Root CA's, and now you have joined the club.

If you become your own CA, then be sure to burn your Root CA private key to disc and keep it offline. Then pop it in your CD/DVD drive when you need to sign a signing request. Now you are issuing certificates just like a Public CA.

None of this is terribly difficult once you sign one or two signing requests. I've been running a Private PKI for years at the house. All my devices and gadgets trust my CA.

For more information on becoming your own CA, see How do you sign Certificate Signing Request with your Certification Authority and How to create a self-signed certificate with openssl?.


From the comments in the configuration file below...

Self Signed (note the addition of -x509)

openssl req -config example-com.conf -new -x509 -sha256 -newkey rsa:2048 -nodes -keyout example-com.key.pem -days 365 -out example-com.cert.pem

Signing Request (note the lack of -x509)

openssl req -config example-com.conf -new -newkey rsa:2048 -nodes -keyout example-com.key.pem -days 365 -out example-com.req.pem

Print a Self Signed

openssl x509 -in example-com.cert.pem -text -noout

Print a Signing Request

openssl req -in example-com.req.pem -text -noout

Configuration File

# Self Signed (note the addition of -x509):
#     openssl req -config example-com.conf -new -x509 -sha256 -newkey rsa:2048 -nodes -keyout example-com.key.pem -days 365 -out example-com.cert.pem
# Signing Request (note the lack of -x509):
#     openssl req -config example-com.conf -new -newkey rsa:2048 -nodes -keyout example-com.key.pem -days 365 -out example-com.req.pem
# Print it:
#     openssl x509 -in example-com.cert.pem -text -noout
#     openssl req -in example-com.req.pem -text -noout

[ req ]
default_bits        = 2048
default_keyfile     = server-key.pem
distinguished_name  = subject
req_extensions      = req_ext
x509_extensions     = x509_ext
string_mask         = utf8only

# The Subject DN can be formed using X501 or RFC 4514 (see RFC 4519 for a description).
#   It's sort of a mashup. For example, RFC 4514 does not provide emailAddress.
[ subject ]
countryName         = Country Name (2 letter code)
countryName_default     = US

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

localityName            = Locality Name (eg, city)
localityName_default        = New York

organizationName         = Organization Name (eg, company)
organizationName_default    = Example, LLC

# Use a friendly name here because it's presented to the user. The server's DNS
#   names are placed in Subject Alternate Names. Plus, DNS names here is deprecated
#   by both IETF and CA/Browser Forums. If you place a DNS name here, then you 
#   must include the DNS name in the SAN too (otherwise, Chrome and others that
#   strictly follow the CA/Browser Baseline Requirements will fail).
commonName          = Common Name (e.g. server FQDN or YOUR name)
commonName_default      = Example Company

emailAddress            = Email Address
emailAddress_default        = test@example.com

# Section x509_ext is used when generating a self-signed certificate. I.e., openssl req -x509 ...
[ x509_ext ]

subjectKeyIdentifier        = hash
authorityKeyIdentifier  = keyid,issuer

#  If RSA Key Transport bothers you, then remove keyEncipherment. TLS 1.3 is removing RSA
#  Key Transport in favor of exchanges with Forward Secrecy, like DHE and ECDHE.
basicConstraints        = CA:FALSE
keyUsage            = digitalSignature, keyEncipherment
subjectAltName          = @alternate_names
nsComment           = "OpenSSL Generated Certificate"

# RFC 5280, Section 4.2.1.12 makes EKU optional
# CA/Browser Baseline Requirements, Appendix (B)(3)(G) makes me confused
# extendedKeyUsage  = serverAuth, clientAuth

# Section req_ext is used when generating a certificate signing request. I.e., openssl req ...
[ req_ext ]

subjectKeyIdentifier        = hash

basicConstraints        = CA:FALSE
keyUsage            = digitalSignature, keyEncipherment
subjectAltName          = @alternate_names
nsComment           = "OpenSSL Generated Certificate"

# RFC 5280, Section 4.2.1.12 makes EKU optional
# CA/Browser Baseline Requirements, Appendix (B)(3)(G) makes me confused
# extendedKeyUsage  = serverAuth, clientAuth

[ alternate_names ]

DNS.1       = example.com
DNS.2       = www.example.com
DNS.3       = mail.example.com
DNS.4       = ftp.example.com

# Add these if you need them. But usually you don't want them or
#   need them in production. You may need them for development.
# DNS.5       = localhost
# DNS.6       = localhost.localdomain
# DNS.7       = 127.0.0.1

# IPv6 localhost
# DNS.8     = ::1
# DNS.9     = fe80::1

You may need to do the following for Chrome. Otherwise Chrome may complain a Common Name is invalid (ERR_CERT_COMMON_NAME_INVALID). I'm not sure what the relationship is between an IP address in the SAN and a CN in this instance.

# IPv4 localhost
# IP.1       = 127.0.0.1

# IPv6 localhost
# IP.2     = ::1
Related Question