💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
- 将所有业务请求参数及系统参数(client_id 和 timestamp) , 将参数名称按字母先后顺序排序 - 参数名称和参数值使用等号(=)链接,然后再使用&连接成一个字符串 A,即QueryString的形式 - 对字段A用RSA+MD5私钥签名, 再用base64 加密 -- - 验证签名是否被使用 - - 将所有业务请求参数及系统参数(client_id 和 timestamp) , 将参数名称按字母先后顺序排序 - 参数名称和参数值使用等号(=)链接,然后再使用&连接成一个字符串 A,即QueryString的形式 - QueryString + 签名base64 解密 + 公钥验签 - https://blog.csdn.net/xz_studying/article/details/80314111 ``` package main import ( "crypto" "crypto/md5" "crypto/rand" "crypto/rsa" "crypto/x509" "encoding/base64" "encoding/pem" "fmt" "net/url" "time" ) var ( publicKey = []byte(`-----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDIBgFl4dNiuDeZxjllYnNmk3/U A6eX+GkW8KQ2A2E0eRZCQ4tLsZHVdE58a4UxW+LArTZwSUy8FrXQjYkAQMASy2wV ofctjDu4RcO1fiJKc/N8v4Kzx+Ta3nkingQGPZhPzYxLWx2VD1ands2jMem/AIv0 oklJBasb57N+7YuFgQIDAQAB -----END PUBLIC KEY-----`) privateKey = []byte(`-----BEGIN PRIVATE KEY----- MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAMgGAWXh02K4N5nG OWVic2aTf9QDp5f4aRbwpDYDYTR5FkJDi0uxkdV0TnxrhTFb4sCtNnBJTLwWtdCN iQBAwBLLbBWh9y2MO7hFw7V+Ikpz83y/grPH5NreeSKeBAY9mE/NjEtbHZUPVqd2 zaMx6b8Ai/SiSUkFqxvns37ti4WBAgMBAAECgYEAp5IgabIe3X1nVzRxsTYhZ7X6 SSwmo3JA2C8R4w5BySwIMctUTz2b5y9g8WtCUm+gL7rs+HTwDEMaXnW0aLnWLmu/ +12n+SEusVlMBnkC0NRtkkfxMIOP0LgVkrIbv4Um6iRDsbyctD7GBFRB+q3qTk6d VVS8qLBU9o/GBCLSgAECQQD5QvH49Xnvh+75tO3yMJry53OBXXnvLY0V8vpc4zy6 7Dd3Q+BZCKnT3gkr/H77fDcn6cf9SyAvN2tMIFNgR/vBAkEAzW5M46qSL0K2uJR4 Ei+ifUl6Rx5vWh0BR0hMZqkdzry8HOxeBpo693XE2fNaE5CmIXdfB3WcX9gcT/GG TWj5wQJBAMgJzM1Cm6f6zHODm045abC0xMK2NOwY/1f1Fq3DA/LzLZQ+Wea6CCjq 0SuGyJWk21Lh0EjbqKmb7TU74A2t10ECQALvGFoIDZ5vLXzlYfGgjImNixmI7b4z u9jwx2aP88UIHQesuIsPmNf/7pfOSfMNldHUip7opxsXUxAxOuHQJgECQQCMyTR+ oAFjZOZFJH9SwoDk9Ew125yTLSZAsOKz0dzfOLUGoNkYJ2HeH7ceSdRo3tEkzGae PXAeKCqkhuuOjP1G -----END PRIVATE KEY-----`) ) func main() { m := make(map[string]string) m["param1"] = "参数1" m["param2"] = "参数2" m["param3"] = "参数3" fmt.Println("签名前的数据:", m) if err := signData(m); err != nil { fmt.Println(err.Error()) } fmt.Println("签名后的数据:", m) if err := verifyData(m); err != nil { fmt.Println("验签结果(公钥验签):", "失败", err) } else { fmt.Println("验签结果(公钥验签):", "成功") } } func signData(m map[string]string) error { m["timestamp"] = fmt.Sprintf("%d", time.Now().UnixNano()/1e6) urlString := url.Values{} for key, value := range m { urlString.Add(key, value) } //进行转码使之可以安全的用在URL查询里 quUrl, err := url.QueryUnescape(urlString.Encode()) if err != nil { fmt.Println("QueryUnescape", err) return err } pKey, _ := pem.Decode(privateKey) if out, err := RsaSignWithMd5(quUrl, string(pKey.Bytes)); err != nil { return err } else { m["sign"] = out return nil } } func verifyData(m map[string]string) error { sign := m["sign"] delete(m, "sign") urlString := url.Values{} for key, value := range m { urlString.Add(key, value) } //进行转码使之可以安全的用在URL查询里 if quUrl, err := url.QueryUnescape(urlString.Encode()); err != nil { return err } else { keyBytes, _ := pem.Decode(publicKey) return RsaVerifySignWithMd5(quUrl, sign, string(keyBytes.Bytes)) } } // 签名 func RsaSignWithMd5(data string, prvKey string) (sign string, err error) { privateKey, err := x509.ParsePKCS8PrivateKey([]byte(prvKey)) if err != nil { fmt.Println("ParsePKCS8PrivateKey", err) return "", err } h := md5.New() h.Write([]byte(data)) hash := h.Sum(nil) signature, err := rsa.SignPKCS1v15(rand.Reader, privateKey.(*rsa.PrivateKey), crypto.MD5, hash[:]) if err != nil { fmt.Println("SignPKCS1v15:", err) return "", err } out := base64.RawURLEncoding.EncodeToString(signature) return out, nil } // 验签 func RsaVerifySignWithMd5(originalData, signData, pubKey string) error { //TODO : 验证时间 sign, err := base64.RawURLEncoding.DecodeString(signData) if err != nil { fmt.Println("DecodeString:", err) return err } pub, err := x509.ParsePKIXPublicKey([]byte(pubKey)) if err != nil { fmt.Println("ParsePKIXPublicKey", err) return err } hash := md5.New() hash.Write([]byte(originalData)) return rsa.VerifyPKCS1v15(pub.(*rsa.PublicKey), crypto.MD5, hash.Sum(nil), sign) } ```