背景
项目要求使用国密加密算法保障安全性,go和java需要通过接口互通,请求时使用sm4加密数据,sm2加密sm4秘钥,必将加密数据和加密后的sm4秘钥发送到第三方接口,
响应用相反的方式解密数据.
java 使用hutool里的工具函数实现,go使用”github.com/tjfoc/gmsm”实现.
2点需要注意:
- hutool工具函数名带有hex的会转成16进制,go需要调用hex.EncodeToString保证编码一致
- sm2/sm4均有多种加密模式,编码时go与java加密模式保持一致
sm2非对称加密
sm2: 基于椭圆曲线公钥密码算法标准,主要用于数字签名、密钥交换和数据加密
sm2有2种模式加密模式:C1C2C3,C1C3C2,hutool中默认使用C1C3C2模式
下面分别介绍go/java实现
1 2 3 4 5 6 7 8 9 10
|
func encryptKey(key []byte, pubKey *sm2.PublicKey) (string, error) { v, err := sm2.Encrypt(pubKey, key, rand.Reader, sm2.C1C3C2) if err != nil { return "", errors.Wrapf(err, "sm2加密失败") } logx.Debugf("加密秘钥,%s", hex.EncodeToString(v)) return hex.EncodeToString(v), nil }
|
1 2 3
| SM2 sm2 = SmUtil.sm2(null, publicSM2KeyHex); String encryptKey = sm2.encryptHex(sm4Key, KeyType.PublicKey);
|
解密
1 2 3 4 5 6 7
| func decryptKey(data []byte, privKey *sm2.PrivateKey) ([]byte, error) { v, err := sm2.Decrypt(privKey, data, sm2.C1C3C2) if err != nil { return nil, errors.Wrapf(err, "sm2解密失败") } return v, nil }
|
1 2 3
| SM2 decryptSM2 = SmUtil.sm2(privateSM2KeyHex, null); String decryptSM4Key = decryptSM2.decryptStr(encryptKey, KeyType.PrivateKey);
|
sm4对称加密
加密
1 2 3 4 5 6 7
| func encryptData(key, data []byte) (string, error) { encrypted, err := sm4.Sm4Ecb(key, data, true) if err != nil { return "", errors.Wrapf(err, "sm4加密失败") } return hex.EncodeToString(encrypted), nil }
|
1 2 3 4 5 6
|
String sm4Key = "565a5d91b637656e2a8ed56b6f3ffb87"; SM4 sm4 = SmUtil.sm4(ByteUtils.fromHexString(sm4Key));
String encryptData = sm4.encryptHex(jsonRequest);
|
解密
1 2 3 4 5 6 7
| func decryptData(key, data []byte) ([]byte, error) { decrypted, err := sm4.Sm4Ecb(key, data, false) if err != nil { return nil, errors.Wrapf(err, "sm4解密失败") } return decrypted, nil }
|
1 2 3 4 5
| String sm4Key = "565a5d91b637656e2a8ed56b6f3ffb87"; SM4 sm4 = SmUtil.sm4(ByteUtils.fromHexString(sm4Key));
String encryptData = sm4.decryptStr(data);
|
具体可参考 go-tool/crypto