summaryrefslogtreecommitdiffstats
path: root/solve/solve.py
diff options
context:
space:
mode:
authorLouis Burda <quent.burda@gmail.com>2024-05-25 00:52:54 +0200
committerLouis Burda <quent.burda@gmail.com>2024-05-25 00:52:54 +0200
commita7f46b9f7c31c7ae936588b969bae92d561aebaa (patch)
tree14f9c2b664cf526a97da2c69700d2616b5c6ac46 /solve/solve.py
downloadcscg2020-cry3-master.tar.gz
cscg2020-cry3-master.zip
Add challenge files and solutionHEADmaster
Diffstat (limited to 'solve/solve.py')
-rw-r--r--solve/solve.py37
1 files changed, 37 insertions, 0 deletions
diff --git a/solve/solve.py b/solve/solve.py
new file mode 100644
index 0000000..4f38cde
--- /dev/null
+++ b/solve/solve.py
@@ -0,0 +1,37 @@
+#!/usr/bin/env python3
+
+from Crypto.PublicKey import RSA
+from Crypto.Util.number import long_to_bytes
+from gmpy2 import iroot
+from sympy import primefactors
+
+# Hastad Boardcast: Multiple unpadded ciphertexts with small e.
+# Use Chinese Remainder Theorem to extract plaintext.
+# Possible since N1*N2*N3 larger than M^e for e = 3.
+
+recipients = [
+ RSA.importKey(open("german_government.pem").read()),
+ RSA.importKey(open("us_government.pem").read()),
+ RSA.importKey(open("russian_government.pem").read()),
+]
+ciphertexts = [int(l.split(": ")[1]) for l in open("intercepted-messages.txt").readlines()]
+
+# C1 = K mod N1, C2 = K mod N2, C3 = K mod N3
+# K = C1 * N2 * N3 * pow(N2 * N3, -1, N1) + ... (mod N1 * N2 * N3)
+# K % N1 = C1 * N2 * N3 * pow(N2 * N3, -1, N1) = C1
+
+N = 1
+for r in recipients:
+ assert(r.e == 3)
+ N *= r.n
+
+K = 0
+for i in range(3):
+ K += ciphertexts[i] * (N // recipients[i].n) \
+ * pow(N // recipients[i].n, -1, recipients[i].n)
+K %= N
+
+plaintext, real = iroot(K, 3)
+assert(real)
+
+print(long_to_bytes(plaintext).decode().lstrip("A"))