35 namespace SecureRecommendations {
44 const std::map<std::string, SecureSvm::KernelTypes>
SecureSvm::kernelTypesMap = boost::assign::map_list_of(
"linear", SecureSvm::linear)
45 (
"homogeneous_poly", SecureSvm::homogeneousPolynomial)
46 (
"inhomogeneous_poly", SecureSvm::inhomogeneousPolynomial)
47 (
"rbf", SecureSvm::inverseQuadraticRBF);
61 SecureSvm::SecureSvm (
const std::string &directoryPath,
const std::string &modelFile,
const PaillierPublicKey &publicKey,
const std::weak_ptr<const Server> &server) : cryptoProvider(publicKey), server(server), modelFileName(modelFile), model(NULL) {
73 if (std::string::npos != this->
modelFileName.find(this->safetyModelFilePrefix)) {
74 std::vector<unsigned short> unsafeClasses;
81 std::sort(unsafeClasses.begin(), unsafeClasses.end());
84 std::stringstream unsafeClassesStream;
85 for (std::vector<unsigned short>::const_iterator unsafeClassesIterator = unsafeClasses.begin(); unsafeClassesIterator != unsafeClasses.end(); ++unsafeClassesIterator) {
86 unsafeClassesStream << *unsafeClassesIterator;
92 if (SecureSvm::inverseQuadraticRBF == this->kernel) {
99 std::string modelFilePath = directoryPath + this->
modelFileName;
101 std::ifstream fileStream(modelFilePath);
104 if (!fileStream.good()) {
105 throw std::runtime_error(
"Can't open the SVM model file.");
109 if (SecureSvm::linear != this->kernel) {
112 bool foundGamma =
false;
113 while (std::getline(fileStream, line)) {
114 if (std::string::npos != line.find(
"gamma")) {
116 if (std::string::npos != line.find(
'.')) {
117 std::string gammaValueString = line.substr(line.find(
' '));
118 std::stringstream gammaValueStream; gammaValueStream << gammaValueString;
119 double gammaValue; gammaValueStream >> gammaValue;
122 double exponent = std::log(gammaValue) / std::log(2.0);
123 if (exponent > 0)
throw std::runtime_error(
"Unexpected gamma value detected.");
127 this->
gammaScaling = BigInteger(2).Pow(static_cast<unsigned long>(std::abs(std::ceil(exponent - 0.5))));
140 throw std::runtime_error(
"Can't find gamma in the model file.");
147 this->
model = svm_load_model(modelFilePath.c_str());
149 if (NULL == this->
model) {
150 throw std::runtime_error(
"Invalid model file.");
155 std::cout <<
"Loaded " << modelFile <<
"; nSV: " << this->
model->l << std::endl;
162 svm_free_and_destroy_model(&this->
model);
176 throw std::runtime_error(
"Invalid kernel name received.");
179 return iterator->second;
216 for (
size_t i = 0; i < this->
aVector.size(); ++i) {
221 case SecureSvm::linear:
224 case SecureSvm::homogeneousPolynomial:
227 case SecureSvm::inhomogeneousPolynomial:
230 case SecureSvm::inverseQuadraticRBF:
236 throw std::runtime_error(
"Invalid kernel type.");
242 if (SecureSvm::inverseQuadraticRBF != this->
kernel) {
243 output = output + encryptedKernelValue * this->
aVector[i];
248 if (SecureSvm::inverseQuadraticRBF == this->
kernel) {
257 for (
size_t i = 0; i < this->
aVector.size(); ++i) {
262 output = output + inverseQuadraticRbfKernelValues[i] * this->
aVector[i];
290 if (this->
model->label[0] < 0)
297 if (SecureSvm::linear != this->
kernel) {
298 this->
scaledGamma = BigInteger(this->
model->param.gamma, this->gammaScaling);
311 double minAbsAi = std::abs(this->
model->sv_coef[0][0]);
312 for (
unsigned int i = 1; i < static_cast<unsigned int>(this->
model->l); ++i) {
313 if (minAbsAi > std::abs(this->
model->sv_coef[0][i])) {
314 minAbsAi = std::abs(this->
model->sv_coef[0][i]);
318 double minAbsAiB = minAbsAi;
319 if (minAbsAi > std::abs(this->
model->rho[0])) {
320 minAbsAiB = std::abs(this->
model->rho[0]);
328 for (
unsigned int i = 0; i < static_cast<unsigned int>(this->
model->l); ++i) {
331 double aValue = this->
reversedSign ? -this->
model->sv_coef[0][i] / minAbsAiB : this->
model->sv_coef[0][i] / minAbsAiB;
351 case SecureSvm::linear:
356 case SecureSvm::homogeneousPolynomial:
357 case SecureSvm::inhomogeneousPolynomial:
366 case SecureSvm::inverseQuadraticRBF:
374 throw std::runtime_error(
"Invalid kernel type.");
380 double bValue = this->
reversedSign ? this->
model->rho[0] / minAbsAiB : -(this->
model->rho[0] / minAbsAiB);
381 BigInteger scaledB = BigInteger(bValue, bScaling);
392 BigInteger gammaSquared = this->
scaledGamma.GetPow(2);
394 for (
unsigned int row = 0; row < static_cast<unsigned int>(this->
model->l); ++row) {
413 svm_node *iterator = this->
model->SV[row];
418 while (-1 != iterator->index) {
420 BigInteger tempSValue(iterator->value, this->featureScalingFactor);
423 if (tempSValue == 0) {
430 tempS.push_back(tempSValue);
436 if (SecureSvm::linear == this->
kernel) {
438 this->
sMatrix.emplace_back(tempS);
442 if (SecureSvm::linear != this->
kernel) {
443 for (
size_t i = 0; i < tempS.size(); ++i) {
445 if (SecureSvm::inverseQuadraticRBF != this->
kernel) {
446 for (
size_t j = i; j < tempS.size(); ++j) {
449 tempTwoGammaSquaredSS.push_back(two * gammaSquared * tempS[i] * tempS[j]);
452 tempTwoGammaSquaredSS.push_back(gammaSquared * tempS[i] * tempS[j]);
459 if (SecureSvm::inhomogeneousPolynomial == this->
kernel) {
461 BigInteger tempSValue = tempS[i];
468 tempTwoGammaS.push_back(two * this->
scaledGamma * tempSValue);
472 if (SecureSvm::inverseQuadraticRBF == this->
kernel) {
477 tempMinusTwoS.push_back(-two * tempS[i]);
482 if (SecureSvm::inverseQuadraticRBF != this->
kernel) {
487 if (SecureSvm::inhomogeneousPolynomial == this->
kernel) {
492 if (SecureSvm::inverseQuadraticRBF == this->
kernel) {
501 if (SecureSvm::inhomogeneousPolynomial == this->
kernel) {
514 if (SecureSvm::inverseQuadraticRBF == this->
kernel) {
554 for (
size_t i = 0; i < s.size(); ++i) {
560 output = output + x[i] * s[i];
583 for (
size_t i = 0; i < xx.size(); ++i) {
584 output = output + xx[i] * twoGammaSquaredSS[i];
590 for (
size_t i = 0; i < s.size(); ++i) {
591 for (
size_t j = 0; j < s.size(); ++j) {
597 index = i * (s.size() - 1) - (i - 1) * i / 2 + j;
601 index = j * (s.size() - 1) - (j - 1) * j / 2 + i;
607 output = output + xx[index] * ss[index];
660 for (
size_t i = 0; i < x.size(); ++i) {
661 encryptedDenominator = encryptedDenominator + xSquared[i] + x[i] * minusTwoS[i] + encryptedSSquared[i];
669 return encryptedDenominator;
PaillierCiphertext Ciphertext
Provide public access to the T_Ciphertext type.
std::vector< Paillier::Ciphertext > EncryptedVector
Define a vector template specialization for vectors of encrypted data.
Paillier cryptoProvider
The crypto provider.
unsigned short minimumAiDecimalDigits
The minimum number of relevant decimal digits that should preserve.
BigInteger inverseQuadraticRbfNumerator
Scaled 1 - the inverse quadratic RBF kernel numerator.
Ciphertext GetEncryptedZero(const bool randomized=true) const
Returns [0].
Paillier::Ciphertext encryptedZero
Contains [0], used for optimization purposes.
Paillier::Ciphertext linearKernel(const SecureSvm::EncryptedVector &x, const SecureSvm::ModelVector &s) const
Computes the linear kernel on encrypted data.
static Config & GetInstance()
Returns a reference to the singleton.
std::vector< ModelVector > sMatrix
Matrix which stores the scaled SVM model vectors.
const std::string & GetUnsafeClasses() const
Returns the unsafe classes of safety block SVMs.
BigInteger scaledGamma
Stores the scaled gamma SVM parameter (1/(number of attributes) by default)
static const std::map< std::string, KernelTypes > kernelTypesMap
Map kernel names to the kernelTypes enum.
std::vector< BigInteger > aVector
Vector which stores the scaled SVM parameters.
SecureSvm::KernelTypes kernel
The SVM kernel type.
virtual T_Ciphertext EncryptInteger(const BigInteger &plaintext) const
Encrypt an integer and apply randomization.
Definition of class SecureSvm.
BigInteger gammaScaling
The scaling applied to the SVM gamma parameter.
std::string safetyModelFilePrefix
The prefix of the safety block model files.
static KernelTypes GetKernel(const std::string &input)
Converts the input string to the proper kernel.
Paillier::Ciphertext inhomogeneousPolynomialKernel(const SecureSvm::EncryptedVector &x, const SecureSvm::EncryptedVector &xx, const SecureSvm::ModelVector &twoGammaS, const SecureSvm::ModelVector &twoGammaSquaredSS) const
Computes the second degree polynomial kernel on encrypted data.
KernelTypes
Types of implemented kernels.
Paillier::Ciphertext homogeneousPolynomialKernel(const SecureSvm::EncryptedVector &xx, const SecureSvm::ModelVector &twoGammaSquaredSS) const
Computes the second degree polynomial kernel on encrypted data.
std::string modelFileName
The name of the model file.
Paillier::Ciphertext computeInverseQuadraticRbfKernelDenominator(const SecureSvm::EncryptedVector &x, const SecureSvm::EncryptedVector &xSquared, const SecureSvm::ModelVector &minusTwoS, const SecureSvm::EncryptedVector &encryptedSSquared) const
Computes the inverse quadratic RBF kernel d values on encrypted data.
Paillier::Ciphertext Predict(const SecureSvm::EncryptedVector &x, const SecureSvm::EncryptedVector &xx=SecureSvm::nullVector, const SecureSvm::EncryptedVector &xSquared=SecureSvm::nullVector) const
Computes the prediction for a given set of data.
std::vector< EncryptedVector > encryptedSSquaredMatrix
Matrix which stores the encrypted scaled SVM model vectors.
BigInteger featureScalingFactor
The scaling applied to the test and model vectors and .
unsigned short inverseQuadraticRbfKernelRelevantDigits
The number of digits preserved in the inverse quadratic RBF kernel value after performing the divisio...
T GetParameter(const std::string ¶meter) const
Template method which returns the value of the specified configuration parameter. ...
std::weak_ptr< const Server > server
A reference to the server - required for interactive protocol requests with the client (secure divisi...
std::vector< ModelVector > twoGammaSquaredSSMatrix
Matrix containing scaled vector product combinations, , stored as an unraveled upper triangular matri...
std::vector< ModelVector > minusTwoSMatrix
Matrix which stores the scaled vectors.
Paillier::Ciphertext encryptedScaledOne
[scaled 1], required when computing the inhomogeneous kernel. Precompute it for optimization purposes...
std::vector< ModelVector > twoGammaSMatrix
Matrix which stores the scaled vectors.
BigInteger blindingFactorScaling
The scaling that needs to be applied to the b parameter in order to compensate for the blinding facto...
SecureSvm(const std::string &directoryPath, const std::string &modelFile, const PaillierPublicKey &publicKey, const std::weak_ptr< const Server > &server)
Constructor.
std::string safetyModelUnsafeClasses
The unsafe classes of the safety block model.
bool reversedSign
During training, libsvm uses an internal flag to denote the sign of the first label it encounters...
BigInteger svWeightScaling
static const EncryptedVector nullVector
Use this to pass a NULL vector to the Predict method;.
Definition of class Server.
Paillier::Ciphertext encryptedB
Stores the scaled and encrypted SVM parameter (-rho in libsvm)
std::vector< BigInteger > ModelVector
Define an std::vector template specialization for rows of model weights.
The public key container structure for the Paillier cryptosystem.
void preprocessData()
Performs scalings and encryptions.