While fixing MakeSGuid I tested BCryptGenRandom
and found it’s straightforward to use in Clarion for generating cryptographically secure random numbers.
Clarion’s built-in RANDOM
function uses a simple pseudo-random algorithm that can produce predictable patterns, particularly problematic in multithreaded applications where multiple threads might generate similar sequences.
Since a LONG
is 4 bytes, we can easily use BCryptGenRandom
to fill those bytes with cryptographic-quality random data to get a random integer, and then scale the integer to a specific range, like Clarion:
!!! <summary>
!!! Returns a cryptographically secure random integer.
!!! </summary>
!!! <param name="low">A numeric constant, variable, or expression for the lower boundary of the range.</param>
!!! <param name="high">A numeric constant, variable, or expression for the upper boundary of the range.</param>
!!! <returns>A random LONG integer between the low and high values, inclusively.</returns>
cRandom PROCEDURE(LONG low, LONG high)!,LONG
randomData STRING(4),AUTO
randomLong LONG,OVER(randomData)
range LONG,AUTO
CODE
BCryptGenRandom(0,randomData,4,BCRYPT_USE_SYSTEM_PREFERRED_RNG) !Get 4 cryptographic random bytes
range = high - low + 1
randomLong %= range
randomLong += low
RETURN randomLong
Performance testing shows cRandom
is approximately 24 times slower than RANDOM
, making it useful for scenarios where random distribution is more important than speed.
The complete code and test project are available on GitHub. To integrate into your application:
- Copy
bcryptrandom.lib
toaccessory\lib
or your app folder - Copy
cRandom.inc
andcRandom.clw
toaccessory\libsrc\win
or your app folder. - Add
INCLUDE('cRandom.inc'),ONCE
to your global map