You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@milagro.apache.org by sa...@apache.org on 2020/02/07 12:57:27 UTC

[incubator-milagro-MPC] 07/11: Add benchmark and example for mtawc zkp

This is an automated email from the ASF dual-hosted git repository.

sandreoli pushed a commit to branch add-mta-zk-proofs
in repository https://gitbox.apache.org/repos/asf/incubator-milagro-MPC.git

commit 1ab4ed2fa48759a85c1c3919f66676b832bf7a89
Author: Samuele Andreoli <sa...@yahoo.it>
AuthorDate: Wed Feb 5 17:05:12 2020 +0000

    Add benchmark and example for mtawc zkp
---
 benchmark/bench_mta_zkwc.c  | 226 ++++++++++++++++++++++++++++++++++++++
 examples/example_mta_zkwc.c | 257 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 483 insertions(+)

diff --git a/benchmark/bench_mta_zkwc.c b/benchmark/bench_mta_zkwc.c
new file mode 100644
index 0000000..d9db043
--- /dev/null
+++ b/benchmark/bench_mta_zkwc.c
@@ -0,0 +1,226 @@
+/*
+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 ZKP of knowledge of factoring.
+ */
+
+#include "bench.h"
+#include "amcl/mta.h"
+
+#define MIN_TIME 5.0
+#define MIN_ITERS 10
+
+// Primes for Paillier key
+char *P_hex = "94f689d07ba20cf7c7ca7ccbed22ae6b40c426db74eaee4ce0ced2b6f52a5e136663f5f1ef379cdbb0c4fdd6e4074d6cff21082d4803d43d89e42fd8dfa82b135aa31a8844ffea25f255f956cbc1b9d8631d01baf1010d028a190b94ce40f3b72897e8196df19edf1ff62e6556f2701d52cef1442e3301db7608ecbdcca703db";
+char *Q_hex = "9a9ad73f246df853e129c589925fdad9df05606a61081e62e72be4fb33f6e5ec492cc734f28bfb71fbe2ba9a11e4c02e2c0d103a5cbb0a9d6402c07de63b1b995dd72ac8f29825d66923a088b421fb4d52b0b855d2f5dde2be9b0ca0cee6f7a94e5566735fe6cff1fcad3199602f88528d19aa8d0263adff8f5053c38254a2a3";
+
+// BC setup
+char *PT_hex    = "CA5F37B7C0DDF6530B30A41116588218DE95F1F36B807FD7C28E4C467EE3F35967BC01D28B71F8A627A353675A81C86A1FF03DCECAF1686891183FA317BA34A4A1148D40A89F1F3AC0C200511C6CFE02342CD75354C25A2E069886DD4FB73BD365660D163F1282B143119AB8F375A73875EC16B634F52593B73BC6D875F2D3EF";
+char *QT_hex    = "C2FC545C1C803F6C7625FBC4ECF9355734D6B6058FD714816D3ECFB93F1F705C9CE90D4F8796A05148AB5ABC201F90889231CC6BF5F68ED15EE4D901F603930A280EEABF10C613BFCB67A816363C839EB902B02607EB48AB8325E2B72620D4D294A232803217090DFB50AF8C620D4679E77CE3053437ED518F4F68840DCF1AA3";
+char *ALPHA_hex = "1128dc85f9bbdde2826244bcefd0ec6668c19ee254b81bbbfc7575ec45922fc573567d45dc27fc659ec29e8909548a94f1d1ed280cfa49d75192c8cb04925884fa2e7ee9cce71bf5f699f73c07a9bcfbeed87aa4446099a940a03b6828a292319f3a4a71206bd902e9f99f6d6226344a14a0eb2b127b0e8925db779c21fa15ef 465212e8b5c0a8bd2fb3d171bfdad345d15676ad65f20447d8d28d9f7a3be092903966725054e94d95f7aff0ff854efeae993e9b97a2942fa7426cd1bfb843cd635c1058fb73d21ab7f9cc2319a307129f4f84369c01f0e29ea3716dfa692c56a3e4aae1437e9110464003af [...]
+char *B0_hex    = "544c8b0766c7490f7c6abfe0517709f3ab2c9b81fa8455cd8f99302dc58efa8d73318b078b31e49336d05caae1be491e620ec4893dfd50153c75d99d81970995c48b73cbb379097f69d55d4fb07de6124388b30c5718ccc5bd251945a1a51de335a7ebc4e226d7a60d82a7afc485845e849228de10211b2b8d7a759dd24ec4a4 57fdae3380b96fa8f3e12ba112a2ea07c1a74484ae7938e80afd4f17e17dddb7257fdcddfbcf2d2c51f350fb0c30a4eed76625039e5310da553ceaad1f9993c3b25bff1a657800308d4864199baeec8036945a9ac2bb429bd92d568b500f65268743179451623d45e7e25234 [...]
+
+// Paillier ciphertext and plaintext
+char* X_hex  = "0000000000000000000000000000000000000000000000000000000000000003";
+char* Y_hex  = "0000000000000000000000000000000000000000000000000000000000000004";
+char* C1_hex = "19c8b725dbd74b7dcaf72bd9ff2cd207b47cb1095393685906171af9e2f2959e7f68729e0e40f97a22bbca93373d618ad51dd077c0d102938598a8ecc8a656e978ebd14007da99db8e691d85fc18a428097ee8a63dcf95b84b660294474a20ed2edcf2b1b4f305c1cc25860a08d1348c2a4d24cc1a97b51f920e2985b8108b3392a5eafc443cf3449e288eb49dbde2228a56233afa5a6643e5ae6ec6aa8937a666ef74a30625c35bb22c3cc57b700f8eae7690f8d37edbfd27ccb2e882f70d0d85e0cc825347453a28e98e877ab1eeaa6efa09f034bc8976bffb86420106978066ff52221b315f71eb32cbf608d2 [...]
+char* C2_hex = "1f1f087e749c85aacdacaace8659a33b53baad5eec1e56628435d335a8b150f96865d6e090f53146e120e7089b6f4a91c762622b24d0d2fba0e703301170a0b826a1336d4d6bb83dccd29ad9ef0936614bf14e992ea4daa202c63ace9bd3f95b9a8a6edd7949e89ec165541e7c01bd41395baf3e2fe7f3a9611af8b5ed8639c02a2bfc236c17a136bef6d09f966db718f3df9d6f4f40b618b4b6058b4e4ec241e6c2424404d0aee0ef5cd666e5c4253a62ae9deb09289fb84657109e0b933f58871ba7ea77190d6ea45a04be68360478adf43a85851cf583c5575543578635996d2dcd020aeceabf18be6ff8b45e [...]
+char* R_hex  = "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 [...]
+
+// DLOG public ECP
+char *ECPX_hex = "02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9";
+
+// RV for Range Proof
+char *ZK_ALPHA_hex = "000000000000000000000000000000000000000000000000000000000000000076f5e997c4867a05c7997d84a283473a8c611ed65a8cf0acfaf17d8930700af9bd20b9f17545d87ab92d9820be15f922d452027cabba1a66ccb1d816daaf84adda09ffbaa981b6985d55e3bbf440089a405f90fca71b0767ea7b7d3125965c8b";
+char *BETA_hex     = "89d4ea9f023d28e5a69b21995668c4c12abc92bd7f6b2b446c37bb3d2db4e1235f4a213dcc3bdb054ddd6287fcc4987235916985505bfb16c81dab556ee8f8470e714a646600f532eaf2d6709cf93df9afcf4f0a97569e75a53a903b3b323dc38bd7db5231bef89ea6ebc46c364d21ad2fd547699e59625b98200d0f7375fb8d39b4ae6fba9c300fe6f565cf4d5625d127afd11da71b97db9c36c34221b70625307d91d0c3e447cbbfe4db3677a1bccd60f077e7cf4d1c3c51df8e359536676f0ad4a804f408fd37348f6b45102a75069812a7cd62c1a2aac267ea44e3b1cc499de47baab2450d97d16fb9 [...]
+char *GAMMA_hex    = "b5f19c6877cb4e4adf42b68c9bc70912bdaaa783f7c59bb03698095c964b84d2d453a2ad6f9948dc6fa0d2ce38115b96e74fddeaa33e2838ad7303eacab69816318d74d200269178971879e27e6c31a3dcbc0288b2adbd749f5249e03046ce73eb55ec7abc738b837d7973247c8fc4992232672ef58a9e423e3ed8ad55e9ce29b2b8f9839a6d61f04a4de0fdcd87f4bd3e36976b86257f275158b318b5ebe5e8e9098fc99213b1cd1266db9169c61170e19cd7c9f99224111e5d8dc4aca32def232bc236bdae32c5bff081abc92d7963de20258a75a13db67d3f5fd1567d836cc083f9e4bb251301f7de06 [...]
+char *RHO_hex      = "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000021d7fe4be0364f97b605cbc60fb1d081220fe45635b245f1f88ff35c0b9a00d7253df086e791a13a085752ae0ecc47bda62c98bf7f0dcd428eb75242c32277f41e23f1d41046464c89e9fe0a527e2196fee85564c2b2107388b6069a6f44b8f4354067fcebca5d0671b17146658aa4372a855984b1f9a102f35b1764dd1bb43dc3c14b08bd6230413cf54a [...]
+char *RHO1_hex     = "000000000000000000000000000000000000000000000000000000000000000058c0c9f5ddbf7bd65d5878ca82a4ea6e6f4887e0f400b326213a076685004ca34e7d6a56ef83c0aa9c95b5fcc44db71bb14cb4faf1ff717da92f57ddc1dd8e318ccd1b7de38bdbda1a193d5dc92f78092a90da77ec295817bc4129bd689ca860ce3f8dbb11065cdec047a2f8fe25fc2fc2c13b82347bee6b96b1444dcb4af664e8be05634e338f2a8c6931030f24f35e44aa4976a82312d46675e67afd30c505103050aedb1c15c8e613ebd81bc3301920254f91226afe3972bfdb569fe6a70938397e047afb83a853e2b2 [...]
+char *SIGMA_hex    = "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004b407580fb3003f6ee0e91502d0fe5bc85804356c143afa7e9c27254a19806619283e7cea7ad9791ebdb12a0901968560d422f274e833f9d5bcdf14238df3caf39a16ac84868e31a338f89966a9c17b608d6efbbc34c33c6a09e6f5752cf4bd34a6f3eb5170689c8393c07a828d8b3541a7c6132bf217f1797450fe38818c838e8ec10656a4e336d770df8 [...]
+char *TAU_hex      = "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000765cade56daf04af46039c9b3ea3f64faac275c0d7472bcfe9ccb4f624c828876573a69a8588b18612feb9ab30aaf68358862f8da2a12625a2dc70740dfe6a54e86a1187184d5c0381d2d14a476e908bc27aba81fb190d9a938f1f1e7ddf01044fed18239b6b0248492c50f3568128d19387e59491537fc3c0bbe727247f0e8166384d7140788fd0f8d04e [...]
+
+int main()
+{
+    int rc;
+
+    int iterations;
+    clock_t start;
+    double elapsed;
+
+    PAILLIER_private_key priv_key;
+    PAILLIER_public_key pub_key;
+    COMMITMENTS_BC_priv_modulus priv_mod;
+    COMMITMENTS_BC_pub_modulus pub_mod;
+
+    MTA_ZKWC_commitment c;
+    MTA_ZKWC_commitment_rv rv;
+    MTA_ZKWC_proof proof;
+
+    char c1[2*FS_2048];
+    octet C1 = {0, sizeof(c1), c1};
+
+    char c2[2*FS_2048];
+    octet C2 = {0, sizeof(c2), c2};
+
+    char r[2*FS_2048];
+    octet R = {0, sizeof(r), r};
+
+    char x[MODBYTES_256_56];
+    octet X = {0, sizeof(x), x};
+
+    char ecpx[EFS_SECP256K1 + 1];
+    octet ECPX = {0, sizeof(ecpx), ecpx};
+
+    char y[MODBYTES_256_56];
+    octet Y = {0, sizeof(y), y};
+
+    char e[MODBYTES_256_56];
+    octet E = {0, sizeof(e), e};
+
+    char p[HFS_2048];
+    octet P = {0, sizeof(p), p};
+
+    char q[HFS_2048];
+    octet Q = {0, sizeof(q), q};
+
+    char alpha[FS_2048];
+    octet ALPHA = {0, sizeof(alpha), alpha};
+
+    char b0[FS_2048];
+    octet B0 = {0, sizeof(b0), b0};
+
+    char oct[FS_2048 + HFS_2048];
+    octet OCT = {0, sizeof(oct), oct};
+
+    // Load paillier key
+    OCT_fromHex(&P, P_hex);
+    OCT_fromHex(&Q, Q_hex);
+    PAILLIER_KEY_PAIR(NULL, &P, &Q, &pub_key, &priv_key);
+
+    // Load DLOG ECP
+    OCT_fromHex(&ECPX, ECPX_hex);
+
+    // Generate BC commitment modulus
+    OCT_fromHex(&P,     PT_hex);
+    OCT_fromHex(&Q,     QT_hex);
+    OCT_fromHex(&ALPHA, ALPHA_hex);
+    OCT_fromHex(&B0,    B0_hex);
+    COMMITMENTS_BC_setup(NULL, &priv_mod, &P, &Q, &ALPHA, &B0);
+    COMMITMENTS_BC_export_public_modulus(&pub_mod, &priv_mod);
+
+    // Load Paillier encryption values
+    OCT_fromHex(&X,  X_hex);
+    OCT_fromHex(&Y,  Y_hex);
+    OCT_fromHex(&R,  R_hex);
+    OCT_fromHex(&C1, C1_hex);
+    OCT_fromHex(&C2, C2_hex);
+
+    // Load Random Values for Range Proof
+    OCT_fromHex(&OCT, ZK_ALPHA_hex);
+    OCT_pad(&OCT, FS_2048);
+    FF_2048_fromOctet(rv.alpha, &OCT, FFLEN_2048);
+
+    OCT_fromHex(&OCT, BETA_hex);
+    FF_2048_fromOctet(rv.beta, &OCT, FFLEN_2048);
+
+    OCT_fromHex(&OCT, GAMMA_hex);
+    FF_2048_fromOctet(rv.gamma, &OCT, FFLEN_2048);
+
+    OCT_fromHex(&OCT, RHO_hex);
+    FF_2048_fromOctet(rv.rho, &OCT, FFLEN_2048 + HFLEN_2048);
+
+    OCT_fromHex(&OCT, RHO1_hex);
+    FF_2048_fromOctet(rv.rho1, &OCT, FFLEN_2048 + HFLEN_2048);
+
+    OCT_fromHex(&OCT, SIGMA_hex);
+    FF_2048_fromOctet(rv.sigma, &OCT, FFLEN_2048 + HFLEN_2048);
+
+    OCT_fromHex(&OCT, TAU_hex);
+    FF_2048_fromOctet(rv.tau, &OCT, FFLEN_2048 + HFLEN_2048);
+
+    print_system_info();
+
+    printf("Timing info\n");
+    printf("===========\n");
+
+    iterations = 0;
+    start = clock();
+    do
+    {
+        MTA_ZKWC_commit(NULL, &pub_key, &pub_mod, &X, &Y, &C1, &c, &rv);
+        iterations++;
+        elapsed = (clock() - start) / (double)CLOCKS_PER_SEC;
+    }
+    while (elapsed < MIN_TIME || iterations < MIN_ITERS);
+
+    elapsed = MILLISECOND * elapsed / iterations;
+    printf("\tMTA_ZKWC_commit\t\t%8d iterations\t", iterations);
+    printf("%8.2lf ms per iteration\n", elapsed);
+
+    iterations = 0;
+    start = clock();
+    do
+    {
+        MTA_ZKWC_challenge(&pub_key, &pub_mod, &C1, &C2, &ECPX, &c, &E);
+        iterations++;
+        elapsed = (clock() - start) / (double)CLOCKS_PER_SEC;
+    }
+    while (elapsed < MIN_TIME || iterations < MIN_ITERS);
+
+    elapsed = MICROSECOND * elapsed / iterations;
+    printf("\tMTA_ZKWC_challenge\t%8d iterations\t", iterations);
+    printf("%8.2lf us per iteration\n", elapsed);
+
+    iterations = 0;
+    start = clock();
+    do
+    {
+        MTA_ZKWC_prove(&pub_key, &rv, &X, &Y, &R, &E, &proof);
+        iterations++;
+        elapsed = (clock() - start) / (double)CLOCKS_PER_SEC;
+    }
+    while (elapsed < MIN_TIME || iterations < MIN_ITERS);
+
+    elapsed = MILLISECOND * elapsed / iterations;
+    printf("\tMTA_ZKWC_prove\t\t%8d iterations\t", iterations);
+    printf("%8.2lf ms per iteration\n", elapsed);
+
+    iterations = 0;
+    start = clock();
+    do
+    {
+        rc = MTA_ZKWC_verify(&priv_key, &priv_mod, &C1, &C2, &ECPX, &E, &c, &proof);
+        iterations++;
+        elapsed = (clock() - start) / (double)CLOCKS_PER_SEC;
+    }
+    while (elapsed < MIN_TIME || iterations < MIN_ITERS);
+
+    if (rc != MTA_OK)
+    {
+        printf("FAILURE MTA_ZKWC_verify: %d\n", rc);
+        exit(EXIT_FAILURE);
+    }
+
+    elapsed = MILLISECOND * elapsed / iterations;
+    printf("\tMTA_ZKWC_verify\t\t%8d iterations\t", iterations);
+    printf("%8.2lf ms per iteration\n", elapsed);
+
+    exit(EXIT_SUCCESS);
+}
diff --git a/examples/example_mta_zkwc.c b/examples/example_mta_zkwc.c
new file mode 100644
index 0000000..28781a3
--- /dev/null
+++ b/examples/example_mta_zkwc.c
@@ -0,0 +1,257 @@
+/*
+    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.
+*/
+
+#include <string.h>
+#include "amcl/mta.h"
+#include "amcl/commitments.h"
+
+/* MTA Receiver ZK Proof example */
+
+// Primes for Paillier key
+char *P_hex = "94f689d07ba20cf7c7ca7ccbed22ae6b40c426db74eaee4ce0ced2b6f52a5e136663f5f1ef379cdbb0c4fdd6e4074d6cff21082d4803d43d89e42fd8dfa82b135aa31a8844ffea25f255f956cbc1b9d8631d01baf1010d028a190b94ce40f3b72897e8196df19edf1ff62e6556f2701d52cef1442e3301db7608ecbdcca703db";
+char *Q_hex = "9a9ad73f246df853e129c589925fdad9df05606a61081e62e72be4fb33f6e5ec492cc734f28bfb71fbe2ba9a11e4c02e2c0d103a5cbb0a9d6402c07de63b1b995dd72ac8f29825d66923a088b421fb4d52b0b855d2f5dde2be9b0ca0cee6f7a94e5566735fe6cff1fcad3199602f88528d19aa8d0263adff8f5053c38254a2a3";
+
+// Safe primes for BC setup
+char *PT_hex = "CA5F37B7C0DDF6530B30A41116588218DE95F1F36B807FD7C28E4C467EE3F35967BC01D28B71F8A627A353675A81C86A1FF03DCECAF1686891183FA317BA34A4A1148D40A89F1F3AC0C200511C6CFE02342CD75354C25A2E069886DD4FB73BD365660D163F1282B143119AB8F375A73875EC16B634F52593B73BC6D875F2D3EF";
+char *QT_hex = "C2FC545C1C803F6C7625FBC4ECF9355734D6B6058FD714816D3ECFB93F1F705C9CE90D4F8796A05148AB5ABC201F90889231CC6BF5F68ED15EE4D901F603930A280EEABF10C613BFCB67A816363C839EB902B02607EB48AB8325E2B72620D4D294A232803217090DFB50AF8C620D4679E77CE3053437ED518F4F68840DCF1AA3";
+
+// Paillier ciphertext and plaintext
+char* X_hex = "0000000000000000000000000000000000000000000000000000000000000003";
+char* Y_hex = "0000000000000000000000000000000000000000000000000000000000000004";
+char* C1_hex = "19c8b725dbd74b7dcaf72bd9ff2cd207b47cb1095393685906171af9e2f2959e7f68729e0e40f97a22bbca93373d618ad51dd077c0d102938598a8ecc8a656e978ebd14007da99db8e691d85fc18a428097ee8a63dcf95b84b660294474a20ed2edcf2b1b4f305c1cc25860a08d1348c2a4d24cc1a97b51f920e2985b8108b3392a5eafc443cf3449e288eb49dbde2228a56233afa5a6643e5ae6ec6aa8937a666ef74a30625c35bb22c3cc57b700f8eae7690f8d37edbfd27ccb2e882f70d0d85e0cc825347453a28e98e877ab1eeaa6efa09f034bc8976bffb86420106978066ff52221b315f71eb32cbf608d2 [...]
+char* C2_hex = "1f1f087e749c85aacdacaace8659a33b53baad5eec1e56628435d335a8b150f96865d6e090f53146e120e7089b6f4a91c762622b24d0d2fba0e703301170a0b826a1336d4d6bb83dccd29ad9ef0936614bf14e992ea4daa202c63ace9bd3f95b9a8a6edd7949e89ec165541e7c01bd41395baf3e2fe7f3a9611af8b5ed8639c02a2bfc236c17a136bef6d09f966db718f3df9d6f4f40b618b4b6058b4e4ec241e6c2424404d0aee0ef5cd666e5c4253a62ae9deb09289fb84657109e0b933f58871ba7ea77190d6ea45a04be68360478adf43a85851cf583c5575543578635996d2dcd020aeceabf18be6ff8b45e [...]
+char* R_hex = "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 [...]
+
+// DLOG public ECP
+char *ECPX_hex = "02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9";
+
+int main()
+{
+    int rc;
+
+    PAILLIER_private_key priv_key;
+    PAILLIER_public_key pub_key;
+    COMMITMENTS_BC_priv_modulus priv_mod;
+    COMMITMENTS_BC_pub_modulus pub_mod;
+
+    MTA_ZKWC_commitment c;
+    MTA_ZKWC_commitment_rv rv;
+    MTA_ZKWC_proof proof;
+
+    char c1[2*FS_2048];
+    octet C1 = {0, sizeof(c1), c1};
+
+    char c2[2*FS_2048];
+    octet C2 = {0, sizeof(c2), c2};
+
+    char r[2*FS_2048];
+    octet R = {0, sizeof(r), r};
+
+    char x[MODBYTES_256_56];
+    octet X = {0, sizeof(x), x};
+
+    char ecpx[EFS_SECP256K1 + 1];
+    octet ECPX = {0, sizeof(ecpx), ecpx};
+
+    char y[MODBYTES_256_56];
+    octet Y = {0, sizeof(y), y};
+
+    char e[MODBYTES_256_56];
+    octet E = {0, sizeof(e), e};
+
+    char p[HFS_2048];
+    octet P = {0, sizeof(p), p};
+
+    char q[HFS_2048];
+    octet Q = {0, sizeof(q), q};
+
+    char u[EFS_SECP256K1 + 1];
+    octet U = {0, sizeof(u), u};
+
+    char z[FS_2048];
+    octet Z = {0, sizeof(z), z};
+
+    char z1[FS_2048];
+    octet Z1 = {0, sizeof(z1), z1};
+
+    char t[FS_2048];
+    octet T = {0, sizeof(t), t};
+
+    char v[2 * FS_2048];
+    octet V = {0, sizeof(v), v};
+
+    char w[FS_2048];
+    octet W = {0, sizeof(w), w};
+
+    char s[FS_2048];
+    octet S = {0, sizeof(s), s};
+
+    char s1[HFS_2048];
+    octet S1 = {0, sizeof(s1), s1};
+
+    char s2[FS_2048 + HFS_2048];
+    octet S2 = {0, sizeof(s2), s2};
+
+    char t1[FS_2048];
+    octet T1 = {0, sizeof(t1), t1};
+
+    char t2[FS_2048 + HFS_2048];
+    octet T2 = {0, sizeof(t2), t2};
+
+    // Deterministic RNG for testing
+    char seed[32] = {0};
+    csprng RNG;
+    RAND_seed(&RNG, 32, seed);
+
+    // Load paillier key
+    OCT_fromHex(&P, P_hex);
+    OCT_fromHex(&Q, Q_hex);
+
+    PAILLIER_KEY_PAIR(NULL, &P, &Q, &pub_key, &priv_key);
+
+    printf("Run MTA Range Proof\nParameters:\n");
+    printf("\tPaillier Key\n");
+    printf("\t\tP = ");
+    OCT_output(&P);
+    printf("\t\tQ = ");
+    OCT_output(&Q);
+
+    // Generate BC commitment modulus
+    OCT_fromHex(&P, PT_hex);
+    OCT_fromHex(&Q, QT_hex);
+    COMMITMENTS_BC_setup(&RNG, &priv_mod, &P, &Q, NULL, NULL);
+
+    COMMITMENTS_BC_export_public_modulus(&pub_mod, &priv_mod);
+
+    FF_2048_output(priv_mod.alpha, FFLEN_2048);
+    printf("\n");
+    FF_2048_output(priv_mod.b0, FFLEN_2048);
+
+    printf("\n\tBit Commitment Modulus\n");
+    printf("\t\tP = ");
+    OCT_output(&P);
+    printf("\t\tQ = ");
+    OCT_output(&Q);
+
+    // Load Paillier encryption values
+    OCT_fromHex(&X,  X_hex);
+    OCT_fromHex(&Y,  Y_hex);
+    OCT_fromHex(&R,  R_hex);
+    OCT_fromHex(&C1, C1_hex);
+    OCT_fromHex(&C2, C2_hex);
+
+    // Load DLOG ECP
+    OCT_fromHex(&ECPX, ECPX_hex);
+
+    printf("\nInput:\n");
+    printf("\t\tX    = ");
+    OCT_output(&X);
+    printf("\t\tY    = ");
+    OCT_output(&Y);
+    printf("\t\tC1   = ");
+    OCT_output(&C1);
+    printf("\t\tC2   = ");
+    OCT_output(&C2);
+    printf("\t\tR    = ");
+    OCT_output(&R);
+    printf("\t\tECPX = ");
+    OCT_output(&ECPX);
+
+    // Prover - commit to values for the proof and output
+    // the commitment to octets for transmission
+    MTA_ZKWC_commit(&RNG, &pub_key, &pub_mod, &X, &Y, &C1, &c, &rv);
+    MTA_ZKWC_commitment_toOctets(&U, &Z, &Z1, &T, &V, &W, &c);
+
+    printf("\nCommitment Phase\n");
+    printf("\tGenerate Random Values:");
+    printf("\n\t\tALPHA = ");
+    FF_2048_output(rv.alpha, HFLEN_2048);
+    printf("\n\t\tBETA  = ");
+    FF_2048_output(rv.beta, FFLEN_2048);
+    printf("\n\t\tGAMMA = ");
+    FF_2048_output(rv.gamma, FFLEN_2048);
+    printf("\n\t\tRHO   = ");
+    FF_2048_output(rv.rho, FFLEN_2048 + HFLEN_2048);
+    printf("\n\t\tRHO1  = ");
+    FF_2048_output(rv.rho1, FFLEN_2048 + HFLEN_2048);
+    printf("\n\t\tSIGMA = ");
+    FF_2048_output(rv.sigma, FFLEN_2048 + HFLEN_2048);
+    printf("\n\t\tTAU   = ");
+    FF_2048_output(rv.tau, FFLEN_2048 + HFLEN_2048);
+    printf("\n\n\tGenerate Commitment:\n");
+    printf("\t\tU  = ");
+    OCT_output(&U);
+    printf("\t\tZ  = ");
+    OCT_output(&Z);
+    printf("\t\tZ1 = ");
+    OCT_output(&Z1);
+    printf("\t\tT  = ");
+    OCT_output(&T);
+    printf("\t\tV  = ");
+    OCT_output(&V);
+    printf("\t\tW  = ");
+    OCT_output(&W);
+
+    // Prover - compute deterministic challenge
+    MTA_ZKWC_challenge(&pub_key, &pub_mod, &C1, &C2, &ECPX, &c, &E);
+
+    printf("\nCompute deterministic challenge\n");
+    printf("\t\tE = ");
+    OCT_output(&E);
+
+    // Prover - generate proof and otuput it to octets for transmission
+    MTA_ZKWC_prove(&pub_key, &rv, &X, &Y, &R, &E, &proof);
+    MTA_ZKWC_proof_toOctets(&S, &S1, &S2, &T1, &T2, &proof);
+
+    printf("\nProof Phase\n");
+    printf("\t\tS  = ");
+    OCT_output(&S);
+    printf("\t\tS1 = ");
+    OCT_output(&S1);
+    printf("\t\tS2 = ");
+    OCT_output(&S2);
+    printf("\t\tT1 = ");
+    OCT_output(&T1);
+    printf("\t\tT2 = ");
+    OCT_output(&T2);
+
+    // Prover - clean random values
+    MTA_ZKWC_commitment_rv_kill(&rv);
+
+    // Transmit the proof and commitment to the verifier
+
+    // Verifier - read commitment and proof from octets
+    MTA_ZKWC_proof_fromOctets(&proof, &S, &S1, &S2, &T1, &T2);
+    MTA_ZKWC_commitment_fromOctets(&c, &U, &Z, &Z1, &T, &V, &W);
+
+    // Verifier - compute deterministic challenge
+    MTA_ZKWC_challenge(&pub_key, &pub_mod, &C1, &C2, &ECPX, &c, &E);
+
+    printf("\nVerification\n");
+
+    rc = MTA_ZKWC_verify(&priv_key, &priv_mod, &C1, &C2, &ECPX, &E, &c, &proof);
+    if (rc == MTA_OK)
+    {
+        printf("\t\tSuccess!\n");
+    }
+    else
+    {
+        printf("\t\tFailure!\n");
+    }
+}