I have this function to generate a random password.
My question is How do I ensure that a selected range of letters/sign/numbers is included in the result?
As an example, if I select that there must be numbers or signs in the result string, how do I check if there is at least one number or sign in the result. I have toughed about looping through numbers or signs for each member of the result, and then break the loop if I meet a character I am testing for.
The code snippet works, but without validating the result
function generatePassword() {
var base = "";
var result = "";
var latinLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
var cyrillicLetters = "БбВвГгДдЕеЖжЗзИиЙйКкЛлМмНнОоПпРрСсТтУуФфХхЦцЧчШшЩщЬьЮюЯя"
var greekLetters = "ΑαΒβΓγΔδΕεΖζΗηΘθΙιΚκΛλΜμΝνΞξΟοΠπΡρΣσςΤτΥυΦφΧχΨψΩω"
var numbersLetters = "1234567890"
var signsLetters = "/|()1{}[]?-_ ~<>!I;:,^`.$@B%&WM*"
var armenianLetters = "աբգդեզէըթժիլխծկհձղճմյնշոչպջռսվտրցւփքօֆուև"
var hangulLetters = "ㄱㄴㄷㄹㅁㅂㅅㅇㅈㅊㅋㅌㅍㅎㅏㅑㅓㅕㅗㅛㅜㅠㅡㅣ"
var nordicLetters = "AaÁáBbCcDdÐðEeÉéFfGgHhIiÍíJjKkLlMmNnOoÓóPpRrSsTtUuÚúVvWwXxYyÝýZzÞþÆæÖöZzÄäØøÅå"
var arabicLetters = "ءي و ه ن م لك ق ف غ ع ظ ط ض ص ش س ز ر ذ د خ ح ج ث ت ب ا"
var georgianLetters = "აბგდევზთიკლმნოპჟრსტუფქღყშჩცძწჭხჯჰ"
var ethiopianLetters = "ሀለሐመሠረሰቀበተኀነአከወዐዘየደገጠጸፀፈጰፐ"
var thaanaLetters = "ހށނރބޅކއވމފދތލގސޑޒޓޔޕޖޗޘޙޚޛޜޝޞޟޠޡޢޣޤޥަ ީ ު ޫ ެ ޭ ޮ ޯޱ"
var hanziLetters = "ぁあぃいぅうぇえぉおかがきぎくぐけげこごさざしじすずせぜそぞただちぢっつづてでとどなにぬねのはばぱひびぴふぶぷへべぺほぼぽまみむめもゃやゅゆょよらりるれろゎわゐゑをんゔゕゖ ゙ ゛゜ゝゞゟ"
// input
var length = document.getElementById('pwLength').value
var latin = document.getElementById('latinChecked')
var numbers = document.getElementById('numbersChecked')
var signs = document.getElementById('signsChecked')
var nordic = document.getElementById('nordicChecked')
var cyrillic = document.getElementById('cyrillicChecked')
var greek = document.getElementById('greekChecked')
var armenian = document.getElementById('armenianChecked')
var hangul = document.getElementById('hangulChecked')
var arabic = document.getElementById('arabicChecked')
var georgian = document.getElementById('georgianChecked')
var ethiopian = document.getElementById('ethiopianChecked')
var thaana = document.getElementById('thaanaChecked')
var hanzi = document.getElementById('hanziChecked')
// build source string
if (arabic.checked) { base = base arabicLetters; }
if (latin.checked) { base = base latinLetters; }
if (signs.checked) { base = base signsLetters; }
if (greek.checked) { base = base greekLetters; }
if (numbers.checked) { base = base numbersLetters; }
if (armenian.checked) { base = base armenianLetters; }
if (hangul.checked) { base = base hangulLetters; }
if (numbers.checked) { base = base numbersLetters; }
if (nordic.checked) { base = base nordicLetters; }
if (cyrillic.checked) { base = base cyrillicLetters; }
if (numbers.checked) { base = base numbersLetters; }
if (georgian.checked) { base = base georgianLetters; }
if (ethiopian.checked) { base = base ethiopianLetters; }
if (thaana.checked) { base = base thaanaLetters; }
if (hanzi.checked) { base = base hanziLetters; }
// fill result
for (let i = 0; i < length; i ) {
var rand = Math.floor(Math.random() * base.length);
result = result base.charAt(rand);
}
// write to html
document.getElementById("productX").innerHTML = result;
}
CodePudding user response:
You can use this process:
- Select exactly one random character from each character set that was selected
- Select the remaining needed characters from all available characters
- Concatenate all of the above and shuffle randomly
Here is an implementation:
// Some utility functions on Math.random
const randInt = end => Math.floor(Math.random() * end);
const randomOf = array => array[randInt(array.length)];
const sample = (array, count) => shuffle(array).slice(-count);
function shuffle(array) {
for (let i = array.length - 1; i > 0; i--) {
let j = randInt(i 1);
let temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
}
const groups = {
latin: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
cyrillic: "БбВвГгДдЕеЖжЗзИиЙйКкЛлМмНнОоПпРрСсТтУуФфХхЦцЧчШшЩщЬьЮюЯя",
greek: "ΑαΒβΓγΔδΕεΖζΗηΘθΙιΚκΛλΜμΝνΞξΟοΠπΡρΣσςΤτΥυΦφΧχΨψΩω",
numbers: "1234567890",
signs: "/|()1{}[]?-_ ~<>!I;:,^`.$@B%&WM*",
armenian: "աբգդեզէըթժիլխծկհձղճմյնշոչպջռսվտրցւփքօֆուև",
hangul: "ㄱㄴㄷㄹㅁㅂㅅㅇㅈㅊㅋㅌㅍㅎㅏㅑㅓㅕㅗㅛㅜㅠㅡㅣ",
nordic: "AaÁáBbCcDdÐðEeÉéFfGgHhIiÍíJjKkLlMmNnOoÓóPpRrSsTtUuÚúVvWwXxYyÝýZzÞþÆæÖöZzÄäØøÅå",
arabic: "ءي و ه ن م لك ق ف غ ع ظ ط ض ص ش س ز ر ذ د خ ح ج ث ت ب ا",
georgian: "აბგდევზთიკლმნოპჟრსტუფქღყშჩცძწჭხჯჰ",
ethiopian: "ሀለሐመሠረሰቀበተኀነአከወዐዘየደገጠጸፀፈጰፐ",
thaana: "ހށނރބޅކއވމފދތލގސޑޒޓޔޕޖޗޘޙޚޛޜޝޞޟޠޡޢޣޤޥަ ީ ު ޫ ެ ޭ ޮ ޯޱ",
hanzi: "ぁあぃいぅうぇえぉおかがきぎくぐけげこごさざしじすずせぜそぞただちぢっつづてでとどなにぬねのはばぱひびぴふぶぷへべぺほぼぽまみむめもゃやゅゆょよらりるれろゎわゐゑをんゔゕゖ ゙ ゛゜ゝゞゟ",
};
function generatePassword() {
const length = document.getElementById('pwLength').value;
// get selected character sets
const selected = Object.keys(groups).filter(group => document.getElementById(group "Checked").checked);
if (selected.length > length) throw "Required length incompatible with selection";
// Select one from each set, and take the rest from any in those sets. Then shuffle.
const result = shuffle([
...selected.map(group => randomOf(groups[group])),
...sample([...selected.map(group => groups[group]).join("")], length - selected.length)
]).join("");
// write to html
document.getElementById("productX").textContent = result;
}
document.getElementById("generate").addEventListener("click", generatePassword);
#pwLength { width: 4em }
#productX { font-family: monospace }
Length: <input id="pwLength" type="number" value="16">
<table><tr>
<td><input id="latinChecked" type="checkbox" checked>Latin</td>
<td><input id="cyrillicChecked" type="checkbox">Cyrillic</td>
<td><input id="greekChecked" type="checkbox">Greek</td>
<td><input id="numbersChecked" type="checkbox" checked>Numbers</td>
</tr><tr>
<td><input id="signsChecked" type="checkbox" checked>Signs</td>
<td><input id="armenianChecked" type="checkbox">Armenian</td>
<td><input id="hangulChecked" type="checkbox">Hangul</td>
</tr><tr>
<td><input id="nordicChecked" type="checkbox">Nordic</td>
<td><input id="arabicChecked" type="checkbox">Arabic</td>
<td><input id="georgianChecked" type="checkbox">Georgian</td>
</tr><tr>
<td><input id="ethiopianChecked" type="checkbox">Etheopian</td>
<td><input id="thaanaChecked" type="checkbox">Thaana</td>
<td><input id="hanziChecked" type="checkbox">Hanzi</td>
</tr></table>
<button id="generate">Generate password</button><br>
Password: <span id="productX"></span>