here a slightly modified version which uses AES to create a nonreversible result and different initialisation to reduce the chance for MD5 collisions:
Code: Select all
;================================================================================================================================
;SUBJECT: Generating random numbers with a string as seed
; This should fill the gap between Random() and CryptRandom()
;AUTHOR: codeprof
;LICENSE: PUBLIC DOMAIN (can be used without any restriction)
; This software is provided 'as-is', without any express or implied warranty.
; In the author cannot be held liable for any damages arising from the use of this software.
; Use this software at your own risk.
;DATE: 2013-03-23
;================================================================================================================================
;Advantages:
; - String can be used as seed!
; - more secure than Random()
; - configurable whether it should be fast or more secure
; - supports Unicode (and returns the same values like in ANSI mode)
; - support for quad random numbers (up to 63 bits instead of 31 bits with Random())
; - works for Windows, Linux and MacOSX
;Disadvantages:
; - probably not as secure as CryptRandom()
; - not thread safe ( as the "Threaded" keyword of PureBasic cannot be used inside procedures
; To make it thread safe move the "Static" variables outside of the procedure as
; global variables and use the "Threaded" keyword)
;================================================================================================================================
;Initializes the random number generator with an seed string.
;Parameters:
; seed : string with which the random number generator is initialized (max 128 chars)
; num_iterations [optional] : Number of times the result s encrypted with AES on a nonreversible way
; The result should be at least hashed once for security reason (prevents known plaintext attacks...)
; If security is not important "num_iterations" can be set to 0 to improve performace.
; A high number will result in very slow number generation.
; This could be used to prevent timing attacks (make brute force attacks harder).
;================================================================================================================================
Procedure.q QRandomSeed(seed.s, num_iterations.i = 16)
Static Dim key.q(1)
Static Dim current.q(1)
Static Dim result.q(1)
Static Dim tmp.q(1)
Static num_aes_iterations = 0
Protected md5.s, i.i, *key
If seed <> ""
;Initalize random number generator
Protected Dim seed_string.UNICODE(127 + 1)
PokeS(@seed_string(0), Left(seed, 128), 128, #PB_Unicode)
;We use the MD5 of "seed.s" to generate a 128 bit key.
md5.s = MD5Fingerprint(@seed_string(0), SizeOf(UNICODE) * 128)
key(0) = Val("$" + Left(md5, 16))
key(1) = Val("$" + Right(md5, 16))
;We use MD5(MD5(seed)+seed) as initialisation value.
;The MD5 of the MD5 is used here so it is not possible to restore the key out of it (as reverting the MD5 is not possible).
;MD5(seed)+seed is used to reduce the chance for a collision, because it is much harder to find a string
;which returns a correct result for MD5(seed) and MD5(MD5(seed)+seed).
PokeS(@seed_string(0), Left(md5 + seed, 128), 128, #PB_Unicode)
md5.s = MD5Fingerprint(@seed_string(0), SizeOf(UNICODE) * 128)
current(0) = Val("$" + Left(md5, 16))
current(1) = Val("$" + Right(md5, 16))
num_aes_iterations = num_iterations
Else
;generate the next random number
AESEncoder(@current(0), @result(0), 128 / 8, @key(0), 128, #Null, #PB_Cipher_ECB)
CopyMemory(@result(0), @current(0), 128 / 8)
;To prevent short cycles we increment the 128 bit key by 1.
key(0) + 1
If key(0) = 0:key(1) + 1:EndIf
;Despite it seems not very useful the next part is relevant for security.
;Of course we could encrypt our "result" buffer just with the key. The result would be also
;equally distributed random numbers, but a known plaintext attack would be easier.
;The attacker would know half of "result", so it would be easier to him to predict the next random number.
;Therefore we add this nonreversible part to calculate the final result.
;AES itself is reversible. However, here it is not because the key selection is based on intermediate values, which cannot be restored (just by trying out all possibilites).
For i = 1 To num_aes_iterations
*key = ?QRANDOM_RANDOM_AES_KEYS + (result(0) & 255) * (128 / 8)
CopyMemory(@result(0), @tmp(0), 128 / 8)
AESEncoder(@tmp(0), @result(0), 128 / 8, *key, 128, #Null, #PB_Cipher_ECB)
Next
EndIf
ProcedureReturn result(0) ! result(1)
DataSection
QRANDOM_RANDOM_AES_KEYS:
Data.q $56925DA264FD4DE2,$B90230394D9E4C09,$F148E6F393B5345A,$86BAA4AFAC0BD66B,$9EE5F0320041D959,$AF40EBC1D48ED2F3,$4C136BEDDE6B2972,$AE3E86F172E01244
Data.q $7A23C4B1800E3A02,$ADC52DA72A1C5DC5,$6F346B5F5F5B66DC,$94C0BAE326EEBD49,$28F6923F50B00CB5,$5D9AF464E0678E3,$382BA9357A1F028D,$B1E357D2384EF571
Data.q $4C6862BA6CE6ABD3,$1E2D71EEB8FE866A,$AB5CDF3D14613DC,$7188ECC96EA66C94,$913E76A782E63112,$14B075C78D75D6FA,$39088E41B3CC6F57,$E67DBCAAE004A7EE
Data.q $5C8669B2CDF96DDB,$E40D67CDD9B62C6F,$70D13A3F684A0E3,$AA2F6FB5F9755B4D,$25225CFBD17E3BA9,$4A7D35BF5C9A5D9B,$B733511B26C9FF45,$15DF406F74BB3EC1
Data.q $CF44858AD6E405C0,$8EBFF1048B85353C,$4C77FEFF474DC82D,$43B1FEC3AAEAEEAA,$E9DD6B6E34902354,$9AD9DB5B4AC985DA,$275C12DA289271D,$CF2D6B4E4BAAD466
Data.q $63F145609D9119B5,$E7CB07E1972A9169,$6CBF479570D4B1B4,$38A274473C72503D,$9B034557BCC80186,$D340DE87E0178ED9,$57A74946065FA8E4,$A062A242303AD0E9
Data.q $93E67D76AE37FCB1,$263209EE68FE122,$67CDAA2AF11FB15D,$3233E03B77184F19,$64F4A36DD72543D9,$C2BDBF273A764271,$4226B8DDE5DAD94D,$38C17659BB725CDA
Data.q $F0EDC1E4391E2E02,$EE0E56D2D092841C,$6412D1AFDBE21C3E,$AA6810A2EE4AEE50,$DE41D5E06C0DA59C,$63B7679D41247D92,$424360D65FA69A4D,$D1C6EA12A19DE6F9
Data.q $1973BD4E0B3719F6,$8D33ECAF55B8CFD0,$4A5B3BDED278E7F8,$6C6A0C28B077456F,$8789437E8D4C624E,$1AA550C42117D7B4,$A0A25A6498076AD5,$F3CABE4D6ED84A47
Data.q $196CE3F6B9BD8AB9,$FA89196A5997CB44,$B0D75770C8F93661,$31770EDBD5E14591,$908346DEB51EE7A7,$F83A4A2111ACF2F,$BF1AB48895219528,$4D7D6C74D629150B
Data.q $3C16AB42DFC8774E,$BA77F10C8E106C,$FA91EAC12706C60E,$3FD28E3C92522B7D,$79F8EC7049F21A98,$7F3F65E753F038AD,$69DC9F82EB818304,$1F7FE007E916CFD
Data.q $D32FCE2241FD6309,$2DADAD60657C370C,$E1E327C69F626222,$1BCD588FE26CC2C1,$CEC030DCB86E933A,$9760406E2923AEAC,$EAF872423B45DA34,$F741DD4918168377
Data.q $6AA57A7FD2336E5C,$2BEDB29E6A90632C,$5B23E4E47345C318,$FE369B7E29D485DC,$183D2C349F874CF3,$E8608033C9F31410,$2FE9B09BF04DB4C,$7350811E8B5E2266
Data.q $FB61418C3567AC6E,$9738E6FD75377200,$D8E405B3E24201B5,$97A79CB326D628BE,$84217FCABD5A57D,$E6752370C0D2EBAB,$2FF160D2D10652BC,$6FBC4AD86EF7E709
Data.q $20C89D0A1728F88D,$33B5545E43AC5884,$6D3478E25F852F1C,$BC824338595BD588,$80B99060E96333D,$A1C433301B91D931,$EF997D68F3AD4530,$17FEEE23CEC879C8
Data.q $CE1AD285A66A997B,$BE3F1FA65FCC808A,$52C340DDC988675A,$C69756FAB53E63DD,$97B4BA69558E2FEE,$BF76DED8E987FF9,$3669C9D555E7CE25,$320CBAA8F8D38221
Data.q $9634517161ECC14C,$FD4CEF5D623C15FE,$94EEF8AD43F2FB78,$827BCE8BD03B1858,$3B587A1EE530FBBF,$CEE74063D4AE41F0,$DA5D4C3536C498EE,$4FC36CD8ACF6D1E1
Data.q $573484F07D8EFD51,$6E4627750DDF7EB,$828512641265D518,$95133C5752870CAE,$5B8F03F85C613263,$B96D5A159D6F464,$8A8ACEF38BD86C18,$4EAF8B485E6E3B4B
Data.q $F3F7DC21CFD24F3,$4F5AD47EF9B00D03,$89EF7560CF43F6F6,$E7A50E3FE0BD772B,$52E9E46EE416115,$22A7DA166A38CD6F,$59A17EAE8FF57E53,$68EF8A17D1742B26
Data.q $34C90892C5E44450,$C06EDE1FB27E63BC,$1089C0C661EAA7C3,$A60AA3DB869696C7,$C5BCC23D86CB50E7,$F2A5F34C734E0AB,$D14963A785F3E426,$C63852FD0C0A1DA1
Data.q $19B3F8C18ACFC954,$7758E09008DA71F0,$FF7037B8F928CFD6,$36B8F4745886F52,$FBE9A80E29C76BF9,$84B6EBA20D7E8B3C,$918E6AD8E3190789,$82953D049C86A0E7
Data.q $A35A35E938E4A59F,$6CEB5143F083BC3F,$B2735C8D052FB0E,$68998879091D0603,$F87C24F2ADA46483,$C9E7678CDA227D0,$85BC9793A6728690,$51B7D14CBFFD3971
Data.q $5CF314972B8954EE,$57A094C50E1DD661,$991EA8CCBA51BD4C,$F95DD9BB53507F0B,$6FBA25A8DC04E30A,$3AD08575567298F9,$440DF63AF36C5F7A,$CABF8EC94788C76F
Data.q $8746FED39869CDC3,$8C5CF05C9B784955,$4CB21746BC3DA641,$BEC72950C465E35F,$22AF87AC1235197A,$7CF47C499F6D046,$A3FC02EA6F58DDDD,$5C60269388FD6F1D
Data.q $94CC8F5A4FD9DECB,$B7010D951B642DE3,$81E455DE1ABD07DB,$A50E9310AC0FED07,$B4A6D6ECAE80C787,$B68FB0F470BDE967,$F6BD5F469151CE11,$AB2DDE8490158EF3
Data.q $B3B240B1452A29BD,$6E1308166FE917CC,$BBE60EAAB9FD0550,$C09FA63F0835B619,$C00942B033E8DAE9,$A3D0CBF5EC3A5E2D,$F162E3368F8B9F7E,$23A515ACC04818AB
Data.q $7A4A8D873080EF1,$570AE960C7DDE005,$11DD70CFFB9301AF,$545281D622DE08A5,$2C6E2CED2B2F7D90,$46F7827B73F4DF8D,$9A9D46A7401DB2A9,$36B8C4F9A8232C12
Data.q $A5168DAFFC03FA06,$DC1E101E92B35D5A,$AAF2DA2CB0AB6C6E,$9466FB4860D03CA0,$FDE20D681CAD4A8C,$EBF1A82934B3A83F,$D417CE5876E5E302,$1AEEADE7606A1E63
Data.q $D3F427E74A873960,$CE8912C5441975AF,$6BE4446A5C4478DF,$41F2056329845F92,$70055F6166144C43,$7F41B582B12032CC,$41630771C027025A,$E4934B2C90352527
Data.q $8264D5546A2F94AC,$3ECD63E723090C27,$5EEC88981AA10F66,$92DD2DFFDA9A754,$1740048B164ECDED,$75B4B965C6915103,$E213378E806C3C2B,$1BEE8EFF35668EBB
Data.q $37DCE7231BEF603B,$F95E01BCA74A9C01,$AFC89440B74CEFAE,$5B291B2C8E497856,$730D7E26160DF867,$3D8B9D368CAED9F5,$10CBA51860F97EE5,$7065EC769F880456
Data.q $95E888E75193899A,$F9B86EAB9C297301,$68CB85117EA74CE4,$361220DE24250982,$4C1A0EB5D2B4D579,$43BCF471686386CE,$CF80EAD42A0409DF,$D5757F5B019EA974
Data.q $38D77241492C41FF,$680D1A4B8D5E549B,$AB39E19720AA1FF1,$9CB4AF79EEAC8CD6,$206447A6AEEA5EB5,$CD6100231DFC502D,$9A6E23B329C6D1C9,$D16360CED435261
Data.q $5A36DF256B843326,$A90D7D2423B30C26,$876231841877BD,$D3BF957242AFF313,$C7F41783868E1069,$1BDDA0D34C0A1BFF,$5317D6A96DE00432,$995D6B4F8225A78
Data.q $1D1117B914CAD59E,$3290F3B229E8BD7C,$C78F777676406EED,$34F9DD87C0C697F1,$C0625A74C657A369,$D87E6120DAB5CED3,$492ACD83D7A5108A,$815C6DFE33ADCB0
Data.q $7010AAA14BAF974D,$65BB51D37DB5A996,$DCC7FE4045B96FFA,$AF9FAE13CB56ADB4,$DD573ED9A1364DCA,$63EA3FD57A9A22A0,$4664EBE7CF4DC9D2,$95F23898A0BB022
Data.q $9906DB957B8B4224,$18C472E1151E4BD1,$BC05105858EE9841,$111708612EC47DD8,$883AFBE8EF4CC14C,$BE71050B7CDE4848,$8D88B422F2600332,$FA5FABA6DAFDCE5
Data.q $3B38748C2F109A28,$520890A68A69BF69,$490CFE76D9A9BEDD,$CCFB524B4E2D7A14,$93F953D64D2E7D56,$A0F8AB531BE85F2A,$91745B732F5410AD,$C6F3674B2177B35
Data.q $7A5E26F6E6A04ABE,$208AC27EEC163720,$C21FFF700CA8415A,$BC748631FF6655C6,$551B159966C93A90,$B3062C8037E27085,$F0F05E7BB78CA447,$E3D15C2C9C4ECE1
Data.q $19CC57A883E7B173,$4F18EEA3A042A31C,$5168DD323C54F4E9,$455EACF7FEF2A22,$A8001A49448490D4,$929DEB73252D61B,$5748603B3C195A93,$FECA7E8FDCBB2B1
Data.q $160A8C2A008F2286,$19E69781CA07E421,$1B5AD949E7B53231,$CF430A969977B,$D0F620EBA61481D9,$897BDE8348876DE4,$DC6D6E090D2786E1,$CB31D4CDFD1CE3F
Data.q $9E140CCE53C00CEE,$5382AF3A3D523E34,$D9E2C77DDED1E631,$BA4372D24D3F3AA3,$4B8788702ABDE6BC,$DAA32BC53E3172F,$C3C892FDC244359A,$E424F4AF6783386
Data.q $E167744719BA08C9,$E1D2CD44CFD61F8C,$2A33F97FB51A7932,$A46B09245E74BE92,$89F1ADC7FCB8C0,$6BF560982BC7F927,$7633C879310A359,$8BBC6B5E23C5B21
Data.q $BE3E2E31356BFFB2,$AE31E0510FA7F81B,$28F4CB637F1DE609,$2544DC34E2DD2657,$62652CC78EAEF6D5,$4AC932FF5A8EDB99,$33A06CEB8661D6BD,$75904721A898025
Data.q $3C89277F2BE46132,$F351FCF7BE85C744,$ED2C57D0C0005027,$B257EE9C3D1607FA,$7B8CFC03C19A6981,$416F7ED2C05825DD,$D43C3181F2D36A7B,$B67074512AD3ADA
Data.q $9CE391191789172E,$E157F3C0B6425035,$6312EF1C1270F118,$51D5DB8FC47BE92C,$D36DD0DF9A774D0E,$DD0B094CD70D3B35,$91F273C0AA850276,$E722BECCD746683
Data.q $DB741026D009D493,$D9526DA149AD7787,$47BEA9AD53DDAAC1,$186DB654D8788D55,$A6FC38CD22A5C5D7,$A1B2D34EA1879085,$27350CA239AA9AF1,$4380B2302FDED0B
Data.q $2A03D5AF40482376,$A0CF8D9762F57314,$69215EA7A127E530,$6347C715FA298C06,$4AE1799FA47BEAE6,$D923F6E610D1F57C,$74DDEDC19E6B6E79,$18160D19699704F
Data.q $71C07B45D2084927,$DAA23DB03366BDEE,$BF05280EC4E21BDB,$2B3C01AA802E36AF,$2456174C0C83A6FA,$72722245C4282B10,$B4AA20BF55C961EB,$1EACCB347E6076B
Data.q $429C76D1489A5ED8,$906B9BF5921986F4,$9E76DE69BD351703,$D86A451D0B671F25,$47681B42664A9917,$81259366FC2043D3,$D6DA4C57516527B3,$4E7D7BCCD9206D8
Data.q $CB05698C9B70CDC4,$C9CF466EEB9CA043,$ADD9533A3087B40A,$6E387A6A4D21601E,$DBDACC32CC5E1278,$C9724EAF63F3ACDB,$48BE2C5826EB359D,$49E8FE5B097E145
Data.q $D96FF933C01D932A,$4395B13C20AB6BCF,$3DB9E797637EA969,$4E4D53B7DB0B0246,$1273F2E14115FAA9,$A6FE328AABFDC53A,$F6537B797DEB302C,$6F47E5FE4676C06
Data.q $366055EF2D4B5A68,$163981DF741208F5,$3B799E9BCD51A631,$C85F8BF9ACECC739,$D13F0D6E1001CBFC,$33288A9D92B052A0,$A41F301BCAEFA166,$2CB59BC50FA020C
Data.q $C72BAD0528DF317E,$29D9114E987FC11E,$7E007E88AE674F60,$FFF0CF79668B2CCF,$E01B02FD3E1CDE29,$6216AA694B247FAD,$AEE1028D92A02528,$CEFE4539A349FCA
Data.q $89B286BA88E7CEA6,$5F5FAF9B9F5D97B8,$BE393D9620C390C2,$A08E98A6E9F55D3F,$20EC5856361FCDE2,$3BBB4902CE27B37B,$4CD1829B74801CEF,$65592FEAEF0C11E
Data.q $60B2BB0EB594515B,$27AA68C366FE0AFB,$74832D014E1F3B98,$F67057131EEB882,$642179C24DA6F097,$15F4D99DA3F215BA,$660146DAE4F11310,$505AC2B1C4B6E80
Data.q $7CA3ADDC8CA5AB34,$B5B67FD5AC15D7A3,$2118FD8D779F99E1,$DCB2F3FED513343A,$2100DE48F0F6933,$6E5E5D08B69B4D0A,$C2A833A9D86398D5,$3A071892689AEB5
Data.q $320B18EB9FF82DBF,$DB1167D123C7D5AB,$91E429470E54FBBB,$66AFC84AD7CDCB53,$26D4BE4909265B3D,$7257C21B7686FD80,$43AB276CC71AFBF2,$8EBD9F046D00B26
Data.q $F812A1A93DDAE031,$19D07A966EB09C57,$ED339969D1C9D91C,$C5A01A87D7E4F18E,$654C238B8390DE1C,$24DAF15170D78348,$6F3AC78B98881E5D,$1DEAB11D55CFD9
Data.q $989EE52C999AB969,$999D63A249C04667,$5840989A13C6409F,$182DA800947FFE0D,$F4D77B16313AC67E,$A62AF6BA5B90BD00,$CE06A209B852557B,$DE73A3756BE169A
Data.q $E18254F41356831E,$DFCF201D9F166007,$C1FA653913BE9BB1,$926211EBA0FD769E,$DAEE70A12EEB8B10,$E63EE0C041422DAE,$A716D9A78149F1EE,$9C1E4AF26088AB5
Data.q $F92FE5ABA3AEC085,$EB56B15423149015,$C81B167E43199416,$78315333D0C65D5,$65A81BC84102883B,$8185188E7EC5713E,$3161A88922C34CF6,$F565A5C1708A97A
Data.q $EBF540293B35AC5B,$F74571A64CC718B5,$9F223B3D49F507AB,$ABD43C220BFF07FF,$C45CC0CF111C1644,$48A035273EB44D59,$F584310AD9E32182,$32BEC7C9300A838
Data.q $D4FE0597EAF45046,$B13A297D234AA959,$4C03F71B4BA9A878,$1342607A07F4F892,$6BD03BEFCD866F01,$D5DDE4979536D1A9,$1B89AF18CB0F519B,$2B16DB1D045C301
EndDataSection
EndProcedure
;================================================================================================================================
;Random number between "min" and "max" (including "min" and "max")
;The functions supports random numbers up to 63 bits.
; max : maximum number (must be greater than "min")
; min : minimum number (must be less than "max")
;================================================================================================================================
Procedure.q QRandom(max.q, min.q = 0)
Protected val.q = QRandomSeed("") & $7FFFFFFFFFFFFFFF
val = val % ( max - min + 1)
ProcedureReturn val + min
EndProcedure
;Example
QRandomSeed("MY TOP SECRET MASTER PASSWORD", 100000)
For j = 1 To 10
passwd$ = ""
For i = 0 To 30
passwd$ + Chr(QRandom(126,33))
Next
Debug "Password("+Str(j)+"): " + passwd$
Next