266 plus some value depending on the memory allocation state, |
266 plus some value depending on the memory allocation state, |
267 plus a random salt, and shuffles those bits around. |
267 plus a random salt, and shuffles those bits around. |
268 The entropy returned should be reasonable enough for a good seed of a good rnd |
268 The entropy returned should be reasonable enough for a good seed of a good rnd |
269 generator. However, keep in mind, that it only has a limited number of entropy bits |
269 generator. However, keep in mind, that it only has a limited number of entropy bits |
270 (in the order of 32). |
270 (in the order of 32). |
271 But it shoud be much better than what is commonly used in older |
271 But it should be much better than what is commonly used in older |
272 programs (current time) or even a constant." |
272 programs (current time) or even a constant." |
273 |
273 |
274 |newSeed hash| |
274 |hash| |
|
275 |
|
276 hash := MD5Stream new. |
275 |
277 |
276 RandomSalt isNil ifTrue:[ |
278 RandomSalt isNil ifTrue:[ |
277 RandomSalt := 1. |
279 RandomSalt := 1. |
278 ] ifFalse:[ |
280 ] ifFalse:[ |
279 RandomSalt := RandomSalt + 1. |
281 RandomSalt := RandomSalt + 1. |
280 ]. |
282 ]. |
281 newSeed := RandomSalt + (Time microsecondClockValue bitXor:OperatingSystem getProcessId). |
283 hash nextPut:RandomSalt. |
282 newSeed := newSeed bitXor:(ObjectMemory addressOf:(Object new)). |
284 hash nextPutAll:Time microsecondClockValue asLargeInteger digitBytes. |
283 newSeed := newSeed bitXor:(ObjectMemory oldSpaceUsed). |
285 hash nextPutAll:OperatingSystem getProcessId asLargeInteger digitBytes. |
|
286 hash nextPutAll:(ObjectMemory addressOf:(Object new)) asLargeInteger digitBytes. |
|
287 hash nextPutAll:(ObjectMemory oldSpaceUsed) asLargeInteger digitBytes. |
|
288 hash nextPutAll:(ObjectMemory newSpaceUsed) asLargeInteger digitBytes. |
284 [ |
289 [ |
285 newSeed := newSeed bitXor:(OperatingSystem getCPUCycleCount). |
290 hash nextPutAll:(OperatingSystem getCPUCycleCount) asLargeInteger digitBytes. |
286 ] on:PrimitiveFailure do:[]. |
291 ] on:PrimitiveFailure do:[]. |
287 |
292 |
288 "/ any other easy sources of entropy? |
293 "/ any other cheap sources of entropy? |
289 |
|
290 "/ how likely is that? - paranoia |
|
291 newSeed = 0 ifTrue:[ newSeed := Time microsecondClockValue ]. |
|
292 |
|
293 "/ The above gives us a 5-8 byte number, but some high bits are constant. |
|
294 "/ (the constant high bits from the above do not provide any entropy) |
|
295 "/ so the effective entropy is more in the order of 32 bits. |
|
296 "/ if called shortly in a row, the returned values are only affected by |
|
297 "/ the amount of memory allocated in between (and if there are any newspace reclamations), |
|
298 "/ the real time in between and the number of cpu cycles between, |
|
299 "/ plus the salt counter. |
|
300 "/ Hashing should make this less likely to be predicted. |
|
301 |
294 |
302 "/ I think there is no problem in that MD5 is not a secure hash algo here - the idea is to shuffle the bits around a bit |
295 "/ I think there is no problem in that MD5 is not a secure hash algo here - the idea is to shuffle the bits around a bit |
303 "/ (because the numbers above usually have many high bits in common) |
296 "/ (because the numbers above usually have many high bits in common) |
304 "/ and then condense the bits into a smaller number. |
297 "/ and then condense the bits into a smaller number. |
305 "/ Any comment from a crypto guy here - I am willing to change this to some other hash, if that makes a problem |
298 "/ Any comment from a crypto guy here - I am willing to change this to some other hash, if that makes a problem |
306 |
299 |
307 hash := MD5Stream hashValueOf:(newSeed asLargeInteger digitBytes). |
300 "/ Seeding rnd generators should take some bits from the returned number (i.e. their max. seed size) |
308 "/ still the same number of entropy bits, bit no longer limited to an unknown number of low bits, |
301 ^ LargeInteger digitBytes:hash hashValue. |
309 "/ bit arbitrarily spread among the hash bytes. |
|
310 "/ Seeding rnd generators should Xor the returned 8 bytes to their max. seed size |
|
311 ^ LargeInteger digitBytes:hash. |
|
312 |
302 |
313 " |
303 " |
314 10 timesRepeat:[Transcript showCR:self randomSeed]. |
304 10 timesRepeat:[Transcript showCR:self randomSeed]. |
|
305 10 timesRepeat:[Transcript showCR:(self randomSeed bitAnd:16rFFFF)]. |
315 self randomSeed bitAnd:16rFFFFFFFF |
306 self randomSeed bitAnd:16rFFFFFFFF |
316 " |
307 " |
317 ! ! |
308 ! ! |
318 |
309 |
319 !Random class methodsFor:'testing'! |
310 !Random class methodsFor:'testing'! |