From 66a3dbb61d43c7b24e3cd36dfe8ddcdc78f14031 Mon Sep 17 00:00:00 2001 From: Braydon Fuller Date: Fri, 18 Sep 2015 09:49:41 -0400 Subject: [PATCH] Added gulp tasks for release process. - Includes commands to build and release browser builds - Commands to run node and browser tests with karma --- .gitignore | 4 + .jshintrc | 2 +- .travis.yml | 10 ++- README.md | 41 +++++----- bower.json | 29 +++++++ dist/.gitignore | 3 - gulpfile.js | 176 ++++++++++++++++++++++++++++++++++++++++++ index.js | 18 +++-- karma.conf.js | 18 +++++ lib/bitauth-common.js | 2 +- package.json | 14 +++- scripts/make-dist.sh | 5 -- test/index.html | 3 +- test/test.bitauth.js | 9 +-- 14 files changed, 284 insertions(+), 50 deletions(-) create mode 100644 bower.json delete mode 100644 dist/.gitignore create mode 100644 gulpfile.js create mode 100644 karma.conf.js delete mode 100644 scripts/make-dist.sh diff --git a/.gitignore b/.gitignore index a56a7ef..74bbd23 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,6 @@ node_modules +bitauth.js +bitauth.min.js +tests.js + diff --git a/.jshintrc b/.jshintrc index dd738f2..7267c01 100644 --- a/.jshintrc +++ b/.jshintrc @@ -30,7 +30,7 @@ "maxlen": 120, "multistr": true, - "predef": [ // Extra globals. + "predef": [ "after", "afterEach", "before", diff --git a/.travis.yml b/.travis.yml index df46744..379d258 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,12 @@ language: node_js +sudo: false node_js: -- '0.10' + - '0.10' + - '0.12' +before_install: + - export DISPLAY=:99.0 + - sh -e /etc/init.d/xvfb start +install: + - npm install + diff --git a/README.md b/README.md index 6f68caf..dbe12ce 100644 --- a/README.md +++ b/README.md @@ -21,10 +21,9 @@ npm install bitauth To generate a browser bundle, you can then run: ```bash -npm run make-dist +gulp browser ``` - ## Advantages over other authentication mechanisms * By signing each request, man in the middle attacks are impossible. @@ -38,18 +37,18 @@ in HMAC. ## Technical Overview BitAuth uses the same technology in Bitcoin. A public private key pair is created -using elliptic curve secp256k1. The public SIN (System identification number), -like a bitcoin address, is the RIPEMD 160, SHA256 hash of the public key. +using elliptic curve secp256k1. The public SIN (System identification number), +like a bitcoin address, is the RIPEMD 160, SHA256 hash of the public key. See https://en.bitcoin.it/wiki/Identity_protocol_v1 for complete details. In each request, the client includes a nonce to prevent replay attacks. The client -signs the full url with the request body concatenated if there is one. The signature -is included in the `x-signature` header and the public key is included in the +signs the full url with the request body concatenated if there is one. The signature +is included in the `x-signature` header and the public key is included in the `x-identity` header. The server verifies that the signature is valid and that it matches the identity (the public key). It then computes the SIN from the public key, and sees whether that SIN has access -to the requested resource. The nonce is checked to make sure it is higher than +to the requested resource. The nonce is checked to make sure it is higher than the previously used nonce. ## Technology is readily available @@ -62,7 +61,7 @@ to start using BitAuth. ## Problems with password authentication * Have to keep track of a separate password for every web service. People forget -passwords, encouraging them to reuse passwords and opening themselves up to +passwords, encouraging them to reuse passwords and opening themselves up to having multiple services compromised. * Brute force attacks on weak passwords. * Passwords may travel over plaintext @@ -76,16 +75,16 @@ not worry about one service gaining access to another. In the future, an identity system could be built around BitAuth keys where a user could create one key to represent an identity which could authenticate against -multiple services. +multiple services. -In order for this to work, there would have to be a browser -integration or plugin which would manage these identities and a Javascript API -where websites could sign requests going to their website with the private key, +In order for this to work, there would have to be a browser +integration or plugin which would manage these identities and a Javascript API +where websites could sign requests going to their website with the private key, but without exposing the private key to the third party sites. There also needs to be a public place to store SIN's, preferably in -a decentralized blockchain or datastore like namecoin. Key revocations could -be stored here as well as reviews/feedback to build a reputation around an +a decentralized blockchain or datastore like namecoin. Key revocations could +be stored here as well as reviews/feedback to build a reputation around an identity. ## Examples @@ -188,7 +187,7 @@ for(k in keys) { } if(body) { console.log(body); - } + } }); } @@ -206,21 +205,19 @@ app.use( bitauth.middleware ); To build a browser compatible version of BitAuth, run the following command from the project's root directory: ```bash -npm run make-dist +gulp browser ``` -This will output `bitauth.browser.min.js` to the `dist` directory. The script introduces a global variable at `window.bitauth`. +This will output `bitauth.min.js` to project directory. The script can be loaded using `require('bitauth')`. - -To then run tests for a web browser open `test/index.html` in a browser, such as: +To then run tests for a web browser: ```bash -firefox test/index.html -chromium-browser test/index.html +gulp test:browser ``` To run tests for Node.js: ```bash -npm run test +gulp test:node ``` diff --git a/bower.json b/bower.json new file mode 100644 index 0000000..0c6714c --- /dev/null +++ b/bower.json @@ -0,0 +1,29 @@ +{ + "name": "bitauth", + "main": "./bitauth.min.js", + "version": "0.2.1", + "homepage": "https://github.com/bitpay/bitauth", + "authors": [ + "BitPay, Inc." + ], + "description": "Passwordless authentication using Bitcoin cryptography", + "moduleType": [ + "globals" + ], + "keywords": [ + "bitcoin", + "bitcore", + "btc", + "satoshi" + ], + "license": "MIT", + "ignore": [ + "**/.*", + "CONTRIBUTING.md", + "gulpfile.js", + "lib", + "index.js", + "karma.conf.js", + "test" + ] +} diff --git a/dist/.gitignore b/dist/.gitignore deleted file mode 100644 index 600a000..0000000 --- a/dist/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -# Ignore everything in this directory -* -!.gitignore \ No newline at end of file diff --git a/gulpfile.js b/gulpfile.js new file mode 100644 index 0000000..88e6a3b --- /dev/null +++ b/gulpfile.js @@ -0,0 +1,176 @@ +'use strict'; + +// Run these commands to make a release: +// +// gulp release:checkout-releases +// gulp release:install +// gulp test +// gulp release:bump: +// gulp browser +// gulp release:build-commit +// gulp release:push-tag +// npm publish +// gulp release:checkout-master +// gulp release:bump: +// gulp release:version-commit +// gulp release:push + +var path = require('path'); +var gulp = require('gulp'); +var shell = require('gulp-shell'); +var mocha = require('gulp-mocha'); +var runsequence = require('run-sequence'); +runsequence.use(gulp); +var bump = require('gulp-bump'); +var git = require('gulp-git'); + +var binPath = path.resolve(__dirname, './node_modules/.bin/'); +var browserifyPath = path.resolve(binPath, './browserify'); +var uglifyPath = path.resolve(binPath, './uglifyjs'); +var indexPath = path.resolve(__dirname, './lib/bitauth-browserify'); +var namePath = path.resolve(__dirname, './bitauth'); +var bundlePath = namePath + '.js'; +var minPath = namePath + '.min.js'; + +var browserifyCommand = browserifyPath + ' --require ' + indexPath + ':bitauth -o ' + bundlePath; +var uglifyCommand = uglifyPath + ' ' + bundlePath + ' --compress --mangle -o ' + minPath; + +gulp.task('browser:uncompressed', shell.task([ + browserifyCommand +])); + +gulp.task('browser:compressed', ['browser:uncompressed'], shell.task([ + uglifyCommand +])); + +gulp.task('browser:maketests', shell.task([ + 'find test/ -type f -name "*.js" | xargs ' + browserifyPath + ' -o tests.js' +])); + +gulp.task('browser', function(callback) { + runsequence(['browser:compressed'], callback); +}); + + +gulp.task('release:install', function() { + return shell.task([ + 'npm install', + ]); +}); + +var releaseFiles = ['./package.json', './bower.json']; + +var bumpVersion = function(importance) { + return gulp.src(releaseFiles) + .pipe(bump({ + type: importance + })) + .pipe(gulp.dest('./')); +}; + +['patch', 'minor', 'major'].forEach(function(importance) { + gulp.task('release:bump:' + importance, function() { + bumpVersion(importance); + }); +}); + +gulp.task('release:checkout-releases', function(cb) { + var tempBranch = 'releases/' + new Date().getTime() + '-build'; + git.branch(tempBranch, { + args: '' + }, function() { + git.checkout(tempBranch, { + args: '' + }, cb); + }); +}); + +gulp.task('release:checkout-master', function(cb) { + git.checkout('master', { + args: '' + }, cb); +}); + +gulp.task('release:sign-built-files', shell.task([ + 'gpg --yes --out ' + namePath + '.js.sig --detach-sig ' + namePath + '.js', + 'gpg --yes --out ' + namePath + '.min.js.sig --detach-sig ' + namePath + '.min.js' +])); + +var buildFiles = ['./package.json']; +var signatureFiles = []; +buildFiles.push(namePath + '.js'); +buildFiles.push(namePath + '.js.sig'); +buildFiles.push(namePath + '.min.js'); +buildFiles.push(namePath + '.min.js.sig'); +buildFiles.push('./bower.json'); +signatureFiles.push(namePath + '.js.sig'); +signatureFiles.push(namePath + '.min.js.sig'); + +var addFiles = function() { + return gulp.src(buildFiles) + .pipe(git.add({ + args: '-f' + })); +}; + +var buildCommit = function() { + var pjson = require('./package.json'); + return gulp.src(buildFiles) + .pipe(git.commit('Build: ' + pjson.version, { + args: '' + })); +}; + +gulp.task('release:add-signed-files', ['release:sign-built-files'], addFiles); +gulp.task('release:add-built-files', addFiles); +gulp.task('release:build-commit', [ + 'release:add-signed-files' +], buildCommit); + +gulp.task('release:version-commit', function() { + var pjson = require('./package.json'); + return gulp.src(releaseFiles) + .pipe(git.commit('Bump package version to ' + pjson.version, { + args: '' + })); +}); + +gulp.task('release:push', function(cb) { + git.push('upstream', 'master', { + args: '' + }, cb); +}); + +gulp.task('release:push-tag', function(cb) { + var pjson = require('./package.json'); + var name = 'v' + pjson.version; + git.tag(name, 'Release ' + name, function() { + git.push('upstream', name, cb); + }); +}); + +gulp.task('release:publish', shell.task([ + 'npm publish' +])); + +var tests = ['test/**/*.js']; +var testmocha = function() { + return gulp.src(tests).pipe(new mocha({ + recursive: true + })); +}; +var testkarma = shell.task([ + path.resolve(__dirname, './node_modules/karma/bin/karma') + + ' start ' + path.resolve(__dirname, './karma.conf.js') +]); + +gulp.task('test:node', testmocha); +gulp.task('test:browser', ['browser:uncompressed', 'browser:maketests'], testkarma); + +gulp.task('test', function(callback) { + runsequence(['test:node'], ['test:browser'], callback); +}); + +gulp.task('benchmark', shell.task([ + 'node benchmarks/index.js' +])); diff --git a/index.js b/index.js index c3bf4bb..a3eb239 100644 --- a/index.js +++ b/index.js @@ -1,9 +1,15 @@ -// get base functionality -var bitauth = require('./lib/bitauth-node'); +'use strict'; -// add node-specific encrypt/decrypt -bitauth.encrypt = require('./lib/encrypt'); -bitauth.decrypt = require('./lib/decrypt'); -bitauth.middleware = require('./lib/middleware/bitauth'); +var bitauth; +if (process.browser) { + bitauth = require('./lib/bitauth-browserify'); +} else { + bitauth = require('./lib/bitauth-node'); + + // add node-specific encrypt/decrypt + bitauth.encrypt = require('./lib/encrypt'); + bitauth.decrypt = require('./lib/decrypt'); + bitauth.middleware = require('./lib/middleware/bitauth'); +} module.exports = bitauth; diff --git a/karma.conf.js b/karma.conf.js new file mode 100644 index 0000000..9a6ca1a --- /dev/null +++ b/karma.conf.js @@ -0,0 +1,18 @@ +'use strict'; + +module.exports = function(config) { + + config.set({ + browsers: ['Firefox'], + frameworks: ['mocha'], + singleRun: true, + files: [ + './tests.js' + ], + plugins: [ + 'karma-mocha', + 'karma-firefox-launcher' + ] + }); + +}; diff --git a/lib/bitauth-common.js b/lib/bitauth-common.js index 828780e..f1d0de2 100644 --- a/lib/bitauth-common.js +++ b/lib/bitauth-common.js @@ -13,7 +13,7 @@ BitAuth.PREFIX = new Buffer('0f02', 'hex'); */ BitAuth.generateSin = function() { var pair = BitAuth._generateRandomPair(); - var sin = this.getSinFromPublicKey(pair[1]); + var sin = BitAuth.getSinFromPublicKey(pair[1]); var sinObj = { created: Math.round(Date.now() / 1000), priv: pair[0], diff --git a/package.json b/package.json index f33e5d9..15a8184 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ ], "scripts": { "make-dist": "sh scripts/make-dist.sh", - "test": "mocha test/*.js --reporter spec" + "test": "gulp test" }, "main": "index.js", "version": "0.2.1", @@ -38,7 +38,17 @@ "benchmark": "^1.0.0", "browserify": "=6.1.0", "chai": "=1.9.1", + "gulp": "^3.8.10", + "gulp-bump": "^0.1.11", + "gulp-mocha": "^2.0.0", + "gulp-git": "^0.5.5", + "gulp-shell": "^0.2.10", + "karma": "^0.13.9", + "karma-firefox-launcher": "^0.1.4", + "karma-mocha": "^0.1.9", + "run-sequence": "^1.0.2", "uglify-js": "~2.4.14", "mocha": "~1.20.1" - } + }, + "license": "MIT" } diff --git a/scripts/make-dist.sh b/scripts/make-dist.sh deleted file mode 100644 index ab3325f..0000000 --- a/scripts/make-dist.sh +++ /dev/null @@ -1,5 +0,0 @@ -echo "Building browser bundle for bitauth..." -node_modules/.bin/browserify lib/bitauth-browserify.js -s bitauth -o dist/bitauth.bundle.js -echo "Minifying bitauth..." -node_modules/.bin/uglifyjs dist/bitauth.bundle.js --compress --mangle -o dist/bitauth.browser.min.js -echo "Done!" diff --git a/test/index.html b/test/index.html index 9fae4cb..1690a3d 100644 --- a/test/index.html +++ b/test/index.html @@ -9,11 +9,10 @@ - - + diff --git a/test/test.bitauth.js b/test/test.bitauth.js index 365c641..9639417 100644 --- a/test/test.bitauth.js +++ b/test/test.bitauth.js @@ -1,12 +1,7 @@ 'use strict'; -if (typeof(window) === 'undefined') { - var bitauth = require('../index'); -} else { - var bitauth = window.bitauth; -} - -var chai = chai || require('chai'); +var bitauth = require('../'); +var chai = require('chai'); describe('bitauth', function() {