Skip to content

Instantly share code, notes, and snippets.

@kawaz
Last active November 30, 2023 20:06
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kawaz/d625e27ae267389cd842834d0d9ac8b3 to your computer and use it in GitHub Desktop.
Save kawaz/d625e27ae267389cd842834d0d9ac8b3 to your computer and use it in GitHub Desktop.
ブラウザのJavascriptで暗号論的にセキュアな疑似乱数を使って指定範囲の整数の乱数を得る方法。
/**
* a以上b以下の整数の乱数を生成する
* @param {number|bigint} a
* @param {number|bigint} b
* @returns {number|bigint}
*/
function getRandomIntBetween(a, b) {
if (b < a) {
// [a, b] = [b, a]
const t = a; a = b; b = t;
}
if(typeof a === 'bigint' || typeof b === 'bigint') {
return getRandomBigUint64(b - a) + a
} else {
return getRandomUint(b - a) + a
}
}
/**
* 0以上max以下の整数の乱数を生成する
* @param {number|bigint} max
* @returns {number|bigint}
*/
function getRandomUint(max = 0xFFFFFFFF) {
if (max === 0xFFFFFFFF) {
return crypto.getRandomValues(new Uint32Array(1))[0]
}
if (max < 0xFFFFFFFF) {
const validMax = 0xFFFFFFFF - 0xFFFFFFFF % (max + 1)
while (true) {
const r = crypto.getRandomValues(new Uint32Array(8)).find(i => i <= validMax)
if (r !== undefined) {
return r % (max + 1)
}
}
}
if (typeof max == 'number') {
return Number(getRandomBigUint64(BigInt(max)))
}
return getRandomBigUint64(BigInt(max))
}
/**
* 0以上max以下の整数の乱数を生成する
* @param {bigint} max
* @returns {bigint}
*/
function getRandomBigUint64(max = 2n ** 64n - 1n) {
if (max === 2n ** 64n - 1n) {
return crypto.getRandomValues(new BigUint64Array(1))[0]
}
if (max < 2n ** 64n - 1n) {
const validMax = (2n ** 64n - 1n) - (2n ** 64n - 1n) % (max + 1n)
while (true) {
const r = crypto.getRandomValues(new BigUint64Array(8)).find(i => i <= validMax)
if (r !== undefined) {
return r % (max + 1n)
}
}
}
}
// ランダム英数文字列を取得
function getRandomAN(length=20) {
return btoa(String.fromCharCode.apply(null,crypto.getRandomValues(new Uint8Array(length*2)))).replace(/[^a-zA-Z0-9]/g,"").substring(0,length);
}
@kawaz
Copy link
Author

kawaz commented Sep 5, 2021

ブラウザが対応してないならしゃーない。

// crypto.getRandomValues が使えないなら諦めて Math.random にフォールバックする
if(!window.crypto || !typeof window.crypto.getRandomValues === 'function') {
    function getRandomUint(max) {
        return Math.floor(Math.random(max + 1))
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment