【问题标题】:How to disable ssl critical extension check in Android?如何在 Android 中禁用 ssl 关键扩展检查?
【发布时间】:2017-02-16 03:56:38
【问题描述】:

我使用 okHTTP 向我的 Android 应用程序中的服务器发送 HTTPS 请求。 Android版本> Jelly Bean没问题,但是Jelly Bean会抛出以下异常:

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 扩展支持,但行为相同:(

ConnectionSpec connSpec = new ConnectionSpec.Builder(ConnectionSpec.COMPATIBLE_TLS)
     .supportsTlsExtensions(false)
     .build();

OkHttpClient.Builder()
    .connectionSpecs(Collections.singletonList(connSpec))

您知道如何禁用 okHTTP(或似乎在下面的 Bouncy Castle)中的关键扩展检查吗?

【问题讨论】:

    标签: android ssl bouncycastle okhttp


    【解决方案1】:

    我使用okHTTP waycustomize 受信任的证书,然后我包装 TrustManager 和证书以返回关键扩展的空列表。

    这是一个果冻豆类时的 TrustManager 包装:

            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();
    }
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-21
      • 1970-01-01
      • 1970-01-01
      • 2023-03-27
      • 1970-01-01
      • 2014-12-10
      相关资源
      最近更新 更多