自签名证书固定不适用于Android

时间:2018-06-14 03:58:40

标签: android ssl certificate self-signed pinning

我正在尝试按照教程制作Android自签名证书固定示例 https://www.approov.io/blog/hands-on-mobile-api-security-pinning-client-connections.html

这是我实施证书固定的课程

public class App extends Application {
    final static String TAG = "App";

    OkHttpClient mClient = null;
    Picasso mDownloader = null;

    @Override
    public void onCreate() {
        super.onCreate();

        //---------------------------- Certificate Pinning -----------------------------//
        try {

            SSLContextPinner pinner = new SSLContextPinner("cert.pem");
            mClient = new OkHttpClient.Builder()
                    .sslSocketFactory(pinner.getSSLContext().getSocketFactory(), pinner.getX509TrustManager())
                    .hostnameVerifier(new NoHostnameVerifier())
                    //.addInterceptor(new ApproovInterceptor())
                    .build();
        } catch (Exception e) {
            Log.e(TAG, e.toString());
            Log.e(TAG, "Failed to pin connection");
            throw new IllegalStateException("Failed to pin connection:");
        }
        mDownloader = new Picasso.Builder(this)
                .downloader(new OkHttp3Downloader(mClient))
                .build();
    }

    /**
     * Returns a client for http requests.
     *
     * @returns an http client.
     */
    public OkHttpClient getHttpClient() {
        return mClient;
    }

    /**
     * Returns an image downloader for http requests.
     *
     * @returns an http downloader.
     */
    public Picasso getImageDownloader() {
        return mDownloader;
    }


    /**
     * Creates an SSL context useful for pinning certificates.
     */
    private class SSLContextPinner {
        private SSLContext sslContext;
        private TrustManager trustManager;

        public SSLContextPinner(String pemAssetName) {
            try {
                KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
                keyStore.load(null, null);
                InputStream certInputStream = getAssets().open(pemAssetName);
                BufferedInputStream bis = new BufferedInputStream(certInputStream);
                CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
                int idx = -1;
                while (bis.available() > 0) {
                    Certificate cert = certificateFactory.generateCertificate(bis);
                    keyStore.setCertificateEntry("" + ++idx, cert);
                    Log.i(TAG, "pinned " + idx + ": " + ((X509Certificate) cert).getSubjectDN());
                    Log.i(TAG, "ca=" + ((X509Certificate) cert).getSubjectDN());
                }
                TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
                trustManagerFactory.init(keyStore);
                TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
                trustManager = trustManagers[0];
                sslContext = SSLContext.getInstance("TLS");
                sslContext.init(null, trustManagers, null);
            } catch (Exception e) {
                sslContext = null;
                trustManager = null;
                Log.e(TAG, e.toString());
            }
        }

        public SSLContext getSSLContext() {
            return sslContext;
        }

        public X509TrustManager getX509TrustManager() {
            return (X509TrustManager) trustManager;
        }
    }

    ;

    /**
     * Passes any host name verification.
     * <p>
     * There appear to be some issues when verifying absolute IP
     * addresses when using subjectAltNames in certs, so we
     * just pass everything for demonstration purposes.
     */
    private class NoHostnameVerifier implements HostnameVerifier {
        @Override
        public boolean verify(final String hostname, final SSLSession session) {
            Log.i(TAG, "hostnameverifier: " + hostname);
            return true;
        }
    }
}

// end of file

cert.pem 是我的自签名证书(它也在我的服务器上使用)

如果我更改证书文件,我的示例不起作用。 它似乎运作正常。

但是,当我使用Package Capture应用程序(https://play.google.com/store/apps/details?id=app.greyshirts.sslcapture&hl=vi)测试我的示例时,它仍然有效。

如果我正确实施证书固定,我的应用程序在运行Package Capture时不起作用。

我希望有人可以帮我解释一下。谢谢!

0 个答案:

没有答案