liscense-utils.go 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. package comm
  2. import (
  3. "crypto/aes"
  4. "crypto/cipher"
  5. "crypto/rsa"
  6. "crypto/sha1"
  7. "crypto/sha256"
  8. "crypto/x509"
  9. "encoding/base64"
  10. "encoding/pem"
  11. "errors"
  12. "fmt"
  13. "hash"
  14. "io"
  15. "math"
  16. "crypto/rand"
  17. mrand "math/rand"
  18. "strconv"
  19. "strings"
  20. "time"
  21. )
  22. // 实现php的sha1()方法,返回的是byte转换的字符串,如果需要转成16进制,可以使用hex.EncodeToString
  23. func GetSha1(str string) string {
  24. h := sha1.New()
  25. io.WriteString(h, str)
  26. return string(h.Sum(nil))
  27. }
  28. // 右边补全字符串实现方法,主要实现php的str_pad()方法
  29. func StrPadRight(input string, padLength int, padString string) string {
  30. output := ""
  31. inputLen := len(input)
  32. if inputLen >= padLength {
  33. return input
  34. }
  35. ll := padLength - inputLen
  36. for i := 1; i <= ll; i = i + len(padString) {
  37. output += padString
  38. }
  39. return input + output
  40. }
  41. // url安全模式decode字符串
  42. func UrlSafeB64decode(str string) (result []byte) {
  43. str = strings.Replace(str, "-", "+", -1)
  44. str = strings.Replace(str, "_", "/", -1)
  45. mod4 := len(str) % 4
  46. if mod4 != 0 {
  47. str = str + "===="[0:mod4]
  48. }
  49. result, _ = base64.StdEncoding.DecodeString(str)
  50. return result
  51. }
  52. // base64字符串,替换转换为安全模式
  53. func UrlSafeB64encode(str string) (result string) {
  54. str = strings.Replace(str, "+", "-", -1)
  55. str = strings.Replace(str, "/", "_", -1)
  56. return str
  57. }
  58. // 使用aes-256-gcm方式解密字符串,主要针对php的openssl_decrypt()方法,注意在php7.1后增加了tag和add参数
  59. func DecodeAesGcm(encryptData string, hex_key string, hex_add string) ([]byte, error) {
  60. tagSize := 16 //nonceSize,tag的长度,用于open时候生成tag,默认12
  61. key := []byte(hex_key)
  62. add := []byte(hex_add)
  63. block, err := aes.NewCipher(key) //生成加解密用的block
  64. if err != nil {
  65. return []byte(""), err
  66. }
  67. //根据不同加密算法,也有不同tag长度的方法设定和调用,比如NewGCMWithTagSize、newGCMWithNonceAndTagSize
  68. aesgcm, err := cipher.NewGCMWithNonceSize(block, tagSize)
  69. if err != nil {
  70. return []byte(""), err
  71. }
  72. decodeEncryptStr := UrlSafeB64decode(encryptData)
  73. ciphertext := decodeEncryptStr
  74. if len(ciphertext) <= aesgcm.NonceSize() { // 长度应该>iv
  75. return []byte(""), errors.New("string: too short") //解密失败
  76. }
  77. iv := ciphertext[:aesgcm.NonceSize()] //分离出IV
  78. ciphertext = ciphertext[aesgcm.NonceSize():] // 密文,tag是调用open方法时候通过密文和前面new时候传的size来进行截取的
  79. plaintext, err := aesgcm.Open(nil, iv, ciphertext, add)
  80. return plaintext, err
  81. }
  82. // 使用aes-256-gcm加密数据,主要针对php的openssl_encrypt()方法,注意在php7.1后增加了tag和add参数
  83. func EncodeAesGcm(data string, hex_key string, hex_add string) (result string, error error) {
  84. tagSize := 16 //nonceSize,tag的长度,用于open时候生成tag,默认12
  85. key := []byte(hex_key)
  86. add := []byte(hex_add)
  87. block, err := aes.NewCipher(key) //生成加解密用的block
  88. if err != nil {
  89. return result, err
  90. }
  91. //根据不同加密算法,也有不同tag长度的方法设定和调用,比如NewGCMWithTagSize、newGCMWithNonceAndTagSize
  92. aesgcm, err := cipher.NewGCMWithNonceSize(block, tagSize)
  93. if err != nil {
  94. return result, err
  95. }
  96. plaintext := []byte(data)
  97. iv := make([]byte, tagSize) // NonceSize=12
  98. rand.Read(iv) //获取随机值
  99. ciphertext := aesgcm.Seal(iv, iv, plaintext, add) //加密,密文为:iv+密文+tag
  100. result = base64.StdEncoding.EncodeToString(ciphertext)
  101. result = UrlSafeB64encode(result)
  102. return result, nil // 生成的BS64
  103. }
  104. func GenSecretKey(appId string, appSecret string) string {
  105. key := appId + "&" + appSecret
  106. sha1_str := GetSha1(key)
  107. str10 := "0"
  108. pack64, _ := strconv.ParseUint(str10, 10, 32) //对应php的pack()方法,字符串转换为uint类型
  109. pack32 := uint32(pack64)
  110. str_pad := StrPadRight(sha1_str, 32, fmt.Sprintf("%d", pack32))
  111. return base64.StdEncoding.EncodeToString([]byte(str_pad))
  112. }
  113. // 加密
  114. func Encode(secretKey string, data []byte) (string, error) {
  115. decodeSecretKeyByte, _ := base64.StdEncoding.DecodeString(secretKey)
  116. c, e := EncodeAesGcm(string(data), string(decodeSecretKeyByte), "")
  117. if e != nil {
  118. return "", e
  119. }
  120. return c, nil
  121. }
  122. // 加密
  123. func Decode(secretKey string, encryptData string) ([]byte, error) {
  124. decodeSecretKeyByte, _ := base64.StdEncoding.DecodeString(secretKey)
  125. decodeSecretKey := string(decodeSecretKeyByte)
  126. //$data = openssl_decrypt(substr($decodeEncrypt, 16, -16), 'aes-256-gcm', $decodeSecret, 1, substr($decodeEncrypt, 0, 16), substr($decodeEncrypt, -16, 16));
  127. p, e := DecodeAesGcm(encryptData, decodeSecretKey, "")
  128. if e != nil {
  129. return nil, e
  130. }
  131. return p, nil
  132. }
  133. func decryptOAEP(pritKey []byte, cipherdata []byte, label []byte) ([]byte, error) {
  134. block, _ := pem.Decode(pritKey)
  135. if block == nil {
  136. err := fmt.Errorf("failed to parse certificate PEM")
  137. return nil, err
  138. }
  139. priv, err := x509.ParsePKCS1PrivateKey(block.Bytes) // ASN.1 PKCS#1 DER encoded form.
  140. if err != nil {
  141. return nil, err
  142. }
  143. h := sha256.New()
  144. return DecryptOAEPLong(h, rand.Reader, priv, cipherdata, label)
  145. }
  146. func EncryptOAEPLong(hash hash.Hash, random io.Reader, public *rsa.PublicKey, msg []byte, label []byte) ([]byte, error) {
  147. msgLen := len(msg)
  148. step := public.Size() - 2*hash.Size() - 2
  149. var encryptedBytes []byte
  150. for start := 0; start < msgLen; start += step {
  151. finish := start + step
  152. if finish > msgLen {
  153. finish = msgLen
  154. }
  155. encryptedBlockBytes, err := rsa.EncryptOAEP(hash, random, public, msg[start:finish], label)
  156. if err != nil {
  157. return nil, err
  158. }
  159. encryptedBytes = append(encryptedBytes, encryptedBlockBytes...)
  160. }
  161. return encryptedBytes, nil
  162. }
  163. func DecryptOAEPLong(hash hash.Hash, random io.Reader, private *rsa.PrivateKey, msg []byte, label []byte) ([]byte, error) {
  164. msgLen := len(msg)
  165. step := private.PublicKey.Size()
  166. var decryptedBytes []byte
  167. for start := 0; start < msgLen; start += step {
  168. finish := start + step
  169. if finish > msgLen {
  170. finish = msgLen
  171. }
  172. decryptedBlockBytes, err := rsa.DecryptOAEP(hash, random, private, msg[start:finish], label)
  173. if err != nil {
  174. return nil, err
  175. }
  176. decryptedBytes = append(decryptedBytes, decryptedBlockBytes...)
  177. }
  178. return decryptedBytes, nil
  179. }
  180. func encryptOAEP(pubkey []byte, msg []byte, label []byte) ([]byte, error) {
  181. block, _ := pem.Decode(pubkey)
  182. if block == nil {
  183. err := fmt.Errorf("failed to parse certificate PEM")
  184. return nil, err
  185. }
  186. pub, err := x509.ParsePKIXPublicKey(block.Bytes)
  187. if err != nil {
  188. return nil, err
  189. }
  190. rsaPublicKey := pub.(*rsa.PublicKey)
  191. h := sha256.New() // sha1.New() or md5.New()
  192. return EncryptOAEPLong(h, rand.Reader, rsaPublicKey, msg, label)
  193. }
  194. func radomInt() int32 {
  195. mrand.Seed(time.Now().UnixNano())
  196. return mrand.Int31n(math.MaxInt32)
  197. }