node-aptoma-plugin-auth
Advanced tools
Comparing version 1.1.0 to 1.2.0
{ | ||
"name": "node-aptoma-plugin-auth", | ||
"version": "1.1.0", | ||
"version": "1.2.0", | ||
"description": "Node version of no.aptoma.plugin-api's example auth module.", | ||
"main": "auth.js", | ||
"scripts": { | ||
"test": "./node_modules/mocha/bin/mocha -R spec" | ||
}, | ||
"author": "Helge S. Holm <helge.holm@brik.no>", | ||
"license": "MIT", | ||
"dependencies": { | ||
}, | ||
"devDependencies": { | ||
"mocha": "^2.1.0", | ||
"mcrypt": "0.0.7" | ||
} | ||
} |
@@ -26,13 +26,2 @@ # node-aptoma-plugin-auth | ||
## Prerequisites | ||
The `mcrypt` library is used for encryption and decryption, and must | ||
be installed for this module to work. | ||
Example install command for Ubuntu: | ||
``` | ||
apt-get install libmcrypt4 libmcrypt-dev | ||
``` | ||
## Documentation | ||
@@ -39,0 +28,0 @@ |
@@ -8,3 +8,2 @@ /** | ||
var url = require('url'); | ||
var mcrypt = require('mcrypt'); | ||
@@ -16,5 +15,8 @@ /** | ||
* _appUrl - The scheme, host and port of the app. Port defaults to 80. | ||
* test - Intentionally undocumented test config object. | ||
*/ | ||
module.exports = function apptomaApp(name, _key, _appUrl) { | ||
module.exports = function apptomaApp(name, _key, _appUrl, test) { | ||
test = test || {}; | ||
var key = determineKey(); | ||
var keyBuf = cutKeyBuffer(key); | ||
@@ -28,2 +30,11 @@ function determineKey() { | ||
/** | ||
* Makes the a key a certain length | ||
*/ | ||
function cutKeyBuffer(key) { | ||
var keySha1 = crypto.createHash('sha1').update(key).digest('hex'); | ||
var keyHex = keySha1.slice(0, 32); | ||
return new Buffer(keyHex); | ||
} | ||
/** | ||
* Returns false on failure, and an object containing the following on | ||
@@ -53,6 +64,8 @@ * success: | ||
// Make sure we're not being replayed | ||
var timeNow = Math.floor(Date.now() / 1000); | ||
if (incoming.time == null || timeNow - incoming.time > 60) | ||
return false; | ||
if (!test.allowReplayAttacks) { | ||
// Make sure we're not being replayed | ||
var timeNow = Math.floor(Date.now() / 1000); | ||
if (incoming.time == null || timeNow - incoming.time > 60) | ||
return false; | ||
} | ||
@@ -86,5 +99,4 @@ // Make sure the auth is for the correct app | ||
var base64Data = new Buffer(outgoing.data).toString('base64'); | ||
return { | ||
'signature': base64Data, | ||
'signature': outgoing.data, | ||
'iv': outgoing.iv | ||
@@ -99,15 +111,18 @@ }; | ||
function decryptAppData(data, iv) { | ||
if (!~mcrypt.getAlgorithmNames().indexOf('rijndael-128')) | ||
throw new Error('MCrypt algorithm "rijndael-128" not found.') | ||
if (!~mcrypt.getModeNames().indexOf('cbc')) | ||
throw new Error('MCrypt mode "cbc" not found.') | ||
var td = new mcrypt.MCrypt('rijndael-128', 'cbc'); | ||
// Intialize encryption | ||
td.open(cutKey(td, key), iv); | ||
var decipher = crypto.createDecipheriv('AES-256-CBC', keyBuf, iv); | ||
decipher.setAutoPadding(false); | ||
// Decrypt data | ||
var decrypted = td.decrypt(data).toString().replace(/\x00/g, ''); | ||
return JSON.parse(decrypted); | ||
var decrypted = decipher.update(data); | ||
decrypted += decipher.final(); | ||
decrypted = decrypted.toString().replace(/\x00/g, ''); | ||
try { | ||
return JSON.parse(decrypted); | ||
} catch(_) { | ||
// Bad key, bad data or bad IV will result in random garbage, | ||
// which causes a SyntaxError when trying to parse it as JSON. | ||
return null; | ||
} | ||
} | ||
@@ -118,21 +133,24 @@ | ||
* using the given key, and returns both the encrypted | ||
* data and the used IV | ||
* data (base64-encoded) and the used IV | ||
*/ | ||
function encryptAppData(data) { | ||
var td = new mcrypt.MCrypt('rijndael-128', 'cbc'); | ||
// Create the IV and determine the keysize length | ||
var ivRaw = td.generateIv(); | ||
var ivSha1 = crypto.createHash('sha1').update(ivRaw).digest('hex'); | ||
var iv = ivSha1.slice(0, td.getIvSize()); | ||
// Create the IV | ||
var iv = crypto.randomBytes(8).toString('hex'); | ||
// Intialize encryption | ||
td.open(cutKey(td, key), iv); | ||
var cipher = crypto.createCipheriv('AES-256-CBC', keyBuf, iv); | ||
cipher.setAutoPadding(false); | ||
// Prepare data | ||
var plainText = new Buffer(JSON.stringify(data)); | ||
// Encrypt data | ||
var encrypted = td.encrypt(JSON.stringify(data)); | ||
var encrypted = cipher.update(plainText, null, 'binary'); | ||
for (var i = plainText.length % 16; i < 16; i++) | ||
encrypted += cipher.update('\0', 'binary', 'binary'); | ||
encrypted += cipher.final('binary'); | ||
return { | ||
iv: iv, | ||
data: encrypted | ||
data: new Buffer(encrypted, 'binary').toString('base64') | ||
}; | ||
@@ -142,11 +160,2 @@ } | ||
/** | ||
* Makes the a key a certain length | ||
*/ | ||
function cutKey(td, key) { | ||
var keySha1 = crypto.createHash('sha1').update(key).digest('hex'); | ||
var keyHex = keySha1.slice(0, td.getKeySize()); | ||
return new Buffer(keyHex); | ||
} | ||
/** | ||
* Generates a random salt of the given size | ||
@@ -153,0 +162,0 @@ */ |
10910
0
6
258
2
48
- Removedmcrypt@0.0.7
- Removedmcrypt@0.0.7(transitive)