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

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. 若依-更换数据库-sqlite

    基础 我是在ruoyi-vue已经安装了mybatis-plus的基础上进行的修改 关于SQLite SQLite 是一个软件库,实现了自给自足的.无服务器的.零配置的.事务性的 SQL 数据库引擎. ...

  2. api规范PHP,RESTful API规范(详细版)

    rest 是一种软件架构风格,如果你们的接口是 rest 接口,那么就可被认为你们的的接口是restful的,英文名词和形容词的区别. rest 接口是围绕"资源"展开的,利用HT ...

  3. adb的详解

    1.何为adb adb(Android Debug Bridge)是android sdk的一个工具 adb是用来连接安卓手机和pc端的桥梁,要有adb作为二者之间的维系,才能让用户在电脑上对手机进行 ...

  4. 基于GPU 显卡在k8s 集群上实现hpa 功能

    前言 Kubernetes 支持HPA模块进行容器伸缩,默认支持CPU和内存等指标.原生的HPA基于Heapster,不支持GPU指标的伸缩,但是支持通过CustomMetrics的方式进行HPA指标 ...

  5. vue+element form 动态改变rules校验数据

    优化:确定secondRules的数据在secondFlag改变之前进行赋值 可以用$nextTick来执行,不用setTimeOut ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ...

  6. PHP接口微信支付

    PHP后台调用微信支付下单function wx_getPayRequest($openid, $orderid, $rmb, $title,$appoids){ $nonce = $orderid. ...

  7. web基础(4): CSS布局与定位

    chapter 5 CSS 布局与定位 web 前端开发的时候不是马上就考虑字体 字号这些细节,而是要先定下布局,也就是页面结构.    右图中一个个栏目就像是"盒子",每个盒子的 ...

  8. SSL certificate problem: unable to get local issuer certificate 错误解决

    终端报了如下错误git SSL certificate problem: unable to get local issuer certificate 这个问题是由于没有配置信任的服务器HTTPS验证 ...

  9. requests学习笔记02

    一.会话对象 会话对象让你能够跨请求保持某些参数.它也会在同一个 Session 实例发出的所有请求之间保持 cookie, 期间使用 urllib3 的 connection pooling 功能. ...

  10. JAVA笔记_方法递归调用

    方法递归调用   简单地说递归调用就是方法自己调用自己,每次调用时传入不同的变量,递归有助于编程者解决复杂问题,同时可以让代码变得更加简洁. 递归调用执行机制案例1: /** * @ClassName ...