124 lines
2.5 KiB
Go
124 lines
2.5 KiB
Go
package crypto
|
|
|
|
import (
|
|
stdcrypto "crypto"
|
|
"crypto/rand"
|
|
"crypto/rsa"
|
|
"crypto/x509"
|
|
"encoding/base64"
|
|
"encoding/pem"
|
|
"net/url"
|
|
"sort"
|
|
"strings"
|
|
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
// Alipay alipay cryptor
|
|
type Alipay struct {
|
|
aliPub []byte
|
|
biliPriv []byte
|
|
}
|
|
|
|
// NewAlipay is.
|
|
func NewAlipay(aliPub, biliPriv string) (a *Alipay) {
|
|
return &Alipay{
|
|
aliPub: ParsePublicKey(aliPub),
|
|
biliPriv: ParsePrivateKey(biliPriv),
|
|
}
|
|
}
|
|
|
|
func (e *Alipay) splitData(originalData []byte, packageSize int) (r [][]byte) {
|
|
var src = make([]byte, len(originalData))
|
|
copy(src, originalData)
|
|
|
|
r = make([][]byte, 0)
|
|
if len(src) <= packageSize {
|
|
return append(r, src)
|
|
}
|
|
for len(src) > 0 {
|
|
var p = src[:packageSize]
|
|
r = append(r, p)
|
|
src = src[packageSize:]
|
|
if len(src) <= packageSize {
|
|
r = append(r, src)
|
|
break
|
|
}
|
|
}
|
|
return r
|
|
}
|
|
|
|
// EncryptParam rsa encrypt.
|
|
func (e *Alipay) EncryptParam(p url.Values) (ep string, err error) {
|
|
var (
|
|
pubInterface interface{}
|
|
pub *rsa.PublicKey
|
|
data []byte
|
|
block *pem.Block
|
|
)
|
|
block, _ = pem.Decode(e.aliPub)
|
|
if block == nil {
|
|
err = errors.New("private key error")
|
|
return
|
|
}
|
|
if pubInterface, err = x509.ParsePKIXPublicKey(block.Bytes); err != nil {
|
|
err = errors.WithStack(err)
|
|
return
|
|
}
|
|
pub = pubInterface.(*rsa.PublicKey)
|
|
var sd = e.splitData([]byte(p.Encode()), pub.N.BitLen()/8-11)
|
|
for _, d := range sd {
|
|
var pd []byte
|
|
if pd, err = rsa.EncryptPKCS1v15(rand.Reader, pub, d); err != nil {
|
|
err = errors.WithStack(err)
|
|
return
|
|
}
|
|
data = append(data, pd...)
|
|
}
|
|
ep = base64.StdEncoding.EncodeToString(data)
|
|
return
|
|
}
|
|
|
|
// SignParam sign alipay param
|
|
func (e *Alipay) SignParam(p url.Values) (sign string, err error) {
|
|
if p == nil {
|
|
p = make(url.Values)
|
|
}
|
|
var pList = make([]string, 0)
|
|
for key := range p {
|
|
var value = strings.TrimSpace(p.Get(key))
|
|
if len(value) > 0 {
|
|
pList = append(pList, key+"="+value)
|
|
}
|
|
}
|
|
sort.Strings(pList)
|
|
var src = strings.Join(pList, "&")
|
|
|
|
var h = stdcrypto.SHA256.New()
|
|
if _, err = h.Write([]byte(src)); err != nil {
|
|
err = errors.WithStack(err)
|
|
return
|
|
}
|
|
var (
|
|
hashed = h.Sum(nil)
|
|
pri *rsa.PrivateKey
|
|
data []byte
|
|
block *pem.Block
|
|
)
|
|
block, _ = pem.Decode(e.biliPriv)
|
|
if block == nil {
|
|
err = errors.New("private key error")
|
|
return
|
|
}
|
|
if pri, err = x509.ParsePKCS1PrivateKey(block.Bytes); err != nil {
|
|
err = errors.WithStack(err)
|
|
return
|
|
}
|
|
if data, err = rsa.SignPKCS1v15(rand.Reader, pri, stdcrypto.SHA256, hashed); err != nil {
|
|
err = errors.WithStack(err)
|
|
return
|
|
}
|
|
sign = base64.StdEncoding.EncodeToString(data)
|
|
return
|
|
}
|