Longfellow ZK 0290cb32
Loading...
Searching...
No Matches
verify_witness.h
1// Copyright 2025 Google LLC.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#ifndef PRIVACY_PROOFS_ZK_LIB_CIRCUITS_ECDSA_VERIFY_WITNESS_H_
16#define PRIVACY_PROOFS_ZK_LIB_CIRCUITS_ECDSA_VERIFY_WITNESS_H_
17
18#include <cstddef>
19
20#include "algebra/utility.h"
21#include "arrays/dense.h"
22#include "util/panic.h"
23
24/*
25Methods to help prepare witnesses for use in assertions about ecdsa.
26*/
27namespace proofs {
28
29template <class EC, class ScalarField>
30class VerifyWitness3 {
31 using Field = typename EC::Field;
32 using Elt = typename Field::Elt;
33 using Nat = typename Field::N;
34 using Point = typename EC::ECPoint;
35 using Scalar = typename ScalarField::Elt;
36
37 public:
38 constexpr static size_t kBits = EC::kBits;
39 const ScalarField& fn_;
40 const EC& ec_;
41 Elt rx_, ry_;
42 Elt rx_inv_;
43 Elt s_inv_;
44 Elt pk_inv_;
45 Elt pre_[8];
46 Elt bi_[kBits];
47 Elt int_x_[kBits]; /* Intermediate x,y elliptic curve points */
48 Elt int_y_[kBits]; /* encountered during the scalar mult loop. */
49 Elt int_z_[kBits]; /* z-coordinate of the intermediate points */
50
51 VerifyWitness3(const ScalarField& Fn, const EC& ec) : fn_(Fn), ec_(ec) {}
52
53 void fill_witness(DenseFiller<Field>& filler) const {
54 filler.push_back(rx_);
55 filler.push_back(ry_);
56 filler.push_back(rx_inv_);
57 filler.push_back(s_inv_);
58 filler.push_back(pk_inv_);
59 for (size_t i = 0; i < 8; ++i) {
60 filler.push_back(pre_[i]);
61 }
62 for (size_t i = 0; i < kBits; ++i) {
63 filler.push_back(bi_[i]);
64 if (i < kBits - 1) {
65 filler.push_back(int_x_[i]);
66 filler.push_back(int_y_[i]);
67 filler.push_back(int_z_[i]);
68 }
69 }
70 }
71
72 // Produces witnesses to support the verification of the equation
73 // id = g*e + pk*r + (rx,ry)*-s
74 // Note that the same rx is interpreted in scalar field as r.
75 bool compute_witness(const Elt pkX, const Elt pkY, const Nat e, const Nat r,
76 const Nat s) {
77 const Field& F = ec_.f_;
78 const Scalar _s = fn_.invertf(fn_.to_montgomery(s));
79 const Scalar tms = fn_.negf(fn_.to_montgomery(s));
80
81 // Because Fp does not have a sqrt method, compute ry via the
82 // elliptic curve point g*(e/s) + pk*(r/s).
83 auto te_s = fn_.mulf(fn_.to_montgomery(e), _s);
84 auto tr_s = fn_.mulf(fn_.to_montgomery(r), _s);
85 const Nat nes = fn_.from_montgomery(te_s);
86 const Nat nrs = fn_.from_montgomery(tr_s);
87 Point bases[] = {ec_.generator(), Point(pkX, pkY, F.one())};
88 Nat scalars[] = {nes, nrs};
89 auto pr = ec_.scalar_multf(2, bases, scalars);
90 ec_.normalize(pr);
91
92 rx_ = F.to_montgomery(r);
93 ry_ = pr.y;
94
95 // In the case of a malicious input with rx=0 or s=0, the proof will fail.
96 if (rx_ != F.zero()) {
97 rx_inv_ = F.invertf(rx_);
98 check(F.mulf(rx_, rx_inv_) == F.one(), "bad inv");
99 }
100
101 s_inv_ = F.to_montgomery(fn_.from_montgomery(tms));
102 if (s_inv_ != F.zero()) {
103 F.invert(s_inv_);
104 }
105
106 if (pkX != F.zero()) {
107 pk_inv_ = F.invertf(pkX);
108 }
109
110 const Nat nms = fn_.from_montgomery(tms); /* -s */
111
112 // Produce the table of pre-computed g,r,pk sums.
113 const Elt one = F.one(), gX = ec_.gx_, gY = ec_.gy_;
114 const Elt lh[] = {gX, gY, gX, gY, pkX, pkY};
115 const Elt rh[] = {pkX, pkY, rx_, ry_, rx_, ry_};
116 Elt zi;
117 for (size_t i = 0; i < 3; ++i) {
118 ec_.addE(pre_[2 * i], pre_[2 * i + 1], zi,
119 lh[2 * i], lh[2 * i + 1], one,
120 rh[2 * i], rh[2 * i + 1], one);
121
122 // This invert cannot fail because both the generator and pk are
123 // trusted inputs, so the above addition is not the identity.
124 // In the case that it is, the proof will fail (and it should, since
125 // the system is unsound with sk=-1).
126 if (zi != F.zero()) {
127 F.invert(zi);
128 }
129 F.mul(pre_[2 * i], zi);
130 F.mul(pre_[2 * i + 1], zi);
131 }
132 // rgpk
133 ec_.addE(pre_[6], pre_[7], zi, pre_[2], pre_[3], one, pkX, pkY, one);
134 if (zi != F.zero()) {
135 F.invert(zi);
136 }
137 F.mul(pre_[6], zi);
138 F.mul(pre_[7], zi);
139
140 Elt aX = F.zero(), aY = one, aZ = F.zero();
141
142 // Compute b[], and intermediate points, encode b as:
143 // 1:g 2:pk 3: gpk 4: r 5: r+g 6: r+pk 7:g+r+pk
144 // Elt int_z[kBits];
145 size_t b[kBits];
146 // bool early_zero = false; /* indicates if any intermediate z is zero */
147 for (size_t i = 0; i < kBits; ++i) {
148 b[i] = e.bit(kBits - i - 1) + 2 * r.bit(kBits - i - 1) +
149 4 * nms.bit(kBits - i - 1);
150
151 // Manually compute standard (-n...n representation).
152 bi_[i] = F.subf(F.of_scalar(2 * b[i]), F.of_scalar(7));
153
154 if (i > 0) {
155 ec_.doubleE(aX, aY, aZ, aX, aY, aZ);
156 }
157 switch (b[i]) {
158 case 0:
159 ec_.addE(aX, aY, aZ, aX, aY, aZ, F.zero(), F.one(), F.zero());
160 break;
161 case 1:
162 ec_.addE(aX, aY, aZ, aX, aY, aZ, gX, gY, one);
163 break;
164 case 2:
165 ec_.addE(aX, aY, aZ, aX, aY, aZ, pkX, pkY, one);
166 break;
167 case 3:
168 ec_.addE(aX, aY, aZ, aX, aY, aZ, pre_[0], pre_[1], one);
169 break;
170 case 4:
171 ec_.addE(aX, aY, aZ, aX, aY, aZ, rx_, ry_, one);
172 break;
173 case 5:
174 ec_.addE(aX, aY, aZ, aX, aY, aZ, pre_[2], pre_[3], one);
175 break;
176 case 6:
177 ec_.addE(aX, aY, aZ, aX, aY, aZ, pre_[4], pre_[5], one);
178 break;
179 case 7:
180 ec_.addE(aX, aY, aZ, aX, aY, aZ, pre_[6], pre_[7], one);
181 break;
182 }
183
184 int_x_[i] = aX;
185 int_y_[i] = aY;
186 int_z_[i] = aZ;
187 }
188
189 if (aX != F.zero()) {
190 return false;
191 }
192 if (aZ != F.zero()) {
193 return false;
194 }
195
196 return true;
197 }
198};
199} // namespace proofs
200
201#endif // PRIVACY_PROOFS_ZK_LIB_CIRCUITS_ECDSA_VERIFY_WITNESS_H_
Definition dense.h:153
Definition gf2_128.h:63