国密套件ECC-SM2-SM4-CBC-SM3和ECDHE-SM2-WITH-SM4-SM3

问题描述:构建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则不可以。

很高兴回答你的问题!以下是一个使用国密算法(SM2-SM3)的Java Demo Maven工程,供您参考: 1. 首先,在pom.xml文件中添加以下依赖: ```xml <dependency> <groupId>com.huawei.security</groupId> <artifactId>sm</artifactId> <version>2.0.5.300</version> </dependency> ``` 2. 创建SM2密钥对 ```java import com.huawei.security.sm.SM2KeyPair; import com.huawei.security.sm.SM2PrivateKey; import com.huawei.security.sm.SM2PublicKey; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.Security; public class SM2Demo { public static void main(String[] args) throws NoSuchProviderException, NoSuchAlgorithmException { Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); SM2KeyPair sm2KeyPair = new SM2KeyPair(); SM2PublicKey publicKey = sm2KeyPair.getPublicKey(); SM2PrivateKey privateKey = sm2KeyPair.getPrivateKey(); System.out.println("publicKey: " + publicKey.getHexString()); System.out.println("privateKey: " + privateKey.getHexString()); } } ``` 3. SM2加密和解密 ```java import com.huawei.security.sm.SM2PrivateKey; import com.huawei.security.sm.SM2PublicKey; import com.huawei.security.sm.SM2Engine; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.Security; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.KeyPairGenerator; import javax.crypto.Cipher; import javax.crypto.NoSuchPaddingException; public class SM2Demo { public static void main(String[] args) throws NoSuchProviderException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, NoSuchPaddingException { Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); // 创建密钥对 KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC", "BC"); keyPairGenerator.initialize(256); SM2KeyPair sm2KeyPair = new SM2KeyPair(keyPairGenerator.generateKeyPair()); // 获取公钥和私钥 SM2PublicKey publicKey = sm2KeyPair.getPublicKey(); SM2PrivateKey privateKey = sm2KeyPair.getPrivateKey(); // 加密 SM2Engine sm2Engine = new SM2Engine(); Cipher cipher = Cipher.getInstance(sm2Engine.getAlgorithmName(), "BC"); cipher.init(Cipher.ENCRYPT_MODE, publicKey); byte[] plaintext = "Hello, world!".getBytes(); byte[] ciphertext = cipher.doFinal(plaintext); System.out.println("ciphertext: " + new String(ciphertext)); // 解密 cipher.init(Cipher.DECRYPT_MODE, privateKey); byte[] decrypted = cipher.doFinal(ciphertext); System.out.println("decrypted: " + new String(decrypted)); } } ``` 4. SM3哈希算法 ```java import com.huawei.security.sm.SM3Digest; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.Security; public class SM3Demo { public static void main(String[] args) throws NoSuchProviderException, NoSuchAlgorithmException { Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); // 计算哈希值 SM3Digest sm3Digest = new SM3Digest(); byte[] plaintext = "Hello, world!".getBytes(); sm3Digest.update(plaintext, 0, plaintext.length); byte[] hash = new byte[sm3Digest.getDigestSize()]; sm3Digest.doFinal(hash, 0); System.out.println("hash: " + org.bouncycastle.util.encoders.Hex.toHexString(hash)); } } ``` 希望这个Demo工程能够帮助您使用国密算法(SM2-SM3)的Java开发。如果您有任何疑问,请随时联系我!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值