From 99a38065bf10619a2677cb6dcbfe93ee16de69d1 Mon Sep 17 00:00:00 2001
From: zhangzengfei <zhangzengfei@iotlink.com>
Date: 星期四, 21 十一月 2019 17:20:05 +0800
Subject: [PATCH] fix: encrypt replace with RSA

---
 machine.go |   87 ++++++
 licence.go |  200 +++++++------
 README.md  |   51 +++
 rsa.go     |  485 ++++++++++++++++++++++++++++++++++
 4 files changed, 720 insertions(+), 103 deletions(-)

diff --git a/README.md b/README.md
index 159487d..4533534 100644
--- a/README.md
+++ b/README.md
@@ -7,20 +7,53 @@
 	"basic.com/valib/licence.git"
 )
 
-const key = "flzxsqc,ysyhljt."
-
 func main() {
+	// 鐢熸垚绉橀挜鍜屽叕閽�
+	if len(os.Args) > 1 && os.Args[1] == "-g" {
+		licence.GetRsaKey()
+		return
+	}
+
 	// 鑾峰彇鏈哄櫒鐮�
-	machineCode := licence.GetMachineCode()
+	machCode := licence.GetMachineCode()
+	fmt.Println("MachineCode: ", machCode)
 
-	// 鐢熸垚Licence
-	licenceCode := licence.GenerateLicence(machineCode, "2019-12-12 00:00:00", key)
+	// 鑾峰彇娉ㄥ唽鐮�, 鍙傛暟: 鍏徃鍚�, 鐢靛瓙閭, 鎵嬫満鍙�
+	regCode := licence.GetRegisterCode("basic.com", "dev@basic.com", "13911697509")
+	fmt.Println("Register code:", regCode)
 
-	fmt.Println("machineCode: ", machineCode)
-	fmt.Println("licenceCode: ", licenceCode)
+	fd, err := os.Open("./private.key")
+	if err != nil {
+		fmt.Println(err)
+		return
+	}
 
-	// 楠岃瘉Licence锛� 0, 鎴愬姛 1, 鏃犳晥 2, 璁惧鏈巿鏉� 3, 杩囨湡
-	fmt.Println(licence.VerifyLicence(licenceCode, key))
+	defer fd.Close()
+	privateKey, err := ioutil.ReadAll(fd)
+	if err != nil {
+		fmt.Println(err)
+		return
+	}
+
+	// 鐢熸垚Licence, 鍙傛暟: 娉ㄥ唽鐮�, 鍒版湡鏃堕棿, 绉橀挜
+	licenceCode, err := licence.GenerateLicence(regCode, "2106-01-02 15:04:05", privateKey)
+	if err != nil {
+		fmt.Println("GenerateLicence error :", err)
+		return
+	}
+	fmt.Println("licence code:", licenceCode)
+	ioutil.WriteFile("./LicenceFile", []byte(licenceCode), 0666)
+
+	// 瑙e瘑Licence鏂囦欢
+	licenceText, err := licence.DecryptLicence("./LicenceFile", "./public.pem")
+	if err != nil {
+		fmt.Println("DecryptLicence error :", err)
+		return
+	}
+	fmt.Println("licence text:", string(licenceText))
+
+	// 楠岃瘉Licence, 鍙傛暟: LicenceFile, public.pem 鐨勮矾寰� 杩斿洖: 0, 鎴愬姛 1, 鏃犳晥 2, 璁惧鏈巿鏉� 3, 杩囨湡
+	fmt.Println(licence.VerifyLicence("./LicenceFile", "./public.pem"))
 }
 
 ```
\ No newline at end of file
diff --git a/licence.go b/licence.go
index 14ed41c..31d5799 100644
--- a/licence.go
+++ b/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
 }
diff --git a/machine.go b/machine.go
new file mode 100644
index 0000000..82966df
--- /dev/null
+++ b/machine.go
@@ -0,0 +1,87 @@
+package licence
+
+import (
+	"strings"
+
+	"github.com/shirou/gopsutil/cpu"
+	psnet "github.com/shirou/gopsutil/net"
+	// "github.com/shirou/gopsutil/host"
+	// "github.com/shirou/gopsutil/disk"
+)
+
+func GetMachineCode() string {
+	var machineCode string
+
+	// CPU
+	if cpu, err := cpu.Info(); err == nil {
+		for _, c := range cpu {
+			machineCode = strings.Join([]string{machineCode, c.String()}, "-cpu-")
+		}
+	}
+
+	/* // Disk
+	if diskInfo, err := disk.Partitions(false); err == nil {
+		for _, d := range diskInfo {
+			diskSerialNumber := disk.GetDiskSerialNumber(d.Device)
+	 		strings.Join([]string{machineCode, diskSerialNumber}, "-")
+	 	}
+	}
+
+	// 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)
+}
+
+func VNetFilter(iface *psnet.InterfaceStat) bool {
+	if iface.HardwareAddr == "" {
+		return true
+	}
+
+	vNetNamePrefix := [...]string{
+		"docker",
+		"br-",
+		"veth",
+		"Npcap",
+		"VirtualBox",
+	}
+
+	for _, v := range vNetNamePrefix {
+		if strings.HasPrefix(iface.Name, v) {
+			return true
+		}
+	}
+
+	/* 鏆傛椂鏀惧純杩囨护铏氭嫙鏈篗AC锛屼細瀵艰嚧杩愯鍦ㄨ櫄鎷熸満鏃讹紝鏈哄櫒鐮佷笉鍖呭惈MAC鍦板潃鐨勯棶棰樸�傚鏋滀笉鍏佽鏈嶅姟杩愯鍦ㄨ櫄鎷熸満锛屽啀鍚敤骞舵彁绀鸿鍛�
+	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
+	}
+
+	for _, v := range vNetAddrPrefix {
+		if strings.HasPrefix(iface.HardwareAddr, v) {
+			return true
+		}
+	}
+	*/
+
+	return false
+}
diff --git a/rsa.go b/rsa.go
new file mode 100644
index 0000000..9391146
--- /dev/null
+++ b/rsa.go
@@ -0,0 +1,485 @@
+package licence
+
+import (
+	"bytes"
+	"crypto/rand"
+	"crypto/rsa"
+	"crypto/x509"
+	"encoding/pem"
+	"errors"
+	"io"
+	"io/ioutil"
+	"math/big"
+	"os"
+)
+
+const (
+	privateFileName = "private.key"
+	publicFileName  = "public.pem"
+
+	privateKeyPrefix = "BASIC AIOTLINK PRIVATE KEY "
+	publicKeyPrefix  = "BASIC AIOTLINK PUBLIC KEY "
+)
+
+type RSASecurity struct {
+	pubStr []byte          //鍏挜瀛楃涓�
+	priStr []byte          //绉侀挜瀛楃涓�
+	pubkey *rsa.PublicKey  //鍏挜
+	prikey *rsa.PrivateKey //绉侀挜
+}
+
+func GetRsaKey() error {
+	privateKey, err := rsa.GenerateKey(rand.Reader, 4096)
+	if err != nil {
+		return err
+	}
+	x509PrivateKey := x509.MarshalPKCS1PrivateKey(privateKey)
+	privateFile, err := os.Create(privateFileName)
+	if err != nil {
+		return err
+	}
+	defer privateFile.Close()
+	privateBlock := pem.Block{
+		Type:  privateKeyPrefix,
+		Bytes: x509PrivateKey,
+	}
+
+	if err = pem.Encode(privateFile, &privateBlock); err != nil {
+		return err
+	}
+	publicKey := privateKey.PublicKey
+	x509PublicKey, err := x509.MarshalPKIXPublicKey(&publicKey)
+	if err != nil {
+		panic(err)
+	}
+	publicFile, _ := os.Create(publicFileName)
+	defer publicFile.Close()
+	publicBlock := pem.Block{
+		Type:  publicKeyPrefix,
+		Bytes: x509PublicKey,
+	}
+	if err = pem.Encode(publicFile, &publicBlock); err != nil {
+		return err
+	}
+	return nil
+}
+
+// 璁剧疆鍏挜
+func (rsas *RSASecurity) SetPublicKey(pubStr []byte) (err error) {
+	rsas.pubStr = pubStr
+	rsas.pubkey, err = rsas.GetPublickey()
+	return err
+}
+
+// 璁剧疆绉侀挜
+func (rsas *RSASecurity) SetPrivateKey(priStr []byte) (err error) {
+	rsas.priStr = priStr
+	rsas.prikey, err = rsas.GetPrivatekey()
+	return err
+}
+
+// *rsa.PublicKey
+func (rsas *RSASecurity) GetPrivatekey() (*rsa.PrivateKey, error) {
+	return getPriKey(rsas.priStr)
+}
+
+// *rsa.PrivateKey
+func (rsas *RSASecurity) GetPublickey() (*rsa.PublicKey, error) {
+	return getPubKey(rsas.pubStr)
+}
+
+// 鍏挜鍔犲瘑
+func (rsas *RSASecurity) PubKeyENCTYPT(input []byte) ([]byte, error) {
+	if rsas.pubkey == nil {
+		return []byte(""), errors.New(`Please set the public key in advance`)
+	}
+	output := bytes.NewBuffer(nil)
+	err := pubKeyIO(rsas.pubkey, bytes.NewReader(input), output, true)
+	if err != nil {
+		return []byte(""), err
+	}
+	return ioutil.ReadAll(output)
+}
+
+// 鍏挜瑙e瘑
+func (rsas *RSASecurity) PubKeyDECRYPT(input []byte) ([]byte, error) {
+	if rsas.pubkey == nil {
+		return []byte(""), errors.New(`Please set the public key in advance`)
+	}
+	output := bytes.NewBuffer(nil)
+	err := pubKeyIO(rsas.pubkey, bytes.NewReader(input), output, false)
+	if err != nil {
+		return []byte(""), err
+	}
+	return ioutil.ReadAll(output)
+}
+
+// 绉侀挜鍔犲瘑
+func (rsas *RSASecurity) PriKeyENCTYPT(input []byte) ([]byte, error) {
+	if rsas.prikey == nil {
+		return []byte(""), errors.New(`Please set the private key in advance`)
+	}
+	output := bytes.NewBuffer(nil)
+	err := priKeyIO(rsas.prikey, bytes.NewReader(input), output, true)
+	if err != nil {
+		return []byte(""), err
+	}
+	return ioutil.ReadAll(output)
+}
+
+// 绉侀挜瑙e瘑
+func (rsas *RSASecurity) PriKeyDECRYPT(input []byte) ([]byte, error) {
+	if rsas.prikey == nil {
+		return []byte(""), errors.New(`Please set the private key in advance`)
+	}
+	output := bytes.NewBuffer(nil)
+	err := priKeyIO(rsas.prikey, bytes.NewReader(input), output, false)
+	if err != nil {
+		return []byte(""), err
+	}
+
+	return ioutil.ReadAll(output)
+}
+
+var (
+	ErrDataToLarge     = errors.New("message too long for RSA public key size")
+	ErrDataLen         = errors.New("data length error")
+	ErrDataBroken      = errors.New("data broken, first byte is not zero")
+	ErrKeyPairDismatch = errors.New("data is not encrypted by the private key")
+	ErrDecryption      = errors.New("decryption error")
+	ErrPublicKey       = errors.New("get public key error")
+	ErrPrivateKey      = errors.New("get private key error")
+)
+
+// 璁剧疆鍏挜
+func getPubKey(publickey []byte) (*rsa.PublicKey, error) {
+	// decode public key
+	block, _ := pem.Decode(publickey)
+	if block == nil {
+		return nil, errors.New("get public key error")
+	}
+	// x509 parse public key
+	pub, err := x509.ParsePKIXPublicKey(block.Bytes)
+	if err != nil {
+		return nil, err
+	}
+	return pub.(*rsa.PublicKey), err
+}
+
+// 璁剧疆绉侀挜
+func getPriKey(privatekey []byte) (*rsa.PrivateKey, error) {
+	block, _ := pem.Decode(privatekey)
+	if block == nil {
+		return nil, errors.New("get private key error")
+	}
+	pri, err := x509.ParsePKCS1PrivateKey(block.Bytes)
+	if err == nil {
+		return pri, nil
+	}
+	pri2, err := x509.ParsePKCS8PrivateKey(block.Bytes)
+	if err != nil {
+		return nil, err
+	}
+	return pri2.(*rsa.PrivateKey), nil
+}
+
+// 鍏挜鍔犲瘑鎴栬В瀵哹yte
+func pubKeyByte(pub *rsa.PublicKey, in []byte, isEncrytp bool) ([]byte, error) {
+	k := (pub.N.BitLen() + 7) / 8
+	if isEncrytp {
+		k = k - 11
+	}
+	if len(in) <= k {
+		if isEncrytp {
+			return rsa.EncryptPKCS1v15(rand.Reader, pub, in)
+		} else {
+			return pubKeyDecrypt(pub, in)
+		}
+	} else {
+		iv := make([]byte, k)
+		out := bytes.NewBuffer(iv)
+		if err := pubKeyIO(pub, bytes.NewReader(in), out, isEncrytp); err != nil {
+			return nil, err
+		}
+		return ioutil.ReadAll(out)
+	}
+}
+
+// 绉侀挜鍔犲瘑鎴栬В瀵哹yte
+func priKeyByte(pri *rsa.PrivateKey, in []byte, isEncrytp bool) ([]byte, error) {
+	k := (pri.N.BitLen() + 7) / 8
+	if isEncrytp {
+		k = k - 11
+	}
+	if len(in) <= k {
+		if isEncrytp {
+			return priKeyEncrypt(rand.Reader, pri, in)
+		} else {
+			return rsa.DecryptPKCS1v15(rand.Reader, pri, in)
+		}
+	} else {
+		iv := make([]byte, k)
+		out := bytes.NewBuffer(iv)
+		if err := priKeyIO(pri, bytes.NewReader(in), out, isEncrytp); err != nil {
+			return nil, err
+		}
+		return ioutil.ReadAll(out)
+	}
+}
+
+// 鍏挜鍔犲瘑鎴栬В瀵哛eader
+func pubKeyIO(pub *rsa.PublicKey, in io.Reader, out io.Writer, isEncrytp bool) (err error) {
+	k := (pub.N.BitLen() + 7) / 8
+	if isEncrytp {
+		k = k - 11
+	}
+	buf := make([]byte, k)
+	var b []byte
+	size := 0
+	for {
+		size, err = in.Read(buf)
+		if err != nil {
+			if err == io.EOF {
+				return nil
+			}
+			return err
+		}
+		if size < k {
+			b = buf[:size]
+		} else {
+			b = buf
+		}
+		if isEncrytp {
+			b, err = rsa.EncryptPKCS1v15(rand.Reader, pub, b)
+		} else {
+			b, err = pubKeyDecrypt(pub, b)
+		}
+		if err != nil {
+			return err
+		}
+		if _, err = out.Write(b); err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+// 绉侀挜鍔犲瘑鎴栬В瀵哛eader
+func priKeyIO(pri *rsa.PrivateKey, r io.Reader, w io.Writer, isEncrytp bool) (err error) {
+	k := (pri.N.BitLen() + 7) / 8
+	if isEncrytp {
+		k = k - 11
+	}
+	buf := make([]byte, k)
+	var b []byte
+	size := 0
+	for {
+		size, err = r.Read(buf)
+		if err != nil {
+			if err == io.EOF {
+				return nil
+			}
+			return err
+		}
+		if size < k {
+			b = buf[:size]
+		} else {
+			b = buf
+		}
+		if isEncrytp {
+			b, err = priKeyEncrypt(rand.Reader, pri, b)
+		} else {
+			b, err = rsa.DecryptPKCS1v15(rand.Reader, pri, b)
+		}
+		if err != nil {
+			return err
+		}
+		if _, err = w.Write(b); err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+// 鍏挜瑙e瘑
+func pubKeyDecrypt(pub *rsa.PublicKey, data []byte) ([]byte, error) {
+	k := (pub.N.BitLen() + 7) / 8
+	if k != len(data) {
+		return nil, ErrDataLen
+	}
+	m := new(big.Int).SetBytes(data)
+	if m.Cmp(pub.N) > 0 {
+		return nil, ErrDataToLarge
+	}
+	m.Exp(m, big.NewInt(int64(pub.E)), pub.N)
+	d := leftPad(m.Bytes(), k)
+	if d[0] != 0 {
+		return nil, ErrDataBroken
+	}
+	if d[1] != 0 && d[1] != 1 {
+		return nil, ErrKeyPairDismatch
+	}
+	var i = 2
+	for ; i < len(d); i++ {
+		if d[i] == 0 {
+			break
+		}
+	}
+	i++
+	if i == len(d) {
+		return nil, nil
+	}
+	return d[i:], nil
+}
+
+// 绉侀挜鍔犲瘑
+func priKeyEncrypt(rand io.Reader, priv *rsa.PrivateKey, hashed []byte) ([]byte, error) {
+	tLen := len(hashed)
+	k := (priv.N.BitLen() + 7) / 8
+	if k < tLen+11 {
+		return nil, ErrDataLen
+	}
+	em := make([]byte, k)
+	em[1] = 1
+	for i := 2; i < k-tLen-1; i++ {
+		em[i] = 0xff
+	}
+	copy(em[k-tLen:k], hashed)
+	m := new(big.Int).SetBytes(em)
+	c, err := decrypt(rand, priv, m)
+	if err != nil {
+		return nil, err
+	}
+	copyWithLeftPad(em, c.Bytes())
+	return em, nil
+}
+
+// 浠巆rypto/rsa澶嶅埗
+var bigZero = big.NewInt(0)
+var bigOne = big.NewInt(1)
+
+// 浠巆rypto/rsa澶嶅埗
+func encrypt(c *big.Int, pub *rsa.PublicKey, m *big.Int) *big.Int {
+	e := big.NewInt(int64(pub.E))
+	c.Exp(m, e, pub.N)
+	return c
+}
+
+// 浠巆rypto/rsa澶嶅埗
+func decrypt(random io.Reader, priv *rsa.PrivateKey, c *big.Int) (m *big.Int, err error) {
+	if c.Cmp(priv.N) > 0 {
+		err = ErrDecryption
+		return
+	}
+	var ir *big.Int
+	if random != nil {
+		var r *big.Int
+
+		for {
+			r, err = rand.Int(random, priv.N)
+			if err != nil {
+				return
+			}
+			if r.Cmp(bigZero) == 0 {
+				r = bigOne
+			}
+			var ok bool
+			ir, ok = modInverse(r, priv.N)
+			if ok {
+				break
+			}
+		}
+		bigE := big.NewInt(int64(priv.E))
+		rpowe := new(big.Int).Exp(r, bigE, priv.N)
+		cCopy := new(big.Int).Set(c)
+		cCopy.Mul(cCopy, rpowe)
+		cCopy.Mod(cCopy, priv.N)
+		c = cCopy
+	}
+	if priv.Precomputed.Dp == nil {
+		m = new(big.Int).Exp(c, priv.D, priv.N)
+	} else {
+		m = new(big.Int).Exp(c, priv.Precomputed.Dp, priv.Primes[0])
+		m2 := new(big.Int).Exp(c, priv.Precomputed.Dq, priv.Primes[1])
+		m.Sub(m, m2)
+		if m.Sign() < 0 {
+			m.Add(m, priv.Primes[0])
+		}
+		m.Mul(m, priv.Precomputed.Qinv)
+		m.Mod(m, priv.Primes[0])
+		m.Mul(m, priv.Primes[1])
+		m.Add(m, m2)
+
+		for i, values := range priv.Precomputed.CRTValues {
+			prime := priv.Primes[2+i]
+			m2.Exp(c, values.Exp, prime)
+			m2.Sub(m2, m)
+			m2.Mul(m2, values.Coeff)
+			m2.Mod(m2, prime)
+			if m2.Sign() < 0 {
+				m2.Add(m2, prime)
+			}
+			m2.Mul(m2, values.R)
+			m.Add(m, m2)
+		}
+	}
+	if ir != nil {
+		m.Mul(m, ir)
+		m.Mod(m, priv.N)
+	}
+
+	return
+}
+
+// 浠巆rypto/rsa澶嶅埗
+func copyWithLeftPad(dest, src []byte) {
+	numPaddingBytes := len(dest) - len(src)
+	for i := 0; i < numPaddingBytes; i++ {
+		dest[i] = 0
+	}
+	copy(dest[numPaddingBytes:], src)
+}
+
+// 浠巆rypto/rsa澶嶅埗
+func nonZeroRandomBytes(s []byte, rand io.Reader) (err error) {
+	_, err = io.ReadFull(rand, s)
+	if err != nil {
+		return
+	}
+	for i := 0; i < len(s); i++ {
+		for s[i] == 0 {
+			_, err = io.ReadFull(rand, s[i:i+1])
+			if err != nil {
+				return
+			}
+			s[i] ^= 0x42
+		}
+	}
+	return
+}
+
+// 浠巆rypto/rsa澶嶅埗
+func leftPad(input []byte, size int) (out []byte) {
+	n := len(input)
+	if n > size {
+		n = size
+	}
+	out = make([]byte, size)
+	copy(out[len(out)-n:], input)
+	return
+}
+
+// 浠巆rypto/rsa澶嶅埗
+func modInverse(a, n *big.Int) (ia *big.Int, ok bool) {
+	g := new(big.Int)
+	x := new(big.Int)
+	y := new(big.Int)
+	g.GCD(x, y, a, n)
+	if g.Cmp(bigOne) != 0 {
+		return
+	}
+	if x.Cmp(bigOne) < 0 {
+		x.Add(x, n)
+	}
+	return x, true
+}

--
Gitblit v1.8.0