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”.
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).
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.
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.
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