为什么需要双向认证
双向认证原理
实现过程
keytool -genkeypair -alias auth_server -keyalg RSA -validity 36500 -keypass auth_server -storepass auth_server -keystore /Users/renzhongrui/android/certs/auth_server.keystore
keytool -export -alias auth_server -file /Users/renzhongrui/android/certs/auth_server_pub.cer -keystore /Users/renzhongrui/android/certs/auth_server.keystore -storepass auth_server
keytool -genkeypair -alias auth_client -keyalg RSA -validity 36500 -keypass auth_client -storepass auth_client -keystore /Users/renzhongrui/android/certs/auth_client.jks
keytool -export -alias auth_client -file /Users/renzhongrui/android/certs/auth_client_pub.cer -keystore /Users/renzhongrui/android/certs/auth_client.jks -storepass auth_client
keytool -import -v -alias auth_client -file /Users/renzhongrui/android/certs/auth_client_pub.cer -keystore /Users/renzhongrui/android/certs/auth_server.keystore -storepass auth_server
keytool -import -v -alias auth_server -file /Users/renzhongrui/android/certs/auth_server_pub.cer -keystore /Users/renzhongrui/android/certs/auth_truststore.jks -storepass auth_truststore
keytool -list -keystore /Users/renzhongrui/android/certs/auth_server.keystore -storepass auth_server
keytool -list -keystore /Users/renzhongrui/android/certs/auth_truststore.jks -storepass auth_truststore
java -jar portecle.jar
server: port: 443 server: tomcat: uri-encoding: UTF-8 # 开启https,配置跟证书对应 ssl: key-store: classpath:auth_server.keystore key-store-type: JKS key-store-password: auth_server key-password: auth_server key-alias: auth_server enabled: true #是否需要进行认证 client-auth: need protocol: TLS # 默认 trust-store: classpath:auth_server.keystore trust-store-password: auth_server trust-store-type: JKS
public class PackApplication implements WebMvcConfigurer { public static void main(String[] args) { SpringApplication.run(PackApplication.class, args); } public Connector connector(){ Connector connector=new Connector("org.apache.coyote.http11.Http11NioProtocol"); connector.setScheme("http"); connector.setPort(80); connector.setSecure(false); connector.setRedirectPort(443); return connector; } public TomcatServletWebServerFactory tomcatServletWebServerFactory(Connector connector){ TomcatServletWebServerFactory tomcat=new TomcatServletWebServerFactory(){ protected void postProcessContext(Context context) { SecurityConstraint securityConstraint=new SecurityConstraint(); securityConstraint.setUserConstraint("CONFIDENTIAL"); SecurityCollection collection=new SecurityCollection(); collection.addPattern("/*"); securityConstraint.addCollection(collection); context.addConstraint(securityConstraint); } }; tomcat.addAdditionalTomcatConnectors(connector); return tomcat; }}
server { listen 443; server_name 192.168.200.101; # 代理服务IP ssl on; # 开启Https ssl_certificate /usr/local/nginx/conf/https/auth_server.cer; # auth_server.keystore导出的cer证书 ssl_certificate_key /usr/local/nginx/conf/https/auth_server.key; # auth_server.keystore导出的私钥 ssl_client_certificate /usr/local/nginx/conf/https/auth_client.cer; # auth_client.keystore导出的cer ssl_session_cache shared:SSL:1m; ssl_session_timeout 5m; ssl_verify_client optional; # 配置校验客户端策略,设置成optional时候可以开启白名单接口 ssl_protocols TLSv1.1 TLSv1.2; ssl_ciphers HIGH:!aNULL:!MD5; ssl_prefer_server_ciphers off; location / { # 需要双向验证https的接口 if ($ssl_client_verify != SUCCESS) { return 401; } proxy_pass http://192.168.200.101:8008; proxy_connect_timeout 600; proxy_read_timeout 600; } location /aarm/downloadUpdateFile { # 获取证书版本和下载证书接口,不需要验证Https proxy_pass http://192.169.200.101:8008; proxy_connect_timeout 600; proxy_read_timeout 600; } }
OkHttpClient okHttpClient = new OkHttpClient.Builder() .connectTimeout(10, TimeUnit.SECONDS) .readTimeout(10, TimeUnit.SECONDS) .sslSocketFactory(Https.getSSLCertifcation(getApplicationContext()))//获取SSLSocketFactory .hostnameVerifier(new UnSafeHostnameVerifier())//添加hostName验证器 .build();
public class Https { private final static String CLIENT_PRI_KEY = "auth_client.bks"; private final static String TRUSTSTORE_PUB_KEY = "auth_truststore.bks"; private final static String CLIENT_BKS_PASSWORD = "auth_client"; private final static String TRUSTSTORE_BKS_PASSWORD = "auth_truststore"; private final static String KEYSTORE_TYPE = "BKS"; private final static String PROTOCOL_TYPE = "TLS"; private final static String CERTIFICATE_FORMAT = "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(); //初始化SSLContext SSLContext sslContext = SSLContext.getInstance(PROTOCOL_TYPE); TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(CERTIFICATE_FORMAT); KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(CERTIFICATE_FORMAT); trustManagerFactory.init(trustStore); keyManagerFactory.init(keyStore, CLIENT_BKS_PASSWORD.toCharArray()); sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null); sslSocketFactory = sslContext.getSocketFactory(); } catch (Exception e) { e.printStackTrace(); } return sslSocketFactory; }}
private class UnSafeHostnameVerifier implements HostnameVerifier { public boolean verify(String hostname, SSLSession session) { return true; }}
{ "version":1, "authType":2, "clientBksPath":"https://localhost/downloadUpdateFile?fileName=auth_client.bks", "trustBksPath":"https://localhost/downloadUpdateFile?fileName=auth_truststore.bks", "authKey":"auth_client"}
keytool -list -rfc --keystore release.keystore | openssl x509 -inform pem -pubkey
keytool -v -importkeystore -srckeystore release.keystore -srcstoretype jks -srcstorepass 123456 -destkeystore keystore/release.pfx -deststoretype pkcs12 -deststorepass 123456 -destkeypass 123456
openssl pkcs12 -in release.pfx -nocerts -nodes
原文链接
https://blog.csdn.net/u010982507/article/details/122290850
推荐阅读
Android系统中run-as和su命令的源码解析(升降权限)
Android系统定制之Android.mk和Android.bp语法详解(精通版)
Android系统定制/测试(Crash/ANR等Bug/性能分析必备技巧)
关注、点赞、分享、转发
原文始发于微信公众号(哆啦安全):Android应用实现Https双向认证
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论