Is there a way to check if a certificate is client cert or server cert? - certificate

I received a new keystore .jks file for ssl connection to replace an old, but working, .jks keystore file, but I got "unexpected handshake message: serve_hello" error. I was told to make sure the keystore contains a client cert, so I used keytool to export its cert to a pem file, then use openssl to check the purpose. The result shows
Certificate purposes:
SSL client : No
SSL client CA : No
SSL server : Yes
SSL server CA : No
...
However when I applied the same process to check the old but working jks file I got the same result. Wonder if this is the right way to verify the certificate? And how to troubleshooting this handshake error with the new jks file?
Thanks!

The extended key usage extension contains OIDs which define the purpose:
id-kp-serverAuth OBJECT IDENTIFIER ::= { id-kp 1 }
-- TLS WWW server authentication
-- Key usage bits that may be consistent: digitalSignature,
-- keyEncipherment or keyAgreement
id-kp-clientAuth OBJECT IDENTIFIER ::= { id-kp 2 }
-- TLS WWW client authentication
-- Key usage bits that may be consistent: digitalSignature
-- and/or keyAgreement
https://datatracker.ietf.org/doc/html/rfc5280 Page 44
See: https://oidref.com/1.3.6.1.5.5.7.3.1 and https://oidref.com/1.3.6.1.5.5.7.3.2
When opening a certificate on Windows you can see the extension here:

Related

minio+KMS x509: certificate signed by unknown authority

I am trying to use minio as a local S3 server. I am following this article
I downloaded key and cert files.
I added the env parameters:
set MINIO_KMS_KES_ENDPOINT=https://play.min.io:7373
set MINIO_KMS_KES_KEY_FILE=D:\KMS\root.key
set MINIO_KMS_KES_CERT_FILE=D:\KMS\root.cert
set MINIO_KMS_KES_KEY_NAME=my-minio-key
I started minio server: D:\>minio.exe server D:\Photos
It logs after sturt up:
Endpoint: http://169.254.182.253:9000 http://169.254.47.198:9000 http://172.17.39.193:9000 http://192.168.0.191:9000 http://169.254.103.105:9000 http://169.254.209.102:9000 http://169.254.136.71:9000 http://127.0.0.1:9000
AccessKey: minioadmin
SecretKey: minioadmin
Browser Access:
http://169.254.182.253:9000 http://169.254.47.198:9000 http://172.17.39.193:9000 http://192.168.0.191:9000 http://169.254.103.105:9000 http://169.254.209.102:9000 http://169.254.136.71:9000 http://127.0.0.1:9000
Command-line Access: https://docs.min.io/docs/minio-client-quickstart-guide
$ mc.exe alias set myminio http://169.254.182.253:9000 minioadmin minioadmin
Object API (Amazon S3 compatible):
Go: https://docs.min.io/docs/golang-client-quickstart-guide
Java: https://docs.min.io/docs/java-client-quickstart-guide
Python: https://docs.min.io/docs/python-client-quickstart-guide
JavaScript: https://docs.min.io/docs/javascript-client-quickstart-guide
.NET: https://docs.min.io/docs/dotnet-client-quickstart-guide
Detected default credentials 'minioadmin:minioadmin', please change the credentials immediately using 'MINIO_ACCESS_KEY' and 'MINIO_SECRET_KEY'
I opened UI in browser: http://localhost:9000/minio/mybacket/
I tried to upload a jpg file and got an exception:
<?xml version="1.0" encoding="UTF-8"?> <Error><Code>InternalError</Code><Message>We encountered an internal error, please try again.</Message><Key>Completed.jpg</Key><BucketName>mybacket</BucketName><Resource>/minio/upload/mybacket/Completed.jpg</Resource><RequestId>1634A6E5663C9D70</RequestId><HostId>4a46a947-6473-4d53-bbb3-a4f908d444ce</HostId></Error>
And I got this exception in minio console:
Error: Post "https://play.min.io:7373/v1/key/generate/my-minio-key": x509: certificate signed by unknown authority
3: cmd\api-errors.go:1961:cmd.toAPIErrorCode()
2: cmd\api-errors.go:1986:cmd.toAPIError()
1: cmd\web-handlers.go:1116:cmd.(*webAPIHandlers).Upload()
Most probably your OS trust store (containing the Root CA certificates) does not trust Let's Encrypt (the Let's Encrypt Authority X3 CA certificate).
The server https://play.min.io:7373 serves a TLS certificates issued by Let's Encrypt.
See:
openssl s_client -showcerts -servername play.min.io -connect play.min.io:7373
Eventually, check your the root CA store of your windows machine.
See: https://security.stackexchange.com/questions/48437/how-can-you-check-the-installed-certificate-authority-in-windows-7-8

PHP imap_open(), OpenSSL, and no Cipher

I have moved a PHP script to another server, and now fail to login to an IMAP (TLS) postbox:
TLS/SSL failure for mail.servername.de: SSL negotiation failed
It seems that the problem is caused by OpenSSL, because when I try to connect to the Mailserver from both servers, I get a connection in one case (the mailserver asking for input), but none in the other (the connection is closed, I am back to bash):
openssl s_client -crlf -connect mail.servername.de:993
The most obvious difference is here:
verify return:1
---
<snip>
-----END CERTIFICATE-----
subject=/CN=mail.servername.de
issuer=/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
---
No client certificate CA names sent
Peer signing digest: SHA512
Server Temp Key: DH, 1024 bits
---
SSL handshake has read 3398 bytes and written 483 bytes
Verification: OK
---
New, TLSv1.2, Cipher is DHE-RSA-AES256-GCM-SHA384
Server public key is 2048 bit
And on th other server (where no connection is made)
verify return:1
depth=0 CN = mail.servername.de
verify return:1
140410888582464:error:141A318A:SSL routines:tls_process_ske_dhe:dh key too small:../ssl/statem/statem_clnt.c:2149:
---
<snip>
-----END CERTIFICATE-----
subject=CN = mail.servername.de
issuer=C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3
---
No client certificate CA names sent
---
SSL handshake has read 3167 bytes and written 318 bytes
Verification: OK
---
New, (NONE), Cipher is (NONE)
Server public key is 2048 bit
On the mailserver dovecot is configured not to accept non-encrypted connections. But, I assume it already fails due to dh key too small, which seems to relate to cipher negotiation.
Now I simply fail to put the things together... Why does the SSL connection work from one server, but not from the other?
As I own the "remote end" myself, I was able to increase security. The solution is simple, and may be relevant for others as well ...
The dovecot version is 2.2.x, which is of some relevance for the DH parmaters (see Dovecot SSL configuration). In the configuration file /etc/dovecot/conf.d/10-ssl.conf you can simply add this line:
ssl_dh_parameters_length = 2048
And eventually, it may be necessary to add this here to the main configuration file /etc/dovecot/dovecot.conf at the end:
!include conf.d/*.conf
Finally, it is important not to reload, but to restart dovecot.
systemctl restart dovecot
And suddently, the weight, troubles, and frustration of several hours is gone. Great...
Further to the above, there's a change from dovecot 2.3.
ssl_dh_parameters_length is now not used, and ssl_dh must be used instead, to point to a file generated using
openssl dhparam 4096 > dh.pem
see https://doc.dovecot.org/configuration_manual/dovecot_ssl_configuration/ and scroll down to SSL Security Settings. That was the only change I had to make following the upgrade to get it to work properly again. I put the dh.pem file in /etc/dovecot, so my line in 10-ssh.conf is
ssl_dh=</etc/dovecot/dh.pem
TL;DR: your new host has a newer version of OpenSSL probably with higher security settings which prohibit connecting to the host for reasons explained below.
"dh key too small" comes from OpenSSL and because of too low security.
Things changed, and for example in newest Debian versions and with OpenSSL 1.1.1 (and I guess it is similar for newer versions), the security was enhanced.
The best and simplest explanation I have found is on Debian wiki at https://wiki.debian.org/ContinuousIntegration/TriagingTips/openssl-1.1.1
which says:
In Debian the defaults are set to more secure values by default. This
is done in the /etc/ssl/openssl.cnf config file. At the end of the
file there is:
[system_default_sect]
MinProtocol = TLSv1.2
CipherString = DEFAULT#SECLEVEL=2
This can results in errors such as:
dh key too small
ee key too small
ca md too weak
Now the possible solutions in descending order of preference:
ask the remote end to generate better "DH" values ("Server Temp Key: DH, 1024 bits"); the best explanations are at https://weakdh.org/sysadmin.html; note specifically the "Administrators should use 2048-bit or stronger Diffie-Hellman groups with "safe" primes."
configure your end specifically for this connnection to not use the OS default and lower your settings; it should be enough to set ciphers to "DEFAULT#SECLEVEL=1" in the code that does the connection
(really, really, really not recommended) change the value of SECLEVEL from 2 to 1 in the global configuration file on your end. But this impacts all connections from your host not just this one so you are lowering the global security of your system just because of one low level of security from one remote node.

Dart Add SSL certificate and key to HttpClient

I'm trying to secure a REST API using TLS/SSL, to do so I needed to update my client to use the public key and certificate.
The client is written in dart and here's how I implemented the SecurityContext :
SecurityContext clientContext = SecurityContext.defaultContext;
var certificate = (await rootBundle.load("assets/ssl/coastr.crt")).buffer.asInt8List();
print(certificate.toString());
clientContext.setTrustedCertificatesBytes(certificate);
/*var authorities = (await rootBundle.load('assets/ssl/coastr.ca-bundle')).buffer.asUint8List();
print(authorities.toString());
clientContext.setClientAuthoritiesBytes(authorities);*/
var key = (await rootBundle.load("assets/ssl/coastr_public.key")).buffer.asInt8List();
print(key.toString());
clientContext.usePrivateKeyBytes(key);
HttpClient client = HttpClient(context: clientContext);
HttpClientRequest request = await client.getUrl(Uri.parse(url));
HttpClientResponse response = await request.close();
The certificate (.crt file) is added without issue to the clientContext but adding the key to it returns me this error :
[ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhandled Exception:
TlsException: Failure in usePrivateKeyBytes (OS Error:
BAD_PKCS12_DATA(pkcs8_x509.c:606)
passed a null parameter(ssl_privkey.cc:375), errno = 0)
The files I'm using are :
coastr.crt with this as a header : -----BEGIN CERTIFICATE-----
coastr_public.key with header : -----BEGIN PUBLIC KEY-----
I have no idea if I'm providing the wrong files to the client or if the error comes from elsewhere.
The files where generated using openssl.
Thank you for your help.
In general, you shouldn't have to add anything to the client to allow it to connect to a correctly configured HTTPS server. Hopefully, the server has a signed server side certificate. If that certificate is signed by a reputable CA, the client should automatically trust it. If it is signed by an in house CA, or self signed, you need to do some work. You need to provide the client with the signing certificate. In the former case that would be the root CA's certificate. In the latter case, supplying the server's certificate may work, though it's probably easier to disable the client check altogether.
The signing certificate is likely to be in CRT form as you've found. And you need to supply that exactly as you are doing. There's no need to supply any public keys as the are distributed in the certificates sent with the server hello.
Unless you want to use a client side certificate, there's no need to supply a private key, so you can skip the step that is failing. And supplying a public key to it is definitely not going to work, anyway.

Unable to get the new paypal SSL CA certificates to be recognized. Handshake to Sandbox failing

I am testing a sandbox version of the PayPal IPN system that worked previously, but is now not functioning. The IPN simulator says:
"IPN was not sent, and the handshake was not verified. Please review your information."
I reviewed the documentation about the Verisign G5 CA certificate and followed the instructions shown, but the following command:
openssl s_client -connect api-3t.sandbox.paypal.com:443 -showcerts -CApath /etc/ssl/certs/
Still produces this output: (Truncated)
SSL-Session:
Protocol : TLSv1
Cipher : AES256-SHA
Session-ID: 9E01CD86FA9E600EAD505F17E34C0F9BE07E7894E35B20BAF2946F88596BB047
Session-ID-ctx:
Master-Key: 90F662CD0BD319EB87ACFE89CDACEFED2327AC4C827ED74861166B86423B5404
587A70B65BCEA2FAC23F7DDAAA49F9DC
Key-Arg : None
Start Time: 1445624886
Timeout : 300 (sec)
Verify return code: 20 (unable to get local issuer certificate)
I verified that the G3 certificate is no longer in the certificate store, and even removed and reinstalled the new certificate many times. I have spent the last 10 hours on this with no end in sight.
I own my own servers, so there is no other administrator I can turn to... I need to figure out how to solve this myself, and am at my wits end. I know I do not know as much about SSL and certificate chains as I should, but theres no help for that part lol.
Can anyone who has performed this task give me a kick in the right direction, and/or let me know what additional information I can provide to help solicit a solution?
Thank you very much,
Dave
Here's how I did to import the G5 root cert into openssl:
Obtain a G5 root certificate from Verisign (Symantec) HERE (get it in PEM format, save the file with .pem extension)
Put the file into your openssl base dir (should be like "/usr/lib/ssl" on your server, but you may check the base dir by running openssl version -d)
Run the command to install the cert
openssl verify -CApath <ssl-base-dir>certs server-certificate-file
(replace <ssl-base-dir> with your openssl base dir, and replace server-certificate-file with your .pem file, the command would be something like openssl verify -CApath /usr/lib/ssl/certs G5.pem)
The response would be an G5.pem: OK for the installation
Try again with the connection command
openssl s_client -connect api-3t.sandbox.paypal.com:443 -showcerts -CApath /usr/lib/ssl/certs/
You will see Verify return code: 0 (ok) at the end of the response
I downloaded the VeriSign Class 3 Public Primary Certification Authority - G5.pem certificate file into a local directory, and ran the following command:
openssl s_client -connect api-3t.sandbox.paypal.com:443 -showcerts
-CAfile "ssl\VeriSign Class 3 Public Primary Certification Authority - G5.pem"
Openssl returned a successful result (truncated):
Server certificate
subject=/C=US/ST=California/L=San Jose/O=PayPal, Inc./OU=PayPal Production/CN=api-3t.sandbox.paypal.com
issuer=/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=Terms of use at https://www.verisign.com/rpa (c)10/CN=VeriSign Class 3 Secure Server CA - G3
---
No client certificate CA names sent
---
SSL handshake has read 3379 bytes and written 344 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol : TLSv1
Cipher : ECDHE-RSA-AES256-SHA
Session-ID: 9E01CD86FA9CEB77AD505F17E34C0B9B8A233BD98E30D705F2946F88596F077D
Session-ID-ctx:
Master-Key: 7AC616B7499ED70B6D75FAD3308C332A48B85987685A514365B7507297A3C6A70CD6E7503CE27A9A157045531B54149F
Key-Arg : None
PSK identity: None
PSK identity hint: None
Start Time: 1445867355
Timeout : 300 (sec)
Verify return code: 0 (ok)
---
Note that I used the -CAfile option to directly reference the CA root certificate.

Java SSL keystore load

I use Eclipse to make ssl socket server-client communication.
I am trying to use self signed certificate.
I make keystorage with Eclipse keytool.
Than I try to load this keystorage:
String ksName = "herong.jks";
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(new FileInputStream(ksName), ksPass);
But I get following message:
herong.jks (No such file or directory)
Name of keysotre is correct. May be I should do something else? now I only create keystore and certificate in key tool.