OkHttp:SSLPeerUnverifiedException 无法找到签署 X.509 证书的可信证书
OkHttp: SSLPeerUnverifiedException Failed to find a trusted cert that signed X.509 Certificate
其实这周我也有和下面的问题一样的问题
在我的 phone(摩托罗拉,Android 4.1.2)中,我禁用了所有 DigiCert CA(在 Settings - Security - Trusted credentials - System
内)。
我的代码如下:
public class CertPinActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_cert_pin);
try {
CertificatePinner certificatePinner = new CertificatePinner.Builder()
.add("github.com", "sha256/WoiWRyIOVNa9ihaBciRSC7XHjliYS9VwUGOIud4PB18=")
.build();
OkHttpClient client = new OkHttpClient.Builder()
.sslSocketFactory(getSSLSocketFactory())
.certificatePinner(certificatePinner)
.build();
Request request = new Request.Builder()
.url("https://github.com/square/okhttp/wiki/HTTPS")
.build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.e("onFailure","-------------------------------------------------");
e.printStackTrace();
}
@Override
public void onResponse(Call call, Response response) throws IOException {
Log.d("onResponse", response.body().string());
}
});
} catch (Exception e){
e.printStackTrace();
}
}
private SSLSocketFactory getSSLSocketFactory()
throws CertificateException, KeyStoreException, IOException,
NoSuchAlgorithmException, KeyManagementException {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream caInput = getResources().openRawResource(R.raw.github); // this is exported from Chrome then stored inside \app\src\main\res\raw path
Certificate ca = cf.generateCertificate(caInput);
caInput.close();
KeyStore keyStore = KeyStore.getInstance("BKS");
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, tmf.getTrustManagers(), null);
return sslContext.getSocketFactory();
}
}
我的应用程序得到了以下 logcat(对不起,我 t运行 分类,因为它太长了)
06-14 09:10:10.065 30176-30211/com.example.okhttps3 E/onFailure: -------------------------------------------------
06-14 09:10:10.065 30176-30211/com.example.okhttps3 W/System.err: javax.net.ssl.SSLPeerUnverifiedException: Failed to find a trusted cert that signed X.509 Certificate:
06-14 09:10:10.065 30176-30211/com.example.okhttps3 W/System.err: [
06-14 09:10:10.065 30176-30211/com.example.okhttps3 W/System.err: [
06-14 09:10:10.065 30176-30211/com.example.okhttps3 W/System.err: Version: V3
06-14 09:10:10.065 30176-30211/com.example.okhttps3 W/System.err: Subject: CN=DigiCert SHA2 Extended Validation Server CA,OU=www.digicert.com,O=DigiCert Inc,C=US
06-14 09:10:10.065 30176-30211/com.example.okhttps3 W/System.err: Signature Algorithm: SHA256WithRSAEncryption, params unparsed, OID = 1.2.840.113549.1.1.11
06-14 09:10:10.065 30176-30211/com.example.okhttps3 W/System.err: Key:
...................................................................................
06-14 09:17:56.813 5934-5984/com.example.okhttps3 W/System.err: at okhttp3.internal.tls.CertificateChainCleaner$BasicCertificateChainCleaner.clean(CertificateChainCleaner.java:132)
06-14 09:17:56.813 5934-5984/com.example.okhttps3 W/System.err: at okhttp3.CertificatePinner.check(CertificatePinner.java:149)
06-14 09:17:56.813 5934-5984/com.example.okhttps3 W/System.err: at okhttp3.internal.io.RealConnection.connectTls(RealConnection.java:252)
06-14 09:17:56.823 5934-5984/com.example.okhttps3 W/System.err: at okhttp3.internal.io.RealConnection.establishProtocol(RealConnection.java:196)
06-14 09:17:56.823 5934-5984/com.example.okhttps3 W/System.err: at okhttp3.internal.io.RealConnection.buildConnection(RealConnection.java:171)
06-14 09:17:56.823 5934-5984/com.example.okhttps3 W/System.err: at okhttp3.internal.io.RealConnection.connect(RealConnection.java:111)
06-14 09:17:56.823 5934-5984/com.example.okhttps3 W/System.err: at okhttp3.internal.http.StreamAllocation.findConnection(StreamAllocation.java:187)
06-14 09:17:56.823 5934-5984/com.example.okhttps3 W/System.err: at okhttp3.internal.http.StreamAllocation.findHealthyConnection(StreamAllocation.java:123)
06-14 09:17:56.823 5934-5984/com.example.okhttps3 W/System.err: at okhttp3.internal.http.StreamAllocation.newStream(StreamAllocation.java:93)
06-14 09:17:56.823 5934-5984/com.example.okhttps3 W/System.err: at okhttp3.internal.http.HttpEngine.connect(HttpEngine.java:296)
06-14 09:17:56.823 5934-5984/com.example.okhttps3 W/System.err: at okhttp3.internal.http.HttpEngine.sendRequest(HttpEngine.java:248)
06-14 09:17:56.823 5934-5984/com.example.okhttps3 W/System.err: at okhttp3.RealCall.getResponse(RealCall.java:243)
06-14 09:17:56.823 5934-5984/com.example.okhttps3 W/System.err: at okhttp3.RealCall$ApplicationInterceptorChain.proceed(RealCall.java:201)
06-14 09:17:56.823 5934-5984/com.example.okhttps3 W/System.err: at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:163)
06-14 09:17:56.823 5934-5984/com.example.okhttps3 W/System.err: at okhttp3.RealCall.access0(RealCall.java:30)
06-14 09:17:56.823 5934-5984/com.example.okhttps3 W/System.err: at okhttp3.RealCall$AsyncCall.execute(RealCall.java:127)
06-14 09:17:56.823 5934-5984/com.example.okhttps3 W/System.err: at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
06-14 09:17:56.823 5934-5984/com.example.okhttps3 W/System.err: at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
06-14 09:17:56.823 5934-5984/com.example.okhttps3 W/System.err: at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
06-14 09:17:56.823 5934-5984/com.example.okhttps3 W/System.err: at java.lang.Thread.run(Thread.java:856)
但是,onResponse
在以下情况下调用:
.sslSocketFactory(getSSLSocketFactory())
和 .certificatePinner(certificatePinner)
都删除了;
- 仅删除
.sslSocketFactory(getSSLSocketFactory())
; (实际上,使用模拟器,当系统 CA 禁用时,onFailure
调用并在其中 java.security.cert.CertPathValidatorException: Trust anchor for certification path not found
抛出)
- 只删除了
.certificatePinner(certificatePinner)
。
Logcat 和 onResponse
如下(太长所以我 t运行cate):
06-14 09:06:23.143 26571-26616/com.example.okhttps3 D/onResponse: <!DOCTYPE html>
<html lang="en" class="">
.....
所以,我的问题是:
- 和我问题开头的link一样(实际上是他的第1期);
- 当
certificatePinner
与 getSSLSocketFactory
一起使用时,为什么我的应用程序得到 javax.net.ssl.SSLPeerUnverifiedException: Failed to find a trusted cert that signed X.509 Certificate
?请注意,此 SSLPeerUnverifiedException
的内部消息与 this JavaDoc 中提到的 Certificate pinning failure!
不同。
更新:
第一期:
看起来这个问题(System/User 受信任的凭据无效)只发生在我的 phone 中 运行 Android 4.1.2,我检查了 02 台设备,所以我想我应该联系制造商。
第 2 期:
根据下面@Robert的评论"I assume you have to include the full certificate chain (or the root certificate if the server sends you the chain), not only the leave certificate"
,我改为导出Root CA,如下截图,虽然没有完成链,在getSSLSocketFactory
里面我改为getResources().openRawResource(R.raw.github_rootca);
现在,我的第二个问题解决了!
证书固定是一种额外的安全措施,因此证书必须受到使用的 TrustManager 的信任并且它必须与固定的证书相匹配。
由于您禁用了 DigiCert CA 证书,因此该证书不受所起诉的 TrustManager 的信任,因此您会收到 SSLPeerUnverifiedException。
我描述的行为记录在 CertificatePinner 的 JavaDoc 中:
Note about self-signed certificates
CertificatePinner can not be used to pin self-signed certificate if such certificate is not accepted by TrustManager.
如果您禁用默认系统证书 trustore,(使用或不使用没有自定义 trustore 的证书固定)您将始终遇到异常,因为将无法验证对等证书,因此
- 如果您不使用
Certificate pinning
并且您的 default system certificate trustore
是 working
(使用 Digicert High Assurance EV Root CA),您的连接将是 OK
- 如果您不使用
Certificate pinning
并且您的 default system certificate trustore
是 not working
,您的连接将 FAIL
- 如果您使用证书固定并且您的默认系统证书托管正在工作(使用 Digicert High Assurance EV 根 CA),您的连接将 OK
- 如果您使用
Certificate pinning
并且您的 default system certificate trustore
是 not working
,您的连接将 FAIL
- 如果您使用
Certificate pinning
并且您的 default system certificate trustore
是 not working
并且您设置了 custom trustore with the digicert CA
您的连接将是 OK
- 如果您使用
Certificate pinning
和您的 default system certificate trustore is not working
并且您 setup a custom trustore without the digicert CA
您的连接将 FAIL
使用证书固定 + sslSocketFactory + 自定义信任管理器的示例 (Java)(基于 OkHttp3 CustomTrust example)
(digicert.cer 包含 Digicert High Assurance EV Root CA)
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.util.Arrays;
import java.util.Collection;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
import org.junit.Test;
import junit.framework.TestCase;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.CertificatePinner;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public class OkHttpTest extends TestCase {
@Test
public void test() {
try {
CertificatePinner certificatePinner = new CertificatePinner.Builder()
.add("github.com", "sha256/WoiWRyIOVNa9ihaBciRSC7XHjliYS9VwUGOIud4PB18=").build();
X509TrustManager trustManager;
SSLSocketFactory sslSocketFactory;
try {
trustManager = trustManagerForCertificates(new FileInputStream(new File("/tmp/digicert.cer")));
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[] { trustManager }, null);
sslSocketFactory = sslContext.getSocketFactory();
} catch (GeneralSecurityException e) {
throw new RuntimeException(e);
}
OkHttpClient client = new OkHttpClient.Builder().sslSocketFactory(sslSocketFactory, trustManager)
.certificatePinner(certificatePinner).build();
Request request = new Request.Builder().url("https://github.com/square/okhttp/wiki/HTTPS").build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
e.printStackTrace();
}
@Override
public void onResponse(Call call, Response response) throws IOException {
System.out.println("onResponse: " + response.body().string());
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
private X509TrustManager trustManagerForCertificates(InputStream in) throws GeneralSecurityException {
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
Collection<? extends Certificate> certificates = certificateFactory.generateCertificates(in);
if (certificates.isEmpty()) {
throw new IllegalArgumentException("expected non-empty set of trusted certificates");
}
// Put the certificates a key store.
char[] password = "password".toCharArray(); // Any password will work.
KeyStore keyStore = newEmptyKeyStore(password);
int index = 0;
for (Certificate certificate : certificates) {
String certificateAlias = Integer.toString(index++);
keyStore.setCertificateEntry(certificateAlias, certificate);
}
// Use it to build an X509 trust manager.
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, password);
TrustManagerFactory trustManagerFactory = TrustManagerFactory
.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
throw new IllegalStateException("Unexpected default trust managers:" + Arrays.toString(trustManagers));
}
return (X509TrustManager) trustManagers[0];
}
private KeyStore newEmptyKeyStore(char[] password) throws GeneralSecurityException {
try {
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
InputStream in = null;
keyStore.load(in, password);
return keyStore;
} catch (IOException e) {
throw new AssertionError(e);
}
}
}
其实这周我也有和下面的问题一样的问题
在我的 phone(摩托罗拉,Android 4.1.2)中,我禁用了所有 DigiCert CA(在 Settings - Security - Trusted credentials - System
内)。
我的代码如下:
public class CertPinActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_cert_pin);
try {
CertificatePinner certificatePinner = new CertificatePinner.Builder()
.add("github.com", "sha256/WoiWRyIOVNa9ihaBciRSC7XHjliYS9VwUGOIud4PB18=")
.build();
OkHttpClient client = new OkHttpClient.Builder()
.sslSocketFactory(getSSLSocketFactory())
.certificatePinner(certificatePinner)
.build();
Request request = new Request.Builder()
.url("https://github.com/square/okhttp/wiki/HTTPS")
.build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.e("onFailure","-------------------------------------------------");
e.printStackTrace();
}
@Override
public void onResponse(Call call, Response response) throws IOException {
Log.d("onResponse", response.body().string());
}
});
} catch (Exception e){
e.printStackTrace();
}
}
private SSLSocketFactory getSSLSocketFactory()
throws CertificateException, KeyStoreException, IOException,
NoSuchAlgorithmException, KeyManagementException {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream caInput = getResources().openRawResource(R.raw.github); // this is exported from Chrome then stored inside \app\src\main\res\raw path
Certificate ca = cf.generateCertificate(caInput);
caInput.close();
KeyStore keyStore = KeyStore.getInstance("BKS");
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, tmf.getTrustManagers(), null);
return sslContext.getSocketFactory();
}
}
我的应用程序得到了以下 logcat(对不起,我 t运行 分类,因为它太长了)
06-14 09:10:10.065 30176-30211/com.example.okhttps3 E/onFailure: -------------------------------------------------
06-14 09:10:10.065 30176-30211/com.example.okhttps3 W/System.err: javax.net.ssl.SSLPeerUnverifiedException: Failed to find a trusted cert that signed X.509 Certificate:
06-14 09:10:10.065 30176-30211/com.example.okhttps3 W/System.err: [
06-14 09:10:10.065 30176-30211/com.example.okhttps3 W/System.err: [
06-14 09:10:10.065 30176-30211/com.example.okhttps3 W/System.err: Version: V3
06-14 09:10:10.065 30176-30211/com.example.okhttps3 W/System.err: Subject: CN=DigiCert SHA2 Extended Validation Server CA,OU=www.digicert.com,O=DigiCert Inc,C=US
06-14 09:10:10.065 30176-30211/com.example.okhttps3 W/System.err: Signature Algorithm: SHA256WithRSAEncryption, params unparsed, OID = 1.2.840.113549.1.1.11
06-14 09:10:10.065 30176-30211/com.example.okhttps3 W/System.err: Key:
...................................................................................
06-14 09:17:56.813 5934-5984/com.example.okhttps3 W/System.err: at okhttp3.internal.tls.CertificateChainCleaner$BasicCertificateChainCleaner.clean(CertificateChainCleaner.java:132)
06-14 09:17:56.813 5934-5984/com.example.okhttps3 W/System.err: at okhttp3.CertificatePinner.check(CertificatePinner.java:149)
06-14 09:17:56.813 5934-5984/com.example.okhttps3 W/System.err: at okhttp3.internal.io.RealConnection.connectTls(RealConnection.java:252)
06-14 09:17:56.823 5934-5984/com.example.okhttps3 W/System.err: at okhttp3.internal.io.RealConnection.establishProtocol(RealConnection.java:196)
06-14 09:17:56.823 5934-5984/com.example.okhttps3 W/System.err: at okhttp3.internal.io.RealConnection.buildConnection(RealConnection.java:171)
06-14 09:17:56.823 5934-5984/com.example.okhttps3 W/System.err: at okhttp3.internal.io.RealConnection.connect(RealConnection.java:111)
06-14 09:17:56.823 5934-5984/com.example.okhttps3 W/System.err: at okhttp3.internal.http.StreamAllocation.findConnection(StreamAllocation.java:187)
06-14 09:17:56.823 5934-5984/com.example.okhttps3 W/System.err: at okhttp3.internal.http.StreamAllocation.findHealthyConnection(StreamAllocation.java:123)
06-14 09:17:56.823 5934-5984/com.example.okhttps3 W/System.err: at okhttp3.internal.http.StreamAllocation.newStream(StreamAllocation.java:93)
06-14 09:17:56.823 5934-5984/com.example.okhttps3 W/System.err: at okhttp3.internal.http.HttpEngine.connect(HttpEngine.java:296)
06-14 09:17:56.823 5934-5984/com.example.okhttps3 W/System.err: at okhttp3.internal.http.HttpEngine.sendRequest(HttpEngine.java:248)
06-14 09:17:56.823 5934-5984/com.example.okhttps3 W/System.err: at okhttp3.RealCall.getResponse(RealCall.java:243)
06-14 09:17:56.823 5934-5984/com.example.okhttps3 W/System.err: at okhttp3.RealCall$ApplicationInterceptorChain.proceed(RealCall.java:201)
06-14 09:17:56.823 5934-5984/com.example.okhttps3 W/System.err: at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:163)
06-14 09:17:56.823 5934-5984/com.example.okhttps3 W/System.err: at okhttp3.RealCall.access0(RealCall.java:30)
06-14 09:17:56.823 5934-5984/com.example.okhttps3 W/System.err: at okhttp3.RealCall$AsyncCall.execute(RealCall.java:127)
06-14 09:17:56.823 5934-5984/com.example.okhttps3 W/System.err: at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
06-14 09:17:56.823 5934-5984/com.example.okhttps3 W/System.err: at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
06-14 09:17:56.823 5934-5984/com.example.okhttps3 W/System.err: at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
06-14 09:17:56.823 5934-5984/com.example.okhttps3 W/System.err: at java.lang.Thread.run(Thread.java:856)
但是,onResponse
在以下情况下调用:
.sslSocketFactory(getSSLSocketFactory())
和.certificatePinner(certificatePinner)
都删除了;- 仅删除
.sslSocketFactory(getSSLSocketFactory())
; (实际上,使用模拟器,当系统 CA 禁用时,onFailure
调用并在其中java.security.cert.CertPathValidatorException: Trust anchor for certification path not found
抛出) - 只删除了
.certificatePinner(certificatePinner)
。
Logcat 和 onResponse
如下(太长所以我 t运行cate):
06-14 09:06:23.143 26571-26616/com.example.okhttps3 D/onResponse: <!DOCTYPE html>
<html lang="en" class="">
.....
所以,我的问题是:
- 和我问题开头的link一样(实际上是他的第1期);
- 当
certificatePinner
与getSSLSocketFactory
一起使用时,为什么我的应用程序得到javax.net.ssl.SSLPeerUnverifiedException: Failed to find a trusted cert that signed X.509 Certificate
?请注意,此SSLPeerUnverifiedException
的内部消息与 this JavaDoc 中提到的Certificate pinning failure!
不同。
更新:
第一期:
看起来这个问题(System/User 受信任的凭据无效)只发生在我的 phone 中 运行 Android 4.1.2,我检查了 02 台设备,所以我想我应该联系制造商。
第 2 期:
根据下面@Robert的评论"I assume you have to include the full certificate chain (or the root certificate if the server sends you the chain), not only the leave certificate"
,我改为导出Root CA,如下截图,虽然没有完成链,在getSSLSocketFactory
里面我改为getResources().openRawResource(R.raw.github_rootca);
现在,我的第二个问题解决了!
证书固定是一种额外的安全措施,因此证书必须受到使用的 TrustManager 的信任并且它必须与固定的证书相匹配。
由于您禁用了 DigiCert CA 证书,因此该证书不受所起诉的 TrustManager 的信任,因此您会收到 SSLPeerUnverifiedException。
我描述的行为记录在 CertificatePinner 的 JavaDoc 中:
Note about self-signed certificates
CertificatePinner can not be used to pin self-signed certificate if such certificate is not accepted by TrustManager.
如果您禁用默认系统证书 trustore,(使用或不使用没有自定义 trustore 的证书固定)您将始终遇到异常,因为将无法验证对等证书,因此
- 如果您不使用
Certificate pinning
并且您的default system certificate trustore
是working
(使用 Digicert High Assurance EV Root CA),您的连接将是 OK - 如果您不使用
Certificate pinning
并且您的default system certificate trustore
是not working
,您的连接将 FAIL - 如果您使用证书固定并且您的默认系统证书托管正在工作(使用 Digicert High Assurance EV 根 CA),您的连接将 OK
- 如果您使用
Certificate pinning
并且您的default system certificate trustore
是not working
,您的连接将 FAIL - 如果您使用
Certificate pinning
并且您的default system certificate trustore
是not working
并且您设置了custom trustore with the digicert CA
您的连接将是 OK - 如果您使用
Certificate pinning
和您的default system certificate trustore is not working
并且您setup a custom trustore without the digicert CA
您的连接将 FAIL
使用证书固定 + sslSocketFactory + 自定义信任管理器的示例 (Java)(基于 OkHttp3 CustomTrust example)
(digicert.cer 包含 Digicert High Assurance EV Root CA)
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.util.Arrays;
import java.util.Collection;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
import org.junit.Test;
import junit.framework.TestCase;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.CertificatePinner;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public class OkHttpTest extends TestCase {
@Test
public void test() {
try {
CertificatePinner certificatePinner = new CertificatePinner.Builder()
.add("github.com", "sha256/WoiWRyIOVNa9ihaBciRSC7XHjliYS9VwUGOIud4PB18=").build();
X509TrustManager trustManager;
SSLSocketFactory sslSocketFactory;
try {
trustManager = trustManagerForCertificates(new FileInputStream(new File("/tmp/digicert.cer")));
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[] { trustManager }, null);
sslSocketFactory = sslContext.getSocketFactory();
} catch (GeneralSecurityException e) {
throw new RuntimeException(e);
}
OkHttpClient client = new OkHttpClient.Builder().sslSocketFactory(sslSocketFactory, trustManager)
.certificatePinner(certificatePinner).build();
Request request = new Request.Builder().url("https://github.com/square/okhttp/wiki/HTTPS").build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
e.printStackTrace();
}
@Override
public void onResponse(Call call, Response response) throws IOException {
System.out.println("onResponse: " + response.body().string());
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
private X509TrustManager trustManagerForCertificates(InputStream in) throws GeneralSecurityException {
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
Collection<? extends Certificate> certificates = certificateFactory.generateCertificates(in);
if (certificates.isEmpty()) {
throw new IllegalArgumentException("expected non-empty set of trusted certificates");
}
// Put the certificates a key store.
char[] password = "password".toCharArray(); // Any password will work.
KeyStore keyStore = newEmptyKeyStore(password);
int index = 0;
for (Certificate certificate : certificates) {
String certificateAlias = Integer.toString(index++);
keyStore.setCertificateEntry(certificateAlias, certificate);
}
// Use it to build an X509 trust manager.
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, password);
TrustManagerFactory trustManagerFactory = TrustManagerFactory
.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
throw new IllegalStateException("Unexpected default trust managers:" + Arrays.toString(trustManagers));
}
return (X509TrustManager) trustManagers[0];
}
private KeyStore newEmptyKeyStore(char[] password) throws GeneralSecurityException {
try {
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
InputStream in = null;
keyStore.load(in, password);
return keyStore;
} catch (IOException e) {
throw new AssertionError(e);
}
}
}