SeComLib
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Macros Pages
data_packing/service_provider.cpp
Go to the documentation of this file.
1 /*
2 SeComLib
3 Copyright 2012-2013 TU Delft, Information Security & Privacy Lab (http://isplab.tudelft.nl/)
4 
5 Contributors:
6 Inald Lagendijk (R.L.Lagendijk@TUDelft.nl)
7 Mihai Todor (todormihai@gmail.com)
8 Thijs Veugen (P.J.M.Veugen@tudelft.nl)
9 Zekeriya Erkin (z.erkin@tudelft.nl)
10 
11 Licensed under the Apache License, Version 2.0 (the "License");
12 you may not use this file except in compliance with the License.
13 You may obtain a copy of the License at
14 
15 http://www.apache.org/licenses/LICENSE-2.0
16 
17 Unless required by applicable law or agreed to in writing, software
18 distributed under the License is distributed on an "AS IS" BASIS,
19 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 See the License for the specific language governing permissions and
21 limitations under the License.
22 */
30 #include "service_provider.h"
31 //avoid circular includes
33 
34 namespace SeComLib {
35 namespace PrivateRecommendationsDataPacking {
39  const std::string ServiceProvider::configurationPath("PrivateRecommendationsDataPacking");
40 
47  ServiceProvider::ServiceProvider (const PaillierPublicKey &paillierPublicKey, const DgkPublicKey &dgkPublicKey) :
48  paillierCryptoProvider(paillierPublicKey),
49  dgkCryptoProvider(dgkPublicKey),
50  userCount(Utils::Config::GetInstance().GetParameter<size_t>(configurationPath + ".userCount")),
51  itemCount(Utils::Config::GetInstance().GetParameter<size_t>(configurationPath + ".itemCount")),
52  denselyRatedItemCount(Utils::Config::GetInstance().GetParameter<size_t>(configurationPath + ".denselyRatedItemCount")),
53  scaledNormalizedRatingBitSize(Utils::Config::GetInstance().GetParameter<size_t>(configurationPath + ".scaledNormalizedRatingBitSize")),
54  digitsToPreserve(Utils::Config::GetInstance().GetParameter<unsigned int>(configurationPath + ".digitsToPreserve")),
55  kappa(Utils::Config::GetInstance().GetParameter<size_t>(configurationPath + ".BlindingFactorCache.kappa")),
56  //the similarity threshold needs to be scaled twice as much as the normalized ratings, due to the way the similarity values are computed
57  similarityTreshold(BigInteger(Utils::Config::GetInstance().GetParameter<double>(configurationPath + ".similarityTreshold"), 2 * digitsToPreserve)) {
59  unsigned long ceilLogBaseTwoR = static_cast<unsigned long>(std::ceil(std::log(static_cast<double>(this->denselyRatedItemCount)) / std::log(2.0)));//change base from e to 2 and round up to the nearest integer
60  size_t l = 2 * this->scaledNormalizedRatingBitSize + ceilLogBaseTwoR;
61  this->bucketSize = l + 2;
62 
67  this->maxPackedBuckets = (this->paillierCryptoProvider.GetMessageSpaceSize() - this->kappa - 2) / this->bucketSize;
68 
70  BigInteger one(1);
71  for (size_t i = 0; i < this->maxPackedBuckets; ++i) {
72  this->emptyBuckets.emplace_back(one << (static_cast<unsigned long>(i * this->bucketSize)));
73  }
74 
75  //initialize the secureComparisonServer
76  this->secureComparisonServer = std::make_shared<SecureComparisonServer>(this->paillierCryptoProvider, this->dgkCryptoProvider, this->similarityTreshold, l, this->bucketSize, this->maxPackedBuckets, this->emptyBuckets, this->configurationPath);
77  this->secureMultiplicationServer = std::make_shared<SecureMultiplicationServer<Paillier>>(this->paillierCryptoProvider, l, configurationPath);
78  }
79 
91  BigInteger two(2);
92  #ifdef FIRST_USER_ONLY
93  std::cout << "Warning: running simulation for a single user." << std::endl << std::endl;
94  for (size_t user = 0; user < 1; ++user) {
95  #else
96  for (size_t user = 0; user < this->userCount; ++user) {
97  #endif
98  //measure the time it takes to generate the packed densely related items for each user
99  Utils::CpuTimer userTimer;
100 
101  PackedItems userPackedDenselyRelatedItems;
102  for (size_t item = 0; item < this->denselyRatedItemCount; ++item) {
104  PackedData packedItems;
105 
106  Paillier::Ciphertext packedBuckets;
107  size_t bucketCount = 0;
108  for (size_t i = 0; i < this->userCount; ++i) {
109  //sim(i, i) does not exist and sim(A, B) = sim(B, A), so we compute only sim(A, B) (the upper triangle of the matrix, without the diagonal)
110  if (i > user) {
112 
113  //the encryption is empty, so we assign to it the next value
114  if (0 == bucketCount) {
115  /*
116  this->privacyServiceProvider.lock()->DebugPaillierEncryption(this->normalizedScaledRatings[i][item]);
117  std::cout << this->emptyBuckets[bucketCount].ToString() << std::endl << std::endl;
118  */
119  packedBuckets = normalizedScaledRatings[i][item] * (this->emptyBuckets[bucketCount] << 1);
120  //this->privacyServiceProvider.lock()->DebugPaillierEncryption(packedBuckets);
121  }
122  //the encryption is not empty, so we add values to it using homomorphic addition
123  else {
124  /*
125  this->privacyServiceProvider.lock()->DebugPaillierEncryption(this->normalizedScaledRatings[i][item]);
126  std::cout << this->emptyBuckets[bucketCount].ToString() << std::endl << std::endl;
127  */
128  packedBuckets = packedBuckets + normalizedScaledRatings[i][item] * (this->emptyBuckets[bucketCount] << 1);
129  //this->privacyServiceProvider.lock()->DebugPaillierEncryption(packedBuckets);
130  }
131 
132  //if all the buckets inside the encryption are full, persist the encryption and reset the bucket counter
133  if (bucketCount == this->maxPackedBuckets - 1) {
134  packedItems.emplace_back(packedBuckets);
135  bucketCount = 0;
136  }
137  else {
138  ++bucketCount;
139  }
140  }
141  }
142 
143  //store the last packed buckets for the current item
144  if (bucketCount > 0) {
145  packedItems.emplace_back(packedBuckets);
146  }
147 
149  if (packedItems.size() > 0) {
150  userPackedDenselyRelatedItems.emplace_back(packedItems);
151  }
152  }
153 
154  std::cout << "Packed items for user " << user << " in " << userTimer.ToString() << std::endl;
155 
156  if (userPackedDenselyRelatedItems.size() > 0) {
157  this->packedNormalizedScaledRatings.emplace_back(userPackedDenselyRelatedItems);
158  }
159  }
160  }
161 
168  //the packedNormalizedScaledRatings contain only the upper triangle of the similarity matrix (excluding the diagonal) because sim(A, B) = sim(B, A)
169  #ifdef FIRST_USER_ONLY
170  for (size_t user = 0; user < 1; ++user) {
171  #else
172  for (size_t user = 0; user < this->packedNormalizedScaledRatings.size(); ++user) {
173  #endif
174  //measure the time it takes to compute the similarity values for each user
175  Utils::CpuTimer similarityTimer;
176 
178  PackedData packedSimilarityValues;
179  for (size_t i = 0; i < this->packedNormalizedScaledRatings[user][0].size(); ++i) {
180  packedSimilarityValues.emplace_back(this->secureMultiplicationServer->Multiply(this->packedNormalizedScaledRatings[user][0][i], normalizedScaledRatings[user][0]));
181 
182  //this->privacyServiceProvider.lock()->DebugPaillierEncryption(userPackedSimilarityValues.back());
183  }
184 
186  for (size_t item = 1; item < this->denselyRatedItemCount; ++item) {
187  for (size_t i = 0; i < this->packedNormalizedScaledRatings[user][item].size(); ++i) {
188  packedSimilarityValues[i] = packedSimilarityValues[i] + (this->secureMultiplicationServer->Multiply(this->packedNormalizedScaledRatings[user][item][i], normalizedScaledRatings[user][item]));
189 
190  //this->privacyServiceProvider.lock()->DebugPaillierEncryption(userPackedSimilarityValues.back());
191  }
192  }
193 
194  std::cout << "Similarity processing: " << similarityTimer.ToString();
195 
196  //measure the time it takes to compute the gamma values for each user
197  Utils::CpuTimer gammaTimer;
198 
200  /*
201  for each user, we have userCount - 1 similarity values, and, since sim(A, A) does not exist and sim(A, B) = sim(B, A), we need to compute fewer by one similarity values for each user.
202  The number of buckets in the last encryption of packedSimilarityValues is: (rowSimilarityCount) % maxPackedBuckets
203  */
204  size_t rowSimilarityCount = this->userCount - 1 - user;
205  this->gamma.emplace_back(this->secureComparisonServer->Compare(packedSimilarityValues, rowSimilarityCount % this->maxPackedBuckets));
206 
207  std::cout << " Gamma processing (" << this->gamma.back().size() << " values): " << gammaTimer.ToString() << " for user " << user << std::endl;
208  }
209  }
210 
221  #ifdef FIRST_USER_ONLY
222  for (size_t user = 0; user < 1; ++user) {
223  #else
224  for (size_t user = 0; user < this->userCount; ++user) {
225  #endif
226  //measure the time it takes to compute L and URSum for each user
227  Utils::CpuTimer recommendationsTimer;
228 
230  Paillier::Ciphertext L = this->gamma[0][user == 0 ? user : user - 1];//gamma(i, 0) = gamma(0, i)
231 
233  PackedData userURSum;
234  for (size_t encryptionIndex = 0; encryptionIndex < sparseRatings[user].size(); ++encryptionIndex) {
235  //gamma(i, 0) = gamma(0, i)
236  userURSum.emplace_back(this->secureMultiplicationServer->Multiply(sparseRatings[user == 0 ? 1 : 0][encryptionIndex], this->gamma[0][user == 0 ? user : user - 1]));//gamma(i, 0) = gamma(0, i)
237  }
238 
243  for (size_t i = (user == 0 ? 2 : 1); i < this->userCount; ++i) {
244  if (i != user) {
245  //compute the row and column indices for gamma (gamma(A, B) = gamma(B, A), and this->gamma contains only gamma(A, B), where A != B)
246  size_t gammaRow = user < i ? user : i;
247  size_t gammaColumn = user < i ? i - 1 - user : user - 1 - i;
248 
249  L = L + this->gamma[gammaRow][gammaColumn];
250 
251  for (size_t encryptionIndex = 0; encryptionIndex < sparseRatings[i].size(); ++encryptionIndex) {
252  userURSum[encryptionIndex] = userURSum[encryptionIndex] + this->secureMultiplicationServer->Multiply(sparseRatings[i][encryptionIndex], this->gamma[gammaRow][gammaColumn]);
253  }
254  }
255  }
256  this->LValues.push_back(L);
257  this->URSumContainer.emplace_back(userURSum);
258 
259  std::cout << "Generated recommendations for user " << user << " in " << recommendationsTimer.ToString() << std::endl;
260  //this->privacyServiceProvider.lock()->DebugPaillierEncryption(this->LValues.back());
261  }
262  }
263 
268  const Paillier::Ciphertext &ServiceProvider::GetEncryptedL (const size_t userId) const {
269  return this->LValues.at(userId);
270  }
271 
277  return this->URSumContainer.at(userId);
278  }
279 
280 #if 0
281 
288  const ServiceProvider::PackedData ServiceProvider::ComputeURSum (const size_t userId, const PackedData &userPackedSparseRatings) const {
289  // We need to recompute the packedSparseRatings for all users first...
290  PackedData output;
291 
293  for (size_t encryptionIndex = 0; encryptionIndex < userPackedSparseRatings.size(); ++encryptionIndex) {
294  output.emplace_back(this->secureMultiplicationServer->Multiply(userPackedSparseRatings[encryptionIndex], this->gamma[userId][0]));
295  }
296 
298  for (size_t i = 1; i < this->gamma[userId].size(); ++i) {
299  for (size_t encryptionIndex = 0; encryptionIndex < userPackedSparseRatings.size(); ++encryptionIndex) {
300  output[encryptionIndex] = output[encryptionIndex] + this->secureMultiplicationServer->Multiply(userPackedSparseRatings[encryptionIndex], this->gamma[userId][i]);
301  }
302  }
303 
304  return output;
305  }
306 #endif
307 
311  void ServiceProvider::SetPrivacyServiceProvider (const std::shared_ptr<const PrivacyServiceProvider> &privacyServiceProvider) {
312  this->privacyServiceProvider = privacyServiceProvider;
313  this->secureComparisonServer->SetClient(privacyServiceProvider->GetSecureComparisonClient());
314  this->secureMultiplicationServer->SetClient(privacyServiceProvider->GetSecureMultiplicationClient());
315  }
316 
321  return this->bucketSize;
322  }
323 
328  return this->maxPackedBuckets;
329  }
330 
334  const std::shared_ptr<SecureComparisonServer> &ServiceProvider::GetSecureComparisonServer () const {
335  return this->secureComparisonServer;
336  }
337 
341  const std::shared_ptr<SecureMultiplicationServer<Paillier>> &ServiceProvider::GetSecureMultiplicationServer () const {
342  return this->secureMultiplicationServer;
343  }
344 
345 }//namespace PrivateRecommendationsDataPacking
346 }//namespace SeComLib
const std::shared_ptr< SecureComparisonServer > & GetSecureComparisonServer() const
Getter for this->secureComparisonClient.
void GenerateDummyDatabase(const EncryptedUserDataContainer &normalizedScaledRatings)
Generates a dummy database for the users.
const Paillier::Ciphertext & GetEncryptedL(const size_t userId) const
Returns the value for the specified user.
size_t GetMaxPackedBuckets() const
Getter for the maximum number of packed data buckets.
std::deque< EncryptedUserData > EncryptedUserDataContainer
Container for encrypted user data.
const std::shared_ptr< SecureMultiplicationServer< Paillier > > & GetSecureMultiplicationServer() const
Getter for this->secureMultiplicationServer.
EncryptedUserData LValues
Vector of values, where L is the number of users similar to a given user.
The public key container structure for the Dgk cryptosystem.
Definition: dgk.h:47
std::weak_ptr< const PrivacyServiceProvider > privacyServiceProvider
A reference to the PrivacyServiceProvider.
void SetPrivacyServiceProvider(const std::shared_ptr< const PrivacyServiceProvider > &privacyServiceProvider)
Sets a reference to the Privacy Service Provider.
PackedItems URSumContainer
Contains the vectors for each user.
Utilitary class providing algorithm timing functionality.
Definition: cpu_timer.h:47
std::string ToString() const
Returns the elapsed user process time as a formatted string (HH::MM::SS.mmm)
Definition: cpu_timer.cpp:63
virtual size_t GetMessageSpaceSize() const
Returns the message space bit size.
Definition: paillier.cpp:283
ServiceProvider(const PaillierPublicKey &paillierPublicKey, const DgkPublicKey &dgkPublicKey)
Constructor.
std::shared_ptr< SecureComparisonServer > secureComparisonServer
A reference to the SecureComparisonServer.
size_t scaledNormalizedRatingBitSize
k - The size of the scaled normalized ratings (in bits) (should be l / 2?)
size_t kappa
The security parameter for the secure comparison protocol (in bits)
Definition of class PrivacyServiceProvider.
BigInteger similarityTreshold
- Scaled public threshold value for the similarity values
void ComputeUserRecommendations(const PackedItems &sparseRatings)
Computes , and for each user.
EncryptedUserDataContainer gamma
- the encrypted gamma values for every user (the upper triangle of the matrix, excluding the diagona...
Definition of class ServiceProvider.
static const std::string configurationPath
Service Provider configuration path.
size_t maxPackedBuckets
The maximum number of buckets that fit in one encryption.
std::shared_ptr< SecureMultiplicationServer< Paillier > > secureMultiplicationServer
A reference to the SecureMultiplicationServer.
const PackedData & GetEncryptedURSum(const size_t userId) const
Returns the vector for the specified user.
void ComputeSimilarityValues(const EncryptedUserDataContainer &normalizedScaledRatings)
Computes the similarity values between each pair of users for the first items.
The public key container structure for the Paillier cryptosystem.
Definition: paillier.h:49