我正在尝试按照此处的说明生成CosmosDb Auth令牌: https://docs.microsoft.com/en-us/rest/api/documentdb/access-control-on-documentdb-resources
这是我在GoLang中的实现(我用上面文档中“示例编码”部分中的文字值替换了所有参数):
import(
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"net/url")
func generateAuthToken(
verb string,
resourceType string,
resourceId string,
date string,
base64Key string) string {
// Example Key
base64Key := "dsZQi3KtZmCv1ljt3VNWNm7sQUF1y5rJfC6kv5JiwvW0EndXdDku/dkKBp8/ufDToSxLzR4y+O/0H/t4bQtVNw=="
msg := fmt.Sprintf("%s\n%s\n%s\n%s\n%s\n",
"get", //verb
"dbs", //resourceId
"dbs/todolist", //resourceLink
"thu, 27 apr 2017 00:51:12 gmt", //RFC1123 date
"")
hasher := hmac.New(sha256.New, []byte(base64Key))
hasher.Write([]byte(msg))
signature := base64.StdEncoding.EncodeToString(hasher.Sum(nil))
authHeader := fmt.Sprintf("type=master&ver=1.0&sig=%s", signature)
return url.QueryEscape(authHeader)
}
我还从链接中获取了C#示例,并使用与参考相同的参数运行它。
这是我从C#实现中获得的(参考):
"type%3Dmaster%26ver%3D1.0%26sig%3DSGWmGNFZlBH%2Bt9QCvuMy%2FVsbBAOKLbxsgy3Z7aG0PdA%3D"
这是我从GoLang实施中得到的结果:
"type%3Dmaster%26ver%3D1.0%26sig%3Dwst1NDxfOeoYMurn69DgZtJUQOrgxFz%2Bp6A2vKnXxEI%3D"
显然我在GoLang实现中做错了,因为两者不相同(可能误用了散列库?)
为便于参考,这里是C#实现:
static void Main(string[] args) {
string token = GenerateAuthToken(
"get",
"dbs",
"dbs/todolist",
"thu, 27 apri 2017 00:51:12 gmt",
"dsZQi3KtZmCv1ljt3VNWNm7sQUF1y5rJfC6kv5JiwvW0EndXdDku/dkKBp8/ufDToSxLzR4y+O/0H/t4bQtVNw==",
"master",
"1.0");
}
static string GenerateAuthToken(string verb, string resourceType, string resourceId, string date, string key, string keyType, string tokenVersion)
{
var hmacSha256 = new System.Security.Cryptography.HMACSHA256 { Key = Convert.FromBase64String(key) };
verb = verb ?? "";
resourceType = resourceType ?? "";
resourceId = resourceId ?? "";
string payLoad = string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}\n{1}\n{2}\n{3}\n{4}\n",
verb.ToLowerInvariant(),
resourceType.ToLowerInvariant(),
resourceId,
date.ToLowerInvariant(),
"");
byte[] hashPayLoad = hmacSha256.ComputeHash(System.Text.Encoding.UTF8.GetBytes(payLoad));
string signature = Convert.ToBase64String(hashPayLoad);
return System.Net.WebUtility.UrlEncode(String.Format(System.Globalization.CultureInfo.InvariantCulture, "type={0}&ver={1}&sig={2}",
keyType,
tokenVersion,
signature));
}
答案 0 :(得分:4)
这让我找到了比我希望的更长的时间。有一个明显的问题,你不是base64解码这一行的密钥
hasher := hmac.New(sha256.New, []byte(base64Key))
您应该执行类似
的操作hmacKey, _ := base64.StdEncoding.DecodeString(base64Key)
// handle error
hasher := hmac.New(sha256.New, hmacKey)
但即使这样也没有解决它。直到我终于弄清楚这种差异
C# "thu, 27 apri 2017 00:51:12 gmt"
Go "thu, 27 apr 2017 00:51:12 gmt"
这有效
func generateAuthToken(
verb string,
resourceType string,
resourceId string,
date string,
base64Key string) string {
msg := fmt.Sprintf("%s\n%s\n%s\n%s\n%s\n",
verb,
resourceType,
resourceId,
date,
"")
hmacKey, _ := base64.StdEncoding.DecodeString(base64Key)
// handle error
hasher := hmac.New(sha256.New, hmacKey)
hasher.Write([]byte(msg))
signature := base64.StdEncoding.EncodeToString(hasher.Sum(nil))
authHeader := fmt.Sprintf("type=master&ver=1.0&sig=%s", signature)
return url.QueryEscape(authHeader)
}
因此,Go版本几乎是正确的(除了密钥),C#部分几乎是正确的(非RFC1123格式除外)。