12 июля 2012 г.

Посмотреть на рандом.

Бывает интересно посмотреть на алгоритм псевдо генератора рандом не просто в цифрах, а в виде картинок и подобрать параметры которые больше всего нравятся. Не всегда есть желание и возможность провести полноформатное тестирование с его монстроподными формулами и прочим да и не особа это нужно если не разрабатывать новые алгоритмы для криптографии. По этому решил я написать небольшую программку которая выводит в фаил нули и единицы которые генерятся нв выходе алгоритмов.

Возьмем пару алгоритмов псевдо рандом генераторов и один также псевдо, но генерируемый при помощи команды RDTSC.
1. Алгоритм который я уже рассматривал, это линейный конгруэнтный генератор, я не буду его подробно разбирать, это было сделано в статье про него, которую можно почитать тут.
Рисунок при
K0 = 1
A = 11
B = 23
G = 255
Получается такой:
По вертикальным чертам сразу видно, что генератор псевдо случайных писем повторяется, еслиб он не повторялся то рисунок был бы более хаотичный.

2. Алгоритм тоже достаточно извесный но я о нем еще не говорил и называется он BBS, от фамилий их создателей L. Blum, M. Blum, M. Shub
Этот алгоритм к стати интересен тем, что он не только генерит неплохие последовательности, но и также при известных значениях с которыми работал генератор можно вычислить любую Xn, не перебирая все варианты от X0 до Xn.
Формула сего алгоритма следующая:
Сначало выбираются 2 больших простых числа q и p.
Числа должны быть оба сравнимы с 3 по модулю 4, тоесть оба числа должны при взятии модуля 4 получать 3 в остатке. Например это числа: 31 и 51, если возвести их оба в модуль 4 получим 3.
Далее перемножаем p * q = M и выбираем взаимно простое число x, тоесть число которое не имеет с M одинаковых множетелей кроме 1. И вычисляем по формуле:
х0= (х*x) mod M
Ну а дальше как линейный конгруэнтный генератор, подставляем число x , получаем профит, тоесть вот эту картину:

3. И последний алгоритм добывания некоторого рандома, это команда RDTSC, которая считывает Time Stamp Counter. Эта команда полезна тем, что может быть в принципе источником энтропии. Алгоритм тут совсем простой, получаем число, смотрим на младший бит рисуем картинку:
Как видно даже вроде неплохой рандом получается, но реально использовать в серьезных программах народ в интернетах не рекомендует, хотя по мне, в полне нармально вроде получилось :)


Ну а теперь как обычно немного ассемблерного кода:
.386
.model flat, stdcall  ;32 bit memory model
option casemap :none  ;case sensitive

include checkRND.inc

.code

start:
    invoke    createBMPHeader ; создаем заголовок BMP файла
    push    eax ; сохраним ссылку на него
    invoke    CreateFile, offset filename, GENERIC_WRITE,FILE_SHARE_WRITE, NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL, 0 ; открываем фаил на запись
    mov        hFile, eax ; сохраняем хендл
    invoke  SetFilePointer, hFile, NULL,NULL, FILE_END ; ставим указатель на конец файла
    pop        eax ; востановим ссылку на заголовок
    invoke    WriteFile, hFile, offset hBMP, eax, ADDR cWrite, NULL ; записываем заголовок bmp
    mov        ecx, IMGSIZE*IMGSIZE ; в ecx помещаем размер картинки
nextpoint:
    push    ecx ; сохраним ecx
    invoke  SetFilePointer, hFile, NULL,NULL, FILE_END ;ставим указатель на конец файла
    invoke    createColor ; создаем цвет FF - белый, 0 - черный
    invoke    WriteFile, hFile, offset color, 1, ADDR cWrite, NULL ; записываем байт
    pop        ecx ; востанавливаем ecx
    loop    nextpoint ; обрабатываем следующий байт
    
    invoke    CloseHandle, hFile ; закрываем хэндл
    
    invoke    ExitProcess,0 ; выходим из программы
    
createBMPHeader proc ; создаем заголовок bmp картинки
    mov        hBMP.bfType, 'MB' ; записываем магическую комбинацию
    xor        eax, eax ; обнуляем eax
    mov        eax, sizeof ihBMP ; вычисляем размер, ахинея но пусть будет
    mov        ihBMP.biSize, eax ; записываем размер всего файла, необязательный параметр
    mov        ihBMP.biWidth, IMGSIZE ; пишем высоту
    mov        ihBMP.biHeight, IMGSIZE ; пишем ширину
    mov        ihBMP.biPlanes, 1h ; насколько я понял всегда еденица
    mov        ihBMP.biBitCount, 1h ; бит на еденицу, значит монохромное
    mov        bcol.rgbBlue, 0FFh ;цвет1
    mov        bcol.rgbGreen, 0FFh ;цвет1
    mov        bcol.rgbRed, 0FFh ;цвет1
    xor        eax, eax ; обнулили eax
    add        eax, sizeof hBMP ; сложили файловый хидер bmp
    add        eax, sizeof ihBMP ; сложили инфо хидер bmp
    add        eax, sizeof wcol*2 ; прибавили цвета, 2 штуки
    mov        hBMP.bfOffBits, eax ; записали в общий размер заголовка
    ret
createBMPHeader endp

createColor    proc
LOCAL    tmpk:DWORD
    mov        color, 0 ; изначально цвет 0
    mov        tmpk, 5h ; во временную перменную заносим 5
    xor        eax, eax ; обнуляем eax
    mov        ecx, 8 ; так как в байте 8 бит, записываем в ecx 8
nextbit:
    mov        eax, tmpk ; востанавливаем временную переменную
;    invoke    random ; разнообразные функции рандома 
;    invoke    Gen_Ps_Random,eax, 0Bh, 17h, 0FFh ; разнообразные функции рандома 
    invoke     Gen_Bbs_Random,eax, 1Fh, 33 ; работающая BBS функция
    mov        tmpk, eax ; сохраняем во временной переменной eax
    bt        ax, 0 ; смотрим какой самый младший бит
    jc        biton ; если 1, то прыгаем на biton
    mov        al, color ; копируем число из color в al
    rol        al, 1 ; сдвигаем al на 1 позицию
    mov        color, al ; записываем в переменнюу color al
    jmp        endbit прыгаем на конец обработки бита
biton: ; если бит всетаки 1
    mov        al, color копируем число из color в al
    or        al, 1 ; вклеиваем 1 в младший бит
    rol        al, 1 ; сдвигаем al на 1 позицию
    mov        color, al ; записываем в переменнюу color al
endbit:        
    loop    nextbit ; обрабатываем следующий бит
    
    ret
createColor endp

random proc uses ebx edx ; самопальный рандом
    db         0fh,031h ;записываем команду RDTSC в хексе, чтобы не ругался компилятор
    neg        eax    ; инвентируем eax
    rcl     eax, 5        ; сдвигаем в лево теряя один бит
    mov        ebx, eax ; копируем eax в ebx
    mov        edx, eax ; копируем eax в edx
    db         0fh,031h ;записываем команду RDTSC в хексе, чтобы не ругался компилятор
    rcr        eax, 6    ; сдвигаем eax на 6 в право теряя один бит
    neg     eax    ; снова инвертируем eax
    xor     eax, ebx ; ксорим eax и ebx
    Ret
random EndP

Gen_Ps_Random proc uses edx k:DWORD, a:DWORD, b:DWORD, g:DWORD
    
    mov        eax, a ; копируем в eax a
    mul        k ; умножаем eax на k
    add        eax, b  ; складываем eax с b
    xor        edx, edx ; обнуляем edx
    div        g ; берем модуль от g
    mov        eax, edx ; копируем модуль в eax
    
    Ret
Gen_Ps_Random EndP

Gen_Bbs_Random proc uses edx ebx x:DWORD, p:DWORD, q:DWORD
    mov        eax, x ; копируем в eax x
    mul        eax ; умножаем eax на eax
    mov        ebx, eax ; копируем eax в ebx
    mov        eax, p ; копируем p в eax
    mul        q ; умножаем на q
    xchg    eax, ebx ; меняем местами eax и ebx
    xor        edx,edx ; обнуляем edx
    div        ebx ; вычисляем модуль 
    mov        eax, edx : копируем модуль в eax
    
    Ret
Gen_Bbs_Random EndP

end start

Ну и конечно целиком исходный код на pastebin - http://pastebin.com/kr3ArVfV

Комментариев нет:

Отправить комментарий