国密sm4加密
国密sm4-golang使用
sm4
国密SM4算法是一种分组加密算法。SM4分组密码(block cipher)算法是一种迭代分组密码算法,由加解密算法和密钥扩展算法组成。
SM4是一种Feistel结构的分组密码算法,其分组长度和密钥长度均为128bits。加密算法和密钥扩展算法迭代轮数均为32轮。SM4加解密过程的算法相同但是轮密钥的使用顺序相反
开发
这里我们使用 gmsm库来实现国密sm4算法的加密和解密
https://github.com/emmansun/gmsm
封装代码
package sm4
import (
"crypto/cipher"
"encoding/base64"
"github.com/emmansun/gmsm/sm4"
)
func Encrypt(SrcData []byte, appKey, appIv string) (string, error) {
key, _ := base64.StdEncoding.DecodeString(appKey)
iv, _ := base64.StdEncoding.DecodeString(appIv)
block, _ := sm4.NewCipher(key)
// 手动填充
SrcData = pkcs5Padding(SrcData, 16)
// CTR 模式加密
stream := cipher.NewCTR(block, iv)
ciphertext := make([]byte, len(SrcData))
stream.XORKeyStream(ciphertext, SrcData)
// Base64 编码加密结果
return base64.StdEncoding.EncodeToString(ciphertext), nil
}
func Decrypt(base64Data string, appKey, appIv string) ([]byte, error) {
key, _ := base64.StdEncoding.DecodeString(appKey)
iv, _ := base64.StdEncoding.DecodeString(appIv)
block, err := sm4.NewCipher(key)
if err != nil {
return nil, err
}
// Base64 解码密文
ciphertext, err := base64.StdEncoding.DecodeString(base64Data)
if err != nil {
return nil, err
}
// CTR 模式解密
stream := cipher.NewCTR(block, iv)
plaintext := make([]byte, len(ciphertext))
stream.XORKeyStream(plaintext, ciphertext)
// 手动去除填充
plaintext, err = pkcs5UnPadding(plaintext)
return plaintext, nil
}
// PKCS5Padding 填充
func pkcs5Padding(data []byte, blockSize int) []byte {
padding := blockSize - len(data)%blockSize
padText := make([]byte, padding)
for i := range padText {
padText[i] = byte(padding)
}
return append(data, padText...)
}
// PKCS5UnPadding 去除填充
func pkcs5UnPadding(data []byte) ([]byte, error) {
length := len(data)
if length == 0 {
return nil, errors.New("解密数据为空")
}
paddingLen := int(data[length-1])
if paddingLen > length || paddingLen > 16 {
return nil, errors.New("填充长度不正确")
}
return data[:length-paddingLen], nil
}
func DecodeSecretKey(secret string) string {
decodeData, _ := base64.StdEncoding.DecodeString(secret)
return string(decodeData)
}
注意⚠️:一些平台在使用sm4的使用对外提供的appKey和appIV可能并不是事件用到的密钥,可能是随机数种子,需要你去自己二次生成
转载请标明,谢谢

浙公网安备 33010602011771号