This is an automated email from the ASF dual-hosted git repository. sandreoli pushed a commit to branch issue51 in repository https://gitbox.apache.org/repos/asf/incubator-milagro-crypto-c.git
commit 6662a6f16652d8526f0323f83535578a43329a05 Author: samuele-andreoli <[email protected]> AuthorDate: Tue Nov 12 12:56:43 2019 +0000 add benchmark and example --- benchmark/CMakeLists.txt | 6 + benchmark/benchtest_paillier.c.in | 356 ++++++++++++++++++++++++++++++++++++++ examples/CMakeLists.txt | 5 + examples/example_paillier.c | 280 ++++++++++++++++++++++++++++++ 4 files changed, 647 insertions(+) diff --git a/benchmark/CMakeLists.txt b/benchmark/CMakeLists.txt index b1e7c37..af05ab7 100644 --- a/benchmark/CMakeLists.txt +++ b/benchmark/CMakeLists.txt @@ -50,3 +50,9 @@ foreach(level ${AMCL_RSA}) add_executable(benchtest_rsa_${TFF} ${benchtest_rsa_${TFF}_GEN_SRCS}) target_link_libraries(benchtest_rsa_${TFF} PRIVATE amcl_rsa_${TFF}) endforeach() + +if(${BUILD_PAILLIER}) + amcl_configure_file_core(benchtest_paillier.c.in benchtest_paillier.c benchtest_paillier_GEN_SRCS) + add_executable(benchtest_paillier ${benchtest_paillier_GEN_SRCS}) + target_link_libraries(benchtest_paillier PRIVATE amcl_paillier) +endif() diff --git a/benchmark/benchtest_paillier.c.in b/benchmark/benchtest_paillier.c.in new file mode 100644 index 0000000..2cfb594 --- /dev/null +++ b/benchmark/benchtest_paillier.c.in @@ -0,0 +1,356 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. +*/ + +/* + Benchmark Paillier crypto system. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include "ff_8192.h" +#include "ff_4096.h" +#include "ff_2048.h" +#include "randapi.h" +#include "paillier.h" +#include "amcl.h" +#include "arch.h" + +#define MIN_TIME 5.0 +#define MIN_ITERS 10 +#define NTHREADS 2 + +// https://sourceforge.net/p/predef/wiki/Compilers/ +static void print_compiler_info() +{ +#if defined(__clang__) + printf("Compiler:\t\tclang (%s)\n", __clang_version__); +#elif defined(__GNUC_PATCHLEVEL__) + printf("Compiler:\t\tgcc (%d.%d.%d)\n", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__); +#elif defined(__GNUC_MINOR__) + printf("Compiler:\t\tgcc (%d.%d)\n", __GNUC__, __GNUC_MINOR__); +#elif defined(__INTEL_COMPILER) + printf("Compiler:\t\tIntel C/C++ (%d)\n", __INTEL_COMPILER); +#elif defined(_MSC_FULL_VER) + printf("Compiler:\tMicrosoft C/C++ (%d)\n", _MSC_FULL_VER); +#elif defined(__CC_ARM) + printf("Compiler:\t\tARM C/C++ (%d)\n", __ARMCC_VERSION); +#else + printf("Compiler:\t\tUnknown"\n); +#endif +} + +#if defined(__ANDROID__) +#include <android/api-level.h> +#endif + +// https://sourceforge.net/p/predef/wiki/Architectures/ +// https://sourceforge.net/p/predef/wiki/OperatingSystems/ +static void print_platform_info() +{ +#if defined(__linux__) + printf("Target platform:\tLinux "); + +#if defined(__x86_64__) + printf("(64-bit)\n"); +#else + printf("(32-bit)\n"); +#endif + +#if defined(__ANDROID__) + printf("Target platform:\tAndroid %d\n", __ANDROID_API__); +#endif + +#elif defined(_WIN64) + printf("Target platform:\tWindows (64-bit)\n"); +#elif defined(_WIN32) + printf("Target platform:\tWindows (32-bit)\n"); +#elif defined(__APPLE__) + printf("Target platform:\tMac OS\n"); +#else + printf("Target platform:\tUnknown\n"); +#endif +} + + +static void print_paillier_configuration() +{ + printf("Project Version:\t@BUILD_VERSION@\n"); + printf("CFLAGS:\t\t\t@CMAKE_C_FLAGS@\n"); + printf("Build type:\t\t@CMAKE_BUILD_TYPE@\n"); + printf("AMCL Version:\t\t@AMCL_VERSION_MAJOR@.@AMCL_VERSION_MINOR@.@AMCL_VERSION_PATCH@\n"); + printf("AMCL Detected OS:\t@OS@\n"); + printf("AMCL CHUNK:\t\t%d\n", CHUNK); +} + +static void print_system_info() +{ + printf("Configuration info\n"); + printf("==================\n"); + print_platform_info(); + print_compiler_info(); + print_paillier_configuration(); + printf("\n"); +} + + +int paillier(csprng *RNG) +{ + int rc; + + int iterations; + clock_t start; + double elapsed; + + char p[FS_2048]; + octet P = {0,sizeof(p),p}; + char q[FS_2048]; + octet Q = {0,sizeof(q),q}; + + char p1[FS_2048]; + octet P1 = {0,sizeof(p1),p1}; + char q1[FS_2048]; + octet Q1 = {0,sizeof(q1),q1}; + + char n[FS_2048] = {0}; + octet N = {0,sizeof(n),n}; + char g[FS_2048]; + octet G = {0,sizeof(g),g}; + + char l[FS_2048] = {0}; + octet L = {0,sizeof(l),l}; + + char m[FS_2048] = {0}; + octet M = {0,sizeof(m),m}; + + // Plaintext to encrypt + char ptin[NTHREADS][FS_2048]; + octet PTIN[NTHREADS]; + char ptout[NTHREADS][FS_2048]; + octet PTOUT[NTHREADS]; + + // Constant value for multiplication + char ptko[NTHREADS][FS_2048]; + octet PTK[NTHREADS]; + + // Encrypted PTIN values + char cto[NTHREADS][FS_4096]; + octet CT[NTHREADS]; + + // Homomorphic multiplicaton of plaintext by a constant ciphertext + char cta[NTHREADS][FS_4096]; + octet CTA[NTHREADS]; + + // Homomorphic addition of ciphertext + char cto3[FS_4096] = {0}; + octet CT3 = {0,sizeof(cto3),cto3}; + + // Output plaintext of addition of homomorphic multiplication values + char pto3[FS_2048] = {0}; + octet PT3 = {sizeof(pto3),sizeof(pto3),pto3}; + + // Expected ouput is 26 / 0x1a i.e. 2*3 + 4*5 + int values[NTHREADS] = {2,4}; + int kvalues[NTHREADS] = {3,5}; + + print_system_info(); + + // Initialize octets + for(int i=0; i<NTHREADS; i++) + { + memset(ptin[i], 0, FS_2048*sizeof(ptin[i][0])); + PTIN[i].max = FS_2048; + PTIN[i].len = 0; + PTIN[i].val = ptin[i]; + + memset(ptout[i], 0, FS_2048*sizeof(ptout[i][0])); + PTOUT[i].max = FS_2048; + PTOUT[i].len = 0; + PTOUT[i].val = ptout[i]; + + memset(ptko[i], 0, FS_2048*sizeof(ptko[i][0])); + PTK[i].max = FS_2048; + PTK[i].len = 0; + PTK[i].val = ptko[i]; + + memset(cto[i], 0, FS_4096*sizeof(cto[i][0])); + CT[i].max = FS_4096; + CT[i].len = 0; + CT[i].val = cto[i]; + + memset(cta[i], 0, FS_4096*sizeof(cta[i][0])); + CTA[i].max = FS_4096; + CTA[i].len = 0; + CTA[i].val = cta[i]; + } + + printf("Timing info\n"); + printf("===========\n"); + + // Generating public/private key pair + iterations=0; + start=clock(); + do + { + PAILLIER_KEY_PAIR(RNG, &P, &Q, &N, &G, &L, &M); + iterations++; + elapsed=(clock()-start)/(double)CLOCKS_PER_SEC; + } + while (elapsed<MIN_TIME || iterations<MIN_ITERS); + elapsed=1000.0*elapsed/iterations; + printf("PAILLIER_KEY_PAIR\t%8d iterations\t",iterations); + printf("%8.2lf ms per iteration\n",elapsed); + + // Set plaintext values + for(int i=0; i<NTHREADS; i++) + { + BIG_1024_58 pt[FFLEN_2048]; + FF_2048_init(pt, values[i],FFLEN_2048); + FF_2048_toOctet(&PTIN[i], pt, FFLEN_2048); + + BIG_1024_58 ptk[FFLEN_2048]; + FF_2048_init(ptk, kvalues[i],FFLEN_2048); + FF_2048_toOctet(&PTK[i], ptk, FFLEN_2048); + } + + // Encrypt plaintext + iterations=0; + start=clock(); + do + { + PAILLIER_ENCRYPT(RNG, &N, &G, &PTIN[0], &CT[0], NULL); + iterations++; + elapsed=(clock()-start)/(double)CLOCKS_PER_SEC; + } + while (elapsed<MIN_TIME || iterations<MIN_ITERS); + elapsed=1000.0*elapsed/iterations; + printf("PAILLIER_ENCRYPT\t%8d iterations\t",iterations); + printf("%8.2lf ms per iteration\n",elapsed); + + rc = PAILLIER_ENCRYPT(RNG, &N, &G, &PTIN[1], &CT[1], NULL); + if (rc) + { + fprintf(stderr, "ERROR PAILLIER_ENCRYPT rc: %d\n", rc); + exit(EXIT_FAILURE); + } + + // Multiple by constant + iterations=0; + start=clock(); + do + { + PAILLIER_MULT(&N, &CT[0], &PTK[0], &CTA[0]); + iterations++; + elapsed=(clock()-start)/(double)CLOCKS_PER_SEC; + } + while (elapsed<MIN_TIME || iterations<MIN_ITERS); + elapsed=1000.0*elapsed/iterations; + printf("PAILLIER_MULT\t\t%8d iterations\t",iterations); + printf("%8.2lf ms per iteration\n",elapsed); + + rc = PAILLIER_MULT(&N, &CT[1], &PTK[1], &CTA[1]); + if (rc) + { + fprintf(stderr, "ERROR PAILLIER_MULT rc: %d\n", rc); + exit(EXIT_FAILURE); + } + + // Homomorphic addition + iterations=0; + start=clock(); + do + { + PAILLIER_ADD(&N, &CTA[0], &CTA[1], &CT3); + iterations++; + elapsed=(clock()-start)/(double)CLOCKS_PER_SEC; + } + while (elapsed<MIN_TIME || iterations<MIN_ITERS); + elapsed=1000.0*elapsed/iterations; + printf("PAILLIER_ADD\t\t%8d iterations\t",iterations); + printf("%8.2lf ms per iteration\n",elapsed); + + // Homomorphic addition + iterations=0; + start=clock(); + do + { + PAILLIER_DECRYPT(&N, &L, &M, &CT3, &PT3); + iterations++; + elapsed=(clock()-start)/(double)CLOCKS_PER_SEC; + } + while (elapsed<MIN_TIME || iterations<MIN_ITERS); + elapsed=1000.0*elapsed/iterations; + printf("PAILLIER_DECRYPT\t%8d iterations\t",iterations); + printf("%8.2lf ms per iteration\n\n",elapsed); + + printf("Size info\n"); + printf("=========\n"); + + printf("public key n\t%d bytes\n", FS_2048); + printf("public key g\t%d bytes\n", FS_2048); + printf("secret key l\t%d bytes\n", FS_2048); + printf("secret key m\t%d bytes\n", FS_2048); + printf("ciphertext\t%d bytes\n", FS_4096); + +#ifdef DEBUG + printf("PT3: "); + OCT_output(&PT3); + printf("\n"); +#endif + + OCT_clear(&P); + OCT_clear(&Q); + OCT_clear(&P1); + OCT_clear(&Q1); + OCT_clear(&N); + OCT_clear(&G); + OCT_clear(&L); + OCT_clear(&M); + OCT_clear(&CT3); + OCT_clear(&PT3); + for(int i=0; i<NTHREADS; i++) + { + OCT_clear(&PTIN[i]); + OCT_clear(&PTOUT[i]); + OCT_clear(&CT[i]); + OCT_clear(&CTA[i]); + } + return 0; +} + +int main() +{ + char* seedHex = "78d0fb6705ce77dee47d03eb5b9c5d30"; + char seed[16] = {0}; + octet SEED = {sizeof(seed),sizeof(seed),seed}; + + // CSPRNG + csprng RNG; + + // fake random source + OCT_fromHex(&SEED,seedHex); + + // initialise strong RNG + CREATE_CSPRNG(&RNG,&SEED); + + paillier(&RNG); + + KILL_CSPRNG(&RNG); +} diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 785630e..d22cffe 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -66,3 +66,8 @@ foreach(level ${AMCL_RSA}) target_link_libraries(example_rsa_${TFF} PRIVATE amcl_rsa_${TFF}) endforeach() + +if(BUILD_PAILLIER) + add_executable(example_paillier example_paillier.c) + target_link_libraries(example_paillier PRIVATE amcl_paillier) +endif() diff --git a/examples/example_paillier.c b/examples/example_paillier.c new file mode 100644 index 0000000..884929f --- /dev/null +++ b/examples/example_paillier.c @@ -0,0 +1,280 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. +*/ + +/* + Example of Paillier crypto system. + + Homomorphic multiplicaton of ciphertext by a constant and + homomorphic addition of ciphertexts + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include "ff_8192.h" +#include "ff_4096.h" +#include "ff_2048.h" +#include "randapi.h" +#include "paillier.h" + +#define NTHREADS 2 + +int paillier(csprng *RNG) +{ + int rc; + char p[FS_2048]; + octet P = {0,sizeof(p),p}; + char q[FS_2048]; + octet Q = {0,sizeof(q),q}; + + char n[FS_2048] = {0}; + octet N = {0,sizeof(n),n}; + char g[FS_2048]; + octet G = {0,sizeof(g),g}; + + char l[FS_2048] = {0}; + octet L = {0,sizeof(l),l}; + + char m[FS_2048] = {0}; + octet M = {0,sizeof(m),m}; + + // Plaintext to encrypt + char ptin[NTHREADS][FS_2048]; + octet PTIN[NTHREADS]; + char ptout[NTHREADS][FS_2048]; + octet PTOUT[NTHREADS]; + + // Constant value for multiplication + char ptko[NTHREADS][FS_2048]; + octet PTK[NTHREADS]; + + // Encrypted PTIN values + char cto[NTHREADS][FS_4096]; + octet CT[NTHREADS]; + + // Homomorphic multiplicaton of plaintext by a constant ciphertext + char cta[NTHREADS][FS_4096]; + octet CTA[NTHREADS]; + + // Homomorphic addition of ciphertext + char cto3[FS_4096] = {0}; + octet CT3 = {0,sizeof(cto3),cto3}; + + // Output plaintext of addition of homomorphic multiplication values + char pto3[FS_2048] = {0}; + octet PT3 = {sizeof(pto3),sizeof(pto3),pto3}; + + // Expected ouput is 26 / 0x1a i.e. 2*3 + 4*5 + int values[NTHREADS] = {2,4}; + int kvalues[NTHREADS] = {3,5}; + + // Initialize octets + for(int i=0; i<NTHREADS; i++) + { + memset(ptin[i], 0, FS_2048*sizeof(ptin[i][0])); + PTIN[i].max = FS_2048; + PTIN[i].len = 0; + PTIN[i].val = ptin[i]; + + memset(ptout[i], 0, FS_2048*sizeof(ptout[i][0])); + PTOUT[i].max = FS_2048; + PTOUT[i].len = 0; + PTOUT[i].val = ptout[i]; + + memset(ptko[i], 0, FS_2048*sizeof(ptko[i][0])); + PTK[i].max = FS_2048; + PTK[i].len = 0; + PTK[i].val = ptko[i]; + + memset(cto[i], 0, FS_4096*sizeof(cto[i][0])); + CT[i].max = FS_4096; + CT[i].len = 0; + CT[i].val = cto[i]; + + memset(cta[i], 0, FS_4096*sizeof(cta[i][0])); + CTA[i].max = FS_4096; + CTA[i].len = 0; + CTA[i].val = cta[i]; + } + + printf("Generating public/private key pair\n"); + rc = PAILLIER_KEY_PAIR(RNG, &P, &Q, &N, &G, &L, &M); + if (rc) + { + fprintf(stderr, "ERROR PAILLIER_KEY_PAIR rc: %d\n", rc); + exit(EXIT_FAILURE); + } + + printf("P: "); + OCT_output(&P); + printf("\n"); + printf("Q: "); + OCT_output(&Q); + printf("\n"); + + printf("Public Key \n"); + printf("N: "); + OCT_output(&N); + printf("\n"); + printf("G: "); + OCT_output(&G); + printf("\n"); + + printf("Secret Key \n"); + printf("L: "); + OCT_output(&L); + printf("\n"); + printf("M: "); + OCT_output(&M); + printf("\n"); + + // Set plaintext values + for(int i=0; i<NTHREADS; i++) + { + BIG_1024_58 pt[FFLEN_2048]; + FF_2048_init(pt, values[i],FFLEN_2048); + FF_2048_toOctet(&PTIN[i], pt, FFLEN_2048); + + BIG_1024_58 ptk[FFLEN_2048]; + FF_2048_init(ptk, kvalues[i],FFLEN_2048); + FF_2048_toOctet(&PTK[i], ptk, FFLEN_2048); + } + + for(int i=0; i<NTHREADS; i++) + { + printf("PTIN[%d] ", i); + OCT_output(&PTIN[i]); + printf("\n"); + } + + // Encrypt plaintext + for(int i=0; i<NTHREADS; i++) + { + rc = PAILLIER_ENCRYPT(RNG, &N, &G, &PTIN[i], &CT[i], NULL); + if (rc) + { + fprintf(stderr, "ERROR PAILLIER_ENCRYPT rc: %d\n", rc); + exit(EXIT_FAILURE); + } + } + + for(int i=0; i<NTHREADS; i++) + { + printf("CT[%d] ", i); + OCT_output(&CT[i]); + printf("\n"); + } + + // Decrypt ciphertexts + for(int i=0; i<NTHREADS; i++) + { + rc = PAILLIER_DECRYPT(&N, &L, &M, &CT[i], &PTOUT[i]); + if (rc) + { + fprintf(stderr, "ERROR PAILLIER_DECRYPT rc: %d\n", rc); + exit(EXIT_FAILURE); + } + } + + for(int i=0; i<NTHREADS; i++) + { + printf("PTOUT[%d] ", i); + OCT_output(&PTOUT[i]); + printf("\n"); + } + + for(int i=0; i<NTHREADS; i++) + { + rc = PAILLIER_MULT(&N, &CT[i], &PTK[i], &CTA[i]); + if (rc) + { + fprintf(stderr, "ERROR PAILLIER_MULT rc: %d\n", rc); + exit(EXIT_FAILURE); + } + } + + rc = PAILLIER_ADD(&N, &CTA[0], &CTA[1], &CT3); + if (rc) + { + fprintf(stderr, "ERROR PAILLIER_ADD rc: %d\n", rc); + exit(EXIT_FAILURE); + } + + for(int i=0; i<NTHREADS; i++) + { + printf("CTA[%d] ", i); + OCT_output(&CTA[i]); + printf("\n"); + } + printf("CT3: "); + OCT_output(&CT3); + printf("\n"); + + rc = PAILLIER_DECRYPT(&N, &L, &M, &CT3, &PT3); + if (rc) + { + fprintf(stderr, "ERROR PAILLIER_DECRYPT rc: %d\n", rc); + exit(EXIT_FAILURE); + } + + printf("PT3: "); + OCT_output(&PT3); + printf("\n"); + + OCT_clear(&P); + OCT_clear(&Q); + OCT_clear(&N); + OCT_clear(&G); + OCT_clear(&L); + OCT_clear(&M); + OCT_clear(&CT3); + OCT_clear(&PT3); + for(int i=0; i<NTHREADS; i++) + { + OCT_clear(&PTIN[i]); + OCT_clear(&PTOUT[i]); + OCT_clear(&CT[i]); + OCT_clear(&CTA[i]); + } + return 0; +} + +int main() +{ + char* seedHex = "78d0fb6705ce77dee47d03eb5b9c5d30"; + char seed[16] = {0}; + octet SEED = {sizeof(seed),sizeof(seed),seed}; + + // CSPRNG + csprng RNG; + + // fake random source + OCT_fromHex(&SEED,seedHex); + printf("SEED: "); + OCT_output(&SEED); + + // initialise strong RNG + CREATE_CSPRNG(&RNG,&SEED); + + printf("\nPaillier example\n"); + paillier(&RNG); + + KILL_CSPRNG(&RNG); +}
