base64id.js (2365B)
1 /*! 2 * base64id v0.1.0 3 */ 4 5 /** 6 * Module dependencies 7 */ 8 9 var crypto = require('crypto'); 10 11 /** 12 * Constructor 13 */ 14 15 var Base64Id = function() { }; 16 17 /** 18 * Get random bytes 19 * 20 * Uses a buffer if available, falls back to crypto.randomBytes 21 */ 22 23 Base64Id.prototype.getRandomBytes = function(bytes) { 24 25 var BUFFER_SIZE = 4096 26 var self = this; 27 28 bytes = bytes || 12; 29 30 if (bytes > BUFFER_SIZE) { 31 return crypto.randomBytes(bytes); 32 } 33 34 var bytesInBuffer = parseInt(BUFFER_SIZE/bytes); 35 var threshold = parseInt(bytesInBuffer*0.85); 36 37 if (!threshold) { 38 return crypto.randomBytes(bytes); 39 } 40 41 if (this.bytesBufferIndex == null) { 42 this.bytesBufferIndex = -1; 43 } 44 45 if (this.bytesBufferIndex == bytesInBuffer) { 46 this.bytesBuffer = null; 47 this.bytesBufferIndex = -1; 48 } 49 50 // No buffered bytes available or index above threshold 51 if (this.bytesBufferIndex == -1 || this.bytesBufferIndex > threshold) { 52 53 if (!this.isGeneratingBytes) { 54 this.isGeneratingBytes = true; 55 crypto.randomBytes(BUFFER_SIZE, function(err, bytes) { 56 self.bytesBuffer = bytes; 57 self.bytesBufferIndex = 0; 58 self.isGeneratingBytes = false; 59 }); 60 } 61 62 // Fall back to sync call when no buffered bytes are available 63 if (this.bytesBufferIndex == -1) { 64 return crypto.randomBytes(bytes); 65 } 66 } 67 68 var result = this.bytesBuffer.slice(bytes*this.bytesBufferIndex, bytes*(this.bytesBufferIndex+1)); 69 this.bytesBufferIndex++; 70 71 return result; 72 } 73 74 /** 75 * Generates a base64 id 76 * 77 * (Original version from socket.io <http://socket.io>) 78 */ 79 80 Base64Id.prototype.generateId = function () { 81 var rand = Buffer.alloc(15); // multiple of 3 for base64 82 if (!rand.writeInt32BE) { 83 return Math.abs(Math.random() * Math.random() * Date.now() | 0).toString() 84 + Math.abs(Math.random() * Math.random() * Date.now() | 0).toString(); 85 } 86 this.sequenceNumber = (this.sequenceNumber + 1) | 0; 87 rand.writeInt32BE(this.sequenceNumber, 11); 88 if (crypto.randomBytes) { 89 this.getRandomBytes(12).copy(rand); 90 } else { 91 // not secure for node 0.4 92 [0, 4, 8].forEach(function(i) { 93 rand.writeInt32BE(Math.random() * Math.pow(2, 32) | 0, i); 94 }); 95 } 96 return rand.toString('base64').replace(/\//g, '_').replace(/\+/g, '-'); 97 }; 98 99 /** 100 * Export 101 */ 102 103 exports = module.exports = new Base64Id();