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:31 UTC

[incubator-milagro-MPC] 11/11: Add random challenge generation for interactive ZK proofs

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 990b4edbd066af1ca96a8a191a85bd6b21f05802
Author: Samuele Andreoli <sa...@yahoo.it>
AuthorDate: Thu Feb 6 10:24:44 2020 +0000

    Add random challenge generation for interactive ZK proofs
---
 examples/example_mta_zk_interactive.c      | 247 +++++++++++++++++++++++++++++
 include/amcl/mta.h                         |  16 ++
 src/mta.c                                  |  12 ++
 test/smoke/test_mta_zk_interactive_smoke.c | 136 ++++++++++++++++
 4 files changed, 411 insertions(+)

diff --git a/examples/example_mta_zk_interactive.c b/examples/example_mta_zk_interactive.c
new file mode 100644
index 0000000..6729f8f
--- /dev/null
+++ b/examples/example_mta_zk_interactive.c
@@ -0,0 +1,247 @@
+/*
+    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 interactive ZK Proof example
+ *
+ * This example uses the Receiver ZK Proof, but the
+ * same procedure can be used for the Range Proof and
+ * the Receiver ZK Proof with check
+ */
+
+// 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 [...]
+
+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_ZK_commitment c;
+    MTA_ZK_commitment_rv rv;
+    MTA_ZK_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 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 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);
+
+    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);
+
+    // Prover - commit to values for the proof and output
+    // the commitment to octets for transmission
+    MTA_ZK_commit(&RNG, &pub_key, &pub_mod, &X, &Y, &C1, &c, &rv);
+    MTA_ZK_commitment_toOctets(&Z, &Z1, &T, &V, &W, &c);
+
+    printf("\n[Prover] Commitment 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\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);
+
+    // Verifier - compute deterministic challenge and send it
+    // back to the prover
+    MTA_ZK_random_challenge(&RNG, &E);
+
+    printf("\n[Verifier] Compute random challenge\n");
+    printf("\t\tE = ");
+    OCT_output(&E);
+
+    // Prover - generate proof and otuput it to octets for transmission
+    MTA_ZK_prove(&pub_key, &rv, &X, &Y, &R, &E, &proof);
+    MTA_ZK_proof_toOctets(&S, &S1, &S2, &T1, &T2, &proof);
+
+    printf("\n[Prover] Proof 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_ZK_commitment_rv_kill(&rv);
+
+    // Transmit the proof and commitment to the verifier
+
+    // Verifier - read commitment and proof from octets
+    MTA_ZK_proof_fromOctets(&proof, &S, &S1, &S2, &T1, &T2);
+    MTA_ZK_commitment_fromOctets(&c, &Z, &Z1, &T, &V, &W);
+
+    // Verifier - compute deterministic challenge
+    MTA_ZK_challenge(&pub_key, &pub_mod, &C1, &C2, &c, &E);
+
+    printf("\n[Verifier] Verification\n");
+
+    rc = MTA_ZK_verify(&priv_key, &priv_mod, &C1, &C2, &E, &c, &proof);
+    if (rc == MTA_OK)
+    {
+        printf("\t\tSuccess!\n");
+    }
+    else
+    {
+        printf("\t\tFailure!\n");
+    }
+}
diff --git a/include/amcl/mta.h b/include/amcl/mta.h
index a78593f..824989e 100644
--- a/include/amcl/mta.h
+++ b/include/amcl/mta.h
@@ -111,6 +111,22 @@ void MPC_SUM_MTA(octet *A, octet *B, octet *ALPHA, octet *BETA, octet *SUM);
 
 // The protocols require a BC modulus (Pt, Qt, Nt, h1, h2) and a Paillier PK (N, g)
 
+/** \brief Random challenge for any of the ZK Proofs
+ *
+ *  Generate a random challenge for any of the ZK Proofs
+ *  below. This can be used instead of the deterministic challenges
+ *  produced for each specific proof to make any of the proofs
+ *  interactive and be interoperable with other implementations.
+ *
+ *  <ol>
+ *  <li> \f$ e \in_R [0, \ldots, q] \f$
+ *  <ol>
+ *
+ *  @param RNG               csprng for random generation
+ *  @param E                 Destination octet for the challenge.
+ */
+void MTA_ZK_random_challenge(csprng *RNG, octet *E);
+
 /* Range Proof API */
 
 /** \brief Secret random values for the Range Proof commitment */
diff --git a/src/mta.c b/src/mta.c
index 3022be0..1a7cd4c 100644
--- a/src/mta.c
+++ b/src/mta.c
@@ -336,6 +336,18 @@ void MPC_SUM_MTA(octet *A, octet *B, octet *ALPHA, octet *BETA,  octet *SUM)
     BIG_256_56_toBytes(SUM->val,sum);
 }
 
+void MTA_ZK_random_challenge(csprng *RNG, octet *E)
+{
+    BIG_256_56 e;
+    BIG_256_56 q;
+
+    BIG_256_56_rcopy(q, CURVE_Order_SECP256K1);
+    BIG_256_56_randomnum(e, q, RNG);
+
+    BIG_256_56_toBytes(E->val, e);
+    E->len = EGS_SECP256K1;
+}
+
 void MTA_RP_commit(csprng *RNG, PAILLIER_private_key *key, COMMITMENTS_BC_pub_modulus *mod,  octet *M, MTA_RP_commitment *c, MTA_RP_commitment_rv *rv)
 {
     BIG_1024_58 n[FFLEN_2048];
diff --git a/test/smoke/test_mta_zk_interactive_smoke.c b/test/smoke/test_mta_zk_interactive_smoke.c
new file mode 100644
index 0000000..6ceb1ec
--- /dev/null
+++ b/test/smoke/test_mta_zk_interactive_smoke.c
@@ -0,0 +1,136 @@
+/*
+    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"
+
+void ff_2048_cleaned(BIG_1024_58 *a, char *name, int n)
+{
+    if(!FF_2048_iszilch(a, n))
+    {
+        fprintf(stderr, "FAILURE MTA_ZK_commitment_rv_kill. %s was not cleaned\n", name);
+        exit(EXIT_FAILURE);
+    }
+}
+
+/* MTA ZKP interactive smoke tests */
+
+// 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 [...]
+
+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_ZK_commitment c;
+    MTA_ZK_commitment_rv rv;
+    MTA_ZK_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 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};
+
+    // 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);
+
+    // 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);
+
+    // 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);
+
+    // Run smoke test
+    MTA_ZK_commit(&RNG, &pub_key, &pub_mod, &X, &Y, &C1, &c, &rv);
+    MTA_ZK_random_challenge(&RNG, &E);
+    MTA_ZK_prove(&pub_key, &rv, &X, &Y, &R, &E, &proof);
+
+    rc = MTA_ZK_verify(&priv_key, &priv_mod, &C1, &C2, &E, &c, &proof);
+    if (rc != MTA_OK)
+    {
+        printf("FAILURE MTA_ZK interactive smoke test. rc = %d\n", rc);
+        exit(EXIT_FAILURE);
+    }
+
+    // Clean random values
+    MTA_ZK_commitment_rv_kill(&rv);
+
+    ff_2048_cleaned(rv.alpha, "rv.alpha", FFLEN_2048);
+    ff_2048_cleaned(rv.beta,  "rv.beta",  FFLEN_2048);
+    ff_2048_cleaned(rv.gamma, "rv.gamma", FFLEN_2048);
+    ff_2048_cleaned(rv.rho,   "rv.rho",   FFLEN_2048 + HFLEN_2048);
+    ff_2048_cleaned(rv.sigma, "rv.sigma", FFLEN_2048 + HFLEN_2048);
+    ff_2048_cleaned(rv.tau,   "rv.tau",   FFLEN_2048 + HFLEN_2048);
+
+    printf("SUCCESS");
+    exit(EXIT_SUCCESS);
+}