Better RandomizeSeed

Working with a Random object, if I set the Seed to a known value, I will get the same stream of numbers. It turns out that that’s also true if I use RandomizeSeed after setting Seed. So, for example:

  dim r as new Random
  r.Seed = 0.123
  
  dim arr() as double
  for i as integer = 1 to 10
    arr.Append r.Number
    r.RandomizeSeed()
  next i

Every time this code is run, arr will contain exactly the same values, so RandomizeSeed is not cryptographically secure.

Instead, I was thinking of doing something like this instead:

  dim arr() as double
  for i as integer = 1 to 10
    arr.Append r.Number
    r.Seed = Crypto.GenerateRandomBytes( 8 ).Int64Value( 0 )
  next i

Would this be considered cryptographically secure?

(To clarify, I am setting the initial seed for testing purposes only.)

Use Microseconds for a Random seed. If you need cryptographically secure random numbers, ** presumably ** you will want to call Crypto.GenerateRandomBytes repeatedly and make sure you’re not biasing a portion of the range with “mod”.

I’d expect Microseconds in a tight loop would lead to the same numbers being repeated.

You only seed once.

Right, but that wouldn’t be cryptographically secure. What I’m looking for is a way to use Random where it it is cryptographically secure. I’m aware that I have alternatives.

I would avoid having Random in the mix. Get enough bytes from Crypto.GenerateRandomBytes that it doesn’t bias the range you want. If you use Random and the seed, you’re maxed out by the number of bytes in a double. Isn’t that 8? So you’re getting 64-bit encryption effectively (or less).

What about Random.Seed=Microseconds XOR <precious result of the random>

In a loop, I’d expect the same. If the Microseconds value hasn’t changed (possible), then the result won’t change either. Even if it does, it could lead to a predictable set of results, which would not be considered cryptographically secure.

[quote=93653:@Kem Tekinay]In a loop, I’d expect the same. If the Microseconds value hasn’t changed (possible), then the result won’t change either. Even if it does, it could lead to a predictable set of results, which would not be considered cryptographically secure.
[/quote]

You won’t get anything cryptographically secure (enough) if one of your inputs is only 64 bits – the double for the seed.

What about building a big chunk of randomized data made into strings, then crypted, which you use to fetch blocks of data at random to seed your random ? You would be certain that in a loop seed would be much more different than Microseconds.

There was an old bug : <https://xojo.com/issue/11528> where .seed would ignore some bits. I think it was fixed although the case report is unclear.

From the tests outlined in the Wikipedia article, I think my scheme would pass the test. It should be statistically random, and there would be no way to guess the next or previous bytes even if one or more bytes is revealed.

BTW, what sparked this question is an attempt to improve the RandomString function in my M_String module. Basically, you ask for a string of x length and give it a character set from which to choose. Before, it was simply using Random. Now, if you don’t specify a character set, it returns Crypto.GenerateRandomBytes. If you do… well, that’s where I’m considering alternatives.

Michel, the problem with using straight Random in any capacity is that that the data it outputs is reproducible. The problem with using GenerateRandomBytes too frequently is that the systems stack of truly random numbers is limited, and then it turns to a pseudo-random generator.

Hi Kem,

I use the function RandomString from your M_String collection. As CharSet I use nearly all letters a-z, A-Z and Numbers 1-9 (ParamArray charSet as String: one String “abcdefghij …”) and I want 8 random characters at the end. Since there are no utf-8 special fonts I disabled ConvertEncoding.
I run all in a Loop for 1000 times. But after displaying all random strings it seems not to be completely random. For example no letter “a” or “A” at the first position of the string and some letters seems to appear more often in the strings. Do I made a mistake?

Cheers,
Thomas

// Kem Tekenay M_Strings
// Returns a random string of a specified length.
// If no charsets are specified, the entire ASCII range is used and the
// encoding of the string is set to nil.
  
  #if not DebugBuild
    #pragma BackgroundTasks False
    #pragma BoundsChecking False
  #endif
  
  if length <= 0 then return ""
  
  if zRnd is nil then zRnd = new Random
  
  dim completeCharSet as string
  dim s as string
  if charSet.Ubound = -1 then
    
    // Special handling
    s = Crypto.GenerateRandomBytes( length )
    
  else
    completeCharSet = join( charSet, "" )
    if completeCharSet = EmptyString then return EmptyString
    
    dim r() as string
    dim lastIndex as integer = length - 1
    redim r( lastIndex )
    
    dim chars() as string = split( completeCharSet, "" )
    dim lastCharIndex as integer = chars.Ubound
    
    for i as integer = 0 to lastIndex
      dim mb as MemoryBlock = Crypto.GenerateRandomBytes( 8 )
      dim seedValue as Int64 = mb.Int64Value( 0 ) // Close as I get get the securely randomizing this
      zRnd.Seed = seedValue 
      
      r( i ) = Chr(Asc(chars( zRnd.InRange( 0, lastCharIndex ) ) ) )
    next
    
    s = join( r, "" )           //.ConvertEncoding( completeCharSet.Encoding )
    
  end if
  
  return s

Response is here:

https://forum.xojo.com/23638-question-about-m-string