from Crypto.Util.number import*defgen_key():whileTrue: p =getPrime(1024) q =2* p +1ifisPrime(q):breakreturn p * qn =gen_key()e =65537flag =open("flag.txt","rb").read()m =bytes_to_long(flag)c =pow(m, e, n)print("n = ", n)print("e = ", e)print("c = ", c)
Karena equationnya simple, kita bisa gunakan fungsi solve pada sage untuk mendapatkan nilai p
Kode diatas jika hanya c[i] += A[i][j] * m[j] maka merupakan matrix multiplication. Namun karena terdapat noise yaitu *e untuk setiap index i maka bukan hanya perkalian matrix namun terdapat perubahan di nilai akhirnya yaitu dikali dengan e. Atau bisa kita tuliskan
Jadi kalau kita bisa mendapatkan nilai e untuk setiap index i maka kita bisa lakukan multiplication inverse seperti biasa. Disini kita tahu bahwa nilai e adalah prima dengan panjang bit 16, idenya adalah melakukan faktorisasi prima untuk semua nilai c dan memfilter hanya yang 16 bit saja untuk menjadi kemungkinan nilai e. Karena setelah dicoba pada c di soal jumlahnya sangat sedikit (mayoritas hanya ada 1 nilai prima 16 bit untuk setiap index di c) maka kita bisa lakukan semua kemungkinan yang ada untuk masing-masing kemungkinan e pada setiap index. Jadi flownya adalah melakukan brute untuk kemungkinan e dimana e[i] sebagai pembagi untuk c[i] lalu tinggal multiplication inverse pada matrix. Berikut solver yang saya gunakan
from Crypto.Util.number import *
n = 29237198406447781840629726127809047660383994335982924017224165828947709888758817269330403616908753186654631934499630618269567226674757132570007351085595605345287089516753763258487567739997507428518364754926023428870567365087983926359766808760651362733024484642642130442198490208916336961141986329674270074758077168615387351540496624245321855451332339081859238865571419260611470144444333460718577949627290874422401816829724442862220140607155250782464921851735879929393939033223725572127225448491536267521471036484319582454901570581439471387728922421052405132489464009444709947629676451887119970077229329137396371678153
e = 65537
c = 5357624642921225510304458214528110256781731158227005082138032795561958182784301019426489867607735126321049257926005082018017602782337781933985047030746809420950408100455448858496355250905325511372799862570809648366646065545306516572963278402972088299653531841551844930909269487873647292645080007960390236241418753964802497472465043345321046531697603479418903526906298436978891764524534146121421596169306822115179183159612811336551281527383679899544897495492459540772355788065265764607837907724998656439578091932254136971737995959215027303360158145506983463331869617633351834924037983664699792872702481075229826916574
p = var('p')
q = 2 * p + 1
eq = solve(p * q == n , p)
sol = [i.rhs() for i in eq]
p = int(sol[0])
q = n//p
phi = (p-1)*(q-1)
d = pow(e, -1, phi)
print(long_to_bytes(pow(c, d, n)))
from Crypto.Util.number import *
def gen_matrix(n):
matrix = []
for i in range(n):
matrix.append([getRandomInteger(16) for _ in range(n)])
return matrix
def encrypt(m, A):
c = [0] * len(m)
for i in range(len(A)):
e = getPrime(16)
for j in range(len(A[i])):
c[i] += A[i][j] * m[j] * e
return c
flag = open("flag.txt", "r").read()
msg = [ord(c) for c in flag]
A = gen_matrix(len(msg))
c = encrypt(msg, A)
print("A = ", A)
print("c = ", c)
A = matrix axb
m = matrix cxd
c = mxA
c[i] *= e[i] for i in range(len(c))