Generate random password based on user input in Javascript - javascript

The assignment is to prompt for length of the password and character type from the user, then generate a random password. I think the for loop isn't working correctly. The retVal is returned empty because the for loop isn't passing it anything. I tried removing the charAt function and having the Math.floor give me just and index, that just gave me undefinedundefinedundefinedundefinedundefinedundefined. Back with the regular charAt function I'm getting nothing.
//ask for length
var length = prompt("How many characters will your password be? Enter a number between 8 and 128");
//ask for character type
var charType = prompt("Enter a character type: special, numeric, uppercase, lowercase.");
//generate password
function generatePassword() {
//evaluate character type
var charSet = "";
if( charType.toLowerCase === "lowercase" ) {
charSet = "abcdefghijklmnopqrstuvwxyz";
} else if( charType.toLowerCase === "uppercase" ) {
charSet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
} else if( charType.toLowerCase === "numeric" ) {
charSet = "0123456789";
} else if( charType.toLowerCase === "special" ) {
charSet = " !\"#$%&'()*+,-./:;<=>?#[\]^_`{|}~";
}
//return value
var retVal = "";
//for (var i = 0, n = charSet.length; i < length; i++) {
for (var i = 0, n = length; i < length; i++) {
//picks a character within charSet at index of random number
retVal += charSet.charAt(Math.floor(Math.random() * n));
}
console.log(retVal);
return retVal;
}

There are a couple of subtle issues you are having.
prompt returns a string, you will need to cast it to a number to use it for your length (Number(prompt(...))).
The string toLowerCase is a method, not a property, you have to call it (charType.toLowerCase()). You also only need to do this once, if you set it to a variable you can avoid re-computing it.
You want a random character in the full charset range, not the password length (using charSet.length).
var length = Number(prompt("How many characters will your password be? Enter a number between 8 and 128"));
//ask for character type
var charType = prompt("Enter a character type: special, numeric, uppercase, lowercase.");
//generate password
function generatePassword() {
//evaluate character type
var charSet = "";
var charTypeLower = charType.toLowerCase();
if( charTypeLower === "lowercase" ) {
charSet = "abcdefghijklmnopqrstuvwxyz";
} else if( charTypeLower === "uppercase" ) {
charSet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
} else if( charTypeLower === "numeric" ) {
charSet = "0123456789";
} else if( charTypeLower === "special" ) {
charSet = " !\"#$%&'()*+,-./:;<=>?#[\]^_`{|}~";
}
//return value
var retVal = "";
for (var i = 0; i < length; i++) {
//picks a character within charSet at index of random number
retVal += charSet.charAt(Math.floor(Math.random() * charSet.length));
}
return retVal;
}
alert(generatePassword());
Side Note:
I'm guessing this is just for learning purposes, but if you want to generate cryptographically secure passwords you should use a random number generator based on crypto.getRandomValues (see this question).

charType.toLowerCase is a function, what you want is
charType.toLowerCase(), which is the result of the function.

Related

The output of my password generator is less than desired

I'm trying to make a password generator for a coding bootcamp but I'm running into an issue that has 2 outcomes both of which aren't desired. The HTML is very basic and I'm supposed to use prompts for the selection. I included my code but took out a few unnecessary things, the other 14 if-else statements, and a few variables. I'm turning in the project with the ugly formatting and spaces but still would like to know where I went wrong. The two outcomes are
The selections won't be unique and instead use the same character over and over
It comes out looking sloppy and adds spaces into it
function randomLower() {
return String.fromCharCode(Math.floor(Math.random() * 26) + 97);
}
//random uppercase from character code
function randomUpper() {
return String.fromCharCode(Math.floor(Math.random() * 26) + 65);
}
//random number from character code
function randomNumber() {
return String.fromCharCode(Math.floor(Math.random() * 10) + 48);
}
// random symbol from character code
function randomSymbol() {
let symbol = "!##$%^&*()_-><[]}{";
return symbol[Math.floor(Math.random() * symbol.length)];
}
// Get references to the #generate element
var generateBtn = document.querySelector("#generate");
// Write password to the #password input
function writePassword() {
var password = generatePassword();
var passwordText = document.querySelector("#password");
passwordText.value = password;
}
// Add event listener to generate button
generateBtn.addEventListener("click", writePassword);
// function for generatePassword
function generatePassword() {
//Confirms # of characters needed
click = parseInt(prompt("How many characters?", "8-128"));
if (!click) {
alert("Input is needed");
//Ensures the character count isn't too high or low
} else if (click < 8 || click > 128) {
click = parseInt(prompt("Answer must be between 8 and 128"));
} else {
//The procedding few lines will confirm other variables
useNumbers = confirm("Include numbers?");
useLower = confirm("Include lowercase letters?");
useUpper = confirm("Include uppercase letters?");
useSymbol = confirm("Include special characters?");
}
//If all prompts are denied
if (!useLower && !useUpper && !useNumbers && !useSymbol) {
choices = alert("At least one option is needed");
//If all prompts are accepted
} else if (useLower && useUpper && useNumbers && useSymbol) {
choices = randomLower().concat(randomUpper, randomNumber, randomSymbol);
//code only makes repeating characters
//choices = randomLower().concat(randomUpper(), randomNumber(), randomSymbol())
//placeholder for an array for user choices
var pWord = [];
//for loop to randomize selection
for (let i = 0; i < click; i++) {
var selected = choices[Math.floor(Math.random() * choices.length)];
pWord.push(selected);
}
//.join will take all choices in the array pWord and turns it into a string
var pass = pWord.join("");
UserInput(pass);
return pass;
}
// This puts the new password into the textbox
function UserInput(pass) {
document.getElementById("password").value = pass;
}
You only set choices if the user selects all the options.
When you set choices, you don't call the functions in the arguments to concat(). So you're concatenating the function definitions, not the random letters returned by the functions.
Even if you fix that to call the functions, you'll just get 4 characters. You need to call the randomXXX functions in the loop that generates each character.
In my code I've made choices an array of functions, not characters. I add each function to the array conditionally from the prompts. Then the loop picks a random function first, and calls it to get a random character of that type.
// function for generatePassword
function generatePassword() {
//Confirms # of characters needed
let click = parseInt(prompt("How many characters?", "8-128"));
let choices = [];
if (!click) {
alert("Input is needed");
//Ensures the character count isn't too high or low
} else if (click < 8 || click > 128) {
click = parseInt(prompt("Answer must be between 8 and 128"));
} else {
//The procedding few lines will confirm other variables
if (confirm("Include numbers?")) {
choices.push(randomNumber);
}
if (confirm("Include lowercase letters?")) {
choices.push(randomLower);
}
if (confirm("Include uppercase letters?")) {
choices.push(randomUpper);
}
if (confirm("Include special characters?")) {
choices.push(randomSymbol);
}
}
//If all prompts are denied
if (choices.length == 0) {
alert("At least one option is needed");
return;
}
//placeholder for an array for user choices
var pWord = [];
//for loop to randomize selection
for (let i = 0; i < click; i++) {
let selected = choices[Math.floor(Math.random() * choices.length)];
pWord.push(selected());
}
//.join will take all choices in the array pWord and turns it into a string
var pass = pWord.join("");
return pass;
}
console.log(generatePassword());
function randomLower() {
return String.fromCharCode(Math.floor(Math.random() * 26) + 97);
}
//random uppercase from character code
function randomUpper() {
return String.fromCharCode(Math.floor(Math.random() * 26) + 65);
}
//random number from character code
function randomNumber() {
return String.fromCharCode(Math.floor(Math.random() * 10) + 48);
}
// random symbol from character code
function randomSymbol() {
let symbol = "!##$%^&*()_-><[]}{";
return symbol[Math.floor(Math.random() * symbol.length)];
}
Im writing the same pattren as per passwords generators website. you can add this javascript in your html. You can generate random alphanumeric strings in JavaScript using the following code:
function generateRandomString(length) {
var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz";
var string_length = 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);
}
return randomstring;
}

Random password generator with prompts [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I'm working on an assignment that requires prompts asking for password length and character type and I have two issues:
a) The prompts aren't showing up
b) I cant seem to put the password in my display box. Here is my code:
var length = Number(prompt("How many characters will your password be? Enter a number between 8 and 128"));
//ask for character type
var charType = prompt("Enter a character type: special, numeric, uppercase, lowercase.");
//generate password
function generatePassword() {
//evaluate character type
var charSet = "";
var charTypeLower = charType.toLowerCase();
if (charTypeLower === "lowercase") {
charSet = "abcdefghijklmnopqrstuvwxyz";
} else if (charTypeLower === "uppercase") {
charSet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
} else if (charTypeLower === "numeric") {
charSet = "0123456789";
} else if (charTypeLower === "special") {
charSet = " !\"#$%&'()*+,-./:;<=>?#[\]^_`{|}~";
}
//return value
var retVal = "";
for (var i = 0; i < length; i++) {
//picks a character within charSet at index of random number
retVal += charSet.charAt(Math.floor(Math.random() * charSet.length));
}
return retVal;
}
alert(generatePassword());
}
//make password appear in display box
document.getElementById("display").value = password;
//function to copy password to clipboard
function copyPassword() {
document.getElementById("display").select();
document.execCommand("Copy");
alert("Password copied to clipboard!");
You had a } after your alert, which was throwing an error and preventing the prompts from showing. I applied some other fixes as well:
var length = Number(prompt("Enter a password length between 8 and 128")),
charType = prompt("Enter a character type: special, numeric, uppercase, lowercase."),
password = generatePassword();
document.getElementById("display").value = password;
document.getElementById('copy-btn').addEventListener('click', copyPassword);
function generatePassword() {
var charSets = {
lowercase: 'abcdefghijklmnopqrstuvwxyz',
uppercase: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
numeric: '0123456789',
special: ' !"#$%&\'()*+,-./:;<=>?#[\\]^_`{|}~'
};
var charSet = charSets[charType.toLowerCase()] || charSets.lowercase;
var retVal = "";
for (var i = 0; i < length; i++) {
retVal += charSet.charAt(Math.floor(Math.random() * charSet.length));
}
return retVal;
}
function copyPassword() {
document.getElementById("display").select();
document.execCommand("Copy");
alert("Password copied to clipboard!");
}
<input id="display"> <button id="copy-btn">Copy</button>

for loop string each word

if this type character '這' = NonEnglish each will take up 2 word space, and English will take up 1 word space, Max length limit is 10 word space; How to get the first 10 space.
for below example how to get the result This這 is?
I'm trying to use for loop from first word but I don't know how to get each word in string...
string = "This這 is是 English中文 …";
var NonEnglish = "[^\u0000-\u0080]+",
Pattern = new RegExp(NonEnglish),
MaxLength = 10,
Ratio = 2;
If you mean you want to get that part of the string where it's length has reached 10, here's the answer:
var string = "This這 is是 English中文 …";
function check(string){
// Length of A-Za-z characters is 1, and other characters which OP wants is 2
var length = i = 0, len = string.length;
// you can iterate over strings just as like arrays
for(;i < len; i++){
// if the character is what the OP wants, add 2, else 1
length += /\u0000-\u0080/.test(string[i]) ? 2 : 1;
// if length is >= 10, come out of loop
if(length >= 10) break;
}
// return string from the first letter till the index where we aborted the for loop
return string.substr(0, i);
}
alert(check(string));
Live Demo
EDIT 1:
Replaced .match with .test. The former returns a whole array while the latter simply returns true or false.
Improved RegEx. Since we are checking only one character, no need for ^ and + that were before.
Replaced len with string.length. Here's why.
I'd suggest something along the following lines (assuming that you're trying to break the string up into snippets that are <= 10 bytes in length):
string = "This這 is是 English中文 …";
function byteCount(text) {
//get the number of bytes consumed by a string
return encodeURI(text).split(/%..|./).length - 1;
}
function tokenize(text, targetLen) {
//break a string up into snippets that are <= to our target length
var result = [];
var pos = 0;
var current = "";
while (pos < text.length) {
var next = current + text.charAt(pos);
if (byteCount(next) > targetLen) {
result.push(current);
current = "";
pos--;
}
else if (byteCount(next) == targetLen) {
result.push(next);
current = "";
}
else {
current = next;
}
pos++;
}
if (current != "") {
result.push(current);
}
return result;
};
console.log(tokenize(string, 10));
http://jsfiddle.net/5pc6L/

pass $` value to associated parameter function of replace

I have an expression say
log(1,3)+4,5+max(7,8,9)
where comma is being used two ways.
1- In "log(1,3)+4,5" comma is being used in place of dot(.) or decimal sign.i.e. "log(1,3)+4,5" is equivalent to "log(1.3)+4.5".
2- In max(7,8,9) it is being used as number separator. i.e. this outcome of this is 9 ; the maximum number.
My problem is to substitute comma; which is being used as decimal separator; with decimal but this should not affect max(7,8,9). i.e. I need to convert above expression to
log(1.3)+4.5+max(7,8,9)
What I tried-
function substitute(expr) {
expr.replace(/,/g, function ($`) {
/*some processing here to decide whether comma to be substituted with dot or not.On that basis I will return either dot or comma.*/
}
But how can I pass $` value to associated function
or
Is it possible to do this in javascript.
expr.replace(/,/g,function ($`) {
if yes then how?
Your language is ambiguous.
max(8,1,8,2)
Does this return 8, 8,1 or 8,2?
Your language also doesn't look regular, so you can't parse it with a regular expression, you need the context. If something like this is allowed:
max(1,max(2,3)) // 3?
Assuming you can get rid of the ambiguity, you could write a parser to do the context detection.
This could be a solution :
function myFilter(string) {
// save all functions and signs
var functions = [];
var regExp = /[+,-]max\(([^\)]+)\)/;
matches = true;
while (matches !== null) {
var matches = regExp.exec(string);
if (matches !== null) {
functions.push(matches[0]);
string = string.replace(matches[0], '');
}
}
// replace all remaining commas with dots
string = string.replace(/,/g , ".");
for (i in functions) {
string += functions[i];
}
return string;
}
var s = '1,3+4,5+max(7,8,9)-max(2,3,5)';
var filteredString = myFilter(s);
jsFiddle Demo
This currently works with multiple max functions but only + and - signs. It could be improved with *, / and more... You will have to find the good regex.
Try the below using Javascript. Hope this helps you in logic.
DEMO HERE
var value = "log(1,3)-4,5+max(7,8,9)";
var val = '';
var splitValue, appendSym;
if (value.indexOf("+") != -1)
{
splitValue = value.split("+");
appendSym = "+";
}
else if(value.indexOf("-") != -1)
{
splitValue = value.split("-");
appendSym = "-";
}
else if(value.indexOf("*") != -1)
{
splitValue = value.split("*");
appendSym = "*";
}
else
{
splitValue = value.split("/");
appendSym = "/";
}
var length = splitValue.length;
for (var i = 0; i < length; i++) {
if (val) val += appendSym;
var strrep = splitValue[i].replace(/,/g,".");
if (splitValue[i].indexOf("max") != -1 || splitValue[i].indexOf("min") != -1)
{
val+=splitValue[i];
}
else
{
val+=strrep;
}
}
alert(val);
The output for the above code is log(1.3)-4.5+max(7,8,9)

JavaScript regexp?

This is the regexp:
$("#newpassword").keyup(function(e) {
var htm = "";
var pass = this.value;
var length = this.value.length;
if (pass) {
var score = 0;
if(length >= 8 && length <= 16) { //PASSWORD MIN/MAX NUMBER OF CHARACTERS
var upper = /[A-Z]/;
var lower = /[a-z]/;
var number = /^[0-9]+$/; //PATTERN FOR NUMBERS
var schar = /[!##$%^&*?_~+-=<>]/;
//LOOPS THROUGH PASSWORD TO CHECK FOR AT LEAST ONE OF EACH PATTERN
for (i = 0; i < length; i++) {
if (pass.substr(i, 1).match(upper)) {
var uletters = true;
score ++;
//AT LEAST ONE LETTER EXISTS
}
if(pass.substr(i,1).match(lower)) {
var lletters = true;
score++;
//AT LEAST ONE LETTER EXISTS
}
if(pass.substr(i,1).match(schar)) {
var schar = true;
score++;
}
if(pass.substr(i, 1).match(number)) {
var numbers = true;
var schar = false;
//AT LEAST ONE NUMBER EXISTS
score++;
}
}
}
}
});
The any two condition is true means password is ok, but the above code if(numbers == true && schar == true) user type only number display password ok.
Please help me what is the problem in my code.
You don't need to iterate over each character of your password, just do the following:
score += upper.test(password)?1:0;
score += lower.test(password)?1:0;
score += number.test(password)?1:0;
score += schar.test(password)?1:0;
(test returns true or false) and check the score afterwards.
In general it's recommendable not to be too restrictive about the users password. It seriously harms the user experience if they are told to how their password should look like. You can make it a recommendation though. (E.g. display a bar: weak (red) - strong (green) password. This is much more motivating than harassing the user with any error messages.) Let them pass on score 2 and higher.
You can probably use RegExp.test() or RegExp.exec() to "find" a regex match within your string, rather than iterating the characters yourself.
function validatePwd (pwd) {
if (pwd.length < 8)
return false;
if (pwd.length > 16)
return false;
var upperPatt = /[A-Z]/;
var lowerPatt = /[a-z]/;
var numberPatt = /[0-9]/; // FIXED -- this is a better pattern for numbers.
var scharPatt = /[!##$%^&*?_~+-=<>]/;
score = 0;
if (upperPatt.test( pwd))
score++;
if (lowerPatt.test( pwd))
score++;
if (numberPatt.test( pwd))
score++;
if (specialPatt.test( pwd))
score++;
// don't make it too hard for the poor user, please..
// -- they have to type all this horrible rubbish.
if (score < 3) {
return false;
}
// OK.
return true;
}

Categories