HTMLify
index.js
Views: 6 | Author: cody
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | var crypto = require('crypto'); var d = exports.defaults = { cache: true }; var items = {}; function cache(key) { if(!items[key] || !d.cache) { if(Object.keys(items).length > 500) { items = {}; } items[key] = crypto.createHmac('sha512', d.secret).update(key).digest('base64'); } return items[key]; } exports.INVALID = 0; exports.VALID = 1; exports.EXPIRING = 2; exports.verify = function(data, hash) { if(typeof data !== 'string' || typeof hash !== 'string' ) { return false; } var epoch = Math.floor(new Date().getTime() / 1000 / d.timeStep); // e.g. http://tools.ietf.org/html/rfc6238 // allow data to be empty, always take into account the time if (hash === cache(data + epoch) || hash === cache(data + (epoch + 1))) { return exports.VALID; // truthy, valid and current } if (hash === cache(data + (epoch - 1))) { return exports.EXPIRING; // truthy, expired but still valid } return exports.INVALID; }; exports.generate = function(data, opts) { if(typeof data !== 'string') { return false; } var now = opts && opts.now || (new Date().getTime()), ts = opts && opts.timeStep || d.timeStep, secret = opts && opts.secret || d.secret, epoch = Math.floor(now / 1000 / ts); // e.g. http://tools.ietf.org/html/rfc6238 return crypto.createHmac('sha512', secret).update(data + epoch).digest('base64'); }; exports.invalidate = function(data, hash) { var isValidHash = exports.verify(data, hash), epoch = Math.floor(new Date().getTime() / 1000 / d.timeStep); if (!isValidHash) { throw 'invalid hash'; } else { items[hash + epoch] = null; } return true; }; |