alipay.go 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. package crypto
  2. import (
  3. stdcrypto "crypto"
  4. "crypto/rand"
  5. "crypto/rsa"
  6. "crypto/x509"
  7. "encoding/base64"
  8. "encoding/pem"
  9. "net/url"
  10. "sort"
  11. "strings"
  12. "github.com/pkg/errors"
  13. )
  14. // Alipay alipay cryptor
  15. type Alipay struct {
  16. aliPub []byte
  17. biliPriv []byte
  18. }
  19. // NewAlipay is.
  20. func NewAlipay(aliPub, biliPriv string) (a *Alipay) {
  21. return &Alipay{
  22. aliPub: ParsePublicKey(aliPub),
  23. biliPriv: ParsePrivateKey(biliPriv),
  24. }
  25. }
  26. func (e *Alipay) splitData(originalData []byte, packageSize int) (r [][]byte) {
  27. var src = make([]byte, len(originalData))
  28. copy(src, originalData)
  29. r = make([][]byte, 0)
  30. if len(src) <= packageSize {
  31. return append(r, src)
  32. }
  33. for len(src) > 0 {
  34. var p = src[:packageSize]
  35. r = append(r, p)
  36. src = src[packageSize:]
  37. if len(src) <= packageSize {
  38. r = append(r, src)
  39. break
  40. }
  41. }
  42. return r
  43. }
  44. // EncryptParam rsa encrypt.
  45. func (e *Alipay) EncryptParam(p url.Values) (ep string, err error) {
  46. var (
  47. pubInterface interface{}
  48. pub *rsa.PublicKey
  49. data []byte
  50. block *pem.Block
  51. )
  52. block, _ = pem.Decode(e.aliPub)
  53. if block == nil {
  54. err = errors.New("private key error")
  55. return
  56. }
  57. if pubInterface, err = x509.ParsePKIXPublicKey(block.Bytes); err != nil {
  58. err = errors.WithStack(err)
  59. return
  60. }
  61. pub = pubInterface.(*rsa.PublicKey)
  62. var sd = e.splitData([]byte(p.Encode()), pub.N.BitLen()/8-11)
  63. for _, d := range sd {
  64. var pd []byte
  65. if pd, err = rsa.EncryptPKCS1v15(rand.Reader, pub, d); err != nil {
  66. err = errors.WithStack(err)
  67. return
  68. }
  69. data = append(data, pd...)
  70. }
  71. ep = base64.StdEncoding.EncodeToString(data)
  72. return
  73. }
  74. // SignParam sign alipay param
  75. func (e *Alipay) SignParam(p url.Values) (sign string, err error) {
  76. if p == nil {
  77. p = make(url.Values)
  78. }
  79. var pList = make([]string, 0)
  80. for key := range p {
  81. var value = strings.TrimSpace(p.Get(key))
  82. if len(value) > 0 {
  83. pList = append(pList, key+"="+value)
  84. }
  85. }
  86. sort.Strings(pList)
  87. var src = strings.Join(pList, "&")
  88. var h = stdcrypto.SHA256.New()
  89. if _, err = h.Write([]byte(src)); err != nil {
  90. err = errors.WithStack(err)
  91. return
  92. }
  93. var (
  94. hashed = h.Sum(nil)
  95. pri *rsa.PrivateKey
  96. data []byte
  97. block *pem.Block
  98. )
  99. block, _ = pem.Decode(e.biliPriv)
  100. if block == nil {
  101. err = errors.New("private key error")
  102. return
  103. }
  104. if pri, err = x509.ParsePKCS1PrivateKey(block.Bytes); err != nil {
  105. err = errors.WithStack(err)
  106. return
  107. }
  108. if data, err = rsa.SignPKCS1v15(rand.Reader, pri, stdcrypto.SHA256, hashed); err != nil {
  109. err = errors.WithStack(err)
  110. return
  111. }
  112. sign = base64.StdEncoding.EncodeToString(data)
  113. return
  114. }