decrypt.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. package miniprogram
  2. import (
  3. "crypto/aes"
  4. "crypto/cipher"
  5. "encoding/base64"
  6. "encoding/json"
  7. "errors"
  8. )
  9. var (
  10. // ErrAppIDNotMatch appid不匹配
  11. ErrAppIDNotMatch = errors.New("app id not match")
  12. // ErrInvalidBlockSize block size不合法
  13. ErrInvalidBlockSize = errors.New("invalid block size")
  14. // ErrInvalidPKCS7Data PKCS7数据不合法
  15. ErrInvalidPKCS7Data = errors.New("invalid PKCS7 data")
  16. // ErrInvalidPKCS7Padding 输入padding失败
  17. ErrInvalidPKCS7Padding = errors.New("invalid padding on input")
  18. )
  19. // UserInfo 用户信息
  20. type UserInfo struct {
  21. OpenID string `json:"openId"`
  22. UnionID string `json:"unionId"`
  23. NickName string `json:"nickName"`
  24. Gender int `json:"gender"`
  25. City string `json:"city"`
  26. Province string `json:"province"`
  27. Country string `json:"country"`
  28. AvatarURL string `json:"avatarUrl"`
  29. Language string `json:"language"`
  30. Watermark struct {
  31. Timestamp int64 `json:"timestamp"`
  32. AppID string `json:"appid"`
  33. } `json:"watermark"`
  34. }
  35. // 用户手机号
  36. type PhoneInfo struct {
  37. PhoneNumber string `json:"phoneNumber"`
  38. PurePhoneNumber string `json:"purePhoneNumber"`
  39. CountryCode string `json:"countryCode"`
  40. Watermark struct {
  41. Timestamp int64 `json:"timestamp"`
  42. AppID string `json:"appid"`
  43. } `json:"watermark"`
  44. }
  45. // pkcs7Unpad returns slice of the original data without padding
  46. func pkcs7Unpad(data []byte, blockSize int) ([]byte, error) {
  47. if blockSize <= 0 {
  48. return nil, ErrInvalidBlockSize
  49. }
  50. if len(data)%blockSize != 0 || len(data) == 0 {
  51. return nil, ErrInvalidPKCS7Data
  52. }
  53. c := data[len(data)-1]
  54. n := int(c)
  55. if n == 0 || n > len(data) {
  56. return nil, ErrInvalidPKCS7Padding
  57. }
  58. for i := 0; i < n; i++ {
  59. if data[len(data)-n+i] != c {
  60. return nil, ErrInvalidPKCS7Padding
  61. }
  62. }
  63. return data[:len(data)-n], nil
  64. }
  65. // get cipherText
  66. func getCipherText(sessionKey, encryptedData, iv string) ([]byte, error) {
  67. aesKey, err := base64.StdEncoding.DecodeString(sessionKey)
  68. if err != nil {
  69. return nil, err
  70. }
  71. cipherText, err := base64.StdEncoding.DecodeString(encryptedData)
  72. if err != nil {
  73. return nil, err
  74. }
  75. ivBytes, err := base64.StdEncoding.DecodeString(iv)
  76. if err != nil {
  77. return nil, err
  78. }
  79. block, err := aes.NewCipher(aesKey)
  80. if err != nil {
  81. return nil, err
  82. }
  83. mode := cipher.NewCBCDecrypter(block, ivBytes)
  84. mode.CryptBlocks(cipherText, cipherText)
  85. cipherText, err = pkcs7Unpad(cipherText, block.BlockSize())
  86. if err != nil {
  87. return nil, err
  88. }
  89. return cipherText, err
  90. }
  91. // Decrypt 解密(用户)数据
  92. func (wxa *MiniProgram) Decrypt(sessionKey, encryptedData, iv string) (*UserInfo, error) {
  93. // 拿到 cipherText
  94. cipherText,err := getCipherText(sessionKey, encryptedData, iv)
  95. if err != nil {
  96. return nil, err
  97. }
  98. var userInfo UserInfo
  99. err = json.Unmarshal(cipherText, &userInfo)
  100. if err != nil {
  101. return nil, err
  102. }
  103. if userInfo.Watermark.AppID != wxa.AppID {
  104. return nil, ErrAppIDNotMatch
  105. }
  106. return &userInfo, nil
  107. }
  108. // Decrypt 解密(手机)数据
  109. func (wxa *MiniProgram) DecryptPhone(sessionKey, encryptedData, iv string) (*PhoneInfo, error) {
  110. // 拿到 cipherText
  111. cipherText,err := getCipherText(sessionKey, encryptedData, iv)
  112. if err != nil {
  113. return nil, err
  114. }
  115. var phoneInfo PhoneInfo
  116. err = json.Unmarshal(cipherText, &phoneInfo)
  117. if err != nil {
  118. return nil, err
  119. }
  120. if phoneInfo.Watermark.AppID != wxa.AppID {
  121. return nil, ErrAppIDNotMatch
  122. }
  123. return &phoneInfo, nil
  124. }