2024-06-18 22:04:24 +02:00
|
|
|
import sys
|
|
|
|
from hashlib import sha256, sha384
|
|
|
|
import os
|
|
|
|
import random
|
|
|
|
|
|
|
|
byteorder = sys.byteorder
|
|
|
|
|
|
|
|
|
|
|
|
def get_power_2_factors(n: int) -> (int, int):
|
|
|
|
r = 0
|
|
|
|
d = n
|
|
|
|
while n > 0 and d % 2 == 0:
|
|
|
|
d = d // 2
|
|
|
|
r += 1
|
|
|
|
return r, d
|
|
|
|
|
|
|
|
|
|
|
|
def miller_rabin_prime_test(n: int, k: int = 64) -> bool:
|
|
|
|
# Factor powers of 2 from n - 1 s.t. n - 1 = 2^r * d
|
|
|
|
r, d = get_power_2_factors(n - 1)
|
|
|
|
|
|
|
|
for i in range(k):
|
|
|
|
a = get_random_bits(n.bit_length())
|
|
|
|
while a not in range(2, n - 2 + 1):
|
|
|
|
a = get_random_bits(n.bit_length())
|
|
|
|
x = pow(a, d, n)
|
|
|
|
if x == 1 or x == n - 1:
|
|
|
|
continue
|
|
|
|
n_1_found = False
|
|
|
|
for j in range(r - 1):
|
|
|
|
x = pow(x, 2, n)
|
|
|
|
if x == n - 1:
|
|
|
|
n_1_found = True
|
|
|
|
break
|
|
|
|
if not n_1_found:
|
|
|
|
return False
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
|
|
def get_random_bits(bit_length: int) -> int:
|
|
|
|
return int.from_bytes(os.urandom((bit_length + 7) // 8), 'big')
|
|
|
|
|
|
|
|
|
|
|
|
def bezpieczny_randint(poczatek_inkluzywny, koniec_ekskluzywny):
|
|
|
|
dlugosc_przedzialu = koniec_ekskluzywny-poczatek_inkluzywny
|
|
|
|
maksymalna_liczba_bitow_zapisu = dlugosc_przedzialu.bit_length()
|
|
|
|
# liczba miedzy 0 a 2**maksymalna_liczba_bitow_zapisu
|
|
|
|
wyn = get_random_bits(maksymalna_liczba_bitow_zapisu)
|
|
|
|
# liczba miedzy 0 a dlugosc_przedzialu
|
|
|
|
while wyn >= dlugosc_przedzialu:
|
|
|
|
wyn = get_random_bits(maksymalna_liczba_bitow_zapisu)
|
|
|
|
# liczba miedzy poczatek_inkluzywny a koniec_ekskluzywny
|
|
|
|
wyn = poczatek_inkluzywny + wyn
|
|
|
|
return wyn
|
|
|
|
|
|
|
|
|
|
|
|
def generate_prime_number(bit_length: int) -> int:
|
|
|
|
# prime needs to be in range [2^(n-1), 2^n-1]
|
|
|
|
low = pow(2, bit_length - 1)
|
|
|
|
high = pow(2, bit_length) - 1
|
|
|
|
|
|
|
|
while True:
|
|
|
|
|
|
|
|
# Generate odd prime candidate in range
|
|
|
|
candidate_prime = get_random_bits(bit_length)
|
|
|
|
while candidate_prime not in range(low, high + 1) or not candidate_prime % 2:
|
|
|
|
candidate_prime = get_random_bits(bit_length)
|
|
|
|
|
|
|
|
# with k rounds, miller rabin test gives false positive with probability (1/4)^k = 1/(2^2k)
|
|
|
|
k = 64
|
|
|
|
if miller_rabin_prime_test(candidate_prime, k):
|
|
|
|
return candidate_prime
|
|
|
|
|
|
|
|
|
|
|
|
def rozszerzony_algorytm_euklidesa(a0, b0):
|
|
|
|
a, b = a0, b0
|
|
|
|
x, y = 1, 0
|
|
|
|
r, s = 0, 1
|
|
|
|
while b != 0:
|
|
|
|
c = a % b
|
|
|
|
q = a // b
|
|
|
|
a, b = b, c
|
|
|
|
r_pom, s_pom = r, s
|
|
|
|
r = x - q * r
|
|
|
|
s = y - q * s
|
|
|
|
x, y = r_pom, s_pom
|
|
|
|
nwd = x * a0 + y * b0
|
|
|
|
return a, x, y, nwd
|
|
|
|
|
|
|
|
|
|
|
|
def NWD(a, b):
|
|
|
|
nwd1, _, _, nwd2 = rozszerzony_algorytm_euklidesa(a, b)
|
|
|
|
if nwd1 == nwd2:
|
|
|
|
return nwd1
|
|
|
|
else:
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
|
|
def odwrotnosc_modulo(a, n):
|
|
|
|
_, x, y, _ = rozszerzony_algorytm_euklidesa(a, n)
|
|
|
|
if a != 1 and x == 1:
|
|
|
|
odwrotnosc_a = "nie ma elementu odwrotnego"
|
|
|
|
elif x > 0:
|
|
|
|
odwrotnosc_a = x % n
|
|
|
|
else:
|
|
|
|
odwrotnosc_a = (n + x) % n
|
|
|
|
return odwrotnosc_a
|
|
|
|
|
|
|
|
|
|
|
|
def szybkie_potegowanie_modulo(podstawa, wykladnik, rzad):
|
|
|
|
pom = 1
|
|
|
|
while wykladnik > 1:
|
|
|
|
ostatni_bit = wykladnik & 1
|
|
|
|
wykladnik >>= 1
|
|
|
|
if ostatni_bit == 1:
|
|
|
|
pom = (pom * podstawa) % rzad
|
|
|
|
podstawa = (podstawa * podstawa) % rzad
|
|
|
|
return (podstawa * pom) % rzad
|
|
|
|
|
|
|
|
|
|
|
|
def genRSA(n=2048):
|
|
|
|
p = generate_prime_number(n)
|
|
|
|
# print(p.bit_length())
|
|
|
|
q = p
|
|
|
|
while q == p:
|
|
|
|
q = generate_prime_number(n)
|
|
|
|
# print(q.bit_length())
|
|
|
|
N = p * q
|
|
|
|
fi_N = (p - 1) * (q - 1)
|
|
|
|
print(N.bit_length(), fi_N.bit_length())
|
|
|
|
e = bezpieczny_randint(2, fi_N)
|
|
|
|
while NWD(e, fi_N) != 1:
|
|
|
|
e = bezpieczny_randint(2, fi_N)
|
|
|
|
d = odwrotnosc_modulo(e, fi_N)
|
|
|
|
# print(e.bit_length(),d.bit_length())
|
|
|
|
klucz_publiczny = (N, e)
|
|
|
|
klucz_prywatny = d
|
|
|
|
return klucz_publiczny, klucz_prywatny, p, q
|
|
|
|
|
|
|
|
|
|
|
|
def szyfrowanie_RSA_OAEP(N, e, m: bytes):
|
|
|
|
byteorder = sys.byteorder
|
|
|
|
# 256 + 128 = 384
|
|
|
|
k = 256
|
|
|
|
l = 128
|
|
|
|
# G = sha384()
|
|
|
|
# H = sha256()
|
|
|
|
print("m", len(m) * 8)
|
|
|
|
print("m", m)
|
|
|
|
if len(m) * 8 != l:
|
|
|
|
return "wiadomosc usi byc dlugosci l =" + str(l)
|
|
|
|
m_prim = m.ljust(len(m) + k // 8, b"\0")
|
|
|
|
int_m_prim = int.from_bytes(m_prim, byteorder)
|
|
|
|
print("m'", len(m_prim) * 8)
|
|
|
|
print("m'", m_prim)
|
|
|
|
int_r = get_random_bits(k)
|
|
|
|
r = int_r.to_bytes(k // 8, byteorder)
|
|
|
|
print("r", len(r) * 8)
|
|
|
|
print("r", r)
|
|
|
|
int_G_od_r = int.from_bytes(sha384(r).digest(), byteorder)
|
|
|
|
int_t = int_m_prim ^ int_G_od_r
|
|
|
|
t = int_t.to_bytes((l + k) // 8, byteorder)
|
|
|
|
print("t", len(t) * 8)
|
|
|
|
print("t", t)
|
|
|
|
int_H_od_t = int.from_bytes(sha256(t).digest(), byteorder)
|
|
|
|
int_s = int_r ^ int_H_od_t
|
|
|
|
s = int_s.to_bytes(k // 8, byteorder)
|
|
|
|
print("s", len(s) * 8)
|
|
|
|
print("s", s)
|
|
|
|
m_prim_prim = s + t
|
|
|
|
print("m''", len(m_prim_prim) * 8)
|
|
|
|
print("m''", m_prim_prim)
|
|
|
|
int_m_prim_prim = int.from_bytes(m_prim_prim, byteorder)
|
|
|
|
c = szybkie_potegowanie_modulo(int_m_prim_prim, e, N)
|
|
|
|
return c
|
|
|
|
|
|
|
|
|
|
|
|
def deszyfrowanie_RSA_OAEP(N, d, c):
|
|
|
|
byteorder = sys.byteorder
|
|
|
|
# 256 + 128 = 384
|
|
|
|
k = 256
|
|
|
|
l = 128
|
|
|
|
# G = sha384()
|
|
|
|
# H = sha256()
|
|
|
|
int_m_prim_prim = szybkie_potegowanie_modulo(c, d, N)
|
|
|
|
m_prim_prim = int_m_prim_prim.to_bytes((l + 2 * k) // 8, byteorder)
|
|
|
|
print("m''", len(m_prim_prim) * 8)
|
|
|
|
print("m''", m_prim_prim)
|
|
|
|
t = m_prim_prim[-((l + k) // 8):]
|
|
|
|
print("t", len(t) * 8)
|
|
|
|
print("t", t)
|
|
|
|
s = m_prim_prim[:(k // 8)]
|
|
|
|
print("s", len(s) * 8)
|
|
|
|
print("s", s)
|
|
|
|
int_H_od_t = int.from_bytes(sha256(t).digest(), byteorder)
|
|
|
|
int_s = int.from_bytes(s, byteorder)
|
|
|
|
int_r = int_H_od_t ^ int_s
|
|
|
|
r = int_r.to_bytes(k // 8, byteorder)
|
|
|
|
print("r", len(r) * 8)
|
|
|
|
print("r", r)
|
|
|
|
int_G_od_r = int.from_bytes(sha384(r).digest(), byteorder)
|
|
|
|
int_t = int.from_bytes(t, byteorder)
|
|
|
|
int_m_prim = int_G_od_r ^ int_t
|
|
|
|
m_prim = int_m_prim.to_bytes((l + k) // 8, byteorder)
|
|
|
|
print("m'", len(m_prim) * 8)
|
|
|
|
print("m'", m_prim)
|
|
|
|
koncowki = m_prim[-(k // 8):]
|
|
|
|
m = m_prim[:l // 8]
|
|
|
|
if koncowki != b"\0".ljust(k // 8, b"\0"):
|
|
|
|
print("kon")
|
|
|
|
print(koncowki)
|
|
|
|
print(b"\0".ljust(k // 8, b"\0"))
|
|
|
|
print("cowki")
|
|
|
|
return m
|
|
|
|
|
|
|
|
|
|
|
|
def efektywne_deszyfrowanie_RSA(N, d, c, p, q):
|
|
|
|
u = odwrotnosc_modulo(p, q)
|
|
|
|
c_p = c % p
|
|
|
|
c_q = c % q
|
|
|
|
d_p = d % (p - 1)
|
|
|
|
d_q = d % (q - 1)
|
|
|
|
m_p = szybkie_potegowanie_modulo(c_p, d_p, p)
|
|
|
|
m_q = szybkie_potegowanie_modulo(c_q, d_q, q)
|
|
|
|
m = (m_p + p * (m_q - m_p) * u) % N
|
|
|
|
return m
|
|
|
|
|
|
|
|
|
|
|
|
def deszyfrowanie_RSA_OAEP_efektywne(N, d, c, p, q):
|
|
|
|
byteorder = sys.byteorder
|
|
|
|
# 256 + 128 = 384
|
|
|
|
k = 256
|
|
|
|
l = 128
|
|
|
|
# G = sha384()
|
|
|
|
# H = sha256()
|
|
|
|
int_m_prim_prim = efektywne_deszyfrowanie_RSA(N, d, c, p, q)
|
|
|
|
m_prim_prim = int_m_prim_prim.to_bytes((l + 2 * k) // 8, byteorder)
|
|
|
|
print("m''", len(m_prim_prim) * 8)
|
|
|
|
print("m''", m_prim_prim)
|
|
|
|
t = m_prim_prim[-((l + k) // 8):]
|
|
|
|
print("t", len(t) * 8)
|
|
|
|
print("t", t)
|
|
|
|
s = m_prim_prim[:(k // 8)]
|
|
|
|
print("s", len(s) * 8)
|
|
|
|
print("s", s)
|
|
|
|
int_H_od_t = int.from_bytes(sha256(t).digest(), byteorder)
|
|
|
|
int_s = int.from_bytes(s, byteorder)
|
|
|
|
int_r = int_H_od_t ^ int_s
|
|
|
|
r = int_r.to_bytes(k // 8, byteorder)
|
|
|
|
print("r", len(r) * 8)
|
|
|
|
print("r", r)
|
|
|
|
int_G_od_r = int.from_bytes(sha384(r).digest(), byteorder)
|
|
|
|
int_t = int.from_bytes(t, byteorder)
|
|
|
|
int_m_prim = int_G_od_r ^ int_t
|
|
|
|
m_prim = int_m_prim.to_bytes((l + k) // 8, byteorder)
|
|
|
|
print("m'", len(m_prim) * 8)
|
|
|
|
print("m'", m_prim)
|
|
|
|
koncowki = m_prim[-(k // 8):]
|
|
|
|
m = m_prim[:l // 8]
|
|
|
|
if koncowki != b"\0".ljust(k // 8, b"\0"):
|
|
|
|
print("kon")
|
|
|
|
print(koncowki)
|
|
|
|
print(b"\0".ljust(k // 8, b"\0"))
|
|
|
|
print("cowki")
|
|
|
|
return m
|
|
|
|
|
|
|
|
|
2024-06-18 22:37:32 +02:00
|
|
|
# klucz_publiczny_RSA, klucz_prywatny_RSA, p, q = (
|
|
|
|
# 519761468615543605427347715703470532429938244355530617462517836775139947735532430649086044712389065327373881495341570956912263636228899450218205333731994709572385570226639327413165593530360209805759468603639857045256463923468775944877723831073218948735316969800684547536389344549931456857234306842372788643144370170015431494005792115059852604376019742040737720145831855341361995847454762357088678899180062704532000519408988445258760142165454104557986566507437171014234130588907895586535673103026294670410052684946543540355295153040713047596704353948168657913426604838668582082688505569615845354438639297748571125719945947883870935481915168118357450909437162890949276124288629273158626408730136153353280259385734094248099908877393332627830019602495378740189414275791739220123642063963148205857703085745460786497856110396863143452962185817050131451659771071779171468538379804253272573761890205034195675788656368202533040838395434243520115268109258521563259069746861504072033382067677548531381312853098367831348608517017347561078932501869038526817662345324458956129880592307734774686126383765519554521082281355928596367373896420049772278195723106268205519834478036673827492711851824231074849054234160240213942064673753130040021561496201,
|
|
|
|
# 477381706395942701152074095578632486629565400458439476605265085853794121036702612260159616584121387309492215289565364823820329641787576027356541944084504070937525199582998228494161581256587963350479182569767709073476305942938578516914185238354982945951325610464183760057011556336116027667431478443971789852497566022190931964624926914512000465438808202901732238917670859079331357158287446481486109341772535642821404724625886765680916122532309926171425411343129633761470730490722435328973775404176016783739955436887938755254368532747248553601029668098763389748002919821495769996090735951060509426001668094204167013619340151559257016228800996225376949328480285921295583758343588892868414107256524587102802726669931221977934082695445776450539968355018778177567062955955188598370628274906129902341525667948146220455560650547385726862123568732001996709039776914328180353694837345124024464856436018138531057521237527151154874694659679915931307604482959674167927057989516514567590062270287113788435548631219164690228588947375243868674913030414096170014455884449983476702938473784682164922729359739421419438500787506002570332539986745630166359816334300274692876831789517660550946290972807224515579551609831535687760126827024718122063108706599), 351666562595755180375395684706241055066156015118305238714672681051882280187504041643434000791814441548607213636968471872699749514579264747751265631272256072725451071040601318567317130676266378472799425651993837557182657388293299120738132040687844779805705782033358582690112156036725659897429182523487027733035393136127607866012534194708593248355973043622949956480835065663676049584885243751590721741501965828757835520710448143589654198570646114663285241248290713467857410885600973553990582698560020712556891679552160547216847450959753723375562391525266281121596206287835239825464988412752920851291059488855778730214384761750487421888963628985845627716345194071713463878260961723623247223927256636464995367615914339908375807571549256908577125462826282135037163236879694999772105827399413764752262353954388137128091790174996148478228118409615917295349567618090677194660136786354642358341440475271809799562062575133857219513963659279640385931136925337147793582596685284559585465388622433797482322409875254412068070757284707921223037714540415540426945620781055610759002438036137835981012468827444588505213686787128969359012972104378460526475214473144375243797989638951510244270960646393807997876101642432170306423462852210882508497178399, 25135373776665590901202336545666836840803391456241601649197796217462555674052551470602221560430959564950903058760936416369952872220340695429584839910539112417172641186658957618681049568598438406515601629945861509808185343104246257658988353826830801833070838727357392230011787930325906736489581750024881433299826206439672753310114100220662748513681137812457302883579006216830084552049499018274245345348857361546260882853255668574117727827869922237413735566854945952091470823515266658679062817428979342500513620275531312300114575338687577827028450767856524439798014817991240510086446185465180093752648368250982692996851, 20678485756120477969749679171411892295363660397911095536909078058504743163718110463975943096121495385121226766215138672406087647843042984392942673880078680348165649479590165596137059916732118274875699928110613763860604584697412776630385407698849636163585027765534352995283408392656841447656433417025991247442767235071030016493820494123404672276837056547392384047230316759182798179296559194938230590081605300708541927122089496849298160531622588496007433560523950635471318918140715059942293286734964890852647775755004955456829006947025556582805868127595216838587483482482814544235364358121943295803510671636196385576851
|
|
|
|
# klucz_publiczny_RSA,klucz_prywatny_RSA, p, q = genRSA()
|
|
|
|
# print(klucz_publiczny_RSA, klucz_prywatny_RSA, p, q)
|
|
|
|
# N, e = klucz_publiczny_RSA
|
|
|
|
# d = klucz_prywatny_RSA
|
|
|
|
# m = "Thats my Kung Fu".encode("ASCII")
|
|
|
|
# c = szyfrowanie_RSA_OAEP(N, e, m)
|
|
|
|
# print("szyfrgr", c)
|
|
|
|
# m = deszyfrowanie_RSA_OAEP(N, d, c)
|
|
|
|
# print(m)
|
|
|
|
# m = deszyfrowanie_RSA_OAEP_efektywne(N, d, c, p, q)
|
|
|
|
# print(m)
|
2024-06-18 22:04:24 +02:00
|
|
|
|