当前位置:   article > 正文

Android平台实现双向证书(https)验证简单说明_jks转bks工具

jks转bks工具

Android平台实现双向证书(https)验证简单说明

前言

  • Android端实现双向认证的难点主要在于Android接受的证书格式是BKS,而一般提供的证书不包含此格式,需要手动转换
  • 转换之后如果请求不了,表现为握手失败(Handshake failed),则一般是证书转换错误
  • 网上有一大堆转换方法,有的虽能正常生成BKS证书,但还是导致握手失败,推测应该还是转换方式有误
  • 在这里提供一种自己亲自试验过能正常转换的方法供大家参考

证书转换

使用转换工具

  • 在这里提供一个比较好用的转换工具Portecle
  • 下载完后解压双击start.bat即可使用,至于详细使用请自行百度
  • 使用此工具可以很方便地将jks转为bks

通过openssl和keytool转换

  • openssl可以到官网下载,openssl暂时没有windows版,大伙可以在此处下载Win32OpenSSLwindows版本
  • 下载完记得配置环境变量,同时也记得配置jdk的环境变量,因为后面需要用到keytool命令
  • 现在假设你拿到了客户端证书client.crt和client.key(或者client.pem和client.key)
  • 通过以下命令生成pfx文件,期间会让输入密码,输入你想要的密码即可,假如这里输入的是123456

openssl pkcs12 -export -out client.pfx -inkey client.key -in client.pem
或者
openssl pkcs12 -export -out client.pfx -inkey client.key -in client.crt

  • 执行成功则可以看到client.pfx文件,接着再执行如下命令

keytool -importkeystore -srckeystore client.pfx -destkeystore client.jks -srcstoretype PKCS12 -deststoretype JKS

  • 执行成功即可看到生成了client.jks
  • 拿到生成的jks就可以通过Portecle工具转换成bks了

代码实现

SSLHelper.java

import android.content.Context;

import java.io.IOException;
import java.io.InputStream;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;

public class SSLHelper {
    private static final String TAG = "SSLHelper";
    private final static String CLIENT_PRI_KEY = "client.bks";
    private final static String TRUSTSTORE_PUB_KEY = "ca.bks";
    private final static String CLIENT_BKS_PASSWORD = "123456";
    private final static String TRUSTSTORE_BKS_PASSWORD = "123456";
    private final static String KEYSTORE_TYPE = "BKS";
    private final static String PROTOCOL_TYPE = "TLS";
    private final static String CERTIFICATE_STANDARD = "X509";

    public static SSLSocketFactory getSSLCertifcation(Context context) {
        SSLSocketFactory sslSocketFactory = null;
        try {
            // 服务器端需要验证的客户端证书,其实就是客户端的keystore
            KeyStore keyStore = KeyStore.getInstance(KEYSTORE_TYPE);
            // 客户端信任的服务器端证书
            KeyStore trustStore = KeyStore.getInstance(KEYSTORE_TYPE);

            //读取证书
            InputStream ksIn = context.getAssets().open(CLIENT_PRI_KEY);
            InputStream tsIn = context.getAssets().open(TRUSTSTORE_PUB_KEY);

            //加载证书
            keyStore.load(ksIn, CLIENT_BKS_PASSWORD.toCharArray());
            trustStore.load(tsIn, TRUSTSTORE_BKS_PASSWORD.toCharArray());
            ksIn.close();
            tsIn.close();


            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(CERTIFICATE_STANDARD);
            KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(CERTIFICATE_STANDARD);
            trustManagerFactory.init(trustStore);
            keyManagerFactory.init(keyStore, CLIENT_BKS_PASSWORD.toCharArray());

            //初始化SSLContext
            SSLContext sslContext = SSLContext.getInstance(PROTOCOL_TYPE);
            sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), new java.security.SecureRandom());

            sslSocketFactory = sslContext.getSocketFactory();
        } catch (KeyStoreException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (CertificateException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (UnrecoverableKeyException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        }
        return sslSocketFactory;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • HttpsUtil.java
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
public class HttpsUtil {  
  
    public static class SSLParams  
    {  
        public SSLSocketFactory sSLSocketFactory;  
        public X509TrustManager trustManager;  
    }  
  
    public static SSLParams getSslSocketFactory(InputStream[] certificates, InputStream bksFile, String password)  
    {  
        SSLParams sslParams = new SSLParams();  
        try  
        {  
            TrustManager[] trustManagers = prepareTrustManager(certificates);  
            KeyManager[] keyManagers = prepareKeyManager(bksFile, password);  
            SSLContext sslContext = SSLContext.getInstance("TLS");  
            X509TrustManager trustManager = null;  
            if (trustManagers != null)  
            {  
                trustManager = new MyTrustManager(chooseTrustManager(trustManagers));  
            } else  
            {  
                trustManager = new UnSafeTrustManager();  
            }  
            sslContext.init(keyManagers, new TrustManager[]{trustManager},null);  
            sslParams.sSLSocketFactory = sslContext.getSocketFactory();  
            sslParams.trustManager = trustManager;  
            return sslParams;  
        } catch (NoSuchAlgorithmException e)  
        {  
            throw new AssertionError(e);  
        } catch (KeyManagementException e)  
        {  
            throw new AssertionError(e);  
        } catch (KeyStoreException e)  
        {  
            throw new AssertionError(e);  
        }  
    }

    public static class  UnSafeHostnameVerifier implements HostnameVerifier
    {  
        @Override  
        public boolean verify(String hostname, SSLSession session)  
        {  
            return true;  
        }  
    }  
  
    public static class UnSafeTrustManager 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[]{};
        }  
    }  
  
    private static TrustManager[] prepareTrustManager(InputStream... certificates)  
    {  
        if (certificates == null || certificates.length <= 0) return null;  
        try  
        {  
  
            CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");  
            KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());  
            keyStore.load(null);  
            int index = 0;  
            for (InputStream certificate : certificates)  
            {  
                String certificateAlias = Integer.toString(index++);  
                keyStore.setCertificateEntry(certificateAlias, certificateFactory.generateCertificate(certificate));  
                try  
                {  
                    if (certificate != null)  
                        certificate.close();  
                } catch (IOException e)  
  
                {  
                }  
            }  
            TrustManagerFactory trustManagerFactory = null;  
  
            trustManagerFactory = TrustManagerFactory.  
                    getInstance(TrustManagerFactory.getDefaultAlgorithm());  
            trustManagerFactory.init(keyStore);  
  
            TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();  
  
            return trustManagers;  
        } catch (NoSuchAlgorithmException e)  
        {  
            e.printStackTrace();  
        } catch (CertificateException e)  
        {  
            e.printStackTrace();  
        } catch (KeyStoreException e)  
        {  
            e.printStackTrace();  
        } catch (Exception e)  
        {  
            e.printStackTrace();  
        }  
        return null;  
  
    }  
  
    private static KeyManager[] prepareKeyManager(InputStream bksFile, String password)  
    {  
        try  
        {  
            if (bksFile == null || password == null) return null;  
  
            KeyStore clientKeyStore = KeyStore.getInstance("BKS");  
            clientKeyStore.load(bksFile, password.toCharArray());  
            KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());  
            keyManagerFactory.init(clientKeyStore, password.toCharArray());  
            return keyManagerFactory.getKeyManagers();  
  
        } catch (KeyStoreException e)  
        {  
            e.printStackTrace();  
        } catch (NoSuchAlgorithmException e)  
        {  
            e.printStackTrace();  
        } catch (UnrecoverableKeyException e)  
        {  
            e.printStackTrace();  
        } catch (CertificateException e)  
        {  
            e.printStackTrace();  
        } catch (IOException e)  
        {  
            e.printStackTrace();  
        } catch (Exception e)  
        {  
            e.printStackTrace();  
        }  
        return null;  
    }  
  
    private static X509TrustManager chooseTrustManager(TrustManager[] trustManagers)  
    {  
        for (TrustManager trustManager : trustManagers)  
        {  
            if (trustManager instanceof X509TrustManager)  
            {  
                return (X509TrustManager) trustManager;  
            }  
        }  
        return null;  
    }  
  
  
    private static class MyTrustManager implements X509TrustManager  
    {  
        private X509TrustManager defaultTrustManager;  
        private X509TrustManager localTrustManager;  
  
        public MyTrustManager(X509TrustManager localTrustManager) throws NoSuchAlgorithmException, KeyStoreException  
        {  
            TrustManagerFactory var4 = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());  
            var4.init((KeyStore) null);  
            defaultTrustManager = chooseTrustManager(var4.getTrustManagers());  
            this.localTrustManager = localTrustManager;  
        }  
  
  
        @Override  
        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException  
        {  
  
        }  
  
        @Override  
        public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException  
        {  
            try  
            {  
                defaultTrustManager.checkServerTrusted(chain, authType);  
            } catch (CertificateException ce)  
            {  
                localTrustManager.checkServerTrusted(chain, authType);  
            }  
        }  
  
  
        @Override  
        public X509Certificate[] getAcceptedIssuers()  
        {  
            return new X509Certificate[0];  
        }  
    }  
  
}  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • retrofit调用
		//创建日志拦截器,用于日志打印
        HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
        interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        //创建okhttp
        OkHttpClient httpClient = new OkHttpClient().newBuilder()
                .addInterceptor(interceptor)
                .sslSocketFactory(SSLHelper.getSSLCertifcation(this), new HttpsUtil.UnSafeTrustManager())
                .hostnameVerifier(new HttpsUtil.UnSafeHostnameVerifier())//由于还没有域名,此处设置忽略掉域名校验
                .build();
         //创建retrofit       
        String baseUrl = "https://180.101.147.89:8743/";
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(baseUrl)
                .client(httpClient)
                //.addConverterFactory(GsonConverterFactory.create())
                .addConverterFactory(ScalarsConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 顺便贴下依赖build.gradle
apply plugin: 'com.android.application'

android {
...
}
dependencies {
    ...

    //retrofit
    implementation "com.squareup.retrofit2:retrofit:2.3.0"
    implementation "com.squareup.retrofit2:converter-scalars:2.3.0"
    implementation "com.squareup.retrofit2:converter-gson:2.3.0"
    implementation "com.squareup.okhttp3:logging-interceptor:3.8.1"    
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

参考

  • http://blog.csdn.net/zhangyong125/article/details/50402183
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/455217
推荐阅读
相关标签
  

闽ICP备14008679号