utils.go 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. // Copyright 2019 github.com. All rights reserved.
  2. // Use of this source code is governed by github.com.
  3. package utils
  4. import (
  5. "bytes"
  6. "crypto/aes"
  7. "crypto/cipher"
  8. "crypto/md5"
  9. "encoding/base64"
  10. "encoding/hex"
  11. "encoding/json"
  12. "fmt"
  13. "github.com/dgrijalva/jwt-go"
  14. "github.com/tidwall/gjson"
  15. "math/rand"
  16. "strings"
  17. "time"
  18. "github.com/jaryhe/gopkgs/cache"
  19. )
  20. var jwtSecret = []byte("12345678abcdefg")
  21. //var CRYPTO_KEY = string(RandStr(32, 3))
  22. func Base64URLDecode(data string) ([]byte, error) {
  23. var missing = (4 - len(data)%4) % 4
  24. data += strings.Repeat("=", missing)
  25. return base64.URLEncoding.DecodeString(data)
  26. }
  27. func Base64UrlSafeEncode(source []byte) string {
  28. // Base64 Url Safe is the same as Base64 but does not contain '/' and '+' (replaced by '_' and '-') and trailing '=' are removed.
  29. bytearr := base64.StdEncoding.EncodeToString(source)
  30. safeurl := strings.Replace(string(bytearr), "/", "_", -1)
  31. safeurl = strings.Replace(safeurl, "+", "-", -1)
  32. safeurl = strings.Replace(safeurl, "=", "", -1)
  33. return safeurl
  34. }
  35. func AesDecrypt(crypted, key []byte) ([]byte, error) {
  36. block, err := aes.NewCipher(key)
  37. if err != nil {
  38. return nil, err
  39. }
  40. blockMode := NewECBDecrypter(block)
  41. origData := make([]byte, len(crypted))
  42. blockMode.CryptBlocks(origData, crypted)
  43. origData = PKCS5UnPadding(origData)
  44. return origData, nil
  45. }
  46. func AesEncrypt(src, key string) ([]byte, error) {
  47. block, err := aes.NewCipher([]byte(key))
  48. if err != nil {
  49. return nil, err
  50. }
  51. ecb := NewECBEncrypter(block)
  52. content := []byte(src)
  53. content = PKCS5Padding(content, block.BlockSize())
  54. crypted := make([]byte, len(content))
  55. ecb.CryptBlocks(crypted, content)
  56. return crypted, nil
  57. }
  58. func PKCS5Padding(ciphertext []byte, blockSize int) []byte {
  59. padding := blockSize - len(ciphertext)%blockSize
  60. padtext := bytes.Repeat([]byte{byte(padding)}, padding)
  61. return append(ciphertext, padtext...)
  62. }
  63. func PKCS5UnPadding(origData []byte) []byte {
  64. length := len(origData)
  65. unpadding := int(origData[length-1])
  66. return origData[:(length - unpadding)]
  67. }
  68. type ecb struct {
  69. b cipher.Block
  70. blockSize int
  71. }
  72. func newECB(b cipher.Block) *ecb {
  73. return &ecb{
  74. b: b,
  75. blockSize: b.BlockSize(),
  76. }
  77. }
  78. type ecbEncrypter ecb
  79. // NewECBEncrypter returns a BlockMode which encrypts in electronic code book mode, using the given Block.
  80. func NewECBEncrypter(b cipher.Block) cipher.BlockMode {
  81. return (*ecbEncrypter)(newECB(b))
  82. }
  83. func (x *ecbEncrypter) BlockSize() int { return x.blockSize }
  84. func (x *ecbEncrypter) CryptBlocks(dst, src []byte) {
  85. if len(src)%x.blockSize != 0 {
  86. fmt.Println("crypto/cipher: input not full blocks")
  87. return
  88. }
  89. if len(dst) < len(src) {
  90. fmt.Println("crypto/cipher: output smaller than input")
  91. return
  92. }
  93. for len(src) > 0 {
  94. x.b.Encrypt(dst, src[:x.blockSize])
  95. src = src[x.blockSize:]
  96. dst = dst[x.blockSize:]
  97. }
  98. }
  99. type ecbDecrypter ecb
  100. // NewECBDecrypter returns a BlockMode which decrypts in electronic code book mode, using the given Block.
  101. func NewECBDecrypter(b cipher.Block) cipher.BlockMode {
  102. return (*ecbDecrypter)(newECB(b))
  103. }
  104. func (x *ecbDecrypter) BlockSize() int { return x.blockSize }
  105. func (x *ecbDecrypter) CryptBlocks(dst, src []byte) {
  106. if len(src)%x.blockSize != 0 {
  107. fmt.Println("crypto/cipher: input not full blocks")
  108. return
  109. }
  110. if len(dst) < len(src) {
  111. fmt.Println("crypto/cipher: output smaller than input")
  112. return
  113. }
  114. for len(src) > 0 {
  115. x.b.Decrypt(dst, src[:x.blockSize])
  116. src = src[x.blockSize:]
  117. dst = dst[x.blockSize:]
  118. }
  119. }
  120. func RandStr(size int, kind int) []byte {
  121. ikind, kinds, result := kind, [][]int{[]int{10, 48}, []int{26, 97}, []int{26, 65}}, make([]byte, size)
  122. is_all := kind > 2 || kind < 0
  123. rand.Seed(time.Now().UnixNano())
  124. for i := 0; i < size; i++ {
  125. if is_all { // random ikind
  126. ikind = rand.Intn(3)
  127. }
  128. scope, base := kinds[ikind][0], kinds[ikind][1]
  129. result[i] = uint8(base + rand.Intn(scope))
  130. }
  131. return result
  132. }
  133. func GenToken(id, issuer, subject string, seconds time.Duration) (string, error) {
  134. if len(jwtSecret) == 0 {
  135. return "", fmt.Errorf("jwtSecret is empty.")
  136. }
  137. nowTime := time.Now()
  138. expireTime := nowTime.Add(seconds)
  139. claims := jwt.StandardClaims{
  140. ExpiresAt: expireTime.Unix(),
  141. Id: id,
  142. Issuer: issuer,
  143. Subject: subject,
  144. }
  145. tokenClaims := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
  146. token, err := tokenClaims.SignedString(jwtSecret)
  147. return token, err
  148. }
  149. func ParseToken(token string) (*jwt.StandardClaims, error) {
  150. tokenClaims, err := jwt.ParseWithClaims(
  151. token,
  152. &jwt.StandardClaims{},
  153. func(token *jwt.Token) (interface{}, error) {
  154. return jwtSecret, nil
  155. },
  156. )
  157. if tokenClaims != nil {
  158. claims, ok := tokenClaims.Claims.(*jwt.StandardClaims)
  159. if !ok {
  160. return nil, err
  161. }
  162. if tokenClaims.Valid {
  163. return claims, nil
  164. }
  165. return claims, err
  166. }
  167. return nil, err
  168. }
  169. func MD5(s string) string {
  170. m := md5.New()
  171. m.Write([]byte(s))
  172. return hex.EncodeToString(m.Sum(nil))
  173. }
  174. func getMd5Pass(passwd string, crykey string) (string) {
  175. cryPasswd, err := AesEncrypt(passwd, crykey)
  176. if err != nil {
  177. return ""
  178. }
  179. ret := MD5(base64.StdEncoding.EncodeToString(cryPasswd))
  180. return ret
  181. }
  182. func GetCredential() string {
  183. crykey := string(RandStr(32, 3))
  184. key := string(RandStr(8, 3))
  185. md5Pass := getMd5Pass(key, crykey)
  186. sub := map[string]string{
  187. "key":key,
  188. "crykey":crykey,
  189. "pass":md5Pass,
  190. }
  191. subStr, _ := json.Marshal(sub)
  192. token, err := GenToken("1", "", string(subStr), 600 *time.Second)
  193. fmt.Printf("%v\n", err)
  194. return token
  195. }
  196. var credentialKey = "credential_"
  197. func checkCredentialToCache(token string) (bool, error) {
  198. key := credentialKey + token
  199. res, err := cache.Redis().Get(key)
  200. if err != nil && strings.Contains(err.Error(), "redis: nil") == false {
  201. return false, err
  202. }
  203. if res == "1" {
  204. return true, nil
  205. }
  206. return false, nil
  207. }
  208. func saveCredentialToCache(token string) error {
  209. key := credentialKey + token
  210. _, err := cache.Redis().SetEx(key, 60*20, "1")
  211. if err != nil {
  212. return err
  213. }
  214. return nil
  215. }
  216. func VerifyCredential(token string) bool {
  217. if token == "" {
  218. return false
  219. }
  220. exist, err := checkCredentialToCache(token)
  221. if err != nil {
  222. fmt.Printf("%v\n", err)
  223. return false
  224. }
  225. if exist {
  226. fmt.Printf("凭据已失效\n")
  227. }
  228. claimes, err := ParseToken(token)
  229. if err != nil {
  230. fmt.Printf("%v\n", err)
  231. return false
  232. }
  233. key := gjson.GetBytes([]byte(claimes.Subject), "key").String()
  234. crykey := gjson.GetBytes([]byte(claimes.Subject), "crykey").String()
  235. pass := gjson.GetBytes([]byte(claimes.Subject), "pass").String()
  236. dst := getMd5Pass(key, crykey)
  237. if pass != dst || dst == "" {
  238. fmt.Printf("key is not match\n")
  239. return false
  240. }
  241. if saveCredentialToCache(token) != nil {
  242. fmt.Printf("内部错误\n")
  243. return false
  244. }
  245. return true
  246. }