zhangzengfei
2019-11-21 99a38065bf10619a2677cb6dcbfe93ee16de69d1
licence.go
@@ -1,135 +1,147 @@
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, &registerCode); 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
}