From 6a939f7082f46bc853b5e9e05a96143c637fc191 Mon Sep 17 00:00:00 2001 From: zhaoxiaorong Date: Fri, 7 Feb 2025 17:47:11 +0800 Subject: [PATCH] licence --- licence/licence.go | 296 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 296 insertions(+) create mode 100644 licence/licence.go diff --git a/licence/licence.go b/licence/licence.go new file mode 100644 index 0000000..1dece3f --- /dev/null +++ b/licence/licence.go @@ -0,0 +1,296 @@ +// 校验授权文件 + +package licence + +import ( + "crypto/sha256" + "encoding/base64" + "encoding/json" + "errors" + "fmt" + "io" + "log" + "net" + "os" + "path" + "sort" + "strconv" + "strings" + "time" + + "git.apinb.com/bsm-sdk/core/crypto/aes" + "git.apinb.com/bsm-sdk/core/utils" + "github.com/shirou/gopsutil/cpu" +) + +// -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +// CPU 信息 +type CpuInfo struct { + Cpu int32 `json:"cpu"` + Cores int32 `json:"cores"` + ModelName string `json:"modelName"` + VendorId string `json:"vendorId"` + PhysicalId string `json:"physicalId"` +} + +// -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +type MachineInfo struct { + MacAddrs []string `json:"macAddrs"` + Cpus []*CpuInfo `json:"cpus"` +} + +// -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +// 授权信息 +type Licence struct { + CompanyName string `json:"licence_to"` // 授权公司 + CreateDate int `json:"create"` // 生效日期 + ExpireDate int `json:"expire"` // 有效期 + MachineCodes []string `json:"machine_codes"` // 机器码列表 +} + +// -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +var ( + des_key string + des_iv string + + Check_Licence_File bool = true // 是否检查部署授权文件 +) + +// -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +const ( + signKey = "8E853B589944FF7A56BEF02AAA51D6F4" + LICENCE_KEY = "TRAIN_LICENCE_KEY" +) + +// -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +func init() { + des_key = base64.StdEncoding.EncodeToString([]byte(signKey)) + des_iv = base64.StdEncoding.EncodeToString([]byte(signKey[:16])) +} + +func WatchCheckLicence(licPath, licName string) { + for { + if CheckLicence(licPath, licName) == false { + log.Println("授权文件失效,请重新部署授权文件:", licPath) + os.Exit(99) + } + time.Sleep(time.Hour * 1) + } +} + +// -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +func CheckLicence(licPath, licName string) bool { + // 加载授权文件 + content, err := LoadLicenceFromFile(licPath) + if err != nil { + return false + } + + // 解密解码授权文件 + var l Licence + if err := DecodeLicence(content, &l); err != nil { + return false + } + + return l.VerifyLicence(licName) +} + +// -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +// Licence 校验 +func (l *Licence) VerifyLicence(licName string) bool { + // 用于开发环境,为授权公司时跳过验证 + if l.CompanyName == licName { + return true + } + + today := StrToInt(time.Now().Format("20060102")) + // 机器日期不在授权文件有限期之内 (早于生效日期,或超过有效期) + if (today < l.CreateDate) || (today > l.ExpireDate) { + return false + } + + // 机器码不在授权列表中 + machine_code := GetMachineCode() + if (len(machine_code) == 0) || !l.ValidMachineCode(machine_code) { + return false + } + + return true +} + +// -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +// 检查机器码是否存在授权列表中 +func (l *Licence) ValidMachineCode(code string) bool { + result := false + for _, c := range l.MachineCodes { + if c == code { + result = true + break + } + } + + return result +} + +// -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +// 加载授权文件 +func LoadLicenceFromFile(licPath string) (string, error) { + key_path := path.Join(licPath, "licence.key") + if utils.PathExists(key_path) { + file, err := os.Open(key_path) + if err != nil { + return "", err + } + defer file.Close() + + content, err := io.ReadAll(file) + if err != nil { + return "", err + } + + return string(content), nil + } + return "", errors.New("授权文件不存在") +} + +// -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +// 解密授权文件内容,并析构至 Licence +func DecodeLicence(content string, licence *Licence) error { + if len(content) == 0 { + return errors.New("授权文件无效") + } + + if txt := DecryptStr(content); len(txt) > 0 { + if err := json.Unmarshal([]byte(txt), licence); err != nil { + return err + } + } + + return nil +} + +// -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +// 字符串解密 +func DecryptStr(txt string) string { + result := "" + + if len(txt) > 0 { + result = aes.Decrypt(des_key, des_iv, txt) + } + + return result +} + +// -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +// 加密字符串 +func EncryptStr(txt string) string { + result := "" + + if len(txt) > 0 { + result = aes.Encrypt(des_key, des_iv, txt) + } + + return result +} + +// -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +// 生成授权文件 +func BuildLicence(company_name string, Create_date int, expire_date int, machine_codes []string) (string, error) { + // 构造licence + licence := &Licence{ + CompanyName: company_name, + CreateDate: Create_date, + ExpireDate: expire_date, + MachineCodes: machine_codes, + } + + content, err := json.Marshal(licence) + if err != nil { + return "", err + } + // 对json加密 + result := EncryptStr(string(content)) + return result, nil +} + +// -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +// 生成激活码 +func GetLicenceCode(machinceCode string) string { + return hash256(machinceCode + "&" + signKey) +} + +// -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +// 获取CPU信息 +func getCpuInfo() []*CpuInfo { + cpus, _ := cpu.Info() + cinfos := make([]*CpuInfo, len(cpus)) + for k, v := range cpus { + cinfos[k] = &CpuInfo{ + Cpu: v.CPU, + ModelName: v.ModelName, + Cores: v.Cores, + VendorId: v.VendorID, + PhysicalId: v.PhysicalID, + } + } + sort.SliceStable(cinfos, func(i, j int) bool { + if cinfos[i].Cores != cinfos[j].Cores { + return cinfos[i].Cores > cinfos[j].Cores + } + return cinfos[i].Cpu < cinfos[j].Cpu + }) + return cinfos +} + +// -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +// 获取MAC地址 +func getMacAddrs() []string { + var macs []string + netfaces, err := net.Interfaces() + if err != nil { + return macs + } + for i := 0; i < len(netfaces); i++ { + if (netfaces[i].Flags&net.FlagUp) != 0 && (netfaces[i].Flags&net.FlagLoopback) == 0 { + addrs, _ := netfaces[i].Addrs() + for _, address := range addrs { + ipnet, ok := address.(*net.IPNet) + if ok && ipnet.IP.IsGlobalUnicast() { + macs = append(macs, netfaces[i].HardwareAddr.String()) + } + } + } + } + sort.Slice(macs, func(i, j int) bool { + return macs[i] > macs[j] + }) + return macs +} + +// -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +// 获取机器码 +func GetMachineCode() string { + info := MachineInfo{MacAddrs: getMacAddrs(), Cpus: getCpuInfo()} + json, _ := json.Marshal(info) + machineCode := hash256(string(json)) + licenceCode := GetLicenceCode(machineCode) + return licenceCode +} + +// -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +// 加密 +func hash256(d string) string { + h := sha256.New() + h.Write([]byte(d)) + bs := fmt.Sprintf("%x", h.Sum(nil)) + return strings.ToUpper(bs) +} + +// -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +func StrToInt(valstr string) int { + val, err := strconv.Atoi(valstr) + if err != nil { + val = 0 + } + return val +}