defframe_dir(): root = project_root() rsa_dir = next(p for p in root.iterdir() if p.is_dir() and p.name.startswith("RSA")) challenge_dir = next(p for p in rsa_dir.iterdir() if p.is_dir()) returnnext(p for p in challenge_dir.iterdir() if p.is_dir() and"3-2"in p.name)
defload_frame(frame_id): raw = (frame_dir() / f"Frame{frame_id}").read_text().strip() n = int(raw[:256], 16) e = int(raw[256:512], 16) c = int(raw[512:], 16) return n, e, c
defegcd(a, b): if b == 0: return a, 1, 0 g, x1, y1 = egcd(b, a % b) return g, y1, x1 - a // b * y1
definvmod(a, m): g, x, _ = egcd(a, m) if g != 1: raise ValueError("inverse does not exist") return x % m
defframe_dir(): root = project_root() rsa_dir = next(p for p in root.iterdir() if p.is_dir() and p.name.startswith("RSA")) challenge_dir = next(p for p in rsa_dir.iterdir() if p.is_dir()) returnnext(p for p in challenge_dir.iterdir() if p.is_dir() and"3-2"in p.name)
defload_frame(frame_id): raw = (frame_dir() / f"Frame{frame_id}").read_text().strip() n = int(raw[:256], 16) e = int(raw[256:512], 16) c = int(raw[512:], 16) return n, e, c
defegcd(a, b): if b == 0: return a, 1, 0 g, x1, y1 = egcd(b, a % b) return g, y1, x1 - a // b * y1
definvmod(a, m): g, x, _ = egcd(a, m) if g != 1: raise ValueError("inverse does not exist") return x % m
frames = {frame_id: load_frame(frame_id) for frame_id in [1, 18]} p = math.gcd(frames[1][0], frames[18][0])
for frame_id in [1, 18]: n, e, c = frames[frame_id] q = n // p phi = (p - 1) * (q - 1) d = invmod(e, phi) m = pow(c, d, n) print(frame_id, decode_block(m))
这一组恢复出了两个分片:
序号 10:m A to B
序号 11:. Imagin
3.低指数广播攻击
Frame3/8/12/16/20 全部满足 e = 5,并且密文对应的是同一个明文分片。由于相同消息在不同模数下被重复发送,且模数彼此互素,就可以使用 Hastad 广播攻击:
defframe_dir(): root = project_root() rsa_dir = next(p for p in root.iterdir() if p.is_dir() and p.name.startswith("RSA")) challenge_dir = next(p for p in rsa_dir.iterdir() if p.is_dir()) returnnext(p for p in challenge_dir.iterdir() if p.is_dir() and"3-2"in p.name)
defload_frame(frame_id): raw = (frame_dir() / f"Frame{frame_id}").read_text().strip() n = int(raw[:256], 16) e = int(raw[256:512], 16) c = int(raw[512:], 16) return n, e, c
defegcd(a, b): if b == 0: return a, 1, 0 g, x1, y1 = egcd(b, a % b) return g, y1, x1 - a // b * y1
definvmod(a, m): g, x, _ = egcd(a, m) if g != 1: raise ValueError("inverse does not exist") return x % m
defcrt(items): mod_all = 1 for _, n in items: mod_all *= n
value = 0 for a, n in items: part = mod_all // n value = (value + a * part * invmod(part, n)) % mod_all return value
defiroot(n, k): lo = 0 hi = 1 << ((n.bit_length() + k - 1) // k) while lo < hi: mid = (lo + hi) // 2 if mid**k < n: lo = mid + 1 else: hi = mid return lo, lo**k == n