Recently, I've been testing the certificate pinning implementation provided by OkHttp using version 4.9.0 + Retrofit 2.9.0; And I've noticed that the hash check is not conjunctive but rather disjunctive.
According to the example implementation the certificate chain of publicobject.com:
Peer certificate chain:
sha256/afwiKY3RxoMmLkuRW1l7QsPZTJPwDS2pdDROQjXw8ig=: CN=publicobject.com, OU=PositiveSSL
sha256/klO23nT2ehFDXCfx3eHTDRESMz3asj1muO+4aIdjiuY=: CN=COMODO RSA Secure Server CA
sha256/grX4Ta9HpZx6tSHkmCrvpApTQGo67CYDnvprLg5yRME=: CN=COMODO RSA Certification Authority
sha256/lCppFqbkrlJ3EcVFAkeip0+44VaoJUymbnOaEUk7tEU=: CN=AddTrust External CA Root
If we change the certificate and we do so with the same provider and/or root as before, we would get something like:
Peer certificate chain:
sha256/dklfnskvAAQFvandjfjASAFjvjvg45nbwskdvur5548=: CN=publicobject.com, OU=PositiveSSL
sha256/klO23nT2ehFDXCfx3eHTDRESMz3asj1muO+4aIdjiuY=: CN=COMODO RSA Secure Server CA
sha256/grX4Ta9HpZx6tSHkmCrvpApTQGo67CYDnvprLg5yRME=: CN=COMODO RSA Certification Authority
sha256/lCppFqbkrlJ3EcVFAkeip0+44VaoJUymbnOaEUk7tEU=: CN=AddTrust External CA Root
Only the first hash changes, naturally I would assume that communications with the site should stop working since our implementation now has an incorrect hash, but that is not the case because the other three are the same as before.
Is it my error when creating a new certificate?
Is this the correct behavior or an error?
Is there a way to check for all hashes in the chain to be correct?
There's 4 certificates involved in that particular handshake, and OkHttp is happy if any of them match one of your signatures.
This means you can survive either of these operational events:
changing your certificate authority (your organization public key stays the same)
losing your public key and switching it out (the CA stays the same)
But if you change certificate authorities and you get a new public key, clients won't connect until you update their pins.
Related
While using AndroidKeyStore KeyGenerator to create a new ceritificate for key attestation, why Android doesn't provide an option in KeyGenParameterSpec to allow developer to create a CA with additional SubjectAltName?
The reason to ask is that if we would like to create a self-defined gRPC channel (over HTTP2) for example, using this AndroidKeyStore-generated CA for attestation, the CN will always be unchanged as "Android Keystore Key" even setCertificateSubject() is invoked and there is no valid hostname (FQDN, IP-Address) can be verified in TLS session in GrpcUtil.checkAuthority().
The current workaround is to modified the gRPC library to call disableCheckAuthority() when utilizing OkHttp Connection.
How to set SubAltName in an attestation CA generated from Android KeyStore?
I was implementing secure calling from asterisk official site tutorial
And after a lot of effort and understanding of ssl and certificates, I have managed to secure it only 1 way.
Following was the best clue and direction:
SSL using self signed certs on linphone
How can I make use of client certificates (which the above tutorial generated) to validate clients also on server; called full ssl authentication
I read about this setting in linphonerc file: "verify_client_certs=1" but I don't know where to put client certs?
Hi you can check on our wiki to more information about client certificats.
https://wiki.linphone.org/wiki/index.php/Security:ClientCertAuth
Security:ClientCertAuth
1. Creating Client certificate
Generate a Certificate Signing Request
Creates a new private key and a certificate request with CN=username#domain
example test#test.linphone.org
openssl req -new -keyout key.pem -out newreq.pem
Sign the client certificate
Creates newcert.pem certificate signed by root certificate. You will need to enter the passphrase of the cacert.pem
openssl ca -policy policy_anything -out newcert.pem -infiles newreq.pem
Then extract the private key in a new file
openssl rsa -in key.pem -out clientkey.pem
Parameters for linphone
In linphonerc add path to client/key certificate
[sip]
client_cert_chain=/pathTo/newcert.pem
client_cert_key=/pathTo/clientkey.pem
Please, confirm where in following command we use cacert.pem
openssl ca -policy policy_anything -out newcert.pem -infiles newreq.pem
also i have trying to use self signed ca certficate to setup asterisk with linphone. But i could'nt figure where in linphone app i have to put the client cert or even would it work if i just add my rootca.pem to the rootca.pem in the provided source for linphone-android
I'm currently developing an Android app that generates an RSA key pair, builds and sends an PKCS#10 certification request to one CA, waits for the CA's response (which contains the certificate-chain including the issued for the end-entity), and then builds the PKCS#12 KeyStore to be installed within the Android KeyStore.
I just show you below some piece of code:
// It removes Android-BC
Security.removeProvider("BC");
// I've tried with SpongyCastle but it also fails.
// I've previously imported BC jars.
Security.addProvider(new BouncyCastleProvider());
KeyStore ks = KeyStore.getInstance("PKCS12","BC");
ks.load(null);
// KeyPair generated by RSA with BC, and certificates obtained from CA.
PrivateKey prvK;
Certificate eeCert, caCert;
PKCS12BagAttributeCarrier caCertBagAttr =
(PKCS12BagAttributeCarrier) caCert;
caCertBagAttr.setBagAttribute(
PKCSObjectIdentifiers.pkcs_9_at_friendlyName,
new DERBMPString("CA"));
PKCS12BagAttributeCarrier certBagAttr =
(PKCS12BagAttributeCarrier) eeCert;
certBagAttr.setBagAttribute(
PKCSObjectIdentifiers.pkcs_9_at_friendlyName,
new DERBMPString("EE Certificate"));
certBagAttr.setBagAttribute(
PKCSObjectIdentifiers.pkcs_9_at_localKeyId,
new SubjectKeyIdentifierStructure(eeCert.getPublicKey()));
Certificate[] chain = new Certificate[2];
chain[1] = caCert;
chain[0] = eeCert;
PKCS12BagAttributeCarrier privBagAttr =
(PKCS12BagAttributeCarrier) prvK;
privBagAttr.setBagAttribute(
PKCSObjectIdentifiers.pkcs_9_at_friendlyName,
new DERBMPString("EE Certificate Key"));
privBagAttr.setBagAttribute(
PKCSObjectIdentifiers.pkcs_9_at_localKeyId,
new SubjectKeyIdentifierStructure(eeCert.getPublicKey()));
// Finally, keystore is saved to file.
ks.setKeyEntry("P12", prvK, null, chain);
saveP12File(ks);
The thing is that everything is working OK when I run it on my Windows PC (BouncyCastle 1.49), but that PKCS#12 file created when I run it on Android cannot be used on SSL handshake or signing because Logcat says that it doesn't have any associated PrivateKey.
If I print the full content of the KeyStore on Java after loading the file, it seems that everything is right, but when I use on Android Browser or when I take it and install on Windows, its private key can't be used.
Same code on Android and PC, same version of BC, PKCS#12 doesn't seem to be malformed.
Can anybody help me?
Thanks in advance.
EDIT
I have built a servlet that generates an RSA Key Pair and sends back to my app in PEM format.
All seems work OK:
I can generate a valid (encrypting with public and decrypting test works good) RSA keypair either on Android device or through the external servlet.
I receive both CA and EE certificates from the CA.
I'm able to build a "valid" PKCS12 (I called it valid because it can be read by Android, Windows)
But:
I'm not able to open an SSL channel using the EE certificate as client-certificate for handshake. Either on Windows or Android.
I have uploaded to my Dropbox:
CA certificate
EE certificate issued by the CA
Private Key for the EE certificate
Public Key for the EE certificate
PKCS12 created on Android
Java Android Code
Tested against Tomcat with empty trustStore (doesnt' matter which CA issued client-certificate) unsuccessfully.
Does anybody see something that could explain it?
After some testing on Android 2.2, and after thinking I solved the issue, somehow I get again this error message, first time I did the story below all over and it worked for a day, but now again I'm facing this issue. Does anybody have a solution next to the one I used below? Or is there an explanation for the issue returning?
On Android 2.3 I never got it to work and I get the following error:
07-26 19:48:12.580: W/System.err(1201): javax.net.ssl.SSLPeerUnverifiedException: No peer certificate
ERROR MESSAGE 2.2:
07-23 00:12:18.726: W/System.err(22569): Caused by: java.security.cert.CertPathValidatorException: TrustAnchor for CertPath not found.
07-23 00:12:18.730: W/System.err(22569): at org.bouncycastle.jce.provider.PKIXCertPathValidatorSpi.engineValidate(PKIXCertPathValidatorSpi.java:149)
07-23 00:12:18.730: W/System.err(22569): at java.security.cert.CertPathValidator.validate(CertPathValidator.java:202)
07-23 00:12:18.730: W/System.err(22569): at org.apache.harmony.xnet.provider.jsse.TrustManagerImpl.checkServerTrusted(TrustManagerImpl.java:164)
EDIT: I thought I fixed the following issue like this:
When I post an HTTP-request through my windows web browser to a third party server it returns an XML, but when doing the same in an Android activity I get the following error:
W/System.err(9471): javax.net.ssl.SSLException: Not trusted server certificate
.
.
.
W/System.err(7207): Caused by: java.security.cert.CertPathValidatorException: TrustAnchor for CertPath not found.
I use the following request:
https://www.voipinfocenter.com/API/ Request.ashx?command=_&username= _&password=______&customer=__&customerpassword=___ &geocallcli=__&tariffrate=_
It doesn't seem smart to ignore this security issue, is there a way to work around this, especially since it's not my own server?
EDIT: I fount the android-trusting-ssl-certificates post and managed to download the certificate with SSLCertDownloader-Download
C:\ssl>SSLCertDownloader.exe www.server.com 443 c:\ssl\CAcert.cer
Downloaded bcprov-jdk16-145.jar and saved it in the c:\ssl folder
Made sure the keytool was in the c:\ssl folder
Imported certificate:
keytool -importcert -v -trustcacerts -file "CAcert.cer" -alias In
ermediateCA -keystore "mykeystore.bks" -provider org.bouncycastle.jce.provider.
ouncyCastleProvider -providerpath "bcprov-jdk16-145.jar" -storetype BKS -storep
ss Password
How do I know if this downloaded all the required certificates?
openssl client_s connect -showcerts gives me the following:
Loading 'screen' into random state - done
CONNECTED(000000D4)
depth=0 /C=LU/postalCode=2130/ST=NA/L=Luxembourg/streetAddress=Boulevard Charle
Marx 23/O=Dellmont Sarl/OU=Comodo InstantSSL/CN=77.72.173.130
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 /C=LU/postalCode=2130/ST=NA/L=Luxembourg/streetAddress=Boulevard Charle
Marx 23/O=Dellmont Sarl/OU=Comodo InstantSSL/CN=77.72.173.130
verify error:num=27:certificate not trusted
verify return:1
depth=0 /C=LU/postalCode=2130/ST=NA/L=Luxembourg/streetAddress=Boulevard Charle
Marx 23/O=Dellmont Sarl/OU=Comodo InstantSSL/CN=77.72.173.130
verify error:num=21:unable to verify the first certificate
verify return:1
---
Certificate chain
0 s:/C=LU/postalCode=2130/ST=NA/L=Luxembourg/streetAddress=Boulevard Charles M
rx 23/O=Dellmont Sarl/OU=Comodo InstantSSL/CN=77.72.173.130
i:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO High-A
surance Secure Server CA
-----BEGIN CERTIFICATE-----
MIIFczCCBFugAwIBAgIQHXnQEnG/Ft0D1oCzycDFbDANBgkqhkiG9w0BAQUFADCB
iTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxLzAtBgNV
BAMTJkNPTU9ETyBIaWdoLUFzc3VyYW5jZSBTZWN1cmUgU2VydmVyIENBMB4XDTEx
MDMzMTAwMDAwMFoXDTE0MDUwMjIzNTk1OVowga4xCzAJBgNVBAYTAkxVMQ0wCwYD
VQQREwQyMTMwMQswCQYDVQQIEwJOQTETMBEGA1UEBxMKTHV4ZW1ib3VyZzEiMCAG
A1UECRMZQm91bGV2YXJkIENoYXJsZXMgTWFyeCAyMzEWMBQGA1UEChMNRGVsbG1v
bnQgU2FybDEaMBgGA1UECxMRQ29tb2RvIEluc3RhbnRTU0wxFjAUBgNVBAMTDTc3
LjcyLjE3My4xMzAwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCo5mTI
oNnf4NsNKq3tXxxszbBOs22UubyUzwExBQ5i220y/qcXF0iA6h+lc+41WIJkT4mI
IltTMdAs9L8BLMIu/bFQRBlL5M1y7GRnGTEr2IqgE83gOWq5Bpz6Mvmhu67HDkHv
0ZBK/IwKn4f1lW+fntGD6++RfQixGAY0Ei+XDxn09mHV++qgFPA+4WpeOwVy3+I+
bk9hf8MR3aUfWDyPwdDF0BpNJ8yyzXwUzL/8RwEIN90wBRQ5O8KjociAXC/uqnXk
f8/woZkhfwqtQ0yWbHDWJlBSIg+xs3HtB6UhagFRWuLLZiJz9AurGRfb0pfOmwjI
XWkU6jVhLRDndzzpAgMBAAGjggGuMIIBqjAfBgNVHSMEGDAWgBQ/1bXQ1kR5UEoX
o5uMSty4sCJkazAdBgNVHQ4EFgQUmIxbnFxciu12ZJ84pSL/aVMLVAcwDgYDVR0P
AQH/BAQDAgWgMAwGA1UdEwEB/wQCMAAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG
AQUFBwMCMEYGA1UdIAQ/MD0wOwYMKwYBBAGyMQECAQMEMCswKQYIKwYBBQUHAgEW
HWh0dHBzOi8vc2VjdXJlLmNvbW9kby5jb20vQ1BTME8GA1UdHwRIMEYwRKBCoECG
Pmh0dHA6Ly9jcmwuY29tb2RvY2EuY29tL0NPTU9ET0hpZ2gtQXNzdXJhbmNlU2Vj
dXJlU2VydmVyQ0EuY3JsMIGABggrBgEFBQcBAQR0MHIwSgYIKwYBBQUHMAKGPmh0
dHA6Ly9jcnQuY29tb2RvY2EuY29tL0NPTU9ET0hpZ2gtQXNzdXJhbmNlU2VjdXJl
U2VydmVyQ0EuY3J0MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5jb21vZG9jYS5j
b20wDwYDVR0RBAgwBocETUitgjANBgkqhkiG9w0BAQUFAAOCAQEAH1jjfuwJxIac
s1uBibTiJyQKRVuyrb3MLo5A0D9mwQ+hew4GktAkJBc73AJ4gQgufADt06eJjzqc
SzpxkATx38W6WuRcis5odJRvkVrNv0yiJfAsQf6mB0laMXCrvt9+drGy8O/Xd4TC
4OU6A+s551SYKAhkAdlZuCCn4A0FgxL3nX/K/cXcvhHt+v2hDy/TraFlC3CQ73tp
SOxVNO9g8DZBu38c0W6SejQti40/xR2245t/U39GznSy9sgeMdQVU1JHpkwR2R9J
lXsRiev1PtTX1MZGLbyLhH1gSMn+n7gdBb7hZpaIZWicmp1NaRtC1oVQL49l7NdU
WcXYaeeuQA==
-----END CERTIFICATE-----
---
Server certificate
subject=/C=LU/postalCode=2130/ST=NA/L=Luxembourg/streetAddress=Boulevard Charle
Marx 23/O=Dellmont Sarl/OU=Comodo InstantSSL/CN=77.72.173.130
issuer=/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO High
Assurance Secure Server CA
---
No client certificate CA names sent
---
SSL handshake has read 1551 bytes and written 450 bytes
---
New, TLSv1/SSLv3, Cipher is AES128-SHA
Server public key is 2048 bit
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol : TLSv1
Cipher : AES128-SHA
Session-ID: F724000041ACE5FC6871CF549CAE1BC0F076578433238D6FF8B1DF3F374627D
Session-ID-ctx:
Master-Key: ADB009A0D064383C492EA9FBBDCFA81C5D945C88F168ECC225BCDF2798B063C
814CDA4E1E29AFB91C75290C7C41CB66
Key-Arg : None
Start Time: 1374894544
Timeout : 300 (sec)
Verify return code: 21 (unable to verify the first certificate)
---
Saved the mykeystore.bks in the res/raw folder of my app and created the following class:
public class MyHttpClient extends DefaultHttpClient {
final Context context;
public MyHttpClient(Context context) {
this.context = context;
}
#Override
protected ClientConnectionManager createClientConnectionManager() {
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
// Register for port 443 our SSLSocketFactory with our keystore
// to the ConnectionManager
registry.register(new Scheme("https", newSslSocketFactory(), 443));
return new SingleClientConnManager(getParams(), registry);
}
private SSLSocketFactory newSslSocketFactory() {
try {
// Get an instance of the Bouncy Castle KeyStore format
KeyStore trusted = KeyStore.getInstance("BKS");
// Get the raw resource, which contains the keystore with
// your trusted certificates (root and any intermediate certs)
InputStream in = context.getResources().openRawResource(R.raw.mykeystore);
try {
// Initialize the keystore with the provided trusted certificates
// Also provide the password of the keystore
trusted.load(in, "Password".toCharArray());
} finally {
in.close();
}
// Pass the keystore to the SSLSocketFactory. The factory is responsible
// for the verification of the server certificate.
SSLSocketFactory sf = new SSLSocketFactory(trusted);
// Hostname verification from certificate
// http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html#d4e506
sf.setHostnameVerifier(SSLSocketFactory.STRICT_HOSTNAME_VERIFIER);
return sf;
} catch (Exception e) {
throw new AssertionError(e);
}
}
}
In the activity:
// Instantiate the custom HttpClient
DefaultHttpClient client = new MyHttpClient(getApplicationContext());
HttpGet get = new HttpGet("https://www.mydomain.ch/rest/contacts/23");
// Execute the GET call and obtain the response
HttpResponse getResponse = client.execute(get);
HttpEntity responseEntity = getResponse.getEntity();
W/System.err(1201): javax.net.ssl.SSLPeerUnverifiedException: No peer certificate
What cipher suites are you using? Anonymous Diffie-Hellman (ADH) will cause the server to not send a certificate.
W/System.err(22569): Caused by: java.security.cert.CertPathValidatorException: TrustAnchor for CertPath not found.
It sounds like you did not trust a CA's root certificate required to validate the chain. Has it been loaded? Is it the correct root to trust?
Certificate chain
0 s:/C=LU/postalCode=2130/ST=NA/L=Luxembourg/streetAddress=Boulevard Charle
Marx 23/O=Dellmont Sarl/OU=Comodo InstantSSL/CN=77.72.173.130
i:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO
High-Asurance Secure Server CA
[Repeated three times]
This looks malformed in practice. There's no need to send the end entity certificate three or four times.
EDIT: that certificate was only sent once:
Usually there are three or four certificates used in a chain validation: (1) the CA root certificate, (2) one or two intermediate certificates, and (3) the end entity (or leaf, or server) certificate. In the SSL/TLS Server Hello, certificates from (2) and (3) should be sent.
As an example, there's a screenshot of all the certificates used in a Server Hello on OpenSSL's wiki. Its an example of how to write an OpenSSL client, and its based on a site that actually uses COMODO. Here's the capture: http://wiki.openssl.org/index.php/File:Bio-fetch-1.png, and here's the example: http://wiki.openssl.org/index.php/SSL/TLS_Client.
So I believe the chain is missing the Root:
AddTrust External CA Root
And two Intermediates:
COMODO Certification Authority
COMODO Extended Validation Secure Server CA
The certificates in question can be found at COMODO's site: Root and Intermediate Certificates. Or, you can copy and paste it from the chain offered in Fix 2 below.
Fix 1
To fix this, the server in question should send a concatenation of three certificates. The first is the Server's Certificate, the second is the "COMODO Extended Validation Secure Server CA" (intermediate) certificate, and third is "COMODO Certification Authority" (intermediate) certificate. You are also required to trust "AddTrust External CA Root" (root) certificate.
Here's what it looks like in practice using Google's site and the "Equifax Secure Certificate Authority". Notice the intermediate certificates are sent in addition to the server's end entity certificate:
$ echo "GET / HTTP\1.0" | openssl s_client -connect www.google.com:443 -showcerts
CONNECTED(00000003)
depth=2 C = US, O = GeoTrust Inc., CN = GeoTrust Global CA
verify error:num=20:unable to get local issuer certificate
verify return:0
---
Certificate chain
0 s:/C=US/ST=California/L=Mountain View/O=Google Inc/CN=www.google.com
i:/C=US/O=Google Inc/CN=Google Internet Authority G2
-----BEGIN CERTIFICATE-----
MIIEdjCCA16gAwIBAgIIRYUpUVjSfHQwDQYJKoZIhvcNAQEFBQAwSTELMAkGA1UE
BhMCVVMxEzARBgNVBAoTCkdvb2dsZSBJbmMxJTAjBgNVBAMTHEdvb2dsZSBJbnRl
cm5ldCBBdXRob3JpdHkgRzIwHhcNMTMxMTIwMTUxMDQ3WhcNMTQwMzIwMDAwMDAw
WjBoMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwN
TW91bnRhaW4gVmlldzETMBEGA1UECgwKR29vZ2xlIEluYzEXMBUGA1UEAwwOd3d3
Lmdvb2dsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDW8ZNM
PeVQTl+gbie7LVVCUrZ/Y3pM7EhWD9L9ZDeL39IeGeyKIfTIWLBpQRnM2xk3ITuR
2cIEH7WuhGfXi2bKwp27N2H9j5vPfsl04b50pus8XaJXUvwq+TgT1852QQy+sGQl
QE9UN0HIK8qleDV5VycpK6KnhSl7QH6283WX2xtiW1oxVETspRPv5gLIFXm9po9X
fTzQZm/Wnkvyl3SAXa4msAMABqrrczWM6ySC6UoWUEttYTAEy2OPsqEBhTBSseP5
W4w5X6kM7nU7u2R05NtxaVb/vO7RxIngU73+i7PF3ZDg6TxfQYGdAs0h03WoZCrI
JjsvdRU9QEhnZXVjAgMBAAGjggFBMIIBPTAdBgNVHSUEFjAUBggrBgEFBQcDAQYI
KwYBBQUHAwIwGQYDVR0RBBIwEIIOd3d3Lmdvb2dsZS5jb20waAYIKwYBBQUHAQEE
XDBaMCsGCCsGAQUFBzAChh9odHRwOi8vcGtpLmdvb2dsZS5jb20vR0lBRzIuY3J0
MCsGCCsGAQUFBzABhh9odHRwOi8vY2xpZW50czEuZ29vZ2xlLmNvbS9vY3NwMB0G
A1UdDgQWBBSloFBACjHuLBs7YbSkN82IHLBklzAMBgNVHRMBAf8EAjAAMB8GA1Ud
IwQYMBaAFErdBhYbvPZotXb1gba7Yhq6WoEvMBcGA1UdIAQQMA4wDAYKKwYBBAHW
eQIFATAwBgNVHR8EKTAnMCWgI6Ahhh9odHRwOi8vcGtpLmdvb2dsZS5jb20vR0lB
RzIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQCQSyYioqaFpkdSfBReEEFHffMcXzE9
VL5L/ysdFAqCk9bmMyHsYKZ8FET1mh2BqzwXY7VWulaeOg+SPv8D4kwKRtCGuDgp
/6Jo7+TzkU5GSQxnrrSuA4DW+nKwrkoS+bLEMV67MrSAMSQ3/TVwIHpxWmU16aGO
08ICQCzXyWevTaCxbC49n1iBloZPNYFk74QfUTllKYbzhKrUPqJvCjlkaHPAVzv0
OtGjXuOdSfB4nURA7INNYvx8ULMECg5Sj8Gan8kIOfeW3jt9vdxsZrbn0Cu/bcTm
OEK3nH1sBk2Hy5ZBcyludHyUzqTHsXSjnIjwZNPpihVmFrs5I1Ma7iEj
-----END CERTIFICATE-----
1 s:/C=US/O=Google Inc/CN=Google Internet Authority G2
i:/C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
-----BEGIN CERTIFICATE-----
MIIEBDCCAuygAwIBAgIDAjppMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT
MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i
YWwgQ0EwHhcNMTMwNDA1MTUxNTU1WhcNMTUwNDA0MTUxNTU1WjBJMQswCQYDVQQG
EwJVUzETMBEGA1UEChMKR29vZ2xlIEluYzElMCMGA1UEAxMcR29vZ2xlIEludGVy
bmV0IEF1dGhvcml0eSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
AJwqBHdc2FCROgajguDYUEi8iT/xGXAaiEZ+4I/F8YnOIe5a/mENtzJEiaB0C1NP
VaTOgmKV7utZX8bhBYASxF6UP7xbSDj0U/ck5vuR6RXEz/RTDfRK/J9U3n2+oGtv
h8DQUB8oMANA2ghzUWx//zo8pzcGjr1LEQTrfSTe5vn8MXH7lNVg8y5Kr0LSy+rE
ahqyzFPdFUuLH8gZYR/Nnag+YyuENWllhMgZxUYi+FOVvuOAShDGKuy6lyARxzmZ
EASg8GF6lSWMTlJ14rbtCMoU/M4iarNOz0YDl5cDfsCx3nuvRTPPuj5xt970JSXC
DTWJnZ37DhF5iR43xa+OcmkCAwEAAaOB+zCB+DAfBgNVHSMEGDAWgBTAephojYn7
qwVkDBF9qn1luMrMTjAdBgNVHQ4EFgQUSt0GFhu89mi1dvWBtrtiGrpagS8wEgYD
VR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAQYwOgYDVR0fBDMwMTAvoC2g
K4YpaHR0cDovL2NybC5nZW90cnVzdC5jb20vY3Jscy9ndGdsb2JhbC5jcmwwPQYI
KwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwOi8vZ3RnbG9iYWwtb2NzcC5n
ZW90cnVzdC5jb20wFwYDVR0gBBAwDjAMBgorBgEEAdZ5AgUBMA0GCSqGSIb3DQEB
BQUAA4IBAQA21waAESetKhSbOHezI6B1WLuxfoNCunLaHtiONgaX4PCVOzf9G0JY
/iLIa704XtE7JW4S615ndkZAkNoUyHgN7ZVm2o6Gb4ChulYylYbc3GrKBIxbf/a/
zG+FA1jDaFETzf3I93k9mTXwVqO94FntT0QJo544evZG0R0SnU++0ED8Vf4GXjza
HFa9llF7b1cq26KqltyMdMKVvvBulRP/F/A8rLIQjcxz++iPAsbw+zOzlTvjwsto
WHPbqCRiOwY1nQ2pM714A5AuTHhdUDqB1O6gyHA43LL5Z/qHQF1hwFGPa4NrzQU6
yuGnBXj8ytqU0CwIPX4WecigUCAkVDNx
-----END CERTIFICATE-----
2 s:/C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
i:/C=US/O=Equifax/OU=Equifax Secure Certificate Authority
-----BEGIN CERTIFICATE-----
MIIDfTCCAuagAwIBAgIDErvmMA0GCSqGSIb3DQEBBQUAME4xCzAJBgNVBAYTAlVT
MRAwDgYDVQQKEwdFcXVpZmF4MS0wKwYDVQQLEyRFcXVpZmF4IFNlY3VyZSBDZXJ0
aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDIwNTIxMDQwMDAwWhcNMTgwODIxMDQwMDAw
WjBCMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UE
AxMSR2VvVHJ1c3QgR2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
CgKCAQEA2swYYzD99BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9m
OSm9BXiLnTjoBbdqfnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIu
T8rxh0PBFpVXLVDviS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6c
JmTM386DGXHKTubU1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmR
Cw7+OC7RHQWa9k0+bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5asz
PeE4uwc2hGKceeoWMPRfwCvocWvk+QIDAQABo4HwMIHtMB8GA1UdIwQYMBaAFEjm
aPkr0rKV10fYIyAQTzOYkJ/UMB0GA1UdDgQWBBTAephojYn7qwVkDBF9qn1luMrM
TjAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjA6BgNVHR8EMzAxMC+g
LaArhilodHRwOi8vY3JsLmdlb3RydXN0LmNvbS9jcmxzL3NlY3VyZWNhLmNybDBO
BgNVHSAERzBFMEMGBFUdIAAwOzA5BggrBgEFBQcCARYtaHR0cHM6Ly93d3cuZ2Vv
dHJ1c3QuY29tL3Jlc291cmNlcy9yZXBvc2l0b3J5MA0GCSqGSIb3DQEBBQUAA4GB
AHbhEm5OSxYShjAGsoEIz/AIx8dxfmbuwu3UOx//8PDITtZDOLC5MH0Y0FWDomrL
NhGc6Ehmo21/uBPUR/6LWlxz/K7ZGzIZOKuXNBSqltLroxwUCEm2u+WR74M26x1W
b8ravHNjkOR/ez4iyz0H7V84dJzjA1BOoa+Y7mHyhD8S
-----END CERTIFICATE-----
---
Server certificate
subject=/C=US/ST=California/L=Mountain View/O=Google Inc/CN=www.google.com
issuer=/C=US/O=Google Inc/CN=Google Internet Authority G2
---
No client certificate CA names sent
---
SSL handshake has read 3728 bytes and written 448 bytes
...
The server must send the needed certificates for chain validation to avoid the "which directory" problem. Its well known in PKI, and it essentially means a client does not know where to go to find a missing certificate. For example, how does a client know where to fetch "COMODO High-Assurance Secure Server CA" from?
Fix 2:
In this fix, you load the root and intermediate certificates because the server or site is not setup properly (usually you only load the root you trust). To see how its done in practice with OpenSSL, see the OpenSSL client example at http://wiki.openssl.org/index.php/SSL/TLS_Client. In the file openssl-bio-fetch.c (line 115), you will see the following call to set the trusted root (and intermediates) used during chain validation:
res = SSL_CTX_load_verify_locations(ctx, "random-org-chain.pem", NULL);
ASSERT(res == 1)
...
The file random-org-chain.pem contains the following PEM encoded concatenation. The concatenation consists of the Root certificate and two Intermediate certificates required to validate www.random.org's server certificate.
$ cat random-org-chain.pem
#
# AddTrust External CA Root
#
-----BEGIN CERTIFICATE-----
MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEU
MBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFs
IFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290
MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFowbzELMAkGA1UEBhMCU0Ux
FDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRUcnVzdCBFeHRlcm5h
bCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0EgUm9v
dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvt
H7xsD821+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9
uMq/NzgtHj6RQa1wVsfwTz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzX
mk6vBbOmcZSccbNQYArHE504B4YCqOmoaSYYkKtMsE8jqzpPhNjfzp/haW+710LX
a0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy2xSoRcRdKn23tNbE7qzN
E0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv77+ldU9U0
WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYD
VR0PBAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0
Jvf6xCZU7wO94CTLVBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRU
cnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsx
IjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3SCAQEwDQYJKoZIhvcN
AQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZlj7DYd7usQWxH
YINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5
6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvC
Nr4TDea9Y355e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEX
c4g/VhsxOBi0cQ+azcgOno4uG+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5a
mnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ=
-----END CERTIFICATE-----
#
# COMODO Certification Authority
#
-----BEGIN CERTIFICATE-----
MIIE8TCCA9mgAwIBAgIQbyXcFa/fXqMIVgw7ek/H+DANBgkqhkiG9w0BAQUFADBv
MQswCQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFk
ZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBF
eHRlcm5hbCBDQSBSb290MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFow
gYExCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO
BgNVBAcTB1NhbGZvcmQxGjAYBgNVBAoTEUNPTU9ETyBDQSBMaW1pdGVkMScwJQYD
VQQDEx5DT01PRE8gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3
DQEBAQUAA4IBDwAwggEKAoIBAQDQQIuLcuORG/dRwRtUBJjTqb/B5opdO4f7u4jO
DeMvPwaW8KIpUJmu2zuhV7B0UXHN7UKRTUH+qcjYaoZ3RLtZZpdQXrTULHBEz9o3
lUJpPDDEcbNS8CFNodi6OXwcnqMknfKDFpiqFnxDmxVbt640kf7UYiYYRpo/68H5
8ZBX66x6DYvbcjBqZtXgRqNw3GjZ/wRIiXfeten7Z21B6bw5vTLZYgLxsag9bjec
4i/i06Imi8a4VUOI4SM+pdIkOWpHqwDUobOpJf4NP6cdutNRwQuk2qw471VQJAVl
RpM0Ty2NrcbUIRnSjsoFYXEHc0flihkSvQRNzk6cpUisuyb3AgMBAAGjggF0MIIB
cDAfBgNVHSMEGDAWgBStvZh6NLQm9/rEJlTvA73gJMtUGjAdBgNVHQ4EFgQUC1jl
i8ZMFTekQKkwqSG+RzZaVv8wDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMB
Af8wEQYDVR0gBAowCDAGBgRVHSAAMEQGA1UdHwQ9MDswOaA3oDWGM2h0dHA6Ly9j
cmwudXNlcnRydXN0LmNvbS9BZGRUcnVzdEV4dGVybmFsQ0FSb290LmNybDCBswYI
KwYBBQUHAQEEgaYwgaMwPwYIKwYBBQUHMAKGM2h0dHA6Ly9jcnQudXNlcnRydXN0
LmNvbS9BZGRUcnVzdEV4dGVybmFsQ0FSb290LnA3YzA5BggrBgEFBQcwAoYtaHR0
cDovL2NydC51c2VydHJ1c3QuY29tL0FkZFRydXN0VVROU0dDQ0EuY3J0MCUGCCsG
AQUFBzABhhlodHRwOi8vb2NzcC51c2VydHJ1c3QuY29tMA0GCSqGSIb3DQEBBQUA
A4IBAQAHYJOZqs7Q00fQNzPeP2S35S6jJQzVMx0Njav2fkZ7WQaS44LE5/X289kF
z0k0LTdf9CXH8PtrI3fx8UDXTLtJRTHdAChntylMdagfeTHJNjcPyjVPjPF+3vxG
q79om3AjMC63xVx7ivsYE3lLkkKM3CyrbCK3KFOzGkrOG/soDrc6pNoN90AyT99v
uwFQ/IfTdtn8+7aEA8rJNhj33Wzbu7qBHKat/ij5z7micV0ZBepKRtxzQe+JlEKx
Q4hvNRevHmCDrHqMEHufyfaDbZ76iO4+3e6esL/garnQnweyCROa9aTlyFt5p0c1
M2jlVZ6qW8swC53HD79oRIGXi1FK
-----END CERTIFICATE-----
#
# COMODO Extended Validation Secure Server CA
#
-----BEGIN CERTIFICATE-----
MIIFBjCCA+6gAwIBAgIQEaO00OyNt3+doM1dLVEvQjANBgkqhkiG9w0BAQUFADCB
gTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNV
BAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0xMDA1MjQwMDAw
MDBaFw0yMDA1MzAxMDQ4MzhaMIGOMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3Jl
YXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01P
RE8gQ0EgTGltaXRlZDE0MDIGA1UEAxMrQ09NT0RPIEV4dGVuZGVkIFZhbGlkYXRp
b24gU2VjdXJlIFNlcnZlciBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
ggEBAMxKljPNJY1n7iiWN4dG8PYEooR/U6qW5h+xAhxu7X0h1Nc8HqLYaS+ot/Wi
7WRYZOFEZTZJQSABjTsT4gjzDPJXOZM3txyTRIOOvy3xoQV12m7ue28b6naDKHRK
HCvT9cQDcpOvhs4JjDx11MkKL3Lzrb0OMDyEoXMfAyUUpY/D1vS15N2GevUZumjy
hVSiMBHK0ZLLO3QGEqA3q2rYVBHfbJoWlLm0p2XGdC0x801S6VVRn8s+oo12mHDS
b6ZlRS8bhbtbbfnywARmE4R6nc4n2PREnr+svpnba0/bWCGwiSe0jzLWS15ykV7f
BZ3ZSS/0tm9QH3XLgJ3m0+TR8tMCAwEAAaOCAWkwggFlMB8GA1UdIwQYMBaAFAtY
5YvGTBU3pECpMKkhvkc2Wlb/MB0GA1UdDgQWBBSIRFH/UCppXi2I9CG62Qzyzsvq
fDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBADA+BgNVHSAENzA1
MDMGBFUdIAAwKzApBggrBgEFBQcCARYdaHR0cHM6Ly9zZWN1cmUuY29tb2RvLmNv
bS9DUFMwSQYDVR0fBEIwQDA+oDygOoY4aHR0cDovL2NybC5jb21vZG9jYS5jb20v
Q09NT0RPQ2VydGlmaWNhdGlvbkF1dGhvcml0eS5jcmwwdAYIKwYBBQUHAQEEaDBm
MD4GCCsGAQUFBzAChjJodHRwOi8vY3J0LmNvbW9kb2NhLmNvbS9DT01PRE9BZGRU
cnVzdFNlcnZlckNBLmNydDAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuY29tb2Rv
Y2EuY29tMA0GCSqGSIb3DQEBBQUAA4IBAQCaQ7+vpHJezX1vf/T8PYy7cOYe3QT9
P9ydn7+JdpvyhjH8f7PtKpFTLOKqsOPILHH3FYojHPFpLoH7sbxiC6saVBzZIl40
TKX2Iw9dej3bQ81pfhc3Us1TocIR1FN4J2TViUFNFlW7kMvw2OTd3dMJZEgo/zIj
hC+Me1UvzymINzR4DzOq/7fylqSbRIC1vmxWVKukgZ4lGChUOn8sY89ZIIwYazgs
tN3t40DeDDYlV5rA0WCeXgNol64aO+pF11GZSe5EWVYLXrGPaOqKnsrSyaADfnAl
9DLJTlCDh6I0SD1PNXf82Ijq9n0ezkO21cJqfjhmY03n7jLvDyToKmf6
-----END CERTIFICATE-----
Sorry about the C/C++ code. I don't have a Java example handy, but it is OpenSSL code and the same concepts apply.
0 s:/C=LU/postalCode=2130/ST=NA/L=Luxembourg/streetAddress=Boulevard Charle
Marx 23/O=Dellmont Sarl/OU=Comodo InstantSSL/CN=77.72.173.130
When an IP is used for the Common Name (CN), I believe the IP must also be listed in the Subject Alternate Name (SAN). It was not apparent if the end entity certificate was well formed, and Bouncy Castle might be aggressive in its validation. The certificate requirements are published by the CA/Browser forum and can be found at:
Baseline Certificate Requirements
Extended Validation Certificate Requirements
Some of the methods you are using are marked as deprecated. For example, X509HostnameVerifier'sSTRICT_HOSTNAME_VERIFIER is deprecated.
Finally, you can get free certificates trusted by most desktop and mobile browsers from Eddy Nigg at Startcom. Startcom will charge you if revocation is required because that's where the cost lies. CAs will charge you up front for the revocation and pocket the unused proceeds ;)
I need to build a keystore with all the needed SSL certificates to make my Android app connect to a webserver via https.
This is my certificate chain (obtained with openssl s_client -connect www.myhost.com:443):
0 s:/C=US/ST=State/L=Location/O=Organization/OU=Webserver Team/CN=www.myhost.com
i:/C=US/O=Thawte, Inc./CN=Thawte SGC CA - G2
1 s:/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=(c) 2006 VeriSign, Inc. - For authorized use only/CN=VeriSign Class 3 Public Primary Certification Authority - G5
i:/C=US/O=VeriSign, Inc./OU=Class 3 Public Primary Certification Authority
2 s:/C=US/O=Thawte, Inc./CN=Thawte SGC CA - G2
i:/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=(c) 2006 VeriSign, Inc. - For authorized use only/CN=VeriSign Class 3 Public Primary Certification Authority - G5
3 s:/C=US/O=thawte, Inc./OU=Terms of use at https://www.thawte.com/cps (c)06/CN=thawte Extended Validation SSL CA
i:/C=US/O=thawte, Inc./OU=Certification Services Division/OU=(c) 2006 thawte, Inc. - For authorized use only/CN=thawte Primary Root CA
4 s:/C=US/O=thawte, Inc./OU=Certification Services Division/OU=(c) 2006 thawte, Inc. - For authorized use only/CN=thawte Primary Root CA
i:/C=ZA/ST=Western Cape/L=Cape Town/O=Thawte Consulting cc/OU=Certification Services Division/CN=Thawte Premium Server CA/emailAddress=premium-server#thawte.com
My problem is that I'm not 100% sure about how to create the keystore to import in my android application. I've only been able to download VeriSign Class 3 Public Primary Certification Authority - G5 and Thawte Primary Root CA from the Thawte and Verisign website. I can't find the other two that If I'm not wrong should be Thawte SGC CA - G2 and thawte Extended Validation SSL CA.
If I had all of them, I would proceed creating a keystore with the procedure explained in this answer to a question similar to this one.
Am I misunderstanding something? Do I really need all the 4 certificates or not? I'm also not sure of the order (and the aliases) I should use when adding these certificates to the keystore. Does it matter?
If your server cert is signed by VeriSign, you don't need to install it, it is most probably already trusted by Android. Are you getting an error? On what version?
Generally, you only need to have the root (CA) certificate installed in the device's trust store. All intermediate certificate should be sent by the server if properly configured.
In the end, my problem was that the server was not sending the certificates in the right order (you can see it from the openssl output I posted in my question). The solution was to subclass X509TrustManager and, on method checkServerTrusted, just reorder the certificate chain before passing it to the super implementation. The reordering code is the following:
int currIndex;
for (currIndex = 0; currIndex < certificates.length; ++currIndex) {
boolean foundNext = false;
for (int nextIndex = currIndex + 1; nextIndex < certificates.length; ++nextIndex) {
if (certificates[currIndex].getIssuerDN().equals(certificates[nextIndex].getSubjectDN())) {
foundNext = true;
// Exchange certificates so that 0 through currIndex + 1 are in proper order
if (nextIndex != currIndex + 1) {
X509Certificate tempCertificate = certificates[nextIndex];
certificates[nextIndex] = certificates[currIndex + 1];
certificates[currIndex + 1] = tempCertificate;
}
break;
}
}
if (!foundNext) break;
}