Compare commits

...

4 commits

Author SHA1 Message Date
Todd Treece
e1f26c365a adds static getters for Client.Stream & Client.Signature 2015-09-25 12:52:52 -04:00
Todd Treece
89074c9848 finished client signature class 2015-09-25 12:50:38 -04:00
Todd Treece
187e7c5fe4 use eslint instead of jshint 2015-09-25 12:50:02 -04:00
Todd Treece
ec6eb8a631 adds signature module 2015-09-24 18:36:49 -04:00
4 changed files with 119 additions and 20 deletions

View file

@ -1,7 +1,8 @@
'use strict';
const Swagger = require('swagger-client-promises'),
Stream = require('./lib/stream');
Stream = require('./lib/stream'),
Signature = require('./lib/signature');
class Client {
@ -61,6 +62,14 @@ class Client {
}
static get Signature() {
return Signature;
}
static get Stream() {
return Stream;
}
}
exports = module.exports = Client;

99
client/lib/signature.js Normal file
View file

@ -0,0 +1,99 @@
'use strict';
const crypto = require('crypto'),
url = require('url');
class Signature {
constructor(options) {
this.username = false;
this.key = false;
this.host = false;
this.method = 'GET';
this.params = false;
this.path = false;
this.parsed = false;
Object.assign(this, options || {});
if(! this.username)
throw new Error('Username is required');
if(! this.key)
throw new Error('AIO Key is required');
if(! this.path)
throw new Error('path is required');
}
toString() {
const step1 = this.hmac(this.key, this.date()),
step2 = this.hmac(step1, this.host),
step3 = this.hmac(step2, this.method),
step4 = this.hmac(step3, this.params);
const signing_key = this.hmac(step4, this.version),
canonical_request = this.hash(this.request),
to_sign = `${this.algorithm}\n${this.date}\n${canonical_request}`;
return this.hmac(signing_key, to_sign);
}
get request() {
return `${this.method}\n${this.path}?${this.params}
host: ${this.host}
x-aio-date: ${this.date}`;
}
get version() {
return 'aio-signature-v1';
}
get credential() {
return `${this.username}/${this.version}`;
}
get date() {
return (new Date()).toISOString();
}
get algorithm() {
return 'sha512';
}
get algorithmName() {
return `aio-hmac-${this.algorithm()}`;
}
get path() {
return this.path;
}
set path(path) {
this.parsed = url.parse(path, true);
this.params = Object.keys(this.parsed.query).sort().map(q => q.toLowerCase()).join('&');
this.host = this.parsed.host;
this.path = this.parsed.href.split('?')[0];
}
hash(data) {
const hash = crypto.createHash(this.algorithm());
return hmac.update(data).digest('hex');
}
hmac(key, data) {
const hmac = crypto.createHmac(this.algorithm(), key);
return hmac.update(data).digest('hex');
}
}
exports = module.exports = Signature;

View file

@ -1,24 +1,16 @@
'use strict';
const gulp = require('gulp'),
jshint = require('gulp-jshint');
eslint = require('gulp-eslint');
gulp.task('lint', function() {
const lint = jshint({
"esnext": true,
"curly": false,
"eqeqeq": true,
"immed": true,
"newcap": false,
"noarg": true,
"sub": true,
"unused": "var",
"boss": true,
"eqnull": true,
"node": true,
"-W086": true
});
const config = {
ecmaFeatures: {
templateStrings: true
},
env: ['node', 'es6']
};
return gulp.src([
'index.js',
@ -28,7 +20,7 @@ gulp.task('lint', function() {
'server/lib/*.js',
'tunnel/index.js',
'tunnel/lib/*.js'
]).pipe(lint).pipe(jshint.reporter('jshint-stylish'));
]).pipe(eslint(config)).pipe(eslint.format()).pipe(eslint.failAfterError());
});

View file

@ -19,9 +19,8 @@
"homepage": "https://github.com/adafruit/adafruit-io-node#readme",
"devDependencies": {
"gulp": "^3.9.0",
"gulp-jshint": "^1.11.2",
"gulp-mocha": "^2.1.3",
"jshint-stylish": "^2.0.1"
"gulp-eslint": "^1.0.0",
"gulp-mocha": "^2.1.3"
},
"keywords": [
"adafruit",