package totp_tier_one import ( "cmii-uav-watchdog-common/models" "cmii-uav-watchdog-common/wdd_log" "crypto/aes" "crypto/cipher" "crypto/sha256" "encoding/base64" "errors" "fmt" "strconv" "strings" ) // Encrypt 加密字符串 // 保证使用相同的plaintext和key进行加密,在不同时间、不同机器上输出的加密字符串都是固定的 func Encrypt(plaintext string, key string) (encryptedPlaintext string, encryptError error) { // 创建hash hasher := sha256.New() hasher.Write([]byte(key)) keyBytes := hasher.Sum(nil) // 创建cipher block, err := aes.NewCipher(keyBytes) if err != nil { return "", err } // 创建gcm gcm, err := cipher.NewGCM(block) if err != nil { return "", err } // 生成确定性nonce - 使用plaintext和key的组合生成,确保对相同输入产生相同nonce nonceHasher := sha256.New() nonceHasher.Write([]byte(key + "fixed_salt_for_deterministic_result" + plaintext[:min(10, len(plaintext))])) nonceSource := nonceHasher.Sum(nil) // 创建合适大小的nonce nonce := nonceSource[:gcm.NonceSize()] // 加密 ciphertext := gcm.Seal(nil, nonce, []byte(plaintext), nil) // 将nonce和密文连接起来 result := append(nonce, ciphertext...) // 编码为base64 return base64.StdEncoding.EncodeToString(result), nil } // Decrypt 解密字符串 // 可以使用加密字符串和key在不同时间、不同机器上解密出原始plaintext func Decrypt(encrypted string, key string) (decryptedPlaintext string, decryptError error) { // 解码base64 data, err := base64.StdEncoding.DecodeString(encrypted) if err != nil { return "", err } // 创建hash hasher := sha256.New() hasher.Write([]byte(key)) keyBytes := hasher.Sum(nil) // 创建cipher block, err := aes.NewCipher(keyBytes) if err != nil { return "", err } // 创建gcm gcm, err := cipher.NewGCM(block) if err != nil { return "", err } // 检查长度 if len(data) < gcm.NonceSize() { return "", errors.New("密文太短") } // 分离nonce和密文 nonce, ciphertext := data[:gcm.NonceSize()], data[gcm.NonceSize():] // 解密 plaintext, err := gcm.Open(nil, nonce, ciphertext, nil) if err != nil { return "", err } return string(plaintext), nil } // min 返回两个整数中较小的一个 func min(a, b int) int { if a < b { return a } return b } // EncryptHostInfo 加密主机信息 func EncryptHostInfo(hostInfo models.HostInfo, key string) (encryptedHostInfo string, encryptError error) { // 生成主机唯一标识作为加密密钥 info := generateHostUniqueID(hostInfo) // 加密主机信息 encrypted, err := Encrypt(info, key) if err != nil { return "", err } return encrypted, nil } // DecryptHostInfo 解密主机信息 func DecryptHostInfo(encrypted string, hostInfo models.HostInfo, key string) (decryptedOK bool, decryptError error) { // 解密主机信息 decryptedStr, err := Decrypt(encrypted, key) if err != nil { wdd_log.Error("[DecryptHostInfo] - Decrypt失败: %v", err) return false, err } // wdd_log.Info("[DecryptHostInfo] - Decrypt成功: %s", decryptedStr) // 生成主机唯一标识作为加密密钥 hostUniqueID := generateHostUniqueID(hostInfo) if hostUniqueID != decryptedStr { wdd_log.Error("[DecryptHostInfo] - 主机信息篡改") return false, errors.New("主机信息篡改") } return true, nil } // generateHostUniqueID 生成主机唯一标识作为加密密钥 func generateHostUniqueID(hostInfo models.HostInfo) string { // hostinfo.SystemInfo.MachineID machineID := hostInfo.SystemInfo.MachineID // hostinfo.SystemInfo.KernelVersion kernelVersion := hostInfo.SystemInfo.KernelVersion // 将CPU信息中的ModelName Cores Hypervisor 拼接起来 cpuCores := hostInfo.CPUInfo.Cores cpuHypervisor := hostInfo.CPUInfo.Hypervisor cpuModelName := hostInfo.CPUInfo.ModelName cpuInfo := fmt.Sprintf("%s-%d-%s", cpuModelName, cpuCores, cpuHypervisor) // 不能使用 mac 地址,因为 每个Pod 的 mac 地址会变化 // hostinfo.SystemInfo.MachineSerial machineSerial := hostInfo.SystemInfo.MachineSerial // 将memory中的total 和 used 拼接起来 memoryTotal := hostInfo.MemoryInfo.Total // 将上述的全部信息拼接起来 info := strings.Join([]string{machineID, kernelVersion, cpuInfo, machineSerial, strconv.FormatUint(memoryTotal, 10)}, "==") return info }