Witam.
Problem pewnie banalny, ale chyba wykorzystałem już wszystkie opcje.
Otóż napisałem w asemblerze trzy procedury :
-
FuncNwd PROC la:DWORD, lb:DWORD
Oblicza największy wspólny dzielnik dwóch liczb -
FuncModulo PROC a:DWORD, n:DWORD
Procedura obliczająca odwrotność modulo n -
FuncGenerateKey PROC
Procedura generująca klucz publiczny i prywatny
Oto ich kod
FuncNwd PROC la:DWORD, lb:DWORD
LOCAL NWDZmienna:DWORD
LOCAL NWDReszta:DWORD
mov edx, 0
mov ecx, 0
.WHILE lb!=0
mov eax, lb
mov NWDZmienna, eax
mov eax, la
mov ecx, lb
mov edx, 0
div ecx
mov NWDReszta, edx
mov eax, NWDReszta
mov lb, eax
mov eax, NWDZmienna
mov la, eax
mov edx, 0
mov ecx, 0
.ENDW
mov eax, la
ret
FuncNwd ENDP
FuncModulo PROC a:DWORD, n:DWORD
; zmienne
LOCAL a0:DWORD, n0:DWORD, p0:DWORD, p1:DWORD, q :DWORD, r :DWORD, t :DWORD, temp:DWORD
; zmienna pomomcnicze
LOCAL test1:DWORD, test2:DWORD
;inicjalizacja zmiennych
mov eax, 0
mov p0, eax ;p0 = 0
;inicjalizacja zmiennych
mov eax, 1
mov p1, eax ;p1 = 1
;inicjalizacja zmiennych
mov eax, a
mov a0, eax ; a0 = la
;inicjalizacja zmiennych
mov eax, n
mov n0, eax ; n0 = n
;zerowanie rejestrów eax, edx, ecx
mov eax, 0
mov edx, 0
mov ecx, 0
;inicjalizacja zmiennych
; q = n0 / a0
mov eax, n0
mov ecx, a0
mov edx, 0 ;obliczenie wyniku dzielenia n0 przez a0
div ecx
mov q, eax ;wynik dzielenia w rejestrze eax
; r = n0 % a0
mov eax, n0
mov ecx, a0
mov edx, 0 ;obliczanie dzielenia modulo
div ecx
mov r, edx ;reszta z dzielenia w rejestrzea edx
.WHILE r > 0
; t = p0 - q * p1
mov eax, q
mul p1
mov temp, eax
mov eax, p0
sub eax, temp
mov t, eax
.IF t>=0
; t = t % n
mov eax, t
mov ecx, n
mov edx, 0
div ecx
mov t, edx ;reszta z dzielenia
.ELSEIF
; zamiana zmiennej t na znak przecziwny -t
mov eax, t
neg eax
mov t, eax
; dzielenie modulo
mov eax, t
mov ecx, n
mov edx, 0
div ecx
neg edx
mov temp, edx
mov eax, n
add eax, temp
mov n, eax
.ENDIF
mov eax, p1
mov p0, eax
mov eax, t
mov p1, eax
mov eax, a0
mov n0, eax
mov eax, r
mov a0, eax
mov eax, n0
mov ecx, a0
mov edx, 0
div ecx
mov q, eax
mov eax, n0
mov ecx, a0
mov edx, 0
div ecx
mov r, edx
.ENDW
; p1 wynik diałania funkcji
mov eax, p1
ret
FuncModulo ENDP
; generowanie klucza dla liczb 111 oraz 433
FuncGenerateKey PROC
LOCAL p:DWORD, q:DWORD
LOCAL phi:DWORD, n:DWORD, e:DWORD, d:DWORD
LOCAL licznik:DWORD
mov p, 111
mov q, 433
sub p, 1
sub q, 1
mov eax, p
mul q
mov phi, eax
mov p, 111
mov q, 433
mov eax, p
mul q
mov n, eax
mov e, 3
invoke FuncNwd,e,phi
.WHILE eax != 1
add e, 2
invoke FuncModulo,e,phi
mov d, eax
invoke FuncNwd,e,phi
.ENDW
ret
FuncGenerateKey ENDP
Problem w tym, iż klucz prywatny (zmienne e oraz n) generuje poprawnie, tak jak implementacja w C++.
Niestety nie generuje poprawnie klucza publicznego (zmienna d).
Implemetacja w C++ wygląda następująco :
Największy wspólny dzielnik
int nwd(int a, int b)
{
int t;
while(b != 0)
{
t = b;
b = a % b;
a = t;
};
return a;
}
Funkcja obliczająca odwrotność modulo n
int odwr_mod(int a, int n)
{
int a0,n0,p0,p1,q,r,t;
p0 = 0; p1 = 1; a0 = a; n0 = n;
q = n0 / a0;
r = n0 % a0;
while(r > 0)
{
t = p0 - q * p1;
if(t >= 0)
t = t % n;
else
t = n - ((-t) % n);
p0 = p1; p1 = t;
n0 = a0; a0 = r;
q = n0 / a0;
r = n0 % a0;
}
return p1;
}
Generowanie kluczy :
int p,q,phi,n,e,d;
int eax;
p = 111;
q = 433;
phi = (p - 1) * (q - 1);
n = p * q;
// wyznaczamy wykładniki e i d
e=3;
eax = nwd(e,phi);
while (eax != 1)
{
e = e+2;
d = odwr_mod(e,phi);
eax=nwd(e,phi);
}
EDIT :
Jeśli procedury wywoływane są osobno (dla testów) to zwracają takie same wartości jak te napisane w C++
Pewnie coś źle zaimplementowałem w asemblerze. Najprawdopodobniej chodzi o pętlę w procedurze odpowiedzialnej za generowanie kluczy, ale nie jestem pewien.
Prosiłbym kogoś o zerknięcie na kod i o jakieś rady.
Z góry dziękuję za odpowiedź.
Pozdrawiam.