Reputation: 5238
I want to generate a random string that has to have 5 letters from a to z and 3 numbers.
How can I do this with JavaScript?
I've got the following script, but it doesn't meet my requirements.
var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
var string_length = 8;
var randomstring = '';
for (var i=0; i<string_length; i++) {
var rnum = Math.floor(Math.random() * chars.length);
randomstring += chars.substring(rnum,rnum+1);
}
Upvotes: 156
Views: 258479
Reputation: 8583
Updated 2023:
If you need to generate passwords for end-users, avoid relying on answers from Stackoverflow or ID generators. Instead, consider referring to open-source password generators, like Bitwarden, which is also a password manager. You can find the password generation function in bitwarden/password-generation.service.ts.
If you're looking for a straightforward generator, consider this option:
Based on mwag's answer, this one utilizes crypto.getRandomValues
, which provides a stronger randomization than Math.random
.
(Of course, you can shuffle or generate on-the-fly the characters
before passing them to the function)
var generatePassword = (
length = 20,
characters = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz~!@-#$'
) =>
Array.from(crypto.getRandomValues(new Uint32Array(length)))
.map((x) => characters[x % characters.length])
.join('')
console.log(generatePassword())
javascript:prompt("Random password:",((o=20,n="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz~!@-#$")=>Array.from(crypto.getRandomValues(new Uint32Array(o))).map(o=>n[o%n.length]).join(""))())
const crypto = require('crypto')
const generatePassword = (
length = 20,
characters = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz~!@-#$'
) =>
Array.from(crypto.randomFillSync(new Uint32Array(length)))
.map((x) => characters[x % characters.length])
.join('')
console.log(generatePassword())
Suggested by Michael Bauer: https://stackoverflow.com/a/61471228/12757511
Upvotes: 64
Reputation: 3680
I'm loathe to add a 29th answer here, but I looked at all of the others closely and none seemed secure enough for my requirements.
mwag's answer is close, but I couldn't easily verify that it actually avoids bias in the distribution. It still uses a modulus operation, and the max/umax
technique isn't documented or obvious. I also feel like the code has low readability, even after reformatting.
This code uses the rejection sampling technique, which feels simple and straight-forward to me.
/**
* Generate a cryptographically secure random password.
*
* @returns {string}
*/
function generatePassword() {
const characterPool = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()';
const passwordLength = 24;
const randomNumber = new Uint8Array( 1 );
let password = '';
// JS doesn't provide a way to generate a cryptographically secure random number within a range, so instead
// we just throw out values that don't correspond to a character. This is a little bit slower than using a
// modulo operation, but it avoids introducing bias in the distribution. Realistically, it's easily performant
// in this context.
// @link https://dimitri.xyz/random-ints-from-random-bits/
for ( let i = 0; i < passwordLength; i++ ) {
do {
crypto.getRandomValues( randomNumber );
} while ( randomNumber[0] >= characterPool.length );
password += characterPool[ randomNumber[0] ];
}
return password;
}
My company has released it as a package with configurable arguments for length and characters. bermi/password-generator works in a similar way, but isn't as lean.
Aside: I also looked at existing solutions for passphrases, but unfortunately didn't find a secure one that worked for me. The two that seemed best were:
Upvotes: 2
Reputation: 4045
Many answers (including the original of this one) don't actually answer the letter- and number-count requirements of the OP.
Below are two solutions: general (no min letters/numbers), and with rules as specified in the OP.
Many other answers berate the use of Math.random() and then go on to use a better random number generator that is non-uniformly applied, with an end result that (just like using Math.random!) is not cryptographically secure. Anyway, fwiw this update addresses both, which I don't believe any other answer does.
Advantages of this approach:
Note that this:
Three-liner:
var pwdChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
var pwdLen = 10;
var randPassword = new Array(pwdLen).fill(0).map(x => (function(chars) { let umax = Math.pow(2, 32), r = new Uint32Array(1), max = umax - (umax % chars.length); do { crypto.getRandomValues(r); } while(r[0] > max); return chars[r[0] % chars.length]; })(pwdChars)).join('');
Or, as one-liner:
var randPassword = new Array(10).fill("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz").map(x => (function(chars) { let umax = Math.pow(2, 32), r = new Uint32Array(1), max = umax - (umax % chars.length); do { crypto.getRandomValues(r); } while(r[0] > max); return chars[r[0] % chars.length]; })(x)).join('');
Now, a variation on the above. This will generate three random strings from the given charsets (letter, number, either) and then scramble the result.
First, as a function:
function randPassword(letters, numbers, either) {
var chars = [
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", // letters
"0123456789", // numbers
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" // either
];
function randInt(this_max) { // return int between 0 and this_max - 1
let umax = Math.pow(2, 32);
let max = umax - (umax % this_max);
let r = new Uint32Array(1);
do {
crypto.getRandomValues(r);
} while(r[0] > max);
return r[0] % this_max;
}
function randCharFrom(chars) {
return chars[randInt(chars.length)];
}
function shuffle(arr) { // https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle#The_modern_algorithm
for (let i = 0, n = arr.length; i < n - 2; i++) {
let j = randInt(n - i);
[arr[j], arr[i]] = [arr[i], arr[j]];
}
return arr;
}
return shuffle([letters, numbers, either].map(function(len, i) {
return Array(len).fill(chars[i]).map(x => randCharFrom(x)).join('');
}).concat().join('').split('')).join('')
}
// invoke like so: randPassword(5,3,2);
Same thing, as a 3-liner (well, more like a lot of lines smashed into 3 lines. Not recommended but sometimes it's entertaining anyway):
var chars = ["ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz","0123456789", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"];
function randInt(this_max) { let umax = Math.pow(2, 32); let max = umax - (umax % this_max); let r = new Uint32Array(1); do { crypto.getRandomValues(r); } while(r[0] > max); return r[0] % this_max; };
var randPassword = [[5,3,2].map(function(len, i) { return new Array(len).fill(chars[i]).map(x => (function(chars) { let umax = Math.pow(2, 32), r = new Uint32Array(1), max = umax - (umax % chars.length); do { crypto.getRandomValues(r); } while(r[0] > max); return chars[r[0] % chars.length]; })(x)).join(''); }).join('')].map(s => { let arr = s.split(''); for (let i = 0, n = arr.length; i < n - 2; i++) { let j = randInt(n - i); [arr[j], arr[i]] = [arr[i], arr[j]]; } return arr.join(''); })[0];
Upvotes: 50
Reputation: 361
I wrote this function and it should work for most cases.
function generatePassword(length, options) {
const optionsChars = {
digits: "1234567890",
lowercase: "abcdefghijklmnopqrstuvwxyz",
uppercase: "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
symbols: "@$!%&"
}
const chars = [];
for (let key in options) {
if (options.hasOwnProperty(key) && options[key] && optionsChars.hasOwnProperty(key)) {
chars.push(optionsChars[key]);
}
}
if (!chars.length)
return '';
let password = "";
for (let j = 0; j < chars.length; j++) {
password += chars[j].charAt(Math.floor(Math.random() * chars[j].length));
}
if (length > chars.length) {
length = length - chars.length;
for (let i = 0; i < length; i++) {
const index = Math.floor(Math.random() * chars.length);
password += chars[index].charAt(Math.floor(Math.random() * chars[index].length));
}
}
return password;
}
const password = generatePassword(9, {digits: true, lowercase: true, uppercase: true, symbols: true});
console.log(password)
Upvotes: -1
Reputation: 71
To generate password with minimum 1 char from each array element
generatePassword(length:number){
let password ="";
const chars= [
"ABCDEFGHIJKLMNOPQRSTUVWXYZ",
"abcdefghijklmnopqrstuvwxyz",
"@$!%*?&",
"1234567890"
];
for(let j=0; j<chars.length; j++){
password += chars[j].charAt(Math.floor(Math.random() * chars[j].length));
}
if(length > chars.length){
length = length - chars.length;
for(let i=0; i<length; i++){
const index = Math.floor(Math.random() * chars.length);
password += chars[index].charAt(Math.floor(Math.random() * chars[index].length));
}
}
return password.split('').sort(function(){return 0.5-Math.random()}).join('');
}
Upvotes: -1
Reputation: 1010
Everyone here is using Math.random()
, which is cryptographically insecure
Use this instead using the crypto
API.
const crypto = require("crypto");
function generatePassword() {
return Array(12)
.fill("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")
.map(function (x) {
return x[crypto.randomInt(0, 10_000) % x.length];
})
.join("");
}
Edit: if you’re using crypto-browserfy
you need to use the randomBytes
method.
const crypto = require("crypto");
function generatePassword() {
return Array(12)
.fill("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")
.map(function (x) {
let int = crypto.randomBytes(4, function(ex, buf) {
var hex = buf.toString('hex');
var myInt32 = parseInt(hex, 16);
});
return x[int % x.length];
})
.join("");
}
Upvotes: -1
Reputation: 348
Use this npm package for generating secure password :
npm i generate-secure-password
https://www.npmjs.com/package/generate-secure-password
Sample Code :
const generatePassword = require('generate-secure-password');
let yourPassword = generatePassword({
// None of the arguments are mandatory
length: 8,//not less than 4
numbers: false,//false if number needs to be excluded from password, else true
symbols: false,//false if symbols needs to be excluded from password, else true
lowercase: false,//false if lowercase character needs to be excluded from password, else true
uppercase: false,//false if uppercase character needs to be excluded from password, else true
exclude: ['"','%'] //symbols to exclude, Pass it as an array
});
console.log(yourPassword)
Upvotes: -1
Reputation: 1109
You could use lodash.
import * as _ from 'lodash';
export const generateCustomPassword = (
lowerCaseCount: number,
upperCaseCount: number,
numbersCount: number,
specialsCount: number,
) => {
const chars = 'abcdefghijklmnopqrstuvwxyz';
const numberChars = '0123456789';
const specialChars = '!"£$%^&*()-=+_?';
const pickedChars = _.sampleSize(chars, lowerCaseCount)
.concat(_.sampleSize(chars.toUpperCase(), upperCaseCount))
.concat(_.sampleSize(numberChars, numbersCount))
.concat(_.sampleSize(specialChars, specialsCount));
return _.shuffle(pickedChars).join('');
};
generateCustomPassword(4, 4, 4, 1)
Upvotes: -1
Reputation: 35
Generate a random password of length 8 to 32 characters with at least 1 lower case, 1 upper case, 1 number, 1 spl char (!@$&)
function getRandomUpperCase() {
return String.fromCharCode( Math.floor( Math.random() * 26 ) + 65 );
}
function getRandomLowerCase() {
return String.fromCharCode( Math.floor( Math.random() * 26 ) + 97 );
}
function getRandomNumber() {
return String.fromCharCode( Math.floor( Math.random() * 10 ) + 48 );
}
function getRandomSymbol() {
// const symbol = '!@#$%^&*(){}[]=<>/,.|~?';
const symbol = '!@$&';
return symbol[ Math.floor( Math.random() * symbol.length ) ];
}
const randomFunc = [ getRandomUpperCase, getRandomLowerCase, getRandomNumber, getRandomSymbol ];
function getRandomFunc() {
return randomFunc[Math.floor( Math.random() * Object.keys(randomFunc).length)];
}
function generatePassword() {
let password = '';
const passwordLength = Math.random() * (32 - 8) + 8;
for( let i = 1; i <= passwordLength; i++ ) {
password += getRandomFunc()();
}
//check with regex
const regex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,32}$/
if( !password.match(regex) ) {
password = generatePassword();
}
return password;
}
console.log( generatePassword() );
Upvotes: 0
Reputation: 93
Based on @Ryan Shillington answer above you may find this enhancment helpfull too. Think this is more secured then what was requeted on the original request in the question above.
//Password generated with at least 1 number, 1 upper case character, 1 lower case character and 1 Special character
function generatePassword()
{
var passwordLength = randomIntFromInterval(10,20);
var numberChars = "0123456789";
var upperChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
var lowerChars = "abcdefghijklmnopqrstuvwxyz";
var specialChars = "~!#$%&*-+|";
var allChars = numberChars + upperChars + lowerChars + specialChars;
var randPasswordArray = Array(passwordLength);
randPasswordArray[0] = numberChars;
randPasswordArray[1] = upperChars;
randPasswordArray[2] = lowerChars;
randPasswordArray[3] = specialChars;
randPasswordArray = randPasswordArray.fill(allChars, 4);
if(window.crypto && window.crypto.getRandomValues)
{
return shuffleArray(randPasswordArray.map(function(x) { return x[Math.floor(window.crypto.getRandomValues(new Uint32Array(1))[0] / (0xffffffff + 1) * x.length)] })).join('');
}
else if(window.msCrypto && window.msCrypto.getRandomValues)
{
return shuffleArray(randPasswordArray.map(function(x) { return x[Math.floor(window.msCrypto.getRandomValues(new Uint32Array(1))[0] / (0xffffffff + 1) * x.length)] })).join('');
}else{
return shuffleArray(randPasswordArray.map(function(x) { return x[Math.floor(Math.random() * x.length)] })).join('');
}
}
function shuffleArray(array)
{
for (var i = array.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
}
//generate random number in the range (min and max included)
function randomIntFromInterval(min, max) {
return Math.floor(Math.random() * (max - min + 1) + min);
}
<input type='text' id='p9'/>
<input type='button' value ='pass generator' onclick='document.getElementById("p9").value = generatePassword()'>
Upvotes: 2
Reputation: 358
Try this, it works.
Download script to your javascript application and call the function, randomPassword()
Upvotes: 0
Reputation: 29
Here's a way to create a flexible generator that allows you to add some rules:
function generatePassword(length, rules) {
if (!length || length == undefined) {
length = 8;
}
if (!rules || rules == undefined) {
rules = [
{chars: "abcdefghijklmnopqrstuvwxyz", min: 3}, // As least 3 lowercase letters
{chars: "ABCDEFGHIJKLMNOPQRSTUVWXYZ", min: 2}, // At least 2 uppercase letters
{chars: "0123456789", min: 2}, // At least 2 digits
{chars: "!@#$&*?|%+-_./:;=()[]{}", min: 1} // At least 1 special char
];
}
var allChars = "", allMin = 0;
rules.forEach(function(rule) {
allChars += rule.chars;
allMin += rule.min;
});
if (length < allMin) {
length = allMin;
}
rules.push({chars: allChars, min: length - allMin});
var pswd = "";
rules.forEach(function(rule) {
if (rule.min > 0) {
pswd += shuffleString(rule.chars, rule.min);
}
});
return shuffleString(pswd);
}
function shuffleString(str, maxlength) {
var shuffledString = str.split('').sort(function(){return 0.5-Math.random()}).join('');
if (maxlength > 0) {
shuffledString = shuffledString.substr(0, maxlength);
}
return shuffledString;
}
var pswd = generatePassword(15, [
{chars: "abcdefghijklmnopqrstuvwxyz", min: 4}, // As least 4 lowercase letters
{chars: "ABCDEFGHIJKLMNOPQRSTUVWXYZ", min: 1}, // At least 1 uppercase letters
{chars: "0123456789", min: 3}, // At least 3 digits
{chars: "!@#$&*?|%+-_./:;=()[]{}", min: 2} // At least 2 special chars
]);
console.log(pswd, pswd.length);
Upvotes: 2
Reputation: 89
Any password generated with Math.random() is EXTREMELY BAD.
This function uses the system time as a seed for the random number generator. Anyone who knows the time the password was generated can easily brute-force the password.
In almost all cases, this data is easily available - just take the registration_time column in a hacked database, and test out all the values generated by the Math.random() algorithm using the times from 15 to 0 minutes before.
A password generated with Math.random() is completely worthless because the time the password was first used is enough for cracking it.
Upvotes: 8
Reputation: 1
var Password = {
_pattern : /[a-zA-Z0-9_\-\+\.]/,
_getRandomByte : function()
{
// http://caniuse.com/#feat=getrandomvalues
if(window.crypto && window.crypto.getRandomValues)
{
var result = new Uint8Array(1);
window.crypto.getRandomValues(result);
return result[0];
}
else if(window.msCrypto && window.msCrypto.getRandomValues)
{
var result = new Uint8Array(1);
window.msCrypto.getRandomValues(result);
return result[0];
}
else
{
return Math.floor(Math.random() * 256);
}
},
generate : function(length)
{
return Array.apply(null, {'length': length})
.map(function()
{
var result;
while(true)
{
result = String.fromCharCode(this._getRandomByte());
if(this._pattern.test(result))
{
return result;
}
}
}, this)
.join('');
}
};
<input type='text' id='p'/><br/>
<input type='button' value ='generate' onclick='document.getElementById("p").value = Password.generate(16)'>
Upvotes: -1
Reputation: 25253
A little more maintainable and secure approach.
An update to expand on what I meant and how it works.
Secure. MDN is pretty explicit about the use of Math.random
for anything related to security:
Math.random()
does not provide cryptographically secure random numbers. Do not use them for anything related to security. Use the Web Crypto API instead, and more precisely thewindow.crypto.getRandomValues()
method.
Looking at the can-i-use for getRandomValues
in 2020 you probably don't need the msCrypto
and Math.random
fallback any more, unless you care about ancient browsers.
Maintainable is mostly about the RegExp
_pattern
as an easy way to define what character classes you allow in the password. But also about the 3 things where each does its job: defines a pattern, gets a random byte as securely as possible, provides a public API to combine the two.
var Password = {
_pattern : /[a-zA-Z0-9_\-\+\.]/,
_getRandomByte : function()
{
// http://caniuse.com/#feat=getrandomvalues
if(window.crypto && window.crypto.getRandomValues)
{
var result = new Uint8Array(1);
window.crypto.getRandomValues(result);
return result[0];
}
else if(window.msCrypto && window.msCrypto.getRandomValues)
{
var result = new Uint8Array(1);
window.msCrypto.getRandomValues(result);
return result[0];
}
else
{
return Math.floor(Math.random() * 256);
}
},
generate : function(length)
{
return Array.apply(null, {'length': length})
.map(function()
{
var result;
while(true)
{
result = String.fromCharCode(this._getRandomByte());
if(this._pattern.test(result))
{
return result;
}
}
}, this)
.join('');
}
};
<input type='text' id='p'/><br/>
<input type='button' value ='generate' onclick='document.getElementById("p").value = Password.generate(16)'>
Upvotes: 65
Reputation: 1445
As @RobW notes, restricting the password to a fixed number of characters as proposed in the OP scheme is a bad idea. But worse, answers that propose code based on Math.random
are, well, a really bad idea.
Let's start with the bad idea. The OP code is randomly selecting a string of 8 characters from a set of 62. Restricting the random string to 5 letters and 3 numbers means the resulting passwords will have, at best, 28.5 bits of entropy (as opposed to a potential of 47.6 bits if the distribution restriction of 5 letters and 3 numbers were removed). That's not very good. But in reality, the situation is even worse. The at best aspect of the code is destroyed by the use of Math.random
as the means of generating entropy for the passwords. Math.random
is a pseudo random number generator. Due to the deterministic nature of pseudo random number generators the entropy of the resulting passwords is really bad , rendering any such proposed solution a really bad idea. Assuming these passwords are being doled out to end users (o/w what's the point), an active adversary that receives such a password has very good chance of predicting future passwords doled out to other users, and that's probably not a good thing.
But back to the just bad idea. Assume a cryptographically strong pseudo random number generator is used instead of Math.random
. Why would you restrict the passwords to 28.5 bits? As noted, that's not very good. Presumably the 5 letters, 3 numbers scheme is to assist users in managing randomly doled out passwords. But let's face it, you have to balance ease of use against value of use, and 28.5 bits of entropy isn't much value in defense against an active adversary.
But enough of the bad. Let's propose a path forward. I'll use the JavaScript EntropyString library which "efficiently generates cryptographically strong random strings of specified entropy from various character sets". Rather than the OP 62 characters, I'll use a character set with 32 characters chosen to reduce the use of easily confused characters or the formation of English words. And rather than the 5 letter, 3 number scheme (which has too little entropy), I'll proclaim the password will have 60 bits of entropy (this is the balance of ease versus value).
import { Entropy, charSet32 } from 'entropy-string'
const random = new Entropy({ bits: 60, charset: charset32 })
const string = random.string()
"Q7LfR8Jn7RDp"
Note the arguments to Entropy
specify the desired bits of entropy as opposed to more commonly seen solutions to random string generation that specify passing in a string length (which is both misguided and typically underspecified, but that's another story).
Upvotes: 11
Reputation: 843
Ok so if I understand well you're trying to get a random string password which contains 5 letters and 3 numbers randomly positioned and so which has a length of 8 characters and you accept maj and min letters, you can do that with the following function:
function randPass(lettersLength,numbersLength) {
var j, x, i;
var result = '';
var letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
var numbers = '0123456789';
for (i = 0; i < lettersLength; i++ ) {
result += letters.charAt(Math.floor(Math.random() * letters.length));
}
for (i = 0; i < numbersLength; i++ ) {
result += numbers.charAt(Math.floor(Math.random() * numbers.length));
}
result = result.split("");
for (i = result.length - 1; i > 0; i--) {
j = Math.floor(Math.random() * (i + 1));
x = result[i];
result[i] = result[j];
result[j] = x;
}
result = result.join("");
return result
}
function randPass(lettersLength,numbersLength) {
var j, x, i;
var result = '';
var letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
var numbers = '0123456789';
for (i = 0; i < lettersLength; i++ ) {
result += letters.charAt(Math.floor(Math.random() * letters.length));
}
for (i = 0; i < numbersLength; i++ ) {
result += numbers.charAt(Math.floor(Math.random() * numbers.length));
}
result = result.split("");
for (i = result.length - 1; i > 0; i--) {
j = Math.floor(Math.random() * (i + 1));
x = result[i];
result[i] = result[j];
result[j] = x;
}
result = result.join("");
return result
}
console.log(randPass(5,3))
Upvotes: 3
Reputation: 931
Create a Password generator service called PassswordGeneratorService
import { Injectable } from '@angular/core';
@Injectable()
export class PasswordGeneratorService {
generatePassword(length:number,upper:boolean,numbers:boolean,symbols:boolean) {
const passwordLength = length || 12;
const addUpper = upper;
const addNumbers = numbers;
const addSymbols = symbols;
const lowerCharacters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'];
const upperCharacters = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
const numbers = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
const symbols = ['!', '?', '@'];
const getRandom = array => array[Math.floor(Math.random() * array.length)];
let finalCharacters = '';
if (addUpper) {
finalCharacters = finalCharacters.concat(getRandom(upperCharacters));
}
if (addNumbers) {
finalCharacters = finalCharacters.concat(getRandom(numbers));
}
if (addSymbols) {
finalCharacters = finalCharacters.concat(getRandom(symbols));
}
for (let i = 1; i < passwordLength - 3; i++) {
finalCharacters = finalCharacters.concat(getRandom(lowerCharacters));
}
return finalCharacters.split('').sort(() => 0.5 - Math.random()).join('');
}
}
don't forget to add the service on the module your using
@NgModule({
imports: [
CommonModule,
SharedModule,
CommonModule,
RouterModule.forChild(routes),
FormsModule,
ReactiveFormsModule,
FlexLayoutModule,
TranslateModule,
ExistingUserDialogModule,
UserDocumentsUploadDialogModule
],
declarations: [
UserListComponent,
EditUserDialogComponent,
UserEditorComponent
],
entryComponents: [
EditUserDialogComponent
],
providers: [
AuthService,
PasswordGeneratorService
]
})
export class UsersModule {
}
On you controller add a method which calls the generate password method inside the service and set the result on the password field
constructor(
private passwordGenerator: PasswordGeneratorService,
)
get newPassword() {
return this.password.get('newPassword');
}
generatePassword() {
this.newPassword.setValue(this.passwordGenerator.generatePassword(8,true,true,true));
}
Upvotes: 0
Reputation: 289
Well, you can always use window.crypto object available in the recent version of browser.
Just need one line of code to get a random number:
let n = window.crypto.getRandomValues(new Uint32Array(1))[0];
It also helps to encrypt and decrypt data. More information at MDN Web docs - window.crypto.
Upvotes: 0
Reputation: 474
My Crypto based take on the problem. Using ES6 and omitting any browser feature checks. Any comments on security or performance?
const generatePassword = (
passwordLength = 12,
passwordChars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz',
) =>
[...window.crypto.getRandomValues(new Uint32Array(passwordLength))]
.map(x => passwordChars[x % passwordChars.length])
.join('');
Upvotes: 5
Reputation: 364
Secure password with one upperCase char.
let once = false;
let newPassword = Math.random().toString(36).substr(2, 8).split('').map((char) => {
if(!Number(char) && !once){
once = true;
return char.toUpperCase();
}
return char;
}).join('');
console.log(newPassword)
Upvotes: 0
Reputation: 25147
In case you need a password generated with at least 1 number, 1 upper case character, and 1 lower case character:
function generatePassword(passwordLength) {
var numberChars = "0123456789";
var upperChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
var lowerChars = "abcdefghijklmnopqrstuvwxyz";
var allChars = numberChars + upperChars + lowerChars;
var randPasswordArray = Array(passwordLength);
randPasswordArray[0] = numberChars;
randPasswordArray[1] = upperChars;
randPasswordArray[2] = lowerChars;
randPasswordArray = randPasswordArray.fill(allChars, 3);
return shuffleArray(randPasswordArray.map(function(x) { return x[Math.floor(Math.random() * x.length)] })).join('');
}
function shuffleArray(array) {
for (var i = array.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
}
alert(generatePassword(12));
Here's the fiddle if you want to play/test: http://jsfiddle.net/sJGW4/155/
Props to @mwag for giving me the start to create this.
Upvotes: 13
Reputation: 1258
There is a random password string generator with selected length
let input = document.querySelector("textarea");
let button = document.querySelector("button");
let length = document.querySelector("input");
function generatePassword(n)
{
let pwd = "";
while(!pwd || pwd.length < n)
{
pwd += Math.random().toString(36).slice(-22);
}
return pwd.substring(0, n);
}
button.addEventListener("click", function()
{
input.value = generatePassword(length.value);
});
<div>password:</div>
<div><textarea cols="70" rows="10"></textarea></div>
<div>length:</div>
<div><input type="number" value="200"></div>
<br>
<button>gen</button>
Upvotes: -2
Reputation: 4815
I wouldn't recommend using a forced password as it restricts the User's Security but any way, there are a few ways of doing it -
Math.random().toString(36).slice(-8);
Install random string:
npm install randomstring
Using it in App.js -
var randStr = require('randomstring');
var yourString = randStr.generate(8);
The Value of your password is being hold in the variable yourString
.
Forced Password can harm your security as all the passwords would be under the same character set, which might easily be breached!
Upvotes: 2
Reputation: 2000
And finally, without using floating point hacks:
function genpasswd(n) {
// 36 ** 11 > Number.MAX_SAFE_INTEGER
if (n > 10)
throw new Error('Too big n for this function');
var x = "0000000000" + Math.floor(Number.MAX_SAFE_INTEGER * Math.random()).toString(36);
return x.slice(-n);
}
Upvotes: 0
Reputation: 349112
Forcing a fixed number of characters is a bad idea. It doesn't improve the quality of the password. Worse, it reduces the number of possible passwords, so that hacking by bruteforcing becomes easier.
To generate a random word consisting of alphanumeric characters, use:
var randomstring = Math.random().toString(36).slice(-8);
Math.random() // Generate random number, eg: 0.123456
.toString(36) // Convert to base-36 : "0.4fzyo82mvyr"
.slice(-8);// Cut off last 8 characters : "yo82mvyr"
Documentation for the Number.prototype.toString
and string.prototype.slice
methods.
Upvotes: 404
Reputation: 59
I have written a small one inspired from your answer:
(function(){g=function(){c='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';p='';for(i=0;i<8;i++){p+=c.charAt(Math.floor(Math.random()*62));}return p;};p=g();while(!/[A-Z]/.test(p)||!/[0-9]/.test(p)||!/[a-z]/.test(p)){p=g();}return p;})()
This function returns the password and can be used in bookmarklet like:
javascript:alert(TheCodeOfTheFunction);
Upvotes: 5
Reputation:
var letters = ['a','b','c','d','e','f','g','h','i','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'];
var numbers = [0,1,2,3,4,5,6,7,8,9];
var randomstring = '';
for(var i=0;i<5;i++){
var rlet = Math.floor(Math.random()*letters.length);
randomstring += letters[rlet];
}
for(var i=0;i<3;i++){
var rnum = Math.floor(Math.random()*numbers.length);
randomstring += numbers[rnum];
}
alert(randomstring);
Upvotes: 1
Reputation: 4562
This isn't exactly optimized, but it should work.
var chars = "ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz";
var string_length = 8;
var randomstring = '';
var charCount = 0;
var numCount = 0;
for (var i=0; i<string_length; i++) {
// If random bit is 0, there are less than 3 digits already saved, and there are not already 5 characters saved, generate a numeric value.
if((Math.floor(Math.random() * 2) == 0) && numCount < 3 || charCount >= 5) {
var rnum = Math.floor(Math.random() * 10);
randomstring += rnum;
numCount += 1;
} else {
// If any of the above criteria fail, go ahead and generate an alpha character from the chars string
var rnum = Math.floor(Math.random() * chars.length);
randomstring += chars.substring(rnum,rnum+1);
charCount += 1;
}
}
alert(randomstring);
Here's a jsfiddle for you to test on: http://jsfiddle.net/sJGW4/3/
Upvotes: 7