package market import ( "crypto" "crypto/rand" "crypto/rsa" "crypto/sha256" "crypto/x509" "encoding/base64" "encoding/pem" "errors" "fmt" "sort" ) // getSignString 使用 xx=aa&yy=bb 的字符串拼接 func getSignString(data map[string]interface{}) string { keys := make([]string, 0, len(data)) for key := range data { keys = append(keys, key) } sort.Strings(keys) signString := "" separator := "" for _, key := range keys { value := data[key] if key == "sign" || value == nil { continue } signString += fmt.Sprintf("%s%s=%v", separator, key, value) separator = "&" } return signString } // VerifyRsaSign 签名验证 func VerifyRsaSign(publicKey string, data map[string]interface{}) (map[string]interface{}, error) { // 对 sign nonce timestamp appId 升序排序 // 使用 xx=aa&yy=bb 的字符串拼接 // 商户的公钥验签 RSA2验签 signString := getSignString(data) rsaPubKey, err := parseRSAPublicKeyFromPEM([]byte(publicKey)) if err != nil { return nil, err } signature, err := base64.StdEncoding.DecodeString(data["sign"].(string)) if err != nil { return nil, err } hashed := sha256.Sum256([]byte(signString)) err = rsa.VerifyPKCS1v15(rsaPubKey, crypto.SHA256, hashed[:], signature) if err != nil { return nil, errors.New("签名验证失败") } return data, nil } // MakeRsaSign 生成签名 func MarketMakeRsaSign(privateKey string, data map[string]interface{}) (string, error) { // 对 sign nonce timestamp appId 升序排序 // 使用 xx=aa&yy=bb 的字符串拼接 // 营销系统生成的私钥生成签名 RSA2加签 signString := getSignString(data) privKey, err := parseRSAPrivateKeyFromPEM([]byte(privateKey)) if err != nil { return "", errors.New(fmt.Sprintf("私钥解析失败:%s", err.Error())) } hashed := sha256.Sum256([]byte(signString)) signature, err := rsa.SignPKCS1v15(rand.Reader, privKey, crypto.SHA256, hashed[:]) if err != nil { return "", errors.New("签名失败") } return base64.StdEncoding.EncodeToString(signature), nil } // ParseRSAPrivateKeyFromPEM 解析私钥 func parseRSAPrivateKeyFromPEM(key []byte) (*rsa.PrivateKey, error) { var err error // Parse PEM block var block *pem.Block if block, _ = pem.Decode(key); block == nil { return nil, errors.New("私钥解析失败: 无效的PEM格式") } var parsedKey interface{} if parsedKey, err = x509.ParsePKCS1PrivateKey(block.Bytes); err != nil { if parsedKey, err = x509.ParsePKCS8PrivateKey(block.Bytes); err != nil { return nil, err } } var pkey *rsa.PrivateKey var ok bool if pkey, ok = parsedKey.(*rsa.PrivateKey); !ok { return nil, errors.New("密钥不是有效的RSA私钥") } return pkey, nil } // parseRSAPublicKeyFromPEM parses a PEM encoded PKCS1 or PKCS8 public key func parseRSAPublicKeyFromPEM(key []byte) (*rsa.PublicKey, error) { var err error // Parse PEM block var block *pem.Block if block, _ = pem.Decode(key); block == nil { return nil, errors.New("公钥解析失败: 无效的PEM格式") } // Parse the key var parsedKey interface{} if parsedKey, err = x509.ParsePKIXPublicKey(block.Bytes); err != nil { if cert, err := x509.ParseCertificate(block.Bytes); err == nil { parsedKey = cert.PublicKey } else { return nil, err } } var pkey *rsa.PublicKey var ok bool if pkey, ok = parsedKey.(*rsa.PublicKey); !ok { return nil, errors.New("密钥不是有效的RSA公钥") } return pkey, nil }