Skip to main content
added 7674 characters in body
Source Link
garethTheRed
  • 4.2k
  • 1
  • 20
  • 20

Your approach is somewhat disjointed. Try the following:

Create an OpenSSL config file for the CA (./openssl.cnf)

################ Req Section ################
# This is used by the `openssl req` command
# to create a certificate request

[ req ]

# 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_dn

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

# The extensions added when generating a CSR
req_extensions     = req_ext

[ req_dn ]

countryName            = GB
stateOrProvinceName    = Somewhere
organizationName       = Example
organizationalUnitName = PKI
commonName             = Example Test Root CA

[ req_ext ]

# Extensions added to the request

################ CA Section ################
# This is used with the 'openssl ca' command
# to sign a request
 
[ ca ]

default_ca = CA

[ CA ]

# Where OpenSSL stores information

dir             = .                             # Where everything is kept
certs           = $dir                          # Where the issued certs are kept
crldir          = $dir                          # Where the issued crl are kept

new_certs_dir   = $certs
database        = $dir/index
certificate     = $certs/rootcrt.pem
private_key     = $dir/rootprivkey.pem
crl             = $crldir/crl.pem   
serial          = $dir/serial.txt
RANDFILE        = $dir/.rand

# How OpenSSL will display certificate after signing
name_opt    = ca_default
cert_opt    = ca_default

# How long the CA certificate is valid for
default_days = 3650
# default_startdate  = 180517000000Z
# default_enddate    = 181231235959Z

# 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

# Subjects don't have to be unique in this CA's database
unique_subject    = no
# What to do with CSR extensions
copy_extensions    = copy

# Rules on mandatory or optional DN components
policy      = simple_policy

# Extensions added while singing with the `openssl ca` command
x509_extensions = x509_ext

[ simple_policy ]
countryName             = optional
stateOrProvinceName     = optional
localityName            = optional
organizationName        = optional
organizationalUnitName  = optional
commonName              = optional
domainComponent         = optional
emailAddress            = optional
name                    = optional
surname                 = optional
givenName               = optional
dnQualifier             = optional

[ ca_ext ]
# Optional extensions. Use `-extensions ca_ext`
# These extensions are for a CA certificate

subjectKeyIdentifier    = hash
authorityKeyIdentifier  = keyid:always

basicConstraints            = critical, CA:TRUE
# basicConstraints          = critical, CA:TRUE, pathlen:1

keyUsage = critical, keyCertSign, cRLSign

# Policies and constraints are not recommended for Root CAs
# But could be enforced on subordinate CAs

#nameConstraints        = permitted;DNS:example.org

#policyConstraints = requireExplicitPolicy:1

#inhibitAnyPolicy = 1

#certificatePolicies = @CertPol

[ x509_ext ]
#Default extensions
# These extensions are for an end-entity certificate

# Extensions added when using the `openssl ca` command.
# This section is pointed to by `x509_extensions` above.

subjectKeyIdentifier    = hash
authorityKeyIdentifier  = keyid:always

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

keyUsage = critical, digitalSignature

# Policies and constraints are not recommended for Root CAs
# But could be enforced on subordinate CAs

#nameConstraints        = permitted;DNS:example.org

#policyConstraints = requireExplicitPolicy:1

#inhibitAnyPolicy = 1

#certificatePolicies = @CertPol

[ CertPol ]
policyIdentifier = 1.3.6.1.4.132473
CPS = http://pki.example.org/cps.html

Next, create your request using a similar command to the one you used:

$ openssl req -new -newkey rsa:4096 -keyout rootprivkey.pem -out rootreq.pem -config openssl.cnf

Note that the -sigopt options have been removed as the signature at this point is the request signature used for proof of possession of private key and not the signature of the certificate itself - that's later.

Next, sign it to create the self-signed CA certificate:

$ openssl ca -out rootcrt.pem -days 2652 -keyfile rootprivkey.pem -selfsign -config openssl.cnf -extensions ca_ext -in rootreq.pem -sigopt rsa_padding_mode:pss -sigopt rsa_pss_saltlen:-1

Note that this uses openssl ca instead of openssl x509 which means you can refer to a custom openssl.cnf file. Also note the use of the -extensions option to point the command to a specific section of the config file. Finally, note that the -sigopt options have been moved here as this is the command that signs your CA certificate and therefore should have your PSS scheme.

Next, create a separate OpenSSL config file for your server/end-entity certificate (./server.cnf).

# OpenSSL server/end-entity configuration

[ req ]

string_mask        = default

# The size of the keys in bits:
default_bits       = 2048
distinguished_name = req_dn
req_extensions     = req_ext

[ req_dn ]
 
countryName                     = Country Name (2 letter code)
countryName_default             = 
countryName_min                 = 2
countryName_max                 = 2

stateOrProvinceName             = State or Province Name (full name)
stateOrProvinceName_default     = 
localityName                    = Locality Name (eg, city)
localityName_default            = 

0.organizationName              = Organization Name (eg, company)
0.organizationName_default      = 

commonName                      = Common Name

[ req_ext ]

# Careful...
#basicConstraints=critical,CA:TRUE

# subjectAltName = @alt_names

[alt_names]
# To copy the CN (in the case of a DNS name in the CN) use:
# DNS = ${req_dn::commonName}

Run a similar command to the one you used, but with the config file changed.

$ openssl req -new -newkey rsa:4096 -keyout serverprivkey.pem -out serverreq.pem -config server.cnf

Finally, sign it with the CA:

$ openssl ca -in serverreq.pem -days 1200 -cert rootcrt.pem -keyfile rootprivkey.pem -sigopt rsa_padding_mode:pss -sigopt rsa_pss_saltlen:-1 -out servercrt.pem -config openssl.cnf

Note that there is no -extensions option on this one, so OpenSSL defaults to the section pointed to by the x509_extensions = option in openssl.cnf.

You can now verify the certificates:

$ openssl verify -CAfile rootcrt.pem servercrt.pem
servercrt.pem: OK

Your approach is somewhat disjointed. Try the following:

Create an OpenSSL config file for the CA (./openssl.cnf)

################ Req Section ################
# This is used by the `openssl req` command
# to create a certificate request

[ req ]

# 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_dn

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

# The extensions added when generating a CSR
req_extensions     = req_ext

[ req_dn ]

countryName            = GB
stateOrProvinceName    = Somewhere
organizationName       = Example
organizationalUnitName = PKI
commonName             = Example Test Root CA

[ req_ext ]

# Extensions added to the request

################ CA Section ################
# This is used with the 'openssl ca' command
# to sign a request
 
[ ca ]

default_ca = CA

[ CA ]

# Where OpenSSL stores information

dir             = .                             # Where everything is kept
certs           = $dir                          # Where the issued certs are kept
crldir          = $dir                          # Where the issued crl are kept

new_certs_dir   = $certs
database        = $dir/index
certificate     = $certs/rootcrt.pem
private_key     = $dir/rootprivkey.pem
crl             = $crldir/crl.pem   
serial          = $dir/serial.txt
RANDFILE        = $dir/.rand

# How OpenSSL will display certificate after signing
name_opt    = ca_default
cert_opt    = ca_default

# How long the CA certificate is valid for
default_days = 3650
# default_startdate  = 180517000000Z
# default_enddate    = 181231235959Z

# 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

# Subjects don't have to be unique in this CA's database
unique_subject    = no
# What to do with CSR extensions
copy_extensions    = copy

# Rules on mandatory or optional DN components
policy      = simple_policy

# Extensions added while singing with the `openssl ca` command
x509_extensions = x509_ext

[ simple_policy ]
countryName             = optional
stateOrProvinceName     = optional
localityName            = optional
organizationName        = optional
organizationalUnitName  = optional
commonName              = optional
domainComponent         = optional
emailAddress            = optional
name                    = optional
surname                 = optional
givenName               = optional
dnQualifier             = optional

[ ca_ext ]
# Optional extensions. Use `-extensions ca_ext`
# These extensions are for a CA certificate

subjectKeyIdentifier    = hash
authorityKeyIdentifier  = keyid:always

basicConstraints            = critical, CA:TRUE
# basicConstraints          = critical, CA:TRUE, pathlen:1

keyUsage = critical, keyCertSign, cRLSign

# Policies and constraints are not recommended for Root CAs
# But could be enforced on subordinate CAs

#nameConstraints        = permitted;DNS:example.org

#policyConstraints = requireExplicitPolicy:1

#inhibitAnyPolicy = 1

#certificatePolicies = @CertPol

[ x509_ext ]
#Default extensions
# These extensions are for an end-entity certificate

# Extensions added when using the `openssl ca` command.
# This section is pointed to by `x509_extensions` above.

subjectKeyIdentifier    = hash
authorityKeyIdentifier  = keyid:always

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

keyUsage = critical, digitalSignature

# Policies and constraints are not recommended for Root CAs
# But could be enforced on subordinate CAs

#nameConstraints        = permitted;DNS:example.org

#policyConstraints = requireExplicitPolicy:1

#inhibitAnyPolicy = 1

#certificatePolicies = @CertPol

[ CertPol ]
policyIdentifier = 1.3.6.1.4.132473
CPS = http://pki.example.org/cps.html

Next, create your request using a similar command to the one you used:

$ openssl req -new -newkey rsa:4096 -keyout rootprivkey.pem -out rootreq.pem -config openssl.cnf

Note that the -sigopt options have been removed as the signature at this point is the request signature used for proof of possession of private key and not the signature of the certificate itself - that's later.

Next, sign it to create the self-signed CA certificate:

$ openssl ca -out rootcrt.pem -days 2652 -keyfile rootprivkey.pem -selfsign -config openssl.cnf -extensions ca_ext -in rootreq.pem -sigopt rsa_padding_mode:pss -sigopt rsa_pss_saltlen:-1

Note that this uses openssl ca instead of openssl x509 which means you can refer to a custom openssl.cnf file. Also note the use of the -extensions option to point the command to a specific section of the config file. Finally, note that the -sigopt options have been moved here as this is the command that signs your CA certificate and therefore should have your PSS scheme.

Next, create a separate OpenSSL config file for your server/end-entity certificate (./server.cnf).

# OpenSSL server/end-entity configuration

[ req ]

string_mask        = default

# The size of the keys in bits:
default_bits       = 2048
distinguished_name = req_dn
req_extensions     = req_ext

[ req_dn ]
 
countryName                     = Country Name (2 letter code)
countryName_default             = 
countryName_min                 = 2
countryName_max                 = 2

stateOrProvinceName             = State or Province Name (full name)
stateOrProvinceName_default     = 
localityName                    = Locality Name (eg, city)
localityName_default            = 

0.organizationName              = Organization Name (eg, company)
0.organizationName_default      = 

commonName                      = Common Name

[ req_ext ]

# Careful...
#basicConstraints=critical,CA:TRUE

# subjectAltName = @alt_names

[alt_names]
# To copy the CN (in the case of a DNS name in the CN) use:
# DNS = ${req_dn::commonName}

Run a similar command to the one you used, but with the config file changed.

$ openssl req -new -newkey rsa:4096 -keyout serverprivkey.pem -out serverreq.pem -config server.cnf

Finally, sign it with the CA:

$ openssl ca -in serverreq.pem -days 1200 -cert rootcrt.pem -keyfile rootprivkey.pem -sigopt rsa_padding_mode:pss -sigopt rsa_pss_saltlen:-1 -out servercrt.pem -config openssl.cnf

Note that there is no -extensions option on this one, so OpenSSL defaults to the section pointed to by the x509_extensions = option in openssl.cnf.

You can now verify the certificates:

$ openssl verify -CAfile rootcrt.pem servercrt.pem
servercrt.pem: OK
added 120 characters in body
Source Link
garethTheRed
  • 4.2k
  • 1
  • 20
  • 20

The above config file fails to generate the Root CA certificate in the first place because it doesn't have a CommonName entry. I'm assuming that was a typo or copy/paste error and the rest of the config file is the actual one used.

Your certificate verification fails because your Root CA has the BasicConstraint extensions set to CA:False. That is, it is not a CA and therefore as far as verification is concerned, cannot be used to verify the digital signature on other certificates.

You need to alter your config file so that the command used to generate the CA certificate uses: basicConstraints = CA:true. To make it RFC 5280 compliant, you should also add the critical flag and use basicConstraints = critical,CA:true.

The above config file fails to generate the Root CA certificate in the first place because it doesn't have a CommonName entry. I'm assuming that was a typo or copy/paste error and the rest of the config file is the actual one used.

Your certificate verification fails because your Root CA has the BasicConstraint extensions set to CA:False. That is, it is not a CA and therefore as far as verification is concerned, cannot be used to verify the digital signature on other certificates.

You need to alter your config file so that the command used to generate the CA certificate uses: basicConstraints = CA:true

The above config file fails to generate the Root CA certificate in the first place because it doesn't have a CommonName entry. I'm assuming that was a typo or copy/paste error and the rest of the config file is the actual one used.

Your certificate verification fails because your Root CA has the BasicConstraint extensions set to CA:False. That is, it is not a CA and therefore as far as verification is concerned, cannot be used to verify the digital signature on other certificates.

You need to alter your config file so that the command used to generate the CA certificate uses: basicConstraints = CA:true. To make it RFC 5280 compliant, you should also add the critical flag and use basicConstraints = critical,CA:true.

Source Link
garethTheRed
  • 4.2k
  • 1
  • 20
  • 20

The above config file fails to generate the Root CA certificate in the first place because it doesn't have a CommonName entry. I'm assuming that was a typo or copy/paste error and the rest of the config file is the actual one used.

Your certificate verification fails because your Root CA has the BasicConstraint extensions set to CA:False. That is, it is not a CA and therefore as far as verification is concerned, cannot be used to verify the digital signature on other certificates.

You need to alter your config file so that the command used to generate the CA certificate uses: basicConstraints = CA:true