RTFC Posted September 5, 2018 Posted September 5, 2018 RdRand is Intel's on-chip hardware random number generator using entropy. This is just a quick response to this query; a faster solution would be to integrate some inline assembly (maybe using fasm?) The dll source is written by Stephen Higgins (blog here); there are several alternative codes available on GitHub as well. Usage for encryption is controversial (there are rumours of an NSA backdoor), but it may provide the closest approach to TRNG using PRNG. This is the 32-bit unsigned version, producing an integer in range: 0 to (4GB-1). Example: expandcollapse popup; for dll source, see: https://github.com/viathefalcon/rdrand_msvc_2010 ; NB only some Intel CPUs support this feature $RdRandsupported=_RdRandInit() MsgBox(0,"Is RdRand supported on this CPU?",$RdRandsupported) if $RdRandsupported=False then Exit Global $lowerbound=0 ; NB: negative values are returned as 4GB - value (unsigned int) Global $upperbound=1000 ConsoleWrite("RdRand lower bound: " & $lowerbound & @CRLF) ConsoleWrite("RdRand upper bound: " & $upperbound & @CRLF & @CRLF) For $rc=1 To 100 ConsoleWrite("RdRand: " & @TAB & _RdRand($lowerbound, $upperbound) & @CRLF) Next _RdRandCleanUp() ;################################################################################## Func _RdRandInit() Global $DllHandleRdRand = DllOpen(".\RdRandlib.dll") If @error Then Return SetError(1,0,False) $result=DllCall($DllHandleRdRand, "bool", "rdrand_supported" ) If @error Then Return SetError(1,0,False) Return ($result[0]=1) EndFunc Func _RdRandCleanUp() If IsDeclared($DllHandleRdRand) Then DllClose($DllHandleRdRand) EndFunc Func _RdRand($lower, $upper) $result=DllCall($DllHandleRdRand, "uint", "rdrand_uniform_ex", "uint", $lower, "uint", $upper ) if @error then Return SetError(@error,@extended,False) Return $result[0] EndFunc RdRand.7z coffeeturtle and argumentum 1 1 My Contributions and Wrappers Spoiler BitMaskSudokuSolver BuildPartitionTable CodeCrypter CodeScanner DigitalDisplay Eigen4AutoIt FAT Suite HighMem MetaCodeFileLibrary OSgrid Pool RdRand SecondDesktop SimulatedAnnealing Xbase I/O
Earthshine Posted September 5, 2018 Posted September 5, 2018 (edited) edited Edited September 5, 2018 by Earthshine My resources are limited. You must ask the right questions
Tekk Posted September 6, 2018 Posted September 6, 2018 Just wanted to point out that "rdrand_supported()" will return false when executed on AMD Zen processors even though rdrand is a supported instruction. The dll author did not plan for the future.
RTFC Posted September 6, 2018 Author Posted September 6, 2018 @Tekk: Thanks, but as the title clearly states, this function is explicitly for Genu-ineI-ntel chips only, see source: // Queries CPUID to see if the RDRAND instruction is supported bool rdrand_cpuid(void) { // Check if we are on Intel hardware int info[4] = { -1, -1, -1, -1 }; __cpuid( info, 0 ); if (packcmp( info[1], "Genu" ) != 0 || packcmp( info[3], "ineI" ) != 0 || packcmp( info[2], "ntel" ) != 0 ){ return false; } // Query the feature itself __cpuid( info, 1 ); return ((info[2] & RDRAND_MASK) == RDRAND_MASK); // info[2] == ecx } My Contributions and Wrappers Spoiler BitMaskSudokuSolver BuildPartitionTable CodeCrypter CodeScanner DigitalDisplay Eigen4AutoIt FAT Suite HighMem MetaCodeFileLibrary OSgrid Pool RdRand SecondDesktop SimulatedAnnealing Xbase I/O
Tekk Posted September 6, 2018 Posted September 6, 2018 I understand, I was only pointing it out. As for the title clearly stating this, I would argue that AMD chips, at least the chips in question here, execute the Intel x86 instruction set. AMD's Zen and newer processors will support this instruction. The developer should have simply checked for the feature bit to be set and disregarded manufacturer. I don't mean to argue, I just wanted to point out that it fails to work in a case where it should work. I thank you for wrapping the library for use in AutoIt. Earthshine 1
RTFC Posted September 6, 2018 Author Posted September 6, 2018 (edited) 9 minutes ago, Tekk said: it fails to work It does not, AFAICT. You can still call the RdRand() function itself, it's only the official support-query that returns False. Just call RdRandInit() first without evaluating the returned state and ignore the error, to enable access to the dll. Edited September 6, 2018 by RTFC My Contributions and Wrappers Spoiler BitMaskSudokuSolver BuildPartitionTable CodeCrypter CodeScanner DigitalDisplay Eigen4AutoIt FAT Suite HighMem MetaCodeFileLibrary OSgrid Pool RdRand SecondDesktop SimulatedAnnealing Xbase I/O
Tekk Posted September 6, 2018 Posted September 6, 2018 Right, but it was the check for support that I was questioning. Sorry for being unclear.
argumentum Posted September 7, 2018 Posted September 7, 2018 On 9/5/2018 at 10:10 AM, RTFC said: This is the 32-bit unsigned version, producing an integer in range: 0 to (4GB-1). Cool =D I made run to compare to the build in function Random() ; NB only some Intel CPUs support this feature $RdRandsupported=_RdRandInit() MsgBox(0,"Is RdRand supported on this CPU?",$RdRandsupported) if $RdRandsupported=False then Exit Global $lowerbound=0 ; NB: negative values are returned as 4GB - value (unsigned int) Global $upperbound=1000 ConsoleWrite("RdRand lower bound: " & $lowerbound & @CRLF) ConsoleWrite("RdRand upper bound: " & $upperbound & @CRLF & @CRLF) $t = TimerInit() For $rc=1 To 1000 ConsoleWrite("RdRand: " & @TAB & _RdRand($lowerbound, $upperbound) & @TAB) Next ConsoleWrite(@CRLF & TimerDiff($t) & @CRLF) _RdRandCleanUp() $t = TimerInit() For $rc=1 To 1000 ConsoleWrite("RdRand: " & @TAB & Random($lowerbound, $upperbound,1) & @TAB) Next ConsoleWrite(@CRLF & TimerDiff($t) & @CRLF) and found the internal function runs 4 times faster ( on a i7-8700k, have not tried other CPUs ) Thanks for sharing =) Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting.
Earthshine Posted September 7, 2018 Posted September 7, 2018 but is the internal one as good a randomizer? probably not My resources are limited. You must ask the right questions
argumentum Posted September 7, 2018 Posted September 7, 2018 (edited) 57 minutes ago, Earthshine said: but is the internal one as good a randomizer? no clue. I use random for ... random stuff. Never used it for 4 GB data. I have no idea. But for a simple random ... call it seed ( and I know seed is a different thing ) variable, any random number at the time is good for me. And I don't care much for speed, 0.4 ms. or 4.0 ms. is, to me on my general usage, the same. But there may be the notion that using a DLL call may be better than an internal function of the same functionality, hence my posting. That is all I wanted to point out. Edited September 7, 2018 by argumentum spelling Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting.
RTFC Posted September 7, 2018 Author Posted September 7, 2018 (edited) 2 hours ago, argumentum said: internal function runs 4 times faster Okay, let me quickly try to address the confusion (from a fidgety hotel WiFi in faraway lands, with a weird foreign keyboard, so I have to be brief). RdRand is not about speed (I think a call typically takes 420-460 cycles), it's about approximating TRNG through DRNG, rather than PRNG. PRNG comprises all regular randomiser functions you're used to (such as AutoIt's Mersenne twister). Read Intel's doc here. PRNGs produce a very very very long sequence of totally predictable numbers that for a sufficiently small sample look (and can be used as it they were truly) random. RdRand is different because it uses the (truly unpredictable) entropy of on-chip hardware (3GHz thermal noise) to produce a bitstream. So in theory the sequence of values produced by RdRand never repeats itself. Now in truth there are caveats to this (e.g., the refresh cycle itself), but in theory, if you need true randomness, then DRNG should approximate this significantly better than PRNGs as produced by any and all possible software implementations. And I didn't use a dll for speed, it was just faster to implement that way than to debug a fasm implementation from scratch. All clear? About to be automatically disconnected, so I better post this now... Edited September 7, 2018 by RTFC weird foreign characters argumentum 1 My Contributions and Wrappers Spoiler BitMaskSudokuSolver BuildPartitionTable CodeCrypter CodeScanner DigitalDisplay Eigen4AutoIt FAT Suite HighMem MetaCodeFileLibrary OSgrid Pool RdRand SecondDesktop SimulatedAnnealing Xbase I/O
Earthshine Posted September 7, 2018 Posted September 7, 2018 yep. I like Intel's RdRand myself for truer randomness My resources are limited. You must ask the right questions
AndyG Posted September 8, 2018 Posted September 8, 2018 (edited) Hi, here a short script including the (i hope it is easy enough :o) ) complete developing of an AutoIt-Function with the help of AssembleIt from 32-Bit-Assembler-code (example from here, I used only the necessary code ) Function to use with AutoIt: Func _RdRand() $binarycode = "0xB8010000000FA20FBAE11EB800000000731AB90B00000083E90174100FC7F273F68B7C24048917B801000000C3" ;returns the assembled code $tCodeBuffer = DllStructCreate("byte[" & StringLen($binarycode) / 2 - 1 & "]") ;reserve Memory for opcodes DllStructSetData($tCodeBuffer, 1, $binarycode) $RdRandstruct = DllStructCreate("uint") $RdRandstruct_ptr = DllStructGetPtr($RdRandstruct) $ret = DllCallAddress("uint:cdecl", DllStructGetPtr($tCodeBuffer), "ptr", $RdRandstruct_ptr) ;call the code If $ret[0] = 1 Then $RdRand = DllStructGetData($RdRandstruct, 1) Else $RdRand = "Your Processor is not able to execute the Rdrand-instruction!" EndIf Return $RdRand EndFunc ;==>_RdRand ;call the function $RdRand = _RdRand() ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $RdRand = ' & $RdRand & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console If you need the fastest RdRand-version possible (ie. in a loop) , it is recommended to declare all the needed variables at the begin of the script and call the DllCallAddress() in only one line. $RdRand_binarycode = "0xB8010000000FA20FBAE11EB800000000731AB90B00000083E90174100FC7F273F68B7C24048917B801000000C3" ;returns the assembled code $RdRand_CodeBuffer = DllStructCreate("byte[" & StringLen($RdRand_binarycode) / 2 - 1 & "]") ;reserve Memory for opcodes DllStructSetData($RdRand_CodeBuffer, 1, $RdRand_binarycode) $RdRand_CodeBuffer=DllStructGetPtr($RdRand_CodeBuffer) $RdRandstruct = DllStructCreate("uint") $RdRandstruct_ptr = DllStructGetPtr($RdRandstruct) For $i = 1 To 100 $ret = DllCallAddress("uint:cdecl",$RdRand_CodeBuffer , "ptr", $RdRandstruct_ptr) ;call the code consolewrite (DllStructGetData($RdRandstruct, 1) & @CRLF) Next Example of developing..... AssembleIt64 is attached. Remember that it is possible to develop also 64-Bit-Code (see example scripts) expandcollapse popup#include <assembleit2_64.au3> #AutoIt3Wrapper_UseX64=n #cs _RdRand Use32 ;32Bit! mov eax,1 cpuid ;is RdRand-instruction available on your processor? bt ecx,30 ;looking for the "yes, it is"-Bit mov eax,0 ;exit code to AutoIt: failure jnc .exit ;if the Bit is not set, then exit ; rdrand sets CF=0 if no random number ; was available. Intel documentation ; recommends 10 retries in a tight loop mov ecx,11 .loop1: sub ecx, 1 jz .exit ;exit if ecx=0, 10 loops were executed rdrand edx ;store RdRand into Register jnc .loop1 ;loop 10 times? mov edi,[esp+4] ;Pointer from AutoIt structure _asmdbg_() ;Debugger, so you can see the what´s going on :o) mov [edi],edx ;store Register into AutoIt structure mov eax,1 ;exit code to AutoIt: success .exit: ret #ce ;##########first stage########## ;developer Version :o) including the ability to debug the code $RdRandstruct = DllStructCreate("uint") $RdRandstruct_ptr = DllStructGetPtr($RdRandstruct) $ret = _AssembleIt2("uint", "_RdRand", "ptr", $RdRandstruct_ptr) If $ret = 1 Then $RdRand = DllStructGetData($RdRandstruct, 1) Else $RdRand = "Your Processor is not able to execute the Rdrand-instruction!" EndIf ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $RdRand = ' & $RdRand & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console ;##########second stage########## ;code assembled by AssembleIt $binarycode = _AssembleIt2("retbinary", "_RdRand") ;returns the assembled code ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $binarycode = ' & $binarycode & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console ;##########third stage########## ;get the assembled code, write it into memory and call it $binarycode = "0xB8010000000FA20FBAE11EB800000000731AB90B00000083E90174100FC7F273F68B7C24048917B801000000C3" ;returns the assembled code $tCodeBuffer = _DllStructCreate64("byte[" & StringLen($binarycode) / 2 - 1 & "]") ;reserve Memory for opcodes DllStructSetData($tCodeBuffer, 1, $binarycode) $ret = DllCallAddress("uint:cdecl", DllStructGetPtr($tCodeBuffer), "ptr", $RdRandstruct_ptr) ;call the code If $ret[0] = 1 Then $RdRand = DllStructGetData($RdRandstruct, 1) Else $RdRand = "Your Processor is not able to execute the Rdrand-instruction!" EndIf ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $RdRand = ' & $RdRand & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console ;##########final stage########## ;make an easy function (speed is not necessary) Func _RdRand() $binarycode = "0xB8010000000FA20FBAE11EB800000000731AB90B00000083E90174100FC7F273F68B7C24048917B801000000C3" ;returns the assembled code $tCodeBuffer = _DllStructCreate64("byte[" & StringLen($binarycode) / 2 - 1 & "]") ;reserve Memory for opcodes DllStructSetData($tCodeBuffer, 1, $binarycode) $ret = DllCallAddress("uint:cdecl", DllStructGetPtr($tCodeBuffer), "ptr", $RdRandstruct_ptr) ;call the code If $ret[0] = 1 Then $RdRand = DllStructGetData($RdRandstruct, 1) Else $RdRand = "Your Processor is not able to execute the Rdrand-instruction!" EndIf Return $RdRand EndFunc ;==>_RdRand ;call the function $RdRand = _RdRand() ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $RdRand = ' & $RdRand & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console assembleit2_64 121.zip //EDIT why not use eax to return RdRand directly from the asm-code and save some clockticks? :o) Needs 2 functions then , one to check if RdRand is supported by your processor, an an other (supershort ) function which only returns the RdRand GO ON! Spoiler expandcollapse popup#include <assembleit2_64.au3> #AutoIt3Wrapper_UseX64=n #cs _RdRand_superfast Use32 ;32Bit! rdrand eax ;store RdRand into Register ret #ce #cs _RdRand_slow Use32 ;32Bit! mov ecx,11 .loop1: sub ecx, 1 jz .exit ;exit if ecx=0, 10 loops were executed rdrand eax ;store RdRand into Register jnc .loop1 ;loop 10 times? .exit: ret #ce #cs _RdRand_available Use32 ;32Bit! mov eax,1 cpuid ;is RdRand-instruction available on your processor? bt ecx,30 ;looking for the "yes, it is"-Bit mov eax,0 ;exit code to AutoIt: failure jnc .exit ;if the Bit is not set, then exit mov eax,1 ;exit code to AutoIt: success .exit: ret #ce $ret = _AssembleIt2("uint", "_RdRand_available") If $ret = 1 Then $RdRand_available = "Your Processor supports the Rdrand-instruction!" Else $RdRand_available = "Your Processor is not able to execute the Rdrand-instruction!" EndIf ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $RdRand_available = ' & $RdRand_available & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console $RdRand = _AssembleIt2("uint", "_RdRand_slow") ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $RdRand = ' & $RdRand & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console $RdRand = _AssembleIt2("uint", "_RdRand_superfast") ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $RdRand = ' & $RdRand & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console Edited September 8, 2018 by AndyG
DennisChristensen Posted September 11, 2018 Posted September 11, 2018 Hi Thanks all. Can i get a compiled dll somewhere? Best regards Dennis
AndyG Posted September 11, 2018 Posted September 11, 2018 hi, what is wrong with this function which needs no dll and calls the RdRand Processor opcode? Func _RdRand() $binarycode = "0xB8010000000FA20FBAE11EB800000000731AB90B00000083E90174100FC7F273F68B7C24048917B801000000C3" ;returns the assembled code $tCodeBuffer = DllStructCreate("byte[" & StringLen($binarycode) / 2 - 1 & "]") ;reserve Memory for opcodes DllStructSetData($tCodeBuffer, 1, $binarycode) $RdRandstruct = DllStructCreate("uint") $RdRandstruct_ptr = DllStructGetPtr($RdRandstruct) $ret = DllCallAddress("uint:cdecl", DllStructGetPtr($tCodeBuffer), "ptr", $RdRandstruct_ptr) ;call the code If $ret[0] = 1 Then $RdRand = DllStructGetData($RdRandstruct, 1) Else $RdRand = "Your Processor is not able to execute the Rdrand-instruction!" EndIf Return $RdRand EndFunc ;==>_RdRand ;call the function $RdRand = _RdRand() ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $RdRand = ' & $RdRand & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console oh, and btw. It is ver easy with FASM to compile a dll with the given assembler-code....i will show an example here soon...
DennisChristensen Posted September 11, 2018 Posted September 11, 2018 Hi AndyG Nothing I guess :-) I just saw the DllCallAddress and assumed it needed a Dll. I will soon try your code - thanks Best regards Dennis
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now