Javascript NodeJs Random String alternate techniques - javascript

Is there any particular reason why I should choose either of these techniques for generating a random string in nodejs?
First:
//var TOKEN_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
var TOKEN_CHARS = 'abcdef0123456789';
var len = 24;
var chars = [];
for (var i = 0; i < len; i++) {
var index = Math.floor(Math.random() * TOKEN_CHARS.length);
chars.push(TOKEN_CHARS[index]);
}
console.log(chars.join(''));
Second:
var token = require('crypto').randomBytes(len/2).toString('hex');
console.log(token);
At first glance the output of these look similar. I don't understand fully, but as far as I can tell from researching Math.random() may not be the best technique based on the fact the "seed" has to do with the system time and is not truly random. However the highly used connect library uses the first technique so I assume it must be pretty good.
If I were to use the first technique, would the token be "more" secure using the commented out TOKEN_CHARS (simply due to more possibilities for each character)?

Math.random() is created as a general purpose PRNG, crypto.pseudoRandomBytes is a part of OpenSSL library and is created as a CSPRNG. So it's a good reason to use second one.
If I were to use the first technique, would the token be "more" secure using the commented out TOKEN_CHARS
No. However, if you want more entropy in your token, you can use .toString('base64') in the second case, this way it'll use 64 characters to represent your token.

Related

Performance of array includes vs mapping to an Object and accessing it in JavaScript

According to the fundamentals of CS
the search functionality of an unsorted list has to occur in O(n) time where as direct access into an array will occur in O(1) time for HashMaps.
So is it more performant to map an array into a dictionary and then access the element directly or should I just use includes? This question is specifically for JavaScript because I believe this would come down to core implementation details of how includes() and {} is implemented.
let y = [1,2,3,4,5]
y.includes(3)
or...
let y = {
1: true,
2: true
3: true
4: true
5: true
}
5 in y
It's true that object lookup occurs in constant time - O(1) - so using object properties instead of an array is one option, but if you're just trying to check whether a value is included in a collection, it would be more appropriate to use a Set, which is a (generally unordered) collection of values, which can also be looked up in linear time. (Using a plain object instead would require you to have values in addition to your keys, which you don't care about - so, use a Set instead.)
const set = new Set(['foo', 'bar']);
console.log(set.has('foo'));
console.log(set.has('baz'));
This will be useful when you have to look up multiple values for the same Set. But, adding items to the Set (just like adding properties to an object) is O(N), so if you're just going to look up a single value, once, there's no benefit to this nor the object technique, and you may as well just use an array includes test.
Updated 04/29/2020
As the commenter rightly pointed out it would seem V8 was optimizing out the array includes calls. An updated version that assigns to a var and uses it produces more expected results. In that case Object address is fastest, followed by Set has and in a distant third is Array includes (on my system / browser).
All the same, I do stand by my original point, that if making micro-optimizations it is worth testing assumptions. Just make sure your tests are valid ;)
Original
Well. Despite the obvious expectation that Object address and Set has should outperform Array includes, benchmarks against Chrome indicate that implementation trumps expectation.
In the benches I ran against Chrome Array includes was far and away the best performer.
I also tested locally with Node and got more expected results. In that Object address wins, followed closely by Set has, then Array includes was marginally slower than both.
Bottom line is, if you're making micro-optimizations (not recommending that) it's worth benchmarking rather than assuming which might be best for your particular case. Ultimately it comes down to the implementation, as your question implies. So optimizing for the target platform is key.
Here's the results I got:
Node (12.6.0):
ops for Object address 7804199
ops for Array includes 5200197
ops for Set has 7178483
Chrome (75.0):
https://jsbench.me/myjyq4ixs1/1
This isn't necessarily a direct answer to the question but here is a related performance test I ran real quick in my chrome dev tools
function getRandomInt(max) {
return Math.floor(Math.random() * max);
}
var arr = [1,2,3];
var t = performance.now();
for (var i = 0; i < 100000; i++) {
var x = arr.includes(getRandomInt(3));
}
console.log(performance.now() - t);
var t = performance.now();
for (var i = 0; i < 100000; i++) {
var n = getRandomInt(3);
var x = n == 1 || n == 2 || n == 3;
}
console.log(performance.now() - t);
VM44:9 9.100000001490116
VM44:16 5.699999995529652
I find the array includes syntax nice to look at, so I wanted to know if the performance was likely to be an issue the way I use it, for checking if a variable is one of a set of enums for instance. It doesn't seem to be much of an impact for situations like this with a short list. Then I ran this.
function getRandomInt(max) {
return Math.floor(Math.random() * max);
}
var t = performance.now();
for (var i = 0; i < 100000; i++) {
var x = [1,2,3].includes(getRandomInt(3));
}
console.log(performance.now() - t);
var t = performance.now();
for (var i = 0; i < 100000; i++) {
var n = getRandomInt(3);
var x = n == 1 || n == 2 || n == 3;
}
console.log(performance.now() - t);
VM83:8 12.600000001490116
VM83:15 4.399999998509884
and so the way I actually use it and like lookin at it is quite worse with performance, despite still not being very significant unless run a few million times, so using it inside of an Array.filter that may run a lot as a react redux selector may not be a great idea like I was about to do when I decided to test this.

How do I find the next ID?

I am trying to find out the best way to implement nextId() in a Javascript app that issues unique IDs for its objects. If it matters, it's a program that I am doing as a learning experience that's pure JS, HTML, and CSS (no libraries, frameworks, DBMS, etc.). I saw a similar question on here on SO (although I wasn't able to find it again for the link) with answers that included not only storing a list of possible ids paired with a boolean value to determine if the id is used, but also storing deleted ids in a recycling list to use for future objects that need it. I think the latter option sounds better, but I'm sure there are even more ways to do it. Does anyone know if there is a pattern, algorithm, or otherwise best practice for this task?
EDIT:
I would like to allow users to share data at some point soon in the application's life, so IDs that already exist would likely become an issue at some point. I would like the IDs to be permanent as I will be persisting data with LocalStorage. A simple integer will work which I will prefix with a letter or two to identify the type of object. It would also be nice to fill in the holes, so the integer doesn't get too high when users use it long-term (wishful thinking).
Also, all objects are constructed from strings at the beginning of the program (I know it's insane).
If you just need an id that is unique per the lifetime of a page, you can use a simple monotomically increasing counter in the page:
var getUniqueID = (function() {
var cntr = 0;
return function() {
return cntr++;
};
})();
var idA = getUniqueID();
var idB = getUniqueID();
To make sure your ids are unique among all users is a taller task. Without involving a central server that coins unique ids for you, the general concept here is to create an id that is a combination of three things:
A token that is unique to the user (like a userID)
A token that is guaranteed to be unique for the session (like what we have above)
A random value.
Done right, there can never be a collision between two different users (because the userID is in the id) and the counter makes it so no user ever generates the same id twice in the same session and the random value makes the odds of a user generating the same id themselves in the same session extremely small.
var getGUID = (function() {
var cntr = 0;
return function(userID) {
var rand = Math.random().toString().replace(".", "");
return userID + "_" + rand + "_" + cntr++;
};
})();
var idA = getGUID(myUserID);
var idB = getGUID(myUserID);
Note: this is the simpler approach on GUID generation that assumes you already have a userID. There is a whole lot of research and literature on various strategies for generating a GUID which you can certainly read a lot more about if you want something beyond this. Some references on the topic:
http://en.wikipedia.org/wiki/Globally_unique_identifier
http://betterexplained.com/articles/the-quick-guide-to-guids/
http://www.uddi.org/pubs/draft-leach-uuids-guids-01.txt
Depending on the use case, I like to create a complex unique id:
function newGUID(){
var result = '';
var hexcodes = "0123456789abcdef".split("");
for (var index = 0; index < 32; index++) {
var value = Math.floor(Math.random() * 16);
switch (index) {
case 8:
result += '-';
break;
case 12:
value = 4;
break;
}
result += hexcodes[value];
}
return result;
}
You could use UUIDs as IDs. There's one answer here in SO where you can generate UUIDs in JS. UUIDs are usually enough to be used as IDs. Just to be sure that the id isn't a dupe, you can have an object whose keys are the used IDs. As IDs are generated, you can keep track of them by adding them in the object. You can then look them up by doing obj.hasOwnProperty(id).
You can do it like
var idStorage = {};
var id;
// generate ID that's unique and hasn't been used
do{
id = guid();
} while (idStorage.hasOwnProperty(id));
idStorage[id] = true;
// ID is usable
Also, IDs are supposed to be unique. They should never be reused at all.
AngularJS has a very simply approach to generating unique IDs: just increment a global counter. From src/Angular.js:
var uid = 0;
// ...
/**
* A consistent way of creating unique IDs in angular.
*
* Using simple numbers allows us to generate 28.6 million unique ids per second for 10 years before
* we hit number precision issues in JavaScript.
*
* Math.pow(2,53) / 60 / 60 / 24 / 365 / 10 = 28.6M
*
* #returns {number} an unique alpha-numeric string
*/
function nextUid() {
return ++uid;
}
Of course, you should choose a solution depending on what time frame the generated IDs should be unique. The above solution will generate IDs which are unique for one session of one web page. For a simple single-page application (which is Angular's use case), this will do just fine. If you need them to be unique across multiple page loads, or unique for the same user, you'll need to persist the uid for a bit longer (in a cookie or in a database). If they need to be unique for a longer time, you might also need to look into longer IDs with more than 2^53 possible values.
I would use a UUID v4 since these IDs would always be unique in any circumstance (no additional logic to check if these ids are in use or to recicle old ones), just issue a new id whenever you need one.
Very simple implementation in JS as follows:
function generateUUID(){
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
return v.toString(16);
});
}
$(function() {
$('button').bind('click', function() {
$('input').val(generateUUID());
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" style="width: 350px;"/><button>GENERATE NEW ID</button>
Well, it's a bit unclear what you expect from these ids, however if you only want a unique id per type of entity in your system and your data must only live in memory, then you could use the following approach:
Note: I saw from the comments you wanted a prefix which represents the entity.
function identitySequence(base) {
var id = base || 0;
return function () {
return ++id;
};
}
//Lets say you had some sort of repository for every entity
function InMemoryUserRepository(nextId) {
this._nextId = nextId;
}
InMemoryUserRepository.prototype = {
constructor: InMemoryUserRepository,
get nextId() { return 'user-' + this._nextId(); }
//other operations, like save...
};
var userRepository = new InMemoryUserRepository(identitySequence());
userRepository.nextId; //user-1
Now, lets say you wanted your id sequence to be persistent in the localStorage, here's what you could do (extending the above code):
var userRepository = new InMemoryUserRepository(localStorageIdentitySequence('userIdSeq'));
userRepository.nextId; //user-1
//Reload page
userRepository.nextId; //user-2
function localStorageIdentitySequence(storageKey) {
var next = identitySequence(+localStorage.getItem(storageKey));
return function () {
return +(localStorage[storageKey] = next());
};
}
This works fine for a single machine, however if you want a unique id generator that will generate unique IDs across machines, then this approach will not work. You would have to generate the ID from a server that can be accessed by all clients, or you can generate a GUID on the client instead. There would be no way to know if the GUID was already generated by another client, but that would be very unlikely.

Javascript prototype function: decimal time value to a time string

On a project I'm currently working on in JavaScript, I'm using decimal formats so it's easier to calculate with rather than using an hour/minute format in strings (calendar related project). To display the time on the user's screen though, the timecode has to be shown as hh:mm.
I thought it would be great to use a String prototype function for this as it would allow me to use code like:
var time = 8.75;
document.write("Meeting at "+time.toTime()); // writes: Meeting at 8:45
So far, I've got that almost working, using:
String.prototype.toTime = function(){
var hrs = this.toString().slice(0,this.indexOf("."));
var min = Math.round(this.toString().slice(this.indexOf("."))/100*60);
min = min<10 ? "0"+min : min.toString();
return hrs+":"+min;
}
The problem, though, is that this will only work if the variable time is a string. Otherwise it will give an undefined error.
Would there be any way of applying the prototype to a different object in JavaScript, so that I don't have to use time.toString().toTime()?
Thanks!
Firstly, you can add to the Number prototype. Many people will warn against modifying prototypes, which in many cases is justified. If there is a chance 3rd party scripts will be running alongside yours, it is a danger to modify prototypes.
Secondly, I simplified your code a little, using modulus, and floor to calculate the hrs and mins...
Number.prototype.toTime = function(){
var hrs = Math.floor(this)
var min = Math.round(this%1*60)
min = min<10 ? "0"+min : min.toString();
return hrs+":"+min;
}
var time = 8.25;
console.log("Meeting at "+time.toTime());
You can use Object.prototype.toTime.

Using "eval" in a couchdb reduce - just how dangerous is this?

My docs contain lists of errors.
I have a view which counts the number of docs with a specific error, and an average of how many errors a doc with a given error has.
Map
function (doc) {
var i;
for (i = 0; i < doc.errors.length; i = i + 1){
emit([doc.errors[i], doc.flummery], [1, doc.errors.length])
}
}
Reduce
function (key, values, rereduce) {
var avg = [];
var cnt = [];
var i;
for (i = 0; i < values.length; i = i + 1) {
avg.push(values[i][1]);
cnt.push(values[i][0]);
}
return [sum(cnt), eval(avg.join("+")) / avg.length]
}
I have read many times that the use of eval() is the path to madness, but I can't think of any way that it could really trip me up here. Is eval() safe in couchdb views?
Note that Oleg came up with the obvious answer, which is "don't do that, couchdb gives you a sum() function". It is obvious in this situation that eval() is not needed. However, should I ever require it, is it safe to use given that I'll have good control over my inputs?
Can't you use sum(avg) / avg.length instead?
eval have obvious drawback of calling full power of compiler: it is very resource heavy and introduces a big security hole unless you carefully sanitize your input.

How To Join Relative URLs in JavaScript

I want to join two strings each representing a relative URL in Javascript.
I want to join the base URL http://www.adress.com/more/evenmore with the following examples:
../../adress (with the expected output: http://www.adress.com/adress)
../adress (with the expected output http://www.adress.com/more/adress)
What would be the best way? I was thinking of using regexp and checking
how many ../ preceed the relative URL, then subtracting that amount from the baseurl and adding them to what is left.
8 years later, many browsers (except for Internet Explorer) support the URL constructor (URL(url [, base])).
> new URL('../address', 'http://www.adress.com/more/evenmore/').href
"http://www.adress.com/more/address"
> new URL('../../address', 'http://www.adress.com/more/evenmore/').href
"http://www.adress.com/address"
The following function decomposes the URL then resolves it.
function concatAndResolveUrl(url, concat) {
var url1 = url.split('/');
var url2 = concat.split('/');
var url3 = [ ];
for (var i = 0, l = url1.length; i < l; i ++) {
if (url1[i] == '..') {
url3.pop();
} else if (url1[i] == '.') {
continue;
} else {
url3.push(url1[i]);
}
}
for (var i = 0, l = url2.length; i < l; i ++) {
if (url2[i] == '..') {
url3.pop();
} else if (url2[i] == '.') {
continue;
} else {
url3.push(url2[i]);
}
}
return url3.join('/');
}
Using URI.js (urijs - npm): absoluteTo():
function joinUrl(baseUrl, url) {
var theUrl = new URI(url);
if (theUrl.is("relative")) {
theUrl = theUrl.absoluteTo(baseUrl);
}
return theUrl.toString();
}
The ECMAScript URL Web API mentioned by #ning is a good place to start: especially as it is available in vanilla JS implementations (Node, etc.) and doesn't require you to use a library that does something the implementation nowq already accomplishes. Consulting the MDN documentation, more specifically the examples, is a great place to start.
Borrowing (somewhat) directly from their documentation:
let m = 'https://developer.mozilla.org';
// ... omitted
let d = new URL('/en-US/docs', m);
If you were to do the above, then console.log the .toString of the constructed URL object, your output would be: 'https://developer.mozilla.org/en-US/docs'.
Importantly, if you consult the Syntax section of the documentation, you will note that the second argument is optional and the second argument (as seen in the above example) represents the base URL (though only in the case of two arguments being supplied).
If both argument values are absolute URLs, Web API honors the first and discards the second.
If you are working with Node.js, I would encourage you to look at the native path module for doing work on relative paths, again over using a library. The main motivation here is that spinning up your own algorithm (probably just a call to path here and there) is potentially better than introducing a library that will pull in several other dependencies that may introduce vulnerabilities and unnecessary bloat to your application (or just be too heavy weight for what you need).
However, if you are working on the front end, you won't have path available to you and - as mentioned in #cburgmer's answer comments - Web API's URL doesn't support the relative path case mentioned. In this case, you may need to look for a library to accomplish this for you; however, again, given the other answers, I'd consider trying out a home-spun approach.
To their credit, URI.js currently only integrates one non-dev. dependency and doesn't have a huge footprint.

Categories

Resources