douyong1974 2017-10-07 21:04
浏览 54
已采纳

在GoLang中生成CosmosDB身份验证令牌

I'm trying to generate a CosmosDb Auth token by following the instructions here: https://docs.microsoft.com/en-us/rest/api/documentdb/access-control-on-documentdb-resources.

Here's my implementation in GoLang (I replaced all the parameters with literal values found in the "Example Encoding" section from the doc above):

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
%s
%s
%s
%s
",
        "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)
}

I also took the C# example from the link and ran it with the same parameters as a reference.

This is what I get from the C# implementation (the reference):

"type%3Dmaster%26ver%3D1.0%26sig%3DSGWmGNFZlBH%2Bt9QCvuMy%2FVsbBAOKLbxsgy3Z7aG0PdA%3D"

And this is what I get from my GoLang implementation:

"type%3Dmaster%26ver%3D1.0%26sig%3Dwst1NDxfOeoYMurn69DgZtJUQOrgxFz%2Bp6A2vKnXxEI%3D"

Clearly I'm doing something wrong in the GoLang implementation since the two aren't identical (maybe mis-using the hashing libraries?)

For easy reference, here's the C# implementation:

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}
{1}
{2}
{3}
{4}
",
            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));
}
  • 写回答

1条回答 默认 最新

  • drudfe0446838 2017-10-07 23:45
    关注

    This took me longer to find than I would have hoped. There is one obvious problem, you are not base64 decoding the key on this line

    hasher := hmac.New(sha256.New, []byte(base64Key))
    

    You should do something like

    hmacKey, _ := base64.StdEncoding.DecodeString(base64Key)
    // handle error
    hasher := hmac.New(sha256.New, hmacKey)
    

    But even that didn't fix it. Not until I finally figured out this discrepancy

    C# "thu, 27 apri 2017 00:51:12 gmt"
    Go "thu, 27 apr 2017 00:51:12 gmt" 
    

    This works

    func generateAuthToken(
        verb string,
        resourceType string,
        resourceId string,
        date string,
        base64Key string) string {
    
        msg := fmt.Sprintf("%s
    %s
    %s
    %s
    %s
    ",
            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)
    }
    

    And here is a Go Playground Link

    So, the Go version was nearly right (except for the key) and the C# part was almost right (except for the non-RFC1123 format).

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 对于相关问题的求解与代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 信号傅里叶变换在matlab上遇到的小问题请求帮助
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作
  • ¥15 求NPF226060磁芯的详细资料