I'm having trouble determining when to discard a number versus when to reuse it in Techras. Any advice would be helpful!
Attachment:
#!/usr/bin/env python3
from Crypto.Util.number import *
from string import *
from flag import flag
def pad(flag):
r = len(flag) % 8
if r != 0:
flag = flag[:-1] + (8 - r) * printable[:63][getRandomRange(0, 62)].encode() + flag[-1:]
return flag
def genkey(nbit):
p, q = [getPrime(nbit) for _ in ':)']
n = p * q
return n, (p, q)
def encrypt(msg, pubkey):
msg = pad(msg)
e = getPrime(32)
m = bytes_to_long(msg)
c = pow(m, e, pubkey)
return str(c) + str(e)
nbit = 1024
pubkey, _ = genkey(nbit)
print(f'n = {pubkey}')
for _ in range(110):
print(f'c = {encrypt(flag, pubkey)}')
The problem is, the randomness of pad
is too low: only 63 possibilities. So two pad
leads to the same m
, which is encrypted using two e
. It is prone to the attack describe in https://crypto.stackexchange.com/questions/1614/rsa-cracking-the-same-message-is-sent-to-two-different-people-problem:
Steps:
c
and e
from provided output.txt
from Cryptodome.Util.number import *
lines = open("output.txt", encoding="utf-8").readlines()
n = int(lines[0].split()[2])
c = [int(line.split()[2]) for line in lines[1:]]
print(n, len(c))
# find 32-bit prime suffixes
cs = []
es = []
for i in c:
for j in range(1, 12):
part = int(str(i)[-j:])
if isPrime(part) and part.bit_length() == 32:
cs.append(int(str(i)[:-j]))
es.append(int(str(i)[-j:]))
print(cs, es)
# generated by google search
def extended_gcd(a, b):
if b == 0:
return a, 1, 0
else:
g, x1, y1 = extended_gcd(b, a % b)
x = y1
y = x1 - (a // b) * y1
return g, x, y
# find two c with the same padded message
for i in range(len(c)):
for j in range(i):
c1 = cs[i]
e1 = es[i]
c2 = cs[j]
e2 = es[j]
# if c1 = pow(m, e1, n), c2 = pow(m, e2, n)
# find e1*a+e2*b = 1
# m = pow(c1, a, n) * pow(c2, b, n) % n
# https://crypto.stackexchange.com/questions/1614/rsa-cracking-the-same-message-is-sent-to-two-different-people-problem
g, a, b = extended_gcd(e1, e2)
if g == 1:
m = pow(c1, a, n) * pow(c2, b, n) % n
flag = long_to_bytes(m)
if b"ASIS" in flag:
print(flag)
Flag: ASIS{d0nT___rEuS3___peXp!}
.