CryptoHack Elliptic Curves Curveball
#!/usr/bin/env python3
import fastecdsa
from fastecdsa.point import Point
from utils import listener
FLAG = "crypto{????????????????????????????????????}"
G = fastecdsa.curve.P256.G
assert G.x, G.y == [0x6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296, 0x4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5]
class Challenge():
def __init__(self):
self.before_input = "Welcome to my secure search engine backed by trusted certificate library!\n"
self.trusted_certs = {
'www.cryptohack.org': {
"public_key": Point(0xE9E4EBA2737E19663E993CF62DFBA4AF71C703ACA0A01CB003845178A51B859D, 0x179DF068FC5C380641DB2661121E568BB24BF13DE8A8968EF3D98CCF84DAF4A9),
"curve": "secp256r1",
"generator": [G.x, G.y]
},
'www.bing.com': {
"public_key": Point(0x3B827FF5E8EA151E6E51F8D0ABF08D90F571914A595891F9998A5BD49DFA3531, 0xAB61705C502CA0F7AA127DEC096B2BBDC9BD3B4281808B3740C320810888592A),
"curve": "secp256r1",
"generator": [G.x, G.y]
},
'www.gchq.gov.uk': {
"public_key": Point(0xDEDFC883FEEA09DE903ECCB03C756B382B2302FFA296B03E23EEDF94B9F5AF94, 0x15CEBDD07F7584DBC7B3F4DEBBA0C13ECD2D2D8B750CBF97438AF7357CEA953D),
"curve": "secp256r1",
"generator": [G.x, G.y]
}
}
def search_trusted(self, Q):
for host, cert in self.trusted_certs.items():
if Q == cert['public_key']:
return True, host
return False, None
def sign_point(self, g, d):
return g * d
def connection_host(self, packet):
d = packet['private_key']
if abs(d) == 1:
return "Private key is insecure, certificate rejected."
packet_host = packet['host']
curve = packet['curve']
g = Point(*packet['generator'])
Q = self.sign_point(g, d)
cached, host = self.search_trusted(Q)
if cached:
return host
else:
self.trusted_certs[packet_host] = {
"public_key": Q,
"curve": "secp256r1",
"generator": G
}
return "Site added to trusted connections"
def bing_it(self, s):
return f"Hey bing! Tell me about {s}"
#
# This challenge function is called on your input, which must be JSON
# encoded
#
def challenge(self, your_input):
host = self.connection_host(your_input)
if host == "www.bing.com":
return self.bing_it(FLAG)
else:
return self.bing_it(host)
import builtins; builtins.Challenge = Challenge
listener.start_server(port=13382)
# connect socket.cryptohack.org 13382
目的是选择 www.bing.com 通过返回 generator 参数和 private_key 参数,使得目标值为 public_key,但通过 \(kG = P\) 反推 \(k\) 是困难的,那么我们能否构造一组 \((k, \, G)\) 呢?
答案是可以的,通过查阅 secp256r1 曲线的参数可以得知:
p=FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF
a=FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC
b=5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B
Gx=6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296
Gy=4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5
n=0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551
不妨取 private_key = 2,由生成元 \(G\) 所在子群阶为 \(n\),我们容易求得一个逆元系数,如此,我们可以通过伪造生成元和私钥的方法进行攻击。
解题脚本
# sage
p = 0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF
a = 0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC
b = 0x5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B
n = 0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551
E = EllipticCurve(GF(p), [a, b])
G = E(0x6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296, 0x4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5)
target = E(0x3B827FF5E8EA151E6E51F8D0ABF08D90F571914A595891F9998A5BD49DFA3531, 0xAB61705C502CA0F7AA127DEC096B2BBDC9BD3B4281808B3740C320810888592A)
i = pow(2, -1, n)
print(int(i) * target)
# crypto{Curveballing_Microsoft_CVE-2020-0601}"

浙公网安备 33010602011771号