
사용자에게 SSL 인증서에 대해 물어볼 수 있게 해주는 Android Java용 "플러그인"
MemorizingTrustManager(MTM)는 Android에서 SSL을 더 스마트하고 안전하게 사용할 수 있게 해주는 프로젝트입니다. 알 수 없는 SSL 인증서를 만나면 사용자에게 인증서를 한 번만 수락할지, 영구적으로 수락할지, 아니면 연결을 중단할지 묻습니다. 이는 유효하지 않거나 자체 서명되었거나 만료된 인증서를 무조건 수락함으로써 발생하는 중간자 공격을 방지하는 한 단계입니다.
MTM은 Android 애플리케이션에 원활하게 통합되는 것을 목표로 하며, 소스 코드는 MIT 라이선스로 제공됩니다.

MemorizingTrustManager는 yaxim XMPP 클라이언트에서 프로덕션 환경으로 사용되고 있습니다. 호스트 이름 검증을 아직 지원하지는 않지만(Java API가 통합을 어렵게 만듭니다), 사용할 수 있고 쉽게 통합할 수 있습니다.
MTM은 자신의 애플리케이션에 쉽게 통합할 수 있습니다. 다음 단계를 따르거나 example 디렉터리의 데모 애플리케이션을 살펴보세요.
GitHub에서 MTM 소스를 다운로드하거나 git 서브모듈로 추가하세요:
# plain download:
git clone https://github.com/ge0rg/MemorizingTrustManager
# submodule:
git submodule add https://github.com/ge0rg/MemorizingTrustManager
그런 다음 default.properties에 라이브러리 프로젝트 종속성을 추가하세요:
android.library.reference.1=MemorizingTrustManager
AndroidManifest.xml을 편집하고 닫는 </application> 태그 바로 앞에 MTM activity 요소를 추가하세요.
...
<activity android:name="de.duenndns.ssl.MemorizingActivity"
android:theme="@android:style/Theme.Translucent.NoTitleBar"
/>
</application>
</manifest>
HTTPS 연결에서 MemorizingTrustManager 후킹하기:
// register MemorizingTrustManager for HTTPS
SSLContext sc = SSLContext.getInstance("TLS");
MemorizingTrustManager mtm = new MemorizingTrustManager(this);
sc.init(null, new X509TrustManager[] { mtm }, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier(
mtm.wrapHostnameVerifier(HttpsURLConnection.getDefaultHostnameVerifier()));
SSLSocket의 경우 다음과 같이 해야 합니다:
// register MemorizingTrustManager for all SSLSockets
SSLContext sc = SSLContext.getInstance("TLS");
MemorizingTrustManager mtm = new MemorizingTrustManager(this);
HostnameVerifier hv = mtm.wrapHostnameVerifier(new org.apache.http.conn.ssl.StrictHostnameVerifier());
sc.init(null, new X509TrustManager[] { mtm }, new java.security.SecureRandom());
SSLContext.setDefault(sc);
// connect a socket
SSLSocket s = ...;
s.startHandshake();
if (!hv.verify(your_domain_name, sslSocket.getSession())) {
throw new CertificateException("Server failed to authenticate as " + your_domain_name);
}
또는 Smack에서는 setCustomSSLContext()를 사용할 수 있습니다:
org.jivesoftware.smack.ConnectionConfiguration connectionConfiguration = …
SSLContext sc = SSLContext.getInstance("TLS");
MemorizingTrustManager mtm = new MemorizingTrustManager(this);
sc.init(null, new X509TrustManager[] { mtm }, new java.security.SecureRandom());
connectionConfiguration.setCustomSSLContext(sc);
connectionConfiguration.setHostnameVerifier(
mtm.wrapHostnameVerifier(new org.apache.http.conn.ssl.StrictHostnameVerifier()));
기본적으로 MTM은 사용자에게 묻기 전에 시스템 TrustManager로 폴백합니다. 기본 신뢰 설정을 신뢰하지 않는다면 생성자에 defaultTrustManager = null 매개변수를 전달하여 모든 새 연결에서 대화상자를 강제로 표시할 수 있습니다:
MemorizingTrustManager mtm = new MemorizingTrustManager(this, null);
AndroidPinning 같은 다른 기본 TrustManager를 사용하려면 MTM 생성자에 그것을 전달하기만 하면 됩니다:
X509TrustManager pinning = new PinningTrustManager(SystemKeyStore.getInstance(),
new String[] {"f30012bbc18c231ac1a44b788e410ce754182513"}, 0);
MemorizingTrustManager mtm = new MemorizingTrustManager(this, pinning);
MTM은 로깅 목적으로 java.util.logging(JUL)을 사용합니다. JUL용 Handler를 구성하지 않았다면 Android는 기본적으로 Level.INFO 이상의 모든 메시지를 로그로 남깁니다. 디버그 로그 메시지(Level.FINE 이하)도 얻으려면 그에 맞게 Handler를 구성해야 합니다. MTM 예제 프로젝트에는 런타임에 디버그 로깅을 활성화/비활성화할 수 있는 de.duenndns.mtmexample.JULHandler가 포함되어 있습니다.
MemorizingTrustManager만 있는 것은 아닙니다.
NetCipher는 Guardian Project가 모바일 앱의 네트워크 보안을 개선하기 위해 만든 Android 라이브러리입니다. 더 철저한 인증서 검사를 위한 StrongTrustManager, 독립적인 루트 CA 저장소, 그리고 Orbot을 사용하여 Tor 네트워크로 트래픽을 쉽게 라우팅하는 코드가 함께 제공됩니다.
AndroidPinning은 Moxie Marlinspike가 작성한 또 다른 Android 라이브러리로, 서버 인증서를 고정(pinning)할 수 있게 하여 정부 규모의 중간자(MitM) 공격에 대한 보안을 향상시킵니다. 앱이 특정 서버와 통신하도록 만들어진 경우 이 라이브러리를 사용하세요!
MTM을 더 많은 언어로 번역하는 데 도움을 주세요!