Skip to content

Commit 3271f28

Browse files
committed
* Fixed ChaCha20 could only generate 256 different seeds for number seed values.
* Added `chacha20NumberSeedLegacyBehaviour` to restore the legacy behaviour (`false` by default)
1 parent 5a2fd7e commit 3271f28

2 files changed

Lines changed: 12 additions & 6 deletions

File tree

src/interpreter/lib/math.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ export const stdMath: Record<`Math:${string}`, Value> = {
228228
}
229229
case 'chacha20': {
230230
if (!isSecureContext) throw new AiScriptRuntimeError(`The random algorithm ${algo} cannot be used because \`crypto.subtle\` is not available. Maybe in non-secure context?`);
231-
return await GenerateChaCha20Random(seed);
231+
return await GenerateChaCha20Random(seed, options?.value);
232232
}
233233
default:
234234
throw new AiScriptRuntimeError('`options.algorithm` must be one of these: `chacha20`, `rc4`, or `rc4_legacy`.');

src/utils/random/genrng.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { FN_NATIVE, NULL, NUM } from '../../interpreter/value.js';
33
import { textEncoder } from '../../const.js';
44
import { SeedRandomWrapper } from './seedrandom.js';
55
import { ChaCha20 } from './chacha20.js';
6-
import type { VNativeFn, VNum, VStr } from '../../interpreter/value.js';
6+
import type { Value, VNativeFn, VNum, VStr } from '../../interpreter/value.js';
77

88
export function GenerateLegacyRandom(seed: VNum | VStr): VNativeFn {
99
const rng = seedrandom(seed.value.toString());
@@ -26,11 +26,17 @@ export function GenerateRC4Random(seed: VNum | VStr): VNativeFn {
2626
});
2727
}
2828

29-
export async function GenerateChaCha20Random(seed: VNum | VStr): Promise<VNativeFn> {
29+
export async function GenerateChaCha20Random(seed: VNum | VStr, options: Map<string, Value> | undefined): Promise<VNativeFn> {
3030
let actualSeed: Uint8Array;
31-
if (seed.type === 'num')
32-
{
33-
actualSeed = new Uint8Array(await crypto.subtle.digest('SHA-384', new Uint8Array(new Float64Array([seed.value]))));
31+
if (seed.type === 'num') {
32+
let float64Array = new Float64Array([seed.value]);
33+
let numberAsIntegerOptionValue = options?.get("chacha20NumberSeedLegacyBehaviour");
34+
let numberAsInteger = false;
35+
if (numberAsIntegerOptionValue?.type === "bool") {
36+
numberAsInteger = numberAsIntegerOptionValue.value;
37+
}
38+
let seedToDigest = numberAsInteger ? new Uint8Array(float64Array) : new Uint8Array(float64Array.buffer);
39+
actualSeed = new Uint8Array(await crypto.subtle.digest('SHA-384', seedToDigest));
3440
} else {
3541
actualSeed = new Uint8Array(await crypto.subtle.digest('SHA-384', new Uint8Array(textEncoder.encode(seed.value))));
3642
}

0 commit comments

Comments
 (0)