SeComLib
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Macros Pages
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 PrivateRecommendations {
39  const std::string ServiceProvider::configurationPath("PrivateRecommendations");
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  ratingBitSize(Utils::Config::GetInstance().GetParameter<size_t>(configurationPath + ".t")),
54  digitsToPreserve(Utils::Config::GetInstance().GetParameter<unsigned int>(configurationPath + ".digitsToPreserve")),
55  //the similarity threshold needs to be scaled twice as much as the normalized ratings, due to the way the similarity values are computed
56  similarityTreshold(BigInteger(Utils::Config::GetInstance().GetParameter<double>(configurationPath + ".similarityTreshold"), 2 * digitsToPreserve)),
57  ratingsFilePath(Utils::Config::GetInstance().GetParameter<std::string>(configurationPath + ".ratingsFilePath")),
58  secureComparisonServer(std::make_shared<SecureComparisonServer>(paillierCryptoProvider, dgkCryptoProvider, similarityTreshold, configurationPath)),
59  secureMultiplicationServer(std::make_shared<SecureMultiplicationServer<Paillier>>(paillierCryptoProvider, Utils::Config::GetInstance().GetParameter<size_t>(configurationPath + ".l"), configurationPath)) {
60  }
61 
72  std::ifstream ratingsFile(this->ratingsFilePath);
73  if (!ratingsFile.is_open()) {
74  throw std::runtime_error("Can't open the ratings file.");
75  }
76  std::string line;
77  //foreach user
78  while (std::getline(ratingsFile, line)) {
79  std::istringstream lineStream(line);
80 
81  ServiceProvider::EncryptedUserData userNormalizedScaledRatings;
82  std::deque<unsigned long> userRatings;
83  double squaredSum = 0.0;
84 
85  for (size_t item = 0; item < this->denselyRatedItemCount; ++item) {
86  //fetch the value
87  unsigned long rating;
88  lineStream >> rating;
89 
90  squaredSum += static_cast<double>(rating * rating);
91 
92  userRatings.emplace_back(rating);
93  }
94 
95  double denominator = std::sqrt(squaredSum);
96  for (size_t item = 0; item < this->denselyRatedItemCount; ++item) {
97  double normalizedValue = static_cast<double>(userRatings[item]) / denominator;
98  //truncate the remaining digits after scaling
99  userNormalizedScaledRatings.emplace_back(this->paillierCryptoProvider.EncryptInteger(BigInteger(normalizedValue, this->digitsToPreserve, true)));
100  }
101  this->normalizedScaledRatings.emplace_back(userNormalizedScaledRatings);
102 
103  EncryptedUserData userSparseRatings;
104  //fetch the value
105  unsigned long rating;
106  while (lineStream >> rating) {
107  userSparseRatings.emplace_back(this->paillierCryptoProvider.EncryptInteger(rating));
108  }
109  this->sparseRatings.emplace_back(userSparseRatings);
110  }
111 
112  #if 0//auto-generate ratings
113  for (size_t user = 0; user < this->userCount; ++user) {
114  EncryptedUserData userNormalizedScaledRatings;
115  std::deque<unsigned long> userRatings;
116  double squaredSum = 0.0;
117  for (size_t item = 0; item < this->denselyRatedItemCount; ++item) {
118  //insert random values > 0 and <= max
119  BigInteger random;
120  do {
121  random = RandomProvider::GetInstance().GetRandomInteger(ratingBitSize);
122  }
123  while (random == 0);
124  unsigned long randomValue = random.ToUnsignedLong();
125 
126  squaredSum += static_cast<double>(randomValue * randomValue);
127 
128  userRatings.emplace_back(randomValue);
129  }
130 
131  double denominator = std::sqrt(squaredSum);
132  for (size_t item = 0; item < this->denselyRatedItemCount; ++item) {
133  double normalizedValue = static_cast<double>(userRatings[item]) / denominator;
134  //truncate the remaining digits after scaling
135  userNormalizedScaledRatings.emplace_back(this->paillierCryptoProvider.EncryptInteger(BigInteger(normalizedValue, this->digitsToPreserve, true)));
136  }
137  this->normalizedScaledRatings.emplace_back(userNormalizedScaledRatings);
138 
139  EncryptedUserData userSparseRatings;
140  for (size_t item = this->denselyRatedItemCount; item < this->itemCount; ++item) {
141  //insert random values >= 0 and <= max
142  userSparseRatings.emplace_back(this->paillierCryptoProvider.EncryptInteger(RandomProvider::GetInstance().GetRandomInteger(ratingBitSize)));
143  }
144  this->sparseRatings.emplace_back(userSparseRatings);
145  }
146  #endif
147  }
148 
155  #ifdef FIRST_USER_ONLY
156  for (size_t i = 0; i < 1; ++i) {
157  #else
158  for (size_t i = 0; i < this->userCount; ++i) {
159  #endif
160  //measure the time it takes to compute the similarity values for each user
161  Utils::CpuTimer similarityTimer;
162 
163  EncryptedUserData userSimilarityValues;
164  for (size_t j = 0; j < this->userCount; ++j) {
165  //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)
166  if (j > i) {
167  //initialize the sum with the first item (saves one homomorphic addition)
168  userSimilarityValues.emplace_back(this->secureMultiplicationServer->Multiply(this->normalizedScaledRatings[i][0], this->normalizedScaledRatings[j][0]));
169 
170  for (size_t item = 1; item < this->denselyRatedItemCount; ++item) {
171  userSimilarityValues.back() = userSimilarityValues.back() + this->secureMultiplicationServer->Multiply(this->normalizedScaledRatings[i][item], this->normalizedScaledRatings[j][item]);
172  }
173 
174  /*
175  std::cout << "sim(" << i << "," << j << "): ";
176  this->privacyServiceProvider.lock()->DebugPaillierEncryption(userSimilarityValues.back());
177  */
178  }
179  }
180 
181  std::cout << "Similarity processing: " << similarityTimer.ToString();
182 
183  //measure the time it takes to compute the gamma values for each user
184  Utils::CpuTimer gammaTimer;
185 
186  for (EncryptedUserData::const_iterator similarity = userSimilarityValues.begin(); similarity != userSimilarityValues.end(); ++similarity) {
187  this->gammaValues.emplace_back(this->secureComparisonServer->Compare(*similarity));
188 
189  /*
190  std::cout << "gamma(" << i << "," << j << "): ";
191  this->privacyServiceProvider.lock()->DebugPaillierEncryption(this->gammaValues.back());
192  */
193  }
194 
195  std::cout << " Gamma processing (" << userSimilarityValues.size() << " values): " << gammaTimer.ToString() << " for user " << i << std::endl;
196  }
197  }
198 
211  #ifdef FIRST_USER_ONLY
212  for (size_t user = 0; user < 1; ++user) {
213  #else
214  for (size_t user = 0; user < this->userCount; ++user) {
215  #endif
216  //measure the time it takes to compute L and URSum for each user
217  Utils::CpuTimer recommendationsTimer;
218 
220  /*
221  for user 0, the first value is gamma(0, 1) = gammaValues[0]
222  for user 1, gamma(1, 0) = gamma(0, 1) = gammaValues[0]
223  for user 2, gamma(2, 0) = gamma(0, 2) = gammaValues[1]
224  ...
225  */
226  Paillier::Ciphertext userLValue = this->gammaValues[user == 0 ? 0 : user - 1];
227 
228  EncryptedUserData userURSum;
230  for (size_t item = 0; item < this->itemCount - this->denselyRatedItemCount; ++item) /* //item < M - R */ {
231  userURSum.emplace_back(this->secureMultiplicationServer->Multiply(this->gammaValues[user == 0 ? 0 : user - 1], this->sparseRatings[user == 0 ? 1 : 0][item]));
232  }
233 
235  for (size_t i = (user == 0 ? 2 : 1); i < this->userCount; ++i) {
236  if (i != user) {
238  size_t gammaIndex;
239  if (user < i)
240  gammaIndex = user * this->userCount + i - (user + 1) * (user + 2) / 2;
241  else
242  gammaIndex = i * this->userCount + user - (i + 1) * (i + 2) / 2;
243 
244  userLValue = userLValue + this->gammaValues[gammaIndex];
245 
247  for (size_t item = 0; item < this->itemCount - this->denselyRatedItemCount; ++item)/* item < M - R */ {
248  userURSum[item] = userURSum[item] + this->secureMultiplicationServer->Multiply(this->gammaValues[gammaIndex], this->sparseRatings[i][item]);
249  }
250  }
251  }
252 
253  this->LValues.emplace_back(userLValue);
254 
255  this->URSumContainer.emplace_back(userURSum);
256 
257  /*
258  std::cout << "L(" << user << "): ";
259  this->privacyServiceProvider.lock()->DebugPaillierEncryption(userLValue);
260  */
261 
262  std::cout << "Generated recommendations for user " << user << " in " << recommendationsTimer.ToString() << std::endl;
263  }
264  }
265 
271  return this->LValues.at(userId);
272  }
273 
279  return this->URSumContainer.at(userId);
280  }
281 
285  void ServiceProvider::SetPrivacyServiceProvider (const std::shared_ptr<const PrivacyServiceProvider> &privacyServiceProvider) {
286  this->privacyServiceProvider = privacyServiceProvider;
287  this->secureComparisonServer->SetClient(privacyServiceProvider->GetSecureComparisonClient());
288  this->secureMultiplicationServer->SetClient(privacyServiceProvider->GetSecureMultiplicationClient());
289  }
290 
294  const std::shared_ptr<SecureComparisonServer> &ServiceProvider::GetSecureComparisonServer () const {
295  return this->secureComparisonServer;
296  }
297 
301  const std::shared_ptr<SecureMultiplicationServer<Paillier>> &ServiceProvider::GetSecureMultiplicationServer () const {
302  return this->secureMultiplicationServer;
303  }
304 
305 }//namespace PrivateRecommendations
306 }//namespace SeComLib
size_t ratingBitSize
The size of the user ratings (in bits)
std::string ratingsFilePath
The path to the file containing precomputed ratings.
void ComputeUserRecommendations()
Computes , and for each user.
size_t denselyRatedItemCount
Number of densely rated items.
std::deque< Paillier::Ciphertext > EncryptedUserData
Encrypted user data.
Definition of class PrivacyServiceProvider.
size_t itemCount
Number of ratings per user.
The public key container structure for the Dgk cryptosystem.
Definition: dgk.h:47
virtual T_Ciphertext EncryptInteger(const BigInteger &plaintext) const
Encrypt an integer and apply randomization.
EncryptedUserData LValues
Vector of values, where L is the number of users similar to a given user.
void SetPrivacyServiceProvider(const std::shared_ptr< const PrivacyServiceProvider > &privacyServiceProvider)
Sets a reference to the Privacy Service Provider.
Paillier paillierCryptoProvider
Paillier crypto provider.
static const std::string configurationPath
Service Provider configuration path.
unsigned int digitsToPreserve
Number of digits preserved from the normalized user ratings.
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
const Paillier::Ciphertext & GetEncryptedL(size_t userId) const
Returns the value for the specified user.
size_t userCount
Number of users who need recommendations.
EncryptedUserDataContainer URSumContainer
Contains the vectors for each user.
const std::shared_ptr< SecureMultiplicationServer< Paillier > > & GetSecureMultiplicationServer() const
Getter for this->secureMultiplicationServer.
Implementation of the public-key Paillier Cryptosystem.
Definition: paillier.h:103
std::shared_ptr< SecureMultiplicationServer< Paillier > > secureMultiplicationServer
A reference to the SecureMultiplicationServer.
const std::shared_ptr< SecureComparisonServer > secureComparisonServer
A reference to the SecureComparisonServer.
void ComputeSimilarityValues()
Computes the similarity values between each pair of users for the first items.
ServiceProvider(const PaillierPublicKey &paillierPublicKey, const DgkPublicKey &dgkPublicKey)
Constructor.
void GenerateDummyDatabase()
Generates a dummy database for the users.
const std::shared_ptr< SecureComparisonServer > & GetSecureComparisonServer() const
Getter for this->secureComparisonServer.
const EncryptedUserData & GetEncryptedURSum(size_t userId) const
Returns the vector for the specified user.
Definition of class ServiceProvider.
The public key container structure for the Paillier cryptosystem.
Definition: paillier.h:49
std::weak_ptr< const PrivacyServiceProvider > privacyServiceProvider
A reference to the PrivacyServiceProvider.