xref: /aosp_15_r20/external/federated-compute/fcp/secagg/shared/secagg_messages.proto (revision 14675a029014e728ec732f129a32e299b2da0601)
1/*
2 * Copyright 2017 Google LLC
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17// Definition of the protocol buffers for the SecAgg protocol
18
19syntax = "proto3";
20
21package fcp.secagg;
22
23import "google/protobuf/any.proto";
24
25option java_package = "fcp.secagg.shared";
26option java_outer_classname = "SecAggMessages";
27
28// TODO(team): remove container class, using
29// option java_multiple_files = true;
30
31// # MESSAGE WRAPPERS EXPOSED TO THE OUTSIDE
32
33// This message is a wrapper (simulating polymorphism) for all messages sent
34// from a client to the server during the protocol.
35message ClientToServerWrapperMessage {
36  // Each message from client to server contains exactly one of these
37  // semantic types, depending on the phase of the protocol.
38  oneof message_content {
39    // Abort the protocol.
40    AbortMessage abort = 1;
41
42    // Round 0 message; see details at message definition.
43    AdvertiseKeys advertise_keys = 2;
44
45    // Round 1 message; see details at message definition.
46    ShareKeysResponse share_keys_response = 3;
47
48    // Round 2 message; see details at message definition.
49    MaskedInputCollectionResponse masked_input_response = 4;
50
51    // Round 3 message; see details at message definition.
52    UnmaskingResponse unmasking_response = 5;
53  }
54}
55
56// This message is a wrapper (simulating polymorphism) for all messages sent
57// from the server to a client during the protocol.
58message ServerToClientWrapperMessage {
59  // Each message from server to client contains exactly one of these
60  // semantic types, depending on the phase of the protocol.
61  oneof message_content {
62    // Abort the protocol.
63    AbortMessage abort = 1;
64
65    // Round 1 message; see details at message definition.
66    ShareKeysRequest share_keys_request = 2;
67
68    // Round 2 message; see details at message definition.
69    MaskedInputCollectionRequest masked_input_request = 3;
70
71    // Round 3 message; see details at message definition.
72    UnmaskingRequest unmasking_request = 4;
73  }
74}
75
76// # MESSAGES INTERNAL TO THE LIBRARY
77
78// ## ABORT MESSAGE
79// Sent by the server to the client to cause the client to abort and erase all
80// the state relate to the current session. Can signify either an abort due to
81// some error or an abort because the server needs no more messages.
82// Sent by the client to the server to notify it that the sending client
83// aborted.
84message AbortMessage {
85  // Can contain optional logging/diagnostic info.
86  string diagnostic_info = 1;
87  // If true, the client will halt early but mark the protocol as a success,
88  // rather than as aborted.
89  bool early_success = 2;
90}
91
92// ## ROUND 0 MESSAGES: ADVERTISE KEYS
93// AdvertiseKeys is sent by clients who wish to participate in the protocol.
94
95// Part of a ClientToServerWrapperMessage. Contains a pair of public keys.
96message AdvertiseKeys {
97  // Pair of public keys for this client.
98  PairOfPublicKeys pair_of_public_keys = 1;
99}
100
101// A pair of public keys. Used as part of AdvertiseKeys and ShareKeysRequest.
102// TODO(team): move away from comprossed encoding of ECPoint into
103// encoding the complete PublicKey, including the other parameters.
104message PairOfPublicKeys {
105  // An encoding of the Diffie Hellman public key used to generate correlated
106  // noise to be added to ciphertexts.
107  // The encoding used is the one returned by the getEncoded(compressed=true)
108  // method of the class org.bouncycastle.math.ec.ECPoint
109  // TODO(team): figure out the actual encoding used.
110  bytes noise_pk = 1;
111
112  // An encoding of the Diffie Hellman public key used to establish private
113  // channels between the protocol parties.
114  // The encoding used is the one returned by the getEncoded(compressed=true)
115  // method of the class org.bouncycastle.math.ec.ECPoint
116  // TODO(team): figure out the actual encoding used.
117  bytes enc_pk = 2;
118}
119
120// ## ROUND 1 MESSAGES: SHARE KEYS
121// Clients who are selected to participate in the protocol receive a list of the
122// (pairs of) public keys of all other clients. Each client secret-shares its
123// own noise_sk and prf_sk with all the other clients (encrypting shares for
124// client j with their own enc_pk) and sends all these encrypted shares to the
125// server for distribution.
126
127// Part of a ServerToClientWrapperMessage. Contains a list of pairs of public
128// keys, as well as the logging ID for the SecAgg execution.
129message ShareKeysRequest {
130  // List of public keys for all clients, ordered by the clients'
131  // logical ids. Each client infers its logical id "i" from the
132  // position "i" of its pair of keys in the list.
133  // Note that the logical ids are assumed to be 1-indexed (i.e. the first
134  // public key in the repeated field corresponds to client with logical id 1)
135  repeated PairOfPublicKeys pairs_of_public_keys = 1;
136  // The logging ID for the SecAgg execution. All participants in the protocol
137  // will use this ID while logging, to allow metrics for the entire execution
138  // to be collected.
139  int64 sec_agg_execution_logging_id = 2;
140
141  // May be populated with implementation-specific data.
142  repeated google.protobuf.Any extra_data = 3;
143
144  // The session ID for the Secagg execution. All clients will use this session
145  // ID as part of the seed of PRNGs used during the execution of the protocol,
146  bytes session_id = 4 ;
147}
148
149// Part of a ClientToServerWrapperMessage. Contains a list of encrypted pairs of
150// key shares (one for each other client).
151message ShareKeysResponse {
152  // The (1-indexed) j'th element of the repeated field (of a ShareKeysResponse
153  // message sent from client i) contains the j'th shares of each of client i's
154  // noise_sk and prf_sk, encrypted under client j's enc_pk and intended to be
155  // sent to him. The i'th share (i.e. the share the a client would send to
156  // himself) will be empty.
157  // The client indexes above refer to their logical ids.
158  // This field is opaque, as it will be the output of an AES/GCM encryption.
159  // However, once decrypted, each entry should be interpreted as the
160  // serialization of a PairOfKeyShares message.
161  repeated bytes encrypted_key_shares = 1;
162}
163
164// Each of the encrypted_key_shares bytes in ShareKeysResponse and
165// MaskedInputCollectionRequest is an encryption of the serialization of this
166// message.
167message PairOfKeyShares {
168  // The two shares are encodings of BigIntegers which represents elements of
169  // the group Z_p, where p is the prime denoting the field over which the
170  // elliptic curve prime256v1 is defined. See the ShamirSecretSharing
171  // class for more details on the sharing.
172  //
173  // The following comes from the BigInteger documentation (the encoding is
174  // computed using the toByteArray() method):
175  // [The encoding consists of] a byte array containing the two's-complement
176  // representation of the BigInteger and is in big-endian byte-order: the most
177  // significant byte is in the zeroth element.
178  // The array will contain the minimum number of bytes required to represent
179  // this BigInteger, including at least one sign bit, which is
180  // (ceil((this.bitLength() + 1)/8)).
181  bytes noise_sk_share = 1;
182  bytes prf_sk_share = 2;
183}
184
185// ## ROUND 2 MESSAGES: MASKED INPUT COLLECTION
186// The server gives each client his shares of the keys of each other client who
187// responded in the previous round. Each client computes a masked version of its
188// own input and sends it to the server.
189
190// Part of a ServerToClientWrapperMessage. Contains a list of shares of other
191// clients' keys encrypted and intended for the client who receives this
192// message.
193message MaskedInputCollectionRequest {
194  // Each bytes field of this message (intended for party with logical id i)
195  // contains an encryption of a PairOfKeyShares message.
196  // The bytes are ordered according to the clients' logical ids. If a client
197  // j did not send the ShareKeysResponse in the previous round, the
198  // corresponding encrypted_key_shares bytes field will be empty (the receiving
199  // client i will therefore consider such a client j dead from now on).
200  repeated bytes encrypted_key_shares = 1;
201}
202
203// Part of a ClientToServerWrapperMessage. Contains a map of masked input
204// vectors (each identified by a name string).
205message MaskedInputCollectionResponse {
206  // The string key of the map represents the name of the input vector.
207  map<string, MaskedInputVector> vectors = 1;
208}
209
210// Part of a MaskedInputCollectionResponse message. Contains an encoding of an
211// input vector masked by the addition of pseudo-random values (which will be
212// removed later).
213message MaskedInputVector {
214  // The vector contains a packed representation of a masked SecAggVector,
215  // where each element is packed in little-endian order.
216  bytes encoded_vector = 1;
217
218  // May be populated with implementation-specific data.
219  repeated google.protobuf.Any extra_data = 2;
220}
221
222// ## ROUND 3 MESSAGES: UNMASKING
223// The server communicates to the clients the list of clients which did not
224// complete the previous round (and therefore are considered dead). Each client
225// i, for each other client j, responds with either the share of noise_sk (if
226// client j is dead) OR share of prf_sk (if client j is still alive).
227
228// Part of a ServerToClientWrapperMessage.
229message UnmaskingRequest {
230  // Clients which were alive at round 2, but did not send a ROUND 2 response,
231  // so they are considered dead from round 3 onwards.
232  // NOTE: to minimize bandwidth, this DOES NOT include clients which dropped
233  // before round 2 (i.e. those who did not send a round 1 response).
234  repeated uint32 dead_3_client_ids = 1;
235}
236
237// Part of a ClientToServerWrapperMessage.
238message UnmaskingResponse {
239  // These shares are NOT encrypted. For each other client j, client i sends to
240  // the server his share of noise_sk (if client j is dead) OR share of prf_sk
241  // (if client j is still alive).
242  // The entries corresponding to clients who died before round 2 (i.e. the
243  // ones for which the client sending the message never got any key shares) are
244  // empty. The entry corresponding to the client sending the message must be
245  // a prf_sk_share (otherwise the client would be dead and would not be sending
246  // this response.
247  repeated NoiseOrPrfKeyShare noise_or_prf_key_shares = 1;
248}
249
250// Part of an UnmaskingResponse. Contains either a share of a noise secret key
251// or a share of a prf secret key.
252message NoiseOrPrfKeyShare {
253  // Either a share of a noise secrete key or a share of a prf secret key.
254  // An honest client never reveals both, therefore oneof is appropriate.
255  oneof oneof_shares {
256    // A share of a noise secret key.
257    bytes noise_sk_share = 1;
258
259    // A share of a prf secret key.
260    bytes prf_sk_share = 2;
261  }
262}
263
264// Version(s) supported on each client.
265enum ClientVariant {
266  // No SecAgg versions are supported on this client.
267  SECAGG_CLIENT_VARIANT_NONE = 0;
268  // The Java implementation of the SegAgg client.
269  SECAGG_CLIENT_VARIANT_JAVA = 1 [deprecated = true];
270  // The native (C++) implementation of the SegAgg client.
271  SECAGG_CLIENT_VARIANT_NATIVE_V1 = 2;
272}
273