Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Error when opening https URL: keyCertSign bit is not set

Tags:

java

ssl

groovy

I am calling a remote https URL with the following code:

   def inputStream = new URL("https://somewebsite.com").openStream()

This works great on my local machine, but when I deploy to the server, I get the following Exception:

java.security.cert.CertPathValidatorException: CA key usage check failed: keyCertSign bit is not set

What is the cause of this error, and what could account for it working on one machine and not another?


UPDATE


I'm running an Ubuntu server in production and developing on a Mac locally. The site I'm trying to access (let's call it peopleware.com) has the following certificate info:

  1. AddTrust External CA Root
  2. UTN-USERFirst-Hardware
  3. peopleware.com

I have tried saving the .cer files from my browser and installing them into the keystore at /etc/ssl/certs/java/castore

like image 548
Mike Sickler Avatar asked Apr 22 '12 12:04

Mike Sickler


1 Answers

I'm assuming that you're talking about this certificate from UTN-USERFirst-Hardware:

-----BEGIN CERTIFICATE----- 
MIIEdDCCA1ygAwIBAgIQRL4Mi1AAJLQR0zYq/mUK/TANBgkqhkiG9w0BAQUFADCB
lzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug
Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho
dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3Qt
SGFyZHdhcmUwHhcNOTkwNzA5MTgxMDQyWhcNMTkwNzA5MTgxOTIyWjCBlzELMAkG
A1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEe
MBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8v
d3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdh
cmUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCx98M4P7Sof885glFn
0G2f0v9Y8+efK+wNiVSZuTiZFvfgIXlIwrthdBKWHTxqctU8EGc6Oe0rE81m65UJ
M6Rsl7HoxuzBdXmcRl6Nq9Bq/bkqVRcQVLMZ8Jr28bFdtqdt++BxF2uiiPsA3/4a
MXcMmgF6sTLjKwEHOG7DpV4jvEWbe1DByTCP2+UretNb+zNAHqDVmBe8i4fDidNd
oI6yqqr2jmmIBsX6iSHzCJ1pLgkzmykNRg+MzEk0sGlRvfkGzWitZky8PqxhvQqI
DsjfPe58BEydCl5rkdbux+0ojatNh4lz0G6k0B4WixThdkQDf2Os5M1JnMWS9Ksy
oUhbAgMBAAGjgbkwgbYwCwYDVR0PBAQDAgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYD
VR0OBBYEFKFyXyYbKJhDlV0HN9WFlp1L0sNFMEQGA1UdHwQ9MDswOaA3oDWGM2h0
dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VVE4tVVNFUkZpcnN0LUhhcmR3YXJlLmNy
bDAxBgNVHSUEKjAoBggrBgEFBQcDAQYIKwYBBQUHAwUGCCsGAQUFBwMGBggrBgEF
BQcDBzANBgkqhkiG9w0BAQUFAAOCAQEARxkP3nTGmZev/K0oXnWO6y1n7k57K9cM
//bey1WiCuFMVGWTYGufEpytXoMs61quwOQt9ABjHbjAbPLPSbtNk28Gpgoiskli
CE7/yMgUsogWXecB5BKV5UU0s4tpvc+0hY91UZ59Ojg6FEgSxvunOxqNDYJAB+gE
CJChicsZUN/KHAG8HQQZexB2lzvukJDKxA4fFm517zP4029bHpbj4HR3dHuKom4t
3XbWOTCC8KucUvIqx69JXn7HaOWCgchqJ/kniCrVWFCVH/A7HFe7fRQ5YiuayZSS
KqMiDP+JJn1fIytH1xUdqWqeUQ0qUZ6B+dQ7XnASfxAynB67nfhmqA== 
-----END CERTIFICATE-----

In a human-readable version:

Version: 3 (0x2)
Serial Number:
    44:be:0c:8b:50:00:24:b4:11:d3:36:2a:fe:65:0a:fd
Signature Algorithm: sha1WithRSAEncryption
Issuer: C=US, ST=UT, L=Salt Lake City, O=The USERTRUST Network, OU=http://www.usertrust.com, CN=UTN-USERFirst-Hardware
Validity
    Not Before: Jul  9 18:10:42 1999 GMT
    Not After : Jul  9 18:19:22 2019 GMT
Subject: C=US, ST=UT, L=Salt Lake City, O=The USERTRUST Network, OU=http://www.usertrust.com, CN=UTN-USERFirst-Hardware
Subject Public Key Info:
    [...]
X509v3 extensions:
    X509v3 Key Usage: 
        Digital Signature, Non Repudiation, Certificate Sign, CRL Sign
    X509v3 Basic Constraints: critical
        CA:TRUE
    X509v3 Subject Key Identifier: 
        A1:72:5F:26:1B:28:98:43:95:5D:07:37:D5:85:96:9D:4B:D2:C3:45
    X509v3 CRL Distribution Points: 

        Full Name:
          URI:http://crl.usertrust.com/UTN-USERFirst-Hardware.crl

    X509v3 Extended Key Usage: 
        TLS Web Server Authentication, IPSec End System, IPSec Tunnel, IPSec User

Essentially, we have here a CA certificate with both X509v3 Key Usage and X509v3 Extended Key Usage.

However, RFC 3280 says the following about the extended key usage extension:

In general, this extension will appear only in end entity certificates.

This doesn't start too well for a CA cert, but later on, the same section also says this:

If a certificate contains both a key usage extension and an extended key usage extension, then both extensions MUST be processed independently and the certificate MUST only be used for a purpose consistent with both extensions. If there is no purpose consistent with both extensions, then the certificate MUST NOT be used for any purpose.

The only extended key usage extension in this cert that is in this RFC is TLS Web Server Authentication:

   id-kp-serverAuth             OBJECT IDENTIFIER ::= { id-kp 1 }
   -- TLS WWW server authentication
   -- Key usage bits that may be consistent: digitalSignature,
   -- keyEncipherment or keyAgreement

Of course, this is not consistent with keyCertSign, which, according to RFC 3280 (and RFC 5280). (I also doubt any of the IPSec extensions are compatible with keyCertSign). This makes this certificate useless to issue certificates (not very useful for a CA certificate).

I would contact the website using this certificate to ask them to contact their CA (UTN-USERFirst-Hardware, apparently Comodo) and ask them to fix this. I must say it doesn't look good coming from people who make their money on the back of these RFCs.

Of course, this could take a while and wouldn't solve your immediate problem.

I think I've seen this Subject DN (UTN-USERFirst-Hardware) in other intermediate CA certificates, so the one above might not be the one you're using.

What you might be able to do (provided that you're able to verify the server certificate itself manually despite these problems) is to use an SSLContext and a TrustManager specifically limited to use that very certificate, for this connection. This could prevent the certification path algorithm to try to find the issuer certificate and fall into this problem.

EDIT:

Here are more details on this workaround (which should still keep your connection secure).

  • Connect with Firefox to this website.
  • Click on the blue/green bar and choose 'More information...'
  • Security -> View Certificate -> Details
  • Choose the server certificate from the list at the top and choose 'Export...'
  • Same the PEM file somewhere.

Use keytool to create a new keystore (choose to trust that certificate and choose a sensible password):

keytool -importcert -keystore example.jks -file example.pem

Then, use this Java code, which shouldn't be too hard to port to Groovy:

TrustManagerFactory tmf = TrustManagerFactory
    .getInstance(TrustManagerFactory.getDefaultAlgorithm());
KeyStore ks = KeyStore.getInstance("JKS");
FileInputStream fis = new FileInputStream("/.../example.jks");
ks.load(fis, null);
// or ks.load(fis, "thepassword".toCharArray());
fis.close();

tmf.init(ks);

SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, tmf.getTrustManagers(), null);

URL url = new URL("https://somewebsite.com");
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.setSSLSocketFactory(sslContext.getSocketFactory());

InputStream is = conn.getInputStream();
like image 52
Bruno Avatar answered Oct 20 '22 01:10

Bruno