https原理(六)系统分析

先解决此前的问题:

 

http原理(三)双向实践(curl)

need时java 客户端可访问,但没客户端证书;want时有

后来发现,没有给truststore,猜测为,当springboot读到need,没有读到truststore时,没有强制检验的手段,直接放弃双向握手

后证实如果不给truststore,会用java cacerts文件

而当want时,虽然tomcat没有检验手段,但tomcat不能排除用户没有检验手段,兴许用户就是不用 struststore检验,所以没有放弃双向握手,把客户端公钥传下去

 http原理(四)双向实践(java客户端+tcp代理)

不给truststore

home所有请求都失败 java和curl

com可以不知道为啥

 

com那边没指定truststore,但直接指向了cacerts

truststore:双向认证中是必须的,如果没有显式的指定,默认指定为$JAVA_HOME/lib/security/cacerts 这个文件。

 

2 现在确定了com没给truststrore仍然能跑的第一个必要条件,那么接下去的问题是,ecs上的cacerts里面有什么

是否同时有ca和客户端公钥?

 

3 第2点引出一个问题,是否truststore里面有ca证书就行了?

home实践下来不行

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

失败,无论need还是want

实际上此前也有类似实践,删除truststore属性,模仿com,但是请求失败

根据今天的结论,删除truststore会指向cacerts,我们看下cacerts里有啥

keytool -list -v -keystore cacerts > ~/Downloads/tmp.txt

用mkcert做关键词搜索tmp.txt,仅有一处,即mkcert ca,所以在https代理服务器(三)实践中,mkcert install 已经将mkcert根证书安装到not only mac but java了

 

4 在3的基础上,推测com的ecs cacerts中,运维安装了各服务的公钥和ca证书

 

5 还有个问题,服务每次发布,都会得到一个新的 jks p12文件,密码也新的不变,仅一对同时可用于作为服务端和客户端的密钥对(p12)

那么会发生以下情况

app1 cacerts app2
  既有app1与app2的公钥  
发布,得到一个密钥对 植入app1的新的公钥 不重启
请求app2   不认新的公钥

无穷尽也

那么猜测,新的 jks p12文件,只是把原公钥重新封装一下,并没有重新签发密钥对

app1 cacerts app2
 

运维签发app1和app2的密钥对,将2个公钥和ca证书植入所有ecs的jre cacerts文件(可能都集中管理在ecs某个区域)

 

发布,请求新的jks,

但里面的密钥对还是之前运维签发的

对app1的密钥对重新生成一个jks   
请求app2,带着公钥 app1的公钥一直在truststore(即java cacerts)没变过 检验app1的公钥成功

 

还有一个有此推测的原因是,ca私钥签发密钥对应该是很繁琐的,不太可能发布一次就给一对新的

 

6 如何获得证据

如果能打印前后两次发布获得jks的sha1(可以hash),如果一样,就是证据

那么同一个公钥,两次jks,sha1 一样吗?

 

7 对myhost.com.pem 两次jks,查看证书

keytool -import -file ../mkcert/myhost.com.pem -keystore 1.jks

123456

keytool -import -file ../mkcert/myhost.com.pem -keystore 2.jks

654321

mac@macdeMacBook twicesamepemjkssha1 % keytool -list -v -keystore 1.jks > 1.txt
输入密钥库口令: 123456
mac@macdeMacBook twicesamepemjkssha1 % keytool -list -v -keystore 2.jks > 2.txt
输入密钥库口令: 654321

1与2完全一样

因此可以用6的方式检验2次发布的私钥和公钥有没有变,还是只是jks变了

 

8 获得证据

其实下载的是p12,且app1前后两次下载得到的pw相同;

而app1 app2都是通过一个参数相同的get请求拿的

所以只要证明app1前后两次获得的是一个证书(目前pw相同并不能说证书相同),就证明了该get接口只要入参不变,output也不变,而app2也是用这套参数,所以app1与app2获得的是同一个证书

ecs pem:openssl x509 -sha1 -in cert.pem -noout -fingerprint
本地上次get的p12:"keytool" -list -v -keystore keystore.jks

两者sha1相同

至此证明了ecs的密钥对都是同一个

 

 

9 non ecs

non ecs的keystore同时作为truststore(这一点不同于ecs没给truststore),是个p12文件,转为jks显示有30多个证书在里面,其中有一个公钥证书,CN、sha1与8中获取的一致

"C:\Program Files\jdk8\latest\bin\keytool" -list -v -keystore c:\work/test/httpproxy\keystore2.jks > "C:\work\tmptmp.txt"

 https://www.coder.work/article/67786

通常您可以在一个存储中存储多个私钥和证书。

基于 Java 的服务器使用哪种 key 和证书组合取决于应用程序的实现方式。许多应用程序允许您使用 别名 名称选择给定的证书。 keystore中的 key 和证书 getter 采用 alias 参数来做出此选择。通常,当配置中没有指定时,应用程序或框架将使用它根据 KeyStore.aliases() 枚举找到的第一个合适的。

例如,Tomcat 中使用 keyAlias 属性。 :

keyAlias: The alias used to for the server certificate in the keystore. If not specified the first key read in the keystore will be used.

https://www.elecfans.com/d/1238385.html

如果您的密钥库包含多个私钥别名,则需要添加“ keyAlias”指令以及对所需别名地引用。

keyAlias =“ tomcat”保存更改并重新启动Tomcat Web服务。

作为客户端拿p12的密钥对时,也可以指定alias

错了,写入tomcat配置的是p12而不是jks,p12只包含1个私钥,包含1个或多个公钥。公钥是构成信任链的密钥。https://cloud.tencent.com/developer/ask/sof/100353685

anyway,她只要有一个私钥就够了

ecs non ecs
作为客户端 作为服务端
请求non ecs  
拿着keystore,里面一个ecs密钥对  
  发送keystore里面的公钥
信任一切服务端公钥  
发送ecs公钥  
  核对truststore,里面确实有ecs公钥证书
作为服务端 作为客户端
  请求ecs
发送keystore里面的公钥  
  信任一切服务端公钥
  发送客户端(non ecs)公钥,根据keystore

核对truststore,因为没给,所以找到java的cacerts文件

由此可以推测non ecs keystore的公钥所表达的证书链能在在cacerts文件中被验证

 

 

 这里看出non ecs的keystore和truststore暴露,尤其是keystore有私钥,且keystore读权限宽松,直接可以拿来跟ecs双向ssl握手,从而对ecs进行抓包

 

9+

https://www.coder.work/article/67786

基于 Java 的服务器使用哪种 key 和证书组合取决于应用程序的实现方式。许多应用程序允许您使用 别名 名称选择给定的证书。 KeyStore 中的 key 和证书 getter 采用 alias 参数来做出此选择。通常,当配置中没有指定时,应用程序或框架将使用它根据 KeyStore.aliases() 枚举找到的第一个合适的。

例如,Tomcat 在其 Connector configuration 中使用 keyAlias 属性。 :

keyAlias: The alias used to for the server certificate in the keystore. If not specified the first key read in the keystore will be used.

 

10 虽然non ecs keystore请求ecs双向握手成功,但ecs端的x509 filter获得的Common Name为non ecs的hostname,既然keystore里面有ecs公钥证书,能不能把它拉出来发给ecs?这样就能通过filter

试了各种方式失败,即使只删除 hostname那个公钥

原因推测为里面的唯一的私钥是对应于cn为hostname的那个公钥,所以无法解密ecs用这个发过去的ecs公钥加密的加密方式,握手失败

 

11 此外找到了ecs的cacerts,里面并没有non ecs 和ecs的公钥本身,猜测有root下面次一级的证书链支持

 

 

总结:

整体系统设计非常教科书

1 传输层透明代理,确保端对端ssl

2 ecs每个app一个密钥对,同时作为keystore(单向ssl服务端,双向ssl客户端)和truststore(双向ssl服务端)

3 同一个环境所有ecs app密钥对都是同一个,sit与uat共用ca

4 ecs无需app自己配trustrore,运维统一管理cacerts

5 利用want的严密实现部分url双向ssl验证

 

posted on 2023-02-24 23:52  silyvin  阅读(69)  评论(0编辑  收藏  举报