// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.8.2 <0.9.0;
contract PaillierHomomorphicEncryption {
uint256 public p;
uint256 public q;
uint256 public n;
uint256 public g;
uint256 public l;
uint256 public m;
struct PrivateKey {
uint256 l;
uint256 m;
}
struct PublicKey {
uint256 n;
uint256 n_sq;
uint256 g;
}
PublicKey publicKey;
PrivateKey privateKey;
constructor() {
// Initialize key generation parameters (simplified)
p = 1000000009; // Replace with a prime number
q = 1000000007; // Replace with another prime number
n = p * q;
l = (p - 1) * (q - 1);
m = modInverse(l, n, 1000000); // Calculate the modular inverse
publicKey = PublicKey(n, n * n, n+1);
privateKey = PrivateKey(l, m);
}
function modInverse(uint256 a, uint256 pp, uint256 maxiter) public pure returns (uint256) {
uint256 r = a;
uint256 d = 1;
for (uint256 i = 0; i < min(pp, maxiter); i++) {
d = ((pp / r + 1) * d) % pp;
r = (d * a) % pp;
if (r == 1) {
break;
}
}
return d;
}
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
// Encrypt a plaintext value
function encrypt(uint256 plaintext) public view returns (uint256) {
require(plaintext < n, "Plaintext must be smaller than n");
uint256 r = 5;
uint256 x = powmod(r, publicKey.n, publicKey.n_sq);
return (powmod(publicKey.g, plaintext, publicKey.n_sq) * x) % publicKey.n_sq;
}
// Decrypt a ciphertext value
function decrypt(uint256 ciphertext) public view returns (uint256) {
uint256 c1 = (powmod(ciphertext, privateKey.l, publicKey.n_sq) - 1) % publicKey.n_sq;
uint256 plaintext = ((c1 / publicKey.n) * privateKey.m) % publicKey.n;
return plaintext;
}
function add(uint256 a, uint256 b) public view returns (uint256) {
uint256 a_enc = encrypt(a);
uint256 b_enc = encrypt(b);
uint256 product_enc = (a_enc * b_enc) % publicKey.n_sq;
return decrypt(product_enc);
}
function powmod(uint256 a, uint256 b, uint256 n) public pure returns (uint256) {
if(a > n)
a-=n;
if (b == 0) {
return 1;
} else if (b % 2 == 0) {
uint256 temp = powmod(a, b / 2, n);
return (temp * temp) % n;
} else {
uint256 temp = powmod(a, (b - 1) / 2, n);
return (a * ((temp * temp) % n)) % n;
}
}
}
{"html5":"htmlmixed","css":"css","javascript":"javascript","php":"php","python":"python","ruby":"ruby","lua":"text\/x-lua","bash":"text\/x-sh","go":"go","c":"text\/x-csrc","cpp":"text\/x-c++src","diff":"diff","latex":"stex","sql":"sql","xml":"xml","apl":"apl","asterisk":"asterisk","c_loadrunner":"text\/x-csrc","c_mac":"text\/x-csrc","coffeescript":"text\/x-coffeescript","csharp":"text\/x-csharp","d":"d","ecmascript":"javascript","erlang":"erlang","groovy":"text\/x-groovy","haskell":"text\/x-haskell","haxe":"text\/x-haxe","html4strict":"htmlmixed","java":"text\/x-java","java5":"text\/x-java","jquery":"javascript","mirc":"mirc","mysql":"sql","ocaml":"text\/x-ocaml","pascal":"text\/x-pascal","perl":"perl","perl6":"perl","plsql":"sql","properties":"text\/x-properties","q":"text\/x-q","scala":"scala","scheme":"text\/x-scheme","tcl":"text\/x-tcl","vb":"text\/x-vb","verilog":"text\/x-verilog","yaml":"text\/x-yaml","z80":"text\/x-z80"}