| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125 |
- package encryptor
- import (
- "crypto/aes"
- "crypto/cipher"
- "encoding/base64"
- "encoding/json"
- "errors"
- "fmt"
- "github.com/silenceper/wechat/v2/miniprogram/context"
- )
- // Encryptor struct
- type Encryptor struct {
- *context.Context
- }
- // NewEncryptor 实例
- func NewEncryptor(context *context.Context) *Encryptor {
- basic := new(Encryptor)
- basic.Context = context
- return basic
- }
- var (
- // ErrAppIDNotMatch appid不匹配
- ErrAppIDNotMatch = errors.New("app id not match")
- // ErrInvalidBlockSize block size不合法
- ErrInvalidBlockSize = errors.New("invalid block size")
- // ErrInvalidPKCS7Data PKCS7数据不合法
- ErrInvalidPKCS7Data = errors.New("invalid PKCS7 data")
- // ErrInvalidPKCS7Padding 输入padding失败
- ErrInvalidPKCS7Padding = errors.New("invalid padding on input")
- )
- // PlainData 用户信息/手机号信息
- type PlainData struct {
- OpenID string `json:"openId"`
- UnionID string `json:"unionId"`
- NickName string `json:"nickName"`
- Gender int `json:"gender"`
- City string `json:"city"`
- Province string `json:"province"`
- Country string `json:"country"`
- AvatarURL string `json:"avatarUrl"`
- Language string `json:"language"`
- PhoneNumber string `json:"phoneNumber"`
- OpenGID string `json:"openGId"`
- MsgTicket string `json:"msgTicket"`
- PurePhoneNumber string `json:"purePhoneNumber"`
- CountryCode string `json:"countryCode"`
- Watermark struct {
- Timestamp int64 `json:"timestamp"`
- AppID string `json:"appid"`
- } `json:"watermark"`
- }
- // pkcs7Unpad returns slice of the original data without padding
- func pkcs7Unpad(data []byte, blockSize int) ([]byte, error) {
- if blockSize <= 0 {
- return nil, ErrInvalidBlockSize
- }
- if len(data)%blockSize != 0 || len(data) == 0 {
- return nil, ErrInvalidPKCS7Data
- }
- c := data[len(data)-1]
- n := int(c)
- if n == 0 || n > len(data) {
- return nil, ErrInvalidPKCS7Padding
- }
- for i := 0; i < n; i++ {
- if data[len(data)-n+i] != c {
- return nil, ErrInvalidPKCS7Padding
- }
- }
- return data[:len(data)-n], nil
- }
- // GetCipherText returns slice of the cipher text
- func GetCipherText(sessionKey, encryptedData, iv string) ([]byte, error) {
- aesKey, err := base64.StdEncoding.DecodeString(sessionKey)
- if err != nil {
- return nil, err
- }
- cipherText, err := base64.StdEncoding.DecodeString(encryptedData)
- if err != nil {
- return nil, err
- }
- ivBytes, err := base64.StdEncoding.DecodeString(iv)
- if err != nil {
- return nil, err
- }
- if len(ivBytes) != aes.BlockSize {
- return nil, fmt.Errorf("bad iv length %d", len(ivBytes))
- }
- block, err := aes.NewCipher(aesKey)
- if err != nil {
- return nil, err
- }
- mode := cipher.NewCBCDecrypter(block, ivBytes)
- mode.CryptBlocks(cipherText, cipherText)
- cipherText, err = pkcs7Unpad(cipherText, block.BlockSize())
- if err != nil {
- return nil, err
- }
- return cipherText, nil
- }
- // Decrypt 解密数据
- func (encryptor *Encryptor) Decrypt(sessionKey, encryptedData, iv string) (*PlainData, error) {
- cipherText, err := GetCipherText(sessionKey, encryptedData, iv)
- if err != nil {
- return nil, err
- }
- var plainData PlainData
- err = json.Unmarshal(cipherText, &plainData)
- if err != nil {
- return nil, err
- }
- if plainData.Watermark.AppID != encryptor.AppID {
- return nil, ErrAppIDNotMatch
- }
- return &plainData, nil
- }
|