Skip to content

Instantly share code, notes, and snippets.

@Heasummn
Last active June 25, 2021 03:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Heasummn/7753a55182b5be1c424570468429483b to your computer and use it in GitHub Desktop.
Save Heasummn/7753a55182b5be1c424570468429483b to your computer and use it in GitHub Desktop.

Zero Knowledge Proofs are super interesting. There is a large assortment of literature dedicated to studying commitment schemes, soundness, and completeness.

Thankfully, we can just ignore all that literature and come up with a random number.

In this challenge, we are assuming that the prover (the server that we connect to and query), will commit all of its values before we check a given clause. Since this is a standard 3-SAT problem, the clauses are recorded in conjunctive normal form (a fancy way to say that they are all OR'd together), and each clause must evaluate to True. So, a perfect prover will never have a clause that consists of all Falses. This allows us to write a simple check for a bad prover:

if True not in arr:
  r.sendline('false')
  break

Then, we just need to figure out how many times we need to see the prover give a correct response before we are certain (with 1-p probability) that it is a correct prover. This is a slightly complex analysis involving the number of clauses and literals to find an exact number, but that's a lot of work. Instead, we can make up a number that feels good enough:

else:
  num_correct += 1
  if num_correct >= 25:
    r.sendline('true')
    break
  else:
    r.sendline('next')

The final script includes some boilerplate to read the inputs and makes use of the naughty eval. Please don't judge.

from pwn import *
import random
r = remote('zkp.hsc.tf', 1337)

print(r.readline())
trials = int(r.readline())
for i in range(trials):
  print("starting trial", i)
  literals = int(r.readline())
  clauses = int(r.readline())
  print(literals, clauses)
  num_correct = 0

  while True:
    r.readline()
    r.read()
    r.sendline(str(random.randint(1, clauses))) # send clause number
    arr = eval(r.readline())
    # print(arr, num_correct)
    if True not in arr:
      r.sendline('false')
      break
    else:
      num_correct += 1
      if num_correct >= 25:
        r.sendline('true')
        break
      else:
        r.sendline('next')

r.interactive()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment