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, ®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
}
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