```go package ymt_v3_generate import ( "bytes" "crypto" "crypto/aes" "crypto/rand" "crypto/rsa" "crypto/sha256" "crypto/x509" "encoding/base64" "encoding/json" "encoding/pem" "errors" "fmt" "reflect" "sort" "strings" ) // EncryptType 加密类型 type EncryptType string const ( EncryptTypeAES EncryptType = "aes" // AES ECB模式 EncryptTypeSM4 EncryptType = "sm4" // SM4 CBC模式(暂未实现,仅占位) ) // Crypto 加密工具 type Crypto struct { key []byte encryptType EncryptType } // NewCrypto 创建加密工具 func NewCrypto(key string, encryptType EncryptType) *Crypto { return &Crypto{ key: []byte(key), encryptType: encryptType, } } // Encrypt 加密明文,返回base64编码的密文 func (c *Crypto) Encrypt(plaintext []byte) (string, error) { switch c.encryptType { case EncryptTypeAES: return c.aesECBEncrypt(plaintext) case EncryptTypeSM4: return "", errors.New("SM4 encryption not implemented") default: return "", fmt.Errorf("unsupported encrypt type: %s", c.encryptType) } } // Decrypt 解密密文(base64编码),返回明文 func (c *Crypto) Decrypt(ciphertext string) ([]byte, error) { cipherData, err := base64.StdEncoding.DecodeString(ciphertext) if err != nil { return nil, fmt.Errorf("base64 decode failed: %w", err) } switch c.encryptType { case EncryptTypeAES: return c.aesECBDecrypt(cipherData) case EncryptTypeSM4: return nil, errors.New("SM4 decryption not implemented") default: return nil, fmt.Errorf("unsupported encrypt type: %s", c.encryptType) } } // aesECBEncrypt AES ECB模式加密 func (c *Crypto) aesECBEncrypt(plaintext []byte) (string, error) { block, err := aes.NewCipher(c.key) if err != nil { return "", err } // PKCS7填充 plaintext = pkcs7Pad(plaintext, block.BlockSize()) ciphertext := make([]byte, len(plaintext)) // ECB模式:直接分组加密 for start := 0; start < len(plaintext); start += block.BlockSize() { block.Encrypt(ciphertext[start:start+block.BlockSize()], plaintext[start:start+block.BlockSize()]) } return base64.StdEncoding.EncodeToString(ciphertext), nil } // aesECBDecrypt AES ECB模式解密 func (c *Crypto) aesECBDecrypt(ciphertext []byte) ([]byte, error) { block, err := aes.NewCipher(c.key) if err != nil { return nil, err } if len(ciphertext)%block.BlockSize() != 0 { return nil, errors.New("ciphertext is not a multiple of block size") } plaintext := make([]byte, len(ciphertext)) for start := 0; start < len(ciphertext); start += block.BlockSize() { block.Decrypt(plaintext[start:start+block.BlockSize()], ciphertext[start:start+block.BlockSize()]) } // 去除PKCS7填充 plaintext, err = pkcs7Unpad(plaintext, block.BlockSize()) if err != nil { return nil, err } return plaintext, nil } // pkcs7Pad PKCS7填充 func pkcs7Pad(data []byte, blockSize int) []byte { padding := blockSize - len(data)%blockSize padText := bytes.Repeat([]byte{byte(padding)}, padding) return append(data, padText...) } // pkcs7Unpad 去除PKCS7填充 func pkcs7Unpad(data []byte, blockSize int) ([]byte, error) { if len(data) == 0 { return nil, errors.New("data is empty") } padding := int(data[len(data)-1]) if padding > blockSize || padding == 0 { return nil, errors.New("invalid padding") } for i := len(data) - padding; i < len(data); i++ { if int(data[i]) != padding { return nil, errors.New("invalid padding") } } return data[:len(data)-padding], nil } // Signer 签名工具 type Signer struct { privateKey *rsa.PrivateKey } // NewSigner 创建签名工具 func NewSigner(privateKeyPEM string) (*Signer, error) { block, _ := pem.Decode([]byte(privateKeyPEM)) if block == nil { return nil, errors.New("failed to decode private key PEM") } key, err := x509.ParsePKCS8PrivateKey(block.Bytes) if err != nil { // 尝试PKCS1 key, err = x509.ParsePKCS1PrivateKey(block.Bytes) if err != nil { return nil, fmt.Errorf("failed to parse private key: %w", err) } } rsaKey, ok := key.(*rsa.PrivateKey) if !ok { return nil, errors.New("private key is not RSA") } return &Signer{privateKey: rsaKey}, nil } // Sign 对数据进行签名,返回base64编码的签名 func (s *Signer) Sign(data string) (string, error) { hash := sha256.Sum256([]byte(data)) signature, err := rsa.SignPKCS1v15(rand.Reader, s.privateKey, crypto.SHA256, hash[:]) if err != nil { return "", err } return base64.StdEncoding.EncodeToString(signature), nil } // Verifier 验签工具 type Verifier struct { publicKey *rsa.PublicKey } // NewVerifier 创建验签工具 func NewVerifier(publicKeyPEM string) (*Verifier, error) { block, _ := pem.Decode([]byte(publicKeyPEM)) if block == nil { return nil, errors.New("failed to decode public key PEM") } key, err := x509.ParsePKIXPublicKey(block.Bytes) if err != nil { return nil, fmt.Errorf("failed to parse public key: %w", err) } rsaKey, ok := key.(*rsa.PublicKey) if !ok { return nil, errors.New("public key is not RSA") } return &Verifier{publicKey: rsaKey}, nil } // Verify 验证签名 func (v *Verifier) Verify(data, signatureBase64 string) error { sig, err := base64.StdEncoding.DecodeString(signatureBase64) if err != nil { return fmt.Errorf("base64 decode signature failed: %w", err) } hash := sha256.Sum256([]byte(data)) return rsa.VerifyPKCS1v15(v.publicKey, crypto.SHA256, hash[:], sig) } // BuildPlaintext 构建待加密/签名的明文:将结构体转为JSON,去掉零值字段,按key排序 func BuildPlaintext(v interface{}) (string, error) { val := reflect.ValueOf(v) if val.Kind() == reflect.Ptr { val = val.Elem() } if val.Kind() != reflect.Struct { return "", errors.New("input must be a struct or pointer to struct") } // 转换为map[string]interface{},过滤零值 m := make(map[string]interface{}) typ := val.Type() for i := 0; i < val.NumField(); i++ { field := typ.Field(i) jsonTag := field.Tag.Get("json") if jsonTag == "" || jsonTag == "-" { continue } // 处理json tag,可能包含omitempty name := strings.Split(jsonTag, ",")[0] fieldVal := val.Field(i) if isZeroValue(fieldVal) { continue } m[name] = fieldVal.Interface() } // 按key排序 keys := make([]string, 0, len(m)) for k := range m { keys = append(keys, k) } sort.Strings(keys) // 构建有序JSON var buf bytes.Buffer buf.WriteByte('{') for idx, k := range keys { if idx > 0 { buf.WriteByte(',') } buf.WriteString(fmt.Sprintf(`"%s":`, k)) // 将值转为JSON valBytes, err := json.Marshal(m[k]) if err != nil { return "", err } buf.Write(valBytes) } buf.WriteByte('}') return buf.String(), nil } // isZeroValue 判断反射值是否为零值 func isZeroValue(v reflect.Value) bool { switch v.Kind() { case reflect.String: return v.String() == "" case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return v.Int() == 0 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: return v.Uint() == 0 case reflect.Float32, reflect.Float64: return v.Float() == 0 case reflect.Bool: return !v.Bool() case reflect.Slice, reflect.Map, reflect.Ptr, reflect.Interface: return v.IsNil() default: return false } } ```