собственно, метод, рекомендуемый Microsoft (тот самый CryptoAPI):
Код:
ConsoleWrite(_Crypto_GetRandomString(12, 7) &@CRLF)
; =============================================================================
; _Crypto_GetRandomString($iLen[, $iFlag])
; -----------------------------------------------------------------------------
; Получение случайной символьной строки заданной длины
;
; $iLen : длина получаемой строки
; $iFlag : какие символы используются при генерации строки
; : 1 - цифры
; : 2 - большие английские буквы
; : 4 - малые английские буквы
; : 8 - основные спецсимволы
; : 16 - дополнительные спецсимволы
; : 32 - русские буквы
;
; При успехе : возвращает бинарную строку
;
; При неудаче : пустая строка:
; : @error, @extended - код ошибки _Crypto_GetRandomBinary()
;
; : AutoIT v3.3.0.0
; =============================================================================
Func _Crypto_GetRandomString($iLen, $iFlag = 15)
Local $iMid, $sABC = "", $sOut = ""
If BitAND($iFlag,1) Then $sABC &= "0123456789"
If BitAND($iFlag,2) Then $sABC &= "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
If BitAND($iFlag,4) Then $sABC &= "abcdefghijklmnopqrstuvwxyz"
If BitAND($iFlag,8) Then $sABC &= "~!@#$%^&*()_"
If BitAND($iFlag,16) Then $sABC &= '`+-=",.<>/?\|[]{};:'&"'"
If BitAND($iFlag,32) Then $sABC &= 'АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюя'
Local $iABC = StringLen($sABC)
Local $bPWD = _Crypto_GetRandomBinary($iLen)
If @error Then Return SetError(@error, @extended, $sOut) ; Ошибка _Crypto_GetBinary
For $i=1 To BinaryLen($bPWD)
$iMid = Int(BinaryMid($bPWD,$i,1))*$iABC/0x100+1
$sOut &= StringMid($sABC, $iMid, 1)
Next
Return $sOut
EndFunc ; ==> _Crypto_GetRandomString
; =============================================================================
; _Crypto_GetRandomBinary($iLen)
; -----------------------------------------------------------------------------
; Получение случайной строки байтов заданной длины
;
; $iLen : количество байтов в бинарной строке
;
; При успехе : возвращает бинарную строку
;
; При неудаче : возвращаемое значение не является бинарной строкой:
; : @error=1, @extended=1 - ошибка открытия advapi32.dll
; : @error=1, @extended=2 - ошибка открытия kernel32.dll
; : @error=2 - RunTime ошибка API, @extended - код ошибки
;
; : AutoIT v3.3.0.0
; =============================================================================
Func _Crypto_GetRandomBinary($iLen)
Local $phProv = DllStructCreate("ulong_ptr"), $aRet
Local $pbBuffer = DLLStructCreate("byte[" & $iLen & "]")
; Открытие DLL
Local $hAdvApi = DllOpen("advapi32.dll"), $hKernel = DllOpen("kernel32.dll")
If $hAdvApi=-1 Then Return SetError(1, 1, DllClose($hKernel)) ; Ошибка открытия advapi32.dll
If $hKernel=-1 Then Return SetError(1, 2, DllClose($hAdvApi)) ; Ошибка открытия kernel32.dll
; Создание описателя криптохранилища
$aRet = DllCall($hAdvApi, "int", "CryptAcquireContext", _
"ptr", DllStructGetPtr($phProv), "ptr", 0, "ptr", 0, "dword", 1, "dword", 0xF0000000)
If $aRet[0]=0 Then $aRet = DllCall($hKernel, "int", "GetLastError")
If UBound($aRet)=1 And $aRet[0]=0x80090016 Then
$aRet = DllCall($hAdvApi, "int", "CryptAcquireContext", _
"ptr", DllStructGetPtr($phProv), "ptr", 0, "ptr", 0, "dword", 1, "dword", 0xF0000008)
If $aRet[0]=0 Then $aRet = DllCall($hKernel, "int", "GetLastError")
EndIf
If UBound($aRet)>1 Then
; Генерация случайной последовательности байтов
$aRet = DllCall($hAdvApi, "int", "CryptGenRandom", _
"ptr", DllStructGetData($phProv, 1), "dword", $iLen, "ptr", DllStructGetPtr($pbBuffer))
If $aRet[0]=0 Then $aRet = DllCall($hKernel, "int", "GetLastError")
; Закрытие описателя криптохранилища
DllCall($hAdvApi, "long", "CryptReleaseContext", _
"ulong_ptr", DllStructGetData($phProv, 1), "dword", 0)
EndIf
DllClose($hKernel)
DllClose($hAdvApi)
If UBound($aRet)=1 Then Return SetError(2, $aRet[0], 0) ; Ошибка API RunTime
Return DllStructGetData($pbBuffer, 1) ; Возврат строки
EndFunc ; ==> _Crypto_GetRandomBinary
|