Lucky Dog

[안드로이드] https 통신 (Android https ssl / tls) 본문

안드로이드

[안드로이드] https 통신 (Android https ssl / tls)

Poohya 2014. 1. 22. 10:08

안드로이드 https 통신


인증서 생성


완전한 상호인증은 클라이언트에서 서버 인증서를 검사하고, 서버에서는 클라이언트 인증서를 검사하는 것

서버, 클라이언트에서 각각 keystore 생성 후 인증서(cer) 를 export하고 해당 인증서를 각자의 키스토어에 추가한다.


1. 인증서 생성

서버 : keytool -genkey -keystore server.jks -alias server

클라이언트 : keytool -genkey -keystore client.jks -alias client


2. 인증서 Export

서버 : keytool -export -keystore server.jks -alias server -file server.cer

클라이언트 : keytool -export -keystore client.jks -alias client -file client.cer


3. 인증서 Improt

- 각자 상대편의 인증서를 truststore에 (jks) import 한다

서버 : keytool -import -keystore server.jks -alias client -file client.cer

클라이언트 : keytool -import -keystore client.jks -alias server -file server.cer


* 참조 사이트에서 작성자가 '3번 인증서 import ' 할 때 서버/클라 keystore 를 반대로 적어놓은것 같다.

(일단 고쳐서 적음. 테스트 필요)

참조 : http://kskang.tistory.com/529


* 안드로이드 기본 Keystore 는 'BKS' ('JKS' 아님)


안드로이드 Https 통신 설정


    public void test() {
        try {
            URL url = new URL("input url");
            SSLContext sslCtx = SSLContext.getInstance("TLS");
            sslCtx.init(nullnew TrustManager[]{mTrustManager}, new SecureRandom());
            HttpsURLConnection https = (HttpsURLConnection) url.openConnection();
            https.setSSLSocketFactory(sslCtx.getSocketFactory());
            https.connect();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        }
    }
 
    X509TrustManager mTrustManager = new X509TrustManager() {
        private X509HostnameVerifier verifier = org.apache.http.conn.ssl.SSLSocketFactory.STRICT_HOSTNAME_VERIFIER;
 
        @Override
        public X509Certificate[] getAcceptedIssuers() {
            return null;
        }
 
        @Override
        public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            if ((chain != null&& (chain.length == 1)) {
                X509Certificate certificate = chain[0];
                certificate.checkValidity();
                String serverURL = "serv url";
                try {
                    verifier.verify(serverURL, certificate);
                } catch (SSLException e) {
                    e.printStackTrace();
                    throw new CertificateException(e.getMessage());
                }
            }
        }
 
        @Override
        public void checkClientTrusted(X509Certificate[] chain, String authType)  {
            try {
                KeyStore trustStore = KeyStore.getInstance("JKS");
                String cacertPath = "path";     // ex) C:/Program Files/Java/jdk1.8.0_05/jre/lib/security/cacerts
                trustStore.load(new FileInputStream(cacertPath), "changeit".toCharArray());
                TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
                tmf.init(trustStore);
                TrustManager[] tmArr = tmf.getTrustManagers();
                ((X509TrustManager) tmArr[0]).checkServerTrusted(chain, authType);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    };



보안 검증(Hostname, 인증서) 없이 연결

아래 방법을 사용하면 Google Play Store 에 앱이 업로드 안될 수 있음 (보안 정책 위배)


public final static HostnameVerifier DO_NOT_VERIFY = new HostnameVerifier() {
    public boolean verify(String hostname, SSLSession session) {
        return true;
    }
};



    public static void trustAllHosts() {
        // Create a trust manager that does not validate certificate chains
        TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                return new java.security.cert.X509Certificate[] {};
            }
 
            public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            }
 
            public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            }
 
        } };
 
        // Install the all-trusting trust manager
        try {
            SSLContext sc = SSLContext.getInstance("TLS");
            sc.init(null, trustAllCerts, new java.security.SecureRandom());
            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
cs




Comments