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