我正在尝试计算与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的客户端代码来使其工作。