Challenge Description 1 ECC + RSA = Double security!
Attachment - ecc-rsa.py
- ecc-rsa.txt
ecc-rsa.py 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 from fastecdsa.curve import P521 as Curvefrom fastecdsa.point import Pointfrom Crypto.Util.number import bytes_to_long, isPrimefrom os import urandomfrom random import getrandbitsdef gen_rsa_primes (G ): urand = bytes_to_long(urandom(521 //8 )) while True : s = getrandbits(521 ) ^ urand Q = s*G if isPrime(Q.x) and isPrime(Q.y): print ("ECC Private key:" , hex (s)) print ("RSA primes:" , hex (Q.x), hex (Q.y)) print ("Modulo:" , hex (Q.x * Q.y)) return (Q.x, Q.y) flag = int .from_bytes(input (), byteorder="big" ) ecc_p = Curve.p a = Curve.a b = Curve.b Gx = Curve.gx Gy = Curve.gy G = Point(Gx, Gy, curve=Curve) e = 0x10001 p, q = gen_rsa_primes(G) n = p*q file_out = open ("downloads/ecc-rsa.txt" , "w" ) file_out.write("ECC Curve Prime: " + hex (ecc_p) + "\n" ) file_out.write("Curve a: " + hex (a) + "\n" ) file_out.write("Curve b: " + hex (b) + "\n" ) file_out.write("Gx: " + hex (Gx) + "\n" ) file_out.write("Gy: " + hex (Gy) + "\n" ) file_out.write("e: " + hex (e) + "\n" ) file_out.write("p * q: " + hex (n) + "\n" ) c = pow (flag, e, n) file_out.write("ciphertext: " + hex (c) + "\n" )
ecc-rsa.txt 1 2 3 4 5 6 7 8 ECC Curve Prime: 0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff Curve a: -0x3 Curve b: 0x51953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00 Gx: 0xc6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66 Gy: 0x11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650 e: 0x10001 p * q: 0x1d61da34917e872315d41403c6a59911be97ba4673b0ff1e40201a7c7381845716d1e2f3906f226f649d663af7d9f68e0029629ff9bb07991db2bdff13adad242e9c4c06c6b5cf1ca5fa20eae64f1cdc2376651a4a7f7610e71257ce5da3cc8389c80797a2a9952bcd8c165d0dd5eef523ceb96748eb5aa66d0b4959dcef6a53dac5 ciphertext: 0x12fc466fa277837af8f20c59144d22e80fe4f9ab7371668487cdea44ff1677655d8628aacb688747c2bca111c3b34fa034b9915736fc614c3233bf6445d5ee90eac16a218770f296885bd997989f64a2e70324bba4171ad39759435b4f6d598952e6600eb663d5d9a210baa7134b1aa556aa56a092e7414127a1c35a3bbb1cbb455c
Observation We can notice that the primes are generated using a custom function named gen_rsa_primes
, and that function gets a random point of the given elliptic curve and checks if both co-ordinates are primes and thus maintain a relationship between the primes, and that relation is the equation of the curve.
means: y^2 = x^3 + a*x + b =>=> q^2 = p^3 + a*p + b
Exploit Idea - Recover primes using the relation
- Decrypt the Ciphertext to get the Flag
Recovering Primes using the curve equation 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 lines = open ("downloads/ecc-rsa.txt" , "r" ).read().split("\n" ) p = ZZ(lines[0 ].split(" " )[-1 ]) a = ZZ(lines[1 ].split(" " )[-1 ]) b = ZZ(lines[2 ].split(" " )[-1 ]) e = ZZ(lines[5 ].split(" " )[-1 ]) n = ZZ(lines[6 ].split(" " )[-1 ]) c = ZZ(lines[7 ].split(" " )[-1 ]) P = GF(p) E = EllipticCurve(P, [a, b]) G = E(Gx, Gy) F. < x > = PolynomialRing(P) f = x ^ 5 + a*x ^ 3 + b*x ^ 2 - n ^ 2 p = [int (i[0 ]) for i in f.roots() if int (n) % int (i[0 ]) == 0 ][0 ] q = n//q
Decryption 1 2 3 4 5 6 phi = (p-1 )*(q-1 ) d = invert(e, phi) m = pow (c, d, n) flag = b'watevr{' + long_to_bytes(m) + b'}'
Exploit 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 lines = open ("downloads/ecc-rsa.txt" , "r" ).read().split("\n" ) p = ZZ(lines[0 ].split(" " )[-1 ]) a = ZZ(lines[1 ].split(" " )[-1 ]) b = ZZ(lines[2 ].split(" " )[-1 ]) e = ZZ(lines[5 ].split(" " )[-1 ]) n = ZZ(lines[6 ].split(" " )[-1 ]) c = ZZ(lines[7 ].split(" " )[-1 ]) P = GF(p) E = EllipticCurve(P, [a, b]) G = E(Gx, Gy) F. < x > = PolynomialRing(P) f = x ^ 5 + a*x ^ 3 + b*x ^ 2 - n ^ 2 p = [int (i[0 ]) for i in f.roots() if int (n) % int (i[0 ]) == 0 ][0 ] q = n//q phi = (p-1 )*(q-1 ) d = invert(e, phi) m = pow (c, d, n) flag = b'watevr{' + long_to_bytes(m) + b'}' assert flag == b'watevr{lol}'
Flag
b’watevr{lol}’