Permalink
Browse files

Use spawn instead of exec. Bumped version to 0.2.0

  • Loading branch information...
1 parent d0d7f4d commit b2897ee69e367b07bc8a56981262e13d9579d8b8 Andris Reinman committed with Sep 11, 2014
Showing with 136 additions and 70 deletions.
  1. +20 −0 .jshintrc
  2. +1 −1 LICENSE
  3. +5 −5 README.md
  4. +0 −1 index.js
  5. +2 −2 package.json
  6. +98 −53 pass.js
  7. +10 −8 test.js
View
@@ -0,0 +1,20 @@
+{
+ "indent": 4,
+ "node": true,
+ "globalstrict": true,
+ "evil": true,
+ "unused": true,
+ "undef": true,
+ "newcap": true,
+ "esnext": true,
+ "curly": true,
+ "eqeqeq": true,
+ "expr": true,
+
+ "predef": [
+ "describe",
+ "it",
+ "beforeEach",
+ "afterEach"
+ ]
+}
View
@@ -1,4 +1,4 @@
-Copyright (c) 2011 Andris Reinman
+Copyright (c) 2011-2014 Andris Reinman
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
View
@@ -25,25 +25,25 @@ Simple use-case - generate a hash from a password and validate it.
var pass = require("pass");
var password = "myPassword";
-
+
// generate a password hash
pass.generate(password, function(error, hash){
if(error){
console.log("Error occured: "+error.message);
return;
}
-
-
+
+
// validate a password
pass.validate(password, hash, function(error, success){
if(error){
console.log("Error occured: "+error.message);
return;
}
-
+
console.log(success?"Passwords matched!":"No match!");
});
-
+
});
See [test.js](https://github.com/andris9/pass/blob/master/test.js) for a better example
View
@@ -1 +0,0 @@
-module.exports = require('./pass');
View
@@ -1,7 +1,7 @@
{
"name" : "pass",
- "version": "0.1.3",
- "main" : "./index",
+ "version": "0.2.0",
+ "main" : "./pass",
"description": "Apache htpasswd password generator/validator",
"author" : "Andris Reinman",
"maintainers":[
View
@@ -1,5 +1,7 @@
-var crypto = require("crypto"),
- exec = require('child_process').exec;
+'use strict';
+
+var crypto = require('crypto');
+var spawn = require('child_process').spawn;
/**
* pass.generate(password, callback) -> undefined
@@ -9,33 +11,52 @@ var crypto = require("crypto"),
*
* Generates an Apache htpasswd password
**/
-exports.generate = function(password, callback, param){
- if (!param) param = {};
+exports.generate = function(password, callback, param) {
+ param = param || {};
+
var c;
var algorithm = param.algorithm ? param.algorithm : 'sha1';
var digest = param.digest ? param.digest : 'base64';
+ var cmd, stdout = [],
+ stderr = [];
- var hash_prefix = {sha1: '{SHA}', md5: '$apr1$', crypt: ''};
+ var hash_prefix = {
+ sha1: '{SHA}',
+ md5: '$apr1$',
+ crypt: ''
+ };
- if (algorithm == 'crypt') {
+ if (algorithm === 'crypt') {
- exec('openssl passwd -crypt "' + password.replace(/"/,"\\\"") + '"', function(error, stdout, stderr) {
- if (error) return callback && callback(E, null);
- return callback && callback(null, stdout.trim());
+ cmd = spawn('openssl', ['passwd', '-crypt', password]);
+
+ cmd.stdout.on('data', function(data) {
+ stdout.push(data);
+ });
+
+ cmd.stderr.on('data', function(data) {
+ stderr.push(data);
+ });
+
+ cmd.on('close', function(code) {
+ if (code) {
+ return callback(new Error('Exit code ' + code));
+ }
+ callback(Buffer.concat(stdout).toString().trim());
});
} else {
- try{
- var c = crypto.createHash(algorithm);
+ try {
+ c = crypto.createHash(algorithm);
c.update(password);
c = c.digest(digest);
- }catch(E){
+ } catch (E) {
return callback && callback(E, null);
}
callback && callback(null, hash_prefix[algorithm] + c);
}
-}
+};
/**
* pass.validate(password, hash, callback) -> undefined
@@ -45,40 +66,41 @@ exports.generate = function(password, callback, param){
*
* Checks if an Apache htpasswd password matches with its hash.
**/
-exports.validate = function(password, hash, callback){
+exports.validate = function(password, hash, callback) {
- callback = callback || function(){};
- password = password || "";
- hash = hash && hash.trim() || "";
+ callback = callback || function() {};
+ password = password || '';
+ hash = hash && hash.trim() || '';
- var salt = "", parts;
+ var salt = '',
+ parts;
//SHA - {SHA}VBPuJHI7uixaa6LQGWx4s+5GKNE= (myPassword)
- if(hash.substr(0,5)=="{SHA}"){
+ if (hash.substr(0, 5) === '{SHA}') {
hash = hash.substr(5);
return validate_sha(password, hash, callback);
}
//MD5 - $apr1$r31.....$HqJZimcKQFAMYayBlzkrA/ (myPassword)
- if(hash.substr(0,6)=="$apr1$" || hash.substr(0,3)=='$1$'){
- parts = hash.split("$");
+ if (hash.substr(0, 6) === '$apr1$' || hash.substr(0, 3) === '$1$') {
+ parts = hash.split('$');
parts.shift();
var type = parts.shift();
salt = parts.shift();
- hash = parts.join("$");
+ hash = parts.join('$');
return validate_md5(password, hash, salt, callback, type);
}
// CRYPT - rqXexS6ZhobKA (myPassword)
- if(hash.length==13){
- salt = hash.substr(0,2);
+ if (hash.length === 13) {
+ salt = hash.substr(0, 2);
hash = hash.substr(2);
return validate_crypt(password, hash, salt, callback);
}
// PLAIN
- return callback(null, password==hash);
-}
+ return callback(null, password === hash);
+};
/**
@@ -90,43 +112,55 @@ exports.validate = function(password, hash, callback){
*
* Validates a SHA1 password
**/
-function validate_sha(password, hash, callback, param){
- if (!param) param = {};
+function validate_sha(password, hash, callback, param) {
+ param = param || {};
+
var c;
var algorithm = param.algorithm ? param.algorithm : 'sha1';
var digest = param.digest ? param.digest : 'base64';
- try{
+ try {
c = crypto.createHash(algorithm);
c.update(password);
c = c.digest(digest);
- }catch(E){
+ } catch (E) {
return callback(E, null);
}
- callback(null, c==hash);
+ callback(null, c === hash);
}
/**
* validate_sha(password, hash, callback) -> undefined
* - password (String): password to be validated
* - hash (String): password hash to be checked against
* - callback (Function): callback
- * - which password algorithm, defaults to "MD5-based password algorithm, Apache variant"
+ * - which password algorithm, defaults to 'MD5-based password algorithm, Apache variant'
*
* Validates an APR1/MD5 password
**/
-function validate_md5(password, hash, salt, callback, type){
+function validate_md5(password, hash, salt, callback, type) {
type = type ? type : 'apr1';
- exec(
- 'openssl passwd -'+type+' -salt '+salt+' "'+password.replace(/"/,"\\\"")+'"',
- function (error, stdout, stderr) {
- if(error){
- return callback(error, null);
- }
- callback(null, stdout && stdout.trim()=='$'+type+'$'+salt+'$'+hash);
- }
- );
+ var cmd, stdout = [],
+ stderr = [];
+
+ cmd = spawn('openssl', ['passwd', '-' + type, '-salt', salt, password]);
+
+ cmd.stdout.on('data', function(data) {
+ stdout.push(data);
+ });
+
+ cmd.stderr.on('data', function(data) {
+ stderr.push(data);
+ });
+
+ cmd.on('close', function(code) {
+ if (code) {
+ return callback(new Error('Exit code ' + code));
+ }
+
+ callback(null, Buffer.concat(stdout).toString().trim() === '$' + type + '$' + salt + '$' + hash);
+ });
}
/**
@@ -137,14 +171,25 @@ function validate_md5(password, hash, salt, callback, type){
*
* Validates a Linux crypt(3) password
**/
-function validate_crypt(password, hash, salt, callback){
- exec(
- 'openssl passwd -crypt -salt '+salt+' "'+password.replace(/"/,"\\\"")+'"',
- function (error, stdout, stderr) {
- if(error){
- return callback(error, null);
- }
- callback(null, stdout && stdout.trim()==salt+hash);
- }
- );
-}
+function validate_crypt(password, hash, salt, callback) {
+
+ var cmd, stdout = [],
+ stderr = [];
+
+ cmd = spawn('openssl', ['passwd', '-crypt', '-salt', salt, password]);
+
+ cmd.stdout.on('data', function(data) {
+ stdout.push(data);
+ });
+
+ cmd.stderr.on('data', function(data) {
+ stderr.push(data);
+ });
+
+ cmd.on('close', function(code) {
+ if (code) {
+ return callback(new Error('Exit code ' + code));
+ }
+ callback(null, Buffer.concat(stdout).toString().trim() === salt + hash);
+ });
+}
View
@@ -1,16 +1,18 @@
+'use strict';
+
var pass = require("./pass");
// generate a password
-pass.generate("myPassword", function(error, hash){
- if(error){
- return console.log("Error: "+error.message);
+pass.generate("myPassword", function(error, hash) {
+ if (error) {
+ return console.log("Error: " + error.message);
}
- console.log("Password generation: "+ (hash == "{SHA}VBPuJHI7uixaa6LQGWx4s+5GKNE="?"OK":"Failed"));
-})
+ console.log("Password generation: " + (hash === "{SHA}VBPuJHI7uixaa6LQGWx4s+5GKNE=" ? "OK" : "Failed"));
+});
// check predefined passwords
-function response(type, expected, error, success){
- console.log(type+": "+(success==expected?"OK":"Failed"));
+function response(type, expected, error, success) {
+ console.log(type + ": " + (success === expected ? "OK" : "Failed"));
}
pass.validate("myPassword", "{SHA}VBPuJHI7uixaa6LQGWx4s+5GKNE=", response.bind(this, "SHA1 True ", true));
@@ -23,4 +25,4 @@ pass.validate("myPassword", "$1$saltsalt$2vnaRpHa6Jxjz5n83ok8Z0", response.bind(
pass.validate("myPass", "$1$saltsalt$2vnaRpHa6Jxjz5n83ok8Z0", response.bind(this, "MD5_1 False ", false));
pass.validate("myPassword", "rqXexS6ZhobKA", response.bind(this, "CRYPT True ", true));
-pass.validate("myPass", "rqXexS6ZhobKA", response.bind(this, "CRYPT False", false));
+pass.validate("myPass", "rqXexS6ZhobKA", response.bind(this, "CRYPT False", false));

0 comments on commit b2897ee

Please sign in to comment.