В порядке, я думаю, ваши лучшие ставки следующие:
- window.crypto.getRandomValues или window.msCrypto.getRandomValues
- Функция randomWords библиотеки sjcl (* 1007)* Генератор случайных чисел библиотеки isaac (который заполняется Math.random, поэтому не особо криптографически защищен) (https://github.com/rubycon/isaac.js)
window.crypto.getRandomValues был реализован в Chrome дляв настоящее время, а также относительно недавно в Firefox. К сожалению, Internet Explorer 10 и более ранние версии не реализуют эту функцию. В IE 11 есть window.msCrypto, который выполняет то же самое. У sjcl есть отличный генератор случайных чисел, созданный из движений мыши, новсегда есть вероятность, что либо мышь не будет двигаться достаточно для посева генератора, либо пользователь находится на мобильном устройстве, где нет движения мыши, поэтому я рекомендую использовать запасной вариант, в котором вы все еще можете получитьнебезопасное случайное число, если нет выбора. Вот как я справляюсьсделайте так:
function GetRandomWords (wordCount) {
var randomWords;
// First we're going to try to use a built-in CSPRNG
if (window.crypto && window.crypto.getRandomValues) {
randomWords = new Int32Array(wordCount);
window.crypto.getRandomValues(randomWords);
}
// Because of course IE calls it msCrypto instead of being standard
else if (window.msCrypto && window.msCrypto.getRandomValues) {
randomWords = new Int32Array(wordCount);
window.msCrypto.getRandomValues(randomWords);
}
// So, no built-in functionality - bummer. If the user has wiggled the mouse enough,
// sjcl might help us out here
else if (sjcl.random.isReady()) {
randomWords = sjcl.random.randomWords(wordCount);
}
// Last resort - we'll use isaac.js to get a random number. It's seeded from Math.random(),
// so this isn't ideal, but it'll still greatly increase the space of guesses a hacker would
// have to make to crack the password.
else {
randomWords = [];
for (var i = 0; i < wordCount; i++) {
randomWords.push(isaac.rand());
}
}
return randomWords;
};
Для этой реализации вам нужно будет включить sjcl.js и isaac.js, и обязательно запустите сборщик энтропии sjcl, как только ваша страница загрузится:
sjcl.random.startCollectors();
sjcl - это BSD и GPL с двойной лицензией, тогда как isaac.js - это MIT, поэтому совершенно безопасно использовать любой из них в любом проекте.Как упоминалось в другом ответе, clipperz - это еще один вариант, однако по какой-то причудливой причине он лицензируется в соответствии с AGPL.Я еще не видел никого, кто, по-видимому, понимает, какое значение это имеет для библиотеки JavaScript, но я бы универсально избегал этого.
Один из способов улучшить код, который я разместил, может состоять в сохранении состояниягенератор случайных чисел isaac в localStorage, поэтому он не перезапускается при каждой загрузке страницы.Исаак сгенерирует случайную последовательность, но для целей криптографии семя очень важно.Заполнение с помощью Math.random - это плохо, но, по крайней мере, немного менее плохо, если это не обязательно при каждой загрузке страницы.