diff --git a/.gitignore b/.gitignore index 6203a47..b39926e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,16 +1,3 @@ -lib-cov -*.seed -*.log -*.csv -*.dat -*.out -*.pid -*.gz - -pids -logs -results - npm-debug.log node_modules build/ diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..2041bc4 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,27 @@ +os: + - linux + - osx +sudo: false +language: cpp +addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - g++-4.8 +env: + matrix: + - TRAVIS_NODE_VERSION="0.10" + - TRAVIS_NODE_VERSION="0.12" + - TRAVIS_NODE_VERSION="4" + - TRAVIS_NODE_VERSION="4.1" +install: + - rm -rf ~/.nvm && git clone https://github.com/creationix/nvm.git ~/.nvm && (cd ~/.nvm && git checkout `git describe --abbrev=0 --tags`) && source ~/.nvm/nvm.sh && nvm install $TRAVIS_NODE_VERSION + - npm install npm + - mv node_modules npm + - npm/.bin/npm --version + - if [[ $TRAVIS_OS_NAME == "linux" ]]; then export CXX=g++-4.8; fi + - $CXX --version + - npm/.bin/npm install +script: + - npm/.bin/npm test diff --git a/README.md b/README.md index ac4e1bd..cc6587a 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ node-crypt3 =========== +[![Build Status](https://travis-ci.org/rolandpoulter/node-crypt3.svg)](https://travis-ci.org/rolandpoulter/node-crypt3) + [crypt3link]: https://en.wikipedia.org/wiki/Crypt_(C) "crypt() in C" [crypt(3)][crypt3link] for Node.js @@ -40,9 +42,4 @@ console.log( crypt('6Xz7sS6fEmnWScMb6Ayf363e5cdqF4Kh', crypt.createSalt('sha512' Create hashes ------------- -Use `crypt.createSalt([type=sha512])` where type is one of `md5`, `blowfish`, `sha256` or `sha512` (default). - -Commercial Support ------------------- - -You can buy commercial support from [Sendanor](http://sendanor.com/software). +Use `crypt.createSalt([type=sha512])` where type is one of `md5`, `blowfish`, `sha256` or `sha512` (default). diff --git a/binding.gyp b/binding.gyp index 7349d80..5bb499c 100644 --- a/binding.gyp +++ b/binding.gyp @@ -2,7 +2,10 @@ "targets": [ { "target_name": "crypt3", - "sources": [ "crypt3.cc" ], + "sources": [ + "src/addon.cc", + "src/crypt3.cc" + ], "include_dirs" : [ " -#include -#include -#include // for crypt if _XOPEN_SOURCE exists -#include - -using namespace v8; - -NAN_METHOD(Method) { - NanScope(); - - if (args.Length() < 2) { - return NanThrowTypeError("Wrong number of arguments"); - } - - if (!args[0]->IsString() || !args[1]->IsString()) { - return NanThrowTypeError("Wrong arguments"); - } - - v8::String::Utf8Value key(args[0]->ToString()); - v8::String::Utf8Value salt(args[1]->ToString()); - - char* res = crypt(*key, *salt); - if (res != NULL) { - NanReturnValue(NanNew(res)); - } else { - return NanThrowError(node::ErrnoException(errno, "crypt")); - } -} - -void init(Handle exports) { - exports->Set(NanNew("crypt"), NanNew(Method)->GetFunction()); -} - -NODE_MODULE(crypt3, init) - -/* EOF */ diff --git a/index.js b/index.js index 441930b..53543ff 100644 --- a/index.js +++ b/index.js @@ -1,33 +1,46 @@ /** Node.js Crypt(3) Library */ -var salters = { - 'md5': function() { return '$1$'+require('crypto').randomBytes(10).toString('base64'); }, - 'blowfish': function() { return '$2a$'+require('crypto').randomBytes(10).toString('base64'); }, - 'sha256': function() { return '$5$'+require('crypto').randomBytes(10).toString('base64'); }, - 'sha512': function() { return '$6$'+require('crypto').randomBytes(10).toString('base64'); } +var crypto = require('crypto'), + nativeCrypt3 = require('./build/Release/crypt3'); + +var signitures = { + md5: '$1$', + sha256: '$5$', + sha512: '$6$' }; function createSalt(type) { - type = type || 'sha512'; - if(!salters[type]) throw new TypeError('Unknown salt type at crypt3.createSalt: ' + type); - return salters[type](); + type = type || 'sha512'; + + if(!signitures[type]) { + throw new TypeError('Unknown salt type at crypt3.createSalt: ' + type); + } + + return signitures[type] + generateSalt(); }; +function generateSalt() { + return crypto.randomBytes(10).toString('base64'); +} + /** Crypt(3) password and data encryption. * @param {string} key user's typed password * @param {string} salt Optional salt, for example SHA-512 use "$6$salt$". * @returns {string} A generated hash in format $id$salt$encrypted * @see https://en.wikipedia.org/wiki/Crypt_(C) */ -var crypt3 = module.exports = function(key, salt) { - salt = salt || createSalt(); - return require('./build/Release/crypt3').crypt(key, salt); +var crypt3 = module.exports = function(key, salt, type) { + salt = salt || createSalt(type); + return nativeCrypt3.crypt3(key, salt); }; -/** Create salt +/** Create salt * @param {string} type The type of salt: md5, blowfish (only some linux distros), sha256 or sha512. Default is sha512. * @returns {string} Generated salt string */ crypt3.createSalt = createSalt; -/* EOF */ +/** Random salt fragment + * @returns {string} Random salt string + */ +crypt3.randomSaltFragment = generateSalt; diff --git a/package.json b/package.json index 3ed4c18..6a97dc0 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,9 @@ "blowfish", "hash" ], - "dependencies": { "nan": "1 >=1.6.2" }, + "dependencies": { + "nan": "2.0.9" + }, "author": "Jaakko-Heikki Heusala ", "license": "MIT", "gypfile": true diff --git a/src/addon.cc b/src/addon.cc new file mode 100644 index 0000000..07cc1cf --- /dev/null +++ b/src/addon.cc @@ -0,0 +1,17 @@ +#include +#include "crypt3.h" + +using v8::FunctionTemplate; +using v8::Handle; +using v8::Object; +using v8::String; +using Nan::GetFunction; +using Nan::New; +using Nan::Set; + +NAN_MODULE_INIT(InitAll) { + Nan::Set(target, Nan::New("crypt3").ToLocalChecked(), + Nan::GetFunction(Nan::New(crypt3)).ToLocalChecked()); +} + +NODE_MODULE(crypt3, InitAll) diff --git a/src/crypt3.cc b/src/crypt3.cc new file mode 100644 index 0000000..ef609ec --- /dev/null +++ b/src/crypt3.cc @@ -0,0 +1,33 @@ +/* Node.js Crypt(3) implementation */ +#include "crypt3.h" + +#include +#include // for crypt if _XOPEN_SOURCE exists + +using Nan::New; +using Nan::ThrowError; +using Nan::ThrowTypeError; +using Nan::NanErrnoException; + +NAN_METHOD(crypt3) { + if (info.Length() != 2) { + return Nan::ThrowTypeError("Wrong number of arguments"); + } + + if (!info[0]->IsString() || !info[1]->IsString()) { + return Nan::ThrowTypeError("Wrong arguments"); + } + + v8::String::Utf8Value key(info[0]->ToString()); + v8::String::Utf8Value salt(info[1]->ToString()); + + char* res = crypt(*key, *salt); + + if (res != NULL) { + info.GetReturnValue().Set(Nan::New(res).ToLocalChecked()); + } + + else { + return Nan::ThrowError(Nan::NanErrnoException(errno, "crypt")); + } +} diff --git a/src/crypt3.h b/src/crypt3.h new file mode 100644 index 0000000..e640a98 --- /dev/null +++ b/src/crypt3.h @@ -0,0 +1,8 @@ +#ifndef NE_CRYPT3_H +#define NE_CRYPT3_H + +#include + +NAN_METHOD(crypt3); + +#endif diff --git a/test/test.js b/test/test.js index e1720ac..a778e05 100644 --- a/test/test.js +++ b/test/test.js @@ -1,14 +1,28 @@ -var assert = require('assert') -var crypt3 = require('../') +'use strict'; -assert.throws(function() { - crypt3() -}, /Wrong arguments/) +var assert = require('assert'); -assert.equal(crypt3('pass', 'salt'), 'sa5JEXtYx/rm6') -assert.equal(crypt3('pass', 'sa5JEXtYx/rm6'), 'sa5JEXtYx/rm6') +var crypt3 = require('../index'); -var hash = crypt3('password') -assert.equal(crypt3('password', hash), hash) -assert.notEqual(crypt3('bad-pass', hash), hash) +try { + assert.throws(function() {crypt3()}, /Wrong arguments/); + + assert.equal(crypt3('pass', 'salt'), 'sa5JEXtYx/rm6'); + + assert.equal(crypt3('pass', 'sa5JEXtYx/rm6'), 'sa5JEXtYx/rm6'); + + + var hash = crypt3('password'); + + assert.equal(crypt3('password', hash), hash); + + assert.notEqual(crypt3('bad-pass', hash), hash); +} + +catch (err) { + console.error(err); + process.exit(1); +} + +process.exit(0);