2013-05-14 3 views
0

Android 및 서버 측에서 Netty를 사용하여 클라이언트 인증과 SSL 보안 연결을 설정합니다. 이제는 SSLEngine이 "null cert chain"으로 인해 거부하기 때문에 이러한 인증서에 연결하는 데 어려움을 겪고 있습니다.클라이언트 인증서를 SSL 핸드 셰이크로 받기

이것은 서버 측에서 수행 한 작업입니다. 서명 된 Server Certificat (클라이언트가 CA를 알고 있으므로이 서버의 유효성을 확인할 수 있음)로 SSLContext를 설정합니다.

서버가 클라이언트에서 인증서를 수락하도록하려면 (자체 서명되었으므로) 모든 인증서를 수락하는 DummyTrustManager를 구현했습니다.

private static class DummyTrustManager implements X509TrustManager 
    { 
     private X509Certificate[] mCerts; 

     public DummyTrustManager(Certificate[] pCerts) 
     { 
      // convert into x509 array 
      mCerts = new X509Certificate[pCerts.length]; 
      for(int i = 0; i < pCerts.length; i++) 
      { 
       mCerts[i] = (X509Certificate)pCerts[i]; 
      } 
     } 

     @Override 
     public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException{} 

     @Override 
     public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException{} 

     @Override 
     public X509Certificate[] getAcceptedIssuers() 
     { 
      return mCerts; 
      //return new X509Certificate[0]; 
     } 
    } 

내가 getAcceptedIssuers() 메소드에 대해 아주 잘 모르겠어요 것입니다.
  • 나는보다 빈 배열을 retrurn 경우에는 OpenSSL 바이너리로 인해 빈 AcceptedIssuers 목록 (I 올바른 설정을 veryfi하기 위해 사용하는) 실패합니다.

  • 현재 서버 인증서 체인을 추가하는 경우 최소한 동일한 CA가 서명 한 클라이언트 인증서는 필요하지만 자체 서명 된 인증서는 필요하지 않습니다.

하지만 어쩌면 나는 클라이언트 측에서 뭔가를 잘못하고 있어요 :

또한
 KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); 
     keyStore.load(null); 

     keyStore.setEntry("user_certificate", new KeyStore.PrivateKeyEntry(mPrivate, new Certificate[]{mClientCert}), this); 
     keyStore.setCertificateEntry("server_certificate", mServerCert); 

내가 한 몇 가지 연구와 내가 지금까지 이해 것과 : 클라이언트가 유효한 인증서 체인을 가지고 있지만하지 않습니다 서버가 서버에 나열된 발급자 만 수락한다는 것을 서버가 알려주기 때문에이를 보냅니다.

맞다면 어떻게이 문제를 극복 할 수 있습니까?

저는 모든 클라이언트에게 전달되는 자체 서명 된 별도의 CA가 서버 승인 수취인 목록에도 나열되어 있다고 생각했습니다. 모든 클라이언트는이 CA를 사용하여 자체 인증서에 서명합니다. 나는이 문제에 보안 문제가 없다는 것을 알고있다. 아니면 더 나은 해결책이 있습니까?

+0

여기에 문제가 있습니다. 클라이언트 인증을 사용하고 클라이언트 인증서를 수락하는 것은 상호 모순입니다. 클라이언트가 누구인지 또는 유효한 인증서가 있는지 신경 쓰지 않으면 클라이언트 인증을 전혀 사용하지 않는 이유는 무엇입니까? OpenSSL이 필요하지 않습니다. 자바는 암호화 API로 가득 차 있습니다. – EJP

+1

클라이언트 인증서를 로그인 토큰으로 사용하고 있습니다. 알 수없는 인증서는 새 클라이언트로 스레드되어 등록됩니다. 그래서 둘 다 가질 이유가 있습니다. 그리고 슬프게도 Java에는 완전한 암호화 패킷이 없습니다. 심지어 Bouncycastle을 사용하여 클라이언트 측에서 자체 서명 된 인증서를 만들어야합니다.SSL 핸드 셰이크가 제대로 작동하는지 확인하는 s_client 매개 변수 때문에 openssl을 사용했습니다. – Chris

답변

1

오랫동안 답변이 없었기 때문에 지금 어떻게 해결할 지 간략하게 설명하겠습니다.

신뢰할 수있는 CA가 서명하지 않은 다른 CA를 만들었습니다. 실제로 그것은 자체 서명되어 있습니다. 이 CA는 모든 클라이언트에게 자체 인증서에 서명하도록 제공됩니다. 왜? 그 방법으로 나는이 CA를 유일하게 수락 된 것으로 보내는 서버에 알릴 수 있습니다. getAcceptedIssuers(). 이것은 어느 정도의 권한을 부여하기위한 것이 아닙니다. 클라이언트를 확인하는 방법은 공개 키로 만 이루어 지므로 보안 위험은 없습니다.

TrustedManagers와 SSLContext 인스턴스를 혼동하지 않도록주의해야합니다.

+0

보안 상 위험한 것은 CA가 고객 중 한 명에게서 돈을 내지 않은 사람 또는 자신을 보호하려고 시도하는 사람에게 누출 될 것이라는 것입니다. 당신은 정말로 여기에서 거의 성취하지 못했습니다. – EJP

+1

앞서 언급했듯이. 나는 대부분의 사람들이하는 것처럼 SSL을 사용하지 않는다. 클라이언트가 사용자 이름/암호 대신 공개 키를 사용하는 연결을 설정해야합니다. 공개 키로 클라이언트를 확인하고 발급자가 아닌 ** 모든 클라이언트를 제외하고도 모든 발급자를 제외 할 수 있습니다. 공용 CA는 트릭 할 수있는 방법 일 뿐이며, 그렇지 않은 경우 클라이언트 측에서 인증서를 전혀 보내지 않기 때문에 Java가 할 수 있으면 건너 뛰고 싶습니다. 내 질문에 대한 것입니다. 내가 알지 못하는 공개 키는 새로운 것으로 스레드되어 내 서버에 등록 할 수 있습니다. – Chris

관련 문제