美文网首页
Android 双向认证

Android 双向认证

作者: azu_test | 来源:发表于2022-03-28 10:27 被阅读0次

1、需求,使用以下三个文件做双向认证

a. 服务端证书文件
b. 客户端证书文件
c. 私钥

2、代码实现

import android.content.Context;

import org.bouncycastle.openssl.PEMKeyPair;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.SecureRandom;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.util.Arrays;
import java.util.Collection;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;

import okhttp3.OkHttpClient;

/**
 * @author azu
 * @data
 * @describe
 */
public class NetworkVerifier {
    private final static String CERTIFICATE_STANDARD = "X.509";
    //私钥
    private final static String CLIENT_PRIVATE_KEY = "cloud.com.key";
    private final static String SERVER = "server";
    //服务端证书
    private final static String SERVER_CERTIFICATE = "Root.pem";
    private final static String CLIENT = "client";
    //客户端证书
    private final static String CLIENT_CERTIFICATE = "cloud.com.crt";
    private final static String PROTOCOL_TYPE = "TLS";

    private static KeyStore getServerKeyStore(Context context) {
        try {
            CertificateFactory certificateFactory = CertificateFactory.getInstance(CERTIFICATE_STANDARD);
            // 从文件中获取
            InputStream inputStream = context.getAssets().open(SERVER_CERTIFICATE);
            Collection<Certificate> certificateCollection = (Collection<Certificate>) certificateFactory.generateCertificates(inputStream);
            Certificate[] certificates = new Certificate[certificateCollection.size()];

            KeyStore clientKeyStore = KeyStore.getInstance(KeyStore.getDefaultType());
            clientKeyStore.load(null);

            int i = 0;
            for (Certificate certificate : certificateCollection) {
                certificates[i++] = certificate;
                clientKeyStore.setCertificateEntry(SERVER + i, certificate);
            }
            inputStream.close();
            return clientKeyStore;
        } catch (CertificateException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (KeyStoreException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return null;
    }

    private static KeyStore getClientKeyStore(Context context) {
        try {
            CertificateFactory certificateFactory = CertificateFactory.getInstance(CERTIFICATE_STANDARD);
            // 从文件中获取
            InputStream inputStream = context.getAssets().open(CLIENT_CERTIFICATE);
            Collection<Certificate> certificateCollection = (Collection<Certificate>) certificateFactory.generateCertificates(inputStream);
            Certificate[] certificates = new Certificate[certificateCollection.size()];

            KeyStore serverKeyStore = KeyStore.getInstance(KeyStore.getDefaultType());
            serverKeyStore.load(null);

            int i = 0;
            for (Certificate certificate : certificateCollection) {
                certificates[i++] = certificate;
                serverKeyStore.setCertificateEntry(CLIENT + i, certificate);
            }
            inputStream.close();

            InputStream rsaInputStream = context.getAssets().open(CLIENT_PRIVATE_KEY);
            PEMParser pemParser = new PEMParser(new InputStreamReader(rsaInputStream));
            PEMKeyPair kp = (PEMKeyPair) pemParser.readObject();
            JcaPEMKeyConverter converter = new JcaPEMKeyConverter();
            PrivateKey privateKey = converter.getKeyPair(kp).getPrivate();

            serverKeyStore.setKeyEntry(CLIENT, privateKey, null//"123456".toCharArray()
                    , certificates);
            rsaInputStream.close();
            return serverKeyStore;
        } catch (CertificateException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyStoreException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static void addSSL(Context context, OkHttpClient.Builder builder) {
        try {
            KeyStore clientKeyStore = getClientKeyStore(context);
            KeyStore serverKeyStore = getServerKeyStore(context);

            KeyManagerFactory keyManagerFactory =
                    KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
            keyManagerFactory.init(clientKeyStore, null/*"123456".toCharArray()*/);

            TrustManagerFactory trustManagerFactory =
                    TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
            trustManagerFactory.init(serverKeyStore);
            TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
            if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
                throw new IllegalStateException("Unexpected default trust managers:"
                        + Arrays.toString(trustManagers));
            }
            X509TrustManager trustManager = (X509TrustManager) trustManagers[0];

            //SSLContext
            SSLContext sslContext = SSLContext.getInstance(PROTOCOL_TYPE);
            sslContext.init(keyManagerFactory.getKeyManagers(), trustManagers, new SecureRandom());
            builder.sslSocketFactory(sslContext.getSocketFactory(), trustManager);
            builder.hostnameVerifier(new HostnameVerifier() {
                @Override
                public boolean verify(String hostname, SSLSession session) {
                    //强行返回true 即验证成功
                    return true;
                }
            });
        } catch (UnrecoverableKeyException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyStoreException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        }
    }
}

3、依赖包,百度查找吧

1、bcpkix-jdk15on-1.54.jar
2、bcprov-jdk15on-1.54.jar

相关文章

网友评论

      本文标题:Android 双向认证

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