From 86b0e9be8da26d559d3df7e21fb53b86a2c166c9 Mon Sep 17 00:00:00 2001 From: Brian Thorne Date: Mon, 11 Jan 2016 17:15:10 +1100 Subject: [PATCH] #6 Command to multiply encrypted number with unencrypted number and test. Currently will fail due to result having more negative exponent after the multiplication is carried out. --- phe/command_line.py | 32 ++++++++++++++++++++++- phe/tests/cli_test.py | 61 +++++++++++++++++++++++++++++++++++++++---- 2 files changed, 87 insertions(+), 6 deletions(-) diff --git a/phe/command_line.py b/phe/command_line.py index 13cd0bf..67bc56c 100755 --- a/phe/command_line.py +++ b/phe/command_line.py @@ -223,11 +223,41 @@ def add_encrypted_to_plaintext(public, encrypted, plaintext, output): num = float(plaintext) log("Adding") - enc_result = enc + num serialised_result = serialise_encrypted(enc_result) print(serialised_result, file=output) +@cli.command("multiply") +@click.argument('public', type=click.File('r')) +@click.argument('encrypted', type=click.File('r')) +@click.argument('plaintext', type=str) +@click.option('--output', type=click.File('w'), + help="Save to file instead of stdout") +def multiply_encrypted_to_plaintext(public, encrypted, plaintext, output): + """Multiply an encrypted number to a non encrypted number. + + """ + log("Loading public key") + publickeydata = json.load(public) + pub = load_public_key(publickeydata) + + log("Loading encrypted number") + enc = load_encrypted_number(encrypted, pub) + + log("Loading unencrypted number") + num = float(plaintext) + + encoded_number = phe.EncodedNumber.encode(pub, num, max_exponent=-32) + + assert encoded_number.exponent == -32 + + log("Multiplying") + enc_result = enc * encoded_number + assert enc_result.exponent == -32 + serialised_result = serialise_encrypted(enc_result) + print(serialised_result, file=output) + + if __name__ == "__main__": cli() diff --git a/phe/tests/cli_test.py b/phe/tests/cli_test.py index 06c5d57..c6311e6 100644 --- a/phe/tests/cli_test.py +++ b/phe/tests/cli_test.py @@ -1,5 +1,6 @@ import json import random +import unittest from unittest import TestCase import tempfile @@ -222,12 +223,19 @@ def encrypt_and_add(self, a, b): out = outfile.read() return float(out) - def encrypt_a_and_add_b(self, a, b): + def _a_b_encrypt_helper(self, a, b, operation): self.runner.invoke(cli, - ['encrypt', self.public_keyfile.name, '--output', self.enc_a_file.name, '--', str(a)]) + [ + 'encrypt', + self.public_keyfile.name, + '--output', + self.enc_a_file.name, + '--', + str(a) + ]) result = self.runner.invoke(cli, [ - 'add', + operation, '--output', self.enc_result_file.name, self.public_keyfile.name, @@ -236,7 +244,7 @@ def encrypt_a_and_add_b(self, a, b): str(b) ]) - assert result.exit_code == 0 + assert result.exit_code == 0, "Problem carrying out the {} operation".format(operation) with tempfile.NamedTemporaryFile() as outfile: result = self.runner.invoke(cli, [ @@ -247,6 +255,12 @@ def encrypt_a_and_add_b(self, a, b): out = outfile.read() return float(out) + def encrypt_a_and_add_b(self, a, b): + return self._a_b_encrypt_helper(a, b, 'add') + + def encrypt_a_and_multiply_b(self, a, b): + return self._a_b_encrypt_helper(a, b, 'multiply') + class TestConsoleAddition(TestConsoleHelpers): @@ -267,7 +281,6 @@ def test_addenc_large_ints(self): out = self.encrypt_and_add(a, b) self.assertAlmostEqual(float(a + b), float(out)) - def test_add_large_ints(self): """Test adding large integers. """ @@ -311,6 +324,31 @@ def test_add_large_floats(self): self.assertAlmostEqual(float(a + b), float(out)) +class TestConsoleMultiplication(TestConsoleHelpers): + """ + Expected to fail until we decide if encrypted numbers with different + exponents are allowed for this CLI... + """ + + @unittest.expectedFailure + def test_multiply_floats(self): + a, b = 1.2345, 0.6 + out = self.encrypt_a_and_multiply_b(a, b) + self.assertAlmostEqual(float(a * b), float(out)) + + @unittest.expectedFailure + def test_multiply_random_ints(self): + """ + """ + MAX = 10000 + MIN = -MAX + + for _ in range(20): + a, b = random.randrange(MIN, MAX), random.randrange(MIN, MAX) + out = self.encrypt_a_and_multiply_b(a, b) + self.assertAlmostEqual(float(a * b), float(out)) + + class TestFuzz(TestConsoleHelpers): def test_addenc_random_ints(self): @@ -352,3 +390,16 @@ def test_add_random_floats(self): self.assertAlmostEqual(float(a + b), float(out)) + @unittest.expectedFailure + def test_multiply_random_ints(self): + """ + """ + MAX = 10000 + MIN = -MAX + + for _ in range(20): + a, b = random.randrange(MIN, MAX), random.randrange(MIN, MAX) + out = self.encrypt_a_and_multiply_b(a, b) + self.assertAlmostEqual(float(a * b), float(out)) + +