You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
103 lines
2.3 KiB
103 lines
2.3 KiB
/*! |
|
* base64id v0.1.0 |
|
*/ |
|
|
|
/** |
|
* Module dependencies |
|
*/ |
|
|
|
var crypto = require('crypto'); |
|
|
|
/** |
|
* Constructor |
|
*/ |
|
|
|
var Base64Id = function() { }; |
|
|
|
/** |
|
* Get random bytes |
|
* |
|
* Uses a buffer if available, falls back to crypto.randomBytes |
|
*/ |
|
|
|
Base64Id.prototype.getRandomBytes = function(bytes) { |
|
|
|
var BUFFER_SIZE = 4096 |
|
var self = this; |
|
|
|
bytes = bytes || 12; |
|
|
|
if (bytes > BUFFER_SIZE) { |
|
return crypto.randomBytes(bytes); |
|
} |
|
|
|
var bytesInBuffer = parseInt(BUFFER_SIZE/bytes); |
|
var threshold = parseInt(bytesInBuffer*0.85); |
|
|
|
if (!threshold) { |
|
return crypto.randomBytes(bytes); |
|
} |
|
|
|
if (this.bytesBufferIndex == null) { |
|
this.bytesBufferIndex = -1; |
|
} |
|
|
|
if (this.bytesBufferIndex == bytesInBuffer) { |
|
this.bytesBuffer = null; |
|
this.bytesBufferIndex = -1; |
|
} |
|
|
|
// No buffered bytes available or index above threshold |
|
if (this.bytesBufferIndex == -1 || this.bytesBufferIndex > threshold) { |
|
|
|
if (!this.isGeneratingBytes) { |
|
this.isGeneratingBytes = true; |
|
crypto.randomBytes(BUFFER_SIZE, function(err, bytes) { |
|
self.bytesBuffer = bytes; |
|
self.bytesBufferIndex = 0; |
|
self.isGeneratingBytes = false; |
|
}); |
|
} |
|
|
|
// Fall back to sync call when no buffered bytes are available |
|
if (this.bytesBufferIndex == -1) { |
|
return crypto.randomBytes(bytes); |
|
} |
|
} |
|
|
|
var result = this.bytesBuffer.slice(bytes*this.bytesBufferIndex, bytes*(this.bytesBufferIndex+1)); |
|
this.bytesBufferIndex++; |
|
|
|
return result; |
|
} |
|
|
|
/** |
|
* Generates a base64 id |
|
* |
|
* (Original version from socket.io <http://socket.io>) |
|
*/ |
|
|
|
Base64Id.prototype.generateId = function () { |
|
var rand = Buffer.alloc(15); // multiple of 3 for base64 |
|
if (!rand.writeInt32BE) { |
|
return Math.abs(Math.random() * Math.random() * Date.now() | 0).toString() |
|
+ Math.abs(Math.random() * Math.random() * Date.now() | 0).toString(); |
|
} |
|
this.sequenceNumber = (this.sequenceNumber + 1) | 0; |
|
rand.writeInt32BE(this.sequenceNumber, 11); |
|
if (crypto.randomBytes) { |
|
this.getRandomBytes(12).copy(rand); |
|
} else { |
|
// not secure for node 0.4 |
|
[0, 4, 8].forEach(function(i) { |
|
rand.writeInt32BE(Math.random() * Math.pow(2, 32) | 0, i); |
|
}); |
|
} |
|
return rand.toString('base64').replace(/\//g, '_').replace(/\+/g, '-'); |
|
}; |
|
|
|
/** |
|
* Export |
|
*/ |
|
|
|
exports = module.exports = new Base64Id();
|
|
|