Android Https自签名证书问题!

Android自签名证书问题

服务器给了一个自签名证书,ios那边可以使用,Android不能使用! 坑,自己搭服务器签名验证!,想看问题原因,直接移步最后!

生成自签名证书

//生成 rao.key,后面位数可以指定 需要设置密码,需要记住后面验证需要输入
openssl genrsa -idea -out rao.key 1024
// 生成证书请求 csr 文件,输入key密码,依次输入组织名称等信息 其中 Common Name 为域名或者ip,最后输入的密码为修改csr文件需要配置的
openssl req -new -key rao.key -out rao.csr
// 基于上面的文件生成证书,有效期一年
openssl x509 -req -days 365 -in rao.csr -signkey rao.key -out rao.crt

nginx配置https证书

//示例
server {
    ...
    listen 443;
    server_name www.rao.com;
    ssl on;
    #证书文件路径
    ssl_certificate /etc/nginx/ssl_key/applelife.crt;
    #key文件路劲
    ssl_certificate_key /etc/nginx/ssl_key/applelife.key;
    ...
    location / {
        ...
    }
}

其他命令

//停止 需要输入设置的key密码
nginx -s stop -c /etc/nginx/nginx.conf
//启动
nginx -c /etc/nginx/nginx.conf
//检查语法
nignx -tc /etc/nginx/nginx.cof
//查看端口是否启用
netstat -luntp |grep 443

Android https代码

可以参考google官方代码 https://developer.android.com/training/articles/security-ssl

SSLContext provideSSLContext(Application app) {
    try {
        //加载需要信任的证书,crt格式和cer格式都可以,在windows中可以互转
        //InputStream serverCer = app.getAssets().open("server.crt");
        InputStream serverCer = app.getResources().openRawResource(R.raw.rao);
       //InputStream fiddlerCer = app.getAssets().open("fiddlerroot.cer");
       //InputStream fiddlerCer=app.getResources().openRawResource(R.raw.fiddlerRoot);
        CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
        KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
        keyStore.load(null);
        //如果要信任多个证书,就会存在多个serverCer,那么要分别加载到keyStore中
        //别名可以随便命名,但不能重复
        keyStore.setCertificateEntry("server", certificateFactory.generateCertificate(serverCer));
        // keyStore.setCertificateEntry("fiddler", certificateFactory.generateCertificate(fiddlerCer));
        try {
            serverCer.close();
            //fiddlerCer.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        SSLContext sslContext = SSLContext.getInstance("TLS");
        TrustManagerFactory trustManagerFactory = TrustManagerFactory.
                getInstance(TrustManagerFactory.getDefaultAlgorithm());
        trustManagerFactory.init(keyStore);
        //初始化keystore
        sslContext.init(null, trustManagerFactory.getTrustManagers(), new SecureRandom());
        return sslContext;
    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }
}
...
builder.sslSocketFactory(sslContext.getSocketFactory());
...

问题异常

// 连接异常
HTTP FAILED: javax.net.ssl.SSLPeerUnverifiedException: Hostname 183.230.dd.156 not verified:

查找资料 在生成 .csr 的时候填入的很多信息中,包含了一个叫做 Common Name(CN)的 field,以前这个 CN 可以直接填写 server name 或者 IP,但之后规定了需要使用 Subject Alternative Name(SAN) 来指定 server name, IP
参考地址 https://tools.ietf.org/html/rfc2818#section-3.1

证书添加 subjectAltName

以现有证书添加 subjectAltName

 // 命令
openssl x509 -req -extfile <(printf "subjectAltName=IP:localhost,DNS:www.xxx.com") -days 365 -in rao.csr -CA rao.crt -CAkey rao.key -CAcreateserial -out rao1.crt

至此 Android https问题得到解决

参考:https://www.jianshu.com/p/a56b2234da1a
参考 :https://moxo.io/blog/2017/08/01/problem-missing-subjectaltname-while-makeing-self-signed-cert/

posted @ 2019-05-10 11:04  NiRao  阅读(1958)  评论(0编辑  收藏  举报