亚马逊签名版本4计算

时间:2014-06-27 18:54:20

标签: amazon-web-services amazon-s3 coffeescript

我正在尝试计算与here

所示相同的情况

以下是使用CryptoJS的coffeescirpt片段。根据示例,EncodedPolicy是正确的。

    hmac = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA256, "AWS4" + "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY")
    hmac.update("20130806")
    hmac.update("us-east-1")
    hmac.update("s3")
    hmac.update("aws4_request")
    hmac.update(EncodedPolicy)
    console.log( hmac.finalize().toString() )

输出为“71df5c44d375c21856d92de15941bc0deaf1a845e197c7f46834663256092f56”,但预计为“21496b44de44ccb73d545f1a995c68214c9cb0d41c45a17a5daeec0b1a6db047”。

更新:

    getSignatureKey = (key, dateStamp, regionName, serviceName, EncodedPolicy) ->
      hmac = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA256, "AWS4" + key)
      hmac.update( dateStamp )
      dateKey = hmac.finalize()
      hmac = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA256, dateKey )
      hmac.update( regionName )
      regionKey = hmac.finalize()
      hmac = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA256, regionKey )
      hmac.update( serviceName )
      serviceKey = hmac.finalize()
      hmac = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA256, serviceKey )
      hmac.update( "aws4_request" )
      requestKey = hmac.finalize()
      hmac = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA256, requestKey )
      hmac.update( EncodedPolicy )
      return hmac.finalize()

至少在requestKey之前是正确的。仍然得到亚马逊的回应,说他们计算的签名与我提供的签名不符。

UPDATE2: 以下是所有相关代码。

服务器代码     @ s3 = {}     @ s3.key =“AWS-KEY”     @ s3.privKey =“AWS-PRIV-KEY”     @ s3.region ='us-east-1'     @ s3.service ='s3'     @ s3.alg ='AWS4-HMAC-SHA256'     @ s3.bucket ='bucket-name'     @ s3.acl ='public-read'

@s3.generate_policy = (path,date) ->
  policy = { 
    "conditions": [
      {'bucket': s3.bucket}
      ['starts-with', '$key', path]
      {'acl': s3.acl}
      {'success_action_status': '200'}
      ["content-length-range", 0, 100000]
      ['starts-with', '$Content-Type', 'image/jpeg']
    ]
    "expiration": date.format("YYYY-MM-DDTHH:mm:ss.00\\Z")
  }
  return policy

getSignatureKey = (key, dateStamp, regionName, serviceName, stringToSign) ->
  hmac = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA256, "AWS4" + key)
  hmac.update( dateStamp )
  dateKey = hmac.finalize()
  hmac = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA256, dateKey )
  hmac.update( regionName )
  regionKey = hmac.finalize()
  hmac = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA256, regionKey )
  hmac.update( serviceName )
  serviceKey = hmac.finalize()
  hmac = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA256, serviceKey )
  hmac.update( "aws4_request" )
  requestKey = hmac.finalize()
  hmac = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA256, requestKey )
  hmac.update( stringToSign )
  return hmac.finalize()

stringToSign = (alg, date, creds, hashedReq) ->
  return alg + '\n' + date.format( "YYYYMMDDTHHMMSS\\Z" ) + '\n' + creds + '\n' + hashedReq

canonReq = (date, creds, alg) ->
  headers = "host: " + s3.bucket + ".s3.amazonaws.com" + '\n'
  headers += "Content-type: image/jpeg; charset=utf-8" + '\n'
  headers += "x-amz-date: " + date.format("YYYYMMDDTHHmmss\\Z") + '\n'

  signedHeaders = "content-type;host;x-amz-date"

  canonReq = "POST http://" + s3.bucket + ".s3.amazonaws.com/ HTTP/1.1" + '\n'
  canonReq += "\\" + '\n'
  canonReq += '\n'
  canonReq += headers
  canonReq += '\n'
  canonReq += signedHeaders  + '\n'
  canonReq += CryptoJS.SHA256( signedHeaders )

@s3.generate_credentials = (path, date) ->
  policy = new Buffer(JSON.stringify(s3.generate_policy(path, date )).replace('\n', "")).toString('base64')
  creds = s3.key + '/' + date.format("YYYYMMDD") + '/'  + s3.region + '/' + s3.service + '/' + 'aws4_request'

  hashedCanonicalReq = CryptoJS.SHA256( canonReq(date) )

  stringToSign = stringToSign( s3.alg, date, creds, hashedCanonicalReq )

  sig = getSignatureKey(s3.privKey,date.format('YYYYMMDD'),s3.region,s3.service, stringToSign) 

  credentials = {
    AWSkey: s3.key
    key: path
    policy: policy
    bucket: s3.bucket
    signature: sig.toString()
    acl: s3.acl
    date: date.format("YYYYMMDDTHHmmss\\Z")
    alg: s3.alg
    creds: creds
  }
  return credentials

@Meteor.methods
  get_s3_credentials: () ->
    if !Meteor.user()
      return

    path = "test"
    date = moment().utc().add('minutes', 5)
    credentials = s3.generate_credentials(path, date)
    return credentials

客户代码

uploadFile = function() {
  Meteor.call( 'get_s3_credentials', function(err, res) {
    if( res ){
      var file = document.getElementById('uploadFiles').files[0];
      var fd = new FormData();

      console.log( res );

      fd.append('key',res.key);
      fd.append('AWSAccessKeyId', res.AWSkey)
      fd.append('acl',res.acl);
      fd.append('signature',res.signature);
      fd.append('policy', res.policy);
      fd.append('success_action_status',200);
      fd.append('Content-Type',"image/jpeg");
      fd.append("file",file);

      var xhr = new XMLHttpRequest();

      xhr.open('POST', 'https://' + res.bucket + '.s3.amazonaws.com', true);

      xhr.send(fd);
    }else{
      console.log( err );
    }
  });
}

更新: 能够使用aws-sdk(签名URL)和来自http://www.recursiverobot.com/post/75281512146/demos-using-aws-with-node-js-and-an-angularjs-frontend#s3的客户端代码来使其工作。

0 个答案:

没有答案