Comparing version 2.0.1 to 2.1.1
@@ -9,5 +9,5 @@ (function(e, a) { for(var i in a) e[i] = a[i]; }(exports, /******/ (function(modules) { // webpackBootstrap | ||
/******/ // Check if module is in cache | ||
/******/ if(installedModules[moduleId]) | ||
/******/ if(installedModules[moduleId]) { | ||
/******/ return installedModules[moduleId].exports; | ||
/******/ | ||
/******/ } | ||
/******/ // Create a new module (and put it into the cache) | ||
@@ -75,3 +75,3 @@ /******/ var module = installedModules[moduleId] = { | ||
"use strict"; | ||
Object.defineProperty(exports,'__esModule',{value:!0}),exports.hash=void 0,exports.formatDateTime=formatDateTime,exports.buildCanonicalRequest=buildCanonicalRequest,exports.buildStringToSign=buildStringToSign,exports.preCalculateSigningKey=preCalculateSigningKey,exports.preCalculatedSign=preCalculatedSign,exports.sign=sign,exports.buildAuthorization=buildAuthorization;var _deps=__webpack_require__(1);exports.hash=_deps.hash;const algorithm='AWS4-HMAC-SHA256',emptyHash='e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855';function formatDateTime(a){return a.toISOString().replace(/-|:|(\.\d+)/g,'')}function buildCanonicalRequest(a,b,c,d,e,f=''){return(f?(0,_deps.hash)(f):Promise.resolve(emptyHash)).then((g)=>[a,b,c,d,'',e,g].join('\n'))}function buildStringToSign(a,b,c){return[algorithm,a,b,c].join('\n')}function preCalculateSigningKey(a,b,c,d){const e=[b,c,d,'aws4_request'];let f=Promise.resolve(`AWS4${a}`);var g=!0,h=!1,i=void 0;try{for(var k,j=e[Symbol.iterator]();!(g=(k=j.next()).done);g=!0){const l=k.value;f=f.then((m)=>(0,_deps.hmac)(m,l))}}catch(l){h=!0,i=l}finally{try{!g&&j.return&&j.return()}finally{if(h)throw i}}return f}function preCalculatedSign(a,b){return(0,_deps.hmac)(a,b,'hex')}function sign(a,b,c,d,e){return preCalculateSigningKey(a,b,c,d).then((f)=>preCalculatedSign(f,e))}function buildAuthorization(a,b,c,d){return algorithm+' '+[['Credential',`${a}/${b}`],['SignedHeaders',c],['Signature',d]].map((e)=>e.join('=')).join(', ')} | ||
Object.defineProperty(exports,'__esModule',{value:true});exports.sign=exports.preCalculateSigningKey=exports.buildCanonicalRequest=exports.hash=undefined;let buildCanonicalRequest=exports.buildCanonicalRequest=(()=>{var _ref=_asyncToGenerator(function*(httpRequestMethod,canonicalURI,canonicalQueryString,canonicalHeaders,signedHeaders,requestPayload=''){return[httpRequestMethod,canonicalURI,canonicalQueryString,canonicalHeaders,'',signedHeaders,yield requestPayload?(0,_deps.hash)(requestPayload):emptyHash].join('\n')});return function buildCanonicalRequest(_x,_x2,_x3,_x4,_x5){return _ref.apply(this,arguments)}})();let preCalculateSigningKey=exports.preCalculateSigningKey=(()=>{var _ref2=_asyncToGenerator(function*(secretAccessKey,date,region,service){return[date,region,service,'aws4_request'].reduce((()=>{var _ref3=_asyncToGenerator(function*(acc,val){return(0,_deps.hmac)((yield acc),val)});return function(_x10,_x11){return _ref3.apply(this,arguments)}})(),`AWS4${secretAccessKey}`)});return function preCalculateSigningKey(_x6,_x7,_x8,_x9){return _ref2.apply(this,arguments)}})();let sign=exports.sign=(()=>{var _ref4=_asyncToGenerator(function*(secretAccessKey,date,region,service,stringToSign){const signingKey=yield preCalculateSigningKey(secretAccessKey,date,region,service);return preCalculatedSign(signingKey,stringToSign)});return function sign(_x12,_x13,_x14,_x15,_x16){return _ref4.apply(this,arguments)}})();exports.formatDateTime=formatDateTime;exports.buildStringToSign=buildStringToSign;exports.preCalculatedSign=preCalculatedSign;exports.buildAuthorization=buildAuthorization;var _deps=__webpack_require__(1);function _asyncToGenerator(fn){return function(){var gen=fn.apply(this,arguments);return new Promise(function(resolve,reject){function step(key,arg){try{var info=gen[key](arg);var value=info.value}catch(error){reject(error);return}if(info.done){resolve(value)}else{return Promise.resolve(value).then(function(value){step('next',value)},function(err){step('throw',err)})}}return step('next')})}}exports.hash=_deps.hash;const algorithm='AWS4-HMAC-SHA256';const emptyHash='e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855';function formatDateTime(date){return date.toISOString().replace(/-|:|(\.\d+)/g,'')}function buildStringToSign(requestDate,credentialScope,hashedCanonicalRequest){return[algorithm,requestDate,credentialScope,hashedCanonicalRequest].join('\n')}function preCalculatedSign(signingKey,stringToSign){return(0,_deps.hmac)(signingKey,stringToSign,'hex')}function buildAuthorization(accessKeyId,credentialScope,signedHeaders,signature){return algorithm+' '+[['Credential',`${accessKeyId}/${credentialScope}`],['SignedHeaders',signedHeaders],['Signature',signature]].map(item=>item.join('=')).join(', ')} | ||
@@ -83,3 +83,3 @@ /***/ }), | ||
"use strict"; | ||
Object.defineProperty(exports,'__esModule',{value:!0}),exports.normalize=void 0;var _path=__webpack_require__(3);Object.defineProperty(exports,'normalize',{enumerable:!0,get:function get(){return _path.normalize}}),exports.hmac=hmac,exports.hash=hash;var _crypto=__webpack_require__(2);const algorithm='sha256';function hmac(a,b,c){return Promise.resolve((0,_crypto.createHmac)(algorithm,a).update(b).digest(c))}function hash(a){return Promise.resolve((0,_crypto.createHash)(algorithm).update(a).digest('hex'))} | ||
Object.defineProperty(exports,'__esModule',{value:true});exports.hash=exports.hmac=exports.normalize=undefined;let hmac=exports.hmac=(()=>{var _ref=_asyncToGenerator(function*(key,data,encoding){return(0,_crypto.createHmac)(algorithm,key).update(data).digest(encoding)});return function hmac(_x,_x2,_x3){return _ref.apply(this,arguments)}})();let hash=exports.hash=(()=>{var _ref2=_asyncToGenerator(function*(data){return(0,_crypto.createHash)(algorithm).update(data).digest('hex')});return function hash(_x4){return _ref2.apply(this,arguments)}})();var _path=__webpack_require__(3);Object.defineProperty(exports,'normalize',{enumerable:true,get:function get(){return _path.normalize}});var _crypto=__webpack_require__(2);function _asyncToGenerator(fn){return function(){var gen=fn.apply(this,arguments);return new Promise(function(resolve,reject){function step(key,arg){try{var info=gen[key](arg);var value=info.value}catch(error){reject(error);return}if(info.done){resolve(value)}else{return Promise.resolve(value).then(function(value){step('next',value)},function(err){step('throw',err)})}}return step('next')})}}const algorithm='sha256'; | ||
@@ -86,0 +86,0 @@ /***/ }), |
@@ -19,5 +19,5 @@ (function webpackUniversalModuleDefinition(root, factory) { | ||
/******/ // Check if module is in cache | ||
/******/ if(installedModules[moduleId]) | ||
/******/ if(installedModules[moduleId]) { | ||
/******/ return installedModules[moduleId].exports; | ||
/******/ | ||
/******/ } | ||
/******/ // Create a new module (and put it into the cache) | ||
@@ -85,3 +85,3 @@ /******/ var module = installedModules[moduleId] = { | ||
"use strict"; | ||
Object.defineProperty(exports,'__esModule',{value:!0}),exports.hash=void 0,exports.formatDateTime=formatDateTime,exports.buildCanonicalRequest=buildCanonicalRequest,exports.buildStringToSign=buildStringToSign,exports.preCalculateSigningKey=preCalculateSigningKey,exports.preCalculatedSign=preCalculatedSign,exports.sign=sign,exports.buildAuthorization=buildAuthorization;var _deps=__webpack_require__(1);exports.hash=_deps.hash;const algorithm='AWS4-HMAC-SHA256',emptyHash='e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855';function formatDateTime(a){return a.toISOString().replace(/-|:|(\.\d+)/g,'')}function buildCanonicalRequest(a,b,c,d,e,f=''){return(f?(0,_deps.hash)(f):Promise.resolve(emptyHash)).then((g)=>[a,b,c,d,'',e,g].join('\n'))}function buildStringToSign(a,b,c){return[algorithm,a,b,c].join('\n')}function preCalculateSigningKey(a,b,c,d){const e=[b,c,d,'aws4_request'];let f=Promise.resolve(`AWS4${a}`);var g=!0,h=!1,i=void 0;try{for(var k,j=e[Symbol.iterator]();!(g=(k=j.next()).done);g=!0){const l=k.value;f=f.then((m)=>(0,_deps.hmac)(m,l))}}catch(l){h=!0,i=l}finally{try{!g&&j.return&&j.return()}finally{if(h)throw i}}return f}function preCalculatedSign(a,b){return(0,_deps.hmac)(a,b,'hex')}function sign(a,b,c,d,e){return preCalculateSigningKey(a,b,c,d).then((f)=>preCalculatedSign(f,e))}function buildAuthorization(a,b,c,d){return algorithm+' '+[['Credential',`${a}/${b}`],['SignedHeaders',c],['Signature',d]].map((e)=>e.join('=')).join(', ')} | ||
Object.defineProperty(exports,'__esModule',{value:true});exports.sign=exports.preCalculateSigningKey=exports.buildCanonicalRequest=exports.hash=undefined;let buildCanonicalRequest=exports.buildCanonicalRequest=(()=>{var _ref=_asyncToGenerator(function*(httpRequestMethod,canonicalURI,canonicalQueryString,canonicalHeaders,signedHeaders,requestPayload=''){return[httpRequestMethod,canonicalURI,canonicalQueryString,canonicalHeaders,'',signedHeaders,yield requestPayload?(0,_deps.hash)(requestPayload):emptyHash].join('\n')});return function buildCanonicalRequest(_x,_x2,_x3,_x4,_x5){return _ref.apply(this,arguments)}})();let preCalculateSigningKey=exports.preCalculateSigningKey=(()=>{var _ref2=_asyncToGenerator(function*(secretAccessKey,date,region,service){return[date,region,service,'aws4_request'].reduce((()=>{var _ref3=_asyncToGenerator(function*(acc,val){return(0,_deps.hmac)((yield acc),val)});return function(_x10,_x11){return _ref3.apply(this,arguments)}})(),`AWS4${secretAccessKey}`)});return function preCalculateSigningKey(_x6,_x7,_x8,_x9){return _ref2.apply(this,arguments)}})();let sign=exports.sign=(()=>{var _ref4=_asyncToGenerator(function*(secretAccessKey,date,region,service,stringToSign){const signingKey=yield preCalculateSigningKey(secretAccessKey,date,region,service);return preCalculatedSign(signingKey,stringToSign)});return function sign(_x12,_x13,_x14,_x15,_x16){return _ref4.apply(this,arguments)}})();exports.formatDateTime=formatDateTime;exports.buildStringToSign=buildStringToSign;exports.preCalculatedSign=preCalculatedSign;exports.buildAuthorization=buildAuthorization;var _deps=__webpack_require__(1);function _asyncToGenerator(fn){return function(){var gen=fn.apply(this,arguments);return new Promise(function(resolve,reject){function step(key,arg){try{var info=gen[key](arg);var value=info.value}catch(error){reject(error);return}if(info.done){resolve(value)}else{return Promise.resolve(value).then(function(value){step('next',value)},function(err){step('throw',err)})}}return step('next')})}}exports.hash=_deps.hash;const algorithm='AWS4-HMAC-SHA256';const emptyHash='e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855';function formatDateTime(date){return date.toISOString().replace(/-|:|(\.\d+)/g,'')}function buildStringToSign(requestDate,credentialScope,hashedCanonicalRequest){return[algorithm,requestDate,credentialScope,hashedCanonicalRequest].join('\n')}function preCalculatedSign(signingKey,stringToSign){return(0,_deps.hmac)(signingKey,stringToSign,'hex')}function buildAuthorization(accessKeyId,credentialScope,signedHeaders,signature){return algorithm+' '+[['Credential',`${accessKeyId}/${credentialScope}`],['SignedHeaders',signedHeaders],['Signature',signature]].map(item=>item.join('=')).join(', ')} | ||
@@ -93,3 +93,3 @@ /***/ }), | ||
"use strict"; | ||
Object.defineProperty(exports,'__esModule',{value:!0}),exports.hmac=hmac,exports.hash=hash;const crypto=window.crypto||window.msCrypto,subtle=crypto.subtle||crypto.webkitSubtle,algorithm='sha-256',normalize=exports.normalize=encodeURI;function toHex(a){const b=new Uint8Array(a);let c='';for(let d=0;d<b.length;++d){const e=b[d].toString(16);c+=`${2>e.length?'0':''}${e}`}return c}const toBinary='TextEncoder'in window?(a)=>new TextEncoder().encode(a):(a)=>{const b=a.length,c=new ArrayBuffer(2*b),d=new Uint16Array(c);for(let e=0;e<b;e++)d[e]=a.charCodeAt(e);return c},hashOptions={name:algorithm},algorithmSign={name:'HMAC',hash:hashOptions};function hmac(a,b,c='binary'){return subtle.importKey('raw','string'==typeof a?toBinary(a):a,algorithmSign,!1,['sign']).then((d)=>subtle.sign(algorithmSign,d,toBinary(b))).then((d)=>'binary'===c?d:toHex(d))}function hash(a){return subtle.digest(hashOptions,toBinary(a)).then(toHex)} | ||
Object.defineProperty(exports,'__esModule',{value:true});let hmac=exports.hmac=(()=>{var _ref=_asyncToGenerator(function*(key,data,encoding){const importedKey=yield subtle.importKey('raw',typeof key==='string'?toBinary(key):key,algorithmSign,false,['sign']);const buffer=yield subtle.sign(algorithmSign,importedKey,toBinary(data));return encoding==='hex'?toHex(buffer):buffer});return function hmac(_x,_x2,_x3){return _ref.apply(this,arguments)}})();let hash=exports.hash=(()=>{var _ref2=_asyncToGenerator(function*(data){return toHex((yield subtle.digest(hashOptions,toBinary(data))))});return function hash(_x4){return _ref2.apply(this,arguments)}})();function _asyncToGenerator(fn){return function(){var gen=fn.apply(this,arguments);return new Promise(function(resolve,reject){function step(key,arg){try{var info=gen[key](arg);var value=info.value}catch(error){reject(error);return}if(info.done){resolve(value)}else{return Promise.resolve(value).then(function(value){step('next',value)},function(err){step('throw',err)})}}return step('next')})}}const crypto=window.crypto||window.msCrypto;const subtle=crypto.subtle||crypto.webkitSubtle;const algorithm='sha-256';const normalize=exports.normalize=encodeURI;function toHex(buffer){const bytes=new Uint8Array(buffer);let str='';for(let i=0;i<bytes.length;++i){const byte=bytes[i].toString(16);str+=`${byte.length<2?'0':''}${byte}`}return str}const toBinary='TextEncoder'in window?str=>new TextEncoder().encode(str):str=>{const len=str.length;const buf=new ArrayBuffer(len*2);const bufView=new Uint16Array(buf);for(let i=0;i<len;i++)bufView[i]=str.charCodeAt(i);return buf};const hashOptions={name:algorithm};const algorithmSign={name:'HMAC',hash:hashOptions}; | ||
@@ -96,0 +96,0 @@ /***/ }), |
{ | ||
"name": "aws-sigv4", | ||
"version": "2.0.1", | ||
"version": "2.1.1", | ||
"description": "AWS Signature Version 4", | ||
@@ -16,3 +16,4 @@ "main": "lib/node/index.js", | ||
"coverage": "nyc report --reporter=text-lcov | coveralls", | ||
"build": "webpack" | ||
"build": "webpack", | ||
"docs": "esdoc" | ||
}, | ||
@@ -27,8 +28,7 @@ "keywords": [ | ||
"devDependencies": { | ||
"babel-cli": "^6.24.0", | ||
"babel-core": "^6.24.0", | ||
"babel-cli": "^6.24.1", | ||
"babel-core": "^6.24.1", | ||
"babel-loader": "^6.4.1", | ||
"babel-polyfill": "^6.23.0", | ||
"babel-preset-babili": "0.0.12", | ||
"babel-preset-env": "^1.3.2", | ||
"babel-preset-env": "^1.4.0", | ||
"chai": "^3.5.0", | ||
@@ -42,3 +42,3 @@ "coveralls": "^2.11.4", | ||
"unzip": "0.1.11", | ||
"webpack": "2.3.2" | ||
"webpack": "^2.4.1" | ||
}, | ||
@@ -45,0 +45,0 @@ "babel": { |
# aws-sigv4 | ||
> A dependency-free, test suite-compliant, AWS Signature Version 4 library in ES6 | ||
> A dependency-free, test suite-compliant, AWS Signature Version 4 library in ES2017 | ||
[](https://nodei.co/npm/aws-sigv4/) | ||
[](https://badge.fury.io/js/aws-sigv4) | ||
[](https://travis-ci.org/binoculars/aws-sigv4) | ||
[](http://binoculars.github.io/aws-sigv4/esdoc/) | ||
@@ -17,8 +16,12 @@ [](https://david-dm.org/binoculars/aws-sigv4) | ||
[](https://snyk.io/test/github/binoculars/aws-sigv4) | ||
[](https://greenkeeper.io/) | ||
## Example | ||
- Master: [](https://travis-ci.org/binoculars/aws-sigv4) | ||
- Develop: [](https://travis-ci.org/binoculars/aws-sigv4) | ||
## Example - ES2017 (Node 7.6+) | ||
```JavaScript | ||
const sigv4 = require('aws-sigv4'); | ||
sigv4.sign( | ||
const signature = await sigv4.sign( | ||
secretAccessKey, | ||
@@ -31,2 +34,18 @@ requestDate.slice(0, 8), | ||
console.log(signature); | ||
``` | ||
## Example - ES2016 (Node 4, 6, <= 7.5) | ||
```JavaScript | ||
const sigv4 = require('aws-sigv4'); | ||
sigv4.sign( | ||
secretAccessKey, | ||
requestDate.slice(0, 8), | ||
'us-east-1', | ||
'host', | ||
stringToSign | ||
) | ||
.then(signature => console.log(signature)); | ||
// Or, more specifically for S3: | ||
@@ -37,16 +56,16 @@ | ||
.slice(0, 8); | ||
const credential = `${process.env.AWS_ACCESS_KEY_ID}/${date}/${process.env.AWS_REGION}/s3/aws4_request` | ||
const credential = `${process.env.AWS_ACCESS_KEY_ID}/${date}/${process.env.AWS_REGION}/s3/aws4_request`; | ||
const policy = new Buffer( | ||
JSON.stringify({ | ||
expiration: new Date(Date.now() + 15 * 60000).toISOString(), // 15 minutes from now | ||
conditions: [ | ||
{bucket: 'my-bucket-name'}, | ||
{key: 'my-s3-key.mov'}, | ||
{acl: 'private'}, | ||
['starts-with', '$Content-Type', 'video/'], | ||
['content-length-range', 0, 10 * 1024 * 1024], | ||
{'x-amz-credential': credential}, | ||
{'x-amz-algorithm': 'AWS4-HMAC-SHA256'}, | ||
{'x-amz-date': date + 'T000000Z'} | ||
] | ||
expiration: new Date(Date.now() + 15 * 60000).toISOString(), // 15 minutes from now | ||
conditions: [ | ||
{bucket: 'my-bucket-name'}, | ||
{key: 'my-s3-key.mov'}, | ||
{acl: 'private'}, | ||
['starts-with', '$Content-Type', 'video/'], | ||
['content-length-range', 0, 10 * 1024 * 1024], | ||
{'x-amz-credential': credential}, | ||
{'x-amz-algorithm': 'AWS4-HMAC-SHA256'}, | ||
{'x-amz-date': date + 'T000000Z'} | ||
] | ||
}) | ||
@@ -62,5 +81,6 @@ ) | ||
policy | ||
); | ||
) | ||
.then(signature => console.log(sigature)); | ||
``` | ||
See [Authenticating Requests in Browser-Based Uploads Using POST (AWS Signature Version 4)](https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-UsingHTTPPOST.html) as the primary use case. |
import {hash, hmac, normalize} from 'deps'; | ||
/** @function | ||
* Computes the hash | ||
* | ||
* @name hash | ||
* @param {!string} data - The data to hash | ||
* @returns {Promise<string>} - The hashed output | ||
*/ | ||
export {hash}; | ||
@@ -32,14 +39,13 @@ | ||
*/ | ||
export function buildCanonicalRequest(httpRequestMethod, canonicalURI, canonicalQueryString, canonicalHeaders, signedHeaders, | ||
requestPayload='') { | ||
return (requestPayload ? hash(requestPayload) : Promise.resolve(emptyHash)) | ||
.then(hashedRequestPayload => [ | ||
httpRequestMethod, | ||
canonicalURI, | ||
canonicalQueryString, | ||
canonicalHeaders, | ||
'', | ||
signedHeaders, | ||
hashedRequestPayload | ||
].join('\n')); | ||
export async function buildCanonicalRequest(httpRequestMethod, canonicalURI, canonicalQueryString, canonicalHeaders, | ||
signedHeaders, requestPayload='') { | ||
return [ | ||
httpRequestMethod, | ||
canonicalURI, | ||
canonicalQueryString, | ||
canonicalHeaders, | ||
'', | ||
signedHeaders, | ||
await (requestPayload ? hash(requestPayload) : emptyHash) | ||
].join('\n'); | ||
} | ||
@@ -75,4 +81,4 @@ | ||
*/ | ||
export function preCalculateSigningKey(secretAccessKey, date, region, service) { | ||
const steps = [ | ||
export async function preCalculateSigningKey(secretAccessKey, date, region, service) { | ||
return [ | ||
date, | ||
@@ -82,10 +88,6 @@ region, | ||
'aws4_request' | ||
]; | ||
let promises = Promise.resolve(`AWS4${secretAccessKey}`); | ||
for (const data of steps) | ||
promises = promises.then(signingKey => hmac(signingKey, data)); | ||
return promises; | ||
].reduce( | ||
async (acc, val) => hmac(await acc, val), | ||
`AWS4${secretAccessKey}` | ||
); | ||
} | ||
@@ -116,5 +118,6 @@ | ||
*/ | ||
export function sign(secretAccessKey, date, region, service, stringToSign) { | ||
return preCalculateSigningKey(secretAccessKey, date, region, service) | ||
.then(signingKey => preCalculatedSign(signingKey, stringToSign)); | ||
export async function sign(secretAccessKey, date, region, service, stringToSign) { | ||
const signingKey = await preCalculateSigningKey(secretAccessKey, date, region, service); | ||
return preCalculatedSign(signingKey, stringToSign); | ||
} | ||
@@ -121,0 +124,0 @@ |
@@ -5,2 +5,7 @@ import {normalize} from 'path'; | ||
/** | ||
* Normalizes the path | ||
* | ||
* @return {string} | ||
*/ | ||
export {normalize} from 'path'; | ||
@@ -16,8 +21,6 @@ | ||
*/ | ||
export function hmac(key, data, encoding) { | ||
return Promise.resolve( | ||
createHmac(algorithm, key) | ||
.update(data) | ||
.digest(encoding) | ||
); | ||
export async function hmac(key, data, encoding) { | ||
return createHmac(algorithm, key) | ||
.update(data) | ||
.digest(encoding); | ||
} | ||
@@ -31,8 +34,6 @@ | ||
*/ | ||
export function hash(data) { | ||
return Promise.resolve( | ||
createHash(algorithm) | ||
.update(data) | ||
.digest('hex') | ||
); | ||
export async function hash(data) { | ||
return createHash(algorithm) | ||
.update(data) | ||
.digest('hex'); | ||
} |
@@ -5,4 +5,15 @@ const crypto = window.crypto || window.msCrypto; | ||
/** | ||
* Normalizes the path | ||
* | ||
* @returns {string} | ||
*/ | ||
export const normalize = encodeURI; | ||
/** | ||
* Transforms an ArrayBuffer into a hexadecimal string | ||
* | ||
* @param buffer - An ArrayBuffer | ||
* @returns {string} | ||
*/ | ||
function toHex(buffer) { | ||
@@ -21,2 +32,7 @@ const bytes = new Uint8Array(buffer); | ||
/** | ||
* Transforms a hexadecimal string into an ArrayBuffer | ||
* | ||
* @returns {ArrayBuffer} | ||
*/ | ||
const toBinary = ('TextEncoder' in window) ? | ||
@@ -49,24 +65,21 @@ (str => (new TextEncoder()).encode(str)) : | ||
* @param {!string} data - The data to hash | ||
* @param {?string} [encoding=binary] - The encoding type (hex|binary) | ||
* @param {?string} encoding - The encoding type (hex) | ||
* @returns {string|ArrayBuffer} - The output HMAC | ||
*/ | ||
export function hmac(key, data, encoding='binary') { | ||
return subtle | ||
.importKey( | ||
'raw', | ||
typeof key === 'string' ? toBinary(key) : key, | ||
algorithmSign, | ||
false, | ||
['sign'] | ||
) | ||
.then(importedKey => subtle | ||
.sign( | ||
algorithmSign, | ||
importedKey, | ||
toBinary(data) | ||
) | ||
) | ||
.then(buffer => | ||
encoding === 'binary' ? buffer : toHex(buffer) | ||
); | ||
export async function hmac(key, data, encoding) { | ||
const importedKey = await subtle.importKey( | ||
'raw', | ||
typeof key === 'string' ? toBinary(key) : key, | ||
algorithmSign, | ||
false, | ||
['sign'] | ||
); | ||
const buffer = await subtle.sign( | ||
algorithmSign, | ||
importedKey, | ||
toBinary(data) | ||
); | ||
return encoding === 'hex' ? toHex(buffer) : buffer; | ||
} | ||
@@ -80,9 +93,9 @@ | ||
*/ | ||
export function hash(data) { | ||
return subtle | ||
.digest( | ||
export async function hash(data) { | ||
return toHex( | ||
await subtle.digest( | ||
hashOptions, | ||
toBinary(data) | ||
) | ||
.then(toHex); | ||
); | ||
} |
@@ -33,10 +33,8 @@ 'use strict'; | ||
describe('Task 1: Create a Canonical Request', () => { | ||
it('should match the hashed payload', () => sigv4.hash(requestPayload) | ||
.then(result => assert | ||
.strictEqual( | ||
result, | ||
'b6359072c78d70ebee1e81adcbab4f01bf2c23245fa365ef83fe8f1f955085e2' | ||
) | ||
) | ||
); | ||
it('should match the hashed payload', async () => { | ||
assert.strictEqual( | ||
await sigv4.hash(requestPayload), | ||
'b6359072c78d70ebee1e81adcbab4f01bf2c23245fa365ef83fe8f1f955085e2' | ||
); | ||
}); | ||
@@ -46,29 +44,24 @@ const canonicalForm = 'POST\n/\n\ncontent-type:application/x-www-form-urlencoded; charset=utf-8\nhost:iam.a' + | ||
'bab4f01bf2c23245fa365ef83fe8f1f955085e2'; | ||
const args = [ | ||
'POST', | ||
'/', | ||
'', | ||
'content-type:application/x-www-form-urlencoded; charset=utf-8\nhost:iam.amazonaws.com\nx-amz' + | ||
'-date:20110909T233600Z', | ||
signedHeaders, | ||
requestPayload | ||
]; | ||
it('should match the sample canonical form', () => sigv4.buildCanonicalRequest(...args) | ||
.then(result => assert | ||
.strictEqual( | ||
result, | ||
canonicalForm | ||
) | ||
) | ||
); | ||
it('should match the sample canonical form', async () => { | ||
assert.strictEqual( | ||
await sigv4.buildCanonicalRequest( | ||
'POST', | ||
'/', | ||
'', | ||
'content-type:application/x-www-form-urlencoded; charset=utf-8\nhost:iam.amazonaws.com\nx-amz' + | ||
'-date:20110909T233600Z', | ||
signedHeaders, | ||
requestPayload | ||
), | ||
canonicalForm | ||
); | ||
}); | ||
it('should match the sample hashed canonical request', () => sigv4.hash(canonicalForm) | ||
.then(result => assert | ||
.strictEqual( | ||
result, | ||
hashedCanonicalRequest | ||
) | ||
) | ||
); | ||
it('should match the sample hashed canonical request', async () => { | ||
assert.strictEqual( | ||
await sigv4.hash(canonicalForm), | ||
hashedCanonicalRequest | ||
); | ||
}); | ||
}); | ||
@@ -102,18 +95,14 @@ | ||
describe('Task 3: Calculate the Signature', () => { | ||
const args = [ | ||
'wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY', | ||
'20110909', | ||
'us-east-1', | ||
'iam', | ||
stringToSign | ||
]; | ||
it('should match the hex signature', () => sigv4.sign(...args) | ||
.then(result => assert | ||
.strictEqual( | ||
result, | ||
signature | ||
) | ||
) | ||
); | ||
it('should match the hex signature', async () => { | ||
assert.strictEqual( | ||
await sigv4.sign( | ||
'wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY', | ||
'20110909', | ||
'us-east-1', | ||
'iam', | ||
stringToSign | ||
), | ||
signature | ||
); | ||
}); | ||
}); | ||
@@ -172,3 +161,3 @@ | ||
const testFiles = {}; | ||
const files = fs.readdirSync(directory) | ||
const files = fs.readdirSync(directory); | ||
@@ -200,3 +189,2 @@ for (const file of files) { | ||
{ | ||
const algorithm = 'AWS4-HMAC-SHA256'; | ||
const accessKeyId = 'AKIDEXAMPLE'; | ||
@@ -233,48 +221,42 @@ const requestDate = sigv4.formatDateTime(new Date('Sun, 30 Aug 2015 12:36:00 GMT')); | ||
describe('Task 1: Create a Canonical Request for Signature Version 4', () => { | ||
it('should match the canonical request', () => parsing.requestToCanonicalRequest(request) | ||
.then(result => assert | ||
.strictEqual( | ||
result, | ||
canonicalRequest | ||
) | ||
) | ||
); | ||
it('should match the canonical request', async () => { | ||
assert.strictEqual( | ||
await parsing.requestToCanonicalRequest(request), | ||
canonicalRequest | ||
); | ||
}); | ||
}); | ||
describe('Task 2: Create a String to Sign for Signature Version 4', () => { | ||
it('should match the string to sign', () => sigv4.hash(canonicalRequest) | ||
.then(hashedCanonicalRequest => assert | ||
.strictEqual( | ||
sigv4.buildStringToSign( | ||
requestDate, | ||
credentialScope, | ||
hashedCanonicalRequest | ||
), | ||
stringToSign | ||
) | ||
) | ||
); | ||
it('should match the string to sign', async () => { | ||
assert.strictEqual( | ||
sigv4.buildStringToSign( | ||
requestDate, | ||
credentialScope, | ||
await sigv4.hash(canonicalRequest) | ||
), | ||
stringToSign | ||
); | ||
}); | ||
}); | ||
describe('Task 3: Calculate the AWS Signature Version 4', () => { | ||
it('should match the authorization header value', () => { | ||
it('should match the authorization header value', async () => { | ||
const signedHeaders = canonicalRequest.split('\n').slice(-2, -1)[0]; | ||
return sigv4.sign( | ||
secretAccessKey, | ||
requestDate.slice(0, 8), | ||
'us-east-1', | ||
'service', | ||
stringToSign | ||
) | ||
.then(signature => assert.strictEqual( | ||
sigv4.buildAuthorization( | ||
accessKeyId, | ||
credentialScope, | ||
signedHeaders, | ||
signature | ||
), | ||
authorizationHeader | ||
) | ||
) | ||
assert.strictEqual( | ||
sigv4.buildAuthorization( | ||
accessKeyId, | ||
credentialScope, | ||
signedHeaders, | ||
await sigv4.sign( | ||
secretAccessKey, | ||
requestDate.slice(0, 8), | ||
'us-east-1', | ||
'service', | ||
stringToSign | ||
) | ||
), | ||
authorizationHeader | ||
); | ||
}); | ||
@@ -285,14 +267,8 @@ }); | ||
it('should match the signed request value', () => { | ||
const args = [ | ||
request, | ||
authorizationHeader | ||
]; | ||
// Special case | ||
if (group.name === 'post-sts-header-after') { | ||
args.push(securityToken) | ||
} | ||
assert.strictEqual( | ||
parsing.addAuthorization(...args), | ||
parsing.addAuthorization( | ||
request, | ||
authorizationHeader, | ||
group.name === 'post-sts-header-after' ? securityToken : undefined | ||
), | ||
signedRequest | ||
@@ -299,0 +275,0 @@ ); |
@@ -29,10 +29,9 @@ const webpack = require('webpack'); | ||
[ | ||
"env", | ||
'env', | ||
{ | ||
"targets": { | ||
"node": "current" | ||
targets: { | ||
node: 6 | ||
} | ||
} | ||
], | ||
'babili' | ||
] | ||
], | ||
@@ -39,0 +38,0 @@ compact: true, |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
14
1091
83
228448