添加文件: xy_sh/pkg/crypto/crypto.go
This commit is contained in:
parent
bf43947130
commit
49f640a9e4
|
|
@ -0,0 +1,113 @@
|
|||
package crypto
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/tjfoc/gmsm/sm3"
|
||||
"github.com/tjfoc/gmsm/sm4"
|
||||
)
|
||||
|
||||
// ==================== SM3 with Salt ====================
|
||||
|
||||
// SM3WithSalt 使用SM3加盐哈希
|
||||
// 对应Java hutool的 SmUtil.sm3WithSalt(salt).digestHex(data)
|
||||
// hutool实现为:SM3(salt + data)
|
||||
func SM3WithSalt(salt string, data string) string {
|
||||
h := sm3.New()
|
||||
h.Write([]byte(salt))
|
||||
h.Write([]byte(data))
|
||||
return hex.EncodeToString(h.Sum(nil))
|
||||
}
|
||||
|
||||
// ==================== SM4-ECB 加密/解密 ====================
|
||||
|
||||
// SM4ECBEncrypt SM4-ECB模式加密,返回base64编码字符串
|
||||
func SM4ECBEncrypt(plaintext []byte, key []byte) (string, error) {
|
||||
if len(key) != 16 {
|
||||
return "", fmt.Errorf("SM4密钥长度必须为16字节")
|
||||
}
|
||||
|
||||
block, err := sm4.NewCipher(key)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("创建SM4 cipher失败: %v", err)
|
||||
}
|
||||
|
||||
padded := pkcs7Padding(plaintext, block.BlockSize())
|
||||
ciphertext := make([]byte, len(padded))
|
||||
for i := 0; i < len(padded); i += block.BlockSize() {
|
||||
block.Encrypt(ciphertext[i:i+block.BlockSize()], padded[i:i+block.BlockSize()])
|
||||
}
|
||||
|
||||
return base64.StdEncoding.EncodeToString(ciphertext), nil
|
||||
}
|
||||
|
||||
// SM4ECBDecrypt SM4-ECB模式解密,输入base64编码字符串,返回明文
|
||||
func SM4ECBDecrypt(encryptedData string, key []byte) ([]byte, error) {
|
||||
if len(key) != 16 {
|
||||
return nil, fmt.Errorf("SM4密钥长度必须为16字节")
|
||||
}
|
||||
|
||||
ciphertext, err := base64.StdEncoding.DecodeString(encryptedData)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("base64解码失败: %v", err)
|
||||
}
|
||||
|
||||
block, err := sm4.NewCipher(key)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("创建SM4 cipher失败: %v", err)
|
||||
}
|
||||
|
||||
blockSize := block.BlockSize()
|
||||
if len(ciphertext)%blockSize != 0 {
|
||||
return nil, fmt.Errorf("密文长度不是块大小的整数倍")
|
||||
}
|
||||
|
||||
plaintext := make([]byte, len(ciphertext))
|
||||
for i := 0; i < len(ciphertext); i += blockSize {
|
||||
block.Decrypt(plaintext[i:i+blockSize], ciphertext[i:i+blockSize])
|
||||
}
|
||||
|
||||
plaintext, err = pkcs7UnPadding(plaintext)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("去除填充失败: %v", err)
|
||||
}
|
||||
|
||||
return plaintext, nil
|
||||
}
|
||||
|
||||
// ==================== PKCS7 填充 ====================
|
||||
|
||||
func pkcs7Padding(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...)
|
||||
}
|
||||
|
||||
func pkcs7UnPadding(data []byte) ([]byte, error) {
|
||||
if len(data) == 0 {
|
||||
return nil, fmt.Errorf("数据为空")
|
||||
}
|
||||
padding := int(data[len(data)-1])
|
||||
if padding > len(data) || padding == 0 {
|
||||
return nil, fmt.Errorf("无效的填充")
|
||||
}
|
||||
for i := len(data) - padding; i < len(data); i++ {
|
||||
if int(data[i]) != padding {
|
||||
return nil, fmt.Errorf("无效的填充")
|
||||
}
|
||||
}
|
||||
return data[:len(data)-padding], nil
|
||||
}
|
||||
|
||||
// ==================== 时间戳工具 ====================
|
||||
|
||||
// GenerateTimestampMillis 生成毫秒级时间戳
|
||||
func GenerateTimestampMillis() string {
|
||||
return fmt.Sprintf("%d", time.Now().UnixMilli())
|
||||
}
|
||||
Loading…
Reference in New Issue