170 lines
4.3 KiB
Go
170 lines
4.3 KiB
Go
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
|
||
}
|