diff --git a/3/__pycache__/iloczyn.cpython-310.pyc b/3/__pycache__/iloczyn.cpython-310.pyc new file mode 100644 index 0000000..eb0b07a Binary files /dev/null and b/3/__pycache__/iloczyn.cpython-310.pyc differ diff --git a/3/__pycache__/xor.cpython-310.pyc b/3/__pycache__/xor.cpython-310.pyc new file mode 100644 index 0000000..c38b439 Binary files /dev/null and b/3/__pycache__/xor.cpython-310.pyc differ diff --git a/3/__pycache__/xtime.cpython-310.pyc b/3/__pycache__/xtime.cpython-310.pyc new file mode 100644 index 0000000..2521fd6 Binary files /dev/null and b/3/__pycache__/xtime.cpython-310.pyc differ diff --git a/3/iloczyn.py b/3/iloczyn.py new file mode 100644 index 0000000..3d5542b --- /dev/null +++ b/3/iloczyn.py @@ -0,0 +1,33 @@ +import gmpy2 +from gmpy2 import mpz +from xor import xor_custom +from xtime import xtime + +def iloczyn(a, b): + """ + Mnoży dwa elementy w F_{2^8} za pomocą algorytmu "Russian peasant". + + Args: + a (mpz): Pierwszy element w F_{2^8}. + b (mpz): Drugi element w F_{2^8}. + + Returns: + mpz: Wynik mnożenia w F_{2^8}. + """ + if not isinstance(a, mpz) or not isinstance(b, mpz): + raise TypeError("Oba argumenty muszą być typu mpz.") + + result = gmpy2.mpz(0) + while b > 0: + if b & 1: + result = xor_custom(result, a) + a = xtime(a) + b = b >> 1 + return result + +if __name__ == "__main__": + # Przykład użycia + xy_H = gmpy2.mpz(0x57) # Przykładowy element + uw_H = gmpy2.mpz(0x83) # Przykładowy element + wynik = iloczyn(xy_H, uw_H) + print(f"iloczyn({hex(int(xy_H))}, {hex(int(uw_H))}) = {hex(int(wynik))}") diff --git a/3/odwrotnosc.py b/3/odwrotnosc.py new file mode 100644 index 0000000..2559ec8 --- /dev/null +++ b/3/odwrotnosc.py @@ -0,0 +1,60 @@ +import gmpy2 +from gmpy2 import mpz +from xor import xor_custom +from iloczyn import iloczyn + +def odwrotnosc(a): + """ + Znajduje odwrotność elementu w F_{2^8} za pomocą rozszerzonego algorytmu Euklidesa. + + Args: + a (mpz): Element w F_{2^8}. + + Returns: + mpz: Odwrotność elementu w F_{2^8}. + """ + if not isinstance(a, mpz): + raise TypeError("Argument musi być typu mpz.") + + if a == 0: + raise ValueError("Element 0 nie ma odwrotności w F_{2^8}.") + + # Definicja polinomu niezupełnego (AES) + irreducible = gmpy2.mpz(0x11B) + + # Rozszerzony algorytm Euklidesa + r0, r1 = irreducible, a + s0, s1 = gmpy2.mpz(0), gmpy2.mpz(1) + + while r1 != 0: + deg_r0 = r0.bit_length() - 1 + deg_r1 = r1.bit_length() - 1 + if deg_r0 < deg_r1: + # Swap r0 and r1 + r0, r1 = r1, r0 + s0, s1 = s1, s0 + deg_r0, deg_r1 = deg_r1, deg_r0 + shift = deg_r0 - deg_r1 + # r0 = r0 XOR (r1 << shift) + r0_shifted = r1 << shift + r0 = xor_custom(r0, r0_shifted) + # s0 = s0 XOR (s1 << shift) + s0_shifted = s1 << shift + s0 = xor_custom(s0, s0_shifted) + + if r0 != 1: + raise ValueError(f"Element {hex(int(a))} nie ma odwrotności w F_{2^8}.") + + return s0 & gmpy2.mpz(0xFF) + +if __name__ == "__main__": + # Przykład użycia + xy_H = gmpy2.mpz(0x57) # Przykładowy element + try: + wynik = odwrotnosc(xy_H) + print(f"Odwrotność({hex(int(xy_H))}) = {hex(int(wynik))}") + # Sprawdzenie: iloczyn powinien być 0x01 + ilocz = iloczyn(xy_H, wynik) + print(f"Sprawdzenie: iloczyn({hex(int(xy_H))}, {hex(int(wynik))}) = {hex(int(ilocz))}") + except ValueError as e: + print(e) diff --git a/3/suma.py b/3/suma.py new file mode 100644 index 0000000..c330e7a --- /dev/null +++ b/3/suma.py @@ -0,0 +1,23 @@ +import gmpy2 +from gmpy2 import mpz +from xor import xor_custom + +def suma(a, b): + """ + Dodaje dwa elementy w F_{2^8} za pomocą operacji XOR. + + Args: + a (mpz): Pierwszy element w F_{2^8}. + b (mpz): Drugi element w F_{2^8}. + + Returns: + mpz: Wynik dodawania w F_{2^8}. + """ + return xor_custom(a, b) + +if __name__ == "__main__": + # Przykład użycia + xy_H = gmpy2.mpz(0x57) # Przykładowy element + uw_H = gmpy2.mpz(0x83) # Przykładowy element + wynik = suma(xy_H, uw_H) + print(f"Suma({hex(int(xy_H))}, {hex(int(uw_H))}) = {hex(int(wynik))}") diff --git a/3/xor.py b/3/xor.py new file mode 100644 index 0000000..a43376d --- /dev/null +++ b/3/xor.py @@ -0,0 +1,31 @@ +import gmpy2 +from gmpy2 import mpz + +def xor_custom(a, b): + """ + Wykonuje operację bitowego XOR na dwóch liczbach typu mpz reprezentujących bajty. + + Args: + a (mpz): Pierwszy bajt (0-255) jako mpz. + b (mpz): Drugi bajt (0-255) jako mpz. + + Returns: + mpz: Wynik operacji XOR (0-255) jako mpz. + """ + if not isinstance(a, mpz) or not isinstance(b, mpz): + raise TypeError("Oba argumenty muszą być typu mpz.") + + result = mpz(0) + for i in range(8): + bit_a = (a >> i) & 1 # Pobiera i-ty bit z a + bit_b = (b >> i) & 1 # Pobiera i-ty bit z b + bit_result = bit_a ^ bit_b # XOR bitów + result |= (bit_result << i) # Ustawia wynikowy bit w odpowiedniej pozycji + return result + +if __name__ == "__main__": + # Przykład użycia + a = gmpy2.mpz(0x57) + b = gmpy2.mpz(0x83) + wynik = xor_custom(a, b) + print(f"xor_custom({hex(int(a))}, {hex(int(b))}) = {hex(int(wynik))}") diff --git a/3/xtime.py b/3/xtime.py new file mode 100644 index 0000000..e70fa08 --- /dev/null +++ b/3/xtime.py @@ -0,0 +1,31 @@ +import gmpy2 +from gmpy2 import mpz +from xor import xor_custom + +def xtime(a): + """ + Mnoży element w F_{2^8} przez (02)_H. + + Args: + a (mpz): Element w F_{2^8}. + + Returns: + mpz: Wynik mnożenia w F_{2^8}. + """ + if not isinstance(a, mpz): + raise TypeError("Argument musi być typu mpz.") + + # Sprawdzenie, czy najwyższy bit jest ustawiony + high_bit_set = (a >> 7) & 1 + # Przesunięcie w lewo o jeden bit + result = (a << 1) & 0xFF + if high_bit_set: + # XOR z 0x1B, jeśli najwyższy bit był ustawiony + result = xor_custom(gmpy2.mpz(result), gmpy2.mpz(0x1B)) + return result + +if __name__ == "__main__": + # Przykład użycia + xy_H = gmpy2.mpz(0x57) # Przykładowy element + wynik = xtime(xy_H) + print(f"xtime({hex(int(xy_H))}) = {hex(int(wynik))}") diff --git a/miniprojekt_nr3.pdf b/miniprojekt_nr3.pdf new file mode 100644 index 0000000..55c7e08 Binary files /dev/null and b/miniprojekt_nr3.pdf differ