| | |
| | | package licence |
| | | |
| | | import ( |
| | | "encoding/base64" |
| | | "encoding/json" |
| | | "strings" |
| | | "io/ioutil" |
| | | "os" |
| | | "time" |
| | | |
| | | "github.com/shirou/gopsutil/cpu" |
| | | "github.com/shirou/gopsutil/host" |
| | | psnet "github.com/shirou/gopsutil/net" |
| | | // "github.com/shirou/gopsutil/disk" |
| | | ) |
| | | |
| | | type Licence struct { |
| | | type RegisterCode struct { |
| | | MachineCode string |
| | | Expires int64 |
| | | Company string |
| | | Email string |
| | | Phone string |
| | | Version string |
| | | } |
| | | |
| | | type Licence struct { |
| | | RegCode RegisterCode |
| | | Expires int64 |
| | | Timestamp int64 |
| | | } |
| | | |
| | | const ( |
| | | ValidationErrorMalformed uint32 = iota + 1 // Licence is malformed |
| | | ValidationErrorUnverifiableHost // Licence could not be verified because of signing problems |
| | | ValidationErrorExpired // Signature validation failed |
| | | ValidationErrorDecrypt uint32 = iota + 1 // Licence is malformed |
| | | ValidationErrorUnverifiableHost // Host unauthorized |
| | | ValidationErrorExpired // Signature expired |
| | | ValidationErrorMalformed |
| | | |
| | | Version = "1.0.1" |
| | | aesKey = "www.aiotlink.com" |
| | | ) |
| | | |
| | | func GetMachineCode() string { |
| | | var machineCode string |
| | | func GetRegisterCode(company, email, phone string) string { |
| | | mCode := GetMachineCode() |
| | | |
| | | // CPU |
| | | if cpu, err := cpu.Info(); err == nil { |
| | | for _, c := range cpu { |
| | | machineCode = strings.Join([]string{machineCode, c.String()}, "-cpu-") |
| | | } |
| | | } |
| | | regCode := RegisterCode{mCode, company, email, phone, Version} |
| | | |
| | | // // Disk |
| | | // if diskInfo, err := disk.Partitions(false); err == nil { |
| | | // for _, d := range diskInfo { |
| | | // diskSerialNumber := disk.GetDiskSerialNumber(d.Device) |
| | | // strings.Join([]string{machineCode, diskSerialNumber}, "-") |
| | | // } |
| | | // } |
| | | json, _ := json.Marshal(regCode) |
| | | |
| | | // Host |
| | | if host, err := host.Info(); err == nil { |
| | | machineCode = strings.Join([]string{machineCode, host.HostID}, "-host-") |
| | | } |
| | | |
| | | // Net |
| | | if net, err := psnet.Interfaces(); err == nil { |
| | | for _, n := range net { |
| | | if n.MTU == 1500 && !VNetFilter(&n) { |
| | | machineCode = strings.Join([]string{machineCode, n.HardwareAddr}, "-mac-") |
| | | } |
| | | } |
| | | } |
| | | |
| | | return GetMd5String(machineCode, true, false) |
| | | return AESEncodeStr(json, aesKey) |
| | | } |
| | | |
| | | func VNetFilter(iface *psnet.InterfaceStat) bool { |
| | | vNetNamePrefix := [...]string{ |
| | | "docker", |
| | | "br-", |
| | | "veth", |
| | | "Npcap", |
| | | "VirtualBox", |
| | | } |
| | | |
| | | vNetAddrPrefix := [...]string{ |
| | | "00:05:69", //vmware1 |
| | | "00:0C:29", //vmware2 |
| | | "00:50:56", //vmware3 |
| | | "00:1c:14", //vmware4 |
| | | "00:1C:42", //parallels1 |
| | | "00:03:FF", //microsoft virtual pc |
| | | "00:0F:4B", //virtual iron 4 |
| | | "00:16:3E", //red hat xen , oracle vm , xen source, novell xen |
| | | "08:00:27", //virtualbox |
| | | } |
| | | |
| | | if iface.HardwareAddr == "" { |
| | | return true |
| | | } |
| | | |
| | | for _, v := range vNetAddrPrefix { |
| | | if strings.HasPrefix(iface.HardwareAddr, v) { |
| | | return true |
| | | } |
| | | } |
| | | |
| | | for _, v := range vNetNamePrefix { |
| | | if strings.HasPrefix(iface.Name, v) { |
| | | return true |
| | | } |
| | | } |
| | | |
| | | return false |
| | | func DecryptRegisterCode(regCode string) []byte { |
| | | return AESDecodeStr(regCode, aesKey) |
| | | } |
| | | |
| | | func GenerateLicence(machineCode, timeOut, key string) string { |
| | | func GenerateLicence(regCode, timeOut string, privateKey []byte) (string, error) { |
| | | timeLayout := "2006-01-02 15:04:05" //转化所需模板 |
| | | loc, _ := time.LoadLocation("Local") //获取时区 |
| | | tmp, _ := time.ParseInLocation(timeLayout, timeOut, loc) |
| | | timestamp := tmp.Unix() |
| | | exp := tmp.Unix() |
| | | now := time.Now().Unix() |
| | | |
| | | licence := Licence{machineCode, timestamp} |
| | | regCodeText := AESDecodeStr(regCode, aesKey) |
| | | var registerCode RegisterCode |
| | | if err := json.Unmarshal(regCodeText, ®isterCode); err != nil { |
| | | return "", err |
| | | } |
| | | |
| | | json, _ := json.Marshal(licence) |
| | | return AESEncodeStr(json, key) |
| | | licence := Licence{registerCode, exp, now} |
| | | json, err := json.Marshal(licence) |
| | | if err != nil { |
| | | return "", err |
| | | } |
| | | |
| | | RSA := &RSASecurity{} |
| | | if err := RSA.SetPrivateKey(privateKey); err != nil { |
| | | return "", err |
| | | } |
| | | |
| | | licenceHex, err := RSA.PriKeyENCTYPT(json) |
| | | if err != nil { |
| | | return "", err |
| | | } |
| | | |
| | | licenceText := base64.StdEncoding.EncodeToString(licenceHex) |
| | | |
| | | return licenceText, nil |
| | | } |
| | | |
| | | func VerifyLicence(licenceCode, key string) uint32 { |
| | | decodeData := AESDecodeStr(licenceCode, key) |
| | | if decodeData == nil { |
| | | return ValidationErrorMalformed |
| | | func DecryptLicence(licencePath, publicKeyPath string) ([]byte, error) { |
| | | var publicKey, licenceCode []byte |
| | | var fdLic, fdPub *os.File |
| | | var err error |
| | | |
| | | // 读取Licence File |
| | | fdLic, err = os.Open(licencePath) |
| | | if err != nil { |
| | | return nil, err |
| | | } |
| | | defer fdLic.Close() |
| | | |
| | | licenceCode, err = ioutil.ReadAll(fdLic) |
| | | if err != nil { |
| | | return nil, err |
| | | } |
| | | |
| | | // 读取公钥 |
| | | fdPub, err = os.Open(publicKeyPath) |
| | | if err != nil { |
| | | return nil, err |
| | | } |
| | | defer fdPub.Close() |
| | | |
| | | publicKey, err = ioutil.ReadAll(fdPub) |
| | | if err != nil { |
| | | return nil, err |
| | | } |
| | | |
| | | RSA := &RSASecurity{} |
| | | if err := RSA.SetPublicKey(publicKey); err != nil { |
| | | return nil, err |
| | | } |
| | | |
| | | licenceHex, _ := base64.StdEncoding.DecodeString(string(licenceCode)) |
| | | |
| | | return RSA.PubKeyDECRYPT(licenceHex) |
| | | } |
| | | |
| | | func VerifyLicence(licencePath, publicKeyPath string) uint32 { |
| | | licenceText, err := DecryptLicence(licencePath, publicKeyPath) |
| | | if err != nil { |
| | | return ValidationErrorDecrypt |
| | | } |
| | | |
| | | var licence Licence |
| | | |
| | | if err := json.Unmarshal(decodeData, &licence); err != nil { |
| | | if err := json.Unmarshal(licenceText, &licence); err != nil { |
| | | return ValidationErrorMalformed |
| | | } |
| | | |
| | | code := GetMachineCode() |
| | | if licence.MachineCode != code { |
| | | return ValidationErrorUnverifiableHost |
| | | } |
| | | |
| | | // 判断过期 |
| | | now := time.Now().Unix() |
| | | if now > licence.Expires { |
| | | return ValidationErrorExpired |
| | | } |
| | | |
| | | // 判断机器码 |
| | | mCode := GetMachineCode() |
| | | if licence.RegCode.MachineCode != mCode { |
| | | return ValidationErrorUnverifiableHost |
| | | } |
| | | |
| | | return 0 |
| | | } |