国密sm4-golang使用
sm4
国密SM4算法是一种分组加密算法。SM4分组密码(block cipher)算法是一种迭代分组密码算法,由加解密算法和密钥扩展算法组成。
SM4是一种Feistel结构的分组密码算法,其分组长度和密钥长度均为128bits。加密算法和密钥扩展算法迭代轮数均为32轮。SM4加解密过程的算法相同但是轮密钥的使用顺序相反
开发
这里我们使用 gmsm
库来实现国密sm4算法的加密和解密
https://github.com/emmansun/gmsm
封装代码
package sm4import ("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)%blockSizepadText := 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
可能并不是事件用到的密钥,可能是随机数种子,需要你去自己二次生成