Main codes
function getYMD(d) {
let r = d.getFullYear().toString();
let m = d.getUTCMonth() + 1;
if (m < 10)
m = "0" + m.toString();
else
m = m.toString();
r = r + m;
let day = d.getUTCDate();
if (day < 10)
day = "0" + day.toString();
else
day = day.toString();
r = r + day;
return r;
}
function getTZ(d) {
let r = d.getFullYear().toString();
let m = d.getUTCMonth() + 1;
if (m < 10)
m = "0" + m.toString();
else
m = m.toString();
r = r + m;
let day = d.getUTCDate();
if (day < 10)
day = "0" + day.toString();
else
day = day.toString();
r = r + day + "T";
let h = d.getUTCHours();
if (h < 10)
h = "0" + h.toString();
else
h = h.toString();
r = r + h;
let min = d.getUTCMinutes();
if (min < 10)
min = "0" + min.toString();
else
min = min.toString();
r = r + min;
let s = d.getUTCSeconds();
if (s < 10)
s = "0" + s.toString();
else
s = s.toString();
r = r + s;
r = r + "Z";
return r;
}
const crypto = require('crypto');
function Hmac(key, string){
const hmac = crypto.createHmac('sha256', key);
hmac.end(string);
return hmac.read();
}
function Signature(date, region, service, toSign) {
let dateKey = Hmac('AWS4' + AWS_SECRETACCESS_KEY, date);
let dateRegionKey = Hmac(dateKey, region);
let dateRegionServiceKey = Hmac(dateRegionKey, service);
let signingKey = Hmac(dateRegionServiceKey, 'aws4_request');
let signature = Hmac(signingKey, toSign).toString('hex');
return signature;
}
function stringToSign(timeStamp, scope, canonicalRequest) {
var signParts = [];
signParts.push('AWS4-HMAC-SHA256');
signParts.push(timeStamp);
signParts.push(scope);
signParts.push(crypto.createHash('sha256').update(canonicalRequest).digest(
'hex'));
var result = signParts.join('\n');
console.log('string to sign');
console.log(result);
return result;
};
function canonicalRequest(method, uri, queryString, headers, signedHeaders, has
hedPayload) {
var canonicalParts = [];
canonicalParts.push(method);
canonicalParts.push(uri);
canonicalParts.push(queryString);
canonicalParts.push(headers);
canonicalParts.push(signedHeaders);
canonicalParts.push(hashedPayload);
var result = canonicalParts.join('\n');
console.log('canonical request');
console.log(result);
return result;
}
function download(filepath) {
let filename = filepath;
let position = filename.lastIndexOf('/');
if (position != -1) {
filename = filename.substr(position+1);
}
let d = new Date();
let dtz = getTZ(d);
let dymd = getYMD(d);
let scope = dymd + '/' + AWS_REGION + '/' + AWS_SERVICE + '/aws4_request';
let uri = filepath;
let queryString = "X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=" + en
codeURIComponent(AWS_KEY + "/" + scope) + "&X-Amz-Date=" + dtz + "&X-Amz-Expire
s=400&X-Amz-SignedHeaders=host&response-content-disposition=attachment%3Bfilena
me%3D" + filename;
let headers = "host:s3.amazonaws.com";
let signedHeaders = "";
let hashedPayload = "host\nUNSIGNED-PAYLOAD";
let request = canonicalRequest('GET', uri, queryString, headers, signedHead
ers, hashedPayload);
let signature = Signature(dymd, AWS_REGION, AWS_SERVICE, stringToSign(dtz,
scope, request));
let url = 'https://s3.amazonaws.com' + filepath + '?response-content-dispos
ition=attachment;filename=' + filename + '&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-A
mz-Credential=' + AWS_KEY + "/" + scope + '&X-Amz-Date=' + dtz + '&X-Amz-Expire
s=400&X-Amz-SignedHeaders=host&X-Amz-Signature=' + signature;
console.log(url);
var link = document.createElement('a');
link.innerHTML = 'download';
link.href = url;
document.body.appendChild(link);
}
Usage
const AWS_KEY = 'your aws key';
const AWS_SECRETACCESS_KEY = 'your aws secret access key';
const AWS_REGION = 'your bucket region'; // default us-east-1
const AWS_SERVICE = 's3';
download('/yourbucket/objectkey');
examle
Refers
GET Object Signing AWS Requests with Signature Version 4 Authenticating Requests: Using Query Parameters (AWS Signature Version 4)
Key point:
?response-content-disposition=attachment;filename=objectname
Using this header, browser will open an save dialog once the down load url is correct signed.
You will get a url link like:
https://s3.amazonaws.com/bucket/objectkey?response-content-disposition=attachment;filename=objectname&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAJWWH7EGSUBWE34IQ/20181218/us-east-1/s3/aws4_request&X-Amz-Date=20181218T053905Z&X-Amz-Expires=400&X-Amz-SignedHeaders=host&X-Amz-Signature=71d82d4a99338d777bfa3517315d34cad94619a9ca891222808e16dd02de7835