问题描述:构建ntls国密通道时,发现当使用ECC-SM2-SM4-CBC-SM3时,即使客户端错误的配置加密密钥enc_PrivateKey_file,也可以成功构建ntls国密通道。
分析原因:在国密标准《GM/T 0024-2014 SSL VPN 技术规范》对国密构建tls通道的过程进行了详细的介绍。
1、客户端发送clienthello消息,消息中包括客户端在这个会话中使用的协议版本,在《GM/T 0024-2014 SSL VPN 技术规范》使用的是TLSv1.1;客户端产生的随机信息,包括时钟和随机数(ClientHello.random);客户端会话标识;客户端支持的密码套件列表,ECC-SM2-SM4-CBC-SM3和ECDHE-SM2-WITH-SM4-SM3都是国密密码套件;客户端支持的压缩算法列表。
2.1、服务端接收到客户端的clienthello之后返回serverhello消息,包括服务端支持的协议版本;服务端随机数(ServerHello.random);服务端会话标识;服务端从clienthello中选中的一个密码套件;服务端选中的压缩算法。
2.2、服务端发送证书消息,使用国密通道,需要发送服务端的签名证书和加密证书。
2.3、服务端发送ServerKeyExchange消息,此消息用于客户端计算产生48字节的预主密钥,当使用ECC算法时,此消息包括服务端对双方随机数和服务端加密证书的签名;当使用ECDHE算法时,此消息包括服务端密钥交换参数和服务端对双方随机数和服务端密钥交换参数的签名。
2.4、服务端发送CertificateRequest,当服务端需要验证客户端证书时发送此消息,请求客户端发送客户端证书,若不需要验证客户端证书,则不需要发送此消息
2.5、服务端发送ServerHelloDone,表示握手消息的hello阶段完成
3.1、客户端发送ClientCertificate,当服务端发送了2.4的CertificateRequest时,客户端需要发送此消息和客户端证书
3.2、客户端发送ClientKeyExchange消息,当密钥交换算法使用ECC算法时,本消息包括客户端产生的预主密钥,并使用服务端加密公钥对此预主密钥进行加密,服务端收到加密后的预主密钥后使用服务端加密私钥进行解密获得预主密钥;当密钥交换算法使用ECDHE算法时,本消息包含计算预主密钥的客户端密钥交换参数。
3.3、客户端发送CertificateVerify消息,只有ClientCertificate消息发送时才会发送此消息,用于验证客户端身份,计算从ClientHello至本消息止(不包括本消息)的所有与握手相关消息(包括加密证书)的签名,SM3计算hash值,SM2算法签名,使用客户端签名密钥进行签名
4、客户端和服务端在发送密码规格变更消息ChangeCipherSpec后发送握手结束Finished消息,用于校验握手过程的完整性,本消息使用握手过程协商的密钥和算法进行保护,双方接收到对方发送的此消息并校验通过之后即可使用该连接进行数据安全传输。
ECC密钥协商算法:
1、客户端和服务端分别产生随机数并明文发送给对方(步骤1和步骤2.1)
2、客户端计算预主密钥并在步骤3.2发送给服务端
3、客户端和服务端分别使用预主密钥pre_master_secret,客户端随机数,服务端随机数,字符串常量"master secret",经PRF计算生成主密钥:
master_secret=PRF(pre_master_secret,"master secret",ClientHello.random+ServerHello.random)
4、客户端和服务端分别使用工作密钥,计算主密钥,客户端随机数,服务端随机数,字符串常量"key expansion",经PRF计算生成工作密钥。工作密钥包括加密密钥和校验密钥,具体密钥长度由选择的密码算法决定。
key_block=PRF(SecurityParameters.master_secret,"key expansion",SecurityParameters.client_random+SecurityParameters.server_random);
直到生成所需长度的输出,然后按照顺序分割得到相应的密钥:
client_write_MAC_secret[SecurityParameters.hash_size]
server_write_MAC_secret[SecurityParameters.hash_size]
client_write_key[SecurityParameters.key_material_length]
server_write_key[SecurityParameters.key_material_length]
PRF函数计算方法如下:
PRF(secret,label,seed)=P_SM3(secret,label+seed)
P_SM3(secret,label+seed)=SM3(secret,A(1)+label+seed)+SM3(secret,A(2)+label+seed)+......
A(0)=label+seed,A(1)=SM3(secret,A(0)),A(i)=SM3(secret,A(i-1)).
ECDHE密钥协商算法:
1、A和B事先确定好使用哪种椭圆曲线,和曲线上的基点 G,这两个参数都是公开的;
2、A和B各自随机生成一个随机数作为私钥d,并与基点 G相乘得到公钥Q(Q = dG),此时A的公私钥为 Q1 和 d1,B的公私钥为 Q2 和 d2;
双方交换各自的公钥,最后A计算点(x1,y1) = d1Q2,B计算点(x2,y2) = d2Q1,由于椭圆曲线上是可以满足乘法交换和结合律,所以 d1Q2 = d1d2G = d2d1G = d2Q1 ,因此双方的 x 坐标是一样的,所以它是共享密钥,也就是会话密钥。
这个过程中,双方的私钥都是随机、临时生成的,都是不公开的,即使根据公开的信息(椭圆曲线、公钥、基点 G)也是很难计算出椭圆曲线上的离散对数(私钥)
原文链接:https://blog.csdn.net/m0_50180963/article/details/113061162
结论:ECC密钥交换算法中预主密钥完全由客户端计算获得,无论客户端使用什么方式得到预主密钥,客户端和服务端最终计算出的工作密钥是相同的。
在标准《GMT 0009-2012 SM2密码算法使用规范》9.6节和《GM/T 0003.3-2012 SM2 椭圆曲线公钥密码算法第3部分:密钥交换协议》中对国密ECDHE密钥协商算法进行了详细的介绍,在国密ECDHE密钥交换协议中,A和B的加密证书和加密私钥也参与了运算。
因此客户端配置了错误的加密私钥文件,使用ECC-SM2-SM4-CBC-SM3时仍然可以正确构建国密tls通道,但是使用ECDHE-SM2-WITH-SM4-SM3则不可以。