引言
在不同的系统之间一般是通过API接口的方式来进行交互,服务提供方需要进行身份的验证确保客户端的可靠性。
常用的加密方式
- 微信支付的签名算法
- AES对称加密算法
微信支付签名算法
微信支付文档: pay.weixin.qq.com/wiki/doc/ap…
主要的步骤是参数名排序后拼接成字符串,对参数计算md5,与入参一起传递。
优劣
优点: 计算后的MD5没法解密,安全系数高
缺点:对于存在嵌套的入参不太友好
例:
对于这个json组装后的结果为:array=bar=2,baz=3,foo=1
"array": [
{"foo": 1},
{"bar": 2},
{"baz": 3}
],
Go代码实现如下
微信签名算法找了一下没有递归版本,自己实现了一下
// ParamsMd5 参数加密
func ParamsMd5(data interface{}, secret string) (string, error) {
h := md5.New()
params, err := joinParams(data)
if err != nil {
return "", err
}
h.Write([]byte(params + secret))
return hex.EncodeToString(h.Sum(nil)), nil
}
func joinParams(data interface{}) (string, error) {
var buf bytes.Buffer
switch v := data.(type) {
case map[string]interface{}:
keys := make([]string, 0, len(v))
for k := range v {
if k == "sign" {
continue
}
keys = append(keys, k)
}
sort.Strings(keys)
for _, k := range keys {
if v[k] == nil {
continue
}
if buf.Len() > 0 {
buf.WriteByte('&')
}
buf.WriteString(k)
buf.WriteByte('=')
vv, err := interface2string(v[k])
if err != nil {
return "", err
}
buf.WriteString(vv)
}
}
return buf.String(), nil
}
func interface2string(data interface{}) (string, error) {
switch vv := data.(type) {
case nil:
return "", errors.New("key值为nil")
case string:
return vv, nil
case float64:
return fmt.Sprintf("%v", vv), nil
case int:
return strconv.FormatInt(int64(vv), 10), nil
case bool:
return strconv.FormatBool(vv), nil
case map[string]interface{}:
return joinParams(vv)
case []interface{}:
list := make([]string, 0, len(vv))
for _, vvv := range vv {
tmp, err := interface2string(vvv)
if err != nil {
return "", err
}
list = append(list, tmp)
}
sort.Strings(list)
return strings.Join(list, ","), nil
default:
return "", errors.New(fmt.Sprintf("数据类型有误: %T", vv))
}
}
AES对称加密
AES对称加密后不需要再传递参数,只需要传递加密后的字符串,服务端解密后可以得到对应的入参。在网易云音乐有使用aes加密,可以防一波新手爬虫玩家。
- 这个算法安全系数高,AES对称加密是通过秘钥和偏移量一起实现的,想暴力破解难度很大。
- 实现简单,客户端用json直接加密,服务端用密文直接解密(一般会加密后做base64处理)
对比我更加推荐使用AES对称加密来作为加密算法
网上有很多AES加密算法的实现,不展示demo了。
一般会使用CBC加密模式、用pkcs7padding填充,数据块用128位,验证加密是否正确:tool.chacuo.net/cryptaes
总结
微信加密算法对嵌套入参支持不好,更加推荐使用AES加密算法