-
Notifications
You must be signed in to change notification settings - Fork 43
/
sender_db.h
374 lines (318 loc) · 12.3 KB
/
sender_db.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
#pragma once
// STD
#include <atomic>
#include <cstddef>
#include <cstdint>
#include <iostream>
#include <memory>
#include <unordered_set>
#include <utility>
#include <vector>
// GSL
#include "gsl/span"
// APSI
#include "apsi/bin_bundle.h"
#include "apsi/crypto_context.h"
#include "apsi/item.h"
#include "apsi/oprf/oprf_sender.h"
#include "apsi/psi_params.h"
// SEAL
#include "seal/plaintext.h"
#include "seal/util/locks.h"
namespace apsi {
namespace sender {
/**
A SenderDB maintains an in-memory representation of the sender's set of items and labels (in
labeled mode). This data is not simply copied into the SenderDB data structures, but also
preprocessed heavily to allow for faster online computation time. Since inserting a large
number of new items into a SenderDB can take time, it is not recommended to recreate the
SenderDB when the database changes a little bit. Instead, the class supports fast update and
deletion operations that should be preferred: SenderDB::insert_or_assign and
SenderDB::remove.
The SenderDB constructor allows the label byte count to be specified; unlabeled mode is
activated by setting the label byte count to zero. It is possible to optionally specify the
size of the nonce used in encrypting the labels, but this is best left to its default value
unless the user is absolutely sure of what they are doing.
The SenderDB requires substantially more memory than the raw data would. Part of that memory
can automatically be compressed when it is not in use; this feature is enabled by default,
and can be disabled when constructing the SenderDB. The downside of in-memory compression is
a performance reduction from decompressing parts of the data when they are used, and
recompressing them if they are updated.
*/
class SenderDB {
public:
/**
Creates a new SenderDB.
*/
SenderDB(
PSIParams params,
std::size_t label_byte_count = 0,
std::size_t nonce_byte_count = 16,
bool compressed = true);
/**
Creates a new SenderDB.
*/
SenderDB(
PSIParams params,
oprf::OPRFKey oprf_key,
std::size_t label_byte_count = 0,
std::size_t nonce_byte_count = 16,
bool compressed = true);
/**
Creates a new SenderDB by moving from an existing one.
*/
SenderDB(SenderDB &&source);
/**
Moves an existing SenderDB to the current one.
*/
SenderDB &operator=(SenderDB &&source);
/**
Clears the database. Every item and label will be removed. The OPRF key is unchanged.
*/
void clear();
/**
Returns whether this is a labeled SenderDB.
*/
bool is_labeled() const
{
return 0 != label_byte_count_;
}
/**
Returns the label byte count. A zero value indicates an unlabeled SenderDB.
*/
std::size_t get_label_byte_count() const
{
return label_byte_count_;
}
/**
Returns the nonce byte count used for encrypting labels.
*/
std::size_t get_nonce_byte_count() const
{
return nonce_byte_count_;
}
/**
Indicates whether SEAL plaintexts are compressed in memory.
*/
bool is_compressed() const
{
return compressed_;
}
/**
Indicates whether the SenderDB has been stripped of all information not needed for
serving a query.
*/
bool is_stripped() const
{
return stripped_;
}
/**
Strips the SenderDB of all information not needed for serving a query. Returns a copy of
the OPRF key and clears it from the SenderDB.
*/
oprf::OPRFKey strip();
/**
Returns a copy of the OPRF key.
*/
oprf::OPRFKey get_oprf_key() const;
/**
Inserts the given data into the database. This function can be used only on a labeled
SenderDB instance. If an item already exists in the database, its label is overwritten
with the new label.
*/
void insert_or_assign(const std::vector<std::pair<Item, Label>> &data);
/**
Inserts the given (hashed) item-label pair into the database. This function can be used
only on a labeled SenderDB instance. If the item already exists in the database, its
label is overwritten with the new label.
*/
void insert_or_assign(const std::pair<Item, Label> &data)
{
std::vector<std::pair<Item, Label>> data_singleton{ data };
insert_or_assign(data_singleton);
}
/**
Inserts the given data into the database. This function can be used only on an unlabeled
SenderDB instance.
*/
void insert_or_assign(const std::vector<Item> &data);
/**
Inserts the given (hashed) item into the database. This function can be used only on an
unlabeled SenderDB instance.
*/
void insert_or_assign(const Item &data)
{
std::vector<Item> data_singleton{ data };
insert_or_assign(data_singleton);
}
/**
Clears the database and inserts the given data. This function can be used only on a
labeled SenderDB instance.
*/
void set_data(const std::vector<std::pair<Item, Label>> &data)
{
clear();
insert_or_assign(data);
}
/**
Clears the database and inserts the given data. This function can be used only on an
unlabeled SenderDB instance.
*/
void set_data(const std::vector<Item> &data)
{
clear();
insert_or_assign(data);
}
/**
Removes the given data from the database, using at most thread_count threads.
*/
void remove(const std::vector<Item> &data);
/**
Removes the given (hashed) item from the database.
*/
void remove(const Item &data)
{
std::vector<Item> data_singleton{ data };
remove(data_singleton);
}
/**
Returns whether the given item has been inserted in the SenderDB.
*/
bool has_item(const Item &item) const;
/**
Returns the label associated to the given item in the database. Throws
std::invalid_argument if the item does not appear in the database.
*/
Label get_label(const Item &item) const;
/**
Returns a set of cache references corresponding to the bundles at the given bundle
index. Even though this function returns a vector, the order has no significance. This
function is meant for internal use.
*/
auto get_cache_at(std::uint32_t bundle_idx)
-> std::vector<std::reference_wrapper<const BinBundleCache>>;
/**
Returns a reference to the PSI parameters for this SenderDB.
*/
const PSIParams &get_params() const
{
return params_;
}
/**
Returns a reference to the CryptoContext for this SenderDB.
*/
const CryptoContext &get_crypto_context() const
{
return crypto_context_;
}
/**
Returns a reference to the SEALContext for this SenderDB.
*/
std::shared_ptr<seal::SEALContext> get_seal_context() const
{
return crypto_context_.seal_context();
}
/**
Returns a reference to a set of item hashes already existing in the SenderDB.
*/
const std::unordered_set<HashedItem> &get_hashed_items() const
{
return hashed_items_;
}
/**
Returns the number of items in this SenderDB.
*/
size_t get_item_count() const
{
return item_count_;
}
/**
Returns the total number of bin bundles at a specific bundle index.
*/
std::size_t get_bin_bundle_count(std::uint32_t bundle_idx) const;
/**
Returns the total number of bin bundles.
*/
std::size_t get_bin_bundle_count() const;
/**
Returns how efficiently the SenderDB is packaged. A higher rate indicates better
performance and a lower communication cost in a query execution.
*/
double get_packing_rate() const;
/**
Obtains a scoped lock preventing the SenderDB from being changed.
*/
seal::util::ReaderLock get_reader_lock() const
{
return db_lock_.acquire_read();
}
/**
Writes the SenderDB to a stream.
*/
std::size_t save(std::ostream &out) const;
/**
Reads the SenderDB from a stream.
*/
static std::pair<SenderDB, std::size_t> Load(std::istream &in);
private:
SenderDB(const SenderDB ©) = delete;
seal::util::WriterLock get_writer_lock()
{
return db_lock_.acquire_write();
}
void clear_internal();
void generate_caches();
/**
The set of all items that have been inserted into the database
*/
std::unordered_set<HashedItem> hashed_items_;
/**
The PSI parameters define the SEAL parameters, base field, item size, table size, etc.
*/
PSIParams params_;
/**
Necessary for evaluating polynomials of Plaintexts.
*/
CryptoContext crypto_context_;
/**
A read-write lock to protect the database from modification while in use.
*/
mutable seal::util::ReaderWriterLocker db_lock_;
/**
Indicates the size of the label in bytes. A zero value indicates an unlabeled SenderDB.
*/
std::size_t label_byte_count_;
/**
Indicates the number of bytes of the effective label reserved for a randomly sampled
nonce. The effective label byte count is the sum of label_byte_count and
nonce_byte_count. The value can range between 0 and 16. If label_byte_count is zero,
nonce_byte_count has no effect.
*/
std::size_t nonce_byte_count_;
/**
The number of items currently in the SenderDB.
*/
std::size_t item_count_;
/**
Indicates whether SEAL plaintexts are compressed in memory.
*/
bool compressed_;
/**
Indicates whether the SenderDB has been stripped of all information not needed for
serving a query.
*/
bool stripped_;
/**
All the BinBundles in the database, indexed by bundle index. The set (represented by a
vector internally) at bundle index i contains all the BinBundles with bundle index i.
*/
std::vector<std::vector<BinBundle>> bin_bundles_;
/**
Holds the OPRF key for this SenderDB.
*/
oprf::OPRFKey oprf_key_;
}; // class SenderDB
} // namespace sender
} // namespace apsi