티스토리 툴바

  • 31,058Total hit
  • 15Today hit
  • 14Yesterday hit
블로그 이미지
by soil21

구르는돌


등산 모임을 만들라고 배후 조정하셨던 회장님께서, 관악산에서 였을까? 가을에 지리산 들러 남원에 가자고 제안 아닌 제안을 하셨던 기억이 난다. 이번 남원에서도 해외 등반 이야기도 꺼내 놓으시더니 슬그머니 근우에게 묻어 가시더라. 계속된 회장님의 불참으로 지리산행이 잊혀질 무렵 남한산성에 야유회 갔다가 거기서 다시 지리산 이야기가 나오는데 다들 기회가 없어서 그렇지 가보고 싶었던 모양이다. 여유롭게 다녀 오는 것도 좋겠지만 다들 시간 맞추기도 힘들고 해서 무박 산행을 하기로 의기투합 하여 정한 것이 백무동-천왕봉-중산리 코스였다. 물론 코스를 알아본 건 본인이었지만 별다른 이견이 없어 확정 지으려는데 우리의 회장님 께서 무슨 생각이신지 백무동으로 다시 내려오는 코스를 잡으시잔다. 그 이유는 당일날 았았지만...


페북에 이벤을 띄우고 기다리고 있자니 어라~ 원봉이하고 근우네는 가족 동행이네? 이름만 알고 있던 95? 후배 둘도 간다고 하네? 제법 판이 커지는 상황이 걱정이 앞서있는데 회장님께서 덜컥 동기 세분 까지 명단에 올리신다. 안되겠다 싶어 같이 산에 다니는 친구에게 무전기를 구해 볼려고 했으나 일정이 겹쳐서 어렵게 되고 문제가 있겠나 싶어 출발 당일까지 걱정 붙들어 메어 놓고 당일 동서울 터미날로 향했다. 
 

전날 집을 나온 탓에 가는 도중 화장실에서 등산복으로 갈아 입고 터미날에 도착해 보니 좀 이르다. 우리 회장님께 전화가 온다. 술한잔 하고 가고 있는 중이시라는 데 취기가 상당하게 느껴진다. 내일 산에는 절반도 못 오르고 전부 하산하는 게 아닐지 걱정이 앞선다. 이래저래 밤 12시 동서울 터미날에 도착한 회원은 이병호,정혁기,정동실(부부),나,근우와 아들 지훈,원봉이 하고 미경이 그리고 윤희, 후배 평송이하고 재현이 모두 12명이다. 함양에서 합류하기로 한  석원이 까지 하면 13명이라는 올라야 하는데 선두와 후미가 차이가 많이 날 것 같지만 걱정은 일단 제쳐 두기로 한다,  


드디어 출발시간이 되어 지리산행 버스에 오르려는데 5분 간격으로 4대의 차가 대기하고 있다, 예약 승객이 많아서 3대의 버스를 증편한 것 같다, 대략 150여명이 자정에 지리산으로 행하는 것을 보면 지리산은 모두에게 제일봉이란 인식이 있나 보다. 백무동에 버스가 도착할 무렵 차창밖으로 누군가 주차장에서 해드렌턴을 비추며 열심히 석유 버너로 물을 끓이고 있다. 원봉이가 제일 먼저 광경을 보고 석원이 임을 직감했다 한다. 남원에서 늦을 까봐 자지도 않고 미리 와 있었다 하니 그 마음이 더욱 느껴진다.
 

백무동 주차장에서 산행 준비중

주차장에서 정성껏 준비해준 사과와 오이를 나눠 가방에 넣고 따뜻한 커피와 컵라면으로 요기를 한 뒤 두 팀으로 나눠 등산을 시작한다. 선두는 가장 복장과 장비가 좋은 평송이 하고 재현이가 앞서 출발하고 술자신 양반들 하고 근우네 식구 동실형 부부 혁기형과 후미로 출발한 시간이 새벽 4시 반경인가 보다. 오르는 길이 시작 부터 너덜길이어서 관악산 10분 오른게 전부라는 동실형네와 근우 아들 지훈이와 속도를 맞추다 보니 좀처럼 속도가 나질 않는다. 게다가 렌턴을 준비해온 것이 부족해서 중간중간 끼어 불을 비추고 올라가니 더딜 수 밖에... 그렇게 한참을 낑낑거리며 올라가던 중에 누군가 우리 대열 후미에 따라 붙는다. 이렇게 느린 대열에 합류한 그는 우리가 쉬면 같이 쉬고 출발하면 마치 일행 인 것 같이 간다. 대략 6시 반경이 되었을까 희뿌연 새벽이 어둠을 어느 정도 밀어 낸다. 병호형이 먼저 치고 올라 가신다. 조금 지나 혁기형이 후미는 걱정하지 마시라 하여 형의 등산 이력을 알고 있었던 터라 선두를 따라잡기 위해 나도 출발. 참샘까지 20여분 올라가니 병호형이 가고 계신다. 선두가 궁금한 터라 병호형을 뒤로하고 오르다 보니 얼마가지 않아 배낭을 가볍게 하려는 듯 선두 일행이 쉬고 있다. 가만히 보니 한명이 안보인다. 앞서 간 것인지 어쩐지 물어 보니 후미와 같이 올라 오는게 아니냐고 반문하는데 그제서야 후미 일행에 살짝 합류한 그가 재현이 인것 같다는 생각이 버뜩 든다. 오늘 처음 본 후배인데다 어두워서 사람을 분간하기 어려워 그가 재현이 인 것을 모르고 올라 온 것이다. 아니 침낭까지 배낭에 매고 온 친구가 왜 뒤로 처졌는지... 평송이 말로는 몇해 전 지리산을 왔었는데 그때도 힘들어 했었다고 한다. 아무리 그래도 그렇지 아무말도 없이 조용히 귀신처럼 우리 일행 후미에 달라 붙어 올라온게 그저 황당할 따름이다.


조금 뒤 병호형과 합류하여 출발. 장터목에서 뵙기로 하고 조금 속도를 내 본다. 장터목에 도착한 시간이 대략 8시 30분경. 지리산 산행 중 이렇게 좋은 날을 만나기는 처음이다. 천왕봉에서 새벽 일출을 보고 내려온 산객들이 식사 준비가 한참인데 화려한 일출을 자랑하느라 여기저기 난리다. 3-4시간동안 탁 트인 곳을 보지 못하고 올라왔는데 장터목에 이르자 사위가 훤하다. 구름한점 안보이는 데 새벽 안개인지 낮은 봉우리들이 구름에 걸쳐 있는 듯 마치 한폭의 동양화를 보는 느낌이다.
 


장터목에서 바라본 주변


하산 계획이 12시 정각에 현재 위치에서 무조건 내려간다고 약속을 하고 올라 온 길이다. 산의 어둠이 빨리 내리는 데다 백무동 쪽은 동쪽이어서 더 빨리 어두워 질 것 같아 오후 4-5시 전에는 하산하여야 안전 할 것 같아서 그리 정한 것다. 아무래도 후미는 장터목에서 하산해야 할 것 같아 선두로 올라온 병호형,석원이,평송이 하고 천왕봉으로 방향을 잡았다. 너무 쉬다 다시 올라 가는 길이라 또 힘이 든다. 올라가며 고산 지대에 펼처진 주목 군락과 짙푸른 하늘을 보며 다시 힘을 내고 보니 천왕봉이 지척이다. 마지막 암벽지대를 오르고 보니 사방에 더 높은 곳이 없다. 멀리 노고단이 보이고 마치 섬처럼 덕유도 보이는 것 같고 시계에 걸리는 것이 아무 것도 없다.



천왕봉에서 바라본 풍경 그리고 셀카


천왕봉에서 재현이와 근우,지훈이가 올라 왔다는 소식이 들린다. 올라 오신다는 병호형은 아직 감감이고 불편한 볼일 때문에 먼저 장터목으로 향하는데 병호형이 올라 오신다. 오시다 졸려 한숨하고 오신단다. 후미 소식 전하고 장터목에 도착해 보니 근우가 지고 올라온 라면을 끓여 소주 한잔 했다 한다. 한잔이 아니었겠지?
 



제석봉 근처 살아 천년 죽어 천년 주목 군락지


장터목에서 천왕봉까지 왕복 1시간 내외 걸리는데 11시경에 재현이하고 근우가 아들 지훈이하고 올라간다 한다. 12시 되면 천왕봉 못 가더라도 바로 하산하라 이르고 장터 같은 장터목에서 12시 조금 넘어 하산을 시작했다. 천왕봉 올라간 일행도 당연히 하산을 시작할 것이고 병호형이 같이 하산 하신다 하니 먼저 내려가 먼저 하산한 일행과 합류하려고 서둘러 백무동으로 내려왔다. 오후 두시 조금 넘어 도착해 동실형에게 전화하니 이미 남원에 가 계신다고 한다. 하릴없이 배회 하실까봐 빨리 내려 왔는데 이제는 내가 할일이 없다. 하산후 만나기로 한 집에서 묵에 막걸리 시켜 놓고 한잔하며 기다리고 있는데 혁기형,병호형,평송,석원이가 차례로 내려오고 원봉이가 식구들과 내려온다. 마지막으로 재원이가 내려오는데 근우하고 지훈이가 뒤에 많이 쳐져 있는 상태라고 한다. 날은 어두워 지기 시작하고 걱정이 되서 다시 산을 되짚어 올라 가다 하산하는 객들에게 물어 보니 힘들어 한다는 소식을 전한다, 30여분을 다시 올라 가니 임무를 마치고 내려가는 구조대에게 물으니 바로 뒤에 있다 한다. 구조대에게 같이 하산하자 부탁하여 근우,지훈이 백무동으로 무사히 귀한 비로서 맘을 놓는다.
 



*) 백무동에서 부터 함께해준 함양사는 창호,명숙이 부부 반가웠습니다. 지방의 명산을 그 지역 회원 들과 같이 하는 자리가 가끔 있었으면 하는 바람입니다.

저작자 표시 비영리 동일 조건 변경 허락
TRACKBACK 0 AND COMMENT 0
http://blog.antoine.li/index.php/2010/10/android-trusting-ssl-certificates/

Friday, October 22nd, 2010 | Author: Antoine Hauck

Two weeks ago I got the task to establish TLS secured connections via certificates to a service endpoint.
I thought it’s not a big deal, because the endpoint already uses an EV certificate from a trusted CA (SwissSign) in Switzerland. Therefore I shouldn’t have to worry that the certificate would be considered as untrusted so I don’t have to import it to the trusted certs in the  Java  key store etc.
FAIL! I’ve got a security exception, cert is not trusted. Same problem when I visit the website with the browser. Ok, that’s bad, SwissSign is not such a big player like thawte, so, it needs some time till it will be added to the android trusted CA list. But, when I visit thawte.com, their cert is also not trusted by android. WTF?
Windows Phone and iPhone trust my SwissSign CA and don’t complain.

So, let’s ask google, stackoverflow and the blogosphere. Found a lot of solutions how to disable certificate checking entirely.
Yeah, great, this will solve my problem, my connection will be “secure” and everyone will be able to intercept my connection and inject his own certificate. But I finally found the solution with help from other sites and some testing and debugging.

The Solution

The following main steps are required to achieve a secured connection from trusted Certification Authorities.

  1. Grab all required certificates (root and any intermediate CA’s)
  2. Create a keystore with keytool and the BouncyCastle provider and import the certs
  3. Load the keystore in your android app and use it for the secured connections
    • Don’t use the standard java.net.ssl.HttpsURLConnection for the secure connection. Use the Apache HttpClient (Version 4 atm) library, which is already built-in in android. It’s built on top of the java connection libraries and is, in my opinion, faster, better modularized and easier to understand.

Step 1: Grab the certs

You have to obtain all certificates that build a chain from the endpoint certificate the whole way up to the Root CA. This means, any (if present) Intermediate CA certs and also the Root CA cert. You don’t need to obtain the endpoint certificate.
You can obtain those certs from the chain (if provided) included in the endpoint certificate or from the official site of the issuer (in my case SwissSign).

Ensure that you save the obtained certificates in the Base64 encoded X.509 format. The content should look similar to this:

1
2
3
-----BEGIN CERTIFICATE-----
MIIGqTC.....
-----END CERTIFICATE-----

Step 2: Create the keystore

Download the BouncyCastle Provider and store it to a known location.
Also ensure that you can invoke the keytool command (usually located under the bin folder of your JRE installation).

Now import the obtained certs (don’t import the endpoint cert) into a BouncyCastle formatted keystore.
I didn’t tested it, but I think the order of importing the certificates is important. This means, import the lowermost Intermediate CA certificate first and then all the way up to the Root CA certificate.

With the following command a new keystore (if not already present) with the password mysecret will be created and the Intermediate CA certificate will be imported. I also defined the BouncyCastle provider, where it can be found on my file system and the keystore format. Execute this command for each certificate in the chain.

1
keytool -importcert -v -trustcacerts -file "path_to_cert/interm_ca.cer" -alias IntermediateCA -keystore "res/raw/myKeystore.bks" -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath "path_to_bouncycastle/bcprov-jdk16-145.jar" -storetype BKS -storepass mysecret

Verify if the certificates were imported correctly into the keystore:

1
keytool -list -keystore "res/raw/myKeystore.bks" -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath "path_to_bouncycastle/bcprov-jdk16-145.jar" -storetype BKS -storepass mysecret

Should output the whole chain:

1
2
RootCA, 22.10.2010, trustedCertEntry, Thumbprint (MD5): 24:77:D9:A8:91:D1:3B:FA:88:2D:C2:FF:F8:CD:33:93
IntermediateCA, 22.10.2010, trustedCertEntry, Thumbprint (MD5): 98:0F:C3:F8:39:F7:D8:05:07:02:0D:E3:14:5B:29:43

Now you can copy the keystore as a raw resource in your android app under res/raw/

Step 3: Use the keystore in your app

First of all we have to create a custom Apache HttpClient that uses our keystore for HTTPS connections:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
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, "mysecret".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
            sf.setHostnameVerifier(SSLSocketFactory.STRICT_HOSTNAME_VERIFIER);
            return sf;
        } catch (Exception e) {
            throw new AssertionError(e);
        }
    }
}

We have created our custom HttpClient, now we can just use it for secure connections. For example when we make a GET call to a REST resource.

1
2
3
4
5
6
// 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();

That’s it. Took me long to figure it out, hope this helps and saves you that time.

I really hope that the android platform will implement a better mechanism in future releases for defining which Certification Authorities should be trusted or not or just expand their own trusted CA list. If they don’t, I can’t believe they will get good acceptance from the business sector. Ok, you can control which certificates you want to trust in your app, but you still can’t add thawte as a trusted CA in the android keystore and your browser will always complain about an untrusted CA. The only way I know to eliminate this problem is to root your phone (very user friendly) and add your CA manually to the android keystore.

Feel free to comment.

Tags: 
Category: Codingandroid
You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, ortrackback from your own site.

29 Responses

  1. OMG.
    Why is android team doing many things so complicated?!

  2. 2
    Saran 

    Still getting:
    Caused by: java.security.cert.CertificateException: java.security.cert.CertPathValidatorException: IssuerName(CN=thawte Primary Root CA, OU=”(c) 2006 thawte, Inc. ? For authorized use only”, OU=Certification Services Division, O=”thawte, Inc.”, C=US) does not match SubjectName(CN=Thawte SSL CA, O=”Thawte, Inc.”, C=US) of signing certificate

    :(

    Could you try importing and using certificates from this site:
    https://eu.battle.net/login/en/login.xml?app=armory&locale=en_US&ref=http%3A%2F%2Feu.wowarmory.com%2Fvault%2Fcalendar-feed.xml
    to see if you can get it to work?

  3. Hi Saran

    Hmm… I could reproduce your mentioned exception. Everything looks good with the certificates. I intercepted the HTTPS with Wireshark and saw something very interesting.

    The certificates are sent in the following order from the battle.net server:
    > *.battle.net
    >> thawte Primary Root CA
    >>> Thawte SSL CA (this is the intermedaite cert)

    I really can’t believe that the Cert. Path validation is so bad implemented, that the order how the server sends the certificates is important.
    But I’ve had a customer, whose server was sending the endpoint server certificate twice. And I got similar exceptions in android (IE, Chrome and Firefox weren’t complaining, they also didn’t show the duplicate in the chain). We removed the duplicate from the chain and everything worked fine.
    It’s really possible that the Cert. Path validation really depends on the correct order, which in may opinion sucks.

    I also tried in your case to import the thawte Root cert first and then the Intermediate cert into the keystore, but still got the same exception.

    Maybe you can write to battle.net to change their order, or write your own CertPathValidator or just use the crappier HttpsUrlConnection from the standard java libraries. There you can turn off certificate validation off at all (but you loose a lot of security).

    Hope this helps you a bit.

    Greetz

  4. 4
    Saran 

    Thanks for verifying, Antoine.

    I tried reverse-importing the certs into the store, but even though I imported them in this order:
    > *.battle.net
    >> thawte Primary Root CA
    >>> Thawte SSL CA (this is the intermedaite cert)

    I got this list:
    Keystore type: BKS
    Keystore provider: BC

    Your keystore contains 3 entries

    thawte Primary Root CA, 26.10.2010., trustedCertEntry,
    Certificate fingerprint (MD5): 8C:CA:DC:0B:22:CE:F5:BE:72:AC:41:1A:11:A8:D8:12
    *.battle.net, 26.10.2010., trustedCertEntry,
    Certificate fingerprint (MD5): FC:1C:1D:FE:FF:4A:AE:EA:11:4B:54:8C:2B:F0:C1:51
    Thawte SSL CA, 26.10.2010., trustedCertEntry,
    Certificate fingerprint (MD5): EB:A3:71:66:38:5E:3E:F4:24:64:ED:97:52:E9:9F:1B

    When I used that keystore, I got a different error:

    10-26 20:43:23.743: WARN/System.err(5423): javax.net.ssl.SSLException: Not trusted server certificate
    10-26 20:43:23.743: WARN/System.err(5423): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:371)
    10-26 20:43:23.753: WARN/System.err(5423): at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:92)
    10-26 20:43:23.753: WARN/System.err(5423): at org.apache.http.conn.ssl.SSLSocketFactory.createSocket(SSLSocketFactory.java:381)
    10-26 20:43:23.753: WARN/System.err(5423): at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:164)
    10-26 20:43:23.753: WARN/System.err(5423): at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164)
    10-26 20:43:23.753: WARN/System.err(5423): at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119)
    10-26 20:43:23.753: WARN/System.err(5423): at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:348)
    10-26 20:43:23.753: WARN/System.err(5423): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555)
    10-26 20:43:23.763: WARN/System.err(5423): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487)
    10-26 20:43:23.763: WARN/System.err(5423): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465)
    10-26 20:43:23.763: WARN/System.err(5423): at org.homedns.saran.android.wowcalendarsync.network.NetworkUtilities.authenticateWithPass(NetworkUtilities.java:344)
    10-26 20:43:23.763: WARN/System.err(5423): at org.homedns.saran.android.wowcalendarsync.network.NetworkUtilities$1.run(NetworkUtilities.java:164)
    10-26 20:43:23.763: WARN/System.err(5423): at org.homedns.saran.android.wowcalendarsync.network.NetworkUtilities$5.run(NetworkUtilities.java:276)
    10-26 20:43:23.763: WARN/System.err(5423): Caused by: java.security.cert.CertificateException: java.security.cert.CertPathValidatorException: Could not validate certificate signature.
    10-26 20:43:23.763: WARN/System.err(5423): at org.apache.harmony.xnet.provider.jsse.TrustManagerImpl.checkServerTrusted(TrustManagerImpl.java:168)
    10-26 20:43:23.763: WARN/System.err(5423): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:366)
    10-26 20:43:23.773: WARN/System.err(5423): … 12 more
    10-26 20:43:23.773: WARN/System.err(5423): Caused by: java.security.cert.CertPathValidatorException: Could not validate certificate signature.
    10-26 20:43:23.793: WARN/System.err(5423): at org.bouncycastle.jce.provider.PKIXCertPathValidatorSpi.engineValidate(PKIXCertPathValidatorSpi.java:342)
    10-26 20:43:23.793: WARN/System.err(5423): at java.security.cert.CertPathValidator.validate(CertPathValidator.java:202)
    10-26 20:43:23.793: WARN/System.err(5423): at org.apache.harmony.xnet.provider.jsse.TrustManagerImpl.checkServerTrusted(TrustManagerImpl.java:164)
    10-26 20:43:23.793: WARN/System.err(5423): … 13 more
    10-26 20:43:23.793: WARN/System.err(5423): Caused by: java.security.SignatureException: Signature was not verified.
    10-26 20:43:23.803: WARN/System.err(5423): at org.apache.harmony.security.provider.cert.X509CertImpl.fastVerify(X509CertImpl.java:601)
    10-26 20:43:23.803: WARN/System.err(5423): at org.apache.harmony.security.provider.cert.X509CertImpl.verify(X509CertImpl.java:544)
    10-26 20:43:23.803: WARN/System.err(5423): at org.bouncycastle.jce.provider.PKIXCertPathValidatorSpi.engineValidate(PKIXCertPathValidatorSpi.java:337)
    10-26 20:43:23.803: WARN/System.err(5423): … 15 more

    Using BC version you suggested and used keytool from these Java plugins (on Win7 64bit):
    jdk1.6.0_20 64bit
    jdk1.6.0_22 64bit
    jdk1.6.0_20 32bit

    I used this to retrieve certs:
    openssl s_client -connect eu.battle.net:443 -showcerts

  5. Hi Saran

    You should NOT place the *.battle.net certificate in your keystore. Your keystore should only contain the trusted issuers (the Root CA and any intermediate CA’s) and not the endpoint certificate itself.

    The check if your endpoint certificate is valid is done with several other criterias, like the hostname verification (does the cert correspond to the presented site).

    Please let me know if this is working.

  6. 6
    Saran 

    Yes, I tried it also with only Intermediate and Root (with having tried each of them imported as 1st at one time). Same result :(

  7. 7
    Saran 

    I’ve asked a question on StackOverflow:
    http://stackoverflow.com/questions/4115101/apache-httpclient-on-android-producing-certpathvalidatorexception-issuername

    Hopefully, someone will think of a solution…

  8. Hi Seran

    I tried to answer your question on stackoverflow. Hope it helps ;)

  9. 9
    Andreas 

    Thanks so much for this most useful info!

  10. 10
    Nilz 

    Hi Antoine,

    Your blog aims to tackle the exact problem I’m faced with, however I cannot get your solution to work.

    I keep getting the following in LogCat:

    11-19 15:12:34.777: ERROR/OpenSSLSocketImpl(520): Unknown error 5 during connect
    11-19 15:12:34.777: WARN/System.err(520): java.io.IOException: SSL handshake failure: I/O error during system call, Unknown error: 0
    11-19 15:12:34.786: WARN/System.err(520): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.nativeconnect(Native Method)
    11-19 15:12:34.786: WARN/System.err(520): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:305)
    11-19 15:12:34.786: WARN/System.err(520): at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:92)
    11-19 15:12:34.786: WARN/System.err(520): at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:321)
    11-19 15:12:34.795: WARN/System.err(520): at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:129)
    11-19 15:12:34.795: WARN/System.err(520): at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164)
    11-19 15:12:34.795: WARN/System.err(520): at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119)
    11-19 15:12:34.795: WARN/System.err(520): at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:348)
    11-19 15:12:34.795: WARN/System.err(520): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555)
    11-19 15:12:34.795: WARN/System.err(520): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487)
    11-19 15:12:34.795: WARN/System.err(520): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465)
    11-19 15:12:34.795: WARN/System.err(520): at me.test.TempActivity.onCreate(TempActivity.java:30)
    11-19 15:12:34.805: WARN/System.err(520): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
    11-19 15:12:34.805: WARN/System.err(520): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2459)
    11-19 15:12:34.814: WARN/System.err(520): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2512)
    11-19 15:12:34.814: WARN/System.err(520): at android.app.ActivityThread.access$2200(ActivityThread.java:119)
    11-19 15:12:34.814: WARN/System.err(520): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1863)
    11-19 15:12:34.814: WARN/System.err(520): at android.os.Handler.dispatchMessage(Handler.java:99)
    11-19 15:12:34.814: WARN/System.err(520): at android.os.Looper.loop(Looper.java:123)
    11-19 15:12:34.814: WARN/System.err(520): at android.app.ActivityThread.main(ActivityThread.java:4363)
    11-19 15:12:34.814: WARN/System.err(520): at java.lang.reflect.Method.invokeNative(Native Method)
    11-19 15:12:34.814: WARN/System.err(520): at java.lang.reflect.Method.invoke(Method.java:521)
    11-19 15:12:34.814: WARN/System.err(520): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860)
    11-19 15:12:34.814: WARN/System.err(520): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
    11-19 15:12:34.826: WARN/System.err(520): at dalvik.system.NativeStart.main(Native Method)

    Have you seen this before? Do you know what it means. Unfortunately I cannot share the certificate with you, but I can tell you that is was a p12 certificate which I exported to a X509 in windows xp.

    I really need help on this issue, any guidance would be a great help.

    Cheers,
    Nilz.

  11. 11
    Vlad 

    I tried to implemented and getting error. Any ideas?
    Here is my cert list

    {2df05992-4d0f-48af-9d89-342c0af1d238}, Nov 19, 2010, PrivateKeyEntry,
    Certificate fingerprint (MD5): 90:99:AC:3E:0A:22:7C:81:26:EC:6F:F4:04:F5:BB:A5
    GeotrustCA, Nov 19, 2010, trustedCertEntry,
    Certificate fingerprint (MD5): 67:CB:9D:C0:13:24:8A:82:9B:B2:17:1E:D1:1B:EC:D4

    11-19 12:34:42.577: WARN/System.err(4233): java.net.SocketException: The operation timed out
    11-19 12:34:42.587: WARN/System.err(4233): at org.apache.harmony.luni.platform.OSNetworkSystem.connectStreamWithTimeoutSocketImpl(Native Method)
    11-19 12:34:42.587: WARN/System.err(4233): at org.apache.harmony.luni.platform.OSNetworkSystem.connect(OSNetworkSystem.java:115)
    11-19 12:34:42.597: WARN/System.err(4233): at org.apache.harmony.luni.net.PlainSocketImpl.connect(PlainSocketImpl.java:244)
    11-19 12:34:42.597: WARN/System.err(4233): at org.apache.harmony.luni.net.PlainSocketImpl.connect(PlainSocketImpl.java:533)
    11-19 12:34:42.607: WARN/System.err(4233): at java.net.Socket.connect(Socket.java:1055)
    11-19 12:34:42.607: WARN/System.err(4233): at org.apache.http.conn.scheme.PlainSocketFactory.connectSocket(PlainSocketFactory.java:119)
    11-19 12:34:42.607: WARN/System.err(4233): at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:143)
    11-19 12:34:42.617: WARN/System.err(4233): at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164)
    11-19 12:34:42.617: WARN/System.err(4233): at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119)
    11-19 12:34:42.617: WARN/System.err(4233): at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:348)
    11-19 12:34:42.617: WARN/System.err(4233): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555)
    11-19 12:34:42.617: WARN/System.err(4233): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487)
    11-19 12:34:42.617: WARN/System.err(4233): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465)

  12. 12
    Nick 

    I am very please with your tutorial; it is very thorough, but I am having flaky success.

    I am trying to use it to access Google’s login url: https://www.google.com/accounts/ClientLogin.

    I built everything just the way you detailed. Then the first time I ran it I got the expected response, but every time after that I got “javax.net.ssl.SSLException: Not trusted server certificate”.

    I’ve managed to get the desired response about 3 times, but nothing I change seems to have an effect. I sure would appreciate your help. I don’t know why Android makes this so difficult.

  13. 13
    swapnil 

    Hi,

    I like to know how google manage security certificate on Android. Reason i am asking is i came across a webcast by google for android and in that they mention storing certificate on Android device and using it instead of passing it everytime and accordingly this reduces data connection overhead.

    I am trying to achieve something similar.. i dont want to pass and receive server/client secure certificate everytime.
    My application is kind of pushengine without google PUSH API.

    Awaiting your views.

  14. Hi there

    Sorry for the late response, I was away for a couple of days.

    @Nilz:
    Never seen this error before. Can you provide some code (of the SSL Factory)? Maybe this helps:http://stackoverflow.com/questions/2899079/custom-ssl-handling-stopped-working-on-android-2-2-froyo

    @Vlad:
    The error is indicating that your operation timed out. Does your app executes the request to the server? You could intercept the traffic between the emulator and server for example with Wireshark. Sometimes the reply from the server could also be helpful.

    @Nick:
    Thanks.
    I think the Google ClientLogin uses a different approach.
    http://code.google.com/apis/accounts/docs/AuthForInstalledApps.html

    @swapnil:
    Do you have the link or name of the mentioned webcast?
    I think I didn’t understand your question. What do you mean with storing the certificate and not passing it every time? The certificates are just passed during the establishment of the secure connection. After the cert. exchange (when all certificates are considered as trusted and valid) session keys are generated to secure the actual data. The session keys are valid until the connection closes.

    Found an useful link: http://tokudu.com/2010/how-to-implement-push-notifications-for-android/

    Greetz
    Antoine

  15. 15
    Gergo 

    Hi Antoine

    a very nice tutorial. Thank for that.
    My question is regarding client authentication. As far as i saw, the Apache HttpClient cannot handle this situation. When using only Server Auth, it works perfect , but when setting the Server to authenticate the client it fails.Do you know something about it ?
    I am trying it now the “Java way” with SSL Socket , but it fails too with ” Not trusted Server certifiate :(
    PLZ drop me an email if you have knowledge about turials or articles dealing with that problem

    Thanks in advance
    Gergo

  16. 16
    Gergo 

    Hi Antoine
    i figured out the problem with the “Not Trusted server certificate”
    It was the TrustManager. For some reason i do not know, The Trustmanager could not authenticate the certificate of the server. I have implemented my own.
    Client authentication works now.
    but if you have any idea how to do it with the Apache HttpClient, please drop me some line
    Thanks
    Gergo

  17. 17
    Lys 

    Hi,
    I found your post while looking for a solution to a similar problem. What I need is to connect to the remote server and download the cert for my app to use. Basically steps 1 and 2 but within the app itself. Any thoughts on how to do that?
    Thanks

  18. 18
    Martin 

    Hi,
    very useful, but I’m getting stuck with a 404 reply in the response. Have you any ideas to the reason for this?
    Wireshark shows a encrypted data load, length 288, which could corespond to the expected return from the Webservice

    Thanks

  19. @Gergo
    Hmm… AFAIK the Apache HttpClient is not able to handle client authentication with cert.

    @Lys
    Didn’t look very deep into those links.
    How to create your own keystore:
    http://www.coderanch.com/t/133048/Security/do-programmatically-create-keystore-import
    How to obtain the certificate from the site:
    http://helpdesk.objects.com.au/java/how-do-i-programatically-extract-a-certificate-from-a-site-and-add-it-to-my-keystore

    @Martin
    Can you access your resource via browser (without 404)?
    Maybe your HTTP headers are wrong and the server returns a 404 (but another error code would be much more appropriate in this case). In my opinion 288 bytes is not very much. Maybe the 404 error itself.

    You can try two approaches to see what’s going on with the response:
    1. If you have the private key of the webservice (I doubt that) you can encrypt the traffic with Wireshark. See http://htluo.blogspot.com/2009/01/decrypt-https-traffic-with-wireshark.html
    2. This is the PITA alternative, but you DON’T need the private key from the webservice. You can download fiddler2 (www.fiddler2.com), add the proxy certificate from fiddler (or create a new one to match the hostname to your webservice) to the app keystore. Then add an argument in your Android Emulator to use the fiddler proxy to connect to the webservice. Seehttp://mrrask.wordpress.com/2009/10/01/setting-up-the-android-emulator-for-http-debugging-using-fiddler2/ Your app in the emulator will connect to fiddler and there you can see the decrypted payload.

  20. 20
    pyko 

    Hi Antonie,
    Firstly, thanks heaps for this post ? it’s really really helpful & well written too! :D

    Implemented your solution and bumping into similar problem to Nick ? where the authentication is quite flaky :( though i’m not authing with Google accounts…

    Without changing anything, sometimes logging in will work first attempt… other times it requires several attempts to work..

    Looking at my stacktrace, I would’ve thought I got the order wrong…but I double checked that and what doesn’t make sense is that it sometimes works….
    javax.net.ssl.SSLException: Not trusted server certificate
    at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:371)
    at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:92)
    at org.apache.http.conn.ssl.SSLSocketFactory.createSocket(SSLSocketFactory.java:381)
    at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:164)
    ….etc….
    Caused by: java.security.cert.CertificateException: java.security.cert.CertPathValidatorException: IssuerName(CN=thawte Primary Root CA, OU=”(c) 2006 thawte, Inc. ? For authorized use only”, OU=Certification Services Division, O=”thawte, Inc.”, C=US) does not match SubjectName(CN=Thawte SSL CA, O=”Thawte, Inc.”, C=US) of signing certificate
    at org.apache.harmony.xnet.provider.jsse.TrustManagerImpl.checkServerTrusted(TrustManagerImpl.java:168)
    at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:366)
    … 24 more
    Caused by: java.security.cert.CertPathValidatorException: IssuerName(CN=thawte Primary Root CA, OU=”(c) 2006 thawte, Inc. ? For authorized use only”, OU=Certification Services Division, O=”thawte, Inc.”, C=US) does not match SubjectName(CN=Thawte SSL CA, O=”Thawte, Inc.”, C=US) of signing certificate
    at org.bouncycastle.jce.provider.PKIXCertPathValidatorSpi.engineValidate(PKIXCertPathValidatorSpi.java:373)
    at java.security.cert.CertPathValidator.validate(CertPathValidator.java:202)
    at org.apache.harmony.xnet.provider.jsse.TrustManagerImpl.checkServerTrusted(TrustManagerImpl.java:164)
    … 25 more

  21. 21
    Martin 

    Hi again,
    the Ws can be browsed both on real device/emulator and from pc without problems. Cert chain is exported from firefox (https://google.com/accounts Worked this way).

    http works fine. I’ll investigate the output from wireshark

    Thnx
    martin

  22. 22
    Martin 

    no difference between wireshark output from http and https

    very strange

  23. 23
    allen 

    Hey everyone,

    I think I was able to find a fix to the sporadic nature of this solution. For those who used Antoine’s solution, but get inconsistent behavior, try importing just the root cert into your keystore and not the intermediate cert. not sure if this only worked for our setup with our servers, but it worked for us. I noticed all the exceptions I got were because it was trying to compare the root cert against the intermediate. Hope that helps!

  24. 24
    Martin 

    Hi,
    I finally found a solution for the 404 problem.
    the Webservice I’m calling is a .Net wcf service on an Intranet server, and the config of the ws was the problem.

    After doing a binding modification (http://www.codemeit.com/wcf/wcf-wsdl-xsdimport-schemalocations-link-to-local-machine-name-not-domain-name-while-hosted-in-iis.html)
    a super simple config file solved the problem

    I tried many other config solutions, but this one worked for me. Hope this can help others

    /Martin

  25. @pyko
    I think that the order of the present certificates could still be the problem, especially when you are connecting to an endpoint, which is behind a web farm. One miss configured web server could send the certificates in the wrong order, another one not.
    Check with Wireshark etc. if the order is correct.

    If you are not able to change the certificate order of the webserver, you could change the order programmatically.

    More info about changing the order programmatically can be found on this stackoverflow topic:http://stackoverflow.com/questions/4115101/apache-httpclient-on-android-producing-certpathvalidatorexception-issuername/4199518#4199518

    @allen:
    AFAIK every involved certificate must be in the keystore. Never tried to remove the intermediate cert. But I could imagine, that if the order of the certificates is sent wrong from the webserver, for example the first entry is the Root CA and not the Intermediate, then the Bouncy Castle checks only against the one and only Root CA certificate in the keystore and completes the checking. But this is just an assumption. You can also look at the link that I posted to pyko.

  26. 26
    Teresa 

    Hi Antoine,

    Very pleased with this tutorial. In my app, I am trying to send a soap request using ksoap2, which is working fine in my test environment. If I am trying to connect to a secured site, getting ‘Not trusted server certificate’. I dont want to bypass the certificate check like it was mentioned in some of the blogs. Is it possible to implement your solution with soap. Here is how I am sending the request.

    HttpsTransportSE transport = new HttpsTransportSE(URL, 443, “”, 60000);
    transport.call(SOAP_ACTION, envelope);

    Appreciate your help.

    Thanks,
    Teresa

  27. 27
    Matt 

    Any luck finding an answer to Teresa’s question? I’m having the same problem. I’m fairly sure the 3rd parameter is the keystore with the certificate, but i’m not sure how to find that? Can you help?

    Thanks,
    Matt

  28. 28
    pyko 

    @allen & @Antoine
    Strangely enough just importing the root CA worked! I am able to login successfully everytime now (assuming I enter the correct credentials of course)

  29. @Martin
    I’m glad that you solved the problem. Thank you for commenting the solution here.

    @pyko
    Thank you very much for your testing.

    @Teresa & @Matt
    I’m sorry. I have no idea how to solve this one. Never used ksoap2. I can’t find any useful reference for the parameters in the HttpsTransportSE constructor. Maybe this entry helps a bit:http://stackoverflow.com/questions/2248147/andoird-ksoap2-https-problem/4438993#4438993

    Keep on going and please let me know if you found a solution. Thanks

저작자 표시 비영리 동일 조건 변경 허락
TRACKBACK 0 AND COMMENT 1

ARCHIVE

CALENDAR

«   2012/01   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31        

ARTICLE CATEGORY

분류 전체보기 (161)
가족일기 (3)
낙서장 (32)
밥벌이 (30)
추억 (2)
사회 (27)
혼자만의 방 (2)
생태 (4)
눈여겨 보는 곳 (1)
어머니 일기 (38)
윤선애 (1)
생활 단식 (10)
동거동락 자전거 (2)