How to verify the client certificate during the tls handshake - ssl

I made a tls server by below commands, which will request the client who is connecting to provide a client certificate. And I also simulated a client with the openssl commandline which will provide a client certificate. But it seems that the server didn't check if the client certificate is what exactly we want or not. Do you know how to make the server to do the check?
For the server:
openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 -nodes
openssl s_server -key key.pem -cert cert.pem -accept 44330 -Verify 0
For the client:
openssl req -x509 -newkey rsa:2048 -keyout clientkey.pem -out clientcert.pem -days 365 -nodes
openssl s_client -connect 127.0.0.1:44330 -cert clientcert.pem -key clientkey.pem

... check if the client certificate is what exactly we want or not
You do not specify what you want from the client certificate, that's why it cannot check it. If you want that the client certificate is signed by a specific CA use the -CAfile option as documented:
-CAfile infile
A file containing trusted certificates to use during client authentication and to use when attempting to build the server certificate chain. The list is also used in the list of acceptable client CAs passed to the client when a certificate is requested.
Thus, if you want to make sure that the client certificate is the self-signed certificate you issued (or some other certificate signed by this), use:
openssl s_server -key key.pem -cert cert.pem -accept 44330 -Verify 0 \
-CAfile clientcert.pem

Related

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

Client certificates after CA renewal

I have a root CA that was used to generate both server and client certificates in a currently working system.
It will soon reach its expiration date, and I am trying to renew it without changing any server or client certificate but I have failed so far.
To renew the CA, I have used:
openssl req -new -key ca.key -out newcsr.csr
openssl x509 -req -days 3650 -in newcsr.csr -signkey ca.key -out newca.pem
Then I have replaced my old CA certificate by newca.pem.
I expected that to be enough to have it working, but unfortunately it does not.
When trying to send a request with CuRL using my old client certificates (which are not expired), I get this error message:
curl --cert clientcrt.pem --key clientkey.pem https://myserver/
(35) Peer does not recognize and trust the CA that issued your
certificate
(the same request with the old CA does work, since it is not yet expired)
What are the steps that I missed?
Or do you have any clue of causes of error that I may look for?
If it can be useful to anyone, I finally resolved this problem by setting the serial of my new CA to the same value than the serial of the old CA:
openssl req -new -x509 -days 3650 -key ca.key -set_serial <oldserial> -out newca.pem
With that my client certificates are successfully validated by my CA.

Sign a User certificate with CA.key :openssl

I've a user certificate (certname.pem) and user key (keyname.pem) which I've generated using the command below.
openssl req -newkey rsa:2048 -nodes -keyout keyname.pem -x509 -days 365 -out certname.pem
Also I've generated a CA key (ca.key.pem) and CA root certificate (ca.root.pem) using the command below.
openssl req -x509 -days 557 -newkey rsa:1024 -out ca.root.pem -keyout ca.key.pem
Now I want to sign the user certificate (certname.pem) with the CA key (ca.key.pem) but I am unable to do so using the command below.
openssl ca -create_serial -config openssl.cnf -cert ca.root.pem -keyfile ca.key.pem -in certname.pem -out new-certname.pem
as this command gives error:
Error reading certificate request in certname.pem
139992806578040:error:0906D06C:PEM routines:PEM_read_bio:no start line:pem_lib.c:708:Expecting: CERTIFICATE REQUEST
Where as the contents of my certname.pem are as follows:
-----BEGIN CERTIFICATE-----
MIIDozCCAougAwIBAgIJALv1sRsVLIRgMA0GCSqGSIb3DQEBCwUAMGgxCzAJBgNV
BAYTAmluMQ0wCwYDVQQIDARhc2RmMQ0wCwYDVQQHDARhc2RmMQwwCgYDVQQKDANs
a2oxDDAKBgNVBAsMA2xrajEMMAoGA1UEAwwDbGtqMREwDwYJKoZIhvcNAQkBFgJs
ajAeFw0xODA3MDcxNDU1MzNaFw0xOTA3MDcxNDU1MzNaMGgxCzAJBgNVBAYTAmlu
MQ0wCwYDVQQIDARhc2RmMQ0wCwYDVQQHDARhc2RmMQwwCgYDVQQKDANsa2oxDDAK
BgNVBAsMA2xrajEMMAoGA1UEAwwDbGtqMREwDwYJKoZIhvcNAQkBFgJsajCCASIw
DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJxh0L94MzQgjTodq4/Eha4HmX4c
PPsb7H5cUzk1b4N9tfGPoINZ68CY+HqTwXtBTtiwIvkvP/nKD5cp9PhpDB/AI4Zx
c83J72iBpMefn1KgWAUMBNnxnYkezK7SY3osotakBXAT+4tJI1BXL/TAV74VKe9a
7rXSEqCTxcj/H0kbW+2WR/N5yDXjJk68k1A4oQ4wSLiejC9ycqHkZluKZjJl8XNh
9QnEsTtZRiX59FbRa64A16Alv7tBSSTxyCFfQqPxSpgiORoU1vRQqWxD7IV5WXl7
fQLaxR07nmJKxYSK7fGRdcXLQBmkWA0V0pA3qreDAznSfElk3GNhtx0Erk0CAwEA
AaNQME4wHQYDVR0OBBYEFGDedvJ2pbkR2wFsu60fjDPocMFsMB8GA1UdIwQYMBaA
FGDedvJ2pbkR2wFsu60fjDPocMFsMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEL
BQADggEBAIIVz6Aiu1VwM71ecL7aNgyEuctAtfkiDfopKANtBA5yzLQZYlALSkjz
SIUD/vRkiT4C8ZOdfoWJkHxpk93uYH6xjDL8vsqthAA34FvDBMoecrOVNzJq5uBt
aJC4klj57uf1mPzW71yycS9IKFFGardqijjlHUyhgJVBs8kZbABT7ZedYA5UYdv+
SUNnzOU2Sm/ktPF5vWp8y4WjgujYnZQqj7pI4ucwYxb8WRW2EeeGpkbA6DuU7Tnv
frliIESdu9/UCQm7A5zxW47MKTBrVDfoRsbrbjFo9PiGCxG/7bglykFHovWVN2ez
uqLIdDOC2lNFBOJLPhf5w9s3fEGl8m8=
-----END CERTIFICATE-----
How to sign this certificate with the ca.key.pem?
Please help.
Reference for generating certificates - https://www.ibm.com/support/knowledgecenter/en/SSWHYP_4.0.0/com.ibm.apimgmt.cmc.doc/task_apionprem_gernerate_self_signed_openSSL.html
Question originally answered by - https://stackoverflow.com/users/99027/john-deters
on https://security.stackexchange.com/questions/189148/sign-a-user-certificate-with-ca-key-openssl
You included -out certname.pem on your original request, which in this case instructed openssl to generate a self-signed root CA certificate named certname.pem. It is a certificate, but probably not the kind you want here.
I assume you instead want to use your newly minted CA to sign your public key and create a server certificate. You'll need to first generate a Certificate Signing Request (CSR) from your new key (the one in keyname.pem):
openssl req -out keyname.csr -key keyname.pem -new -days 365
You can then pass this CSR to request a certificate:
openssl ca -create_serial -config openssl.cnf -cert ca.root.pem -keyfile ca.key.pem -in keyname.csr -out new-certname.pem
Your issue is - CA signs a CSR (certificate signing request) and as a result is a completely new certificate issued by the CA
I have some examples ready for myself https://pastebin.com/m9rzFJ9c
#create certificate signing request
openssl req -new -key ./sslCA/private/myserver.key -out ./sslCA/private/cakey.csr
#sign the signing request
openssl x509 -req -days 365 -in ./sslCA/private/cakey.csr -signkey ./sslCA/private/myserver.key -out
./sslCA/private/cacert.pem

Create CSR and self-signed-certificate with pyOpenSSL

using pyOpenSSL I want to create
a key pair for self-signing
a certificate signing request (csr)
a self-signed-certificate
When I use the openSSL command line tool I used the following commands to do that:
a key pair for self-signing
openssl genrsa -out pkey.pem 2048
openssl rsa -in pkey.pem -out public-pkey.pem -outform PEM -pubout
a certificate signing request (csr)
openssl req -new -key pkey.pem -subj "/C=US/O=XXX/CN=XXX" -days 365 -out csrrequest.csr
a self-signed-certificate
openssl x509 -in csrrequest.csr -req -signkey pkey.pem -days 365 -set_serial 0x12345 -sha256 -out selfsignedcert.pem
This works! Server accepts the self-signed certificate and returns a server-signed certificate.
For pyOpenSSL I use the following code:
a key pair for self-signing
psec = crypto.PKey()
psec.generate_key(crypto.TYPE_RSA, 2048)
a certificate signing request (csr)
csrrequest = crypto.X509Req()
csrrequest.get_subject().C = "US"
csrrequest.get_subject().O = "XXX"
csrrequest.get_subject().CN = "XXX"
csrrequest.set_pubkey(psec)
a self-signed-certificate
selfsignedcert = crypto.X509()
selfsignedcert.set_serial_number(12345)
selfsignedcert.gmtime_adj_notBefore(0)
selfsignedcert.gmtime_adj_notAfter(365*24*60*60)
selfsignedcert.set_subject(csrrequest.get_subject())
selfsignedcert.set_issuer(selfsignedcert.get_subject())
selfsignedcert.set_pubkey(csrrequest.get_pubkey())
selfsignedcert.sign(psec, "sha256")
This is not working! Server does not accept the self-signed certificate. The server is not able to sign and return a server-signed certificate.
By using pyOpenSSL, however, I miss the input of openssl x509 -in csrrequest.csr -req for the creation of the self-signed certificate...
Where is my fault? Does anyone know what I am doing wrong??
Thanks!
You need to sign the CSR with the private key (similar to a self-signed certificate, but the CA will replace this signature with its own signature in the final certificate).
Try csrrequest.sign(psec,"sha256")
What is it that is not working ?
I noticed that the times are set wrong
Instead of :
selfsignedcert.gmtime_adj_notBefore(0)
selfsignedcert.gmtime_adj_notAfter(365*24*60*60)
What if you tried
current_ts = int(datetime.datetime.now().timestamp())
selfsignedcert.gmtime_adj_notBefore(current_ts)
selfsignedcert.gmtime_adj_notAfter(current_ts + 365*24*60*60)

I'd like to create SSL sertificates for my test environment

Does anyone have a handy script to generate SSL certificates such that it generates the CA certificate and the server certificate. More importantly, create it in a way that I can import the CA certificate into my trusted root list (of my windows system) so that the browser does not flag the site as untrusted.
I used the following script to do it but I am not able to persuade my browser to trust the certificate.
I'd greatly appreciate any help here.
# Generate a private key
openssl genrsa -des3 -out server.key 1024
# Generate a CSR (Certificate Signing Request)
openssl req -new -key server.key -out server.csr
# Remove Passphrase from Key
cp server.key server.key.org
openssl rsa -in server.key.org -out server.key
# Generating a Self-Signed Certificate
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
Regards,
Kashyap
Your script is only generating one certificate, a self-signed certificate. Usually, the self-signed certificate is called the Root certificate. This can be used as a CA certificate, but often an intermediate CA certificate is created and signed by the Root private key. This intermediate CA certificate is then used to sign Server certificates. So you have this hierarchy:
Root -> CA -> Server
The CA and Root cert can go into the trusted certificate list. Then a browser that trusts that list will also trust any certificate signed by the CA or Root entities.
You don't have to have this hierarchy...you can use the Root certificate as the CA and skip the middle cert. You can also just use 1 self-signed certificate as the Root/Server certificate. See this article (Trusting self-signed certificates).
But assuming you do have this hierarchy, here are some OpenSSL commands to generate the necessary keys and certificates:
# 1. Create Root private key
openssl genrsa -out root.key 2048
# 2. Create self-signed Root certificate
openssl req -new -key root.key -x509 -out root.crt -days 5000 -sha256
# 3. Create CA private key
openssl genrsa -out ca.key 2048
# 4. Create CA CSR
openssl req -new -key ca.key -out ca.csr -days 5000
# 5. Sign and create CA certificate
openssl x509 -req -in ca.csr -CA root.crt -CAkey root.key -out ca.crt -set_serial 2 -days 5000 -sha256
# 6. Create Server private key
openssl genrsa -out server.key 2048
# 7. Create Server CSR
openssl req -new -key server.key -out server.csr -days 5000
# 8. Sign and create Server certificate
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -out server.crt -set_serial 3 -days 5000 -sha256
Change the key bits, # of valid days, serial numbers, and add V3 extensions as you see fit.
Also remember that different browsers have different lists that they trust. Chrome and IE use the Windows default list. Firefox has its own list.
Do you have a trusted CA certificate?
You are generating a self-signed certificate which is always considered as untrusted by browsers.