github.com/consensys/gnark@v0.11.0/internal/security_tests/advisory-9xcg/advisory_test.go (about) 1 // Package advisory9xcg implements a test for advisory GHSA-9xcg-3q8v-7fq6. 2 package advisory9xcg 3 4 import ( 5 "crypto/rand" 6 "fmt" 7 "math/big" 8 "testing" 9 10 "github.com/consensys/gnark-crypto/ecc" 11 "github.com/consensys/gnark-crypto/ecc/bn254" 12 "github.com/consensys/gnark/backend/groth16" 13 groth16_bn254 "github.com/consensys/gnark/backend/groth16/bn254" 14 "github.com/consensys/gnark/frontend" 15 "github.com/consensys/gnark/frontend/cs/r1cs" 16 "github.com/consensys/gnark/test" 17 ) 18 19 type Circuit struct { 20 SecretWitness frontend.Variable `gnark:",private"` 21 } 22 23 func (circuit *Circuit) Define(api frontend.API) error { 24 // the goal of the test is to show that we are able to predict the private 25 // input solely from the stored commitment. 26 commitCompiler, ok := api.Compiler().(frontend.Committer) 27 if !ok { 28 return fmt.Errorf("compiler does not commit") 29 } 30 31 commit, err := commitCompiler.Commit(circuit.SecretWitness) 32 if err != nil { 33 return err 34 } 35 36 api.AssertIsDifferent(commit, 0) 37 api.AssertIsDifferent(circuit.SecretWitness, 0) 38 return nil 39 } 40 41 func TestAdvisory_ghsa_9xcg_3q8v_7fq6(t *testing.T) { 42 assert := test.NewAssert(t) 43 // the goal of the test is to show that we are able to predict the private 44 // input solely from the stored commitment 45 46 // Generating a random secret witness. 47 var bound int64 = 1024 // ten bits of entropy for testing 48 secretWitness, err := rand.Int(rand.Reader, big.NewInt(bound)) 49 assert.NoError(err, "random generation failed") 50 assert.Log("random secret witness: ", secretWitness) 51 52 // Assigning some values. 53 assignment := Circuit{SecretWitness: secretWitness} 54 witness, err := frontend.NewWitness(&assignment, ecc.BN254.ScalarField()) 55 assert.NoError(err, "witness creation failed") 56 witnessPublic, err := witness.Public() 57 assert.NoError(err, "witness public failed") 58 59 // Setup circuit 60 ccs, err := frontend.Compile(ecc.BN254.ScalarField(), r1cs.NewBuilder, &Circuit{}) 61 assert.NoError(err, "compilation failed") 62 63 // run the setup and prover 64 pk, vk, err := groth16.Setup(ccs) 65 assert.NoError(err, "setup failed") 66 proof, err := groth16.Prove(ccs, pk, witness) 67 assert.NoError(err, "proof failed") 68 69 // sanity check, check that the proof verifies 70 err = groth16.Verify(proof, vk, witnessPublic) 71 assert.NoError(err, "verification failed") 72 73 // we're ready to set up the attack. For that first we need to assert the 74 // exact types for being able to extract the proving key information. 75 pkConcrete, ok := pk.(*groth16_bn254.ProvingKey) 76 assert.True(ok, "unexpected type for proving key") 77 proofConcrete, ok := proof.(*groth16_bn254.Proof) 78 assert.True(ok, "unexpected type for proof") 79 80 var guessedCommitment bn254.G1Affine 81 for i := int64(0); i < bound; i++ { 82 // We check our guess for the secret witness. 83 guessedCommitment.ScalarMultiplication(&pkConcrete.CommitmentKeys[0].Basis[0], big.NewInt(int64(i))) 84 if guessedCommitment.Equal(&proofConcrete.Commitments[0]) { 85 assert.Fail("secret witness found: ", i) 86 return 87 } 88 } 89 }