国密Java和Python语言SM2和SM4对照代码

最近将Java的国密签名、验签、加密、解密的代码迁移到Python上,同时,经过验证,Java和Python之间是可以互相验签和加解密,记录下来,以供参考。

Java使用的是Hutool工具包

Python使用的是gmssl库

一、SM2签名

Java

//需要签名的明文,得到明文对应的字节数组
byte[] dataBytes = "111".getBytes();
//指定的私钥
String privateKeyHex = "1ebf8b341c695ee456fd1a41b82645724bc25d79935437d30e7e4b0a554baa5e";

// 此构造从5.5.9开始可使用
final SM2 sm2 = new SM2(privateKeyHex, null, null);
sm2.usePlainEncoding();
sm2.setMode(SM2Engine.Mode.C1C3C2);
byte[] sign = sm2.sign(dataBytes);

Python

import base64
import binascii
from gmssl import sm2, func
#16进制的公钥和私钥
private_key = '00B9AB0B828FF68872F21A837FC303668428DEA11DCD1B24429D0C99E24EED83D5'
public_key = 'B9C9A6E04E9C91F7BA880429273747D7EF5DDEB0BB2FF6317EB00BEF331A83081A6994B8993F3F5D6EADDDB81872266C87C018FB4162F5AF347B483E24620207'
sm2_crypt = sm2.CryptSM2(
    public_key=public_key, private_key=private_key,  mode=0, asn1=False)

data = b"111" # bytes类型
sign = sm2_crypt.sign_with_sm3(data) #  16进制

之前文章也强调过了,Java只要设置私钥就行,Python必须私钥公钥都设置。

Java的sm2.usePlainEncoding();对应Python的asn1=False
Java的sm2.setMode(SM2Engine.Mode.C1C3C2);对应Python的mode=0

二、SM2验签

Java

//指定的公钥
String publicKeyHex ="04db9629dd33ba568e9507add5df6587a0998361a03d3321948b448c653c2c1b7056434884ab6f3d1c529501f166a336e86f045cea10dffe58aa82ea13d725363";
//需要加密的明文,得到明文对应的字节数组
byte[] dataBytes = "111".getBytes();
//签名值
String signHex ="2881346e038d2ed706ccdd025f2b1dafa7377d5cf090134b98756fafe084dddbcdba0ab00b5348ed48025195af3f1dda29e819bb66aa9d4d088050ff148482a";

final SM2 sm2 = new SM2(null, ECKeyUtil.toSm2PublicParams(publicKeyHex));
sm2.usePlainEncoding();
sm2.setMode(SM2Engine.Mode.C1C3C2);

// true
boolean verify = sm2.verify(dataBytes, HexUtil.decodeHex(signHex));

Python

import base64
import binascii
from gmssl import sm2, func
#16进制的公钥和私钥
private_key = '00B9AB0B828FF68872F21A837FC303668428DEA11DCD1B24429D0C99E24EED83D5'
public_key = 'B9C9A6E04E9C91F7BA880429273747D7EF5DDEB0BB2FF6317EB00BEF331A83081A6994B8993F3F5D6EADDDB81872266C87C018FB4162F5AF347B483E24620207'
sm2_crypt = sm2.CryptSM2(
    public_key=public_key, private_key=private_key,  mode=0, asn1=False)

verifyResult= sm2_crypt.verify_with_sm3(sign, data) #  16进制

验签Java只需要设置公钥,而Python公钥和私钥都要设置,其他参数也和签名一致

三、SM4加密

Java

String content = "111";

// 密钥
byte[] key = "222";

SM4 sm4 = SmUtil.sm4(key);

String encryptHex = sm4.encryptHex(content, CharsetUtil.CHARSET_UTF_8);

Python

from gmssl.sm4 import CryptSM4, SM4_ENCRYPT, SM4_DECRYPT

key = b'222'
value = b'111' #  bytes类型
crypt_sm4 = CryptSM4()
crypt_sm4.set_key(key, SM4_ENCRYPT)
encrypt_value = crypt_sm4.crypt_ecb(value) #  bytes类型

四、SM4解密

Java

String content = "111";

// 密钥
byte[] key = "222";

SM4 sm4 = SmUtil.sm4(key);

String decryptStr = sm4.decryptStr(encryptHex, CharsetUtil.CHARSET_UTF_8);

Python

from gmssl.sm4 import CryptSM4, SM4_ENCRYPT, SM4_DECRYPT

key = b'222'
value = b'111' #  bytes类型
crypt_sm4 = CryptSM4()
crypt_sm4.set_key(key, SM4_DECRYPT)
decrypt_value = crypt_sm4.crypt_ecb(encrypt_value) #  bytes类型

其实对国密算法研究的不深入,只是在用到国密算法的场景中,不断验证的结果,希望能够针对国密算法的问题和大家有更多的交流

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值