You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

证书固定实现遇阻:SSLPeerUnverifiedException问题求助

Fixing javax.net.ssl.SSLPeerUnverifiedException During Certificate Pinning

Hey there, let's break down what's going on with your certificate pinning setup and that frustrating error message: Failed to find a trusted cert that signed. I'll walk you through why this happens and how to fix it—plus, I'll address that "trust all certificates" approach (with a big warning about production use).

Why the Exception Happens

This error pops up when OkHttp's CertificatePinner can't find any certificate in the server's returned chain that matches the SHA-256 hash you specified. Either your hash is incorrect, or you're only pinning the leaf certificate but the server is presenting a chain with intermediate/root certs that you haven't accounted for.

Step 1: Verify Your Certificate Hash is Correct

First things first—make sure you're using the right SHA-256 hash for the target server's certificate (or one in its trust chain). Here's how to get the correct value:

  • Via Browser & Command Line: Visit https://*.percolate.com in your browser, export the certificate, then run this command to calculate its hash:
    openssl x509 -in your-exported-cert.crt -pubkey -noout | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64
    
  • Via OkHttp Logs: Temporarily remove the CertificatePinner from your client setup, then run your app. OkHttp will log the actual hashes from the server's certificate chain in an error message (even if you're trusting all certs). Copy those valid hashes directly into your pinning configuration—this is the most reliable method.

Blindly trusting all certificates is a huge security risk (it opens your app to man-in-the-middle attacks), so let's start with the secure fix first:

// Pin multiple certificates in the chain for better compatibility
CertificatePinner certificatePinner = new CertificatePinner.Builder()
    // Add the leaf certificate hash (replace with your verified value)
    .add("*.percolate.com", "sha256/gd0jw5Y5beTzcXkn1mrr9b+Dri2kx2IIkML8vU5Xz04=")
    // Add intermediate/root certificate hashes (get these from OkHttp logs or browser)
    .add("*.percolate.com", "sha256/VALID_INTERMEDIATE_HASH=")
    .add("*.percolate.com", "sha256/VALID_ROOT_HASH=")
    .build();

OkHttpClient client = new OkHttpClient.Builder()
    .certificatePinner(certificatePinner)
    .build();

Pinning multiple certs in the chain prevents failures if the server rotates its leaf certificate but keeps the same intermediate/root certs.

Step 3: Trust All Certificates (Only for Testing!)

If you absolutely need to trust all certificates for testing purposes only (never use this in production), you need to configure a custom X509TrustManager and SSLSocketFactory alongside your certificate pinner. Here's how:

// Custom trust manager that trusts every certificate
X509TrustManager trustAllCerts = new X509TrustManager() {
    @Override
    public void checkClientTrusted(X509Certificate[] chain, String authType) {}

    @Override
    public void checkServerTrusted(X509Certificate[] chain, String authType) {}

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

// Create SSL context with our trust manager
SSLContext sslContext;
try {
    sslContext = SSLContext.getInstance("TLS");
    sslContext.init(null, new TrustManager[]{trustAllCerts}, new SecureRandom());
} catch (NoSuchAlgorithmException | KeyManagementException e) {
    throw new RuntimeException("Failed to create SSL context", e);
}
SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();

// Build the OkHttpClient with pinning + trust-all setup
CertificatePinner certificatePinner = new CertificatePinner.Builder()
    .add("*.percolate.com", "sha256/gd0jw5Y5beTzcXkn1mrr9b+Dri2kx2IIkML8vU5Xz04=")
    .build();

OkHttpClient client = new OkHttpClient.Builder()
    .certificatePinner(certificatePinner)
    .sslSocketFactory(sslSocketFactory, trustAllCerts)
    .hostnameVerifier((hostname, session) -> true) // Skip hostname check (unsafe!)
    .build();

Again—this is not safe for production. Attackers can easily intercept your app's traffic if you use this setup.

Key Takeaways

  • Always verify your certificate hashes before pinning—OkHttp's error logs are your best friend here.
  • Pin multiple certificates in the trust chain to avoid breakage when servers rotate certs.
  • Never use a "trust all certificates" setup in production—it defeats the entire purpose of SSL/TLS.

内容的提问来源于stack exchange,提问作者M.P.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 06:38:35