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
I ran a test loop of 1000 and, ironically, the very first result was “aWgnfSma”. Random is random so you can’t expect an even distribution. If you run it another 1000 times, I’d bet you’d see different oddities.
Just a note: If you’re using this for some secure purpose like a salt, you should use Crypto.RandomBytes instead.
I just ran the 1000-iteration loop three times to check the occurrence of each character on each pass. This doesn’t check for position, just occurrence. These are my results:
A = 107
B = 136
C = 129
D = 135
E = 126
F = 134
G = 123
H = 133
I = 129
J = 142
K = 136
L = 142
M = 135
N = 137
O = 132
P = 141
Q = 113
R = 127
S = 152
T = 126
U = 110
V = 145
W = 132
X = 141
Y = 130
Z = 136
a = 131
b = 114
c = 128
d = 108
e = 115
f = 142
g = 132
h = 122
i = 131
j = 110
k = 133
l = 120
m = 114
n = 136
o = 124
p = 141
q = 142
r = 147
s = 143
t = 125
u = 120
v = 134
w = 149
x = 126
y = 117
z = 125
0 = 127
1 = 103
2 = 119
3 = 108
4 = 141
5 = 126
6 = 147
7 = 123
8 = 117
9 = 131
A = 138
B = 141
C = 113
D = 127
E = 137
F = 110
G = 131
H = 122
I = 123
J = 117
K = 122
L = 130
M = 132
N = 121
O = 144
P = 125
Q = 126
R = 137
S = 111
T = 147
U = 139
V = 132
W = 124
X = 123
Y = 119
Z = 127
a = 125
b = 101
c = 132
d = 117
e = 133
f = 135
g = 119
h = 143
i = 131
j = 133
k = 118
l = 133
m = 126
n = 140
o = 131
p = 147
q = 133
r = 134
s = 123
t = 122
u = 147
v = 137
w = 132
x = 125
y = 136
z = 153
0 = 127
1 = 136
2 = 126
3 = 118
4 = 144
5 = 118
6 = 132
7 = 126
8 = 131
9 = 118
A = 150
B = 150
C = 138
D = 114
E = 153
F = 124
G = 124
H = 117
I = 131
J = 100
K = 125
L = 132
M = 153
N = 127
O = 123
P = 120
Q = 138
R = 148
S = 130
T = 138
U = 126
V = 134
W = 128
X = 147
Y = 121
Z = 125
a = 139
b = 140
c = 121
d = 126
e = 123
f = 121
g = 141
h = 122
i = 112
j = 120
k = 135
l = 135
m = 139
n = 107
o = 122
p = 138
q = 138
r = 116
s = 103
t = 130
u = 114
v = 128
w = 137
x = 120
y = 127
z = 116
0 = 139
1 = 121
2 = 131
3 = 123
4 = 154
5 = 126
6 = 138
7 = 118
8 = 127
9 = 137
Thank you very much.
I will change to Crypto.RandomBytes and try it again.
Thomas.
unfortunately …
I have again weird results.
There is no Crypto.RandomBytes function. Do I understand something wrong?
Thomas
There is definitely something wrong with my class. If I use your M_String all works fine.
Thomas
Sorry, it’s s = Crypto.GenerateRandomBytes( byteCount )
Now my solution works
// M_String Kem Tekinay
// 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
completeCharSet = join( charSet, "" )
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 ) = chars( zRnd.InRange( 0, lastCharIndex ) )
next
s = join( r, "" ).ConvertEncoding( completeCharSet.Encoding )
return s
Request:
RandomString(8, "abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ123456789")
Thank you again Kem!
Thomas