ruby - AWS authentication V4 signature failure; where am I going wrong in generating the signature? -


i generating form using ruby code below (passing csv file credentials downloads aws console argument). if submit file using form, the request signature calculated not match signature provided. check key , signing method.. have copied signing code http://docs.aws.amazon.com/general/latest/gr/signature-v4-examples.html#signature-v4-examples-ruby. i've looked @ amazon mws - request signature calculated not match signature provided , s3 "signature doesn't match" client side post jquery-file-upload, these don't seem apply in case. 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]) |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 |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 amazon s3")       }     }   } end puts builder.to_html 

ok, turns out policy signature should not base64 encoded output hex digest. struggling same problem, worked in 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']) |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   '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 |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 

Comments

Popular posts from this blog

How has firefox/gecko HTML+CSS rendering changed in version 38? -

javascript - Complex json ng-repeat -

jquery - Cloning of rows and columns from the old table into the new with colSpan and rowSpan -