Longfellow ZK 0290cb32

Loading...
Searching...
No Matches
ptrcred.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_ANONCRED_PTRCRED_H_
16#define PRIVACY_PROOFS_ZK_LIB_CIRCUITS_ANONCRED_PTRCRED_H_
17#include <cstddef>
18#include <vector>
19
20#include "circuits/anoncred/small_io.h"
21#include "circuits/compiler/compiler.h"
22#include "circuits/ecdsa/verify_circuit.h"
23#include "circuits/logic/bit_plucker.h"
24#include "circuits/logic/memcmp.h"
25#include "circuits/logic/routing.h"
26#include "circuits/sha/flatsha256_circuit.h"
27
28 namespace proofs {
29
30// This class creates a circuit to verify the signatures in a "ptrcred".
31// A ptr credential is a document formatted as:
32// n // 8 bits specifying the number of attributes
33// ind <table of n pointer, each of 10 bits>
34// each pointer references from the beginning of the document
35// A byte string containing keys and values.
36// A key consists of 3 bytes.
37// A value can be arbitrarily long.
38 template <class LogicCircuit, class Field, class EC, size_t kNumAttr>
39 class PtrCred {
40 using EltW = typename LogicCircuit::EltW;
41 using Elt = typename LogicCircuit::Elt;
42 using Nat = typename Field::N;
43 using Ecdsa = VerifyCircuit<LogicCircuit, Field, EC>;
44 using EcdsaWitness = typename Ecdsa::Witness;
45
46 using v8 = typename LogicCircuit::v8;
47 using v32 = typename LogicCircuit::v32;
48 static constexpr size_t kIndexBits = 5;
49 static constexpr size_t kMaxSHABlocks = 3;
50 static constexpr size_t kMaxMsoLen = kMaxSHABlocks * 64 - 9;
51
52 using vind = typename LogicCircuit::template bitvec<kIndexBits>;
53 using Flatsha = FlatSHA256Circuit<LogicCircuit, BitPlucker<LogicCircuit, 3>>;
54 using RoutingL = Routing<LogicCircuit>;
55 using ShaBlockWitness = typename Flatsha::BlockWitness;
56
57 const LogicCircuit& lc_;
58 const EC& ec_;
59 const Nat& order_;
60
61 public:
62 class Witness {
63 public:
64 EltW e_;
65 EltW dpkx_, dpky_;
66
67 EcdsaWitness sig_;
68 EcdsaWitness dpk_sig_;
69
70 v8 in_[64 * kMaxSHABlocks]; /* input bytes, 64 * MAX */
71 v8 nb_; /* index of sha block that contains the real hash */
72 ShaBlockWitness sig_sha_[kMaxSHABlocks];
73
74 void input(QuadCircuit<Field>& Q, const LogicCircuit& lc) {
75 e_ = Q.input();
76 dpkx_ = Q.input();
77 dpky_ = Q.input();
78
79 sig_.input(Q);
80 dpk_sig_.input(Q);
81
82 nb_ = lc.template vinput<8>();
83
84 // sha input init =========================
85 for (size_t i = 0; i < 64 * kMaxSHABlocks; ++i) {
86 in_[i] = lc.template vinput<8>();
87 }
88 for (size_t j = 0; j < kMaxSHABlocks; j++) {
89 sig_sha_[j].input(Q);
90 }
91 }
92 };
93
94 struct OpenedAttribute {
95 v8 ind; /* index of attribute */
96 v8 len; /* length of attribute, 1--32 */
97 v8 v1[32]; /* attribute value */
98 void input(const LogicCircuit& lc) {
99 ind = lc.template vinput<8>();
100 len = lc.template vinput<8>();
101 for (size_t j = 0; j < 32; ++j) {
102 v1[j] = lc.template vinput<8>();
103 }
104 }
105 };
106
107 EltW repack(const v8 in[], size_t ind) const {
108 EltW h = lc_.konst(0);
109 EltW base = lc_.konst(0x2);
110 for (size_t i = 0; i < 32; ++i) {
111 for (size_t j = 0; j < 8; ++j) {
112 auto t = lc_.mul(&h, base);
113 auto tin = lc_.eval(in[ind + i][7 - j]);
114 h = lc_.add(&tin, t);
115 }
116 }
117 return h;
118 }
119
120 explicit PtrCred(const LogicCircuit& lc, const EC& ec, const Nat& order)
121 : lc_(lc), ec_(ec), order_(order), sha_(lc), r_(lc) {}
122
123 void assert_credential(EltW pkX, EltW pkY, EltW hash_tr,
124 OpenedAttribute oa[/* NUM_ATTR */],
125 const v8 now[/*kDateLen*/], const Witness& vw) const {
126 Ecdsa ecc(lc_, ec_, order_);
127
128 ecc.verify_signature3(pkX, pkY, vw.e_, vw.sig_);
129 ecc.verify_signature3(vw.dpkx_, vw.dpky_, hash_tr, vw.dpk_sig_);
130 sha_.assert_message(kMaxSHABlocks, vw.nb_, vw.in_, vw.sig_sha_);
131
132 const Memcmp<LogicCircuit> CMP(lc_);
133 // validFrom <= now
134 lc_.assert1(CMP.leq(kDateLen, &vw.in_[84], &now[0]));
135
136 // now <= validUntil
137 lc_.assert1(CMP.leq(kDateLen, &now[0], &vw.in_[92]));
138
139 // DPK_{x,y}
140 EltW dpkx = repack(vw.in_, 100);
141 EltW dpky = repack(vw.in_, 132);
142 lc_.assert_eq(&dpkx, vw.dpkx_);
143 lc_.assert_eq(&dpky, vw.dpky_);
144
145 // Attributes parsing
146 const v8 zz = lc_.template vbit<8>(0xff); // cannot appear in strings
147 std::vector<v8> cmp_buf(32);
148 for (size_t ai = 0; ai < kNumAttr; ++ai) {
149 r_.shift(oa[ai].ind, 32, &cmp_buf[0], kMaxMsoLen, vw.in_, zz, 3);
150 assert_attribute(32, oa[ai].len, &cmp_buf[0], &oa[ai].v1[0]);
151 }
152 }
153
154 private:
155 // Checks that an attribute id or attribute value is as expected.
156 // The len parameter holds the byte length of the expected id or value.
157 void assert_attribute(size_t max, const v8& vlen, const v8 got[/*max*/],
158 const v8 want[/*max*/]) const {
159 for (size_t j = 0; j < max; ++j) {
160 auto ll = lc_.vlt(j, vlen);
161 auto cmp = lc_.veq(got[j], want[j]);
162 lc_.assert_implies(&ll, cmp);
163 }
164 }
165
166 Flatsha sha_;
167 RoutingL r_;
168};
169
170} // namespace proofs
171
172#endif // PRIVACY_PROOFS_ZK_LIB_CIRCUITS_ANONCRED_PTRCRED_H_
proofs::FlatSHA256Circuit
Definition flatsha256_circuit.h:52
proofs::PtrCred::Witness
Definition ptrcred.h:62
proofs::QuadCircuit
Definition compiler.h:50
proofs::Routing
Definition routing.h:108
proofs::VerifyCircuit
Definition verify_circuit.h:32
proofs::PtrCred::OpenedAttribute
Definition ptrcred.h:94
proofs::VerifyCircuit::Witness
Definition verify_circuit.h:41