1

I'm looking for an efficient way to build a random string that has specific requirements but can vary in length. It must:

  • Contain at least one uppercase character.
  • Contain at least one lowercase character.
  • Contain at least one number.
  • Contain at least one of the special characters: _-|@.,?/!~#$%^&*(){}[]+=

The random string doesn't have to be unique but if it is, its better. It will be used in a node.js server so any crypto library can be made use of. I saw Math.random().toString(36) which comes close but doesn't get me everything. I'm not sure if I should just try to build a regex for this.

2
  • A regex would be used to validate your string/requirements. It would not generate a string. Commented Jun 13, 2013 at 13:55
  • For crypto always use crypto.randomBytes() Commented Jun 13, 2013 at 14:15

2 Answers 2

3
var randomString = (function() {
  // Define character classes to pick from randomly.
  var uppers = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
  var lowers = 'abcdefghijklmnopqrstuvwxyz';
  var numbers = '0123456789';
  var specials = '_-|@.,?/!~#$%^&*(){}[]+=';
  var charClasses = [uppers, lowers, numbers, specials];
  var minLen = charClasses.length;
  function chooseRandom(x) {
    var i = Math.floor(Math.random() * x.length);
    return (typeof(x)==='string') ? x.substr(i,1) : x[i];
  }
  // Define the function to actually generate a random string.
  return function(maxLen) {
    maxLen = (maxLen || 36);
    if (maxLen < minLen) { throw new Error('length must be >= ' + minLen); }
    do { // Append a random char from a random char class.
      var str='', usedClasses={}, charClass;
      while (str.length < maxLen) {
        charClass = chooseRandom(charClasses);
        usedClasses[charClass] = true;
        str += chooseRandom(charClass);
      }
      // Ensure we have picked from every char class.
    } while (Object.keys(usedClasses).length !== charClasses.length);
    return str;
  }
})();

randomString(); // => "o4m3H@YC7j0r@^gsY@1vlg2]cI66|9^beZ1)"
randomString(); // => "R6-K0Kq%4O0Je*=iPbVaV|bo-_,,g[j8wTW2"
randomString(); // => "!uu5NUWs1P}SRN78l}32Gno$]2m5PV+h+wTG"
Sign up to request clarification or add additional context in comments.

3 Comments

Is that forEach loop needed? It seems to just limit the first couple of characters to a certain order (1st is uppers, second is lowers, etc)
@thearchitect: updated to remove that forEach loop.
@thearchitect: I added your idea of extracting the "minLen" constant.
0

Regex are used to check, capture, split or replace something in a string, you can't build something from zero with them.

However you can make some replacement in a string that contain a random generated number to have that you want.

1 Comment

I thought of that but it will loose a level of uniqueness if I'm just replacing chars. ATM I'm trying Math.random() to build the string.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.