本文采用客户端与服务端共用一个密钥对

1

https代理服务器(三)实践中的mkcert p12分解为一个公钥一个私钥

mac@macdeMacBook mkcert % openssl pkcs12 -clcerts -nokeys -out myhost.com.pem -in myhost.com.p12
Enter Import Password:
MAC verified OK
mac@macdeMacBook mkcert % openssl pkcs12 -nocerts -out myhost.com-key.pem -in myhost.com.p12
Enter Import Password:
MAC verified OK
Enter PEM pass phrase:

2 将公钥导入jks

keytool -import -file myhost.com.pem -keystore myhost.com-client.jks

密码123456

3 curl

mac@macdeMacBook mkcert % chmod 777 myhost.com-key.pem
mac@macdeMacBook mkcert % curl -k --cert myhost.com.pem --key myhost.com-key.pem https://myhost.com:8080/test/test -v
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to myhost.com (127.0.0.1) port 8080 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* unable to set private key file: 'myhost.com-key.pem' type PEM
* Closing connection 0
curl: (58) unable to set private key file: 'myhost.com-key.pem' type PEM

查下来是openssl分解可能存在很深的问题,不浪费时间

4 故从头开始

mkcert myhost.com

openssl pkcs12 -export -in myhost.com.pem -inkey myhost.com-key.pem -out myhost.com.p12

Enter Export Password:

Verifying - Enter Export Password:

把p12弄入springboot,作为keystore

keytool -import -file myhost.com.pem -keystore myhost.com-client(后改名未 -pub-capub).jks 作为truststore

curl -k --cert myhost.com.pem --key myhost.com-key.pem https://myhost.com:8080/test/test -v

成功

mac@macdeMacBook mkcert % curl -k --cert myhost.com.pem --key myhost.com-key.pem https://myhost.com:8080/test/test -v
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to myhost.com (127.0.0.1) port 8080 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: /etc/ssl/cert.pem
CApath: none
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Request CERT (13):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Certificate (11):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS handshake, CERT verify (15):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server did not agree to a protocol
* Server certificate:
* subject: O=mkcert development certificate; OU=mac@macdeMacBook.local
* start date: Feb 23 03:15:33 2023 GMT
* expire date: May 23 03:15:33 2025 GMT
* issuer: O=mkcert development CA; OU=mac@macdeMacBook.local; CN=mkcert mac@macdeMacBook.local
* SSL certificate verify ok.
> GET /test/test HTTP/1.1
> Host: myhost.com:8080
> User-Agent: curl/7.64.1
> Accept: */*
>
< HTTP/1.1 200
< Content-Type: text/plain;charset=UTF-8
< Content-Length: 4
< Date: Thu, 23 Feb 2023 03:23:38 GMT
<
* Connection #0 to host myhost.com left intact
DONE* Closing connection 0

5 java httpclient

        KeyStore keyStore = KeyStore.getInstance("PKCS12");
InputStream inputStream = Test.class.getClassLoader().getResourceAsStream("mkcert/myhost.com.p12");
keyStore.load(inputStream, "changeit".toCharArray());
SSLContext sslcontext = SSLContexts.custom()
//忽略掉对服务器端证书的校验
.loadTrustMaterial(new TrustStrategy() {
@Override
public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
return true;
}
}) //加载服务端提供的truststore(如果服务器提供truststore的话就不用忽略对服务器端证书的校验了)
//.loadTrustMaterial(new File("D:\\truststore.jks"), "123456".toCharArray(),
// new TrustSelfSignedStrategy())
.loadKeyMaterial(keyStore, "changeit".toCharArray())
.build();
HostnameVerifier hostnameVerifier = NoopHostnameVerifier.INSTANCE;
SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslcontext, hostnameVerifier);

Executing request GET https://myhost.com:8080/test/test HTTP/1.1
11:26:48.940 [main] DEBUG org.apache.http.client.protocol.RequestAddCookies - CookieSpec selected: default
11:26:48.969 [main] DEBUG org.apache.http.client.protocol.RequestAuthCache - Auth cache not set in the context
11:26:48.971 [main] DEBUG org.apache.http.impl.conn.PoolingHttpClientConnectionManager - Connection request: [route: {s}->https://myhost.com:8080][total kept alive: 0; route allocated: 0 of 2; total allocated: 0 of 20]
11:26:48.988 [main] DEBUG org.apache.http.impl.conn.PoolingHttpClientConnectionManager - Connection leased: [id: 0][route: {s}->https://myhost.com:8080][total kept alive: 0; route allocated: 1 of 2; total allocated: 1 of 20]
11:26:48.990 [main] DEBUG org.apache.http.impl.execchain.MainClientExec - Opening connection {s}->https://myhost.com:8080
11:26:48.995 [main] DEBUG org.apache.http.impl.conn.DefaultHttpClientConnectionOperator - Connecting to myhost.com/127.0.0.1:8080
11:26:49.005 [main] DEBUG org.apache.http.conn.ssl.SSLConnectionSocketFactory - Connecting socket to myhost.com/127.0.0.1:8080 with timeout 0
11:26:49.034 [main] DEBUG org.apache.http.conn.ssl.SSLConnectionSocketFactory - Enabled protocols: [TLSv1, TLSv1.1, TLSv1.2]
11:26:49.034 [main] DEBUG org.apache.http.conn.ssl.SSLConnectionSocketFactory - Enabled cipher suites:[TLS_ECDHE_ECDSA_W。。。。。ENEGOTIATION_INFO_SCSV]
11:26:49.034 [main] DEBUG org.apache.http.conn.ssl.SSLConnectionSocketFactory - Starting handshake
Exception in thread "main" javax.net.ssl.SSLHandshakeException: Received fatal alert: bad_certificate
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)

经查:

数据和安全②HTTPS单向和双向认证

https://www.codetd.com/article/11579403

5、将客户端证书添加到服务端jks中

## 将客户端证书导入服务端jks
keytool -import -v -file client.cer -keystore server.jks
### 查看证书文件 cer和crt证书文件一模一样,顶多去掉前缀
### 查看jks的证书文件,如下图
keytool -list -rfc -keystore server.jks -storepass 123456
## 服务端信任客户端证书、客户端证书信任服务端不行,要将根证书导入秘钥库
## 要将ca证书也导入证书库
keytool -import -file ca.crt -alias ca -keystore server.jks -storepass 123456

如果没有添加根证书到jks秘钥库,报错如下:

SSLHandshakeException: Received fatal alert: bad_certificate

跟着操作:

mkcert -CAROOT

keytool -import -file /Users/mac/Library/Application\ Support/mkcert/rootCA.pem -alias ca -keystore myhost.com-pub-capub.jks

查看ca证书是否已经在里面了:

mac@macdeMacBook mkcert % keytool -v -list -keystore myhost.com-pub-capub.jks
输入密钥库口令: 密钥库类型: JKS
密钥库提供方: SUN 您的密钥库包含 2 个条目 别名: ca
创建日期: 2023-2-23
条目类型: trustedCertEntry 所有者: CN=mkcert mac@macdeMacBook.local, OU=mac@macdeMacBook.local, O=mkcert development CA
发布者: CN=mkcert mac@macdeMacBook.local, OU=mac@macdeMacBook.local, O=mkcert development CA
序列号: 235d3f5c76501a7ed133bc9d0bc44bd3
有效期开始日期: Mon Dec 12 14:53:21 CST 2022, 截止日期: Sun Dec 12 14:53:21 CST 2032 别名: mykey
创建日期: 2023-2-23
条目类型: trustedCertEntry 所有者: OU=mac@macdeMacBook.local, O=mkcert development certificate
发布者: CN=mkcert mac@macdeMacBook.local, OU=mac@macdeMacBook.local, O=mkcert development CA
序列号: 6e414b515e161572f3da9edbaf732ba7
有效期开始日期: Thu Feb 23 11:15:33 CST 2023, 截止日期: Fri May 23 11:15:33 CST 2025
 

重启

成功

6 透明代理

http代理服务器(三)fiddler【重点】中的透明代理拿来

请求成功

代理输出:

二月 23, 2023 11:35:15 上午 io.netty.handler.logging.LoggingHandler channelRegistered
信息: [id: 0x5522c775] REGISTERED
二月 23, 2023 11:35:15 上午 io.netty.handler.logging.LoggingHandler bind
信息: [id: 0x5522c775] BIND(0.0.0.0/0.0.0.0:1999)
二月 23, 2023 11:35:15 上午 io.netty.handler.logging.LoggingHandler channelActive
信息: [id: 0x5522c775, /0:0:0:0:0:0:0:0:1999] ACTIVE
二月 23, 2023 11:35:25 上午 io.netty.handler.logging.LoggingHandler logMessage
信息: [id: 0x5522c775, /0:0:0:0:0:0:0:0:1999] RECEIVED: [id: 0x6b813dbd, /127.0.0.1:59079 => /127.0.0.1:1999]
--------------------cc----------------------
------------------------------------------

服务器输出:

个人证书信息:OU=mac@macdeMacBook.local, O=mkcert development certificate

说明经过了代理传递了证书,逻辑上 java httpclient与springboot直接ssl双向握手

7

自签名证书穿越want

keytool -genkeypair -alias "test1" -keyalg "RSA" -keystore "test.keystore"

keytool -importkeystore -srckeystore test.keystore -destkeystore test.p12 -srcstoretype jks -deststoretype pkcs12

可以穿越,但拿不到证书

8 ca证书穿越want

mkcert -pkcs12 testca

11:58:28.670 [main] DEBUG org.apache.http.conn.ssl.SSLConnectionSocketFactory - Starting handshake
Exception in thread "main" javax.net.ssl.SSLHandshakeException: Received fatal alert: certificate_unknown
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.Alerts.getSSLException(Alerts.java:154)
11:58:28.946 [main] DEBUG org.apache.http.impl.conn.DefaultManagedHttpClientConnection - http-outgoing-0: Shutdown connection
at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:2023)
11:58:28.947 [main] DEBUG org.apache.http.impl.execchain.MainClientExec - Connection discarded
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1125)
at sun.security.ssl.SSLSocketImpl.waitForClose(SSLSocketImpl.java:1769)
11:58:28.947 [main] DEBUG org.apache.http.impl.conn.PoolingHttpClientConnectionManager - Connection released: [id: 0][route: {s}->https://myhost.com:8080][total kept alive: 0; route allocated: 0 of 2; total allocated: 0 of 20]
at sun.security.ssl.HandshakeOutStream.flush(HandshakeOutStream.java:124)
11:58:28.947 [main] DEBUG org.apache.http.impl.conn.PoolingHttpClientConnectionManager - Connection manager is shutting down
at sun.security.ssl.Handshaker.sendChangeCipherSpec(Handshaker.java:1130)
11:58:28.947 [main] DEBUG org.apache.http.impl.conn.PoolingHttpClientConnectionManager - Connection manager shut down
at sun.security.ssl.ClientHandshaker.sendChangeCipherAndFinish(ClientHandshaker.java:1216)

说明want一旦开始搞就会搞到底,不如不给客户端证书或自签名证书

9 mkcert myhost.com作为客户端证书

两种方式 直接mkcert p12 与mkcert pem再openssl合并,结果都同8 error

所以mkcert两次即使签发同一个cn,证书内容也不相同

10 不给truststore

家里所有请求都失败 java和curl

公司可以不知道为啥 (https原理(六)系统分析中解释了)

  家里有truststore 公司没有truststore
原始 通过有证书 通过有证书
自签名 通过但没证书 通过但没证书
ca不同cn ssl失败 /
ca 相同cn p12 ssl失败 /
ca 相同cn pem p12 ssl失败 /

11 那么对于want

https://qa.1r1g.com/sf/ask/1047344861/

我的应用程序需要对特定URL进行客户端身份验证,在客户端身份验证成功后,应用程序本身也会对客户端证书主题进行一些验证(使用spring security x509过滤器).我想配置tomcat来强制特定URL的客户端身份验证(clientAuth = true),但基于这篇文章,似乎我不能只使用tomcat - 只为特定的URL模式配置tomcat进行客户端身份验证.

我的问题是,如果我使用clientAuth = want,当服务器请求证书时,以下内容如下:

  1. 如果设备具有身份证书但不受tomcat truststoreFile中配置的CA信任,则不会传递证书,并且请求将在spring安全过滤器中失败(证书将为null)
  2. 如果设备具有由tomcat truststoreFile中配置的CA信任的身份证书,但无效(不确定执行了哪些验证)或过期,则认证将在tomcat中失败(在安全过滤器之前)或在选项1中没有证书将传递并且请求将在spring安全过滤器中失败(证书将为null) 我这里直接ssl失败

使用此配置的want +安全过滤器,是否存在我可能缺少的安全漏洞?我想问题是 - 如果证书最终从设备传递到服务器,服务器将始终验证它(未过期,受信任等),即使使用clientAuth = want也不会允许客户端继续,如果证书是无效?没有证书通过的情况由安全过滤器覆盖,该过滤器将检查证书不为空.

您在1和2中的假设都是正确的.Tomcat不允许将不受信任或无效的证书通过您的应用程序.如果获得空证书,则可以假定未传递证书,或者传递了不受信任/无效的证书.

在我正在开发的项目上,我们有与您相同的要求:仅限某些URL的客户端证书.我们通过实验发现了"clientAuth = want"的工作原理.

https原理(四)双向实践(java客户端+tcp代理)的更多相关文章

  1. Tengine HTTPS原理解析、实践与调试【转】

    本文邀请阿里云CDN HTTPS技术专家金九,分享Tengine的一些HTTPS实践经验.内容主要有四个方面:HTTPS趋势.HTTPS基础.HTTPS实践.HTTPS调试. 一.HTTPS趋势 这一 ...

  2. Memcached学习笔记 — 第四部分:Memcached Java 客户端-gwhalin(1)-介绍及使用

     介绍 Memcached java client是官方推荐的最早的memcached java客户端.最新版本:java_memcached-release_2.6.1. 官方下载地址:http ...

  3. 【大量干货】史上最完整的Tengine HTTPS原理解析、实践与调试

    本文邀请阿里云CDN HTTPS技术专家金九,分享Tengine的一些HTTPS实践经验.内容主要有四个方面:HTTPS趋势.HTTPS基础.HTTPS实践.HTTPS调试. 一.HTTPS趋势 这一 ...

  4. HTTPS 原理与证书实践

    1.1 网络安全知识 1.1.1 网结安全出现背景 网络就是实现不同主机之间的通讯,网络出现之初利用TCP/IP协议簇的相关协议概念,已经满足了互连两台主机之间可以进行通汛的目的,虽然看似简简单单几句 ...

  5. https原理与实践

    HTTPS 原理与证书实践   分类: Web应用   1.1 网络安全知识 1.1.1 网结安全出现背景 网络就是实现不同主机之间的通讯,网络出现之初利用TCP/IP协议簇的相关协议概念,已经满足了 ...

  6. Atitit.异常的设计原理与 策略处理 java 最佳实践 p93

    Atitit.异常的设计原理与 策略处理 java 最佳实践 p93 1 异常方面的使用准则,答案是:: 2 1.1 普通项目优先使用异常取代返回值,如果开发类库方面的项目,最好异常机制与返回值都提供 ...

  7. Java实现TCP之Echo客户端和服务端

    Java实现TCP之Echo客户端和服务端 代码内容 采用TCP协议编写服务器端代码(端口任意) 编写客户机的代码访问该端口 客户机按行输入 服务器将收到的字符流和接收到的时间输出在服务器consol ...

  8. java 通过TCP\UDP 协议实现多人聊天,点对点,文件传送-----分服务器端和客户端

    java 通过TCP\UDP 协议实现多人聊天,点对点,文件传送-----分服务器端和客户端 启动界面如下图: 首先启动服务器: 客户端登陆,登陆成功后为: 默认发送是全部用户,是多人发送. 当在边列 ...

  9. Https双向认证Android客户端配置

    Https .cer证书转换为BKS证书 公式https://blog.csdn.net/zww986736788/article/details/81708967 keytool -importce ...

  10. TCP/UDP client/server library for Java, 最好的java语言tcp udp 服务器客户端实现库

    这个库andrdoi也可以用,而且是基于类的使用方式: 它支持类似聊天室的功能,即一个人说话,所有客户端都能收到,当然也支持点点通信.它还支持 RMI 的方式调用远程过程. https://githu ...

随机推荐

  1. python读取Excel指定单元格的值

    使用openpyxl实现 只支持xlsx文件,不支持xls import openpyxl def read_cell(io, sheet, cell='A2'): """ ...

  2. Vue2 常见问题汇总及解决方案

    参考:https://mp.weixin.qq.com/s/6Wapb1bZLQaYv0zlip6ygg 1.安装超时(install timeout) 方案: cnpm : 国内对npm的镜像版本 ...

  3. Java使用Calendar获取月最大天数

    Calendar calendar = Calendar.getInstance(); calendar.set(Calendar.YEAR, year); calendar.set(Calendar ...

  4. Centos 7.9 部署Kubernetes集群 (基于containerd 运行时)

    前言 当Kubernetes社区宣布1.20版本之后会逐步弃用 dockershim ,当时也有很多自媒体在宣 传Kubernetes弃用Docker.其实,我觉得这是一种误导,也许仅仅是为了蹭热度. ...

  5. redis 持久化之RDB和AOF的区别

    持久化之RDB 定义:在指定的时间间隔内生成数据集的时间点快照 RDB 的优点: 1.RDB 是一个非常紧凑的文件 它保存了 Redis 在某个时间点上的数据集. 这种文件非常适合用于进行备份: 比如 ...

  6. 关于CMDB

    关于CMDB: CMDB运维管理平台是由CMDB开发团队,针对目前服务器运维.监控,批量管理提出的一个开源. 易用.实用的跨平台服务器运维管理平台. 统筹来说cmdb就是将已有的规则化运维技术规则到运 ...

  7. asp.net core 全局授权管理系统简介

    大家好,我最近在做一个管理系统,我希望能做出一种授权机制,通过数据库的配置,来动态管控每个登入用于的访问权限. 因为才接触core不久,了解core的授权机制还是用了些时间的. 所以总结出来,供大家分 ...

  8. SDN之Openflow+OpenDayLight课程开课通知

    内容简介: 该课程为期2天,在这两天里 我们将会深入体会SDN的特点与传统网络的区别 ,掌握SDN架构里各层的协议用途,Openflow作为sdn里的一款开源的南向协议,最大的意义体现在它实现了网络设 ...

  9. 【GROMACS】分子动力学模拟①——环境搭建

    系统环境 Win11 22H2 企业版 开启虚拟化.window subsystem for liunx等虚拟机相关的功能 应用商店中安装WSL2 安装步骤 打开Ubuntu,输入sudo apt f ...

  10. win10 + emacs + sml

    1.官网下载sml编译器是smi安装包,安装结束之后把bin文件夹放到环境变量Path中 2.下载emacs压缩包,直接解压 3.emacs中alt+x,输入package-list 然后选择sml- ...