package audit import ( "crypto/hmac" "encoding/hex" "encoding/json" udeModel "udeServer/internal/model" "github.com/tjfoc/gmsm/sm3" ) // CalculateHMAC computes the HMAC-SM3 of the log entry (without the // audit-state / HMAC / timestamp / id fields) with the given secret key. func CalculateHMAC(entry *udeModel.TSystemLog, secretKey string, macBytes []byte) (string, error) { // 解析log对象为字节数组,并清空旧的Hmac data, err := generateHmacBytes(entry) if err != nil { return "", err } // 计算Hmac mac := hmac.New(sm3.New, []byte(secretKey)) mac.Write(data) // 写入复用缓冲区,只清空长度,不清空容量 entryHmac := mac.Sum(macBytes[:0]) return hex.EncodeToString(entryHmac), nil } // generateHmacBytes marshals the entry and strips the fields excluded from // the MAC computation. NOTE: TSystemLog has no json tags on purpose, so the // marshalled keys equal the Go field names and this exclusion list stays in // sync with the struct definition. func generateHmacBytes(entry any) ([]byte, error) { data, err := json.Marshal(entry) if err != nil { return nil, err } var m map[string]interface{} if err = json.Unmarshal(data, &m); err != nil { return nil, err } // 移除Hmac无关字段 delete(m, "AuditStatus") delete(m, "HMac") delete(m, "CreatedAt") delete(m, "Id") signContent, err := json.Marshal(m) if err != nil { return nil, err } return signContent, nil }