Skip to content

Commit 824ca4c

Browse files
committed
zk/qndleq: Check challenge is not congruent to zero.
1 parent 17fdcc4 commit 824ca4c

File tree

3 files changed

+68
-23
lines changed

3 files changed

+68
-23
lines changed

zk/qndleq/internal_test.go

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ import (
99
)
1010

1111
func TestForgedProofSecParamZero(t *testing.T) {
12-
p := big.NewInt(1019)
13-
q := big.NewInt(1021)
12+
// Safe primes: https://oeis.org/A005385
13+
p, q := big.NewInt(1019), big.NewInt(1187)
1414
N := new(big.Int).Mul(p, q)
1515

1616
g, err := SampleQn(rand.Reader, N)
@@ -51,11 +51,14 @@ func TestForgedProofSecParamZero(t *testing.T) {
5151
}
5252

5353
func TestChallenge(t *testing.T) {
54+
// Safe primes: https://oeis.org/A005385
55+
p, q := big.NewInt(1019), big.NewInt(1187)
56+
N := new(big.Int).Mul(p, q)
57+
5458
g, gx := big.NewInt(4), big.NewInt(16)
5559
h, hx := big.NewInt(9), big.NewInt(81)
5660
gP := big.NewInt(50)
5761
hP := big.NewInt(60)
58-
N := big.NewInt(101)
5962

6063
invalidValues := []*big.Int{
6164
new(big.Int).Neg(g), // Negative
@@ -70,3 +73,19 @@ func TestChallenge(t *testing.T) {
7073
test.CheckOk(c == nil, "challenge must be nil", t)
7174
}
7275
}
76+
77+
func TestChallengeZero(t *testing.T) {
78+
// Safe primes: https://oeis.org/A005385
79+
p, q := big.NewInt(1019), big.NewInt(1187)
80+
N := new(big.Int).Mul(p, q)
81+
g, gx := big.NewInt(4), big.NewInt(16) // 4^2 == 16 mod 101
82+
h, hx := big.NewInt(9), big.NewInt(81) // 9^2 == 81 mod 101
83+
84+
// Proof must fail as challenge is congruent to zero modulo m = (p-1)(q-1)/4.
85+
c, _ := new(big.Int).SetString("325783150686773390995072744979517913979", 10)
86+
z, _ := new(big.Int).SetString("909208770437996720153744987183938443953758507571077689625761350579371458087594451128", 10)
87+
invalidProof := Proof{z, c, 128}
88+
89+
isValid := invalidProof.Verify(g, gx, h, hx, N)
90+
test.CheckOk(isValid == false, "proof verification must fail", t)
91+
}

zk/qndleq/qndleq.go

Lines changed: 39 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -72,30 +72,52 @@ func SampleQn(random io.Reader, N *big.Int) (*big.Int, error) {
7272
func Prove(random io.Reader, x, g, gx, h, hx, N *big.Int, secParam uint) (*Proof, error) {
7373
rSizeBits := uint(N.BitLen()) + 2*secParam
7474
rSizeBytes := (rSizeBits + 7) / 8
75-
7675
rBytes := make([]byte, rSizeBytes)
77-
_, err := io.ReadFull(random, rBytes)
78-
if err != nil {
79-
return nil, err
80-
}
81-
r := new(big.Int).SetBytes(rBytes)
8276

83-
gP := new(big.Int).Exp(g, r, N)
84-
hP := new(big.Int).Exp(h, r, N)
77+
ONE := big.NewInt(1)
78+
NUM_TRIES := 10
79+
var r, gP, hP, gc, hc big.Int
80+
for i := 0; i < NUM_TRIES; i++ {
81+
_, err := io.ReadFull(random, rBytes)
82+
if err != nil {
83+
return nil, err
84+
}
8585

86-
c, err := doChallenge(g, gx, h, hx, gP, hP, N, secParam)
87-
if err != nil {
88-
return nil, err
89-
}
86+
r.SetBytes(rBytes)
87+
gP.Exp(g, &r, N)
88+
hP.Exp(h, &r, N)
9089

91-
z := new(big.Int)
92-
z.Mul(c, x).Add(z, r)
90+
c, err := doChallenge(g, gx, h, hx, &gP, &hP, N, secParam)
91+
if err != nil {
92+
return nil, err
93+
}
9394

94-
return &Proof{z, c, secParam}, nil
95+
// Challenge must not be congruent to zero.
96+
// c != 0 mod m, where m = (p-1)(q-1)/4, and N = p*q.
97+
// Check this by doing an Exp because m is unknown.
98+
gc.Exp(g, c, N)
99+
hc.Exp(h, c, N)
100+
if gc.Cmp(ONE) != 0 && hc.Cmp(ONE) != 0 {
101+
z := new(big.Int).Mul(c, x)
102+
z.Add(z, &r)
103+
return &Proof{z, c, secParam}, nil
104+
}
105+
}
106+
107+
return nil, ErrProve
95108
}
96109

97110
// Verify checks whether x = Log_g(g^x) = Log_h(h^x).
98111
func (p Proof) Verify(g, gx, h, hx, N *big.Int) bool {
112+
// Check c != 0 (mod m), where m = (p-1)(q-1)/4,
113+
// by doing an Exp as m is unknown.
114+
ONE := big.NewInt(1)
115+
gc := new(big.Int).Exp(g, p.c, N)
116+
hc := new(big.Int).Exp(h, p.c, N)
117+
if gc.Cmp(ONE) == 0 || hc.Cmp(ONE) == 0 {
118+
return false
119+
}
120+
99121
gPNum := new(big.Int).Exp(g, p.z, N)
100122
gPDen := new(big.Int).Exp(gx, p.c, N)
101123
ok := gPDen.ModInverse(gPDen, N)
@@ -193,4 +215,6 @@ var (
193215
ErrSecParam = errors.New("zk/qndleq: the security parameter must be greater than 128")
194216
// ErrBounds is returned when a value is not in the range 0 to N.
195217
ErrBounds = errors.New("zk/qndleq: input must be greater than 0 and less than N")
218+
// ErrProve is returned when Prove cannot produce a proof.
219+
ErrProve = errors.New("zk/qndleq: Prove cannot produce a proof")
196220
)

zk/qndleq/qndleq_test.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,16 @@ func TestProve(t *testing.T) {
3535
}
3636

3737
func TestInvalidStatement(t *testing.T) {
38-
g, gx := big.NewInt(4), big.NewInt(16) // 4^2 == 16 mod 101
39-
h, hx := big.NewInt(9), big.NewInt(81) // 9^2 == 81 mod 101
40-
N := big.NewInt(101)
38+
// Safe primes: https://oeis.org/A005385
39+
p, q := big.NewInt(1019), big.NewInt(1187)
40+
N := new(big.Int).Mul(p, q)
41+
g, gx := big.NewInt(4), big.NewInt(16) // 4^2 == 16
42+
h, hx := big.NewInt(9), big.NewInt(81) // 9^2 == 81
4143
incorrectX := big.NewInt(3)
4244

43-
p, err := qndleq.Prove(rand.Reader, incorrectX, g, gx, h, hx, N, 128)
45+
proof, err := qndleq.Prove(rand.Reader, incorrectX, g, gx, h, hx, N, 128)
4446
test.CheckNoErr(t, err, "an alleged proof must be computed")
45-
isValid := p.Verify(g, gx, h, hx, N)
47+
isValid := proof.Verify(g, gx, h, hx, N)
4648
test.CheckOk(isValid == false, "proof verification must fail", t)
4749
}
4850

0 commit comments

Comments
 (0)