From d60543c2cb7ae2e8a6740e6c4b7e0215c8ef8761 Mon Sep 17 00:00:00 2001 From: R-Goc Date: Fri, 11 Apr 2025 22:12:04 +0200 Subject: [PATCH] LibJS/LibCrypto: Cleanup JS Math random() RNG This commit adds a convenience method to secure random for initializing single types. It changes the random number generator in JS math random() to use newer constants by the author as well as initializes it with a higher quality seed. --- Libraries/LibCrypto/SecureRandom.h | 8 ++++++++ Libraries/LibJS/Runtime/MathObject.cpp | 17 +++++++++++------ 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/Libraries/LibCrypto/SecureRandom.h b/Libraries/LibCrypto/SecureRandom.h index 9c03d7cafe2..76b37cd3642 100644 --- a/Libraries/LibCrypto/SecureRandom.h +++ b/Libraries/LibCrypto/SecureRandom.h @@ -12,4 +12,12 @@ namespace Crypto { void fill_with_secure_random(Bytes); +template +inline T get_secure_random() +{ + T t; + fill_with_secure_random({ &t, sizeof(T) }); + return t; +} + } diff --git a/Libraries/LibJS/Runtime/MathObject.cpp b/Libraries/LibJS/Runtime/MathObject.cpp index 55d4eb66d89..4e0452dbad3 100644 --- a/Libraries/LibJS/Runtime/MathObject.cpp +++ b/Libraries/LibJS/Runtime/MathObject.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -800,12 +801,15 @@ JS_DEFINE_NATIVE_FUNCTION(MathObject::pow) return pow_impl(vm, vm.argument(0), vm.argument(1)); } -class XorShift128PlusPlusRNG { +// http://vigna.di.unimi.it/ftp/papers/xorshiftplus.pdf +class XorShift128PlusRNG { public: - XorShift128PlusPlusRNG() + XorShift128PlusRNG() { - u64 seed = get_random(); + // Splitmix64 is used as xorshift is sensitive to being seeded with all 0s + u64 seed = Crypto::get_secure_random(); m_low = splitmix64(seed); + seed = Crypto::get_secure_random(); m_high = splitmix64(seed); } @@ -824,6 +828,7 @@ private: return z ^ (z >> 31); } + // Apparently this set of constants is better: https://stackoverflow.com/a/34432126 u64 advance() { u64 s1 = m_low; @@ -831,8 +836,8 @@ private: u64 const result = s0 + s1; m_low = s0; s1 ^= s1 << 23; - s1 ^= s1 >> 17; - s1 ^= s0 ^ (s0 >> 26); + s1 ^= s1 >> 18; + s1 ^= s0 ^ (s0 >> 5); m_high = s1; return result + s1; } @@ -846,7 +851,7 @@ Value MathObject::random_impl() // This function returns a Number value with positive sign, greater than or equal to +0𝔽 but strictly less than 1𝔽, // chosen randomly or pseudo randomly with approximately uniform distribution over that range, using an // implementation-defined algorithm or strategy. - static XorShift128PlusPlusRNG rng; + static XorShift128PlusRNG rng; return Value(rng.get()); }