背景
写一个接口认证的时候,密码需要通过SHA1+HMAC加密以后转base64,发现加密的结果不符合预期
问题
shell里面通过命令生成的字符串 golang生产的结果有差别
具体的说,shell 生产的base64传里面有'/',对应golang生产的是'_',例如下面案例
shell输出: NaY6swRy/2BgUPuVUAWEDlaWZ3s=
golang输出:NaY6swRy_2BgUPuVUAWEDlaWZ3s=
原因
- golang base64 有不同方法进行encode/decode,可以根据不同RFC进行处理,参考链接
- 为了避免base64出现的 '/' '+' 影响到encode以后的使用(例如拿encode以后的字符串做文件名),RFC 特定制定了一套URL and filename-safe标准,把这两个字符串改成'_' '-', 这次就是掉了这个坑,参考链接
- 扩展阅读,查这个问题的时候,看到有其他小伙伴因为base64最后没有 '=' 出现报错的,golang里有 WithPadding 函数能搞定
具体代码
#shell, 希望的解析结果
date='Wed, 31 Mar 2021 08:56:15 GMT'
pass='123456'
password=`echo -en "$date" | openssl dgst -sha1 -hmac ${pass} -binary | openssl enc -base64`
echo $password
输出: NaY6swRy/2BgUPuVUAWEDlaWZ3s=
//golang 不符合预期的情况
key := []byte("123456")
mac := hmac.New(sha1.New, key)
mac.Write([]byte("Wed, 31 Mar 2021 08:56:15 GMT"))
// 这里用的URLEncoding,就是按 RFC4648 section5 规则
fmt.Println(base64.URLEncoding.EncodeToString(mac.Sum(nil)))
输出: NaY6swRy_2BgUPuVUAWEDlaWZ3s=
// 换成 StdEncoding 就可以了,按RFC4648 section4 规则
fmt.Println(base64.StdEncoding.EncodeToString(mac.Sum(nil)))
有疑问加站长微信联系(非本文作者)