--- a/Random.st Thu Mar 24 07:05:34 2016 +0100
+++ b/Random.st Fri Mar 25 06:53:03 2016 +0100
@@ -77,6 +77,11 @@
=======================================================================================
DO NOT USE THIS GENERATOR FOR CRYPTOGRAPHY OR OTHER SECURITY RELATED WORK,
because linear congruential generators are predictable and can be broken easily!!
+
+ Smalltalk/X includes a better generator named RandomGenerator, which uses the best
+ available generator of the system (either OS-random, /dev/random or as a less dangerous
+ fallback, an RC4-based random generator.
+ Please use that one.
=======================================================================================
Notice: although being included here,
--- a/RandomGenerator.st Thu Mar 24 07:05:34 2016 +0100
+++ b/RandomGenerator.st Fri Mar 25 06:53:03 2016 +0100
@@ -14,10 +14,10 @@
"{ NameSpace: Smalltalk }"
Random subclass:#RandomGenerator
- instanceVariableNames:''
- classVariableNames:'RandFile SharedRandomGenerator'
- poolDictionaries:''
- category:'Magnitude-Numbers'
+ instanceVariableNames:''
+ classVariableNames:'HasOSRandom RandFile SharedRandomGenerator RandomDevicePathes'
+ poolDictionaries:''
+ category:'Magnitude-Numbers'
!
!RandomGenerator class methodsFor:'documentation'!
@@ -38,16 +38,16 @@
documentation
"
+ This is a Random number generator,
+ which uses either a OS random number generator or /dev/urandom,
+ or an ST/X internal random number generator.
+
Warning: this generator should not be used for cryptographic work
- unless:
+ UNLESS:
1) you are running on linux, solaris or osx,
2) you have a working /dev/urandom.
3) you can trust your /dev/urandom (I don't really know if any/all of them are good)
- This is a Random number generator,
- which uses either a OS random number generator (/dev/urandom),
- or an ST/X internal random number generator.
-
[author:]
Stefan Vogel
@@ -58,7 +58,9 @@
[instance variables:]
[class variables:]
- RandFile the FileStream we get random numbers from
+ HasOSRandom true if the operatingSystem supports random numbers
+ RandFile (if HasOSRandom is false and non-nil) the FileStream (/dev/random),
+ we get random numbers from
"
! !
@@ -77,17 +79,16 @@
|randDevName|
- RandFile isStream ifTrue:[
+ RandFile notNil ifTrue:[
RandFile close.
+ RandFile := nil.
].
- RandFile := false. "prevent retry"
-
randDevName := self randPath.
randDevName notNil ifTrue:[
randDevName := randDevName asFilename.
randDevName isReadable ifTrue:[
- RandFile := randDevName readStream
+ RandFile := randDevName readStream.
].
].
! !
@@ -109,31 +110,36 @@
^ SharedRandomGenerator.
].
- [
- "fetch a random byte - and check if the OS generator works"
- result := OperatingSystem randomBytesInto:1.
- ] on:PrimitiveFailure do:[:ex| ].
-
- result notNil ifTrue:[
+ HasOSRandom == nil ifTrue:[
+ "/ see if there is an OS or CPU-random generator
+ [
+ "fetch a random byte - and check if the OS generator works"
+ result := OperatingSystem randomBytesInto:1.
+ ] on:PrimitiveFailure do:[:ex| ].
+ HasOSRandom := result notNil.
+ ].
+
+ HasOSRandom ifTrue:[
"OperatingSystem knows how to get random bytes"
- RandFile := true.
SharedRandomGenerator := self basicNew.
^ SharedRandomGenerator.
- ] ifFalse:[
- RandFile isNil ifTrue:[
- self openRandFile.
- ].
- RandFile isStream ifTrue:[
- SharedRandomGenerator := self basicNew.
- ^ SharedRandomGenerator.
- ].
+ ].
+
+ RandFile isNil ifTrue:[
+ self openRandFile.
+ ].
+ RandFile notNil ifTrue:[
+ SharedRandomGenerator := self basicNew.
+ ^ SharedRandomGenerator.
].
+ "/ fallback
Rc4Cipher notNil ifTrue:[
SharedRandomGenerator := Rc4Cipher random.
^ SharedRandomGenerator.
].
+ "/ last fallback - not very good
SharedRandomGenerator := Random sharedGenerator.
^ SharedRandomGenerator.
! !
@@ -151,10 +157,14 @@
update:something with:aParameter from:changedObject
"handle image restarts and flush any device resource handles"
- SharedRandomGenerator := nil.
- RandFile notNil ifTrue:[
- RandFile := nil.
- self openRandFile.
+ (changedObject == ObjectMemory) ifTrue:[
+ (something == #returnFromSnapshot) ifTrue:[
+ SharedRandomGenerator notNil ifTrue:[
+ SharedRandomGenerator := nil.
+ HasOSRandom := RandFile := nil.
+ self new. "/ opens a new sharedGenerator
+ ]
+ ]
].
! !
@@ -163,8 +173,34 @@
randPath
"path to a file/device that is a source or random numbers"
- OperatingSystem isUNIXlike ifTrue:[^ '/dev/urandom'].
+ |pathesOrNil|
+
+ pathesOrNil := self randomDevicePathes.
+ pathesOrNil notNil ifTrue:[
+ pathesOrNil do:[:triedRandom |
+ triedRandom asFilename exists ifTrue:[
+ ^ triedRandom
+ ]
+ ].
+ ].
^ nil.
+!
+
+randomDevicePathes
+ "pathes to look for OS sources of random numbers"
+
+ RandomDevicePathes notNil ifTrue:[^ RandomDevicePathes].
+ OperatingSystem isUNIXlike ifTrue:[
+ ^ #( '/dev/urandom' '/dev/random' )
+ ].
+ ^ nil.
+!
+
+randomDevicePathes:aCollectionOfpathesOrNil
+ "configurable pathes to look for OS sources of random numbers.
+ (can be set during early startup in an rc-file)"
+
+ RandomDevicePathes := aCollectionOfpathesOrNil.
! !
!RandomGenerator methodsFor:'basic reading'!
@@ -172,10 +208,9 @@
nextByte
"get the next random byte"
- RandFile == true ifTrue:[
+ HasOSRandom == true ifTrue:[
^ OperatingSystem randomBytesInto:1.
].
-
RandFile isOpen ifFalse:[
self class openRandFile.
].
@@ -204,7 +239,7 @@
nextBytes:cnt
"get the next cnt random bytes"
- RandFile == true ifTrue:[
+ HasOSRandom == true ifTrue:[
^ OperatingSystem randomBytesInto:(ByteArray new:cnt).
].
RandFile isOpen ifFalse:[
@@ -299,7 +334,7 @@
intSize := SmallInteger maxBytes.
- RandFile == true ifTrue:[
+ HasOSRandom == true ifTrue:[
^ OperatingSystem randomBytesInto:intSize.
].