Crypto-Snore Signatures

These signatures are a bore! - Richard

Challenge

def main():
    p, q, g = gen_snore_group()
    print(f"p = {p}")
    print(f"q = {q}")
    print(f"g = {g}")

    queries = []
    for _ in range(10):
        x, y = snore_gen(p, q, g)
        print(f"y = {y}")

        print('you get one query to the oracle')

        m = int(input("m = "))
        queries.append(m)
        s, e = snore_sign(p, q, g, x, m)
        print(f"s = {s}")
        print(f"e = {e}")

        print('can you forge a signature?')
        m = int(input("m = "))
        s = int(input("s = "))
        # you can't change e >:)
        if m in queries:
            print('nope')
            return
        if not snore_verify(p, q, g, y, m, s, e):
            print('invalid signature!')
            return
        queries.append(m)
        print('correct signature!')

    print('you win!')
    print(open('flag.txt').read())

First, we see how the signatures are being created

p=X(X mod 2q)+1p=2kq+1r=2kg=hr mod pp = X - (X \ mod \ 2q) + 1 \\ p = 2kq +1 \\ r = 2k \\ g = h^r \ mod \ p
r=gkmodpe=hash((r+m1) mod p) mod qs=k+xemodqk=sxemodqr = g^k \mod p \\ e = hash((r+m_1) \ mod \ p) \ mod \ q\\ s = k+xe \mod q \\ k = s-xe \mod q

The server allows us to sign a message m and gives us s,e

In the signature verification, we need to give s,m such that hash(rv+m) == e

rv=gs×ye mod prv=gs×gxe mod prv=gsxe mod pev=hash((rv+m2) mod p) mod qrv = g^s \times y^e \ mod \ p \\ rv = g^s \times g^{-xe} \ mod \ p \\ rv = g^{s-xe} \ mod \ p \\ ev = hash((rv + m_2) \ mod \ p ) \ mod \ q \\

If we give the same s and m we used to sign then

rv=gsxemodprv=gkmodpr=gkmodpev=hash((rv+m) mod p) mod qe=hash((r+m) mod p) mod qev==erv = g^{s-xe} \mod p \\ rv = g^k \mod p \\ r = g^k \mod p \\ ev = hash((rv + m) \ mod \ p ) \ mod \ q \\ e = hash((r+m) \ mod \ p) \ mod \ q \\ ev ==e

However, the server has a condition which doesn't allow us to repeat the same message for signature and verification. So, we need to find m1 and m2 such that

hash((rv+m1) mod p) mod q=hash((r+m2) mod p) mod qrv+m1r+m2(modp)m1m2(modp)hash((rv + m_1) \ mod \ p ) \ mod \ q =hash((r+m_2) \ mod \ p) \ mod \ q \\ rv+m_1\equiv r+m2 \pmod p \\ m_1 \equiv m2 \pmod p

We can send m1 and m2 as multiples of p to bypass this condition and forge the signature.

Last updated