forgeplus/app/services/huawei/signer.rb

54 lines
1.4 KiB
Ruby

require 'openssl'
require 'base64'
require 'json'
require 'uri'
require 'time'
class Huawei::Signer
def initialize(ak, sk)
@ak = ak
@sk = sk
end
def sign_request(method, url, headers = {}, body = "")
uri = URI.parse(url)
host = uri.host
path = uri.path.empty? ? "/" : uri.path
query = uri.query ? "?" + uri.query : ""
# 时间戳
x_sdk_date = Time.now.utc.strftime("%Y%m%dT%H%M%SZ")
# Step 1: CanonicalRequest
canonical_headers = "host:#{host}\n" \
"x-sdk-date:#{x_sdk_date}\n"
signed_headers = "host;x-sdk-date"
hashed_payload = Digest::SHA256.hexdigest(body)
canonical_request = "#{method}\n#{path}\n#{query}\n#{canonical_headers}\n#{signed_headers}\n#{hashed_payload}"
# Step 2: StringToSign
hashed_canonical = Digest::SHA256.hexdigest(canonical_request)
string_to_sign = "SDK-HMAC-SHA256\n#{x_sdk_date}\n#{hashed_canonical}"
# Step 3: 计算签名
signature = OpenSSL::HMAC.hexdigest("SHA256", @sk, string_to_sign)
# Step 4: 生成 Authorization
authorization = "SDK-HMAC-SHA256 Access=#{@ak}, SignedHeaders=#{signed_headers}, Signature=#{signature}"
# 合并 headers
signed_headers_hash = {
"Authorization" => authorization,
"X-Sdk-Date" => x_sdk_date,
"Host" => host,
"Content-Type" => "application/json"
}
headers.merge!(signed_headers_hash)
headers
end
end