美文网首页
在Android遇到Https一些知识点与问题

在Android遇到Https一些知识点与问题

作者: 侯大虎虎 | 来源:发表于2017-10-27 18:36 被阅读0次

    一些知识点

    1.服务端生成证书文件,其实只需要利用keyTool工具生成jks后,再利用KeyTool工具根据这个jks去签发出来一个证书就可以了。具体步骤为
    1. 通过keytool命令生成 jks 秘钥文件
    keytool -genkey -alias zhy_server
     -keyalg RSA -keystore zhy_server.jks
     -validity 3600 -storepass 123456
    
    2. 通过keytool命令对 jks 进行签发证书
    keytool -export -alias zhy_server 
     -file zhy_server.cer  
     -keystore zhy_server.jks  
     -storepass 123456 
    
    
    2.在加载证书的代码中,Java平台默认识别jks格式的证书文件,但是android平台只识别bks格式的证书文件。所以你需要将'jks'转换成bks文件,放入项目中。
    3.加载证书有两种实现方式(访问自签名的网站,单向验证):
    1.你可以通过将证书文件.cer放入到项目可读取的位置,如'assest'文件夹。
    private static SSLSocketFactory getSSLSocketFactory_Certificate(Context context, String keyStoreType, int keystoreResId)
                throws CertificateException, KeyStoreException, IOException, NoSuchAlgorithmException, KeyManagementException {
    
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
    
            InputStream caInput = context.getResources().openRawResource(keystoreResId);
    
            Certificate ca = cf.generateCertificate(caInput);
    
            caInput.close();
    
            if (keyStoreType == null || keyStoreType.length() == 0) {
    
                keyStoreType = KeyStore.getDefaultType();
    
            }
    
            KeyStore keyStore = KeyStore.getInstance(keyStoreType);
    
            keyStore.load(null, null);
    
            keyStore.setCertificateEntry("ca", ca);
    
            String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
    
            TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
    
            tmf.init(keyStore);
    
            TrustManager[] wrappedTrustManagers = getWrappedTrustManagers(tmf.getTrustManagers());
    
            SSLContext sslContext = SSLContext.getInstance("TLS");
    
            sslContext.init(null, wrappedTrustManagers, null);
    
            return sslContext.getSocketFactory();
    
        }
    
    
    2.你可以通过keytool命令,将.cer文件以.rfc格式输出(其实也就是文本格式),然后加载这段文本就行。
    keytool -printcert -rfc -file srca.cer
    
    4.Android中 自带的SSLContext的TrustManager无法进行工作,具体原因目前不清楚,可能是自带的TrustManager的内部实现不符合场景需求。

    TrustManager的主要责任是去决定提出的认证证书应该是可信任的。如果证书是不可信任的,那么连接将会被终止

    完整加载证书代码:

     private static TrustManager[] getWrappedTrustManagers(TrustManager[] trustManagers) {
    
            final X509TrustManager originalTrustManager = (X509TrustManager) trustManagers[0];
    
            return new TrustManager[]{
    
                    new X509TrustManager() {
    
                        public X509Certificate[] getAcceptedIssuers() {
    
                            return originalTrustManager.getAcceptedIssuers();
    
                        }
    
                        public void checkClientTrusted(X509Certificate[] certs, String authType) {
    
                            try {
    
                                originalTrustManager.checkClientTrusted(certs, authType);
    
                            } catch (CertificateException e) {
    
                                e.printStackTrace();
    
                            }
    
                        }
    
                        public void checkServerTrusted(X509Certificate[] certs, String authType) {
    
                            try {
    
                                originalTrustManager.checkServerTrusted(certs, authType);
    
                            } catch (CertificateException e) {
    
                                e.printStackTrace();
    
                            }
    
                        }
    
                    }
    
            };
    
        }
        /**
         *
         * @param context
         * @param keyStoreType   Keystore类型,一般都是jks 或者 bks,but,Android平台只识别bks,所以如果你要做这种
         *                       加密通信的话,你需要将你的秘钥转成bks格式
         * @param keystoreResId
         * @return
         * @throws CertificateException
         * @throws KeyStoreException
         * @throws IOException
         * @throws NoSuchAlgorithmException
         * @throws KeyManagementException
         */
        private static SSLSocketFactory getSSLSocketFactory_Certificate(Context context, String keyStoreType, int keystoreResId)
                throws CertificateException, KeyStoreException, IOException, NoSuchAlgorithmException, KeyManagementException {
    
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
    
            InputStream caInput = context.getResources().openRawResource(keystoreResId);
    
            Certificate ca = cf.generateCertificate(caInput);
    
            caInput.close();
    
            if (keyStoreType == null || keyStoreType.length() == 0) {
    
                keyStoreType = KeyStore.getDefaultType();
    
            }
    
            KeyStore keyStore = KeyStore.getInstance(keyStoreType);
    
            keyStore.load(null, null);
    
            keyStore.setCertificateEntry("ca", ca);
    
            String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
    
            TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
    
            tmf.init(keyStore);
    
            TrustManager[] wrappedTrustManagers = getWrappedTrustManagers(tmf.getTrustManagers());
    
            SSLContext sslContext = SSLContext.getInstance("TLS");
    
            sslContext.init(null, wrappedTrustManagers, null);
    
            return sslContext.getSocketFactory();
    
        }
    
    
    5. 默认信任所有证书

    上面的代码都是在有证书的条件下,而如果没有证书呢?如果跳过这个环节还保证不出错?那么只能信任所有的证书

     client.sslSocketFactory(createSSLSocketFactory());
            client.hostnameVerifier(new TrustAllHostnameVerifier());
            
            
            
              private static class TrustAllManager implements X509TrustManager {
            @Override
            public void checkClientTrusted(X509Certificate[] chain, String authType)
                    throws CertificateException {
            }
    
            @Override
            public void checkServerTrusted(X509Certificate[] chain, String authType)
    
                    throws CertificateException {
            }
    
            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return new X509Certificate[0];
            }
        }
    
        private static class TrustAllHostnameVerifier implements HostnameVerifier {
            @Override
            public boolean verify(String hostname, SSLSession session) {
                return true;
            }
        }
    

    相关文章

      网友评论

          本文标题:在Android遇到Https一些知识点与问题

          本文链接:https://www.haomeiwen.com/subject/fizudxtx.html