Вычисление подписи Amazon версии 4

#amazon-web-services #amazon-s3 #coffeescript

#amazon-веб-сервисы #amazon-s3 #coffeescript

Вопрос:

Я пытаюсь вычислить ту же ситуацию, что и показано здесь

Ниже приведен фрагмент coffeescirpt, который использует CryptoJS. 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. Все еще получаю ответ от Amazon, в котором говорится, что вычисленная ими подпись не соответствует предоставленной мной.

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 = ‘имя корзины’ @s3.acl = ‘общедоступное чтение’

 @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.

Комментарии:

1. Спасибо, что задали этот вопрос, помогли мне сегодня. Вы можете добавить ответ на свой собственный вопрос, чтобы его можно было пометить как «принятый».