az에서 5 개의 문자와 3 개의 숫자가 포함 된 임의의 문자열을 생성하고 싶습니다.
JavaScript로 어떻게 할 수 있습니까?
다음 스크립트가 있지만 내 요구 사항을 충족하지 않습니다.
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);
}
답변
고정 된 수의 문자를 강제하는 것은 나쁜 생각입니다. 암호의 품질은 향상되지 않습니다. 더 나쁜 것은 가능한 암호의 수를 줄여서 무차별 대입에 의한 해킹이 더 쉬워진다는 것입니다.
영숫자로 구성된 임의의 단어를 생성하려면 다음을 사용하십시오.
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"
Number.prototype.toString
및 string.prototype.slice
방법에 대한 문서입니다 .
답변
좀 더 유지 관리 가능하고 안전한 접근 방식입니다.
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)'>
답변
이 답변의 원본을 포함한 많은 답변은 OP의 문자 및 숫자 개수 요구 사항을 다루지 않습니다. 다음은 일반 (최소 문자 / 숫자 없음) 및 규칙 포함의 두 가지 솔루션입니다.
일반:
나는 이것이 위의 것보다 더 나은 일반적인 해결책이라고 생각합니다.
- 대소 문자를 구분하는 방식으로 모든 문자 집합을 지원하기 때문에 수락 / 가장 많이 득표 한 답변보다 더 안전하고 더 다양합니다.
- 다른 답변보다 간결합니다 (일반 솔루션의 경우 최대 3 줄, 한 줄로 가능)
- 네이티브 자바 스크립트 만 사용합니다. 설치 또는 기타 라이브러리가 필요하지 않습니다.
참고
- 이것이 IE에서 작동하려면 Array.fill () 프로토 타입을 폴리 필해야합니다.
- 가능한 경우 Math.random () 대신 window.crypto.getRandomValues ()를 사용하는 것이 좋습니다 (지시를 위해 @BenjaminH에게 감사드립니다)
3 행 :
var pwdChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
var pwdLen = 10;
var randPassword = Array(pwdLen).fill(pwdChars).map(function(x) { return x[Math.floor(Math.random() * x.length)] }).join('');
또는 한 줄로 :
var randPassword = Array(10).fill("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz").map(function(x) { return x[Math.floor(Math.random() * x.length)] }).join('');
문자 / 숫자 규칙 포함
이제 위의 변형입니다. 이것은 주어진 문자 세트 (문자, 숫자, 둘 중 하나)에서 3 개의 임의의 문자열을 생성 한 다음 결과를 스크램블합니다.
아래는 설명 목적으로 만 sort ()를 사용합니다. 프로덕션 용도로 아래 sort () 함수 를 Durstenfeld 와 같은 셔플 함수로 대체하십시오 .
첫째, 함수로서 :
function randPassword(letters, numbers, either) {
var chars = [
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", // letters
"0123456789", // numbers
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" // either
];
return [letters, numbers, either].map(function(len, i) {
return Array(len).fill(chars[i]).map(function(x) {
return x[Math.floor(Math.random() * x.length)];
}).join('');
}).concat().join('').split('').sort(function(){
return 0.5-Math.random();
}).join('')
}
// invoke like so: randPassword(5,3,2);
2 행과 똑같습니다 (분명히 매우 길고보기 흉한 선입니다. 적절한 셔플 기능을 사용하면 1 행이되지 않을 것입니다. 권장하지 않지만 때로는 재미 있습니다) :
var chars = ["ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz","0123456789", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"];
var randPwd = [5,3,2].map(function(len, i) { return Array(len).fill(chars[i]).map(function(x) { return x[Math.floor(Math.random() * x.length)] }).join('') }).concat().join('').split('').sort(function(){return 0.5-Math.random()}).join('');
답변
가장 간단한 스크립트를 찾고있는 사람을 위해. 아니요 while (true)
, 아니요 if/else
, 선언이 없습니다.
mwag의 대답에 자료, 그러나 이것은 사용 crypto.getRandomValues
,보다 강한 랜덤 Math.random
.
Array(20)
.fill('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz~!@-#$')
.map(x => x[Math.floor(crypto.getRandomValues(new Uint32Array(1))[0] / (0xffffffff + 1) * x.length)])
.join('');
참고 이를 위해 0xffffffff
.
대안 1
var generatePassword = (
length = 20,
wishlist = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz~!@-#$"
) => Array(length)
.fill('')
.map(() => wishlist[Math.floor(crypto.getRandomValues(new Uint32Array(1))[0] / (0xffffffff + 1) * wishlist.length)])
.join('');
console.log(generatePassword());
대안 2
var generatePassword = (
length = 20,
wishlist = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz~!@-#$'
) =>
Array.from(crypto.getRandomValues(new Uint32Array(length)))
.map((x) => wishlist[x % wishlist.length])
.join('')
console.log(generatePassword())
Node.js
const crypto = require('crypto')
const generatePassword = (
length = 20,
wishlist = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz~!@-#$'
) =>
Array.from(crypto.randomFillSync(new Uint32Array(length)))
.map((x) => wishlist[x % wishlist.length])
.join('')
console.log(generatePassword())
답변
이것은 정확히 최적화되어 있지는 않지만 작동합니다.
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);
다음은 테스트 할 jsfiddle입니다. http://jsfiddle.net/sJGW4/3/
답변
최소 1 개의 숫자, 1 개의 대문자, 1 개의 소문자로 생성 된 비밀번호가 필요한 경우 :
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));
플레이 / 테스트를 원한다면 여기 바이올린이 있습니다 : http://jsfiddle.net/sJGW4/155/
@mwag에 대한 소품으로 이것을 만들 수 있습니다.
답변
@RobW가 지적했듯이 OP 체계에서 제안한대로 암호를 고정 된 문자 수로 제한하는 것은 좋지 않습니다 . 그러나 더 나쁜 것은 코드를 기반으로 제안하는 답변 Math.random
은 정말 나쁜 생각 입니다.
나쁜 생각 부터 시작합시다 . OP 코드는 62 개의 집합에서 8 개의 문자열을 무작위로 선택합니다. 임의의 문자열을 5 개의 문자와 3 개의 숫자로 제한하면 결과 암호는 기껏 해야 28.5 비트의 엔트로피를 갖게됩니다 (잠재력 47.6 비트와 반대). 5 문자와 3 자리 숫자의 배포 제한이 제거 된 경우). 별로 좋지 않습니다. 그러나 현실적으로 상황은 더 나쁩니다. 최상의 코드 양상의 사용에 의해 파괴되는 Math.random
암호 엔트로피를 생성하는 수단. Math.random
A는 의사 난수 발생기 . 의사 난수 생성기의 결정 론적 특성으로 인해 결과 암호의 엔트로피가 매우 나쁩니다., 그러한 제안 된 솔루션은 정말 나쁜 생각을 렌더링합니다 . 이러한 암호가 최종 사용자에게 유출된다고 가정하면 (요점은 무엇입니까), 그러한 암호를 수신하는 적극적인 공격자는 다른 사용자에게 유출 될 향후 암호를 예측할 가능성이 매우 높으며 이는 아마도 좋은 일이 아닐 것입니다.
그러나 그냥 나쁜 생각으로 돌아갑니다 . 대신 암호화 된 강력한 의사 난수 생성기가 사용된다고 가정합니다 Math.random
. 암호를 28.5 비트로 제한하는 이유는 무엇입니까? 언급했듯이 그것은별로 좋지 않습니다. 아마도 5 개의 문자, 3 개의 숫자 체계는 사용자가 무작위로 할당 된 암호를 관리하는 데 도움을주기위한 것입니다. 그러나의 당신이 균형을 가지고, 그것을 직면하자 사용의 용이성 에 대한 사용 가치 , 그리고 엔트로피의 28.5 비트가 활성 적 방어에 많은 값이 아닙니다.
그러나 나쁜 것은 충분합니다. 앞으로 나아갈 길을 제안합시다. “다양한 문자 집합에서 지정된 엔트로피의 암호화 된 강력한 임의 문자열을 효율적으로 생성” 하는 JavaScript EntropyString 라이브러리를 사용할 것 입니다. OP 62 자보다는 쉽게 혼동되는 문자의 사용이나 영어 단어의 형성을 줄이기 위해 32 개의 문자를 선택한 문자 세트를 사용하겠습니다. 그리고 (엔트로피가 너무 적은) 5 글자 3 개 숫자 체계가 아니라 60 비트 엔트로피 (이것이 용이성과 가치의 균형)를 가질 것이라고 선언합니다.
import {Random, charSet32} from 'entropy-string'
const random = new Random(charSet32)
const string = random.string(60)
“Q7LfR8Jn7RDp”
의 인수 random.string
는 문자열 길이를 전달하는 것을 지정하는 임의의 문자열 생성에 대한보다 일반적으로 볼 수있는 솔루션과 달리 원하는 엔트로피 비트입니다 (이는 잘못 안내되고 일반적으로 지정되지 않았지만 다른 이야기입니다).
