Invalid CA certificate with self signed certificate chain - apache

I have a self signed certificate chain with these commands and configured them on an Apache server
But when i try openssl s_client -showcerts -servername server -connect my-host.local:443 -CAfile all.crt
I get an error from openssl Verify return code: 24 (invalid CA certificate)
Is there something wrong with the commands used to generate the certificates or with the configuration files?
commands used to create certificate chain
# self signed root cert
openssl genrsa -aes256 -out ca.key 4096
openssl req -new -x509 -days 3000 -key ca.key -out ca.crt -config ca.conf
# intermediate cert signed with the root cert
openssl genrsa -aes256 -out int.key 4096
openssl req -new -key int.key -out int.csr -config int.conf
openssl x509 -req -days 3000 -in int.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out int.crt
# leaf cert signed with the intermediate cert
openssl genrsa -aes256 -out leaf.key 4096
openssl req -new -key leaf.key -out leaf.csr -config leaf.conf
openssl x509 -req -days 3000 -in leaf.csr -CA int.crt -CAkey int.key -set_serial 01 -out leaf.crt
cat ca.crt int.crt leaf.crt > all.crt
These are the config files I have used
ca.conf
[ req ]
distinguished_name = req_distinguished_name
x509_extensions = v3_ca
dirstring_type = nobmp
[ req_distinguished_name ]
commonName = Common Name (eg, YOUR name)
commonName_default = root
[ v3_ca ]
keyUsage=critical, keyCertSign
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer:always
basicConstraints=critical,CA:TRUE,pathlen:1
extendedKeyUsage=serverAuth
int.conf
[ req ]
distinguished_name = req_distinguished_name
x509_extensions = ext
[ req_distinguished_name ]
commonName = Common Name (eg, YOUR name)
commonName_default = int
[ ext ]
keyUsage=critical, keyCertSign
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer:always
basicConstraints=CA:TRUE,pathlen:0
extendedKeyUsage=serverAuth
leaf.conf
[ req ]
distinguished_name = req_distinguished_name
dirstring_type = nobmp
[ req_distinguished_name ]
commonName = Common Name (eg, YOUR name)
commonName_default = leaf

A CA root certificate has to be marked as belonging to a CA:
A CA certificate must include the basicConstraints value with the CA
field set to TRUE. An end user certificate must either set CA to FALSE
or exclude the extension entirely. Some software may require the
inclusion of basicConstraints with CA set to FALSE for end entity
certificates.
This is done through the basic constraints standard extension. To check whether your root cert has the CA attribute set, run openssl x509 -text -noout -in ca.crt and look for CA:True in the output. Note that OpenSSL will actually let you sign other certs with a non-CA root cert (or at least used to) but verification of such certs will fail (because the CA check will fail).
With your config file, simply including -extensions v3_ca in the command to generate the root cert should suffice:
openssl req -new -x509 -extensions v3_ca -days 3000 -key ca.key -out ca.crt -config ca.conf -extfile ca.conf

Related

OpenSSL extensions to CA certificate

Im using OpenSSL v1.1.1g and trying to add extensions to my self signed CA certificate using the following bat script:
rem #Create CSR
openssl req -newkey rsa:4096 -keyout ca-key.pem -out ca.csr -subj "..." -addext "keyUsage = cRLSign, digitalSignature, keyCertSign"
rem #Sign it
openssl x509 -signkey ca-key.pem -in ca.csr -req -days 365 -out ca-cert.pem -extfile extensions.cnf
pause
This is contents of extensions.cnf:
subjectAltName=DNS:localhost,IP:0.0.0.0,IP:127.0.0.1
crlDistributionPoints = URI:http://localhost:4444/crl.crl
keyUsage = cRLSign, digitalSignature, keyCertSign
basicConstraints=critical,CA:true,pathlen:0
It seems that neither -addext nor -extfile add keyusage to the cert, but crlDistributionPoints and basicConstraints work.
Can someone post a solution how to add keyusage contents through similar command line commands? I do not want to edit openssl.cnf.
EDIT: Added image of CA cert
CAcert
It seems that the reason for all this whackery was my aversion of openssl.cnf.
The default config was used in background and i just had to create a minimal one by myself rather than using the default.

gRPC SSL No subject alternative names present

How can disable the hostnameverfifier in gRPC to avoid exception below?
java.security.cert.CertificateException: No subject alternative names present
The recommended way to use test certificates where the hostname doesn't match is to call ManagedChannelBuilder.overrideAuthority("test-hostname"). This is functionally similar to adding test-hostname to /etc/hosts. This allows you to choose different IPs/DNS names with forAddress()/forTarget() without disabling security.
But it still seems like your certificate is a bit broken. Subject Alternative Name is required; using the certificate's Subject had been deprecated for a decades.
You may also be interested in using gRPC's test certificates. We provide TlsTesting to load them.
server = ServerBuilder.forPort(0)
// Use test cert on server-side
.useTransportSecurity(
TlsTesting.loadCert("server1.pem"),
TlsTesting.loadCert("server1.key"))
// ...
.build().start();
channel = NettyChannelBuilder
.forAddress("localhost", server.getPort())
// Trust test CA on client-side
.sslContext(
GrpcSslContexts.forClient()
.trustManager(TlsTesting.loadCert("ca.pem"))
.build())
// Change hostname to match certificate
.overrideAuthority("foo.test.google.fr")
.build();
Just to elaborate on #Eric Anderson answer. In the gRPC's test certificates he points to there are 2 types *.cnf files used to generate the client and server certs
1.Generate client cert: openssl.cnf
2.Generate server cert: server1-openssl.cnf
at the very bottom of both files you will find the hostnames where you need to add the matching entries for the client and server
for example if you are local testing for client and server resolving on "localhost" then you would need for both openssl.cnf and server1-openssl.cnf to have
[alt_names]
DNS.1 = localhost
after this you would need to regenerate the certificates
here is a simple script based on the grpc-java info here
#!/bin/bash
SERVER_CN=localhost
CLIENT_CN=localhost # Used when doing mutual TLS
TLS_KEY_PSSWD=somepsswd
echo "When prompted for cert information, everything is default except the common name which is set to localhost"
echo Generate CA key:
openssl genrsa -passout pass:TLS_KEY_PSSWD -des3 -out ca.key 4096
echo Generate CA:
openssl req -passin pass:TLS_KEY_PSSWD -x509 -new -nodes -key ca.key -out ca.pem -config conf/ca-openssl.cnf -days 3650 -extensions v3_req -subj "/CN=${SERVER_CN}"
echo "Now that we’re a CA on all our devices, we can sign certificates for any new dev sites that need HTTPS"
echo Generate client key:
openssl genrsa -out client.key.rsa 1024
openssl pkcs8 -topk8 -in client.key.rsa -out client.key -nocrypt
rm client.key.rsa
echo Generate client signing request:
openssl req -passin pass:TLS_KEY_PSSWD -new -key client.key -out client.csr -subj "/CN=${CLIENT_CN}"
echo Generate client cert:
openssl ca -passin pass:TLS_KEY_PSSWD -in client.csr -out client.pem -keyfile ca.key -cert ca.pem -verbose -config conf/openssl.cnf -days 3650 -updatedb
openssl x509 -in client.pem -out client.pem -outform PEM
echo Generate server key:
openssl genrsa -passout pass:TLS_KEY_PSSWD -out server1.key.rsa 1024
openssl pkcs8 -topk8 -in server1.key.rsa -out server1.key -nocrypt
rm server1.key.rsa
echo Generate server signing request:
openssl req -passin pass:TLS_KEY_PSSWD -new -key server1.key -out server1.csr -config conf/server1-openssl.cnf -subj "/CN=${CLIENT_CN}"
echo Generate server cert:
openssl ca -passin pass:TLS_KEY_PSSWD -in server1.csr -out server1.pem -keyfile ca.key -cert ca.pem -verbose -config conf/server1-openssl.cnf -days 3650 -extensions v3_req -updatedb
openssl x509 -in server1.pem -out server1.pem -outform PEM

Add CRL (certificate revocating list) url to certificates

I am generating the root CA using the commands below:
openssl genrsa -aes256 -out ca.key.pem -passout pass:KeyPassword 4096
openssl req -key ca.key.pem -passin pass:Password -new -x509 -days 365 -sha256 -out ca.root.pem
and then I'm creating signed user certificates (without using intermediate certificates) using the commands below:
1) Generate a key for user
openssl req -newkey rsa:2048 -nodes -keyout keyname.pem -days 365
2) Create a CSR
openssl req -out keyname.csr -key keyname.pem -new -days 365
3) Signing the key with root cert
openssl ca -batch -create_serial -config openssl.cnf -cert ca.root.pem -keyfile ca.key.pem -passin pass:KeyFinalPassword -in keyname.csr -out certname.pem
4) Generate .p12 file
openssl pkcs12 -name username -inkey keyname.pem -in certname.pem -export -out username.p12 -password pass:password
Note - I've added crlDistributionPoints = URI:http://localhost:8000/crl/distripoint.crl.pem to the openssl.cnf along with below options:
# For certificate revocation lists.
# crlDistributionPoints = URI:http://HOSTNAME/crl/distripoint.crl.pem
crlDistributionPoints = URI:http://localhost:8000/crl/distripoint.crl.pem
crlnumber = $dir/config/crl/crlnumber
crl = $dir/config/crl/ca.crl.pem
crl_extensions = crl_ext
default_crl_days = 60
Note- I generated distribution.crl.pem using this tutorial
The crlDistributionPoints parameter must be added to the x509_extensions section of the CA you are using. (In your example, it looks like you have added this parameter to the CA section itself.)
openssl ca using the openssl.cnf with these lines adds the CRL Distribution Points extension to the issued certificate:
[ ca ]
default_ca = CA_default
[ CA_default ]
(...other parameters...)
x509_extensions = added-extensions
[ added-extensions ]
crlDistributionPoints = URI:http://localhost:8000/crl/distripoint.crl.pem
You might want to use a custom openssl.cnf instead of the default one for req and ca commands; the default contains many example entries which may not do what you want. Here are examples of minimal openssl.cnf.
(Side note: your last command generating .p12 file is not relevant to the question; it only packs already created certificates in another format.)

Can't use "custom" SSL certificate in proxy server (built-in works)

I'm trying to configure Titanium web proxy to use my own SSL certificate (ok and I need to generate my certificate(s) again because i just deleted them).
First: my use case works fine, I need to intercept https traffic and
I setup Titanium in a .NET Core app. It generated and
configured/installed come "rootCert.pfx" file and I can intercept
https traffic.
ref: https://github.com/justcoding121/Titanium-Web-Proxy/wiki#custom-root-certificates
The referenced page says I can set a custom root certificate using the RootCertificate property on the proxyserver.
So I create a certificate:
openssl req -x509 -sha256 -nodes -newkey rsa:2048 -days 365 -keyout localhost.key -out localhost.crt
convert it to a pfx:
openssl pkcs12 -export -out localhost.pfx -inkey localhost.key -in localhost.crt
copy it to the output directory and configure it as RootCertificate.
But now my browser says for any https request:
ERR_CONNECTION_CLOSED
I tried doubleclicking and installing the crt file but this doesn't help..
Am a little lost here as to where I should place what certificate. To make things more complicated for me to understand there is also a GenericCertificate property on the ExplicitProxyEndPoint class... If I configure the root certificate there then my browser returns:
ERR_CERT_AUTHORITY_INVALID
Any guidance or tips would be greatly appreciated!
Second try (spoiler: failed again)
Create CA key: customCA.key
openssl genrsa -des3 -out customCA.key 2048
Create CA root certificate: customCA.pem
openssl req -x509 -new -nodes -key customCA.key -sha256 -days 1825 -out customCA.pem
Trust CA root certificate: Import customCA.pem
Create localhost key: localhost.key
openssl genrsa -out localhost.key 2048
Create localhost sign request: localhost.csr
openssl req -new -key localhost.key -out localhost.csr
Create custom ext options: localhost.ext
[ req ]
default_bits = 2048
default_keyfile = customCA.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 = myEmail#email.com
[ v3_req ]
basicConstraints = CA:TRUE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment
[ v3_ca ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always
subjectAltName = email:myEmail#email.com
issuerAltName = issuer:copy
Create signed localhost certificate: localhost.crt
openssl x509 -req -in localhost.csr -CA customCA.pem -CAkey customCA.key -CAcreateserial -out localhost.crt -days 1825 -sha256 -extfile localhost.ext
Convert signed localhost certificate from crt to pfx: localhost.pfx
openssl pkcs12 -export -out localhost.pfx -inkey localhost.key -in localhost.crt
Now if I specify localhost.pfx as the RootCertificate for the proxyserver (which i'm assuming will be trusted due to the fact that it is signed by customCA which is a trusted authority) i still get:
ERR_CONNECTION_CLOSED
I'm starting to get confused about RootCertificate and Certificate Authority. It seems that the proxyserver requires a mix of both?

docker swarm certificate expiry

I am trying to create a docker swarm that has certificates that expire after 1 year or more. The documentation states the syntax and I tried this docker swarm init --cert-expiry 8760h0m0s
However under cat /var/lib/docker/swarm/certificates/swarm-node.crt when I decipher the certificate the validity is still 3 months. How do I make sure that validity is what I have set it to?
You can generate certificates manually using the OpenSSL tool and configure Docker daemon to use these certificates.
Generate Server Certificates
Generate CA private and public keys:
openssl genrsa -aes256 -out ca-key.pem 4096
openssl req -new -x509 -days 1000 -key ca-key.pem -sha256 -out ca.pem
Create a server key and certificate signing request (CSR):
openssl genrsa -out server-key.pem 4096
openssl req -subj "/CN=my.company.com" -sha256 -new -key server-key.pem -out server.csr
Sign the public key with CA:
echo subjectAltName = DNS:my.company.com,IP:127.0.0.1 >> extfile.cnf
echo extendedKeyUsage = serverAuth >> extfile.cnf
Generate the key:
openssl x509 -req -days 1000 -sha256 -in server.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out server-cert.pem -extfile extfile.cnf
Generate Client Certificates
Create a client key and certificate signing request:
openssl genrsa -out key.pem 4096
openssl req -subj '/CN=client' -new -key key.pem -out client.csr
Create an extensions config file:
echo extendedKeyUsage = clientAuth >> extfile.cnf
Sign the private key:
openssl x509 -req -days 1000 -sha256 -in client.csr -CA ../server/ca.pem -CAkey ../server/ca-key.pem -CAcreateserial -out cert.pem -extfile extfile.cnf
Export cert.pem into PFX format to be added into Trusted Root Certification Authorities
openssl pkcs12 -export -in cert.pem -inkey key.pem -out cert.pfx
Configure Docker daemon with /etc/docker/daemon.json
{
"debug": false,
"tls": true,
"tlsverify": true,
"tlscacert": "/etc/docker/certificates/server/ca.pem",
"tlscert": "/etc/docker/certificates/server/server-cert.pem",
"tlskey": "/etc/docker/certificates/server/server-key.pem",
"hosts": ["tcp://0.0.0.0:2376", "unix:///var/run/docker.sock"]
}
Start Docker Service
systemctl start docker
Have a look at this article Building Jenkins Pipelines – Setting Up Docker Swarm. There's a step-by-step guide there.
Run the following commands on any of the management nodes:
docker swarm update --cert-expiry 8760h0m0s
docker swarm ca --rotate | openssl x509 -text -noout
The first one will set certificate expiry date.
The last one will actually apply changes and rotate certificates on all swarm nodes automatically. If not interested in decoding cert text output, the openssl part can be omitted.