computeL($g, $n, $lambda); $mu = $this -> gcdExtended($L, $n)[0]; print("\nMu value is $mu"); if($mu < 1){ print("\nNot a valid mu\n"); $list = $this -> keyGeneration($length); }else{ return [$n, $g, $lambda, $mu]; } return $list; } /** If m is a message to be encrypted (0 $publicKey[0]|| $plaintext < 0){ print("\nWrong plaintext!"); } $r = random_int(0, $publicKey[0]); $part1 = gmp_pow($publicKey[1], $plaintext); $part2 = gmp_pow($r, $publicKey[0]); $part3 = gmp_mul($part1, $part2); $N = gmp_mul($publicKey[0] , $publicKey[0]); $cipher = (int)(gmp_mod($part3, $N)); return $cipher; } public function encryptV2($plaintext, $publicKey, $r){ $r = $r; if($plaintext > $publicKey[0]|| $plaintext < 0){ print("\nWrong plaintext!"); } $part1 = gmp_pow($publicKey[1], $plaintext); $part2 = gmp_pow($r, $publicKey[0]); $part3 = gmp_mul($part1, $part2); $N = gmp_mul($publicKey[0] , $publicKey[0]); $cipher = (int)(gmp_mod($part3, $N)); return $cipher; } // plaintext = L(c^λ mod n^2) * (μ mod n) public function decrypt($cipher, $publicKey, $privateKey){ $L = $this->computeL($cipher, $publicKey[0], $privateKey[0]); $secret0 = gmp_mul($L, $privateKey[1]); $secret = (int)gmp_mod($secret0, $publicKey[0]); return $secret; } public function computeL($base, $n, $lambda){ $N = gmp_mul($n,$n); $exp = gmp_pow($base, $lambda); $x = (int)gmp_mod($exp, $N); $L = ceil(($x-1)/$n); return $L; } //To find multiplicative modulo inverse function gcdExtended($a, $b) { $x = 0; $last_x = 1; $y = 1; $last_y = 0; while($b != 0){ $quot = floor($a / $b); $temp3 = $b; $b = $a % $b; $a = $temp3; if ($b < 0) { $b = $b + $a; } $temp1 = $x; $x = $last_x - $quot * $x; $last_x = $temp1; $temp2 = $y; $y = $last_y - $quot * $y; $last_y = $temp2; } return [$last_x, $last_y]; } function homomorphicAddition($plaintext1, $plaintext2, $cipher1, $cipher2, $publicKey, $privateKey){ print("\n-------Homomorphic Addition Proof----------\n"); $N = $publicKey[0] * $publicKey[0]; print("\nDecryption of product of two ciphers\n"); $product0 = gmp_mul($cipher1, $cipher2); $product1 = (int)gmp_mod($product0, $N); $decryptProof0 = $this->decrypt($product1, $publicKey, $privateKey); print($decryptProof0); $product3 = gmp_add($plaintext1, $plaintext2); $decryptProof = gmp_mod($product3, $publicKey[0]); print("\nAddition of two ciphertexts\n"); print($decryptProof); } function homomorphicMultiplication($plaintext1, $cipher1, $cipher2, $publicKey, $privateKey, $k){ print("\n----------Homomorphic Multiplication Proof-------------\n"); $N = $publicKey[0] * $publicKey[0]; $power = gmp_pow($cipher1, $k); $product0 = gmp_mod($power, $N); $decryptProof0 = $this->decrypt($product0, $publicKey, $privateKey); print("\nDecryption of encrypted text to power k\n"); print($decryptProof0); $decryptProof1 = gmp_mod(gmp_mul($k, $plaintext1), $publicKey[0]); print("\nProduct of multiplication of plaintext with k\n"); print($decryptProof1); } function testAddition($plaintext1, $plaintext2, $cipher1, $cipher2, $publicKey, $privateKey){ $lhs = (int)(gmp_mul($cipher1, $cipher2)); $newText = (int)(gmp_add($plaintext1, $plaintext2)); $rhs = $this->decrypt($lhs, $publicKey, $privateKey); print("\n----------------------------\n"); print("\nDecryption of product of two ciphertexts:\n"); print($rhs); print("\nSum of two added plaintext:\n"); print($newText); } } $test = new Paillier(); $plaintext1 = 42; $keys = $test -> keyGeneration(512); print("\n-----Public key is-------\n"); print("n = ".$keys[0]." g = ".$keys[1]); print("\n-----Private key is------\n"); print("lambda = ".$keys[2]." mu = ".$keys[3]); print("\n-------------------------\n"); $publicKey = [$keys[0], $keys[1]]; $privateKey = [$keys[2], $keys[3]]; print("\nPlaintext1 is $plaintext1"); $cipher1 = $test -> encrypt($plaintext1, $publicKey); print("\nCipher 1 is:\n"); print($cipher1); $decrypt1 = $test -> decrypt($cipher1, $publicKey, $privateKey); print("\nDecrypted text1 is:\n"); print($decrypt1); print("\n------------------------------\n"); $plaintext2 = 15; print("\nPlaintext2 is $plaintext2"); $cipher2 = $test -> encrypt($plaintext2, $publicKey); print("\nCipher 2 is:\n"); print($cipher2); $decrypt2 = $test -> decrypt($cipher2, $publicKey, $privateKey); print("\nDecrypted text2 is:\n"); print($decrypt2); $test->homomorphicAddition($plaintext1, $plaintext2, $cipher1, $cipher2, $publicKey, $privateKey); $test->homomorphicMultiplication($plaintext1, $cipher1, $cipher2, $publicKey, $privateKey, 15); $test->testAddition($plaintext1, $plaintext2, $cipher1, $cipher2, $publicKey, $privateKey); ?>