Longfellow ZK 0290cb32
Loading...
Searching...
No Matches
mdoc_signature.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_MDOC_MDOC_SIGNATURE_H_
16#define PRIVACY_PROOFS_ZK_LIB_CIRCUITS_MDOC_MDOC_SIGNATURE_H_
17
18#include <cstddef>
19
20#include "circuits/compiler/compiler.h"
21#include "circuits/ecdsa/verify_circuit.h"
22#include "circuits/logic/bit_plucker.h"
23#include "circuits/mac/mac_circuit.h"
24
25namespace proofs {
26
27// This class creates a circuit to verify the signatures in an MDOC.
28// There are 2 signatures:
29// 1. A signature on the MSO by the issuer of the MDOC: The public
30// key of the issuer is given as input for now. Later, it can be
31// one among a list of issuers. While the signer is public, the
32// message is private, and thus its hash is committed in the witness.
33// 2. A signature on the transcript provided during a "Show" operation:
34// the signature is under a device public key that is specified in the
35// MSO. Thus, the signing key is private (and committed), but the
36// message is public.
37template <class LogicCircuit, class Field, class EC>
38class MdocSignature {
39 using EltW = typename LogicCircuit::EltW;
40 using Elt = typename LogicCircuit::Elt;
41 using Nat = typename Field::N;
42 using v128 = typename LogicCircuit::v128;
43 using v256 = typename LogicCircuit::v256;
45 using EcdsaWitness = typename Ecdsa::Witness;
47 using packed_v256 = typename MacBitPlucker::packed_v256;
49 using MACWitness = typename mac::Witness;
50
51 const LogicCircuit& lc_;
52 const EC& ec_;
53 const Nat& order_;
54
55 public:
56 class Witness {
57 public:
58 EltW e_;
59 EltW dpkx_, dpky_;
60
61 EcdsaWitness mdoc_sig_;
62 EcdsaWitness dpk_sig_;
63 MACWitness macs_[3];
64
65 void input(QuadCircuit<Field>& Q, const LogicCircuit& lc) {
66 e_ = Q.input();
67 dpkx_ = Q.input();
68 dpky_ = Q.input();
69
70 mdoc_sig_.input(Q);
71 dpk_sig_.input(Q);
72 for (size_t i = 0; i < 3; ++i) {
73 macs_[i].input(lc, Q);
74 }
75 }
76 };
77
78 explicit MdocSignature(const LogicCircuit& lc, const EC& ec, const Nat& order)
79 : lc_(lc), ec_(ec), order_(order) {}
80
81 // This function is used to verify the signatures in an MDOC.
82 // The circuit verifies the following claims:
83 // 1. There exists a hash digest e and a signature (r,s) on e
84 // under the public key (pkX, pkY).
85 // 2. The MAC of e under the secret mac key (a_v+a_pe) is mac_e.
86 // 3. There exists a device public key (dpkX, dpky) and a signature (r,s)
87 // on the value hash_tr.
88 // 4. The MAC of the device public key (dpkX, dpky) under the secret MAC
89 // key (a_v + apdk) is mac_dkpX and mac_dpkY respectively.
90 void assert_signatures(EltW pkX, EltW pkY, EltW hash_tr, v128 mac_e[2],
91 v128 mac_dpkX[2], v128 mac_dpkY[2], v128 a_v,
92 Witness& vw) const {
93 Ecdsa ecc(lc_, ec_, order_);
94 mac macc(lc_);
95
96 ecc.verify_signature3(pkX, pkY, vw.e_, vw.mdoc_sig_);
97 ecc.verify_signature3(vw.dpkx_, vw.dpky_, hash_tr, vw.dpk_sig_);
98
99 macc.verify_mac(vw.e_, mac_e, a_v, vw.macs_[0], order_);
100 macc.verify_mac(vw.dpkx_, mac_dpkX, a_v, vw.macs_[1], order_);
101 macc.verify_mac(vw.dpky_, mac_dpkY, a_v, vw.macs_[2], order_);
102 }
103
104 // This function is similar to assert_signatures, but it also hides the
105 // public key of the issuer. Instead, it verifies that the issuer's public
106 // key belongs in a list of 50 public keys that are supplied as input. The
107 // issuer pk lists are assumed to be trusted inputs, i.e., it is the
108 // caller's responsibility to ensure that (issuer_pkX[i], issuer_pkY[i]) is
109 // a valid curve point for i=0..49. The caller is also responsible for
110 // ensuring that issuer_pkY[i] != -issuer_pkY[j] for i != j.
111 // However, it is OK for the caller to repeat the same key in the list.
112 void assert_signatures_with_issuer_list(
113 EltW hash_tr, v128 mac_e[2], v128 mac_dpkX[2], v128 mac_dpkY[2], v128 a_v,
114 EltW issuer_pkX[/*max_issuers*/], EltW issuer_pkY[/*max_issuers*/],
115 size_t max_issuers,
116 // private inputs begin here
117 EltW pkX, EltW pkY, Witness& vw) const {
118 assert_signatures(pkX, pkY, hash_tr, mac_e, mac_dpkX, mac_dpkY, a_v, vw);
119
120 // Verify that the issuer's public key is one of the 50 keys in the list.
121 // This is done by computing the difference between pkX and issuer_pkX[i]
122 // for i=0..49, and asserting that the product of the differences is zero.
123 //
124 // We argue that it suffices to verify that pkX is on the list and pkY is
125 // on the list independently. Suppose a malicious prover sets pkX to be
126 // equal to the j-th key in issuer_pkX and sets pkY to be the k-th key in
127 // issuer_pkY, where j != k. If (pkX, pkY) is not a curve point, then the
128 // assert_signatures() routine will fail. However, for each X on the curve,
129 // there are only 2 possible Y values, namely, +-Y. By the constraints
130 // imposed on issuer_pkY, we know that issuer_pkY[j] is on the curve, and
131 // that -issuer_pkY[j] does not occur in the issuer_pkY list. Thus, it is
132 // not possible for a witness to pass all checks and for k != j.
133 EltW goodXKey = lc_.mul(0, max_issuers, [&](size_t i) {
134 return lc_.sub(&issuer_pkX[i], pkX);
135 });
136 lc_.assert0(goodXKey);
137
138 EltW goodYKey = lc_.mul(0, max_issuers, [&](size_t i) {
139 return lc_.sub(&issuer_pkY[i], pkY);
140 });
141 lc_.assert0(goodYKey);
142 }
143};
144} // namespace proofs
145
146#endif // PRIVACY_PROOFS_ZK_LIB_CIRCUITS_MDOC_MDOC_SIGNATURE_H_
Definition bit_plucker.h:86
Definition mac_circuit.h:49
Definition mdoc_signature.h:56
Definition compiler.h:50
Definition verify_circuit.h:32
Definition verify_circuit.h:41