4
* Copyright(c) 2010 LearnBoost <dev@learnboost.com>
12
var crypto = require('crypto')
13
, parse = require('url').parse
38
* Return an "Authorization" header value with the given `options`
39
* in the form of "AWS <key>:<signature>"
41
* @param {Object} options
46
function authorization (options) {
47
return 'AWS ' + options.key + ':' + sign(options)
50
module.exports = authorization
51
module.exports.authorization = authorization
54
* Simple HMAC-SHA1 Wrapper
56
* @param {Object} options
61
function hmacSha1 (options) {
62
return crypto.createHmac('sha1', options.secret).update(options.message).digest('base64')
65
module.exports.hmacSha1 = hmacSha1
68
* Create a base64 sha1 HMAC for `options`.
70
* @param {Object} options
75
function sign (options) {
76
options.message = stringToSign(options)
77
return hmacSha1(options)
79
module.exports.sign = sign
82
* Create a base64 sha1 HMAC for `options`.
84
* Specifically to be used with S3 presigned URLs
86
* @param {Object} options
91
function signQuery (options) {
92
options.message = queryStringToSign(options)
93
return hmacSha1(options)
95
module.exports.signQuery= signQuery
98
* Return a string for sign() with the given `options`.
109
* @param {Object} options
114
function stringToSign (options) {
115
var headers = options.amazonHeaders || ''
116
if (headers) headers += '\n'
120
, options.contentType
121
, options.date.toUTCString()
122
, headers + options.resource
126
module.exports.queryStringToSign = stringToSign
129
* Return a string for sign() with the given `options`, but is meant exclusively
130
* for S3 presigned URLs
137
* @param {Object} options
142
function queryStringToSign (options){
143
return 'GET\n\n\n' + options.date + '\n' + options.resource
145
module.exports.queryStringToSign = queryStringToSign
148
* Perform the following:
150
* - ignore non-amazon headers
152
* - sort lexicographically
153
* - trim whitespace between ":"
154
* - join with newline
156
* @param {Object} headers
161
function canonicalizeHeaders (headers) {
163
, fields = Object.keys(headers)
165
for (var i = 0, len = fields.length; i < len; ++i) {
166
var field = fields[i]
167
, val = headers[field]
168
, field = field.toLowerCase()
170
if (0 !== field.indexOf('x-amz')) continue
171
buf.push(field + ':' + val)
173
return buf.sort().join('\n')
175
module.exports.canonicalizeHeaders = canonicalizeHeaders
178
* Perform the following:
180
* - ignore non sub-resources
181
* - sort lexicographically
183
* @param {String} resource
188
function canonicalizeResource (resource) {
189
var url = parse(resource, true)
190
, path = url.pathname
194
Object.keys(url.query).forEach(function(key){
195
if (!~keys.indexOf(key)) return
196
var val = '' == url.query[key] ? '' : '=' + encodeURIComponent(url.query[key])
200
return path + (buf.length ? '?' + buf.sort().join('&') : '')
202
module.exports.canonicalizeResource = canonicalizeResource