将Go语言的HMAC签名逻辑迁移至R语言的实现问题
问题:复现mbtileserver的HMAC签名逻辑(R语言版本故障)
我正在尝试为consbio/mbtileserver复现Go语言的HMAC签名生成逻辑,目标是构建能通过安全连接访问mbtileserver的R和Python应用。目前Python版本已实现成功,但R语言版本无法正常运行,求帮助。
Go语言示例代码
serviceId := "test" date := "2019-03-08T19:31:12.213831+00:00" salt := "0EvkK316T-sBLA" secretKey := "YMIVXikJWAiiR3q-JMz1v2Mfmx3gTXJVNqme5kyaqrY" key := sha1.New() key.Write([]byte(salt + secretKey)) hash := hmac.New(sha1.New, key.Sum(nil)) message := fmt.Sprintf("%s:%s", date, serviceId) hash.Write([]byte(message)) b64hash := base64.RawURLEncoding.EncodeToString(hash.Sum(nil)) fmt.Println(b64hash) // 预期输出: 2y8vHb9xK6RSxN8EXMeAEUiYtZk
Python可行代码
import hashlib import hmac import base64 service_id = "test" date = "2019-03-08T19:31:12.213831+00:00" salt = "0EvkK316T-sBLA" secret_key = "YMIVXikJWAiiR3q-JMz1v2Mfmx3gTXJVNqme5kyaqrY" key = hashlib.sha1() key.update((salt + secret_key).encode()) hash_obj = hmac.new(key.digest(), (date + ":" + service_id).encode(), hashlib.sha1) b64_hash = base64.urlsafe_b64encode(hash_obj.digest()).decode() print(b64_hash) # 预期输出: 2y8vHb9xK6RSxN8EXMeAEUiYtZk
当前无法运行的R语言代码
library(openssl) library(digest) service_id <- "test" date <- "2019-03-08T19:31:12.213831+00:00" salt <- "0EvkK316T-sBLA" secret_key <- "YMIVXikJWAiiR3q-JMz1v2Mfmx3gTXJVNqme5kyaqrY" key <- sha1(paste0(salt, secret_key)) hash_obj <- hmac(key, paste0(date, ":", service_id), "sha1") b64_hash <- base64_encode(hash_obj) print(b64_hash) # 预期输出: 2y8vHb9xK6RSxN8EXMeAEUiYtZk
问题原因与修正方案
R代码的核心问题在于默认使用十六进制字符串而非二进制原始摘要,且base64编码未采用URL安全的无填充格式:
digest::sha1()默认返回十六进制字符串,需添加raw=TRUE参数获取二进制原始值,对应Go/Python中的digest结果openssl::hmac()同样默认返回十六进制字符串,需设置raw=TRUE得到二进制HMAC结果- 使用
openssl::base64_encode()的urlsafe=TRUE和nopad=TRUE参数,匹配Go语言的base64.RawURLEncoding行为
修正后的R代码
library(openssl) library(digest) service_id <- "test" date <- "2019-03-08T19:31:12.213831+00:00" salt <- "0EvkK316T-sBLA" secret_key <- "YMIVXikJWAiiR3q-JMz1v2Mfmx3gTXJVNqme5kyaqrY" # 获取二进制SHA1摘要 key <- sha1(paste0(salt, secret_key), raw = TRUE) # 生成二进制HMAC-SHA1结果 hash_obj <- hmac(key, paste0(date, ":", service_id), "sha1", raw = TRUE) # URL安全的无填充Base64编码 b64_hash <- base64_encode(hash_obj, urlsafe = TRUE, nopad = TRUE) print(b64_hash) # 输出: 2y8vHb9xK6RSxN8EXMeAEUiYtZk
内容的提问来源于stack exchange,提问作者pdbentley
相关产品推荐
相关产品推荐

