Kandres22
Kandres22

Reputation: 717

OpenSSL Certificate (Version 3) with Subject Alternative Name

I'm using the OpenSSL command line tool to generate a self signed certificate. It seems to be working correctly except for two issues. I can't get it to create a .cer with a Subject Alternative Name (critical) and I haven't been able to figure out how to create a cert that is Version 3 (not sure if this is critical yet but would prefer learning how to set the version).

Has anyone done this successfully? The default config (.cfg) file has seemingly clear documentation (seen below):

This stuff is for subjectAltName and issuerAltname. Import the email address. subjectAltName=email:copy

However this does not work. My hunch is that the subject Alternative Name is not showing up b/c it is not present in the V1 specs, which is why I'm also pursuing setting the version.

Here is the config file I'm using:

[ req ]
default_bits        = 2048 
default_keyfile     = privkey.pem 
distinguished_name  = req_distinguished_name
emailAddress        = [email protected]
req_extensions          = v3_req
x509_extensions         = v3_ca

[req_distinguished_name]
C = [Press Enter to Continue]
C_default = US 
C_min = 2 
C_max = 2 

O = [Press Enter to Continue]
O_default = default 

0.OU=[Press Enter to Continue]
0.OU_default = default 
1.OU=[Press Enter to Continue]
1.OU_default = PKI 
2.OU=[Press Enter to Continue] 
2.OU_default = ABCD
commonName = Public FQDN of server 
commonName_max = 64

[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment

[ v3_ca ]
subjectKeyIdentifier   = hash
authorityKeyIdentifier = keyid:always,issuer:always
subjectAltName         = email:[email protected]
issuerAltName          = issuer:copy

Upvotes: 54

Views: 173925

Answers (12)

Raghu K Nair
Raghu K Nair

Reputation: 3942

Here is the simple steps for you

While generating the CSR you should use -config and -extensions and while generating certificate you should use -extfile and -extensions

Here is the example:

openssl req -new -nodes -keyout test.key  -out test.csr -days 3650 -subj "/C=US/ST=SCA/L=SCA/O=Oracle/OU=Java/CN=test cert" -config /etc/pki/tls/openssl.cnf -extensions v3_req
openssl x509 -req -days 3650 -in test.csr -CA cacert.pem -CAkey rootCA.key -CAcreateserial -out test.pem -extfile /etc/pki/tls/openssl.cnf  -extensions v3_req

Upvotes: 44

Salman Siddiqui
Salman Siddiqui

Reputation: 374

response specific to easyrsa script posted in the interest of providing a working solution for including a SAN in an end-user x509 certificate.

On client computer, create a new cnf file, e.g. client_cert.cnf with following content;

[ req ]
default_md = sha512
prompt = no
req_extensions = req_ext
distinguished_name = req_distinguished_name

[ req_distinguished_name ]
commonName = MyFirstName MyLastName
countryName = CA
stateOrProvinceName = MyProvince
localityName = myCity
organizationName = My Company Ltd.
emailAddress = [email protected]

[ req_ext ]
keyUsage=digitalSignature
extendedKeyUsage=clientAuth
basicConstraints=CA:false
subjectAltName = email:[email protected]

use the following command to generate the csr;

openssl req -new -key client-key.pem -out client-csr.pem -config client_cert.cnf

Transfer the resulting client-csr.pem to your CA if needed. On the CA, in ~/myca/x509-types directory copy the 'client' template;

cp x509-types/client x509-types/client-san
vim x509-types/client-san

Match contents with following;

# X509 extensions for a client with SAN
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer:always
extendedKeyUsage = clientAuth
keyUsage = digitalSignature
subjectAltName = email:$ENV::EASYRSA_REQ_EMAIL

Then import and sign the cert.

./easyrsa import-req ../client-csr.pem [email protected]
./easyrsa sign-req client-san [email protected]

Validate that the signed certificate contains Subject Alternate Name field with your email address in it;

openssl x509 -noout -text -in pki/issued/[email protected]

The purpose of this post is to document a complete procedural answer that is not easily available elsewhere.

Upvotes: 0

mpb
mpb

Reputation: 1482

#! /bin/dash

#  Steps 1-3 show how to use openssl to create a certificate request
#  that includes Subject Alternative Names.

#  In the uncommon case where you are creating your own CA, steps 4-6
#  show how to use openssl to create a CA and then use that CA to
#  create a certificate from the request.

#  Step 1:  Create an OpenSSL configuration file
#    to specify the Subject Alternative Names

echo  ;  echo  'step  1'
cat  >  foo.cnf  <<EOF
[ req ]
distinguished_name      =  arbitrary_name_1
req_extensions          =  arbitrary_name_2
[ arbitrary_name_1 ]
[ arbitrary_name_2 ]
subjectAltName          =  @arbitrary_name_3
[ arbitrary_name_3 ]
DNS.1                   =  foo.com
DNS.2                   =  bar.com
DNS.3                   =  baz.com
EOF

#  Step 2:  Create a certificate request for foo.com.
#
#  openssl
#    req
#      -config      read openssl configuration from this file
#      -subj        set the commonName of the certificate
#      -newkey      generate a new key (and, by implication, a new request!)
#        -nodes       do not encrypt the new private key ("no DES")
#        -keyout      write the new private key to this file
#      -out         write the request to this file

echo  ;  echo  'step  2'
openssl                         \
  req                           \
    -config    foo.cnf          \
    -subj      '/CN=foo.com'    \
    -newkey    rsa:2048         \
      -nodes                    \
      -keyout  foo.key          \
    -out       foo.req

#  Step 3:  Display the requested extensions.

echo  ;  echo  'step  3'
openssl  req  -in foo.req  -noout  -text  |  \
  grep  -A 2  'Requested Extensions:'

#  Step 4:  Create a certificate authority by creating
#    a private key and self-signed certificate.
#
#  openssl
#    req            generate a certificate request, but don't because ...
#      -x509        generate a self-signed certificate instead
#      -subj        set the commonName of the certificate
#      -days        certificate is valid for N days, starting now
#      -newkey      generate a new private key
#        -nodes       do not encrypt the new private key ("no DES")
#        -keyout      write the new private key to this file
#      -out         write the self-signed certificate to this file

echo  ;  echo  'step  4'
openssl                         \
  req                           \
    -x509                       \
    -subj      "/CN=Custom CA"  \
    -days      4000             \
    -newkey    rsa:2048         \
      -nodes                    \
      -keyout  ca.key           \
    -out       ca.cert

#  Step 5:  Use the certificate authority
#    to create a certificate for foo.com.
#
#  openssl
#    x509             operate on an x509 certificate
#      -req           create an x509 certificate from a request
#      -in            read the request from this file
#      -CA            read the CA certificate from this file
#      -CAkey         read the CA key form this file
#      -extfile       read openssl's configuration from this file
#      -extensions    read extensions from this section of the configuration
#      -days          certificate is valid for N days, starting now
#      -set_serial    set the new certificate's serial number
#      -out           write the new certificate to this file

echo  ;  echo  'step  5'
openssl                                 \
  x509                                  \
    -req                                \
    -in          foo.req                \
    -CA          ca.cert                \
    -CAkey       ca.key                 \
    -extfile     foo.cnf                \
    -extensions  arbitrary_name_2       \
    -days        30                     \
    -set_serial  1001                   \
    -out         foo.cert

#  Step 6:  Display the X509v3 extensions:

echo  ;  echo  'step  6'
openssl  x509  -in foo.cert  -noout  -text  |  \
  grep  -A 2  'X509v3 extensions:'

Upvotes: 1

robbie fan
robbie fan

Reputation: 686

I referred to several pages, and the most significant helps are from 1. https://geekflare.com/san-ssl-certificate/, 2. https://certificatetools.com/ (see answer from user40662), and 3. answer from Raghu K Nair about the command usage.

Then my successful try:

san.cnf

[ req ]
default_bits       = 2048
default_md         = sha256
distinguished_name = req_distinguished_name
req_extensions     = v3_req
[ req_distinguished_name ]
countryName            = CN                     # C=
stateOrProvinceName    = Shanghai               # ST=
localityName           = Shanghai               # L=
#postalCode             = 200000                 # L/postalcode=
#streetAddress          = "My Address"           # L/street=
organizationName       = My Corporation         # O=
organizationalUnitName = My Department          # OU=
commonName             = myname.mysoftware.mycorporation.com # CN=
emailAddress           = [email protected]     # CN/emailAddress=
[ v3_req ]
subjectAltName = @alt_names
[ alt_names ]
DNS.1   = myname.mysoftware.mycorporation.com
#DNS.2   = other2.com
#DNS.3   = other3.com

Command:

openssl req -x509 -nodes -days 365 -subj "/C=CN/ST=Shanghai/L=Shanghai/O=My Corporation/OU=My Department/CN=myname.mysoftware.mycorporation.com/[email protected]" -keyout privateKey.pem -out certificate.crt -config san.cnf -extensions v3_req

Upvotes: 5

Lyas Spiehler
Lyas Spiehler

Reputation: 121

I just developed a web based tool that will generate this command automatically based on form input and display the output.


UPDATE: see certificatetools.com

It became so popular that I improved it and published it under its own domain name.

It will not only give you the downloadable .csr, but also provide the openssl commands that were used to generate it, and the needed openssl.cnf configuration options.

Example:

OpenSSL Commands

#generate the RSA private key
openssl genpkey -outform PEM -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out priv.key

#Create the CSR
openssl req -new -nodes -key priv.key -config csrconfig.txt -out cert.csr

OpenSSL CSR Config

[ req ]
default_md = sha256
prompt = no
req_extensions = req_ext
distinguished_name = req_distinguished_name
[ req_distinguished_name ]
commonName = example.com
countryName = US
stateOrProvinceName = Louisiana
localityName = Slidell
organizationName = Acme Inc.
[ req_ext ]
keyUsage=critical,digitalSignature,keyEncipherment
extendedKeyUsage=critical,serverAuth,clientAuth
subjectAltName = @alt_names
[ alt_names ]
IP.0 = 1.1.1.1
IP.1 = 2.2.2.2
DNS.0 = server1.example.com
DNS.1 = server2.example.com
email.0 = [email protected]
email.1 = [email protected]

Upvotes: 12

Mathias Brossard
Mathias Brossard

Reputation: 3786

I got it to work with the following version (emailAddress was incorrectly placed):

[ req ]
default_bits        = 2048 
default_keyfile     = privkey.pem 
distinguished_name  = req_distinguished_name
req_extensions          = v3_req
x509_extensions         = v3_ca
  
[req_distinguished_name]
C = [Press Enter to Continue]
C_default = US 
C_min = 2 
C_max = 2 

O = [Press Enter to Continue]
O_default = default 

0.OU=[Press Enter to Continue]
0.OU_default = default 
1.OU=[Press Enter to Continue]
1.OU_default = PKI 
2.OU=[Press Enter to Continue] 
2.OU_default = ABCD
commonName = Public FQDN of server 
commonName_max = 64
emailAddress = [Press Enter to Continue] 
emailAddress_default = [email protected]

[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment

[ v3_ca ]
subjectKeyIdentifier   = hash
authorityKeyIdentifier = keyid:always,issuer:always
subjectAltName         = email:[email protected]
issuerAltName          = issuer:copy

Notes:

  • To generate the certificate I used:

     openssl req -config req.cnf -new -nodes -out req.pem -x509
    
  • I haven't seen much use for issuerAltname (if you have I'd be interested to know where).

  • Using issuer:always isn't recommended for authorityKeyIdentifier.

  • Using email:copy now works with subjectAltName.

  • v3_req section is superfluous (as well as req_extensions line.

Upvotes: 9

Jack Davidson
Jack Davidson

Reputation: 4943

Alright, none of the other answers on this page worked for me, and I tried every last one of them. What worked for me was a little trick:

when requesting the cert:

-config <(cat /etc/ssl/openssl.cnf <(printf "[SAN]\nsubjectAltName=DNS:$SERVER")) \
-reqexts SAN

and when signing the cert:

-extfile <(cat /etc/ssl/openssl.cnf <(printf "[SAN]\nsubjectAltName=DNS:$SERVER")) \
-extensions SAN

Notice that this is a bash trick, <(some commands) makes the stdout output of some commands show as a temp file to the outer commands in bash.

So there is no confusion, here is a working script that covers everything from the start, including creating a certificate authority:

# if the server name is undefined, lets default to 'Some-Server'
SERVER="${SERVER:-Some-Server}"

CORPORATION=My-Corp
GROUP=My-Corporate-Group
CITY=City
STATE=State
COUNTRY=US

CERT_AUTH_PASS=`openssl rand -base64 32`
echo $CERT_AUTH_PASS > cert_auth_password
CERT_AUTH_PASS=`cat cert_auth_password`

# create the certificate authority
openssl \
  req \
  -subj "/CN=$SERVER.ca/OU=$GROUP/O=$CORPORATION/L=$CITY/ST=$STATE/C=$COUNTRY" \
  -new \
  -x509 \
  -passout pass:$CERT_AUTH_PASS \
  -keyout ca-cert.key \
  -out ca-cert.crt \
  -days 36500

# create client private key (used to decrypt the cert we get from the CA)
openssl genrsa -out $SERVER.key

# create the CSR(Certitificate Signing Request)
openssl \
  req \
  -new \
  -nodes \
  -subj "/CN=$SERVER/OU=$GROUP/O=$CORPORATION/L=$CITY/ST=$STATE/C=$COUNTRY" \
  -sha256 \
  -extensions v3_req \
  -reqexts SAN \
  -key $SERVER.key \
  -out $SERVER.csr \
  -config <(cat /etc/ssl/openssl.cnf <(printf "[SAN]\nsubjectAltName=DNS:$SERVER")) \
  -days 36500

# sign the certificate with the certificate authority
openssl \
  x509 \
  -req \
  -days 36500 \
  -in $SERVER.csr \
  -CA ca-cert.crt \
  -CAkey ca-cert.key \
  -CAcreateserial \
  -out $SERVER.crt \
  -extfile <(cat /etc/ssl/openssl.cnf <(printf "[SAN]\nsubjectAltName=DNS:$SERVER")) \
  -extensions SAN \
  -passin pass:$CERT_AUTH_PASS

We can then verify that the Subject Alternative name is in the final cert:

openssl x509 -in Some-Server.crt -text -noout

The pertinent section is:

    X509v3 extensions:
        X509v3 Subject Alternative Name: 
            DNS:Some-Server

So it worked! This is a cert that will be accepted by every major browser (including chrome), so long as you install the certificate authority in the browser. Thats ca-cert.crt that you will need to install.

Here is a sample configuration for nginx that would allow you to use the cert:

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name  localhost:443;

    ssl_certificate /etc/ssl/certs/Some-Server.crt;
    ssl_certificate_key /etc/ssl/private/Some-Server.key;
    ssl_dhparam /etc/ssl/certs/https-dhparam.pem;

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }
}

Upvotes: 29

gratinierer
gratinierer

Reputation: 2518

Basing on that answer this slightly different approach worked for me:

  1. create a server.cnf-file with:
nsCertType = server
nsComment = "OpenSSL Generated Server Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer:always
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[alt_names]
IP.1 = 127.0.0.1
DNS.1 = localhost
  1. generate your CSR
openssl genrsa -out yourServer_private.key 4096
openssl req -new -key yourServer_private.key -out yourServer.csr
  1. create your certificate and add SAN-information
openssl x509 -req -days 3650 -in yourServer.csr -CA ../Root/Ca.pem -CAkey ../Root/Ca.key -set_serial 01 -out yourServer.pem -extfile server.cnf
  1. check your result
openssl x509 -in yourServer.pem -text

=>

(...)
           X509v3 Extended Key Usage:
                TLS Web Server Authentication
            X509v3 Subject Alternative Name:
                IP Address:127.0.0.1, DNS:localhost
    Signature Algorithm: sha256WithRSAEncryption

(...)

Upvotes: 1

Kostyantyn
Kostyantyn

Reputation: 5191

Though after following the steps described here I started .csr files with: X509v3 Subject Alternative Name However, my .crt (.pem) files generated with:

openssl x509 -req -in domain.csr -extensions SAN -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out domain.crt -days 100

still were with:

Version: 1 (0x0)

and without:

X509v3 Subject Alternative Name

Solution

Issue was resolved after I switched to this one:

openssl ca -in domain.csr -cert rootCA.pem -keyfile rootCA.key -out domain.crt

I started to get domain.crt files with:

Version: 3 (0x2)

and

X509v3 Subject Alternative Name

If openssl ca complains, you might need to adjust openssl.cnf (or /etc/ssl/openssl.cnf for ubuntu, NOTE: if you used brew install openssl - it will be in a different location) file. Just make sure you properly set these:

[ CA_default ]
dir= /path/to/rootCA/folder  # Where everything is kept
certificate= $dir/rootCA.pem  # The CA certificate
serial= $dir/rootCA.srl  # The current serial number
private_key= $dir/rootCA.key  # The private key

And run: touch /path/to/index.txt

To generate rootCA.srl you can still use the old command:

openssl x509 -req -in domain.csr -extensions SAN -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out domain.crt -days 100

More details on openssl ca can be found here: https://www.openssl.org/docs/man1.0.2/man1/ca.html

Upvotes: 1

OscarG
OscarG

Reputation: 395

I know this thread is a little old but just in case it works for anyone on windows, check that the file is UTF-8 encoded, in my case I was getting an error indicating there was an error with the .cnf file, so I opened it on Notepad++ set the file encoding to UTF-8, saved, and ran the openssl command again and it made the trick.

Upvotes: 1

Dominic
Dominic

Reputation: 11

The v3_req is required with the entry subjectAltName in the config file. The command

openssl x509 ... -extfile openssl.cnf -extensions v3_req

will insert the SAN into the certificate.

Upvotes: 1

user1844882
user1844882

Reputation: 51

What command did you use to make the CSR certificate request? What command did you use to make the certificate file? Different answers for different circumstances you know.

Maybe you are not putting

subjectAltName=email:copy

in the section

[v3_req]

Maybe you are using openssl x509 to generate the certificate, if so you must use

-extfile /etc/pki/tls/openssl.cnf

because without that it doesnt use your config file

You also might need

-extensions v3_req

command line switch

Upvotes: 4

Related Questions