A cryptographic version of RANDOM()

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:

  1. Copy bcryptrandom.lib to accessory\lib or your app folder
  2. Copy cRandom.inc and cRandom.clw to accessory\libsrc\win or your app folder.
  3. Add INCLUDE('cRandom.inc'),ONCE to your global map
6 Likes