简体   繁体   English

AWS身份验证V4签名失败; 生成签名时我哪里出错了?

[英]AWS authentication V4 signature failure; where am I going wrong in generating the signature?

I am generating a form using the ruby code below (passing the CSV file with credentials downloads from the AWS console as the argument). 我正在使用下面的Ruby代码生成表单(将带有从AWS控制台下载的凭证的CSV文件作为参数传递给CSV文件)。 If I submit a file using this form, I get The request signature we calculated does not match the signature you provided. Check your key and signing method. 如果我使用此表单提交文件, The request signature we calculated does not match the signature you provided. Check your key and signing method.得到The request signature we calculated does not match the signature you provided. Check your key and signing method. The request signature we calculated does not match the signature you provided. Check your key and signing method. . I have copied the signing code from http://docs.aws.amazon.com/general/latest/gr/signature-v4-examples.html#signature-v4-examples-ruby . 我已经从http://docs.aws.amazon.com/general/latest/gr/signature-v4-examples.html#signature-v4-examples-ruby复制了签名代码。 I've looked at Amazon MWS - request signature calculated does not match the signature provided and s3 "signature doesn't match" client side post jquery-file-upload , but these don't seem to apply in my case. 我看过Amazon MWS-计算的请求签名与提供的签名不匹配,并且s3“签名不匹配”客户端发布jquery-file-upload ,但是这些似乎不适用于我的情况。 Where am I going wrong? 我要去哪里错了?

#!/usr/bin/env ruby

require 'nokogiri'
require 'csv'
require 'ostruct'
require 'base64'
require 'json'
require 'openssl'

header = nil
data = nil
CSV.foreach(ARGV[0]) do |row|
  if header.nil?
    header = row.collect{|c| c.strip.gsub(/\s/, '') }
  else
    data = row
  end
end
creds = OpenStruct.new(Hash[*(header.zip(data).flatten)])

bucket = 'zotplus'
region = 'eu-central-1'
service = 's3'
dateStamp = Time.now.strftime('%Y%m%d')

policy = {
  'expiration' => '2029-01-01T00:00:00Z',
  'conditions' => [
    {'bucket' => bucket},
    ['starts-with', '$key', 'uploads/'],
    {'acl' => 'private'},
    {'success_action_redirect' => 'http://zotplus.github.io/submitted.html'},
    ['starts-with', '$Content-Type', 'multipart/form-data'],
    ['content-length-range', 0, 1048576],
    {'x-amz-date' => "#{dateStamp}T000000Z"},
    {'x-amz-credential' => "#{creds.AccessKeyId}/#{dateStamp}/#{region}/#{service}/aws4_request"}
  ]
}

form = {}
%w{acl success_action_redirect bucket x-amz-date x-amz-credential}.each{|eq|
  form[eq] = policy['conditions'].detect{|c| c.is_a?(Hash) && c[eq] }[eq]
}
form['key'] = policy['conditions'].detect{|c| c.is_a?(Array) && c[0,2] = ['starts-with', '$key']}[2] + '${filename}'

policy_string = Base64.encode64(policy.to_json).gsub("\n","")

kDate    = OpenSSL::HMAC.digest('sha256', "AWS4" + creds.SecretAccessKey, dateStamp)
kRegion  = OpenSSL::HMAC.digest('sha256', kDate, region)
kService = OpenSSL::HMAC.digest('sha256', kRegion, service)
kSigning = OpenSSL::HMAC.digest('sha256', kService, 'aws4_request')

signature = Base64.encode64(OpenSSL::HMAC.digest('sha256', kSigning, policy_string)).gsub("\n","")

form['policy'] = policy_string
form['x-amz-signature'] = signature
form['x-amz-algorithm'] = 'AWS4-HMAC-SHA256'

builder = Nokogiri::HTML::Builder.new do |doc|
  doc.html {
    doc.head {
      doc.title {
        doc.text 'submit file'
      }
      doc.meta('http-equiv' => "Content-Type", content: "text/html; charset=UTF-8")
    }

    doc.body {
      doc.form(action: "http://zotplus-964ec2b7-379e-49a4-9c8a-edcb20db343f.s3.amazonaws.com/", method: "post", enctype: "multipart/form-data") {
        form.each_pair{|k, v|
          doc.input(type: "hidden", name: k, value: v)
        }

        doc.text 'File: '
        doc.input(type: "file", name: "file")
        doc.input(type: "submit", name: "submit", value: "Upload to Amazon S3")
      }
    }
  }
end
puts builder.to_html

OK, it turns out the policy signature should not be base64 encoded but simply output as a hex digest. 好的,事实证明策略签名不应该使用base64编码,而只能以十六进制摘要形式输出。 For those struggling with the same problem, this is what worked in the end: 对于那些同样遇到难题的人,最终的结果是:

#!/usr/bin/env ruby

require 'json'
require 'base64'
require 'openssl'
require 'csv'
require 'ostruct'
require 'nokogiri'

algorithm = 'AWS4-HMAC-SHA256'
service = 's3'
requestType = 'aws4_request'
successStatus = '201'
bucket = 'zotplus-964ec2b7-379e-49a4-9c8a-edcb20db343f'
region = 'eu-central-1'
acl = 'private'

header = nil
data = nil
CSV.foreach(ENV['ZOTPLUSAWSCREDENTIALS']) do |row|
  if header.nil?
    header = row.collect{|c| c.strip.gsub(/\s/, '') }
  else
    data = row
  end
end
creds = OpenStruct.new(Hash[*(header.zip(data).flatten)])

date = Time.now.strftime('%Y%m%dT%H%M%SZ')
shortDate = date.sub(/T.*/, '')
credentials = [ creds.AccessKeyId, shortDate, region, service, requestType ].join('/')

policy = Base64.encode64({
  'expiration' => (Time.now + (60*60*24*365*30)).strftime('%Y-%m-%dT%H:%M:%SZ'), # 30 years from now
  'conditions' => [
    {'bucket' => bucket},
    {'acl' => acl},
    ['starts-with', '$key', ''],
    ['starts-with', '$Content-Type', ''],
    {'success_action_status' => successStatus},
    {'x-amz-credential' => credentials},
    {'x-amz-algorithm' => algorithm},
    {'x-amz-date' => date},
    ['content-length-range', 0, 1048576],
  ]
}.to_json).gsub("\n","")

signingKey = ['AWS4' + creds.SecretAccessKey, shortDate, region, service, requestType].inject{|key, data| OpenSSL::HMAC.digest('sha256', key, data) } 

form = OpenStruct.new({
  action: "http://#{bucket}.#{service}-#{region}.amazonaws.com",
  fields: [ # order matters!
    {key: '${filename}'},
    {'Content-Type': 'text/plain'},
    {acl: acl},
    {success_action_status: successStatus},
    {policy: policy},
    {'x-amz-algorithm': algorithm},
    {'x-amz-credential': credentials},
    {'x-amz-date': date},
    {'x-amz-signature': OpenSSL::HMAC.hexdigest('sha256', signingKey, policy)}
  ]
})

################################################

builder = Nokogiri::HTML::Builder.new do |doc|
  doc.html {
    doc.head {
      doc.meta(charset: 'utf-8')
      doc.title { doc.text 'Upload' }
    }
    doc.body {
      doc.form(action: form.action, method: 'POST', enctype: "multipart/form-data") {
        form.fields.each{|field|
          field.each_pair{|name, value|
            doc.input(type: 'hidden', name: name, value: value)
          }
        }
        doc.input(type: 'file', name: 'file')
        doc.input(type: 'submit', value: 'Save')
      }
    }
  }
end
puts builder.to_html

Yea it works :DI tried it this way 是的,它是有效的:DI这样尝试过

def index
access_key = 'YOUR_ACCESS_KEY'
secret_key = 'YOUR_SECRET_KEY'
time = Time.now.utc
date_stamp = time.strftime("%Y%m%d")
region_name = 'ap-south-1'
key_date    = hmac_digest('sha256', "AWS4" + secret_key, date_stamp)
key_region  = hmac_digest('sha256', key_date, region_name)
key_service = hmac_digest('sha256', key_region, 's3')
key_signing = hmac_digest('sha256', key_service, "aws4_request")
algorithm = 'AWS4-HMAC-SHA256'
amzdate = time.strftime('%Y%m%dT%H%M%SZ')
credential_scope = access_key + '/' + date_stamp + '/ap-south-1/s3/aws4_request'
policy = generate_policy(credential_scope, algorithm, amzdate)
signature = OpenSSL::HMAC.hexdigest('sha256', key_signing, policy)
render json: { policy: policy, signature: signature, key: access_key, date: amzdate, credentials: credential_scope, algorithm: algorithm }
end
def generate_policy(credential_scope, algorithm, amzdate)
Base64.encode64({
  'expiration' => (Time.now + (60 * 60 * 24 * 365 * 30)).strftime('%Y-%m-%dT%H:%M:%SZ'), # 30 years from now
  'conditions' => [
    { 'bucket' => 'adcreation-m' },
    { 'acl' => 'public-read' },
    ['starts-with', '$key', ''],
    ['starts-with', '$Content-Type', ''],
    { 'success_action_status' => '201' },
    { 'x-amz-credential' => credential_scope },
    { 'x-amz-algorithm' => algorithm },
    { 'x-amz-date' => amzdate },
    ['content-length-range', 0, 256000000]
  ]
}.to_json).delete("\n")
end

def hmac_digest(digest, key, data)
 OpenSSL::HMAC.digest(digest, key, data)
end

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 设置bxSlider幻灯片放错了什么地方? - Where am I going wrong setting up bxSlider slideshow? Sorbet 没有报告丢失的方法实现(与 RBI 签名相比),我在这里做错了什么吗? - Sorbet doesn't report a missing method implementation (compared to an RBI signature), am I doing something wrong here? 为AWS请求逻辑生成签名-返回SignatureDoesNotMatch - generating a signature for AWS request logic - getting SignatureDoesNotMatch back 在php生成数字签名 - Generating digital signature in php 我无法生成迁移-“必须指定控制器的非法路线”-我在哪里出错? - I can't generate migrations - “illegal route the controller must be specified” - where am I going wrong? 我要去哪里错了? Sinatra:模块的“未定义方法&#39;应用程序&#39;” Sinatra / Passenger / Apache - Where am I going wrong? “undefined method 'application' for Sinatra:Module” Sinatra/Passenger/Apache 另一个禁止的属性错误-无法找到我在哪里出错 - Yet another forbidden attributes error - cannot find where I am going wrong with this 我收到 Stripe 签名错误:# <Stripe::SignatureVerificationError: No signatures found matching the expected signature for payload> - I am getting a Stripe signature error: #<Stripe::SignatureVerificationError: No signatures found matching the expected signature for payload> 无法通过Ruby on Rails中的SOAP连接(SAVON)调用Web服务方法。 我要去哪里错了? - Cannot call web service methods via SOAP Connection (SAVON) in Ruby on Rails. Where am i going wrong? 救援/异常在编辑器中标记为红色? 我是不是走错了 - rescue / exeception marked as red in editor? Were Am I going wrong
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM