我使用okHTTP将HTTPS请求发送到我的Android应用程序中的服务器。适用于Android版本>果冻豆,但果冻豆引发了以下异常:
javax.net.ssl.SSLHandshakeException: com.android.org.bouncycastle.jce.exception.ExtCertPathValidatorException: Certificate has unsupported critical extension
10-04 12:45:01.391 7570-7735/mop.orange.com.moplibapptest5 I/System.out: at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:374)
10-04 12:45:01.391 7570-7735/mop.orange.com.moplibapptest5 I/System.out: at okhttp3.internal.connection.RealConnection.connectTls(RealConnection.java:241)
它似乎与SSL / TLS服务器证书相关联,该证书包含2个带有“严重”标记的扩展名。我无法更改此证书,因为服务器不是我的。
我尝试启用/禁用TLS Extensions支持,但行为是相同的:(
ConnectionSpec connSpec = new ConnectionSpec.Builder(ConnectionSpec.COMPATIBLE_TLS)
.supportsTlsExtensions(false)
.build();
OkHttpClient.Builder()
.connectionSpecs(Collections.singletonList(connSpec))
你知道我怎么能在okHTTP(或似乎在下面的Bouncy Castle)中禁用关键扩展检查?
答案 0 :(得分:2)
我使用okHTTP way到customize可信证书,然后我将TrustManager和证书包装起来,以返回关键扩展的空列表。
以下是TrustManager包装时的Jelly Bean类:
if(trustManagers[0].getClass().toString().equals("class org.apache.harmony.xnet.provider.jsse.TrustManagerImpl")) {
logger.debug("Wrapping TrustManager to return no critical extension");
return new TrustManagerNoCritical((X509TrustManager) trustManagers[0]);
}
这是用于包装链中证书的TrustManager包装类:
public class TrustManagerNoCritical implements X509TrustManager {
protected X509TrustManager trustManager;
public TrustManagerNoCritical(X509TrustManager realTrustManager) {
trustManager = realTrustManager;
}
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
trustManager.checkClientTrusted(chain, authType);
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
List<X509Certificate> certifs = new ArrayList<X509Certificate>();
for (X509Certificate certif : chain) {
certifs.add(new CertificateNoCritical(certif));
}
X509Certificate[] newChain = new X509Certificate[certifs.size()];
newChain = certifs.toArray(newChain);
trustManager.checkServerTrusted(newChain, authType);
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return trustManager.getAcceptedIssuers();
}
}
这是一个证书类,用于包装真实证书并且不返回任何关键扩展名:
public class CertificateNoCritical extends X509Certificate {
protected X509Certificate certif;
public CertificateNoCritical(X509Certificate certificateToWrap) {
certif = certificateToWrap;
}
@Override
public boolean hasUnsupportedCriticalExtension() {
return certif.hasUnsupportedCriticalExtension();
}
@Override
public Set<String> getCriticalExtensionOIDs() {
// Return empty Set to avoid "critical extension" Exception
return new HashSet<String>();
}
@Override
public Set<String> getNonCriticalExtensionOIDs() {
return certif.getNonCriticalExtensionOIDs();
}
@Override
public byte[] getExtensionValue(String oid) {
return certif.getExtensionValue(oid);
}
@Override
public void checkValidity() throws CertificateExpiredException, CertificateNotYetValidException {
certif.checkValidity();
}
@Override
public void checkValidity(Date date) throws CertificateExpiredException, CertificateNotYetValidException {
certif.checkValidity(date);
}
@Override
public int getVersion() {
return certif.getVersion();
}
@Override
public BigInteger getSerialNumber() {
return certif.getSerialNumber();
}
@Override
public Principal getIssuerDN() {
return certif.getIssuerDN();
}
@Override
public Principal getSubjectDN() {
return certif.getSubjectDN();
}
@Override
public Date getNotBefore() {
return certif.getNotBefore();
}
@Override
public Date getNotAfter() {
return certif.getNotAfter();
}
@Override
public byte[] getTBSCertificate() throws CertificateEncodingException {
return certif.getTBSCertificate();
}
@Override
public byte[] getSignature() {
return certif.getSignature();
}
@Override
public String getSigAlgName() {
return certif.getSigAlgName();
}
@Override
public String getSigAlgOID() {
return certif.getSigAlgOID();
}
@Override
public byte[] getSigAlgParams() {
return certif.getSigAlgParams();
}
@Override
public boolean[] getIssuerUniqueID() {
return certif.getIssuerUniqueID();
}
@Override
public boolean[] getSubjectUniqueID() {
return certif.getSubjectUniqueID();
}
@Override
public boolean[] getKeyUsage() {
return certif.getKeyUsage();
}
@Override
public int getBasicConstraints() {
return certif.getBasicConstraints();
}
@Override
public byte[] getEncoded() throws CertificateEncodingException {
return certif.getEncoded();
}
@Override
public void verify(PublicKey key) throws CertificateException, NoSuchAlgorithmException, InvalidKeyException,
NoSuchProviderException, SignatureException {
certif.verify(key);
}
@Override
public void verify(PublicKey key, String sigProvider) throws CertificateException, NoSuchAlgorithmException,
InvalidKeyException, NoSuchProviderException, SignatureException {
certif.verify(key, sigProvider);
}
@Override
public String toString() {
return certif.toString();
}
@Override
public PublicKey getPublicKey() {
return certif.getPublicKey();
}
}