难以为阿里云生成签名

时间:2018-07-12 22:08:04

标签: alibaba-cloud

读取HTTP API docs。我的请求因签名错误而失败。从错误消息中,我可以看到我要签名的字符串是正确的,但是看起来我无法生成正确的HMAC-SHA1(严重地为什么仍要使用SHA1?)。

所以我决定尝试在同一文档中复制样本的签名。

[47] pry(main)> to_sign = "GET&%2F&AccessKeyId%3Dtestid&Action%3DDescribeRegions&Format%3DXML&SignatureMethod%3DHMAC-SHA1&SignatureNonce%3D3ee8c1b8-83d3-44af-a94f-4e0ad82fd6cf&SignatureVersion%3D1.0&Timestamp%3D2016-02-23T12%253A46%253A24Z&Version%3D2014-05-26"

[48] pry(main)> Base64.encode64 OpenSSL::HMAC.digest("sha1", "testsecret", to_sign)
=> "MLAxpXej4jJ7TL0smgWpOgynR7s=\n"

[49] pry(main)> Base64.encode64 OpenSSL::HMAC.digest("sha1", "testsecret&", to_sign)
=> "VyBL52idtt+oImX0NZC+2ngk15Q=\n"

[50] pry(main)> Base64.encode64 OpenSSL::HMAC.hexdigest("sha1", "testsecret&", to_sign)
=> "NTcyMDRiZTc2ODlkYjZkZmE4MjI2NWY0MzU5MGJlZGE3ODI0ZDc5NA==\n"

[51] pry(main)> Base64.encode64 OpenSSL::HMAC.hexdigest("sha1", "testsecret", to_sign)
=> "MzBiMDMxYTU3N2EzZTIzMjdiNGNiZDJjOWEwNWE5M2EwY2E3NDdiYg==\n"

[52] pry(main)> OpenSSL::HMAC.hexdigest("sha1", "testsecret&", to_sign)
=> "57204be7689db6dfa82265f43590beda7824d794"

[53] pry(main)> OpenSSL::HMAC.hexdigest("sha1", "testsecret", to_sign)
=> "30b031a577a3e2327b4cbd2c9a05a93a0ca747bb"

显然,这些都不匹配CT9X0VtwR86fNWSnsc6v8YGOjuE=的示例签名。知道这里缺少什么吗?

更新:从Golang客户端工具中提取了tcpdump,我看到它发出了一个POST请求,例如:

POST /?AccessKeyId=**********&Action=DescribeRegions&Format=JSON&RegionId=cn-qingdao&Signature=aHZVpIMb0%2BFKdoWSIVaFJ7bd2LA%3D&SignatureMethod=HMAC-SHA1&SignatureNonce=c29a0e28964c470a8997aebca4848b57&SignatureType=&SignatureVersion=1.0&Timestamp=2018-07-16T19%3A46%3A33Z&Version=2014-05-26 HTTP/1.1

    Host: ecs.aliyuncs.com
    User-Agent: Aliyun-CLI-V3.0.3
    Content-Length: 0
    Content-Type: application/x-www-form-urlencoded
    x-sdk-client: golang/1.0.0
    x-sdk-core-version: 0.0.1
    x-sdk-invoke-type: common
    Accept-Encoding: gzip

当我从上述请求中获取参数并生成签名时,它匹配。因此,我尝试了所有树:GETPOST(带有URL参数)和POST(带有正文参数)。每次我遇到签名错误。如果我使用与golang工具完全相同的参数来重做请求,那么我将收到现时现用错误(如预期)。

2 个答案:

答案 0 :(得分:1)

  • 似乎aliyun ruby sdk(非官方,仅供参考)有效。您可能要检查how it's implemented
  • 检查其string_to_sign的外观。我进行了一次跑步,似乎与您提供的服务略有不同。参数用O(log(n))而不是&串联。 %26
    require 'rubygems'
    require 'aliyun'

    $DEBUG = true

    options = {
      :access_key_id => "k",
      :access_key_secret => "s",
      :service => :ecs
    }

    service = Aliyun::Service.new options

    puts service.DescribeRegions({})

答案 1 :(得分:1)

最后成功了。在我的情况下,主要问题是我对签名参数进行了百分之二的编码,因此结果无效。对我最大的帮助是运行{% extends "base.html" %} <h1>Django</h1> {% block content %} <h1>Django</h1> {% endblock %} cli实用程序并捕获流量,然后使用完全相同的参数运行查询以比较确切的查询字符串。

但是让我列出一些要点:

  1. 生成hmac-sha1 sig后,请勿对其进行百分比编码,只需将其以常规格式www编码添加到查询中
  2. HTTP查询中参数的
  3. 顺序不重要;尽管签名字符串中的参数顺序很重要
  4. 我发现以下所有类型的请求都可以工作:GET,URL查询中带有参数的POST,POST请求中带有www编码的请求主体形式的参数;我在每个文档中都使用GET,但我看到aliyun在POST中使用POST vs查询参数和查询中的有序参数
  5. 生成HMAC-SHA1时,必须在密钥的末尾添加aliyun字符
  6. 以二进制形式生成HMAC-SHA1,然后编码为Base64(无十六进制值)
  7. 某些参数可能不区分大小写,例如&既可以用作Format,也可以用作json
  8. 我看到aliyun,@ wanghq和John将UUID 4用于SignatureNonce,但我将其推迟为普通随机(根据文档),因为它似乎只是重放攻击保护。因此,无需使用加密安全的随机数。
  9. JSON+*的特殊编码规则似乎仅适用于签名字符串,而实际上并不适用于HTTP查询中的数据编码。
  10. li>

我决定不使用@wanghq的包装器,因为它对我也不起作用disables certificate validation,但也许它将得到解决。我只是以为,一旦找出签名,查询就足够简单了,而附加的间接层是不值得的。尽管对我的签名有帮助,​​但对他的答案+1。

下面是发出简单请求的示例红宝石代码:

~

可以稍微简化一下代码,但决定使其与文档说明非常接近。

P.S。不知道为什么约翰删除了他的答案,但是在上面为任何寻找示例代码的python家伙留下了指向他网页的链接