zhangzengfei
2020-03-17 afbe6a5b8b15f48752fe5542c947b960941daa7c
licence.go
@@ -2,86 +2,174 @@
import (
   "encoding/json"
   "strings"
   "fmt"
   "io/ioutil"
   "os"
   "time"
   "github.com/shirou/gopsutil/cpu"
   // "github.com/shirou/gopsutil/disk"
   "github.com/shirou/gopsutil/host"
)
const key = "flzxsqc,ysyhljt."
/*
   1.0.0 采集机器码, 授权日期 然后 AES 加密, 生成Licence, 秘钥会暴露给客户端
   1.0.1 修改为RSA 非对称加密, 公钥开放. 加密内容为{注册码{机器码+公司+邮箱+手机}+过期时间+授权时间}
   1.0.2 修改Licence文件内容最终为AES加密后的内容, 然后再由公钥解密. 上个版本的bug, 仅使用非对称加密, 用户可以替换公钥
*/
type RegisterCode struct {
   MachineCode string
   Company     string
   Email       string
   Phone       string
   Version     string
}
type Licence struct {
   MachineCode string
   Expires     int64
   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.2"
   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 {
         strings.Join([]string{machineCode, c.String()}, "-")
      }
   }
   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 {
      strings.Join([]string{machineCode, host.HostID}, "-")
   }
   return GetMd5String(machineCode, true, false)
   return AESEncodeStr(json, aesKey)
}
func GenerateLicence(machineCode, timeOut, key string) string {
func DecryptRegisterCode(regCode string) []byte {
   return AESDecodeStr(regCode, aesKey)
}
func GenerateLicence(regCode, timeOut, privateKeyPath string) (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
   }
   fd, err := os.Open(privateKeyPath)
   if err != nil {
      fmt.Println(err)
      return "", err
   }
   defer fd.Close()
   privateKey, err := ioutil.ReadAll(fd)
   if err != nil {
      fmt.Println(err)
      return "", err
   }
   RSA := &RSASecurity{}
   if err := RSA.SetPrivateKey(privateKey); err != nil {
      return "", err
   }
   licenceHex, err := RSA.PriKeyENCTYPT(json)
   if err != nil {
      return "", err
   }
   return AESEncodeStr(licenceHex, aesKey), nil
}
func VerifyLicence(licenceCode string) uint32 {
   decodeData := AESDecodeStr(licenceCode, key)
   if decodeData == nil {
      return ValidationErrorMalformed
func DecryptLicenceFile(licencePath, publicKeyPath string) ([]byte, 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
   }
   return DecryptLicence(string(licenceCode), publicKeyPath)
}
func DecryptLicence(licenceCode, publicKeyPath string) ([]byte, error) {
   // 读取公钥
   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 := AESDecodeStr(licenceCode, aesKey)
   return RSA.PubKeyDECRYPT(licenceHex)
}
func VerifyLicenceFile(licencePath, publicKeyPath string) uint32 {
   licenceText, err := DecryptLicenceFile(licencePath, publicKeyPath)
   if err != nil {
      return ValidationErrorDecrypt
   }
   return _verifyLicence(licenceText)
}
func VerifyLicence(licenceCode, publicKeyPath string) uint32 {
   licenceText, err := DecryptLicence(licenceCode, publicKeyPath)
   if err != nil {
      return ValidationErrorDecrypt
   }
   return _verifyLicence(licenceText)
}
func _verifyLicence(licenceText []byte) uint32 {
   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
}