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 2021/04/16 13:12:19 UTC
[incubator-milagro-MPC] 03/05: Add GG20 ZKP
This is an automated email from the ASF dual-hosted git repository.
sandreoli pushed a commit to branch gg20
in repository https://gitbox.apache.org/repos/asf/incubator-milagro-MPC.git
commit ce9f6d5fe6635807fac647580dd6f1f71ec78dc1
Author: Samuele Andreoli <sa...@yahoo.it>
AuthorDate: Fri Apr 16 14:05:38 2021 +0100
Add GG20 ZKP
---
benchmark/bench_gg20_zkp_phase3.c | 162 +++
benchmark/bench_gg20_zkp_phase6.c | 177 +++
benchmark/bench_modulus.c | 100 ++
benchmark/bench_shamir.c | 175 +++
examples/example_gg20_full.c | 2056 ++++++++++++++++++++++++++++
examples/example_gg20_reshare.c | 903 ++++++++++++
examples/example_gg20_zkp_phase3.c | 137 ++
examples/example_gg20_zkp_phase6.c | 165 +++
include/amcl/gg20_zkp.h | 226 +++
python/amcl/gg20_zkp.py | 417 ++++++
python/amcl/schnorr.py | 3 -
python/benchmark/bench_bc_setup.py | 65 +
python/benchmark/bench_gg20_zkp.py | 112 ++
python/examples/example_gg20_zkp.py | 195 +++
python/test/test_gg20_zkp.py | 225 +++
python/test/test_schnorr.py | 6 +-
src/gg20_zkp.c | 375 +++++
src/mta_zkp.c | 318 +++++
src/schnorr.c | 62 +-
test/smoke/test_gg20_zkp_phase3_smoke.c | 102 ++
test/smoke/test_gg20_zkp_phase6_smoke.c | 124 ++
test/test.c | 104 +-
test/test.h | 50 +-
testVectors/gg20_zkp/octets.txt | 59 +
testVectors/gg20_zkp/phase3_challenge.json | 82 ++
testVectors/gg20_zkp/phase3_challenge.txt | 70 +
testVectors/gg20_zkp/phase3_commit.json | 62 +
testVectors/gg20_zkp/phase3_commit.txt | 50 +
testVectors/gg20_zkp/phase3_prove.json | 102 ++
testVectors/gg20_zkp/phase3_prove.txt | 90 ++
testVectors/gg20_zkp/phase3_verify.json | 82 ++
testVectors/gg20_zkp/phase3_verify.txt | 70 +
testVectors/gg20_zkp/phase6_challenge.json | 112 ++
testVectors/gg20_zkp/phase6_challenge.txt | 100 ++
testVectors/gg20_zkp/phase6_commit.json | 82 ++
testVectors/gg20_zkp/phase6_commit.txt | 70 +
testVectors/gg20_zkp/phase6_prove.json | 102 ++
testVectors/gg20_zkp/phase6_prove.txt | 90 ++
testVectors/gg20_zkp/phase6_verify.json | 112 ++
testVectors/gg20_zkp/phase6_verify.txt | 100 ++
testVectors/schnorr/challenge.json | 90 +-
testVectors/schnorr/challenge.txt | 90 +-
testVectors/schnorr/dchallenge.json | 110 +-
testVectors/schnorr/dchallenge.txt | 110 +-
testVectors/schnorr/dprove.json | 140 +-
testVectors/schnorr/dprove.txt | 140 +-
testVectors/schnorr/dverify.json | 120 +-
testVectors/schnorr/dverify.txt | 120 +-
48 files changed, 8111 insertions(+), 503 deletions(-)
diff --git a/benchmark/bench_gg20_zkp_phase3.c b/benchmark/bench_gg20_zkp_phase3.c
new file mode 100644
index 0000000..e2387a9
--- /dev/null
+++ b/benchmark/bench_gg20_zkp_phase3.c
@@ -0,0 +1,162 @@
+/*
+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 GG20 Phase 3 ZKP
+ */
+
+#include "bench.h"
+#include "amcl/gg20_zkp.h"
+
+#define MIN_TIME 5.0
+#define MIN_ITERS 10
+
+char *S_hex = "00f1f45c44eb4298562677dfc945064ac5d45d683ec2d87efbd2f527bb5a768c";
+char *L_hex = "ab5aa1e7740f849b974fcaaa98840d828a42b16dd59be32f39e3c637730ee9e4";
+
+char *V_hex = "02879452f0c552b01c2cc91101062ca02a1ff3eab1e9c18873992670198bf54f3e";
+
+char *A_hex = "fab4ce512dff74bd9c71c89a14de5b877af45dca0329ee3fcb72611c0784fef3";
+char *B_hex = "803ccd21cddad626e15f21b1ad787949e9beef08e6e68a9e00df59dec16ed290";
+
+int main()
+{
+ int rc;
+
+ int iterations;
+ clock_t start;
+ double elapsed;
+
+ GG20_ZKP_rv r;
+ GG20_ZKP_proof p;
+
+ char id[32];
+ octet ID = {0, sizeof(id), id};
+
+ char ad[32];
+ octet AD = {0, sizeof(ad), ad};
+
+ char s[GGS_SECP256K1];
+ octet S = {0, sizeof(s), s};
+
+ char l[GGS_SECP256K1];
+ octet L = {0, sizeof(l), l};
+
+ char v[GFS_SECP256K1+1];
+ octet V = {0, sizeof(v), v};
+
+ char c[GFS_SECP256K1+1];
+ octet C = {0, sizeof(c), c};
+
+ char e[GGS_SECP256K1];
+ octet E = {0, sizeof(e), e};
+
+ char o[GGS_SECP256K1];
+ octet O = {0, sizeof(o), o};
+
+ // Deterministic RNG for testing
+ char seed[32] = {0};
+ csprng RNG;
+ RAND_seed(&RNG, 32, seed);
+
+ // Generate ID and AD
+ OCT_rand(&ID, &RNG, ID.len);
+ OCT_rand(&AD, &RNG, AD.len);
+
+ // Load hex values
+ OCT_fromHex(&S, S_hex);
+ OCT_fromHex(&L, L_hex);
+ OCT_fromHex(&V, V_hex);
+
+ OCT_fromHex(&O, A_hex);
+ BIG_256_56_fromBytesLen(r.a, O.val, O.len);
+
+ OCT_fromHex(&O, B_hex);
+ BIG_256_56_fromBytesLen(r.b, O.val, O.len);
+
+ // Begin benchmark
+ print_system_info();
+
+ printf("Timing info\n");
+ printf("===========\n");
+
+ iterations = 0;
+ start = clock();
+ do
+ {
+ GG20_ZKP_phase3_commit(NULL, &r, &C);
+ iterations++;
+ elapsed = (clock() - start) / (double)CLOCKS_PER_SEC;
+ }
+ while (elapsed < MIN_TIME || iterations < MIN_ITERS);
+
+ elapsed = MILLISECOND * elapsed / iterations;
+ printf("\tGG20_ZKP_phase3_commit\t\t%8d iterations\t", iterations);
+ printf("%8.2lf ms per iteration\n", elapsed);
+
+ iterations = 0;
+ start = clock();
+ do
+ {
+ GG20_ZKP_phase3_challenge(&V, &C, &ID, &AD, &E);
+ iterations++;
+ elapsed = (clock() - start) / (double)CLOCKS_PER_SEC;
+ }
+ while (elapsed < MIN_TIME || iterations < MIN_ITERS);
+
+ elapsed = MICROSECOND * elapsed / iterations;
+ printf("\tGG20_ZKP_phase3_challenge\t%8d iterations\t", iterations);
+ printf("%8.2lf us per iteration\n", elapsed);
+
+ iterations = 0;
+ start = clock();
+ do
+ {
+ GG20_ZKP_phase3_prove(&r, &E, &S, &L, &p);
+ iterations++;
+ elapsed = (clock() - start) / (double)CLOCKS_PER_SEC;
+ }
+ while (elapsed < MIN_TIME || iterations < MIN_ITERS);
+
+ elapsed = MICROSECOND * elapsed / iterations;
+ printf("\tGG20_ZKP_phase3_prove\t\t%8d iterations\t", iterations);
+ printf("%8.2lf us per iteration\n", elapsed);
+
+ iterations = 0;
+ start = clock();
+ do
+ {
+ rc = GG20_ZKP_phase3_verify(&V, &C, &E, &p);
+ iterations++;
+ elapsed = (clock() - start) / (double)CLOCKS_PER_SEC;
+ }
+ while (elapsed < MIN_TIME || iterations < MIN_ITERS);
+
+ if (rc != GG20_ZKP_OK)
+ {
+ printf("FAILURE GG20_ZKP_phase6_verify rc %d\n", rc);
+ exit(EXIT_FAILURE);
+ }
+
+ elapsed = MILLISECOND * elapsed / iterations;
+ printf("\tGG20_ZKP_phase3_verify\t\t%8d iterations\t", iterations);
+ printf("%8.2lf ms per iteration\n", elapsed);
+
+ exit(EXIT_SUCCESS);
+}
\ No newline at end of file
diff --git a/benchmark/bench_gg20_zkp_phase6.c b/benchmark/bench_gg20_zkp_phase6.c
new file mode 100644
index 0000000..6fa982b
--- /dev/null
+++ b/benchmark/bench_gg20_zkp_phase6.c
@@ -0,0 +1,177 @@
+/*
+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 GG20 Phase 6 ZKP
+ */
+
+#include "bench.h"
+#include "amcl/gg20_zkp.h"
+
+#define MIN_TIME 5.0
+#define MIN_ITERS 10
+
+char *S_hex = "843b282505357e075bd98104f42fe7ea6b41310da7c769b4c402442c1ede922b";
+char *L_hex = "584edf9db99551ff2e0d56218a44fea0943032f7864b8359c213ec36465512c5";
+
+char *ECPR_hex = "03e03cda61f087f9ba381695dc816a4ca42f38bbfc3fc88ffe897594b94ee7b80b";
+char *ECPT_hex = "02863528287942ab88dec016c2e1993bf9e459ffcbfcc48c25ef68f2ec750e55a8";
+char *ECPS_hex = "02ef03c8ecb7cf65b58d85f368c5fc2725b4e4fe93306f98cf53f8e1531cea2bc4";
+
+char *A_hex = "fab4ce512dff74bd9c71c89a14de5b877af45dca0329ee3fcb72611c0784fef3";
+char *B_hex = "803ccd21cddad626e15f21b1ad787949e9beef08e6e68a9e00df59dec16ed290";
+
+int main()
+{
+ int rc;
+
+ int iterations;
+ clock_t start;
+ double elapsed;
+
+ GG20_ZKP_rv r;
+ GG20_ZKP_phase6_commitment c;
+ GG20_ZKP_proof p;
+
+ char id[32];
+ octet ID = {0, sizeof(id), id};
+
+ char ad[32];
+ octet AD = {0, sizeof(ad), ad};
+
+ char s[GGS_SECP256K1];
+ octet S = {0, sizeof(s), s};
+
+ char l[GGS_SECP256K1];
+ octet L = {0, sizeof(l), l};
+
+ char ecpr[GFS_SECP256K1+1];
+ octet ECPR = {0, sizeof(ecpr), ecpr};
+
+ char ecpt[GFS_SECP256K1+1];
+ octet ECPT = {0, sizeof(ecpt), ecpt};
+
+ char ecps[GFS_SECP256K1+1];
+ octet ECPS = {0, sizeof(ecps), ecps};
+
+ char e[GGS_SECP256K1];
+ octet E = {0, sizeof(e), e};
+
+ char o[GGS_SECP256K1];
+ octet O = {0, sizeof(o), o};
+
+ // Deterministic RNG for testing
+ char seed[32] = {0};
+ csprng RNG;
+ RAND_seed(&RNG, 32, seed);
+
+ // Generate ID and AD
+ OCT_rand(&ID, &RNG, ID.len);
+ OCT_rand(&AD, &RNG, AD.len);
+
+ // Load hex values
+ OCT_fromHex(&S, S_hex);
+ OCT_fromHex(&L, L_hex);
+
+ OCT_fromHex(&ECPR, ECPR_hex);
+ OCT_fromHex(&ECPT, ECPT_hex);
+ OCT_fromHex(&ECPS, ECPS_hex);
+
+ OCT_fromHex(&O, A_hex);
+ BIG_256_56_fromBytesLen(r.a, O.val, O.len);
+
+ OCT_fromHex(&O, B_hex);
+ BIG_256_56_fromBytesLen(r.b, O.val, O.len);
+
+ // Begin benchmark
+ print_system_info();
+
+ printf("Timing info\n");
+ printf("===========\n");
+
+ iterations = 0;
+ start = clock();
+ do
+ {
+ rc = GG20_ZKP_phase6_commit(NULL, &ECPR, &r, &c);
+ iterations++;
+ elapsed = (clock() - start) / (double)CLOCKS_PER_SEC;
+ }
+ while (elapsed < MIN_TIME || iterations < MIN_ITERS);
+
+ if (rc != GG20_ZKP_OK)
+ {
+ printf("FAILURE GG20_ZKP_phase6_commit rc %d\n", rc);
+ exit(EXIT_FAILURE);
+ }
+
+ elapsed = MILLISECOND * elapsed / iterations;
+ printf("\tGG20_ZKP_phase6_commit\t\t%8d iterations\t", iterations);
+ printf("%8.2lf ms per iteration\n", elapsed);
+
+ iterations = 0;
+ start = clock();
+ do
+ {
+ GG20_ZKP_phase6_challenge(&ECPR, &ECPT, &ECPS, &c, &ID, &AD, &E);
+ iterations++;
+ elapsed = (clock() - start) / (double)CLOCKS_PER_SEC;
+ }
+ while (elapsed < MIN_TIME || iterations < MIN_ITERS);
+
+ elapsed = MICROSECOND * elapsed / iterations;
+ printf("\tGG20_ZKP_phase6_challenge\t%8d iterations\t", iterations);
+ printf("%8.2lf us per iteration\n", elapsed);
+
+ iterations = 0;
+ start = clock();
+ do
+ {
+ GG20_ZKP_phase6_prove(&r, &E, &S, &L, &p);
+ iterations++;
+ elapsed = (clock() - start) / (double)CLOCKS_PER_SEC;
+ }
+ while (elapsed < MIN_TIME || iterations < MIN_ITERS);
+
+ elapsed = MICROSECOND * elapsed / iterations;
+ printf("\tGG20_ZKP_phase6_prove\t\t%8d iterations\t", iterations);
+ printf("%8.2lf us per iteration\n", elapsed);
+
+ iterations = 0;
+ start = clock();
+ do
+ {
+ rc = GG20_ZKP_phase6_verify(&ECPR, &ECPT, &ECPS, &c, &E, &p);
+ iterations++;
+ elapsed = (clock() - start) / (double)CLOCKS_PER_SEC;
+ }
+ while (elapsed < MIN_TIME || iterations < MIN_ITERS);
+
+ if (rc != GG20_ZKP_OK)
+ {
+ printf("FAILURE GG20_ZKP_phase6_verify rc %d\n", rc);
+ exit(EXIT_FAILURE);
+ }
+
+ elapsed = MILLISECOND * elapsed / iterations;
+ printf("\tGG20_ZKP_phase6_verify\t\t%8d iterations\t", iterations);
+ printf("%8.2lf ms per iteration\n", elapsed);
+
+ exit(EXIT_SUCCESS);
+}
\ No newline at end of file
diff --git a/benchmark/bench_modulus.c b/benchmark/bench_modulus.c
new file mode 100644
index 0000000..42f2c26
--- /dev/null
+++ b/benchmark/bench_modulus.c
@@ -0,0 +1,100 @@
+/*
+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 modulus utilities.
+ */
+
+#include "bench.h"
+#include "amcl/modulus.h"
+
+#define MIN_TIME 5.0
+#define MIN_ITERS 10
+
+char *P_hex = "e008507e09c24d756280f3d94912fb9ac16c0a8a1757ee01a350736acfc7f65880f87eca55d6680253383fc546d03fd9ebab7d8fa746455180888cb7c17edf58d3327296468e5ab736374bc9a0fa02606ed5d3a4a5fb1677891f87fbf3c655c3e0549a86b17b7ddce07c8f73e253105e59f5d3ed2c7ba5bdf8495df40ae71a7f";
+char *Q_hex = "dbffe278edd44c2655714e5a4cc82e66e46063f9ab69df9d0ed20eb3d7f2d8c7d985df71c28707f32b961d160ca938e9cf909cd77c4f8c630aec34b67714cbfd4942d7147c509db131bc2d6a667eb30df146f64b710f8f5247848b0a75738a38772e31014fd63f0b769209928d586499616dcc90700b393156e12eea7e15a835";
+
+int main()
+{
+ int iterations;
+ clock_t start;
+ double elapsed;
+
+ char p[HFS_2048] = {0};
+ octet P = {0, sizeof(p), p};
+
+ char q[HFS_2048];
+ octet Q = {0, sizeof(q), q};
+
+ MODULUS_priv m;
+
+ // Load values
+ OCT_fromHex(&P, P_hex);
+ OCT_fromHex(&Q, Q_hex);
+
+ print_system_info();
+
+ printf("Timing info\n");
+ printf("===========\n");
+
+ iterations = 0;
+ start = clock();
+ do
+ {
+ MODULUS_fromOctets(&m, &P, &Q);
+ iterations++;
+ elapsed = (clock() - start) / (double)CLOCKS_PER_SEC;
+ }
+ while (elapsed < MIN_TIME || iterations < MIN_ITERS);
+
+ elapsed = MICROSECOND * elapsed / iterations;
+ printf("\tMODULUS_fromOctets\t%8d iterations\t", iterations);
+ printf("%8.2lf us per iteration\n", elapsed);
+
+ iterations = 0;
+ start = clock();
+ do
+ {
+ MODULUS_toOctets(&P, &Q, &m);
+ iterations++;
+ elapsed = (clock() - start) / (double)CLOCKS_PER_SEC;
+ }
+ while (elapsed < MIN_TIME || iterations < MIN_ITERS);
+
+ elapsed = MICROSECOND * elapsed / iterations;
+ printf("\tMODULUS_toOctets\t%8d iterations\t", iterations);
+ printf("%8.2lf us per iteration\n", elapsed);
+
+
+ iterations = 0;
+ start = clock();
+ do
+ {
+ MODULUS_kill(&m);
+ iterations++;
+ elapsed = (clock() - start) / (double)CLOCKS_PER_SEC;
+ }
+ while (elapsed < MIN_TIME || iterations < MIN_ITERS);
+
+ elapsed = MICROSECOND * elapsed / iterations;
+ printf("\tMODULUS_kill\t\t%8d iterations\t", iterations);
+ printf("%8.2lf us per iteration\n", elapsed);
+
+ exit(EXIT_SUCCESS);
+}
diff --git a/benchmark/bench_shamir.c b/benchmark/bench_shamir.c
new file mode 100644
index 0000000..09cfd71
--- /dev/null
+++ b/benchmark/bench_shamir.c
@@ -0,0 +1,175 @@
+/*
+ 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 Shamir Secret Sharing
+ */
+
+#include "bench.h"
+#include "amcl/shamir.h"
+
+#define MIN_TIME 5.0
+#define MIN_ITERS 10
+
+char *S_hex = "fab4ce512dff74bd9c71c89a14de5b877af45dca0329ee3fcb72611c0784fef3";
+
+int n = 30;
+int k = 20;
+
+int main()
+{
+ int i, rc;
+
+ int iterations;
+ clock_t start;
+ double elapsed;
+
+ // Secret
+ char s[SGS_SECP256K1];
+ octet S = {0,sizeof(s),s};
+
+ // Secret shares
+ char x[n][SGS_SECP256K1];
+ octet X[n];
+ char y[n][SGS_SECP256K1];
+ octet Y[n];
+
+ for(i = 0; i < n; i++)
+ {
+ Y[i].max = SGS_SECP256K1;
+ Y[i].len = SGS_SECP256K1;
+ Y[i].val = y[i];
+
+ X[i].max = SGS_SECP256K1;
+ X[i].len = SGS_SECP256K1;
+ X[i].val = x[i];
+ }
+
+ SSS_shares shares = {X, Y};
+
+ // Additive share for conversion
+ char sh[SGS_SECP256K1];
+ octet SH = {0, sizeof(sh), sh};
+
+ // Additional checks for verification
+ char c[k][1 + SFS_SECP256K1];
+ octet C[k];
+
+ for(i = 0; i < k; i++)
+ {
+ C[i].max = 1 + SFS_SECP256K1;
+ C[i].len = 1 + SFS_SECP256K1;
+ C[i].val = c[i];
+ }
+
+ // Deterministic RNG for testing
+ char seed[32] = {0};
+ csprng RNG;
+ RAND_seed(&RNG, 32, seed);
+
+ // Load Secret from hex
+ OCT_fromHex(&S, S_hex);
+
+ /* Benchmark */
+ print_system_info();
+
+ printf("Timing info\n");
+ printf("===========\n");
+
+ // Shamir Secret Sharing
+ iterations=0;
+ start=clock();
+ do
+ {
+ SSS_make_shares(k, n, &RNG, &shares, &S);
+ iterations++;
+ elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+ }
+ while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+
+ elapsed= MILLISECOND * elapsed / iterations;
+ printf("\tSSS_make_shares\t\t%8d iterations\t",iterations);
+ printf("%8.2lf ms per iteration\n",elapsed);
+
+ iterations=0;
+ start=clock();
+ do
+ {
+ SSS_recover_secret(k, &shares, &S);
+ iterations++;
+ elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+ }
+ while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+
+ elapsed= MILLISECOND * elapsed / iterations;
+ printf("\tSSS_recover_secret\t%8d iterations\t",iterations);
+ printf("%8.2lf ms per iteration\n",elapsed);
+
+ // Shamir to additive conversion
+ iterations=0;
+ start=clock();
+ do
+ {
+ SSS_shamir_to_additive(k, X, Y, X+1, &SH);
+ iterations++;
+ elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+ }
+ while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+
+ elapsed= MICROSECOND * elapsed / iterations;
+ printf("\tSSS_shamir_to_additive\t%8d iterations\t",iterations);
+ printf("%8.2lf us per iteration\n",elapsed);
+
+ // Verifiable Secret Sharing
+ iterations=0;
+ start=clock();
+ do
+ {
+ VSS_make_shares(k, n, &RNG, &shares, C, &S);
+ iterations++;
+ elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+ }
+ while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+
+ elapsed= MILLISECOND * elapsed / iterations;
+ printf("\tVSS_make_shares\t\t%8d iterations\t",iterations);
+ printf("%8.2lf ms per iteration\n",elapsed);
+
+ iterations=0;
+ start=clock();
+ do
+ {
+ rc = VSS_verify_shares(k, X, Y, C);
+ iterations++;
+ elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
+ }
+ while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+
+ if (rc != VSS_OK)
+ {
+ printf("FAILURE VSS_verify_shares: %d\n", rc);
+ exit(EXIT_FAILURE);
+ }
+
+ elapsed= MILLISECOND * elapsed / iterations;
+ printf("\tVSS_verify_shares\t%8d iterations\t",iterations);
+ printf("%8.2lf ms per iteration\n",elapsed);
+
+ exit(EXIT_SUCCESS);
+}
diff --git a/examples/example_gg20_full.c b/examples/example_gg20_full.c
new file mode 100644
index 0000000..e8608e0
--- /dev/null
+++ b/examples/example_gg20_full.c
@@ -0,0 +1,2056 @@
+/*
+ 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 <stdlib.h>
+#include <string.h>
+#include "amcl/mta.h"
+#include "amcl/mpc.h"
+#include "amcl/mta_zkp.h"
+#include "amcl/nm_commitment.h"
+#include "amcl/gmr.h"
+#include "amcl/ggn.h"
+#include "amcl/schnorr.h"
+#include "amcl/gg20_zkp.h"
+#include "amcl/shamir.h"
+
+#define IDLEN 16
+
+/* Example of the full flow */
+
+// Safe primes for BC Setup
+int primes_len = 4;
+
+char *primes[] =
+{
+ "C421122418EF6FE4D4F14F0F03EABA927C20B1A22BCBE90EC227EFE34AC912095D389ADE615CF55C80874533F4270BB705ABFFDB6007FEF0B44B2DBF31EDA0D5F39523B5826F9854FBF733B98EF450E77DD8B5B15C4E3CE5C195F46E524C8BF6F0C9F6D86CE8642A8B9A0C79CA64A103AB76CD65261F97AED4C17C433CEA5DEF",
+ "ED7859031659B9A5AC011687A60444B19F5A73F31F9EE83D710F2FEAE1C4FED558A1C5C3842EA01DB86C6D07BE9971F8AA7820DD1E8BB8C9AE888319F0E03BDCD8D3DBEBF8A48765188C001A121F7E48D458E1E8A43684A861F0FBE87DC541A06CA98CECB6954F906A52C2B3D0978AE945A1EA2F9285978F76F01E99FD8B6EEF",
+ "D93E4899805ED36219F38C3030D6FF92012E2B41ADC38DFFFFDB110AEAA36D619A5CFD63B02711EA482941E20A3F89A36E2CAF0BD675B154FDE6D5A457BCBD337383EE65B33CDAB078EE8F8E36E55D22BB5DF75D14F570E529A4681B4947A4F5ECCC575763BD765FDE1038DEDF24BEF02BA9A1EA4C17ACA3A1B33D2FB7D974AB",
+ "E4481CEDDBDDDF6E980FBC825B004E52D028784CD3B8290D9810FD987AF2053C3F4056C3A354BFF55B9BB5867A819A22B71BC1069A310087E4FBF98FD291DBCC443AB910301B34A2DEE68D1365E77EDF9A0A21B3928C38046BC15AC338F7E38B9E4586E02655F98523CD041FBB51A358E505A5D1B0A161955B6AC60CB0E37707",
+ "F5F3BB1CEECD21110EFB4BC9CF0AA7AEBB98675A7567D6A1EA4E866FED4838F1B41D8232599718CD82F2936CD15198DC16ADD280C32D6860882704AEF397E1A956DB17E36AEB92D5CF76689DACC9CEFE418EF699C948CE680AFF878768CE8F4BB68F14AB5E8C38209E6C2C54125533B22960BBD350CF76C3B12BBC9FBAAAAA27",
+ "E8E1F9281CB8C10BC01B42197E834F648A5C8AE111F7DB40DD25A6F8896A703D0F84D36EB6D1FC048DC74FD3164742CA86607C81670199FC3F1BF5AB22F2B11E4E2434E757C0484A4162E26B75A0715167C5E8E293B7CEFD475FAA8B10F2324D78150E56B1186E257066D8860603FBCE59865FB0A25FB41014C1740C8EAA29AF",
+ "C3278DF1CD5330CD6DABE2FC9E32B9A560C32F7F140C601D2A5788F856A387531EFA695D728038F8CA2945D01C10A5DA823025BA27D7640E96593C031674380592AF4B8FE29A9C464FF41B1CACD47A4B255A5CA93E2F2A806AF00A67FB78A15D3ED8A37CEBA10CA7D0036412805AEBB88EC8A745F237AC01002D49C459EB2AB7",
+ "DCE9B24D4DE749296335C0F0DB421A330E21DF04C722ADDECC4B72448C387072C84CD7DB1146E1E07BE78585DEF4F1D5E15F53B0942CCA89B0E812B0F6653C7DA8ACB771593D4B2B37A28AD80DD7184698742C110F0506B86BF8A2A20E8975DF2D2A57930438B8528E63C3430DBFCE204712E8D40550E81DA03622953BEA2DFB",
+ "D09A3ECE562DD033EC2C562C2B0B4EEB0D2262FE046C030BAAFD7CBA8F73E9734E337D3551FC6B487CA359A84F598EC5EC6FDBA014A0A0009EF582B9F90DE90C0BA7F941648C4F3A8CF904974BA05E8C23EDA5895025441251B2CFC5A216568E702427DEA178D37BF3D28F1B35E17E58F5551511331961703F3D410924859107",
+ "C03136A1E1E5BA88568A19142F41E9FAC2E76A2D839B550038005E420008AF7D6D7C80EA8A31A936D39C93D2031B20845F23464371909EE589BF80E850C94B9F0FBF516C3DE362868C811505EE15B869844A54FFB32B0620A7FC5BA040898A91AA68657D8B43990166E5A5AF06828AE0F7C1D0EE333C2AF8DE7603F2F662792F",
+ "DF88593FBF2482954BAAA2A48C59E2FDF85936C282514FFB47F18B8D1484C7E8BE1862D0A84D5B753389A2BFBAFF63B03406AC29893B88911F8664E547A63CB58E9A941463D7946CF0909E24E7BD8EF11AFC4EEAFC8F3366DB0A9AB091325AC82C9BAE218B115F8700BAA1F478E194A927F1FBE3A3EF423BCFAE78850059B69B",
+ "D3AE06CD993690F64104D4ECBE6B2386693B766431B86E038CAE39EE81BD8A71387FBCB9D17B5BFAAFB883D68B005E228CD455A4BFF69843F948A9168D1F87545FCBB969260E07BDD44F10E79E7409DED45ADDF32BA1CF33F9B2F68758622FE660F4E47A651F6403D99E7B148768CDDBEC71EBE931D5A95B820B5A75BD495003",
+ "DAA27689A7D8F9B21106DBE472C324EB1CA899F58F0F72F336957312A8ECDB4EBC3B50C38D5A2E9C2D1E552C7EA8D89315DD9C5CA7F9EB99C41F7A857D44F420109FE17092799E60E3537FC9193056979E0FF886B36C2898F45F599E4C5CCDDF9A8EC8DA0D20A53A6849124E027D30D641E21E69FF374792534BD682FCDCA35B",
+ "FBF9D46697C40BCA51A759C47E360F2DD8B81B6241B0A3645645FAC692E9E8F3407EFB6F238AE91F9DEA49240D26E37904673F55E91927CDEA248FE1352B97B226AB159A1539747383B1168FE8CF1B1DF4CD9147053E3702AE491FBCA4CCE835B4B351DF44F5333C185275DB21B807D0BC180BF697EC07AB843E0FA595851A87",
+ "FD44B39DF09A18F215EB391D50D21CD5EAC8BE2E5CC901DF852DE85C93341F82633AAAD07C19863E0CD7861AEEE1C0B4B69275AA8DD2D33C0F5E048EA13E9A6D8E01B77FED72347D527BD7508D2F5EC18E5CB2B27D40BAB5C10A17123E75042F4047C3B1AEB6D36BF0F93BB214501ECBB8F95CC1A3A99219F6933763580CDA2F",
+ "C2442E9569C8999831594E818A159C8C0AF6F7ED2989358E8D9E01D6B8A0D354F5F97D9CEAB766AF12F3CC5C511FE19A587FF1E7029C8E500432D357D90E3EF042E4F308C325760D726BC9B1D78BA439FB0236D85DB301E548C4201B9E74D5832AD3ED06E37CD6DBFD9C23D194068DB1B9209813557FBC0714142AD6F6C56AA3",
+ "DC3B22CFF90690B10EC73C115FED0E3AD3FA01A68F8C8AA1905CA47008E8C4AF9D7922AE4D41794D8123D1768A3E0F8B35DA0001086ADC5EBB92640DD2514CBAD000283F7C5A6C340C040C09654A204C3947A22AC05F72E13C3EBDE61B9D281016E40C559474D33381C974767408EE9E108619AE96E4CC87EB11E39772BA00B3",
+ "C5E0280A5F1B358D16EDEF14540C3C9D468D4AEBC74C9DB605A2E4CEC9F27095A3FDE659E1E6C95FB4BB60533DD89E71D808A8C5EB5A8A51B9FED24F7AE9003FFD6F5401D991153C52002E7DB4F6766363B2CA77E9A113808E7C35713D188AD55CE25B9DB1308A08F3366523E425F77D924346078D8E0E9948674BAD88EA59B7",
+ "FC33DF361A7B1D3C3D1C06FBF3CCAD6C067B27FF28B61B1EFDB364FFFEE79993D9D10213A778A02C6C823DB101CB7C7A483B9F2B060BD1B7EDC13DB890B323AE02B7209DA66B3289069EE8C7747A6D7242194DC48DBDFFB740534A591AE2F41446B08F9966DA045FC9C3F9188F1EF1308509D50BC970314B6AA335EA2839993B",
+ "E63B5740DDB573CF1F0A72DAF3EA00D65CA2A538036D20078CC7E3BDC95529F1D13ABC182EBF8BE42CA87C0AEED4952C1D1FADC3C3C8A363F66FABCA012890FBC76C935B479B4F302F1DC12289D34F1F69EC2278045603F5FE532B0CD86E6261852F99517B6226F013B04DCE1D940DF7FB8BC8A799D153C1490A915A8342B77F"
+};
+
+/* Party related structures */
+typedef struct
+{
+ PAILLIER_private_key paillier_sk;
+ BIT_COMMITMENT_priv bc_sm;
+
+ octet *SKX; // X share of the full key (t,n) sharing
+ octet *SKY; // Y share of the full key (t,n) sharing
+} MPC_priv_key_material;
+
+typedef struct
+{
+ octet *PK; // Full ECDSA PK
+ octet *SPK; // ECDSA PK associated to the player share
+
+ PAILLIER_public_key paillier_pk;
+ BIT_COMMITMENT_pub bc_pm;
+} MPC_pub_key_material;
+
+typedef struct
+{
+ octet *ID;
+
+ MPC_priv_key_material skm;
+ MPC_pub_key_material pkm;
+} MPC_player;
+
+typedef struct
+{
+ int t;
+ int n;
+
+ MPC_player *players;
+} MPC_party;
+
+/* Keygen related structures
+ *
+ * Note that these structures hold all the values
+ * generated in the round, even if they are not to be
+ * transmitted. The values to be transmitted and what channel
+ * to use are specified in the keygen functions
+ */
+
+typedef struct
+{
+ octet *SK; // ECDSA secret key
+ octet *PK; // ECDSA pubilc key
+
+ octet *R; // Decommitment string
+ octet *C; // Commitment string to PK
+} MPC_keygen_round1;
+
+typedef struct
+{
+ SSS_shares SHARES; // Shares for VSS
+ octet *CHECKS; // Checks for VSS
+} MPC_keygen_round2;
+
+typedef struct
+{
+ octet *SCHNORR_C;
+ octet *SCHNORR_P;
+
+ GMR_proof Y;
+
+ BIT_COMMITMENT_setup_proof BCP;
+} MPC_keygen_round3;
+
+typedef struct
+{
+ octet *ID;
+
+ MPC_party *party;
+
+ MPC_keygen_round1 *round1;
+ MPC_keygen_round2 *round2;
+ MPC_keygen_round3 *round3;
+} MPC_keygen_session;
+
+/* Signing related structures
+ *
+ * Note that these structures hold all the values
+ * generated in the round, even if they are not to be
+ * transmitted. The values to be transmitted and what channel
+ * to use are specified in the signing functions
+ */
+
+typedef struct
+{
+ octet *W; // Secret additive share
+ octet *WG; // Public Key associated with the additive share
+} MPC_signing_additive_shares;
+
+typedef struct
+{
+ octet *GAMMA;
+ octet *GAMMAPT;
+ octet *K;
+ octet *R; // Decommitment for GAMMAPT
+ octet *C; // Commitment for GAMMAPT
+} MPC_signing_round1;
+
+typedef struct
+{
+ octet *R; // Random value from K encryption. Saved for round 5
+ octet *CA; // Encryption of K. Saved for round 5
+ octet *DELTA;
+ octet *SIGMA;
+} MPC_signing_round2;
+
+typedef struct
+{
+ octet *INVKGAMMA;
+ octet *T; // Check for SIGMA
+ octet *L; // Random value used in computing T
+ octet *C; // Phase3 commitment. ECP
+ GG20_ZKP_proof p;
+} MPC_signing_round3;
+
+typedef struct
+{
+ octet *R;
+ octet *RP;
+} MPC_signing_round4;
+
+typedef struct
+{
+ octet *RI; // Checks for K, R
+ GGN_commitment *c; // t commitments, since they are tailored for each player
+ GGN_proof *p; // t proofs, since they are tailored for each player
+} MPC_signing_round5;
+
+typedef struct
+{
+ octet *SI; // Check for SIGMAs
+ GG20_ZKP_phase6_commitment c; // Commitment for SI consistency
+ GG20_ZKP_proof p; // Proof for SI consistency
+} MPC_signing_round6;
+
+typedef struct
+{
+ octet *SI; // Signature S shares
+ octet *S; // Reconciled S component
+} MPC_signing_round7;
+
+typedef struct
+{
+ octet *ID;
+
+ MPC_party *party;
+
+ MPC_signing_additive_shares *shares;
+
+ MPC_signing_round1 *round1;
+ MPC_signing_round2 *round2;
+ MPC_signing_round3 *round3;
+ MPC_signing_round4 *round4;
+ MPC_signing_round5 *round5;
+ MPC_signing_round6 *round6;
+ MPC_signing_round7 *round7;
+} MPC_signing_session;
+
+// Utility functions
+void init_octets(char* mem, octet *OCTETS, int max, int n)
+{
+ int i = 0;
+
+ for (i = 0; i < n; i++)
+ {
+ OCTETS[i].val = mem + (i*max);
+ OCTETS[i].len = 0;
+ OCTETS[i].max = max;
+ }
+}
+
+/* *** Keygen functions *** */
+
+/* Keygen - Round 1
+ *
+ * This can be viewed as the secret key material generation.
+ * In particular, we generate keypairs for the ECDSA Signature
+ * and the Paillier cryptosystem, in addition to the modulus
+ * for the Bit Commitment ZKP.
+ *
+ * The ECDSA Public Key is not broadcast here, but a NM Commitment
+ * to it is generated and the commitment string broadcast here.
+ * The decommitment string MUST be saved for later.
+ *
+ * The rest of the (public) key material is broadcast as is.
+ * The reason for broadcasting the Paillier Key here is the specification
+ * in the paper. The moment to broadcast the modulus is not
+ * specified, so there is a case to be done for broadcasting it
+ * in round 3.
+ */
+int MPC_keygen_round1_generate(csprng *RNG, MPC_player *p, MPC_keygen_round1 *r, int i)
+{
+ int rc;
+
+ char oct1[HFS_2048];
+ octet OCT1 = {0, sizeof(oct1), oct1};
+ char oct2[HFS_2048];
+ octet OCT2 = {0, sizeof(oct2), oct2};
+
+ ECP_SECP256K1 ECP;
+
+ char pk[2 * EFS_SECP256K1 + 1];
+ octet PK = {0, sizeof(pk), pk};
+
+ // Generate ECDSA Key Pair
+ printf("\t[Player %d] Generate ECDSA key pair\n", i);
+
+ MPC_ECDSA_KEY_PAIR_GENERATE(RNG, r->SK, &PK);
+ rc = ECP_SECP256K1_PUBLIC_KEY_VALIDATE(&PK);
+ if (rc != 0)
+ {
+ printf("\t\tError generating ECDSA key pair. rc %d\n", rc);
+ return rc;
+ }
+
+ // Convert PK to compressed form
+ ECP_SECP256K1_fromOctet(&ECP, &PK);
+ ECP_SECP256K1_toOctet(r->PK, &ECP, true);
+
+ // Commit to the ECDSA public key
+ printf("\t[Player %d] Commit to ECDSA PK\n", i);
+
+ NM_COMMITMENT_commit(RNG, &PK, r->R, r->C);
+
+ // Generate Paillier Key pair
+ printf("\t[Player %d] Generate Paillier key pair\n", i);
+
+ PAILLIER_KEY_PAIR(RNG, NULL, NULL, &p->pkm.paillier_pk, &p->skm.paillier_sk);
+
+ // Load Primes for BC setup
+ OCT_fromHex(&OCT1, primes[(2 * i) % primes_len]);
+ OCT_fromHex(&OCT2, primes[(2 * i + 1) % primes_len]);
+
+ // Generate BC modulus
+ printf("\t[Player %d] Generate BC modulus\n", i);
+
+ BIT_COMMITMENT_setup(RNG, &p->skm.bc_sm, &OCT1, &OCT2, NULL, NULL);
+ BIT_COMMITMENT_priv_to_pub(&p->pkm.bc_pm, &p->skm.bc_sm);
+
+ printf("\t[Player %d] Broadcast commitment C, Paillier PK and BC modulus (N, B0, B1)\n", i);
+
+ return MPC_OK;
+}
+
+/* Keygen - VSS of ECDSA SK for Round 2
+ *
+ * The output of this computation are the shares and checks for this playe
+ * ECDSA secret key. Note that the check for the coefficient
+ * of degree 0 is the ECDSA PK generated in Round 1. So it
+ * will pass the decommitment for the commitment sent in Round 1
+ *
+ * This part of computation can be performed as soon as the ECDSA
+ * keypair from Round 1 is done. There is a case to be done
+ * for moving this in the body of Round 1, given how inexpensive it
+ * is, but I'm separating it to better reflect the paper.
+ * Either way, the shares and decommitment for the free term in the exponent
+ * MUST NOT be broadcast until every other player broadcasts the
+ * result of its Round 1
+ */
+void MPC_keygen_round2_vss(csprng *RNG, MPC_keygen_round1 *r1, MPC_keygen_round2 *r2, int i, int t, int n)
+{
+ printf("\t[Player %d] Generate VSS Shares for secret key\n", i);
+
+ VSS_make_shares(t, n, RNG, &r2->SHARES, r2->CHECKS, r1->SK);
+
+ printf("\t[Player %d] Broadcast Checks and decommitment string.\n", i);
+ printf("\t[Player %d] Transmit shares with point2point channel\n", i);
+}
+
+/* Keygen - VSS verification and shares composition for Round 2
+ *
+ * Once the shares and decommitments are received they can be
+ * verified and summed to compute the full key share for the player.
+ * Moreover, the full public key can be computed by adding all the
+ * free terms in the exponents from the checks.
+ *
+ * Note that it would be beneficial to have a routine to verify
+ * shares and the decommitment of the free term in the exponent
+ * so they can be processed as they are received, instead of processing
+ * them in bulk. Here it is done in bulk for simplicity.
+ */
+int MPC_keygen_round2_compose(MPC_keygen_session *s, int i)
+{
+ int j, n, rc;
+
+ n = s->party->n;
+
+ char ws[n][EFS_SECP256K1 + 1];
+ octet WS[n];
+
+ init_octets((char *)ws, WS, EFS_SECP256K1 + 1, n);
+
+ SSS_shares *SHARES;
+ octet *CHECKS;
+ MPC_player *p;
+
+ printf("\t[Player %d] Verify Shares\n", i);
+
+ /* Decommit Free term in the exponent and verify shares */
+ for (j = 0; j < n; j++)
+ {
+ if (i == j) continue; // Trust ourselves
+
+ // Load appropriate shares and checks
+ SHARES = &(s->round2[j].SHARES);
+ CHECKS = s->round2[j].CHECKS;
+
+ // Decommit free term in the exponent
+ rc = NM_COMMITMENT_decommit(CHECKS + 0, (s->round1)[j].R, (s->round1)[j].C);
+ if (rc != NM_COMMITMENT_OK)
+ {
+ printf("\t\tInvalid Commitment for Player %d. rc %d\n", j, rc);
+ return rc;
+ }
+
+ // Check the share is for the right player
+ if (!OCT_comp(SHARES->X+i, s->round2[i].SHARES.X+i))
+ {
+ printf("\t\tInvalid X share for Player %d.\n", j);
+ return MPC_FAIL;
+ }
+
+ // VSS Verification for the received share
+ rc = VSS_verify_shares(s->party->t, SHARES->X+i, SHARES->Y+i, CHECKS);
+ if (rc != VSS_OK)
+ {
+ printf("\t\tInvalid Shares for Player %d. rc %d\n", j, rc);
+ return rc;
+ }
+ }
+
+ /* Compose Public Key */
+
+ printf("\t[Player %d] Generate full PK\n", i);
+
+ p = s->party->players + i;
+
+ for (j = 0; j < n; j++)
+ {
+ OCT_copy(WS+j, s->round2[j].CHECKS + 0);
+ }
+
+ rc = MPC_SUM_ECPS(p->pkm.PK, WS, n);
+ if (rc != MPC_OK)
+ {
+ printf("\t\tInvalid format for PK Shares for Player %d. rc %d\n", i, rc);
+ return rc;
+ }
+
+ /* Compose Shares */
+
+ printf("\t[Player %d] Combine full share\n", i);
+
+ for (j = 0; j < n; j++)
+ {
+ OCT_copy(WS+j, s->round2[j].SHARES.Y + i);
+ }
+
+ MPC_SUM_BIGS(p->skm.SKY, WS, n);
+
+ OCT_copy(p->skm.SKX, s->round2[i].SHARES.X+i);
+
+ /* TODO This should not be stored here
+ *
+ * This should be computed by each player for all players
+ */
+ BIG_256_56 w;
+ ECP_SECP256K1 G;
+ ECP_SECP256K1_generator(&G);
+ BIG_256_56_fromBytesLen(w, p->skm.SKY->val, p->skm.SKY->len);
+ ECP_SECP256K1_mul(&G, w);
+ ECP_SECP256K1_toOctet(p->pkm.SPK, &G, true);
+
+ return MPC_OK;
+}
+
+/* Keygen - Generate Proofs of well formedness of the key material
+ *
+ * Generate a Schnorr Proof of knowledge of the secret share
+ * Generate a Square-Freeness proof for the Paillier Keys
+ * Generate a proof of well formedness for the ZKP modulus N, b0, b1
+ *
+ * The Schnorr Proof is performed here as specified in the paper,
+ * but it is inexpensive enough that it could be moved in round 1 and
+ * verified in round 2 to fail early. As for the other two proofs,
+ * they are quite slow and it is a good idea to have them performed
+ * as the last step.
+ */
+void MPC_keygen_round3_proofs(csprng *RNG, MPC_player *p, MPC_keygen_round3 *r3, octet *SESSION_ID, int i)
+{
+ char rv[EGS_SECP256K1];
+ octet RV = {0, sizeof(rv), rv};
+ char e[EGS_SECP256K1];
+ octet E = {0, sizeof(e), e};
+
+ char mp[HFS_2048];
+ octet MP = {0, sizeof(mp), mp};
+ char mq[HFS_2048];
+ octet MQ = {0, sizeof(mq), mq};
+
+ MODULUS_priv m;
+
+ /* Prove knowledge of DLOG PK = s.G */
+ printf("\t[Player %d] Prove knowledge of secret key\n", i);
+
+ SCHNORR_commit(RNG, &RV, r3->SCHNORR_C);
+ SCHNORR_challenge(p->pkm.SPK, r3->SCHNORR_C, p->ID, SESSION_ID, &E);
+ SCHNORR_prove(&RV, &E, p->skm.SKY, r3->SCHNORR_P);
+
+ OCT_clear(&RV);
+
+ /* Prove Square Freeness of the Paillier modulus */
+ printf("\t[Player %d] Prove Square-Freeness of Paillier modulus\n", i);
+
+ FF_2048_toOctet(&MP, p->skm.paillier_sk.p, HFLEN_2048);
+ FF_2048_toOctet(&MQ, p->skm.paillier_sk.q, HFLEN_2048);
+ MODULUS_fromOctets(&m, &MP, &MQ);
+
+ GMR_prove(&m, p->ID, SESSION_ID, r3->Y);
+
+ OCT_clear(&MP);
+ OCT_clear(&MQ);
+ MODULUS_kill(&m);
+
+ /* Prove well formedness of the BC modulus */
+ printf("\t[Player %d] Prove Well formedness of BC modulus\n", i);
+
+ BIT_COMMITMENT_setup_prove(RNG, &p->skm.bc_sm, &r3->BCP, p->ID, SESSION_ID);
+
+ printf("\t[Player %d] Broadcast Schnorr Proof (C, P), GMR Proof Y and BC proof values\n", i);
+}
+
+/* Keygen - Verify the ZKP for round 3
+ *
+ * Verify the Schnorr Proof for the secret key u
+ * Verify the Square-Freeness proof for the paillier PK
+ * Verify the proof of well formedness for the BC modulus
+ *
+ * This is done in bulk here for simplicity, but as for Round 2
+ * there is a strong case to be made to have a routine to perform
+ * this asyncronously as soon as the proofs come in from the other
+ * players.
+ */
+int MPC_keygen_round3_verify(MPC_keygen_session *s, int i)
+{
+ int j, n, rc;
+
+ char e[EGS_SECP256K1];
+ octet E = {0, sizeof(e), e};
+
+ char mn[FS_2048];
+ octet MN = {0, sizeof(mn), mn};
+
+ MPC_keygen_round3 *r;
+ MPC_player *p;
+
+ n = s->party->n;
+
+ printf("\t[Player %d] Verify key material ZKP\n", i);
+
+ for (j = 0; j < n; j++)
+ {
+ if(j == i) continue; // Trust ourselves
+
+ // Load appropriate player and round communications
+ r = s->round3 + j;
+ p = s->party->players + j;
+
+ /* Verify Schnorr Proof */
+ SCHNORR_challenge(p->pkm.SPK, r->SCHNORR_C, p->ID, s->ID, &E);
+ rc = SCHNORR_verify(p->pkm.SPK, r->SCHNORR_C, &E, r->SCHNORR_P);
+ if (rc != SCHNORR_OK)
+ {
+ printf("\t\tInvalid Schnorr Proof for Player %d. rc %d\n", j, rc);
+ return rc;
+ }
+
+ /* Verify GMR proof of Square-Freeness */
+ PAILLIER_PK_toOctet(&MN, &p->pkm.paillier_pk);
+ rc = GMR_verify(&MN, r->Y, p->ID, s->ID);
+ if (rc != GMR_OK)
+ {
+ printf("\t\tInvalid GMR Proof for Player %d. rc %d\n", j, rc);
+ return rc;
+ }
+
+ /* Verify well formedness of BC modulus */
+ rc = BIT_COMMITMENT_setup_verify(&p->pkm.bc_pm, &r->BCP, p->ID, s->ID);
+ if (rc != BIT_COMMITMENT_OK)
+ {
+ printf("\t\tInvalid BC Proof for Player %d. rc %d\n", j, rc);
+ return rc;
+ }
+ }
+
+ printf("\t[Player %d] Broadcast Success\n", i);
+
+ return MPC_OK;
+}
+
+/* Keygen - Orchestrate the Key Setup for all players */
+int key_setup(csprng *RNG, MPC_party *p)
+{
+ int i, t, n, rc;
+
+ n = p->n;
+ t = p->t;
+
+ /* Setup Keygen memory */
+
+ // Round1 memory
+ char round1_sk[n][EGS_SECP256K1];
+ char round1_pk[n][EFS_SECP256K1 + 1];
+ char round1_r[n][EGS_SECP256K1];
+ char round1_c[n][EGS_SECP256K1];
+ octet ROUND1_SK[n];
+ octet ROUND1_PK[n];
+ octet ROUND1_R[n];
+ octet ROUND1_C[n];
+
+ init_octets((char *)round1_sk, ROUND1_SK, EGS_SECP256K1, n);
+ init_octets((char *)round1_pk, ROUND1_PK, EFS_SECP256K1 + 1, n);
+ init_octets((char *)round1_r, ROUND1_R, EGS_SECP256K1, n);
+ init_octets((char *)round1_c, ROUND1_C, EGS_SECP256K1, n);
+
+ MPC_keygen_round1 r1[n];
+
+ for (i = 0; i < n; i++)
+ {
+ r1[i].SK = ROUND1_SK + i;
+ r1[i].PK = ROUND1_PK + i;
+ r1[i].C = ROUND1_C + i;
+ r1[i].R = ROUND1_R + i;
+ }
+
+ // Keygen Round2 memory
+ char round2_shares_x[n][n][EGS_SECP256K1];
+ char round2_shares_y[n][n][EGS_SECP256K1];
+ char round2_checks[n][t][EFS_SECP256K1 + 1];
+ octet ROUND2_CHECKS[n * t];
+ octet ROUND2_SHARES_X[n * n];
+ octet ROUND2_SHARES_Y[n * n];
+
+ init_octets((char *)round2_shares_x, ROUND2_SHARES_X, EGS_SECP256K1, n * n);
+ init_octets((char *)round2_shares_y, ROUND2_SHARES_Y, EGS_SECP256K1, n * n);
+ init_octets((char *)round2_checks, ROUND2_CHECKS, EFS_SECP256K1 + 1, n * t);
+
+ MPC_keygen_round2 r2[n];
+
+ for (i = 0; i < n; i++)
+ {
+ r2[i].SHARES.X = ROUND2_SHARES_X + (n * i);
+ r2[i].SHARES.Y = ROUND2_SHARES_Y + (n * i);
+ r2[i].CHECKS = ROUND2_CHECKS + (t * i);
+ }
+
+ // Keygen Round3 memory
+ char round3_sc[n][EFS_SECP256K1 + 1];
+ char round3_sp[n][EGS_SECP256K1];
+
+ octet ROUND3_SC[n];
+ octet ROUND3_SP[n];
+
+ init_octets((char *)round3_sc, ROUND3_SC, EFS_SECP256K1 + 1, n);
+ init_octets((char *)round3_sp, ROUND3_SP, EGS_SECP256K1, n);
+
+ MPC_keygen_round3 r3[n];
+
+ for (i = 0; i < n; i++)
+ {
+ r3[i].SCHNORR_C = ROUND3_SC + i;
+ r3[i].SCHNORR_P = ROUND3_SP + i;
+ }
+
+ // Keygen Session memory
+ char id[IDLEN];
+ octet ID = {0, sizeof(id), id};
+ MPC_keygen_session s;
+
+ s.ID = &ID;
+ s.party = p;
+ s.round1 = r1;
+ s.round2 = r2;
+ s.round3 = r3;
+
+ /* Agree on session ID for keygen */
+ OCT_rand(s.ID, RNG, s.ID->max);
+
+ printf("\n *** Keygen ***\n");
+
+ /* Round 1 - generate key material, commitment */
+
+ printf("\nRound 1 - Generate Key Material\n");
+
+ for (i = 0; i < n; i++)
+ {
+ rc = MPC_keygen_round1_generate(RNG, p->players +i, s.round1 + i, i);
+ if (rc != MPC_OK)
+ {
+ return rc;
+ }
+
+ printf("\n");
+ }
+
+ /* Round 2 - compute VSS shares and checks */
+
+ printf("\nRound 2 - Compute VSS Shares and Checks\n");
+
+ for (i = 0; i < n; i++)
+ {
+ MPC_keygen_round2_vss(RNG, s.round1 + i, s.round2 + i, i, t, n);
+
+ printf("\n");
+ }
+
+ /* Round 2 - Verify VSS Shares and combine them */
+
+ printf("\nRound 2 - Verify and combine VSS Shares\n");
+
+ for (i = 0; i < n; i++)
+ {
+ rc = MPC_keygen_round2_compose(&s, i);
+ if (rc != MPC_OK)
+ {
+ return rc;
+ }
+
+ printf("\n");
+ }
+
+ /* Round 3 - Generate Proofs for Key Material */
+
+ printf("\nRound 3 - Generate Proofs for key material\n");
+
+ for (i = 0; i < n; i++)
+ {
+ MPC_keygen_round3_proofs(RNG, p->players + i, s.round3 + i, s.ID, i);
+ printf("\n");
+ }
+
+ /* Round 3 - Verify Proofs for Key Material */
+ printf("\n\nRound 3 - Verify Proofs for Key Material\n");
+
+ for (i = 0; i < n; i++)
+ {
+ rc = MPC_keygen_round3_verify(&s, i);
+ if (rc != MPC_OK)
+ {
+ return rc;
+ }
+
+ printf("\n");
+ }
+
+ return MPC_OK;
+}
+
+/* *** Signature functions ***/
+
+/* Sign - Convert shamir shares to additive */
+void MPC_sign_share_conversion(MPC_signing_session *s, int i)
+{
+ int j, k, t;
+
+ t = s->party->t;
+
+ char x[t-1][EGS_SECP256K1];
+ octet X[t-1];
+
+ init_octets((char *) x, X, EGS_SECP256K1, t-1);
+
+ MPC_player *p;
+ MPC_signing_additive_shares *sh;
+
+ k = 0;
+ for (j = 0; j < t; j++)
+ {
+ if (i == j) continue; // Do not include own shares in computation
+
+ // This looks like we are accessing the secret key material,
+ // but it is the X component of the Shamir Share, which
+ // is not secret
+ OCT_copy(X + k, s->party->players[j].skm.SKX);
+ k++;
+ }
+
+ printf("\t[Player %d] Convert Shamir Share to additive Share\n", i);
+
+ p = s->party->players + i;
+ sh = s->shares + i;
+
+ SSS_shamir_to_additive(t, p->skm.SKX, p->skm.SKY, X, sh->W);
+
+ /* TODO This should not be computed here
+ *
+ * This should be computed by each player for all players
+ * using the same Lagrange coefficient above and the stored
+ * xi.G from the keygen
+ */
+ BIG_256_56 w;
+ ECP_SECP256K1 G;
+ ECP_SECP256K1_generator(&G);
+ BIG_256_56_fromBytesLen(w, sh->W->val, sh->W->len);
+ ECP_SECP256K1_mul(&G, w);
+ ECP_SECP256K1_toOctet(sh->WG, &G, true);
+}
+
+/* Sign - Generate secret values k, gamma for signature */
+void MPC_sign_round1_generate(csprng *RNG, MPC_signing_round1* r, int i)
+{
+ BIG_256_56 k;
+ BIG_256_56 q;
+
+ char gammapt[2 * EFS_SECP256K1 + 1];
+ octet GAMMAPT = {0, sizeof(gammapt), gammapt};
+
+ ECP_SECP256K1 ECP;
+
+ BIG_256_56_rcopy(q, CURVE_Order_SECP256K1);
+
+ printf("\t[Player %d] Generate Random k, gamma\n", i);
+
+ BIG_256_56_randomnum(k, q, RNG);
+ BIG_256_56_toBytes(r->K->val, k);
+ r->K->len = EGS_SECP256K1;
+
+ MPC_ECDSA_KEY_PAIR_GENERATE(RNG, r->GAMMA, &GAMMAPT);
+
+ // Convert GAMMAPT to compressed form
+ ECP_SECP256K1_fromOctet(&ECP, &GAMMAPT);
+ ECP_SECP256K1_toOctet(r->GAMMAPT, &ECP, true);
+
+ printf("\t[Player %d] Commit to gamma.G\n", i);
+
+ NM_COMMITMENT_commit(RNG, r->GAMMAPT, r->R, r->C);
+
+ printf("\t[Player %d] Transmit commitment C\n", i);
+}
+
+/* Sign -
+ * Perform MTA with Range Proof and Receiver ZK Proof for all players
+ * Instead of saving all the shares and then summing them, each player
+ * initialises DELTA with its own KGAMMA share and then accumulates the
+ * shares on top of it as they come. This saves memory and it is still
+ * fairly easy to parallelise with an opportune lock on DELTA.
+ *
+ * Given a Alice in the players:
+ * Step 1. Alice encrypts its share and proves it is in the appropriate range in ZK
+ *
+ * The result from Step 1. is then transmitted to all the other players.
+ *
+ * Let's call Bob a generic receinver:
+ * Step 2. Bob verifies the ZK proof and aborts if the verification fails
+ * Step 2A. Bob homomorphically multiplies its share and adds an obfuscation value z
+ * Step 2B. Bob proves knowledge of z and range of its share
+ * Step 2C. Bob adds BETA to its DELTA
+ * Step 3. Alice verifies the ZK proof and aborts if the verification fails
+ * Step 3A. Alice decrypts the obfuscated product, retrieving ALPHA
+ * Step 3B. Alice adds ALPHA to its DELTA
+ *
+ */
+int MPC_sign_round2_mta(csprng *RNG, MPC_signing_session *s)
+{
+ int i, j, t, rc;
+
+ t = s->party->t;
+
+ /* Memory Setup */
+
+ BIG_256_56 delta[t];
+
+ char cb[FS_4096];
+ octet CB = {0, sizeof(cb), cb};
+
+ char rb[FS_4096];
+ octet RB = {0, sizeof(rb), rb};
+
+ char z[EGS_SECP256K1];
+ octet Z = {0, sizeof(z), z};
+
+ char e[EGS_SECP256K1];
+ octet E = {0, sizeof(e), e};
+
+ char alpha[EGS_SECP256K1];
+ octet ALPHA = {0, sizeof(alpha), alpha};
+
+ char beta[EGS_SECP256K1];
+ octet BETA = {0, sizeof(beta), beta};
+
+ MTA_RP_commitment alice_rp_c;
+ MTA_RP_rv alice_rp_rv;
+ MTA_RP_proof alice_rp_proof;
+
+ MTA_ZK_commitment bob_zk_c;
+ MTA_ZK_rv bob_zk_rv;
+ MTA_ZK_proof bob_zk_proof;
+
+ MPC_player *alice;
+ MPC_player *bob;
+
+ MPC_signing_round1 *alice_r1;
+ MPC_signing_round2 *alice_r2;
+ MPC_signing_round1 *bob_r1;
+
+ // Initialize accumulator for delta = k * gamma
+ for (i = 0; i < t; i++)
+ {
+ MTA_ACCUMULATOR_SET(delta[i], s->round1[i].GAMMA, s->round1[i].K);
+ }
+
+ /* MtA runs */
+ for (i = 0; i < t; i++)
+ {
+ alice = s->party->players + i;
+ alice_r1 = s->round1 + i;
+ alice_r2 = s->round2 + i;
+
+ /* Alice - Initiate MTA protocol
+ *
+ * This is reused for all instances of the MTA protocol initiated
+ * by Alice
+ */
+
+ printf("\t[Player %d] MTA Pass 1\n", i);
+
+ MTA_CLIENT1(RNG, &alice->pkm.paillier_pk, alice_r1->K, alice_r2->CA, alice_r2->R);
+
+ for (j = 0; j < t; j++)
+ {
+ if (i == j) continue; // No MtA with ourselves
+
+ /* Alice - Generate Range Proof with Bob BC Public Modulus */
+
+ printf("\t[Player %d] Generate Range Proof for Pass 1\n", i);
+
+ bob = s->party->players + j;
+ bob_r1 = s->round1 + j;
+
+ MTA_RP_commit(RNG, &alice->skm.paillier_sk, &bob->pkm.bc_pm, alice_r1->K, &alice_rp_rv, &alice_rp_c);
+ MTA_RP_challenge(&alice->pkm.paillier_pk, &bob->pkm.bc_pm, alice_r2->CA, &alice_rp_c, alice->ID, s->ID, &E);
+ MTA_RP_prove(&alice->skm.paillier_sk, alice_r1->K, alice_r2->R, &alice_rp_rv, &E, &alice_rp_proof);
+
+ MTA_RP_rv_kill(&alice_rp_rv);
+
+ printf("\t[Player %d] Transmit CA and proof (Z, U, W, S, S1, S2) to Player %d\n", i, j);
+
+ /* Bob - Verify Range Proof and perform second step of MTA protocol */
+
+ printf("\t[Player %d] Verify proof\n", j);
+
+ OCT_clear(&E);
+ MTA_RP_challenge(&alice->pkm.paillier_pk, &bob->pkm.bc_pm, alice_r2->CA, &alice_rp_c, alice->ID, s->ID, &E);
+
+ rc = MTA_RP_verify(&alice->pkm.paillier_pk, &bob->skm.bc_sm, alice_r2->CA, &alice_rp_c, &E, &alice_rp_proof);
+ if (rc != MTA_OK)
+ {
+ printf("\t\tInvalid Range Proof for Player %d. rc %d\n", i, rc);
+ return MPC_FAIL;
+ }
+
+ printf("\t[Player %d] MTA Pass 2 with ZK Proof\n", j);
+
+ MTA_SERVER(RNG, &alice->pkm.paillier_pk, bob_r1->GAMMA, alice_r2->CA, &Z, &RB, &CB, &BETA);
+
+ MTA_ZK_commit(RNG, &alice->pkm.paillier_pk, &alice->pkm.bc_pm, bob_r1->GAMMA, &Z, alice_r2->CA, &bob_zk_rv, &bob_zk_c);
+ MTA_ZK_challenge(&alice->pkm.paillier_pk, &alice->pkm.bc_pm, alice_r2->CA, &CB, &bob_zk_c, bob->ID, s->ID, &E);
+ MTA_ZK_prove(&alice->pkm.paillier_pk, bob_r1->GAMMA, &Z, &RB, &bob_zk_rv, &E, &bob_zk_proof);
+
+ MTA_ZK_rv_kill(&bob_zk_rv);
+ OCT_clear(&RB);
+ OCT_clear(&Z);
+
+ printf("\t[Player %d] Add BETA to the accumulator\n", j);
+
+ MTA_ACCUMULATOR_ADD(delta[j], &BETA);
+
+ printf("\t[Player %d] Transmit CB and proof (Z, Z1, T, V, W, S, S1, S2, T1, T2)\n", j);
+
+ /* Alice - Verify ZK proof and perform last step of MTA protocol */
+
+ printf("\t[Player %d] Verify proof\n", i);
+
+ OCT_clear(&E);
+ MTA_ZK_challenge(&alice->pkm.paillier_pk, &alice->pkm.bc_pm, alice_r2->CA, &CB, &bob_zk_c, bob->ID, s->ID, &E);
+
+ rc = MTA_ZK_verify(&alice->skm.paillier_sk, &alice->skm.bc_sm, alice_r2->CA, &CB, &bob_zk_c, &E, &bob_zk_proof);
+ if (rc != MTA_OK)
+ {
+ printf("\t\tInvalid ZK Proof for Player %d. rc %d\n", j, rc);
+ return MPC_FAIL;
+ }
+
+ printf("\t[Player %d] MTA Pass 3 and sum with accumulator\n", i);
+
+ MTA_CLIENT2(&alice->skm.paillier_sk, &CB, &ALPHA);
+
+ MTA_ACCUMULATOR_ADD(delta[i], &ALPHA);
+ }
+ }
+
+ // Put the accumulators in the correct round structs
+ for (i = 0; i < t; i++)
+ {
+ BIG_256_56_toBytes(s->round2[i].DELTA->val, delta[i]);
+ s->round2[i].DELTA->len = EGS_SECP256K1;
+ }
+
+ return MPC_OK;
+}
+
+/* Perform MTA with Range Proof and Receiver ZK Proof with check for all
+ * players.
+ * The same consideration aobut parallelisation done for the MtA holds.
+ *
+ * There is a case to be done for reusing the same encryption of k
+ * and RP Proof for both the MtA and MtAwC. I'm doing it separately here
+ * to better reflect the paper.
+ *
+ * Given a Alice in the players:
+ * Step 1. Alice encrypts its share and proves it is in the appropriate range in ZK
+ *
+ * The result from Step 1. is then transmitted to all the other players.
+ *
+ * Let's call Bob a gneric receinver:
+ * Step 2. Bob verifies the ZK proof and aborts if the verification fails
+ * Step 2A. Bob homomorphically multiplies its share and adds an obfuscation value z
+ * Step 2B. Bob proves knowledge of z and range and DLOG knowledge for its share
+ * Step 2C. Bob adds BETA to its DELTA
+ * Step 3. Alice verifies the ZK proof and aborts if the verification fails
+ * Step 3A. Alice decrypts the obfuscated product, retrieving ALPHA
+ * Step 3B. Alice adds ALPHA to its DELTA
+ *
+ */
+int MPC_sign_round2_mtawc(csprng *RNG, MPC_signing_session *s)
+{
+ int i, j, t, rc;
+
+ t = s->party->t;
+
+ /* Memory Setup */
+
+ BIG_256_56 sigma[t];
+
+ char ca[FS_4096];
+ octet CA = {0, sizeof(ca), ca};
+
+ char cb[FS_4096];
+ octet CB = {0, sizeof(cb), cb};
+
+ char ra[FS_4096];
+ octet RA = {0, sizeof(ra), ra};
+
+ char rb[FS_4096];
+ octet RB = {0, sizeof(rb), rb};
+
+ char z[EGS_SECP256K1];
+ octet Z = {0, sizeof(z), z};
+
+ char e[EGS_SECP256K1];
+ octet E = {0, sizeof(e), e};
+
+ char alpha[EGS_SECP256K1];
+ octet ALPHA = {0, sizeof(alpha), alpha};
+
+ char beta[EGS_SECP256K1];
+ octet BETA = {0, sizeof(beta), beta};
+
+ MTA_RP_commitment alice_rp_c;
+ MTA_RP_rv alice_rp_rv;
+ MTA_RP_proof alice_rp_proof;
+
+ MTA_ZKWC_commitment bob_zkwc_c;
+ MTA_ZKWC_rv bob_zkwc_rv;
+ MTA_ZKWC_proof bob_zkwc_proof;
+
+ MPC_player *alice;
+ MPC_player *bob;
+
+ MPC_signing_round1 *alice_r1;
+
+ // Initialize accumulator for sigma = k * w
+ for (i = 0; i < t; i++)
+ {
+ MTA_ACCUMULATOR_SET(sigma[i], s->shares[i].W, s->round1[i].K);
+ }
+
+ /* MtAWC runs */
+ for (i = 0; i < t; i++)
+ {
+ alice = s->party->players + i;
+ alice_r1 = s->round1 + i;
+
+ /* Alice - Initiate MTAWC protocol
+ *
+ * This is reused for all instances of the MTAWC protocol initiated
+ * by Alice
+ */
+
+ printf("\t[Player %d] MTAWC Pass 1\n", i);
+
+ MTA_CLIENT1(RNG, &alice->pkm.paillier_pk, alice_r1->K, &CA, &RA);
+
+ for (j = 0; j < t; j++)
+ {
+ if (i == j) continue; // No MtAWC with ourselves
+
+ /* Alice - Generate Range Proof with Bob BC Public Modulus */
+
+ printf("\t[Player %d] Generate Range Proof for Pass 1\n", i);
+
+ bob = s->party->players + j;
+
+ MTA_RP_commit(RNG, &alice->skm.paillier_sk, &bob->pkm.bc_pm, alice_r1->K, &alice_rp_rv, &alice_rp_c);
+ MTA_RP_challenge(&alice->pkm.paillier_pk, &bob->pkm.bc_pm, &CA, &alice_rp_c, alice->ID, s->ID, &E);
+ MTA_RP_prove(&alice->skm.paillier_sk, alice_r1->K, &RA, &alice_rp_rv, &E, &alice_rp_proof);
+
+ MTA_RP_rv_kill(&alice_rp_rv);
+
+ printf("\t[Player %d] Transmit CA and proof (Z, U, W, S, S1, S2) to Player %d\n", i, j);
+
+ /* Bob - Verify Range Proof and perform second step of MTAWC protocol */
+
+ printf("\t[Player %d] Verify proof\n", j);
+
+ OCT_clear(&E);
+ MTA_RP_challenge(&alice->pkm.paillier_pk, &bob->pkm.bc_pm, &CA, &alice_rp_c, alice->ID, s->ID, &E);
+
+ rc = MTA_RP_verify(&alice->pkm.paillier_pk, &bob->skm.bc_sm, &CA, &alice_rp_c, &E, &alice_rp_proof);
+ if (rc != MTA_OK)
+ {
+ printf("\t\tInvalid Range Proof for Player %d. rc %d\n", i, rc);
+ return MPC_FAIL;
+ }
+
+ printf("\t[Player %d] MTA Pass 2 with ZKWC Proof\n", j);
+
+ MTA_SERVER(RNG, &alice->pkm.paillier_pk, s->shares[j].W, &CA, &Z, &RB, &CB, &BETA);
+
+ MTA_ZKWC_commit(RNG, &alice->pkm.paillier_pk, &alice->pkm.bc_pm, s->shares[j].W, &Z, &CA, &bob_zkwc_rv, &bob_zkwc_c);
+ MTA_ZKWC_challenge(&alice->pkm.paillier_pk, &alice->pkm.bc_pm, &CA, &CB, s->shares[j].WG, &bob_zkwc_c, bob->ID, s->ID, &E);
+ MTA_ZKWC_prove(&alice->pkm.paillier_pk, s->shares[j].W, &Z, &RB, &bob_zkwc_rv, &E, &bob_zkwc_proof);
+
+ MTA_ZKWC_rv_kill(&bob_zkwc_rv);
+ OCT_clear(&RB);
+ OCT_clear(&Z);
+
+ printf("\t[Player %d] Add BETA to the accumulator\n", j);
+
+ MTA_ACCUMULATOR_ADD(sigma[j], &BETA);
+
+ printf("\t[Player %d] Transmit CB and proof (Z, Z1, T, V, W, S, S1, S2, T1, T2)\n", j);
+
+ /* Alice - Verify ZK proof and perform last step of MTA protocol */
+
+ printf("\t[Player %d] Verify proof\n", i);
+
+ OCT_clear(&E);
+ MTA_ZKWC_challenge(&alice->pkm.paillier_pk, &alice->pkm.bc_pm, &CA, &CB, s->shares[j].WG, &bob_zkwc_c, bob->ID, s->ID, &E);
+
+ rc = MTA_ZKWC_verify(&alice->skm.paillier_sk, &alice->skm.bc_sm, &CA, &CB, s->shares[j].WG, &bob_zkwc_c, &E, &bob_zkwc_proof);
+ if (rc != MTA_OK)
+ {
+ printf("\t\tInvalid ZKWC Proof for Player %d. rc %d\n", j, rc);
+ return MPC_FAIL;
+ }
+
+ printf("\t[Player %d] MTA Pass 3 and sum with accumulator\n", i);
+
+ MTA_CLIENT2(&alice->skm.paillier_sk, &CB, &ALPHA);
+
+ MTA_ACCUMULATOR_ADD(sigma[i], &ALPHA);
+ }
+
+ OCT_clear(&RA);
+ }
+
+ // Put the accumulators in the correct round structs
+ for (i = 0; i < t; i++)
+ {
+ BIG_256_56_toBytes(s->round2[i].SIGMA->val, sigma[i]);
+ s->round2[i].SIGMA->len = EGS_SECP256K1;
+ }
+
+ return MPC_OK;
+}
+
+/* Sign - Compute commitment and well formedness proof for Phase3 */
+void MPC_sign_round3_commitment(csprng *RNG, MPC_signing_session *s, int i)
+{
+ MPC_player *p;
+ MPC_signing_round2 *r2;
+ MPC_signing_round3 *r3;
+
+ char e[EGS_SECP256K1];
+ octet E = {0, sizeof(e), e};
+
+ GG20_ZKP_rv rv;
+
+ p = s->party->players + i;
+ r2 = s->round2 + i;
+ r3 = s->round3 + i;
+
+ printf("\t[Player %d] Compute commitment to sigma T and ZKP that T is well formed\n", i);
+
+ MPC_PHASE3_T(RNG, r2->SIGMA, r3->L, r3->T);
+
+ GG20_ZKP_phase3_commit(RNG, &rv, r3->C);
+ GG20_ZKP_phase3_challenge(r3->T, r3->C, p->ID, s->ID, &E);
+ GG20_ZKP_phase3_prove(&rv, &E, r2->SIGMA, r3->L, &r3->p);
+
+ printf("\t[Player %d] Broadcast T value and ZK Proof, along with the DELTA value\n", i);
+
+ GG20_ZKP_rv_kill(&rv);
+}
+
+/* Sign - Verify well formedness proof for Phase3 */
+int MPC_sign_round3_verify(MPC_signing_session *s, int i)
+{
+ int t, j, rc;
+
+ t = s->party->t;
+
+ MPC_player *p;
+ MPC_signing_round3 *r3;
+
+ char e[EGS_SECP256K1];
+ octet E = {0, sizeof(e), e};
+
+ /* Verify ZKP for T */
+
+ printf("\t[Player %d] Verify ZKP of well formedness for T\n", i);
+
+ for(j = 0; j < t; j++)
+ {
+ if (i == j) continue; // Trust self
+
+ r3 = s->round3 + j;
+ p = s->party->players + j;
+
+ GG20_ZKP_phase3_challenge(r3->T, r3->C, p->ID, s->ID, &E);
+ rc = GG20_ZKP_phase3_verify(r3->T, r3->C, &E, &r3->p);
+ if (rc != GG20_ZKP_OK)
+ {
+ printf("\t\tInvalid ZKP for player %d. rc %d\n", j, rc);
+ return MPC_FAIL;
+ }
+ }
+
+ return MPC_OK;
+}
+
+/* Sign - Combine the k * gamma shares and combine (k * gamma) ^ -1 */
+void MPC_sign_round3_invkgamma(MPC_signing_session *s, int i)
+{
+ int j, t;
+
+ t = s->party->t;
+
+ char kgamma[t][EGS_SECP256K1];
+ octet KGAMMA[t];
+
+ init_octets((char *) kgamma, KGAMMA, EGS_SECP256K1, t);
+
+ printf("\t[Player %d] Combine receinved delta in k * gamma and invert it\n", i);
+
+ // Load all KGAMMA shares (DELTAs)
+ for (j = 0; j < t; j++)
+ {
+ OCT_copy(KGAMMA + j, s->round2[j].DELTA);
+ }
+
+ MPC_INVKGAMMA(KGAMMA, s->round3[i].INVKGAMMA, t);
+}
+
+/* Sign - decommit gamma_i.G and combine them
+ *
+ * Doing this in bulk, but the same reasoning to bulk
+ * operations in keygen apply here.
+ */
+int MPC_sign_round4_combine_R(MPC_signing_session *s, int i)
+{
+ int j, t, rc;
+
+ MPC_signing_round1 *r1;
+ MPC_signing_round4 *r4;
+
+ t = s->party->t;
+ r4 = s->round4 + i;
+
+ char gammapt[t][EFS_SECP256K1 + 1];
+ octet GAMMAPT[t];
+
+ init_octets((char *)gammapt, GAMMAPT, EFS_SECP256K1 + 1, t);
+
+ /* Verify Decommitmet of gamma_i.G */
+ for (j = 0; j < t; j++)
+ {
+ r1 = s->round1 + j;
+ OCT_copy(GAMMAPT + j, r1->GAMMAPT);
+
+ if (i == j) continue; // Trust ourselves
+
+ rc = NM_COMMITMENT_decommit(r1->GAMMAPT, r1->R, r1->C);
+ if (rc != NM_COMMITMENT_OK)
+ {
+ printf("\t\tInvalid Commitment for Player %d\n", j);
+ return MPC_FAIL;
+ }
+ }
+
+ /* Combine to retreive R component */
+ printf("\t[Player %d] Recombine R component of the signautre\n", i);
+
+ rc = MPC_R(s->round3[i].INVKGAMMA, GAMMAPT, r4->R, r4->RP, t);
+ if (rc != MPC_OK)
+ {
+ printf("\t\tError recombining R component. rc %d", rc);
+ return rc;
+ }
+
+ return MPC_OK;
+}
+
+/* Sign - Compute proof of consistency with Paillier ciphertext */
+int MPC_sign_round5_prove(csprng *RNG, MPC_signing_session *s, int i)
+{
+ int j, rc;
+
+ MPC_player *p;
+ MPC_player *o;
+
+ MPC_signing_round1 *r1;
+ MPC_signing_round2 *r2;
+ MPC_signing_round4 *r4;
+ MPC_signing_round5 *r5;
+
+ p = s->party->players + i;
+ r1 = s->round1 + i;
+ r2 = s->round2 + i;
+ r4 = s->round4 + i;
+ r5 = s->round5 + i;
+
+ GGN_rv rv;
+
+ char e[EGS_SECP256K1];
+ octet E = {0, sizeof(e), e};
+
+ printf("\t[Player %d] Generate check Rt = k.R\n", i);
+
+ rc = MPC_ECP_GENERATE_CHECK(r4->RP, r1->K, r5->RI);
+ if (rc != MPC_OK)
+ {
+ printf("\t\tError generatring Rt\n");
+ return rc;
+ }
+
+ printf("\t[Player %d] Generate consistency proofs for Rt and E(K)\n", i);
+
+ for (j = 0; j < s->party->t; j++)
+ {
+ if (i == j) continue; // No proof for self
+
+ o = s->party->players + j;
+
+ rc = GGN_commit(RNG, &p->skm.paillier_sk, &o->pkm.bc_pm, r4->RP, r1->K, &rv, r5->c + j);
+ if (rc != GGN_OK)
+ {
+ printf("\t\tError generating proof for player %d\n rc %d", i, rc);
+ return MPC_FAIL;
+ }
+
+ GGN_challenge(&p->pkm.paillier_pk, &o->pkm.bc_pm, r4->RP, r5->RI, r2->CA, r5->c + j, p->ID, s->ID, &E);
+ GGN_prove(&p->skm.paillier_sk, r1->K, r2->R, &rv, &E, r5->p + j);
+
+ GGN_rv_kill(&rv);
+ }
+
+ printf("\t[Player %d] Broadcast Rt and consistency proof\n", i);
+
+ return MPC_OK;
+}
+
+/* Sign - Verify proof of consistency with Paillier ciphertext
+ * and check that recombining the Ri the public key is retrieved
+ *
+ * The same reasoning on parallelisation made for the other functions applies
+ */
+int MPC_sign_round5_verify(MPC_signing_session *s, int i)
+{
+ int j, t, rc;
+
+ t = s->party->t;
+
+ char rt[t][EFS_SECP256K1 + 1];
+ octet RT[t];
+
+ char e[EGS_SECP256K1];
+ octet E = {0, sizeof(e), e};
+
+ init_octets((char *)rt, RT, EFS_SECP256K1 + 1, t);
+
+ MPC_player *p;
+ MPC_player *o;
+ MPC_signing_round2 *r2;
+ MPC_signing_round4 *r4;
+ MPC_signing_round5 *r5;
+
+ p = s->party->players + i;
+
+ /* Verify the proofs of consistency for the checks */
+
+ printf("\t[Player %d] Verify Proofs of consistency for Rt\n", i);
+
+ for (j = 0; j < t; j++)
+ {
+ o = s->party->players + j;
+ r2 = s->round2 + j;
+ r4 = s->round4 + j;
+ r5 = s->round5 + j;
+
+ OCT_copy(RT + j, r5->RI);
+
+ if (i == j) continue; // Trust ourselves
+
+ GGN_challenge(&o->pkm.paillier_pk, &p->pkm.bc_pm, r4->RP, r5->RI, r2->CA, r5->c + i, o->ID, s->ID, &E);
+ rc = GGN_verify(&o->pkm.paillier_pk, &p->skm.bc_sm, r4->RP, r5->RI, r2->CA, r5->c + i, &E, r5->p + i);
+ if (rc != GGN_OK)
+ {
+ printf("\t\tInvalid Proof for Player %d. rc %d\n", j, rc);
+ return MPC_FAIL;
+ }
+ }
+
+ /* Verify R using the checks */
+
+ printf("\t[Player %d] Verify R with the received checks\n", i);
+
+ rc = MPC_ECP_VERIFY(RT, NULL, t);
+ if (rc != MPC_OK)
+ {
+ printf("\t\tInvalid checks for R. rc %d\n", rc);
+ return MPC_FAIL;
+ }
+
+ return MPC_OK;
+}
+
+/* Sign - compute check for sigma and ZKP of consistency with T from round 3 */
+int MPC_sign_round6_prove(csprng *RNG, MPC_signing_session *s, int i)
+{
+ int rc;
+
+ char e[EGS_SECP256K1];
+ octet E = {0, sizeof(e), e};
+
+ MPC_player *p;
+ MPC_signing_round2 *r2;
+ MPC_signing_round3 *r3;
+ MPC_signing_round4 *r4;
+ MPC_signing_round6 *r6;
+
+ p = s->party->players + i;
+ r2 = s->round2 + i;
+ r3 = s->round3 + i;
+ r4 = s->round4 + i;
+ r6 = s->round6 + i;
+
+ GG20_ZKP_rv rv;
+
+ /* Generate check for consistency of sigma */
+
+ printf("\t[Player %d] Generate check for consistency of sigma\n", i);
+
+ rc = MPC_ECP_GENERATE_CHECK(r4->RP, r2->SIGMA, r6->SI);
+ if (rc != MPC_OK)
+ {
+ printf("\t\tError genereting Si. rc %d\n", rc);
+ return rc;
+ }
+
+ /* Generate ZKP of consistency of the check */
+ rc = GG20_ZKP_phase6_commit(RNG, r4->RP, &rv, &r6->c);
+ if (rc != GG20_ZKP_OK)
+ {
+ printf("\t\tError generating commit for phase6 proof. rc %d\n", rc);
+ return rc;
+ }
+
+ GG20_ZKP_phase6_challenge(r4->RP, r3->T, r6->SI, &r6->c, p->ID, s->ID, &E);
+ GG20_ZKP_phase6_prove(&rv, &E, r2->SIGMA, r3->L, &r6->p);
+
+ // Clean memory
+ GG20_ZKP_rv_kill(&rv);
+
+ return MPC_OK;
+}
+
+/* Sign - Verify the checks and consistency proofs for Phase 6 */
+int MPC_sign_round6_verify(MPC_signing_session *s, int i)
+{
+ int j, t, rc;
+
+ t = s->party->t;
+
+ char e[EGS_SECP256K1];
+ octet E = {0, sizeof(e), e};
+
+ char si[t][EFS_SECP256K1 + 1];
+ octet SI[t];
+
+ init_octets((char *)si, SI, EFS_SECP256K1 + 1, t);
+
+ MPC_signing_round3 *r3;
+ MPC_signing_round4 *r4;
+ MPC_signing_round6 *r6;
+
+ /* Verify the consistency of the SI checks */
+
+ printf("\t[Player %d] Verify the consistency of the SI checks\n", i);
+
+ for (j = 0; j < t; j++)
+ {
+ r3 = s->round3 + j;
+ r4 = s->round4 + j;
+ r6 = s->round6 + j;
+
+ OCT_copy(SI + j, r6->SI);
+
+ if (i == j) continue; // Trust ourselves
+
+ GG20_ZKP_phase6_challenge(r4->RP, r3->T, r6->SI, &r6->c, s->party->players[j].ID, s->ID, &E);
+ rc = GG20_ZKP_phase6_verify(r4->RP, r3->T, r6->SI, &r6->c, &E, &r6->p);
+ if (rc != GG20_ZKP_OK)
+ {
+ printf("\t\tInvalid check for player %d. rc %d\n", j, rc);
+ return MPC_FAIL;
+ }
+ }
+
+ /* Verify R, SIGMA using the checks */
+
+ printf("\t[Player %d] Verify R, SIGMA using checks\n", i);
+
+ rc = MPC_ECP_VERIFY(SI, s->party->players[i].pkm.PK, t);
+ if (rc != MPC_OK)
+ {
+ printf("\t\tInvalid checks for R, SIGMA. rc %d\n", rc);
+ return MPC_FAIL;
+ }
+
+ return MPC_OK;
+}
+
+/* Sign - compute S component of the signature */
+int MPC_sign_round7_si(MPC_signing_session *s, octet *HM, int i)
+{
+ int rc;
+
+ printf("\t[Player %d] Compute share s_i of the signature S component\n", i);
+
+ rc = MPC_S(HM, s->round4[i].R, s->round1[i].K, s->round2[i].SIGMA, s->round7[i].SI);
+ if (rc != MPC_OK)
+ {
+ printf("\t\tError generating S share. rc %d\n", rc);
+ return rc;
+ }
+
+ return MPC_OK;
+}
+
+/* Sign - compute S component of the signature */
+int MPC_sign_round7_combine(MPC_signing_session *s, octet *HM, int i)
+{
+ int j, t, rc;
+
+ t = s->party->t;
+
+ char si[t][EGS_SECP256K1];
+ octet SI[t];
+
+ init_octets((char *)si, SI, EGS_SECP256K1, t);
+
+ for (j = 0; j < t; j++)
+ {
+ OCT_copy(SI + j, s->round7[j].SI);
+ }
+
+ printf("\t[Player %d] Recombine S component of signature\n", i);
+
+ MPC_SUM_BIGS(s->round7[i].S, SI, t);
+
+ printf("\t[Player %d] Verify Signature\n", i);
+
+ rc = MPC_ECDSA_VERIFY(HM, s->party->players[i].pkm.PK, s->round4[i].R, s->round7[i].S);
+ if (rc != MPC_OK)
+ {
+ fprintf(stderr, "\t\tInvalid signature. rc: %d\n", rc);
+ return rc;
+ }
+
+ return MPC_OK;
+}
+
+/* Sign - Orchestrate the signing functions
+ *
+ * Step 1. Each player generates random k, gamma and commits to gamma.G
+ * Step 2. Each player performs a MTA with shares k_i, gamma_j and accumulates the shares
+ * Step 2A. Each player performs a MTAWC with shares k_i, sk_j and accumulates the shares
+ * Step 3. Players compute the Phase3 values and ZKP and sigma.
+ * Step 3A. Players broadcast delta shares and recombine (k * gamma)^-1
+ * Step 4. Players decommit gamma_i.G and recombine the R component
+ * Step 5. Compute checks Rt for R, K and ZKP of consistency with the encryption from round 2
+ * Step 5A. Verify Rt consistency and then use them to check R, K
+ * Step 6. Compute checks SI for R, SIGMA and ZKP of consistency with T from round 3
+ * Step 6A Verify SI consistency and use them to check R, SIGMA
+ * Step 7. Compute the signature S component share
+ * Step 7A. Recombine the full S component
+ */
+int signature(csprng *RNG, MPC_party *p, octet *MSG)
+{
+ int i, t, rc;
+
+ t = p->t;
+
+ /* Signing Session Memory Setup */
+ char hm[SHA256];
+ octet HM = {0, sizeof(hm), hm};
+
+ // Additive shares
+ char as_w[t][EGS_SECP256K1];
+ char as_wg[t][EFS_SECP256K1 + 1];
+
+ octet AS_W[t];
+ octet AS_WG[t];
+
+ init_octets((char *)as_w, AS_W, EGS_SECP256K1, t);
+ init_octets((char *)as_wg, AS_WG, EFS_SECP256K1 + 1, t);
+
+ MPC_signing_additive_shares as[t];
+
+ for (i = 0; i < t; i++)
+ {
+ as[i].W = AS_W + i;
+ as[i].WG = AS_WG + i;
+ }
+
+ // Round 1
+ char phase1_gamma[t][EGS_SECP256K1];
+ char phase1_gammapt[t][EFS_SECP256K1 + 1];
+ char phase1_k[t][EGS_SECP256K1];
+ char phase1_r[t][EGS_SECP256K1];
+ char phase1_c[t][EGS_SECP256K1];
+
+ octet PHASE1_GAMMA[t];
+ octet PHASE1_GAMMAPT[t];
+ octet PHASE1_K[t];
+ octet PHASE1_R[t];
+ octet PHASE1_C[t];
+
+ init_octets((char *)phase1_gamma, PHASE1_GAMMA, EGS_SECP256K1, t);
+ init_octets((char *)phase1_gammapt, PHASE1_GAMMAPT, EFS_SECP256K1 + 1, t);
+ init_octets((char *)phase1_k, PHASE1_K, EGS_SECP256K1, t);
+ init_octets((char *)phase1_r, PHASE1_R, EGS_SECP256K1, t);
+ init_octets((char *)phase1_c, PHASE1_C, EGS_SECP256K1, t);
+
+ MPC_signing_round1 r1[t];
+
+ for (i = 0; i < t; i++)
+ {
+ r1[i].GAMMA = PHASE1_GAMMA + i;
+ r1[i].GAMMAPT = PHASE1_GAMMAPT + i;
+ r1[i].K = PHASE1_K + i;
+ r1[i].R = PHASE1_R + i;
+ r1[i].C = PHASE1_C + i;
+ }
+
+ // Round 2
+ char phase2_r[t][FS_4096];
+ char phase2_ca[t][FS_4096];
+ char phase2_delta[t][EGS_SECP256K1];
+ char phase2_sigma[t][EGS_SECP256K1];
+
+ octet PHASE2_R[t];
+ octet PHASE2_CA[t];
+ octet PHASE2_DELTA[t];
+ octet PHASE2_SIGMA[t];
+
+ init_octets((char *)phase2_r, PHASE2_R, FS_4096, t);
+ init_octets((char *)phase2_ca, PHASE2_CA, FS_4096, t);
+ init_octets((char *)phase2_delta, PHASE2_DELTA, EGS_SECP256K1, t);
+ init_octets((char *)phase2_sigma, PHASE2_SIGMA, EGS_SECP256K1, t);
+
+ MPC_signing_round2 r2[t];
+
+ for (i = 0; i < t; i++)
+ {
+ r2[i].R = PHASE2_R + i;
+ r2[i].CA = PHASE2_CA + i;
+ r2[i].DELTA = PHASE2_DELTA + i;
+ r2[i].SIGMA = PHASE2_SIGMA + i;
+ }
+
+ // Round 3
+ char phase3_invkgamma[t][EGS_SECP256K1];
+ char phase3_t[t][EFS_SECP256K1 + 1];
+ char phase3_l[t][EGS_SECP256K1];
+ char phase3_c[t][EFS_SECP256K1 + 1];
+
+ octet PHASE3_INVKGAMMA[t];
+ octet PHASE3_T[t];
+ octet PHASE3_L[t];
+ octet PHASE3_C[t];
+
+ init_octets((char *)phase3_invkgamma, PHASE3_INVKGAMMA, EGS_SECP256K1, t);
+ init_octets((char *)phase3_t, PHASE3_T, EFS_SECP256K1 + 1, t);
+ init_octets((char *)phase3_l, PHASE3_L, EGS_SECP256K1, t);
+ init_octets((char *)phase3_c, PHASE3_C, EFS_SECP256K1 + 1, t);
+
+ MPC_signing_round3 r3[t];
+
+ for (i = 0; i < t; i++)
+ {
+ r3[i].INVKGAMMA = PHASE3_INVKGAMMA + i;
+ r3[i].T = PHASE3_T + i;
+ r3[i].L = PHASE3_L + i;
+ r3[i].C = PHASE3_C + i;
+ }
+
+ // Round 4
+ char phase4_r[t][EGS_SECP256K1];
+ char phase4_rp[t][EFS_SECP256K1 + 1];
+
+ octet PHASE4_R[t];
+ octet PHASE4_RP[t];
+
+ init_octets((char *)phase4_r, PHASE4_R, EGS_SECP256K1, t);
+ init_octets((char *)phase4_rp, PHASE4_RP, EFS_SECP256K1 + 1, t);
+
+ MPC_signing_round4 r4[t];
+
+ for (i = 0; i < t; i++)
+ {
+ r4[i].R = PHASE4_R + i;
+ r4[i].RP = PHASE4_RP + i;
+ }
+
+ // Round 5
+ char phase5_ri[t][EFS_SECP256K1 + 1];
+ octet PHASE5_RI[t];
+ init_octets((char *)phase5_ri, PHASE5_RI, EFS_SECP256K1 + 1, t);
+
+ GGN_commitment phase5_c[t][t];
+ GGN_proof phase5_p[t][t];
+
+ MPC_signing_round5 r5[t];
+
+ for (i = 0; i < t; i++)
+ {
+ r5[i].RI = PHASE5_RI + i;
+ r5[i].c = phase5_c[i];
+ r5[i].p = phase5_p[i];
+ }
+
+ // Round 6
+ char phase6_si[t][EFS_SECP256K1 + 1];
+ octet PHASE6_SI[t];
+ init_octets((char *)phase6_si, PHASE6_SI, EFS_SECP256K1 + 1, t);
+
+ MPC_signing_round6 r6[t];
+
+ for (i = 0; i < t; i++)
+ {
+ r6[i].SI = PHASE6_SI + i;
+ }
+
+ // Round 7
+ char phase7_si[t][EGS_SECP256K1];
+ char phase7_s[t][EGS_SECP256K1];
+
+ octet PHASE7_SI[t];
+ octet PHASE7_S[t];
+
+ init_octets((char *)phase7_si, PHASE7_SI, EGS_SECP256K1, t);
+ init_octets((char *)phase7_s, PHASE7_S, EGS_SECP256K1, t);
+
+ MPC_signing_round7 r7[t];
+
+ for (i = 0; i < t; i++)
+ {
+ r7[i].SI = PHASE7_SI + i;
+ r7[i].S = PHASE7_S + i;
+ }
+
+ // Session
+ char id[IDLEN];
+ octet ID = {0, sizeof(id), id};
+
+ MPC_signing_session s;
+
+ s.ID = &ID;
+ s.shares = as;
+ s.party = p;
+ s.round1 = r1;
+ s.round2 = r2;
+ s.round3 = r3;
+ s.round4 = r4;
+ s.round5 = r5;
+ s.round6 = r6;
+ s.round7 = r7;
+
+ /* Agree on session ID for signature */
+ OCT_rand(s.ID, RNG, s.ID->max);
+
+ printf("\n *** Signature ***\n");
+
+ printf("\nSign message '%s'\n", MSG->val);
+
+ printf("\nPreparation\n");
+
+ /* Preparation - hash message */
+
+ printf("\t[Everyone] Compute Message hash\n");
+
+ MPC_HASH(SHA256, MSG, &HM);
+
+ /* Preparation - convert shares to additive */
+ for (i = 0; i < t; i++)
+ {
+ MPC_sign_share_conversion(&s, i);
+ printf("\n");
+ }
+
+ char w[EFS_SECP256K1 + 1];
+ octet W = {0, sizeof(w), w};
+ MPC_SUM_ECPS(&W, AS_WG, t);
+
+ if (!OCT_comp(&W, p->players->pkm.PK))
+ {
+ printf("Not te same\n");
+ OCT_output(&W);
+ OCT_output(p->players->pkm.PK);
+ return MPC_FAIL;
+ }
+
+ /* Round 1 - Generate Secret values */
+ printf("\nRound 1\n");
+
+ for (i = 0; i < t; i++)
+ {
+ MPC_sign_round1_generate(RNG, s.round1 + i, i);
+ printf("\n");
+ }
+
+ /* Round 2 - MTA/WC runs */
+ printf("\nRound 2\n");
+
+ rc = MPC_sign_round2_mta(RNG, &s);
+ if (rc != MPC_OK)
+ {
+ return rc;
+ }
+
+ rc = MPC_sign_round2_mtawc(RNG, &s);
+ if (rc != MPC_OK)
+ {
+ return rc;
+ }
+
+ /* Round 3 - Generate commitment for sigma and its ZKP */
+ printf("\nRound 3\n");
+
+ for (i = 0; i < t; i++)
+ {
+ MPC_sign_round3_commitment(RNG, &s, i);
+ printf("\n");
+ }
+
+ /* Round 3 - Verify commitment ZKP */
+ for (i = 0; i < t; i++)
+ {
+ rc = MPC_sign_round3_verify(&s, i);
+ if (rc != MPC_OK)
+ {
+ return rc;
+ }
+ printf("\n");
+ }
+
+ /* Round 3 - Recombine inverse of k * gamma */
+ for (i = 0; i < t; i++)
+ {
+ MPC_sign_round3_invkgamma(&s, i);
+ printf("\n");
+ }
+
+ /* Round 4 - Combine R component */
+
+ printf("\nRound 4\n");
+
+ for (i = 0; i < t; i++)
+ {
+ rc = MPC_sign_round4_combine_R(&s, i);
+ if (rc != MPC_OK)
+ {
+ return rc;
+ }
+ printf("\n");
+ }
+
+ /* Round 5 - Generate checks and proofs */
+ printf("\nRound 5\n");
+
+ for (i = 0; i < t; i++)
+ {
+ rc = MPC_sign_round5_prove(RNG, &s, i);
+ if (rc != MPC_OK)
+ {
+ return rc;
+ }
+ printf("\n");
+ }
+
+ /* Round 5 - Verify checks and proofs */
+ for (i = 0; i < t; i++)
+ {
+ rc = MPC_sign_round5_verify(&s, i);
+ if (rc != MPC_OK)
+ {
+ return rc;
+ }
+ printf("\n");
+ }
+
+ /* Round 6 - Generate checks and proofs */
+ printf("\nRound 6\n");
+
+ for (i = 0; i < t; i++)
+ {
+ rc = MPC_sign_round6_prove(RNG, &s, i);
+ if (rc != MPC_OK)
+ {
+ return rc;
+ }
+ printf("\n");
+ }
+
+ /* Round 6 - Verify checks and proofs */
+ for (i = 0; i < t; i++)
+ {
+ rc = MPC_sign_round6_verify(&s, i);
+ if (rc != MPC_OK)
+ {
+ return rc;
+ }
+ printf("\n");
+ }
+
+ /* Round 7 - Compute S shares */
+ printf("\nRound 7\n");
+
+ for (i = 0; i < t; i++)
+ {
+ rc = MPC_sign_round7_si(&s, &HM, i);
+ if (rc != MPC_OK)
+ {
+ return rc;
+ }
+ printf("\n");
+ }
+
+ /* Round 7 - Combine S shares */
+ for (i = 0; i < t; i++)
+ {
+ rc = MPC_sign_round7_combine(&s, &HM, i);
+ if (rc != MPC_OK)
+ {
+ return rc;
+ }
+ printf("\n");
+ }
+
+ printf("\nGenerated Signature:\n");
+
+ printf("\tR = ");
+ OCT_output(s.round4->R);
+ printf("\tS = ");
+ OCT_output(s.round7->S);
+
+ return MPC_OK;
+}
+
+void usage(char *name)
+{
+ printf("Usage: %s t n\n", name);
+ printf("Run a full (t, n) keygen and signature flow\n");
+ printf("\n");
+ printf(" t Threshold for the MPC protocol. t <= n\n");
+ printf(" n Number of participants in the MPC protocol. t <= n, n>1\n");
+ printf("\n");
+ printf("Example:\n");
+ printf(" %s 3 4\n", name);
+}
+
+int main(int argc, char *argv[])
+{
+ int i, t, n, rc;
+
+ /* Read arguments */
+ if (argc != 3)
+ {
+ usage(argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ t = atoi(argv[1]);
+ n = atoi(argv[2]);
+
+ if (t < 1 || n < 2 || t > n)
+ {
+ usage(argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ /* Memory setup
+ *
+ * Setup the necessary memory for a (t, n) party
+ */
+ char player_ids[n][IDLEN];
+ char player_pks[n][EFS_SECP256K1 + 1];
+ char player_spks[n][EFS_SECP256K1 + 1];
+ char player_skx[n][EGS_SECP256K1];
+ char player_sky[n][EGS_SECP256K1];
+ octet PLAYER_IDS[n];
+ octet PLAYER_PKS[n];
+ octet PLAYER_SPKS[n];
+ octet PLAYER_SKX[n];
+ octet PLAYER_SKY[n];
+
+ init_octets((char *)player_ids, PLAYER_IDS, IDLEN, n);
+ init_octets((char *)player_pks, PLAYER_PKS, EFS_SECP256K1 + 1, n);
+ init_octets((char *)player_spks, PLAYER_SPKS, EFS_SECP256K1 + 1, n);
+ init_octets((char *)player_skx, PLAYER_SKX, EGS_SECP256K1, n);
+ init_octets((char *)player_sky, PLAYER_SKY, EGS_SECP256K1, n);
+
+ MPC_player players[n];
+
+ for (i = 0; i < n; i++)
+ {
+ players[i].ID = PLAYER_IDS + i;
+ players[i].pkm.PK = PLAYER_PKS + i;
+ players[i].pkm.SPK = PLAYER_SPKS + i;
+ players[i].skm.SKX = PLAYER_SKX + i;
+ players[i].skm.SKY = PLAYER_SKY + i;
+ }
+
+ MPC_party p = {t, n, players};
+
+ // Deterministic RNG for example
+ char seed[32] = {0};
+ csprng RNG;
+ RAND_seed(&RNG, 32, seed);
+
+ // Assign IDs to players
+ for (i = 0; i < n; i++)
+ {
+ OCT_rand(PLAYER_IDS+i, &RNG, IDLEN);
+ }
+
+ printf("MPC full flow example\n");
+
+ // Key setup phase
+ rc = key_setup(&RNG, &p);
+ if (rc != MPC_OK)
+ {
+ exit(EXIT_FAILURE);
+ }
+
+ // Signature phase
+ char* msg = "BANANA";
+ octet MSG = {0, sizeof(msg), msg};
+
+ rc = signature(&RNG, &p, &MSG);
+ if (rc != MPC_OK)
+ {
+ exit(EXIT_FAILURE);
+ }
+
+ printf("\nDone\n");
+}
diff --git a/examples/example_gg20_reshare.c b/examples/example_gg20_reshare.c
new file mode 100644
index 0000000..da717bc
--- /dev/null
+++ b/examples/example_gg20_reshare.c
@@ -0,0 +1,903 @@
+/*
+ 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 <stdlib.h>
+#include <string.h>
+#include "amcl/mta.h"
+#include "amcl/mpc.h"
+#include "amcl/mta_zkp.h"
+#include "amcl/nm_commitment.h"
+#include "amcl/gmr.h"
+#include "amcl/ggn.h"
+#include "amcl/schnorr.h"
+#include "amcl/gg20_zkp.h"
+#include "amcl/shamir.h"
+
+#define IDLEN 16
+
+/* Example of the resharing */
+
+// Safe primes for BC Setup
+int primes_len = 4;
+
+char *primes[] =
+{
+ "C421122418EF6FE4D4F14F0F03EABA927C20B1A22BCBE90EC227EFE34AC912095D389ADE615CF55C80874533F4270BB705ABFFDB6007FEF0B44B2DBF31EDA0D5F39523B5826F9854FBF733B98EF450E77DD8B5B15C4E3CE5C195F46E524C8BF6F0C9F6D86CE8642A8B9A0C79CA64A103AB76CD65261F97AED4C17C433CEA5DEF",
+ "ED7859031659B9A5AC011687A60444B19F5A73F31F9EE83D710F2FEAE1C4FED558A1C5C3842EA01DB86C6D07BE9971F8AA7820DD1E8BB8C9AE888319F0E03BDCD8D3DBEBF8A48765188C001A121F7E48D458E1E8A43684A861F0FBE87DC541A06CA98CECB6954F906A52C2B3D0978AE945A1EA2F9285978F76F01E99FD8B6EEF",
+ "D93E4899805ED36219F38C3030D6FF92012E2B41ADC38DFFFFDB110AEAA36D619A5CFD63B02711EA482941E20A3F89A36E2CAF0BD675B154FDE6D5A457BCBD337383EE65B33CDAB078EE8F8E36E55D22BB5DF75D14F570E529A4681B4947A4F5ECCC575763BD765FDE1038DEDF24BEF02BA9A1EA4C17ACA3A1B33D2FB7D974AB",
+ "E4481CEDDBDDDF6E980FBC825B004E52D028784CD3B8290D9810FD987AF2053C3F4056C3A354BFF55B9BB5867A819A22B71BC1069A310087E4FBF98FD291DBCC443AB910301B34A2DEE68D1365E77EDF9A0A21B3928C38046BC15AC338F7E38B9E4586E02655F98523CD041FBB51A358E505A5D1B0A161955B6AC60CB0E37707",
+ "F5F3BB1CEECD21110EFB4BC9CF0AA7AEBB98675A7567D6A1EA4E866FED4838F1B41D8232599718CD82F2936CD15198DC16ADD280C32D6860882704AEF397E1A956DB17E36AEB92D5CF76689DACC9CEFE418EF699C948CE680AFF878768CE8F4BB68F14AB5E8C38209E6C2C54125533B22960BBD350CF76C3B12BBC9FBAAAAA27",
+ "E8E1F9281CB8C10BC01B42197E834F648A5C8AE111F7DB40DD25A6F8896A703D0F84D36EB6D1FC048DC74FD3164742CA86607C81670199FC3F1BF5AB22F2B11E4E2434E757C0484A4162E26B75A0715167C5E8E293B7CEFD475FAA8B10F2324D78150E56B1186E257066D8860603FBCE59865FB0A25FB41014C1740C8EAA29AF",
+ "C3278DF1CD5330CD6DABE2FC9E32B9A560C32F7F140C601D2A5788F856A387531EFA695D728038F8CA2945D01C10A5DA823025BA27D7640E96593C031674380592AF4B8FE29A9C464FF41B1CACD47A4B255A5CA93E2F2A806AF00A67FB78A15D3ED8A37CEBA10CA7D0036412805AEBB88EC8A745F237AC01002D49C459EB2AB7",
+ "DCE9B24D4DE749296335C0F0DB421A330E21DF04C722ADDECC4B72448C387072C84CD7DB1146E1E07BE78585DEF4F1D5E15F53B0942CCA89B0E812B0F6653C7DA8ACB771593D4B2B37A28AD80DD7184698742C110F0506B86BF8A2A20E8975DF2D2A57930438B8528E63C3430DBFCE204712E8D40550E81DA03622953BEA2DFB",
+ "D09A3ECE562DD033EC2C562C2B0B4EEB0D2262FE046C030BAAFD7CBA8F73E9734E337D3551FC6B487CA359A84F598EC5EC6FDBA014A0A0009EF582B9F90DE90C0BA7F941648C4F3A8CF904974BA05E8C23EDA5895025441251B2CFC5A216568E702427DEA178D37BF3D28F1B35E17E58F5551511331961703F3D410924859107",
+ "C03136A1E1E5BA88568A19142F41E9FAC2E76A2D839B550038005E420008AF7D6D7C80EA8A31A936D39C93D2031B20845F23464371909EE589BF80E850C94B9F0FBF516C3DE362868C811505EE15B869844A54FFB32B0620A7FC5BA040898A91AA68657D8B43990166E5A5AF06828AE0F7C1D0EE333C2AF8DE7603F2F662792F",
+ "DF88593FBF2482954BAAA2A48C59E2FDF85936C282514FFB47F18B8D1484C7E8BE1862D0A84D5B753389A2BFBAFF63B03406AC29893B88911F8664E547A63CB58E9A941463D7946CF0909E24E7BD8EF11AFC4EEAFC8F3366DB0A9AB091325AC82C9BAE218B115F8700BAA1F478E194A927F1FBE3A3EF423BCFAE78850059B69B",
+ "D3AE06CD993690F64104D4ECBE6B2386693B766431B86E038CAE39EE81BD8A71387FBCB9D17B5BFAAFB883D68B005E228CD455A4BFF69843F948A9168D1F87545FCBB969260E07BDD44F10E79E7409DED45ADDF32BA1CF33F9B2F68758622FE660F4E47A651F6403D99E7B148768CDDBEC71EBE931D5A95B820B5A75BD495003",
+ "DAA27689A7D8F9B21106DBE472C324EB1CA899F58F0F72F336957312A8ECDB4EBC3B50C38D5A2E9C2D1E552C7EA8D89315DD9C5CA7F9EB99C41F7A857D44F420109FE17092799E60E3537FC9193056979E0FF886B36C2898F45F599E4C5CCDDF9A8EC8DA0D20A53A6849124E027D30D641E21E69FF374792534BD682FCDCA35B",
+ "FBF9D46697C40BCA51A759C47E360F2DD8B81B6241B0A3645645FAC692E9E8F3407EFB6F238AE91F9DEA49240D26E37904673F55E91927CDEA248FE1352B97B226AB159A1539747383B1168FE8CF1B1DF4CD9147053E3702AE491FBCA4CCE835B4B351DF44F5333C185275DB21B807D0BC180BF697EC07AB843E0FA595851A87",
+ "FD44B39DF09A18F215EB391D50D21CD5EAC8BE2E5CC901DF852DE85C93341F82633AAAD07C19863E0CD7861AEEE1C0B4B69275AA8DD2D33C0F5E048EA13E9A6D8E01B77FED72347D527BD7508D2F5EC18E5CB2B27D40BAB5C10A17123E75042F4047C3B1AEB6D36BF0F93BB214501ECBB8F95CC1A3A99219F6933763580CDA2F",
+ "C2442E9569C8999831594E818A159C8C0AF6F7ED2989358E8D9E01D6B8A0D354F5F97D9CEAB766AF12F3CC5C511FE19A587FF1E7029C8E500432D357D90E3EF042E4F308C325760D726BC9B1D78BA439FB0236D85DB301E548C4201B9E74D5832AD3ED06E37CD6DBFD9C23D194068DB1B9209813557FBC0714142AD6F6C56AA3",
+ "DC3B22CFF90690B10EC73C115FED0E3AD3FA01A68F8C8AA1905CA47008E8C4AF9D7922AE4D41794D8123D1768A3E0F8B35DA0001086ADC5EBB92640DD2514CBAD000283F7C5A6C340C040C09654A204C3947A22AC05F72E13C3EBDE61B9D281016E40C559474D33381C974767408EE9E108619AE96E4CC87EB11E39772BA00B3",
+ "C5E0280A5F1B358D16EDEF14540C3C9D468D4AEBC74C9DB605A2E4CEC9F27095A3FDE659E1E6C95FB4BB60533DD89E71D808A8C5EB5A8A51B9FED24F7AE9003FFD6F5401D991153C52002E7DB4F6766363B2CA77E9A113808E7C35713D188AD55CE25B9DB1308A08F3366523E425F77D924346078D8E0E9948674BAD88EA59B7",
+ "FC33DF361A7B1D3C3D1C06FBF3CCAD6C067B27FF28B61B1EFDB364FFFEE79993D9D10213A778A02C6C823DB101CB7C7A483B9F2B060BD1B7EDC13DB890B323AE02B7209DA66B3289069EE8C7747A6D7242194DC48DBDFFB740534A591AE2F41446B08F9966DA045FC9C3F9188F1EF1308509D50BC970314B6AA335EA2839993B",
+ "E63B5740DDB573CF1F0A72DAF3EA00D65CA2A538036D20078CC7E3BDC95529F1D13ABC182EBF8BE42CA87C0AEED4952C1D1FADC3C3C8A363F66FABCA012890FBC76C935B479B4F302F1DC12289D34F1F69EC2278045603F5FE532B0CD86E6261852F99517B6226F013B04DCE1D940DF7FB8BC8A799D153C1490A915A8342B77F"
+};
+
+/* Party related structures */
+typedef struct
+{
+ PAILLIER_private_key paillier_sk;
+ BIT_COMMITMENT_priv bc_sm;
+
+ octet *SKX; // X share of the full key (t,n) sharing
+ octet *SKY; // Y share of the full key (t,n) sharing
+} MPC_priv_key_material;
+
+typedef struct
+{
+ octet *PK; // Full ECDSA PK
+ octet *SPK; // ECDSA PK associated to the player share
+
+ PAILLIER_public_key paillier_pk;
+ BIT_COMMITMENT_pub bc_pm;
+} MPC_pub_key_material;
+
+typedef struct
+{
+ octet *ID;
+
+ MPC_priv_key_material skm;
+ MPC_pub_key_material pkm;
+} MPC_player;
+
+typedef struct
+{
+ int t;
+ int n;
+
+ MPC_player *players;
+} MPC_party;
+
+/* Reshare related structures
+ *
+ * Note that these structures hold all the values
+ * generated in the round, even if they are not to be
+ * transmitted. The values to be transmitted and what channel
+ * to use are specified in the reshare functions
+ */
+
+typedef struct
+{
+ octet *R; // Decommitment string
+ octet *C; // Commitment string to PK
+} MPC_reshare_round1;
+
+typedef struct
+{
+ SSS_shares SHARES; // Shares for VSS
+ octet *CHECKS; // Checks for VSS
+} MPC_reshare_round2;
+
+typedef struct
+{
+ octet *SCHNORR_C;
+ octet *SCHNORR_P;
+
+ GMR_proof Y;
+ BIT_COMMITMENT_setup_proof BCP;
+} MPC_reshare_round3;
+
+typedef struct
+{
+ octet *W; // Secret additive share
+ octet *WG; // Public Key associated with the additive share
+} MPC_reshare_additive_shares;
+
+typedef struct
+{
+ octet *ID;
+
+ MPC_party *old_party;
+ MPC_party *new_party;
+
+ MPC_reshare_additive_shares* shares;
+
+ MPC_reshare_round1 *round1;
+ MPC_reshare_round2 *round2;
+ MPC_reshare_round3 *round3;
+} MPC_reshare_session;
+
+// Utility functions
+void init_octets(char* mem, octet *OCTETS, int max, int n)
+{
+ int i = 0;
+
+ for (i = 0; i < n; i++)
+ {
+ OCTETS[i].val = mem + (i*max);
+ OCTETS[i].len = 0;
+ OCTETS[i].max = max;
+ }
+}
+
+/* DEMO ONLY
+ * Trusted Key Setup for old party. This generates the SSS shares
+ * with a trusted dealer to have the starting setup. In a real
+ * world scenario this would have been set up with a proper
+ * trustless Keygen
+ */
+int trusted_key_setup(csprng *RNG, MPC_party *p)
+{
+ int i, n, rc;
+
+ n = p->n;
+
+ ECP_SECP256K1 ECP;
+
+ char sk[EGS_SECP256K1];
+ octet SK = {0, sizeof(sk), sk};
+
+ char pk[2 * EFS_SECP256K1 + 1];
+ octet PK = {0, sizeof(pk), pk};
+
+ char skx[n][EGS_SECP256K1];
+ char sky[n][EGS_SECP256K1];
+ octet SKX[n];
+ octet SKY[n];
+
+ init_octets((char *)skx, SKX, EGS_SECP256K1, n);
+ init_octets((char *)sky, SKY, EGS_SECP256K1, n);
+
+ SSS_shares shares = {SKX, SKY};
+
+ // Generate ECDSA Key Pair
+ printf("\t[Dealer] Generate ECDSA key pair\n");
+
+ MPC_ECDSA_KEY_PAIR_GENERATE(RNG, &SK, &PK);
+ rc = ECP_SECP256K1_PUBLIC_KEY_VALIDATE(&PK);
+ if (rc != 0)
+ {
+ printf("\t\tError generating ECDSA key pair. rc %d\n", rc);
+ return rc;
+ }
+
+ // Generate shares
+ SSS_make_shares(p->t, n, RNG, &shares, &SK);
+
+ for(i = 0; i < n; i++)
+ {
+ OCT_copy(p->players[i].skm.SKX, SKX+i);
+ OCT_copy(p->players[i].skm.SKY, SKY+i);
+ }
+
+ // Convert PK to compressed form
+ ECP_SECP256K1_fromOctet(&ECP, &PK);
+ ECP_SECP256K1_toOctet(p->players[0].pkm.PK, &ECP, true);
+
+ for (i = 1; i < n; i++)
+ {
+ OCT_copy(p->players[i].pkm.PK, p->players[0].pkm.PK);
+ }
+
+ return MPC_OK;
+}
+
+/* *** Resharing functions *** */
+
+/* Reshare - Round 1
+ *
+ * The old party converts their SSS shares to additive shares
+ * and commit to the equivalent public keys.
+ */
+void MPC_reshare_round1_commit(csprng *RNG, MPC_reshare_session *s, int i)
+{
+ int j, k, oldt;
+
+ oldt = s->old_party->t;
+
+ char x[oldt-1][EGS_SECP256K1];
+ octet X[oldt-1];
+
+ init_octets((char *) x, X, EGS_SECP256K1, oldt-1);
+
+ MPC_player *p;
+ MPC_reshare_round1 *r;
+ MPC_reshare_additive_shares *sh;
+
+ p = s->old_party->players + i;
+ r = s->round1 + i;
+ sh = s->shares + i;
+
+ printf("\t[Old Player %d] Convert Shamir Share to additive\n", i);
+
+ k = 0;
+ for (j = 0; j < oldt; j++)
+ {
+ if (i == j) continue; // Do not include own shares in computation
+
+ // This looks like we are accessing the secret key material,
+ // but it is the X component of the Shamir Share, which
+ // is not secret
+ OCT_copy(X + k, s->old_party->players[j].skm.SKX);
+ k++;
+ }
+
+ SSS_shamir_to_additive(oldt, p->skm.SKX, p->skm.SKY, X, sh->W);
+
+ /* TODO This should not be stored here
+ *
+ * This should be computed by each player for all players
+ * using the same Lagrange coefficient above and the stored
+ * xi.G from the original keygen
+ */
+ BIG_256_56 w;
+ ECP_SECP256K1 G;
+ ECP_SECP256K1_generator(&G);
+ BIG_256_56_fromBytesLen(w, sh->W->val, sh->W->len);
+ ECP_SECP256K1_mul(&G, w);
+ ECP_SECP256K1_toOctet(sh->WG, &G, true);
+
+ // Commit to the ECDSA public key
+ printf("\t[Old Player %d] Commit to additive share PK\n", i);
+
+ NM_COMMITMENT_commit(RNG, sh->WG, r->R, r->C);
+
+ printf("\t[Old Player %d] Broadcast commitment C\n", i);
+}
+
+/* Reshare - Round 2 - Generate VSS Shares
+ *
+ * Generate the (newt, newn) VSS shares for the old party additive shares.
+ */
+void MPC_reshare_round2_vss(csprng *RNG, MPC_reshare_session *s, int i)
+{
+ int newt, newn;
+
+ newt = s->new_party->t;
+ newn = s->new_party->n;
+
+ MPC_reshare_round2 *r;
+ MPC_reshare_additive_shares *sh;
+
+ r = s->round2 + i;
+ sh = s->shares + i;
+
+ printf("\t[Old Player %d] Generate VSS Shares for additive share\n", i);
+
+ VSS_make_shares(newt, newn, RNG, &r->SHARES, r->CHECKS, sh->W);
+
+ printf("\t[Old Player %d] Broadcast Checks and decommitment string.\n", i);
+ printf("\t[Old Player %d] Transmit shares with point2point channel\n", i);
+}
+
+/* Reshare - Round 2 - Compose New Party shares
+ *
+ * Once the shares and decommitments are received they can be
+ * verified and summed to compute the full key share for the player.
+ * Moreover, the full public key can be computed by adding all the
+ * free terms in the exponents from the checks.
+ *
+ * This is equivalent to the Keygen Round 2 and the same parallelisation
+ * observation applies.
+ */
+int MPC_reshare_round2_compose(MPC_reshare_session *s, int i)
+{
+ int j, oldt, rc;
+
+ oldt = s->old_party->t;
+
+ char ws[oldt][EFS_SECP256K1 + 1];
+ octet WS[oldt];
+
+ init_octets((char *)ws, WS, EFS_SECP256K1 + 1, oldt);
+
+ MPC_player *p;
+ MPC_reshare_round1 *r1;
+ MPC_reshare_round2 *r2;
+
+ printf("\t[New Player %d] Verify Shares\n", i);
+
+ /* Decommit Free term in the exponent and verify shares */
+ for (j = 0; j < oldt; j++)
+ {
+ p = s->old_party->players + j;
+ r1 = s->round1 + j;
+ r2 = s->round2 + j;
+
+ // Decommit free term in the exponent
+ rc = NM_COMMITMENT_decommit(r2->CHECKS + 0, r1->R, r1->C);
+ if (rc != NM_COMMITMENT_OK)
+ {
+ printf("\t\tInvalid Commitment for Old Player %d. rc %d\n", j, rc);
+ return rc;
+ }
+
+ // Check all the shares are for the same player
+ if (!OCT_comp(r2->SHARES.X+i, s->round2->SHARES.X+i))
+ {
+ printf("\t\tInvalid X share from Old Player %d.\n", j);
+ return MPC_FAIL;
+ }
+
+ // VSS Verification for the received share
+ rc = VSS_verify_shares(s->new_party->t, r2->SHARES.X+i, r2->SHARES.Y+i, r2->CHECKS);
+ if (rc != VSS_OK)
+ {
+ printf("\t\tInvalid Shares from Old Player %d. rc %d\n", j, rc);
+ return MPC_FAIL;
+ }
+ }
+
+ /* Compose Public Key */
+
+ printf("\t[New Player %d] Compose full PK\n", i);
+
+ p = s->new_party->players + i;
+
+ for (j = 0; j < oldt; j++)
+ {
+ OCT_copy(WS+j, s->round2[j].CHECKS + 0);
+ }
+
+ rc = MPC_SUM_ECPS(p->pkm.PK, WS, oldt);
+ if (rc != MPC_OK)
+ {
+ printf("\t\tInvalid format for PK Shares from Player %d. rc %d\n", i, rc);
+ return rc;
+ }
+
+ printf("\t[New Player %d] Verify the public key is still the same\n", i);
+
+ if (!OCT_comp(s->old_party->players->pkm.PK, p->pkm.PK))
+ {
+ printf("\t\tNew Public Key does not match\n");
+ return MPC_FAIL;
+ }
+
+ /* Compose Shares */
+
+ printf("\t[New Player %d] Combine full share\n", i);
+
+ for (j = 0; j < oldt; j++)
+ {
+ OCT_copy(WS+j, s->round2[j].SHARES.Y + i);
+ }
+
+ MPC_SUM_BIGS(p->skm.SKY, WS, oldt);
+
+ OCT_copy(p->skm.SKX, s->round2->SHARES.X+i);
+
+ /* TODO This should not be stored here
+ *
+ * This should be computed by each player for all players
+ */
+ BIG_256_56 w;
+ ECP_SECP256K1 G;
+ ECP_SECP256K1_generator(&G);
+ BIG_256_56_fromBytesLen(w, p->skm.SKY->val, p->skm.SKY->len);
+ ECP_SECP256K1_mul(&G, w);
+ ECP_SECP256K1_toOctet(p->pkm.SPK, &G, true);
+
+ return MPC_OK;
+}
+
+/* Reshare - Round 3 - Generate additional key material
+ *
+ * Generate additional key material: Paillier Keypair and BC modulus
+ * Generate a Schnorr Proof of knowledge of the secret share
+ * Generate a Square-Freeness proof for the Paillier Keys
+ * Generate a proof of well formedness for the ZKP modulus N, b0, b1
+ */
+void MPC_reshare_round3_proofs(csprng *RNG, MPC_reshare_session *s, int i)
+{
+ char oct1[HFS_2048];
+ octet OCT1 = {0, sizeof(oct1), oct1};
+ char oct2[HFS_2048];
+ octet OCT2 = {0, sizeof(oct2), oct2};
+
+ char rv[EGS_SECP256K1];
+ octet RV = {0, sizeof(rv), rv};
+
+ char e[EGS_SECP256K1];
+ octet E = {0, sizeof(e), e};
+
+ MODULUS_priv m;
+
+ MPC_player *p;
+ MPC_reshare_round3 *r;
+
+ p = s->new_party->players + i;
+ r = s->round3 + i;
+
+ // Generate Paillier Key pair
+ printf("\t[New Player %d] Generate Paillier key pair\n", i);
+
+ PAILLIER_KEY_PAIR(RNG, NULL, NULL, &p->pkm.paillier_pk, &p->skm.paillier_sk);
+
+ // Load Primes for BC setup
+ OCT_fromHex(&OCT1, primes[(2 * i) % primes_len]);
+ OCT_fromHex(&OCT2, primes[(2 * i + 1) % primes_len]);
+
+ // Generate BC modulus
+ printf("\t[New Player %d] Generate BC modulus\n", i);
+
+ BIT_COMMITMENT_setup(RNG, &p->skm.bc_sm, &OCT1, &OCT2, NULL, NULL);
+ BIT_COMMITMENT_priv_to_pub(&p->pkm.bc_pm, &p->skm.bc_sm);
+
+ /* Prove knowledge of DLOG PK = s.G */
+ printf("\t[New Player %d] Prove knowledge of secret key\n", i);
+
+ SCHNORR_commit(RNG, &RV, r->SCHNORR_C);
+ SCHNORR_challenge(p->pkm.SPK, r->SCHNORR_C, p->ID, s->ID, &E);
+ SCHNORR_prove(&RV, &E, p->skm.SKY, r->SCHNORR_P);
+
+ OCT_clear(&RV);
+
+ /* Prove Square Freeness of the Paillier modulus */
+ printf("\t[New Player %d] Prove Square-Freeness of Paillier modulus\n", i);
+
+ FF_2048_toOctet(&OCT1, p->skm.paillier_sk.p, HFLEN_2048);
+ FF_2048_toOctet(&OCT2, p->skm.paillier_sk.q, HFLEN_2048);
+ MODULUS_fromOctets(&m, &OCT1, &OCT2);
+
+ GMR_prove(&m, p->ID, s->ID, r->Y);
+
+ OCT_clear(&OCT1);
+ OCT_clear(&OCT2);
+ MODULUS_kill(&m);
+
+ /* Prove well formedness of the BC modulus */
+ printf("\t[New Player %d] Prove Well formedness of BC modulus\n", i);
+
+ BIT_COMMITMENT_setup_prove(RNG, &p->skm.bc_sm, &r->BCP, p->ID, s->ID);
+
+ printf("\t[New Player %d] Broadcast Public Key material, GMR Proof Y and BC proof values\n", i);
+}
+
+/* Reshare - Round 3 - Verify Key Material
+ *
+ * Verify the Square-Freeness proof for the paillier PK
+ * Verify the proof of well formedness for the BC modulus
+ *
+ * This is equivalent to the verification of Round 3 of the Keygen,
+ * without the Schnorr Proof. The same observation on parallelisation
+ * applies.
+ */
+int MPC_reshare_round3_verify(MPC_reshare_session *s, int i)
+{
+ int j, n, rc;
+
+ char e[EGS_SECP256K1];
+ octet E = {0, sizeof(e), e};
+
+ char mn[FS_2048];
+ octet MN = {0, sizeof(mn), mn};
+
+ MPC_reshare_round3 *r;
+ MPC_player *p;
+
+ n = s->new_party->n;
+
+ printf("\t[New Player %d] Verify key material ZKP\n", i);
+
+ for (j = 0; j < n; j++)
+ {
+ if(j == i) continue; // Trust ourselves
+
+ // Load appropriate player and round communications
+ r = s->round3 + j;
+ p = s->new_party->players + j;
+
+ /* Verify Schnorr Proof */
+ SCHNORR_challenge(p->pkm.SPK, r->SCHNORR_C, p->ID, s->ID, &E);
+ rc = SCHNORR_verify(p->pkm.SPK, r->SCHNORR_C, &E, r->SCHNORR_P);
+ if (rc != SCHNORR_OK)
+ {
+ printf("\t\tInvalid Schnorr Proof for Player %d. rc %d\n", j, rc);
+ return rc;
+ }
+
+ /* Verify GMR proof of Square-Freeness */
+ PAILLIER_PK_toOctet(&MN, &p->pkm.paillier_pk);
+ rc = GMR_verify(&MN, r->Y, p->ID, s->ID);
+ if (rc != GMR_OK)
+ {
+ printf("\t\tInvalid GMR Proof for New Player %d. rc %d\n", j, rc);
+ return rc;
+ }
+
+ /* Verify well formedness of BC modulus */
+ rc = BIT_COMMITMENT_setup_verify(&p->pkm.bc_pm, &r->BCP, p->ID, s->ID);
+ if (rc != BIT_COMMITMENT_OK)
+ {
+ printf("\t\tInvalid BC Proof for New Player %d. rc %d\n", j, rc);
+ return rc;
+ }
+ }
+
+ printf("\t[New Player %d] Broadcast Success\n", i);
+
+ return MPC_OK;
+}
+
+/* Reshare - Orchestrate the Key Setup for all players
+ *
+ * Step 1. The Old Party Players convert their SSS shares to additive shares
+ * Step 1A. The Old Party Players commit to the equivalent PK for the additive shares
+ * Step 2. The Old Party Players generate VSS shares and checks for the additive shares
+ * Step 2A. The New Party Players combine the shares and checks into their new SSS share and full PK
+ * Step 2B. The New Party Players verify that the full PK is unchanged
+ * Step 3. The New Party Players generate the additional key material and proofs for it
+ * Step 3A. The New Party Players verify the additional key material proofs.
+ * Step 3B. The New Party Players broadcast their success
+ * Step 3C. The Old Party Players delete the old key material
+ */
+int reshare(csprng *RNG, MPC_party *old_p, MPC_party *new_p)
+{
+ int i, oldt, newt, newn, rc;
+
+ oldt = old_p->t;
+ newn = new_p->n;
+ newt = new_p->t;
+
+ /* Setup Keygen memory */
+
+ // Reshare Round1 memory
+ char round1_r[oldt][EGS_SECP256K1];
+ char round1_c[oldt][EGS_SECP256K1];
+ octet ROUND1_R[oldt];
+ octet ROUND1_C[oldt];
+
+ init_octets((char *)round1_r, ROUND1_R, EGS_SECP256K1, oldt);
+ init_octets((char *)round1_c, ROUND1_C, EGS_SECP256K1, oldt);
+
+ MPC_reshare_round1 r1[oldt];
+
+ for (i = 0; i < oldt; i++)
+ {
+ r1[i].C = ROUND1_C + i;
+ r1[i].R = ROUND1_R + i;
+ }
+
+ // Reshare Round2 memory
+ char round2_shares_x[oldt][newn][EGS_SECP256K1];
+ char round2_shares_y[oldt][newn][EGS_SECP256K1];
+ char round2_checks[oldt][newt][EFS_SECP256K1 + 1];
+
+ octet ROUND2_SHARES_X[oldt * newn];
+ octet ROUND2_SHARES_Y[oldt * newn];
+ octet ROUND2_CHECKS[oldt * newt];
+
+ init_octets((char *)round2_shares_x, ROUND2_SHARES_X, EGS_SECP256K1, oldt * newn);
+ init_octets((char *)round2_shares_y, ROUND2_SHARES_Y, EGS_SECP256K1, oldt * newn);
+ init_octets((char *)round2_checks, ROUND2_CHECKS, EFS_SECP256K1 + 1, oldt * newt);
+
+ MPC_reshare_round2 r2[oldt];
+
+ for (i = 0; i < oldt; i++)
+ {
+ r2[i].SHARES.X = ROUND2_SHARES_X + (newn * i);
+ r2[i].SHARES.Y = ROUND2_SHARES_Y + (newn * i);
+ r2[i].CHECKS = ROUND2_CHECKS + (newt * i);
+ }
+
+ // Reshare Round3 memory
+ char round3_schnorr_c[newn][EFS_SECP256K1 + 1];
+ char round3_schnorr_p[newn][EGS_SECP256K1];
+ octet ROUND3_SCHNORR_C[newn];
+ octet ROUND3_SCHNORR_P[newn];
+
+ init_octets((char *)round3_schnorr_c, ROUND3_SCHNORR_C, EFS_SECP256K1 + 1, newn);
+ init_octets((char *)round3_schnorr_p, ROUND3_SCHNORR_P, EGS_SECP256K1, newn);
+
+ MPC_reshare_round3 r3[newn];
+
+ for (i = 0; i < newn; i++)
+ {
+ r3[i].SCHNORR_C = ROUND3_SCHNORR_C + i;
+ r3[i].SCHNORR_P = ROUND3_SCHNORR_P + i;
+ }
+
+ // Keygen Session memory
+ char id[IDLEN];
+ octet ID = {0, sizeof(id), id};
+
+ char as_w[oldt][EGS_SECP256K1];
+ char as_wg[oldt][EFS_SECP256K1 + 1];
+
+ octet AS_W[oldt];
+ octet AS_WG[oldt];
+
+ init_octets((char *)as_w, AS_W, EGS_SECP256K1, oldt);
+ init_octets((char *)as_wg, AS_WG, EFS_SECP256K1 + 1, oldt);
+
+ MPC_reshare_additive_shares shares[oldt];
+
+ for (i = 0; i < oldt; i++)
+ {
+ shares[i].W = AS_W + i;
+ shares[i].WG = AS_WG + i;
+ }
+
+ MPC_reshare_session s;
+
+ s.ID = &ID;
+ s.shares = shares;
+ s.old_party = old_p;
+ s.new_party = new_p;
+ s.round1 = r1;
+ s.round2 = r2;
+ s.round3 = r3;
+
+ /* Agree on session ID for keygen */
+ OCT_rand(s.ID, RNG, s.ID->max);
+
+ printf("\n *** Keygen ***\n");
+
+ /* Round 1 - Commit to old PK shares */
+
+ printf("\nRound 1 - Old party - Commit to old PK shares\n");
+
+ for (i = 0; i < oldt; i++)
+ {
+ MPC_reshare_round1_commit(RNG, &s, i);
+ printf("\n");
+ }
+
+ /* Round 2 - Old Party - Compute VSS shares and checks */
+
+ printf("\nRound 2 - Old Party - Generate Schnorr Proof, compute VSS Shares and Checks\n");
+
+ for (i = 0; i < oldt; i++)
+ {
+ MPC_reshare_round2_vss(RNG, &s, i);
+
+ printf("\n");
+ }
+
+ /* Round 2 - New Party - Verify VSS Shares and combine them */
+
+ printf("\nRound 2 - New Party - Combine VSS Shares and check Schnorr Proof\n");
+
+ for (i = 0; i < newn; i++)
+ {
+ rc = MPC_reshare_round2_compose(&s, i);
+ if (rc != MPC_OK)
+ {
+ return rc;
+ }
+
+ printf("\n");
+ }
+
+ /* Round 3 - New Party - Generate Proofs for Key Material */
+
+ printf("\nRound 3 - New Party - Generate additional key material and Proofs\n");
+
+ for (i = 0; i < newn; i++)
+ {
+ MPC_reshare_round3_proofs(RNG, &s, i);
+ printf("\n");
+ }
+
+ /* Round 3 - New Party - Verify Proofs for Key Material */
+
+ printf("\n\nRound 3 - New Party - Verify Proofs for Key Material\n");
+
+ for (i = 0; i < newn; i++)
+ {
+ rc = MPC_reshare_round3_verify(&s, i);
+ if (rc != MPC_OK)
+ {
+ return rc;
+ }
+
+ printf("\n");
+ }
+
+ /* The old party deletes its key material
+ *
+ * All the material in the player skm must be cleaned, except
+ * for the X share, which may be left alone.
+ *
+ * Not doing it here so the resharing can be verified manually
+ * in the main
+ */
+ printf("\nThe old party can now delete the old key material\n");
+
+ return MPC_OK;
+}
+
+void usage(char *name)
+{
+ printf("Usage: %s t n t1 n2\n", name);
+ printf("Run a resharing from a (t, n) to a (t1, n1)\n");
+ printf("\n");
+ printf(" t Old threshold. 2 <= t <= n\n");
+ printf(" n Old number of participants. t <= n\n");
+ printf(" t1 New threshold. 2 <= t1 <= n\n");
+ printf(" n1 New number of participants. t1 <= n\n");
+ printf("\n");
+ printf("Example:\n");
+ printf(" %s 3 4 5 6\n", name);
+}
+
+int main(int argc, char *argv[])
+{
+ int i, t, n, t1, n1, rc;
+
+ /* Read arguments */
+ if (argc != 5)
+ {
+ usage(argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ t = atoi(argv[1]);
+ n = atoi(argv[2]);
+
+ if (t < 2 || n < 2 || t > n)
+ {
+ usage(argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ t1 = atoi(argv[3]);
+ n1 = atoi(argv[4]);
+
+ if (t1 < 2 || n1 < 2 || t1 > n1)
+ {
+ usage(argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ /* Memory setup */
+
+ // Old Party
+ char old_player_ids[n][IDLEN];
+ char old_player_pks[n][EFS_SECP256K1 + 1];
+ char old_player_skx[n][EGS_SECP256K1];
+ char old_player_sky[n][EGS_SECP256K1];
+ octet OLD_PLAYER_IDS[n];
+ octet OLD_PLAYER_PKS[n];
+ octet OLD_PLAYER_SKX[n];
+ octet OLD_PLAYER_SKY[n];
+
+ init_octets((char *)old_player_ids, OLD_PLAYER_IDS, IDLEN, n);
+ init_octets((char *)old_player_pks, OLD_PLAYER_PKS, EFS_SECP256K1 + 1, n);
+ init_octets((char *)old_player_skx, OLD_PLAYER_SKX, EGS_SECP256K1, n);
+ init_octets((char *)old_player_sky, OLD_PLAYER_SKY, EGS_SECP256K1, n);
+
+ MPC_player old_players[n];
+
+ for (i = 0; i < n; i++)
+ {
+ old_players[i].ID = OLD_PLAYER_IDS + i;
+ old_players[i].pkm.PK = OLD_PLAYER_PKS + i;
+ old_players[i].skm.SKX = OLD_PLAYER_SKX + i;
+ old_players[i].skm.SKY = OLD_PLAYER_SKY + i;
+ }
+
+ MPC_party old_p = {t, n, old_players};
+
+ // New Party
+
+ char new_player_ids[n1][IDLEN];
+ char new_player_pks[n1][EFS_SECP256K1 + 1];
+ char new_player_spks[n1][EFS_SECP256K1 + 1];
+ char new_player_skx[n1][EGS_SECP256K1];
+ char new_player_sky[n1][EGS_SECP256K1];
+ octet NEW_PLAYER_IDS[n1];
+ octet NEW_PLAYER_PKS[n1];
+ octet NEW_PLAYER_SPKS[n1];
+ octet NEW_PLAYER_SKX[n1];
+ octet NEW_PLAYER_SKY[n1];
+
+ init_octets((char *)new_player_ids, NEW_PLAYER_IDS, IDLEN, n1);
+ init_octets((char *)new_player_pks, NEW_PLAYER_PKS, EFS_SECP256K1 + 1, n1);
+ init_octets((char *)new_player_spks, NEW_PLAYER_SPKS, EFS_SECP256K1 + 1, n1);
+ init_octets((char *)new_player_skx, NEW_PLAYER_SKX, EGS_SECP256K1, n1);
+ init_octets((char *)new_player_sky, NEW_PLAYER_SKY, EGS_SECP256K1, n1);
+
+ MPC_player new_players[n1];
+
+ for (i = 0; i < n1; i++)
+ {
+ new_players[i].ID = NEW_PLAYER_IDS + i;
+ new_players[i].pkm.PK = NEW_PLAYER_PKS + i;
+ new_players[i].pkm.SPK = NEW_PLAYER_SPKS + i;
+ new_players[i].skm.SKX = NEW_PLAYER_SKX + i;
+ new_players[i].skm.SKY = NEW_PLAYER_SKY + i;
+ }
+
+ MPC_party new_p = {t1, n1, new_players};
+
+ // Deterministic RNG for example
+ char seed[32] = {0};
+ csprng RNG;
+ RAND_seed(&RNG, 32, seed);
+
+ // Assign IDs to players
+ for (i = 0; i < n; i++)
+ {
+ OCT_rand(OLD_PLAYER_IDS+i, &RNG, IDLEN);
+ }
+
+ for (i = 0; i < n1; i++)
+ {
+ OCT_rand(NEW_PLAYER_IDS+i, &RNG, IDLEN);
+ }
+
+ printf("MPC resharing example\n");
+
+ // Minimal Key Setup for old party
+ rc = trusted_key_setup(&RNG, &old_p);
+ if (rc != MPC_OK)
+ {
+ exit(EXIT_FAILURE);
+ }
+
+ // Resharing
+ rc = reshare(&RNG, &old_p, &new_p);
+ if (rc != MPC_OK)
+ {
+ exit(EXIT_FAILURE);
+ }
+
+ // Check the full SK is the same
+ char old_sk[EGS_SECP256K1];
+ char new_sk[EGS_SECP256K1];
+ octet OLD_SK = {0, sizeof(old_sk), old_sk};
+ octet NEW_SK = {0, sizeof(new_sk), new_sk};
+
+ SSS_shares old_shares = {OLD_PLAYER_SKX, OLD_PLAYER_SKY};
+ SSS_shares new_shares = {NEW_PLAYER_SKX, NEW_PLAYER_SKY};
+
+ SSS_recover_secret(t, &old_shares, &OLD_SK);
+ SSS_recover_secret(t1, &new_shares, &NEW_SK);
+
+ if (!OCT_comp(&OLD_SK, &NEW_SK))
+ {
+ printf("ERROR Old Key does not match New Key\n");
+ exit(EXIT_FAILURE);
+ }
+
+ printf("\nDone\n");
+}
diff --git a/examples/example_gg20_zkp_phase3.c b/examples/example_gg20_zkp_phase3.c
new file mode 100644
index 0000000..0e882f0
--- /dev/null
+++ b/examples/example_gg20_zkp_phase3.c
@@ -0,0 +1,137 @@
+/*
+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 "amcl/gg20_zkp.h"
+
+/* Example of GG20 Phase 3 ZKP */
+
+char *S_hex = "00f1f45c44eb4298562677dfc945064ac5d45d683ec2d87efbd2f527bb5a768c";
+char *L_hex = "ab5aa1e7740f849b974fcaaa98840d828a42b16dd59be32f39e3c637730ee9e4";
+
+char *V_hex = "02879452f0c552b01c2cc91101062ca02a1ff3eab1e9c18873992670198bf54f3e";
+
+int main()
+{
+ int rc;
+
+ GG20_ZKP_rv r;
+ GG20_ZKP_proof p;
+
+ char id[32];
+ octet ID = {0, sizeof(id), id};
+
+ char ad[32];
+ octet AD = {0, sizeof(ad), ad};
+
+ char s[GGS_SECP256K1];
+ octet S = {0, sizeof(s), s};
+
+ char l[GGS_SECP256K1];
+ octet L = {0, sizeof(l), l};
+
+ char v[GFS_SECP256K1+1];
+ octet V = {0, sizeof(v), v};
+
+ char c[GFS_SECP256K1+1];
+ octet C = {0, sizeof(c), c};
+
+ char e[GGS_SECP256K1];
+ octet E = {0, sizeof(e), e};
+
+ char t[GGS_SECP256K1];
+ octet T = {0, sizeof(t), t};
+
+ char u[GGS_SECP256K1];
+ octet U = {0, sizeof(u), u};
+
+ // Deterministic RNG for testing
+ char seed[32] = {0};
+ csprng RNG;
+ RAND_seed(&RNG, 32, seed);
+
+ // Generate ID and AD
+ OCT_rand(&ID, &RNG, ID.len);
+ OCT_rand(&AD, &RNG, AD.len);
+
+ // Load hex values
+ OCT_fromHex(&S, S_hex);
+ OCT_fromHex(&L, L_hex);
+ OCT_fromHex(&V, V_hex);
+
+ printf("Prove knowledge of s, l s.t V = s.G + l.H\n");
+ printf("\tS = ");
+ OCT_output(&S);
+ printf("\tL = ");
+ OCT_output(&L);
+ printf("\tV = ");
+ OCT_output(&V);
+
+ // Commitment Phase
+ GG20_ZKP_phase3_commit(&RNG, &r, &C);
+
+ printf("\n[Alice] Compute commitment");
+ printf("\n\t\tA = ");
+ BIG_256_56_output(r.a);
+ printf("\n\t\tB = ");
+ BIG_256_56_output(r.b);
+ printf("\n\t\tC = ");
+ OCT_output(&C);
+
+ GG20_ZKP_phase3_challenge(&V, &C, &ID, &AD, &E);
+
+ printf("\n[Alice] Comupte pseudo random challenge");
+ printf("\n\t\tE = ");
+ OCT_output(&E);
+
+ // Proof Phase
+ GG20_ZKP_phase3_prove(&r, &E, &S, &L, &p);
+ GG20_ZKP_proof_toOctets(&T, &U, &p);
+
+ printf("\n[Alice] Compute proof and export it to octets for transmission");
+ printf("\n\t\tT = ");
+ OCT_output(&T);
+ printf("\t\tU = ");
+ OCT_output(&U);
+
+ // Clean random values used for proof
+ GG20_ZKP_rv_kill(&r);
+
+ // Verification Phase - compute pseudorandom challenge and verify proof
+ GG20_ZKP_phase3_challenge(&V, &C, &ID, &AD, &E);
+
+ printf("\n[Bob ] Compute pseudo random challenge");
+ printf("\n\t\tE = ");
+ OCT_output(&E);
+
+ rc = GG20_ZKP_phase3_verify(&V, &C, &E, &p);
+
+ printf("\n[Bob ] Verify proof\n");
+
+ if (rc == GG20_ZKP_OK)
+ {
+ printf("Success!\n");
+ }
+ else
+ {
+ printf("Failure!\n");
+ exit(EXIT_FAILURE);
+ }
+
+ exit(EXIT_SUCCESS);
+}
\ No newline at end of file
diff --git a/examples/example_gg20_zkp_phase6.c b/examples/example_gg20_zkp_phase6.c
new file mode 100644
index 0000000..1dee659
--- /dev/null
+++ b/examples/example_gg20_zkp_phase6.c
@@ -0,0 +1,165 @@
+/*
+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 "amcl/gg20_zkp.h"
+
+/* Example of GG20 Phase 6 ZKP */
+
+char *S_hex = "843b282505357e075bd98104f42fe7ea6b41310da7c769b4c402442c1ede922b";
+char *L_hex = "584edf9db99551ff2e0d56218a44fea0943032f7864b8359c213ec36465512c5";
+
+char *ECPR_hex = "03e03cda61f087f9ba381695dc816a4ca42f38bbfc3fc88ffe897594b94ee7b80b";
+char *ECPT_hex = "02863528287942ab88dec016c2e1993bf9e459ffcbfcc48c25ef68f2ec750e55a8";
+char *ECPS_hex = "02ef03c8ecb7cf65b58d85f368c5fc2725b4e4fe93306f98cf53f8e1531cea2bc4";
+
+int main()
+{
+ int rc;
+
+ GG20_ZKP_rv r;
+ GG20_ZKP_phase6_commitment c;
+ GG20_ZKP_proof p;
+
+ char id[32];
+ octet ID = {0, sizeof(id), id};
+
+ char ad[32];
+ octet AD = {0, sizeof(ad), ad};
+
+ char s[GGS_SECP256K1];
+ octet S = {0, sizeof(s), s};
+
+ char l[GGS_SECP256K1];
+ octet L = {0, sizeof(l), l};
+
+ char ecpr[GFS_SECP256K1+1];
+ octet ECPR = {0, sizeof(ecpr), ecpr};
+
+ char ecpt[GFS_SECP256K1+1];
+ octet ECPT = {0, sizeof(ecpt), ecpt};
+
+ char ecps[GFS_SECP256K1+1];
+ octet ECPS = {0, sizeof(ecps), ecps};
+
+ char alpha[GFS_SECP256K1+1];
+ octet ALPHA = {0, sizeof(alpha), alpha};
+
+ char beta[GFS_SECP256K1+1];
+ octet BETA = {0, sizeof(beta), beta};
+
+ char e[GGS_SECP256K1];
+ octet E = {0, sizeof(e), e};
+
+ char t[GGS_SECP256K1];
+ octet T = {0, sizeof(t), t};
+
+ char u[GGS_SECP256K1];
+ octet U = {0, sizeof(u), u};
+
+ // Deterministic RNG for testing
+ char seed[32] = {0};
+ csprng RNG;
+ RAND_seed(&RNG, 32, seed);
+
+ // Generate ID and AD
+ OCT_rand(&ID, &RNG, ID.len);
+ OCT_rand(&AD, &RNG, AD.len);
+
+ // Load hex values
+ OCT_fromHex(&S, S_hex);
+ OCT_fromHex(&L, L_hex);
+
+ OCT_fromHex(&ECPR, ECPR_hex);
+ OCT_fromHex(&ECPT, ECPT_hex);
+ OCT_fromHex(&ECPS, ECPS_hex);
+
+ printf("Prove knowledge of s, l s.t V = s.G + l.H, S = s.R\n");
+ printf("\tS = ");
+ OCT_output(&S);
+ printf("\tL = ");
+ OCT_output(&L);
+ printf("\tECPR = ");
+ OCT_output(&ECPR);
+ printf("\tECPT = ");
+ OCT_output(&ECPT);
+ printf("\tECPS = ");
+ OCT_output(&ECPS);
+
+ // Commitment Phase
+ rc = GG20_ZKP_phase6_commit(&RNG, &ECPR, &r, &c);
+ if (rc != GG20_ZKP_OK)
+ {
+ printf("FAILURE Invalid R\n");
+ exit(EXIT_FAILURE);
+ }
+
+ GG20_ZKP_phase6_commitment_toOctets(&ALPHA, &BETA, &c);
+
+ printf("\n[Alice] Compute commitment and export it to octets for transmission");
+ printf("\n\t\tA = ");
+ BIG_256_56_output(r.a);
+ printf("\n\t\tB = ");
+ BIG_256_56_output(r.b);
+ printf("\n\t\tALPHA = ");
+ OCT_output(&ALPHA);
+ printf("\t\tBETA = ");
+ OCT_output(&BETA);
+
+ GG20_ZKP_phase6_challenge(&ECPR, &ECPT, &ECPS, &c, &ID, &AD, &E);
+
+ printf("\n[Alice] Comupte pseudo random challenge");
+ printf("\n\t\tE = ");
+ OCT_output(&E);
+
+ // Proof Phase
+ GG20_ZKP_phase6_prove(&r, &E, &S, &L, &p);
+ GG20_ZKP_proof_toOctets(&T, &U, &p);
+
+ printf("\n[Alice] Compute proof and export it to octets for transmission");
+ printf("\n\t\tT = ");
+ OCT_output(&T);
+ printf("\t\tU = ");
+ OCT_output(&U);
+
+ // Clean random values used for proof
+ GG20_ZKP_rv_kill(&r);
+
+ // Verification Phase - compute pseudorandom challenge and verify proof
+ GG20_ZKP_phase6_challenge(&ECPR, &ECPT, &ECPS, &c, &ID, &AD, &E);
+
+ printf("\n[Bob ] Compute pseudo random challenge");
+ printf("\n\t\tE = ");
+ OCT_output(&E);
+
+ rc = GG20_ZKP_phase6_verify(&ECPR, &ECPT, &ECPS, &c, &E, &p);
+
+ printf("\n[Bob ] Verify proof\n");
+
+ if (rc == GG20_ZKP_OK)
+ {
+ printf("Success!\n");
+ }
+ else
+ {
+ printf("Failure!\n");
+ exit(EXIT_FAILURE);
+ }
+
+ exit(EXIT_SUCCESS);
+}
\ No newline at end of file
diff --git a/include/amcl/gg20_zkp.h b/include/amcl/gg20_zkp.h
new file mode 100644
index 0000000..2b72e35
--- /dev/null
+++ b/include/amcl/gg20_zkp.h
@@ -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.
+*/
+
+/**
+ * @file gg20_zkp.h
+ * @brief Gennaro 2020 - Schnorr-like proofs declarations
+ *
+ */
+
+#ifndef GG20_ZKP_H
+#define GG20_ZKP_H
+
+#include "amcl/amcl.h"
+#include "amcl/big_256_56.h"
+#include "amcl/ecp_SECP256K1.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/* Field size is assumed to be greater than or equal to group size */
+
+#define GGS_SECP256K1 MODBYTES_256_56 /**< ECP Group Size */
+#define GFS_SECP256K1 MODBYTES_256_56 /**< ECP Field Size */
+
+#define GG20_ZKP_OK 0 /**< Valid proof */
+#define GG20_ZKP_FAIL 141 /**< Invalid proof */
+#define GG20_ZKP_INVALID_ECP 142 /**< Not a valid point on the curve */
+
+/* Structs for the GG20 ZKPs */
+
+/*! \brief Random values for both Phase 3 and Phase 6 ZKP commitment */
+typedef struct
+{
+ BIG_256_56 a; /**< Randomness for the G commitment */
+ BIG_256_56 b; /**< Randomness for the H commitment */
+} GG20_ZKP_rv;
+
+/*! \brief Proof for both Phase 3 and Phase 6 */
+typedef struct
+{
+ BIG_256_56 t; /**< Proof for the s component */
+ BIG_256_56 u; /**< Proof for the l component */
+} GG20_ZKP_proof;
+
+/*! \brief Commitment for the Phase 6 ZKP */
+typedef struct
+{
+ ECP_SECP256K1 ALPHA; /**< Commitment for the additional DLOG proof */
+ ECP_SECP256K1 BETA; /**< Commitment for the base double DLOG proof*/
+} GG20_ZKP_phase6_commitment;
+
+/* ROM for SECP256K1 alternative generator */
+
+/*! \brief Read the alternative generator for the proof from ROM
+ *
+ * Alternative generator of unknown DLOG w.r.t. the standard generator
+ * for SECP256K1.
+ *
+ * @param G Destination ECP
+ */
+extern void GG20_ZKP_generator_2(ECP_SECP256K1 *G);
+
+/* Octet functions */
+
+/*! \brief Import a Proof values from octets
+ *
+ * @param p Destination Proof
+ * @param T Octet with the t value of the proof. GGS_SECP256K1 long
+ * @param U Octet with the u value of the proof. GGS_SECP256K1 long
+ */
+extern void GG20_ZKP_proof_fromOctets(GG20_ZKP_proof *p, octet *T, octet *U);
+
+/*! \brief Exprot a Proof to octets
+ *
+ * @param T Destination octet for the t value of the proof. GGS_SECP256K1 long
+ * @param U Destination octet for the u value of the proof. GGS_SECP256K1 long
+ * @param p Proof to export
+ */
+extern void GG20_ZKP_proof_toOctets(octet *T, octet *U, GG20_ZKP_proof *p);
+
+/*! \brief Import a Phase 6 Commitment from octets
+ *
+ * @param c Destination Commitment
+ * @param ALPHA Octet with the alpha value of the commtiment. 1 + GFS_SECP256K1 long
+ * @param BETA Octet with the beta value of the commtiment. 1 + GFS_SECP256K1 long
+ * @return GG20_ZKP_OK if ALPHA and BETA are valid ECPs, GG20_ZKP_INVALID_ECP otherwise
+ */
+extern int GG20_ZKP_phase6_commitment_fromOctets(GG20_ZKP_phase6_commitment *c, octet *ALPHA, octet *BETA);
+
+/*! \brief Export a Phase 6 Commitment to octets
+ *
+ * @param ALPHA Destination octet for the alpha value of the commtiment. 1 + GFS_SECP256K1 long
+ * @param BETA Destination octet for the beta value of the commtiment. 1 + GFS_SECP256K1 long
+ * @param c Destination Commitment
+ */
+extern void GG20_ZKP_phase6_commitment_toOctets(octet *ALPHA, octet *BETA, GG20_ZKP_phase6_commitment *c);
+
+/* Cleanup functions */
+
+/*! \brief Clean the random values for a GG20 ZKP
+ *
+ * @param r Random values to clean
+ */
+extern void GG20_ZKP_rv_kill(GG20_ZKP_rv *r);
+
+/* Phase 3 ZKP API */
+
+/*! \brief Generate a commitment for the proof
+ *
+ * @param RNG CSPRNG to use for commitment
+ * @param r Secret values used for the commitment. If RNG is NULL this is read
+ * @param C Public commitment value. An ECP in compressed form
+ */
+extern void GG20_ZKP_phase3_commit(csprng *RNG, GG20_ZKP_rv *r, octet *C);
+
+/*! \brief Generate the challenge for the proof
+ *
+ * Compute the challenge for the proof.
+ * The challenge is inspired by RFC8235#section-3.3, with the needed tweak to
+ * also bind the secondary generator H
+ * Returns H(G, H, C, V, ID[, AD])
+ *
+ * @param V Public ECP result of the DLOG. V = s.G + l.H. Compressed form
+ * @param C Public commitment value. Compressed form
+ * @param ID Prover unique identifier
+ * @param AD Additional data to bind in the challenge - Optional
+ * @param E Challenge generated
+ */
+extern void GG20_ZKP_phase3_challenge(const octet *V, const octet *C, const octet* ID, const octet *AD, octet *E);
+
+/*! \brief Generate the proof for the given commitment and challenge
+ *
+ * @param r Random values used in the commitment
+ * @param E Pseudorandom challenge
+ * @param S Secret exponent of the double DLOG. V = s.G + l.H
+ * @param L Secret exponent of the double DLOG. V = s.G + l.H
+ * @param p Proof for the ZKP
+ */
+extern void GG20_ZKP_phase3_prove(GG20_ZKP_rv *r, const octet *E, const octet *S, const octet *L, GG20_ZKP_proof *p);
+
+/*! \brief Verify the proof of knowledge for the DLOG
+ *
+ * @param V Public ECP of the DLOG. V = s.G + l.H. Compressed form
+ * @param C Commitment value received from the prover
+ * @param E Pseudorandom challenge
+ * @param p Proof for the ZKP
+ * @return GG20_ZKP_OK if the prove is valid or an error code
+ */
+extern int GG20_ZKP_phase3_verify(octet *V, octet *C, const octet *E, GG20_ZKP_proof *p);
+
+/* Phase 6 ZKP API */
+
+/*! \brief Generate a commitment for the proof
+ *
+ * @param RNG CSPRNG to use for commitment
+ * @param R DLOG Base for additional consistency Proof
+ * @param r Random values for the commitment. If RNG is NULL this is read
+ * @param c Public commitment value
+ * @return GG20_ZKP_INVALID_ECP if R is not a valid ECP, GG20_ZKP_OK otherwise
+ */
+extern int GG20_ZKP_phase6_commit(csprng *RNG, octet *R, GG20_ZKP_rv *r, GG20_ZKP_phase6_commitment *c);
+
+/*! \brief Generate the challenge for the proof
+ *
+ * Compute the challenge for the proof.
+ * The challenge is inspired by RFC8235#section-3.3, with the needed tweak to
+ * also bind the secondary generator H and the base point R, as well as the
+ * additional commitment value BETA.
+ *
+ * Returns H(G, H, R, ALPHA, BETA, T, S, ID[, AD])
+ *
+ * @param R Base of the additional DLOG S = s.R. Compressed form
+ * @param T Public ECP result of the additional DLOG S = s.R. Compressed form
+ * @param S Public ECP result of the DLOG V = s.G + l.H. Compressed form
+ * @param c Public commitment values
+ * @param ID Prover unique identifier
+ * @param AD Additional data to bind in the challenge - Optional
+ * @param E Challenge generated
+ */
+void GG20_ZKP_phase6_challenge(const octet *R, const octet *T, const octet *S, GG20_ZKP_phase6_commitment *c, const octet *ID, const octet *AD, octet *E);
+
+/*! \brief Generate the proof for the given commitment and challenge
+ *
+ * @param r Random values used in the commitment
+ * @param E Pseudorandom challenge
+ * @param S Secret exponent of the double DLOG. T = s.G + l.H
+ * @param L Secret exponent of the double DLOG. T = s.G + l.H
+ * @param p Proof for the ZKP
+ */
+extern void GG20_ZKP_phase6_prove(GG20_ZKP_rv *r, const octet *E, const octet *S, const octet *L, GG20_ZKP_proof *p);
+
+/*! \brief Verify the proof of knowledge for the DLOG
+ *
+ * @param R Base of the additional DLOG S = s.R. Compressed form
+ * @param T Public ECP result of the DLOG T = s.G + l.H. Compressed form
+ * @param S Public ECP result of the additional DLOG S = s.R. Compressed form
+ * @param c Received Phase6 commitment
+ * @param E Pseudorandom challenge
+ * @param p Received Phase6 proof
+ * @return GG20_ZKP_OK if the prove is valid or an error code
+ */
+int GG20_ZKP_phase6_verify(octet *R, octet *T, octet *S, GG20_ZKP_phase6_commitment *c, const octet *E, GG20_ZKP_proof *p);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/python/amcl/gg20_zkp.py b/python/amcl/gg20_zkp.py
new file mode 100644
index 0000000..b246bff
--- /dev/null
+++ b/python/amcl/gg20_zkp.py
@@ -0,0 +1,417 @@
+"""
+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.
+"""
+
+"""
+
+This module use cffi to access the c functions in the amcl_mpc library.
+
+"""
+
+import platform
+from . import core_utils
+
+_ffi = core_utils._ffi
+_ffi.cdef("""
+typedef struct {
+ BIG_256_56 a;
+ BIG_256_56 b;
+} GG20_ZKP_rv;
+
+typedef struct {
+ BIG_256_56 t;
+ BIG_256_56 u;
+} GG20_ZKP_proof;
+
+typedef struct {
+ ECP_SECP256K1 ALPHA;
+ ECP_SECP256K1 BETA;
+} GG20_ZKP_phase6_commitment;
+
+void GG20_ZKP_proof_fromOctets(GG20_ZKP_proof *p, octet *T, octet *U);
+void GG20_ZKP_proof_toOctets(octet *T, octet *U, GG20_ZKP_proof *p);
+int GG20_ZKP_phase6_commitment_fromOctets(GG20_ZKP_phase6_commitment *c, octet *ALPHA, octet *BETA);
+void GG20_ZKP_phase6_commitment_toOctets(octet *ALPHA, octet *BETA, GG20_ZKP_phase6_commitment *c);
+
+void GG20_ZKP_rv_kill(GG20_ZKP_rv *r);
+
+void GG20_ZKP_phase3_commit(csprng *RNG, GG20_ZKP_rv *r, octet *C);
+void GG20_ZKP_phase3_challenge(const octet *V, const octet *C, const octet* ID, const octet *AD, octet *E);
+void GG20_ZKP_phase3_prove(GG20_ZKP_rv *r, const octet *E, const octet *S, const octet *L, GG20_ZKP_proof *p);
+int GG20_ZKP_phase3_verify(octet *V, octet *C, const octet *E, GG20_ZKP_proof *p);
+
+int GG20_ZKP_phase6_commit(csprng *RNG, octet *R, GG20_ZKP_rv *r, GG20_ZKP_phase6_commitment *c);
+void GG20_ZKP_phase6_challenge(const octet *R, const octet *T, const octet *S, GG20_ZKP_phase6_commitment *c, const octet *ID, const octet *AD, octet *E);
+void GG20_ZKP_phase6_prove(GG20_ZKP_rv *r, const octet *E, const octet *S, const octet *L, GG20_ZKP_proof *p);
+int GG20_ZKP_phase6_verify(octet *R, octet *T, octet *S, GG20_ZKP_phase6_commitment *c, const octet *E, GG20_ZKP_proof *p);
+
+""")
+
+if (platform.system() == 'Windows'):
+ _libamcl_mpc = _ffi.dlopen("libamcl_mpc.dll")
+elif (platform.system() == 'Darwin'):
+ _libamcl_mpc = _ffi.dlopen("libamcl_mpc.dylib")
+else:
+ _libamcl_mpc = _ffi.dlopen("libamcl_mpc.so")
+
+# Constants
+EGS = 32 # Size of a Z/qZ element in bytes
+EFS = 32 # Size of a Fp element in bytes
+PTS = EFS + 1 # Size of a ECP in compressed form
+
+OK = 0
+FAIL = 141
+INVALID_ECP = 142
+
+
+# Octet functions
+
+
+def proof_from_octets(t, u):
+ """ Import a proof from its components octets
+
+ Args::
+ t : t component of the proof
+ u : u component of the proof
+
+ Returns::
+ p : pointer to the proof
+
+ """
+ p = _ffi.new('GG20_ZKP_proof*')
+
+ t_oct, t_val = core_utils.make_octet(None, t)
+ u_oct, u_val = core_utils.make_octet(None, u)
+ _ = t_val, u_val # Suppress warnings
+
+ _libamcl_mpc.GG20_ZKP_proof_fromOctets(p, t_oct, u_oct)
+
+ return p
+
+
+def proof_to_octets(p):
+ """ Export the proof to octets
+
+ Args::
+ p : pointer to the proof
+
+ Returns::
+ t : t component of the proof
+ u : u component of the proof
+
+ """
+ t_oct, t_val = core_utils.make_octet(EGS)
+ u_oct, u_val = core_utils.make_octet(EGS)
+ _ = t_val, u_val # Suppress warnings
+
+ _libamcl_mpc.GG20_ZKP_proof_toOctets(t_oct, u_oct, p)
+
+ t = core_utils.to_str(t_oct)
+ u = core_utils.to_str(u_oct)
+
+ return t, u
+
+
+def phase6_commitment_from_octets(alpha, beta):
+ """ Import a Phase 6 commitment from its components octets
+
+ Args::
+ alpha : commitment for the additional DLOG
+ beta : commitment for the double DLOG
+
+ Returns::
+ c : pointer to the commitment. NULL if rc is not OK
+ rc : OK or an error code
+
+ """
+ c = _ffi.new('GG20_ZKP_phase6_commitment*')
+
+ alpha_oct, alpha_val = core_utils.make_octet(None, alpha)
+ beta_oct, beta_val = core_utils.make_octet(None, beta)
+ _ = alpha_val, beta_val # Suppress warnings
+
+ rc = _libamcl_mpc.GG20_ZKP_phase6_commitment_fromOctets(c, alpha_oct, beta_oct)
+ if rc != OK:
+ c = _ffi.NULL
+
+ return c, rc
+
+
+def phase6_commitment_to_octets(c):
+ """ Export a Phase 6 commitment to octets
+
+ Args::
+ c : pointer to the commitment
+
+ Returns::
+ t : t component of the proof
+ u : u component of the proof
+
+ """
+ alpha_oct, alpha_val = core_utils.make_octet(PTS)
+ beta_oct, beta_val = core_utils.make_octet(PTS)
+ _ = alpha_val, beta_val # Suppress warnings
+
+ _libamcl_mpc.GG20_ZKP_phase6_commitment_toOctets(alpha_oct, beta_oct, c)
+
+ alpha = core_utils.to_str(alpha_oct)
+ beta = core_utils.to_str(beta_oct)
+
+ return alpha, beta
+
+
+# Cleanup functions
+
+
+def rv_kill(rv):
+ """ Clean memory for the commitment random values
+
+ Args::
+ rv : the random values to clean
+ """
+
+ _libamcl_mpc.GG20_ZKP_rv_kill(rv)
+
+
+# GG20 ZKP Phase 3
+
+
+def phase3_commit(rng, rv=None):
+ ''' Generate a commitment for the GG20 Phase 3 ZKP
+
+ Compute random values and commitment. If r is given as input, use
+ the given values instead of generating random ones.
+
+ Args::
+ rng : Pointer to csprng
+ rv : Pointer to deterministic values for commitment. Optional
+
+ Returns::
+ r : Pointer to random values used in commitments
+ C : commitment
+ '''
+
+ if rv is None:
+ rv = _ffi.new('GG20_ZKP_rv*')
+ else:
+ rng = _ffi.NULL
+
+ c_oct, _ = core_utils.make_octet(PTS)
+
+ _libamcl_mpc.GG20_ZKP_phase3_commit(rng, rv, c_oct)
+
+ return rv, core_utils.to_str(c_oct)
+
+
+def phase3_challenge(V, C, ID, AD=None):
+ """ Bind public parameters and commitment in challenge
+
+ Args::
+ V : Public ECP of the double DLOG
+ C : Generated Commitment
+ ID : Unique user identifier
+ AD : Additional data to bind in the challenge. Optional
+
+ Returns::
+ E : Pseudorandom challenge
+ """
+
+ if AD is None:
+ ad_oct = _ffi.NULL
+ else:
+ ad_oct, ad_val = core_utils.make_octet(None, AD)
+ _ = ad_val # Suppress warning
+
+ v_oct, v_val = core_utils.make_octet(None, V)
+ c_oct, c_val = core_utils.make_octet(None, C)
+ id_oct, id_val = core_utils.make_octet(None, ID)
+ e_oct, e_val = core_utils.make_octet(EGS)
+ _ = v_val, c_val, id_val, e_val # Suppress warning
+
+ _libamcl_mpc.GG20_ZKP_phase3_challenge(v_oct, c_oct, id_oct, ad_oct, e_oct)
+
+ return core_utils.to_str(e_oct)
+
+
+def phase3_prove(r, e, s, l):
+ """ Generate proof from commitment random values and ZKP secret input
+
+ Args::
+ r : Pointer to commitment random values from commitment
+ e : pseudorandom challenge
+ s : secret exponent of the double DLOG for G
+ l : secret exponent of the double DLOG for H
+
+ Returns::
+ p : Pointer to generated proof
+ """
+
+ e_oct, e_val = core_utils.make_octet(None, e)
+ s_oct, s_val = core_utils.make_octet(None, s)
+ l_oct, l_val = core_utils.make_octet(None, l)
+ _ = e_val, s_val, l_val # Suppress warning
+
+ p = _ffi.new('GG20_ZKP_proof*')
+
+ _libamcl_mpc.GG20_ZKP_phase3_prove(r, e_oct, s_oct, l_oct, p)
+
+ return p
+
+
+def phase3_verify(V, C, e, p):
+ ''' Verify a GG20 ZKP
+
+ Args::
+ V : Public ECP of the DLOG
+ C : Received Commitment
+ e : Pesudo random challenge
+ p : Pointer to Received Proof
+
+ Returns::
+ ok : OK or an error code
+ '''
+
+ v_oct, v_val = core_utils.make_octet(None, V)
+ c_oct, c_val = core_utils.make_octet(None, C)
+ e_oct, e_val = core_utils.make_octet(None, e)
+ _ = v_val, c_val, e_val # Suppress warnings
+
+ rc = _libamcl_mpc.GG20_ZKP_phase3_verify(v_oct, c_oct, e_oct, p)
+
+ return rc
+
+
+# GG20 ZKP Phase 6
+
+
+def phase6_commit(rng, R, rv=None):
+ ''' Generate a commitment for the GG20 Phase 6 ZKP
+
+ Compute random values and commitment. If rv is given as input, use
+ the given values instead of generating random ones.
+
+ Args::
+ rng : Pointer to csprng
+ R : Base of the additional DLOG
+ rv : Pointer to deterministic values for commitment. Optional
+
+ Returns::
+ rv : Pointer to random values used in commitments
+ c : Pointer to the commitment
+ rc : OK or an error code
+ '''
+
+ if rv is None:
+ rv = _ffi.new('GG20_ZKP_rv*')
+ else:
+ rng = _ffi.NULL
+
+ c = _ffi.new('GG20_ZKP_phase6_commitment*')
+ r_oct, _ = core_utils.make_octet(None, R)
+
+ rc = _libamcl_mpc.GG20_ZKP_phase6_commit(rng, r_oct, rv, c)
+
+ if rc != OK:
+ rv = _ffi.NULL
+ c = _ffi.NULL
+
+ return rv, c, rc
+
+
+def phase6_challenge(R, T, S, c, ID, AD=None):
+ """ Bind public parameters and commitment in challenge.
+
+ Args::
+ R : Base ECP of the additional DLOG
+ T : Double DLOG public ECP
+ S : Additional DLOG public ECP
+ c : Pointer to generated Commitment
+ ID : Unique user identifier
+ AD : Additional data to bind in the challenge. Optional
+
+ Returns::
+ E : Pesudorandom challenge
+ """
+
+ if AD is None:
+ ad_oct = _ffi.NULL
+ else:
+ ad_oct, ad_val = core_utils.make_octet(None, AD)
+ _ = ad_val # Suppress warning
+
+ r_oct, r_val = core_utils.make_octet(None, R)
+ t_oct, t_val = core_utils.make_octet(None, T)
+ s_oct, s_val = core_utils.make_octet(None, S)
+ id_oct, id_val = core_utils.make_octet(None, ID)
+ e_oct, e_val = core_utils.make_octet(EGS)
+ _ = r_val, t_val, s_val, id_val, e_val # Suppress warning
+
+ _libamcl_mpc.GG20_ZKP_phase6_challenge(r_oct, t_oct, s_oct, c, id_oct, ad_oct, e_oct)
+
+ return core_utils.to_str(e_oct)
+
+
+def phase6_prove(r, e, s, l):
+ """ Generate proof from commitment random values and ZKP secret input
+
+ Args::
+ r : Pointer to commitment random values from commitment
+ e : pseudorandom challenge
+ s : secret exponent of the double DLOG for G
+ l : secret exponent of the double DLOG for H
+
+ Returns::
+ p : Pointer to generated proof
+ """
+
+ e_oct, e_val = core_utils.make_octet(None, e)
+ s_oct, s_val = core_utils.make_octet(None, s)
+ l_oct, l_val = core_utils.make_octet(None, l)
+ _ = e_val, s_val, l_val # Suppress warning
+
+ p = _ffi.new('GG20_ZKP_proof*')
+
+ _libamcl_mpc.GG20_ZKP_phase6_prove(r, e_oct, s_oct, l_oct, p)
+
+ return p
+
+
+def phase6_verify(R, T, S, c, e, p):
+ ''' Verify a GG20 ZKP
+
+ Args::
+ R : Base ECP of the additional DLOG
+ T : Double DLOG public ECP
+ S : Additional DLOG public ECP
+ c : Pointer to received Commitment
+ e : Pesudo random challenge
+ p : Pointer to Received Proof
+
+ Returns::
+ ok : OK or an error code
+ '''
+
+ r_oct, r_val = core_utils.make_octet(None, R)
+ t_oct, t_val = core_utils.make_octet(None, T)
+ s_oct, s_val = core_utils.make_octet(None, S)
+ e_oct, e_val = core_utils.make_octet(None, e)
+ _ = r_val, t_val, s_val, e_val # Suppress warnings
+
+ rc = _libamcl_mpc.GG20_ZKP_phase6_verify(r_oct, t_oct, s_oct, c, e_oct, p)
+
+ return rc
diff --git a/python/amcl/schnorr.py b/python/amcl/schnorr.py
index 49b57d3..5473ea7 100644
--- a/python/amcl/schnorr.py
+++ b/python/amcl/schnorr.py
@@ -37,13 +37,10 @@ extern int SCHNORR_verify(octet *V, octet *C, const octet *E, const octet *P);
if (platform.system() == 'Windows'):
_libamcl_mpc = _ffi.dlopen("libamcl_mpc.dll")
- _libamcl_curve_secp256k1 = _ffi.dlopen("libamcl_curve_SECP256K1.dll")
elif (platform.system() == 'Darwin'):
_libamcl_mpc = _ffi.dlopen("libamcl_mpc.dylib")
- _libamcl_curve_secp256k1 = _ffi.dlopen("libamcl_curve_SECP256K1.dylib")
else:
_libamcl_mpc = _ffi.dlopen("libamcl_mpc.so")
- _libamcl_curve_secp256k1 = _ffi.dlopen("libamcl_curve_SECP256K1.so")
# Constants
EGS = 32 # Size of a Z/qZ element in bytes
diff --git a/python/benchmark/bench_bc_setup.py b/python/benchmark/bench_bc_setup.py
new file mode 100755
index 0000000..47fc811
--- /dev/null
+++ b/python/benchmark/bench_bc_setup.py
@@ -0,0 +1,65 @@
+#!/usr/bin/env python3
+
+"""
+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.
+"""
+
+import os
+import sys
+from bench import time_func
+
+sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
+
+from amcl import core_utils
+from amcl import bit_commitment as bc
+
+seed_hex = "78d0fb6705ce77dee47d03eb5b9c5d30"
+
+p_hex = "CA5F37B7C0DDF6530B30A41116588218DE95F1F36B807FD7C28E4C467EE3F35967BC01D28B71F8A627A353675A81C86A1FF03DCECAF1686891183FA317BA34A4A1148D40A89F1F3AC0C200511C6CFE02342CD75354C25A2E069886DD4FB73BD365660D163F1282B143119AB8F375A73875EC16B634F52593B73BC6D875F2D3EF"
+q_hex = "C2FC545C1C803F6C7625FBC4ECF9355734D6B6058FD714816D3ECFB93F1F705C9CE90D4F8796A05148AB5ABC201F90889231CC6BF5F68ED15EE4D901F603930A280EEABF10C613BFCB67A816363C839EB902B02607EB48AB8325E2B72620D4D294A232803217090DFB50AF8C620D4679E77CE3053437ED518F4F68840DCF1AA3"
+
+if __name__ == "__main__":
+ p = bytes.fromhex(p_hex)
+ q = bytes.fromhex(q_hex)
+
+ seed = bytes.fromhex(seed_hex)
+ rng = core_utils.create_csprng(seed)
+
+ id = b'unique_identifier'
+ ad = b'additional_data'
+
+ # Generate quantities for benchmark
+ priv = bc.setup(rng, p=p, q=q)
+ pub = bc.priv_to_pub(priv)
+ proof = bc.setup_prove(rng, priv, id, ad=ad)
+ rc = bc.setup_verify(pub, proof, id, ad=ad)
+
+ assert rc == bc.OK
+
+ # Run benchmark
+ fncall = lambda: bc.setup(rng, p=p, q=q)
+ time_func("bc_setup ", fncall, unit="ms")
+
+ fncall = lambda: bc.priv_to_pub(priv)
+ time_func("bc_priv_to_pub ", fncall, unit="us")
+
+ fncall = lambda: bc.setup_prove(rng, priv, id, ad=ad)
+ time_func("bc_setup_prove ", fncall, unit="ms")
+
+ fncall = lambda: bc.setup_verify(pub, proof, id, ad=ad)
+ time_func("bc_setup_verify", fncall, unit="ms")
\ No newline at end of file
diff --git a/python/benchmark/bench_gg20_zkp.py b/python/benchmark/bench_gg20_zkp.py
new file mode 100755
index 0000000..d367de8
--- /dev/null
+++ b/python/benchmark/bench_gg20_zkp.py
@@ -0,0 +1,112 @@
+#!/usr/bin/env python3
+
+import os
+import sys
+from bench import time_func
+
+sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
+
+from amcl import core_utils, gg20_zkp
+
+
+seed_hex = "78d0fb6705ce77dee47d03eb5b9c5d30"
+
+l_hex = "584edf9db99551ff2e0d56218a44fea0943032f7864b8359c213ec36465512c5"
+s_hex = "843b282505357e075bd98104f42fe7ea6b41310da7c769b4c402442c1ede922b"
+
+R_hex = "03e03cda61f087f9ba381695dc816a4ca42f38bbfc3fc88ffe897594b94ee7b80b"
+T_hex = "02863528287942ab88dec016c2e1993bf9e459ffcbfcc48c25ef68f2ec750e55a8"
+S_hex = "02ef03c8ecb7cf65b58d85f368c5fc2725b4e4fe93306f98cf53f8e1531cea2bc4"
+
+ID = "unique_user_identifier".encode('utf-8')
+AD = "additional_data".encode('utf-8')
+
+if __name__ == "__main__":
+ seed = bytes.fromhex(seed_hex)
+ rng = core_utils.create_csprng(seed)
+
+ # Generate quantities for Phase 3 Benchmark
+ s = bytes.fromhex(s_hex)
+ l = bytes.fromhex(l_hex)
+ V = bytes.fromhex(T_hex)
+
+ rv, c = gg20_zkp.phase3_commit(rng)
+ e = gg20_zkp.phase3_challenge(V, c,ID, AD = AD)
+ p = gg20_zkp.phase3_prove(rv, e, s, l)
+ rc = gg20_zkp.phase3_verify(V, c, e, p)
+
+ assert rc == gg20_zkp.OK, "Error Setting up Phase 3 ZKP"
+
+ # Run Phase 3 ZKP Benchmark
+ print(" *** Phase 3 ZKP ***")
+
+ fncall = lambda: gg20_zkp.phase3_commit(rng, rv=rv)
+ time_func("phase3_commit ", fncall)
+
+ fncall = lambda: gg20_zkp.phase3_challenge(V, c,ID, AD = AD)
+ time_func("phase3_challenge", fncall)
+
+ fncall = lambda: gg20_zkp.phase3_prove(rv, e, s, l)
+ time_func("phase3_prove ", fncall)
+
+ fncall = lambda: gg20_zkp.phase3_verify(V, c, e, p)
+ time_func("phase3_verify ", fncall)
+
+ print("")
+
+ # Generate quantities for Phase 6 benchmark
+ R = bytes.fromhex(R_hex)
+ T = bytes.fromhex(T_hex)
+ S = bytes.fromhex(S_hex)
+
+ rv, c, rc = gg20_zkp.phase6_commit(rng, R)
+
+ assert rc == gg20_zkp.OK, "Error setting up Phase 6 Commit"
+
+ e = gg20_zkp.phase6_challenge(R, T, S, c, ID, AD=AD)
+ p = gg20_zkp.phase6_prove(rv, e, s, l)
+ rc = gg20_zkp.phase6_verify(R, T, S, c, e, p)
+
+ assert rc == gg20_zkp.OK, "Error Setting up Phase 6 ZKP"
+
+ # Run Phase 6 ZKP Benchmark
+ print(" *** Phase 6 ZKP ***")
+
+ fncall = lambda: gg20_zkp.phase6_commit(rng, R, rv=rv)
+ time_func("phase6_commit ", fncall)
+
+ fncall = lambda: gg20_zkp.phase6_challenge(R, T, S, c, ID, AD = AD)
+ time_func("phase6_challenge", fncall)
+
+ fncall = lambda: gg20_zkp.phase6_prove(rv, e, s, l)
+ time_func("phase6_prove ", fncall)
+
+ fncall = lambda: gg20_zkp.phase6_verify(R, T, S, c, e, p)
+ time_func("phase6_verify ", fncall)
+
+ # Generate quantities for additional benchmakrs
+ t, u = gg20_zkp.proof_to_octets(p)
+
+ alpha, beta = gg20_zkp.phase6_commitment_to_octets(c)
+ c, rc = gg20_zkp.phase6_commitment_from_octets(alpha, beta)
+ assert rc == gg20_zkp.OK, "Error setting up octets"
+
+ gg20_zkp.rv_kill(rv)
+
+ # Run Additional Benchmark
+ print(" *** Additional functions ***")
+
+ fncall = lambda: gg20_zkp.proof_to_octets(p)
+ time_func("proof_to_octets ", fncall)
+
+ fncall = lambda: gg20_zkp.proof_from_octets(t, u)
+ time_func("proof_from_octets ", fncall)
+
+ fncall = lambda: gg20_zkp.phase6_commitment_to_octets(c)
+ time_func("phase6_commitment_to_octets ", fncall)
+
+ fncall = lambda: gg20_zkp.phase6_commitment_from_octets(alpha, beta)
+ time_func("phase6_commitment_from_octets", fncall)
+
+ fncall = lambda: gg20_zkp.rv_kill(rv)
+ time_func("rv_kill ", fncall)
diff --git a/python/examples/example_gg20_zkp.py b/python/examples/example_gg20_zkp.py
new file mode 100755
index 0000000..6ed3914
--- /dev/null
+++ b/python/examples/example_gg20_zkp.py
@@ -0,0 +1,195 @@
+#!/usr/bin/env python3
+
+import os
+import sys
+
+sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
+
+from amcl import core_utils, gg20_zkp
+
+
+seed_hex = "78d0fb6705ce77dee47d03eb5b9c5d30"
+
+l_hex = "584edf9db99551ff2e0d56218a44fea0943032f7864b8359c213ec36465512c5"
+s_hex = "843b282505357e075bd98104f42fe7ea6b41310da7c769b4c402442c1ede922b"
+
+R_hex = "03e03cda61f087f9ba381695dc816a4ca42f38bbfc3fc88ffe897594b94ee7b80b"
+T_hex = "02863528287942ab88dec016c2e1993bf9e459ffcbfcc48c25ef68f2ec750e55a8"
+S_hex = "02ef03c8ecb7cf65b58d85f368c5fc2725b4e4fe93306f98cf53f8e1531cea2bc4"
+
+ID = "unique_user_identifier".encode('utf-8')
+AD = "additional_data".encode('utf-8')
+
+if __name__ == "__main__":
+ seed = bytes.fromhex(seed_hex)
+ rng = core_utils.create_csprng(seed)
+
+ print("Example GG20 ZKPs for Phase 3/6\n")
+
+ # Phase 3 GG20 ZKP
+ s = bytes.fromhex(s_hex)
+ l = bytes.fromhex(l_hex)
+ V = bytes.fromhex(T_hex)
+
+ print("*** Phase 3 ZKP ***\n")
+ print("Parameters")
+ print("\ts = {}".format(s.hex()))
+ print("\tl = {}".format(l.hex()))
+ print("\tT = {}".format(V.hex()))
+ print("\tID = {}".format(ID.decode('utf-8')))
+ print("\tAD = {}".format(AD.decode('utf-8')))
+ print("")
+
+ print("Begin Phase 3 ZK proof\n")
+
+ ## Prover
+
+ # Commitment
+ rv, c = gg20_zkp.phase3_commit(rng)
+
+ print("[Alice] Commit")
+ print("\tC = {}".format(c))
+ print("")
+
+ # Challenge
+ e = gg20_zkp.phase3_challenge(V, c,ID, AD = AD)
+
+ print("[Alice] Challenge")
+ print("\te = {}".format(e.hex()))
+ print("")
+
+ # Proof
+ p = gg20_zkp.phase3_prove(rv, e, s, l)
+
+ # Export proof to octets for transmission
+ t, u = gg20_zkp.proof_to_octets(p)
+
+ print("[Alice] Proof")
+ print("\tt = {}".format(t.hex()))
+ print("\tu = {}".format(u.hex()))
+ print("")
+
+ # Clean rv memory
+ gg20_zkp.rv_kill(rv)
+
+ ## Verifier
+
+ # Import proof from received octets
+ p = gg20_zkp.proof_from_octets(t, u)
+ print("[Bob ] Received Proof")
+ print("\tt = {}".format(t.hex()))
+ print("\tu = {}".format(u.hex()))
+ print("")
+
+ # Challenge
+ e = gg20_zkp.phase3_challenge(V, c,ID, AD = AD)
+
+ print("[Bob ] Challenge")
+ print("\te = {}".format(e.hex()))
+ print("")
+
+ # Verify proof
+ rc = gg20_zkp.phase3_verify(V, c, e, p)
+
+ print("[Bob ] Verification")
+ if rc == gg20_zkp.OK:
+ print("\tSuccess")
+ else:
+ print("\tFailure: {}".format(rc))
+ sys.exit(1)
+
+ print("")
+
+ # Phase 6 GG20 ZKP
+ R = bytes.fromhex(R_hex)
+ T = bytes.fromhex(T_hex)
+ S = bytes.fromhex(S_hex)
+
+ print("\n*** Phase 6 ZKP ***\n")
+ print("Parameters")
+ print("\ts = {}".format(s.hex()))
+ print("\tl = {}".format(l.hex()))
+ print("\tR = {}".format(R.hex()))
+ print("\tT = {}".format(T.hex()))
+ print("\tS = {}".format(S.hex()))
+ print("\tID = {}".format(ID.decode('utf-8')))
+ print("\tAD = {}".format(AD.decode('utf-8')))
+ print("")
+
+ print("Begin Phase 3 ZK proof\n")
+
+ ## Prover
+
+ # Commitment
+ rv, c, rc = gg20_zkp.phase6_commit(rng, R)
+
+ if rc != gg20_zkp.OK:
+ print("[Alice] Commit Error: {}".format(rc))
+ sys.exit(1)
+
+ # Export commitment to octets for transmission
+ alpha, beta = gg20_zkp.phase6_commitment_to_octets(c)
+
+ print("[Alice] Commit")
+ print("\talpha = {}\n".format(alpha.hex()))
+ print("\tbeta = {}\n".format(beta.hex()))
+ print("")
+
+ # Challenge
+ e = gg20_zkp.phase6_challenge(R, T, S, c, ID, AD=AD)
+
+ print("[Alice] Challenge")
+ print("\te = {}".format(e.hex()))
+ print("")
+
+ # Proof
+ p = gg20_zkp.phase6_prove(rv, e, s, l)
+
+ # Export proof to octets for transmission
+ t, u = gg20_zkp.proof_to_octets(p)
+
+ print("[Alice] Proof")
+ print("\tt = {}".format(t.hex()))
+ print("\tu = {}".format(u.hex()))
+ print("")
+
+ # Clean rv memory
+ gg20_zkp.rv_kill(rv)
+
+ ## Verifier
+
+ # Import proof from received octets
+ p = gg20_zkp.proof_from_octets(t, u)
+ print("[Bob ] Received Proof")
+ print("\tt = {}".format(t.hex()))
+ print("\tu = {}".format(u.hex()))
+ print("")
+
+ # Import commitment from received octets
+ c, rc = gg20_zkp.phase6_commitment_from_octets(alpha, beta)
+
+ if rc != gg20_zkp.OK:
+ print("[Bob ] Error importing Commitment: {}".format(rc))
+ sys.exit(1)
+
+ print("[Bob ] Received Commitment")
+ print("\talpha = {}\n".format(alpha.hex()))
+ print("\tbeta = {}\n".format(beta.hex()))
+ print("")
+
+ # Challenge
+ e = gg20_zkp.phase6_challenge(R, T, S, c,ID, AD = AD)
+
+ print("[Bob ] Challenge")
+ print("\te = {}".format(e.hex()))
+ print("")
+
+ # Verification
+ rc = gg20_zkp.phase6_verify(R, T, S, c, e, p)
+
+ print("[Bob ] Verification")
+ if rc == gg20_zkp.OK:
+ print("\tSuccess")
+ else:
+ print("\tFailure: {}".format(rc))
+ sys.exit(1)
diff --git a/python/test/test_gg20_zkp.py b/python/test/test_gg20_zkp.py
new file mode 100755
index 0000000..0bb8535
--- /dev/null
+++ b/python/test/test_gg20_zkp.py
@@ -0,0 +1,225 @@
+#!/usr/bin/env python3
+
+"""
+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.
+"""
+
+import os
+import sys
+import unittest
+
+sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
+
+from amcl import core_utils, gg20_zkp
+
+
+
+class TestPhase3(unittest.TestCase):
+ """ Test Phase 3 ZKP """
+
+ def setUp(self):
+ # Deterministic PRNG for testing purposes
+ seed_hex = "78d0fb6705ce77dee47d03eb5b9c5d30"
+ seed = bytes.fromhex(seed_hex)
+ self.rng = core_utils.create_csprng(seed)
+
+ # Proof input
+ self.s = bytes.fromhex("00f1f45c44eb4298562677dfc945064ac5d45d683ec2d87efbd2f527bb5a768c")
+ self.l = bytes.fromhex("ab5aa1e7740f849b974fcaaa98840d828a42b16dd59be32f39e3c637730ee9e4")
+
+ self.v = bytes.fromhex("02879452f0c552b01c2cc91101062ca02a1ff3eab1e9c18873992670198bf54f3e")
+
+ self.id = b'user-id'
+ self.ad = b'more-data'
+
+ # Pre-generate rv for deterministic test
+ self.rv, self.c = gg20_zkp.phase3_commit(self.rng)
+
+
+ def test(self):
+ """ Test Phase 3 ZKP """
+
+ rv, c = gg20_zkp.phase3_commit(self.rng)
+ e = gg20_zkp.phase3_challenge(self.v, c, self.id, AD = self.ad)
+ p = gg20_zkp.phase3_prove(rv, e, self.s, self.l)
+
+ gg20_zkp.rv_kill(self.rv)
+
+ t, u = gg20_zkp.proof_to_octets(p)
+ p = gg20_zkp.proof_from_octets(t, u)
+
+ rc = gg20_zkp.phase3_verify(self.v, c, e, p)
+
+ self.assertEqual(rc, gg20_zkp.OK, "Invalid Proof")
+
+
+ def test_no_ad(self):
+ """ Test Phase 3 ZKP without AD """
+
+ rv, c = gg20_zkp.phase3_commit(self.rng)
+ e = gg20_zkp.phase3_challenge(self.v, c, self.id)
+ p = gg20_zkp.phase3_prove(rv, e, self.s, self.l)
+
+ gg20_zkp.rv_kill(self.rv)
+
+ t, u = gg20_zkp.proof_to_octets(p)
+ p = gg20_zkp.proof_from_octets(t, u)
+
+ rc = gg20_zkp.phase3_verify(self.v, c, e, p)
+
+ self.assertEqual(rc, gg20_zkp.OK, "Invalid Proof")
+
+
+ def test_deterministic(self):
+ """ Test Phase 3 ZKP commitment with pre-generated rv"""
+
+ rv, c = gg20_zkp.phase3_commit(self.rng, rv = self.rv)
+
+ self.assertEqual(c, self.c, "Inconsistent commitment")
+
+ e = gg20_zkp.phase3_challenge(self.v, c, self.id, AD = self.ad)
+ p = gg20_zkp.phase3_prove(rv, e, self.s, self.l)
+
+ gg20_zkp.rv_kill(self.rv)
+
+ t, u = gg20_zkp.proof_to_octets(p)
+ p = gg20_zkp.proof_from_octets(t, u)
+
+ rc = gg20_zkp.phase3_verify(self.v, c, e, p)
+
+ self.assertEqual(rc, gg20_zkp.OK, "Invalid Proof")
+
+
+class TestPhase6(unittest.TestCase):
+ """ Test Phase 6 ZKP """
+
+ def setUp(self):
+ # Deterministic PRNG for testing purposes
+ seed_hex = "78d0fb6705ce77dee47d03eb5b9c5d30"
+ seed = bytes.fromhex(seed_hex)
+ self.rng = core_utils.create_csprng(seed)
+
+ # Proof input
+ self.s = bytes.fromhex("843b282505357e075bd98104f42fe7ea6b41310da7c769b4c402442c1ede922b")
+ self.l = bytes.fromhex("584edf9db99551ff2e0d56218a44fea0943032f7864b8359c213ec36465512c5")
+
+ self.R = bytes.fromhex("03e03cda61f087f9ba381695dc816a4ca42f38bbfc3fc88ffe897594b94ee7b80b")
+ self.T = bytes.fromhex("02863528287942ab88dec016c2e1993bf9e459ffcbfcc48c25ef68f2ec750e55a8")
+ self.S = bytes.fromhex("02ef03c8ecb7cf65b58d85f368c5fc2725b4e4fe93306f98cf53f8e1531cea2bc4")
+
+ self.id = b'user-id'
+ self.ad = b'more-data'
+
+ # Pre-generate rv for deterministic test
+ self.rv, c, rc = gg20_zkp.phase6_commit(self.rng, self.R)
+ self.assertEqual(rc, gg20_zkp.OK, f"Commitment error. RC: {rc}")
+
+ self.alpha, self.beta = gg20_zkp.phase6_commitment_to_octets(c)
+
+
+ def test(self):
+ """ Test Phase 6 ZKP """
+
+ rv, c, rc = gg20_zkp.phase6_commit(self.rng, self.R)
+ self.assertEqual(rc, gg20_zkp.OK, f"Commitment error. RC: {rc}")
+
+ e = gg20_zkp.phase6_challenge(self.R, self.T, self.S, c, self.id, AD = self.ad)
+ p = gg20_zkp.phase3_prove(rv, e, self.s, self.l)
+
+ gg20_zkp.rv_kill(self.rv)
+
+ t, u = gg20_zkp.proof_to_octets(p)
+ p = gg20_zkp.proof_from_octets(t, u)
+
+ alpha, beta = gg20_zkp.phase6_commitment_to_octets(c)
+ c, rc = gg20_zkp.phase6_commitment_from_octets(alpha, beta)
+ self.assertEqual(rc, gg20_zkp.OK, f"Commitment octet functions error. RC: {rc}")
+
+ rc = gg20_zkp.phase6_verify(self.R, self.T, self.S, c, e, p)
+
+ self.assertEqual(rc, gg20_zkp.OK, "Invalid Proof")
+
+
+ def test_no_ad(self):
+ """ Test Phase 6 ZKP without AD """
+
+ rv, c, rc = gg20_zkp.phase6_commit(self.rng, self.R)
+ self.assertEqual(rc, gg20_zkp.OK, f"Commitment error. RC: {rc}")
+
+ e = gg20_zkp.phase6_challenge(self.R, self.T, self.S, c, self.id)
+ p = gg20_zkp.phase3_prove(rv, e, self.s, self.l)
+
+ gg20_zkp.rv_kill(self.rv)
+
+ t, u = gg20_zkp.proof_to_octets(p)
+ p = gg20_zkp.proof_from_octets(t, u)
+
+ alpha, beta = gg20_zkp.phase6_commitment_to_octets(c)
+ c, rc = gg20_zkp.phase6_commitment_from_octets(alpha, beta)
+ self.assertEqual(rc, gg20_zkp.OK, f"Commitment octet functions error. RC: {rc}")
+
+ rc = gg20_zkp.phase6_verify(self.R, self.T, self.S, c, e, p)
+
+ self.assertEqual(rc, gg20_zkp.OK, "Invalid Proof")
+
+
+ def test_deterministic(self):
+ """ Test Phase 6 ZKP commitment with pre-generated rv"""
+
+ rv, c, rc = gg20_zkp.phase6_commit(self.rng, self.R, rv = self.rv)
+ self.assertEqual(rc, gg20_zkp.OK, f"Commitment error. RC: {rc}")
+
+ alpha, beta = gg20_zkp.phase6_commitment_to_octets(c)
+ self.assertEqual(alpha, self.alpha, "Inconsistent commitment alpha")
+ self.assertEqual(beta, self.beta, "Inconsistent commitment beta")
+
+ e = gg20_zkp.phase6_challenge(self.R, self.T, self.S, c, self.id, AD = self.ad)
+ p = gg20_zkp.phase3_prove(rv, e, self.s, self.l)
+
+ gg20_zkp.rv_kill(self.rv)
+
+ t, u = gg20_zkp.proof_to_octets(p)
+ p = gg20_zkp.proof_from_octets(t, u)
+
+ alpha, beta = gg20_zkp.phase6_commitment_to_octets(c)
+ c, rc = gg20_zkp.phase6_commitment_from_octets(alpha, beta)
+ self.assertEqual(rc, gg20_zkp.OK, f"Commitment octet functions error. RC: {rc}")
+
+ rc = gg20_zkp.phase6_verify(self.R, self.T, self.S, c, e, p)
+
+ self.assertEqual(rc, gg20_zkp.OK, "Invalid Proof")
+
+
+ def test_error_propagation(self):
+ """ Test Error Code propagation for invalid ECP """
+
+ rv, c, rc = gg20_zkp.phase6_commit(self.rng, self.l)
+
+ self.assertEqual(rv, gg20_zkp._ffi.NULL, "Commit rv not NULL")
+ self.assertEqual(c, gg20_zkp._ffi.NULL, "Commit c not NULL")
+ self.assertEqual(rc, gg20_zkp.INVALID_ECP, "Commit error code not propagated")
+
+ c = "not_none"
+ c, rc = gg20_zkp.phase6_commitment_from_octets(self.l, self.s)
+
+ self.assertEqual(c, gg20_zkp._ffi.NULL, "Octets c not NULL")
+ self.assertEqual(rc, gg20_zkp.INVALID_ECP, "Octets error code not propagated")
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/python/test/test_schnorr.py b/python/test/test_schnorr.py
index 9423265..b36604d 100755
--- a/python/test/test_schnorr.py
+++ b/python/test/test_schnorr.py
@@ -81,10 +81,10 @@ class TestChallenge(unittest.TestCase):
V = bytes.fromhex(vector["V"])
C = bytes.fromhex(vector["C"])
ID = bytes.fromhex(vector["ID"])
- AD = bytes.fromhex(vector["AD"])
- if not AD:
- AD = None
+ AD = None
+ if vector["AD"]:
+ AD = bytes.fromhex(vector["AD"])
e_golden = bytes.fromhex(vector["E"])
diff --git a/src/gg20_zkp.c b/src/gg20_zkp.c
new file mode 100644
index 0000000..6de8e39
--- /dev/null
+++ b/src/gg20_zkp.c
@@ -0,0 +1,375 @@
+/*
+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 "amcl/gg20_zkp.h"
+#include "amcl/hash_utils.h"
+
+/* Rom for SEC256K1 alternative generator
+ *
+ * This is tested in the unit tests to make sure it is a NUMS number
+ */
+
+const BIG_256_56 CURVE_G2x_SECP256K1= {0x072FA321534A94L, 0x1E5494E1366DF5L, 0x5544A7C6B1AE84L, 0x361809F7E86B0AL, 0x00000050E61A4DL};
+const BIG_256_56 CURVE_G2y_SECP256K1= {0x2EDE1FF33BE530L, 0x3BF41E26F5E241L, 0xB21F8B17AFDFBFL, 0xC7F68F0FD917E8L, 0x000000F1AF85F2L};
+
+void GG20_ZKP_generator_2(ECP_SECP256K1 *G)
+{
+ BIG_256_56 x,y;
+
+ BIG_256_56_rcopy(x,CURVE_G2x_SECP256K1);
+ BIG_256_56_rcopy(y,CURVE_G2y_SECP256K1);
+
+ ECP_SECP256K1_set(G,x,y);
+}
+
+/* Octet functions */
+
+void GG20_ZKP_proof_fromOctets(GG20_ZKP_proof *p, octet *T, octet *U)
+{
+ BIG_256_56_fromBytesLen(p->t, T->val, T->len);
+ BIG_256_56_fromBytesLen(p->u, U->val, U->len);
+}
+
+void GG20_ZKP_proof_toOctets(octet *T, octet *U, GG20_ZKP_proof *p)
+{
+ BIG_256_56_toBytes(T->val, p->t);
+ T->len = GGS_SECP256K1;
+
+ BIG_256_56_toBytes(U->val, p->u);
+ U->len = GGS_SECP256K1;
+}
+
+int GG20_ZKP_phase6_commitment_fromOctets(GG20_ZKP_phase6_commitment *c, octet *ALPHA, octet *BETA)
+{
+ if (!ECP_SECP256K1_fromOctet(&(c->ALPHA), ALPHA))
+ {
+ return GG20_ZKP_INVALID_ECP;
+ }
+
+ if (!ECP_SECP256K1_fromOctet(&(c->BETA), BETA))
+ {
+ return GG20_ZKP_INVALID_ECP;
+ }
+
+ return GG20_ZKP_OK;
+}
+
+void GG20_ZKP_phase6_commitment_toOctets(octet *ALPHA, octet *BETA, GG20_ZKP_phase6_commitment *c)
+{
+ ECP_SECP256K1_toOctet(ALPHA, &(c->ALPHA), true);
+ ECP_SECP256K1_toOctet(BETA, &(c->BETA), true);
+}
+
+/* Cleanup functions definitions */
+
+void GG20_ZKP_rv_kill(GG20_ZKP_rv *r)
+{
+ BIG_256_56_zero(r->a);
+ BIG_256_56_zero(r->b);
+}
+
+/* Phase 3 Proof Definitions */
+
+void GG20_ZKP_phase3_commit(csprng *RNG, GG20_ZKP_rv *r, octet *C)
+{
+ BIG_256_56 q;
+
+ ECP_SECP256K1 G;
+ ECP_SECP256K1 H;
+
+ ECP_SECP256K1_generator(&G);
+ GG20_ZKP_generator_2(&H);
+
+ // Read or generate secrets A, B
+ if (RNG != NULL)
+ {
+ BIG_256_56_rcopy(q, CURVE_Order_SECP256K1);
+
+ BIG_256_56_randomnum(r->a, q, RNG);
+ BIG_256_56_randomnum(r->b, q, RNG);
+ }
+
+ // Generate commitment C = a.G + b.H
+ ECP_SECP256K1_mul2(&G, &H, r->a, r->b);
+ ECP_SECP256K1_toOctet(C, &G, true);
+}
+
+void GG20_ZKP_phase3_challenge(const octet *V, const octet *C, const octet *ID, const octet *AD, octet *E)
+{
+ hash256 sha;
+
+ BIG_256_56 e;
+ BIG_256_56 q;
+ ECP_SECP256K1 G;
+
+ char o[GFS_SECP256K1 + 1];
+ octet O = {0, sizeof(o), o};
+
+ HASH256_init(&sha);
+
+ /* Bind Curve generators */
+ ECP_SECP256K1_generator(&G);
+ ECP_SECP256K1_toOctet(&O, &G, true);
+ HASH_UTILS_hash_oct(&sha, &O);
+
+ GG20_ZKP_generator_2(&G);
+ ECP_SECP256K1_toOctet(&O, &G, true);
+ HASH_UTILS_hash_oct(&sha, &O);
+
+ /* Bind Commitment */
+ HASH_UTILS_hash_oct(&sha, C);
+
+ /* Bind Proof Input */
+ HASH_UTILS_hash_oct(&sha, V);
+
+ /* Bind ID and AD */
+ HASH_UTILS_hash_i2osp4(&sha, ID->len);
+ HASH_UTILS_hash_oct(&sha, ID);
+
+ if (AD != NULL)
+ {
+ HASH_UTILS_hash_i2osp4(&sha, AD->len);
+ HASH_UTILS_hash_oct(&sha, AD);
+ }
+
+ // Compute challenge
+ BIG_256_56_rcopy(q, CURVE_Order_SECP256K1);
+ HASH_UTILS_rejection_sample_mod_BIG(&sha, q, e);
+
+ BIG_256_56_toBytes(E->val, e);
+ E->len = MODBYTES_256_56;
+}
+
+void GG20_ZKP_phase3_prove(GG20_ZKP_rv *r, const octet *E, const octet *S, const octet *L, GG20_ZKP_proof *p)
+{
+ BIG_256_56 e;
+ BIG_256_56 q;
+
+ DBIG_256_56 d;
+
+ BIG_256_56_rcopy(q, CURVE_Order_SECP256K1);
+
+ BIG_256_56_fromBytesLen(e, E->val, E->len);
+ BIG_256_56_modneg(e, e, q);
+
+ // Generate proof t = a - (e * s) mod the curve order
+ BIG_256_56_fromBytesLen(p->t, S->val, S->len);
+
+ BIG_256_56_mul(d, e, p->t);
+ BIG_256_56_dmod(p->t, d, q);
+ BIG_256_56_add(p->t, p->t, r->a);
+ BIG_256_56_mod(p->t, q);
+
+ // Generate proof u = b - (e * l) mod the curve order
+ BIG_256_56_fromBytesLen(p->u, L->val, L->len);
+
+ BIG_256_56_mul(d, e, p->u);
+ BIG_256_56_dmod(p->u, d, q);
+ BIG_256_56_add(p->u, p->u, r->b);
+ BIG_256_56_mod(p->u, q);
+
+ // Clean memory
+ BIG_256_56_dzero(d);
+}
+
+int GG20_ZKP_phase3_verify(octet *V, octet *C, const octet *E, GG20_ZKP_proof *p)
+{
+ ECP_SECP256K1 G;
+ ECP_SECP256K1 H;
+
+ BIG_256_56 e;
+
+ BIG_256_56_fromBytesLen(e, E->val, E->len);
+
+ // Compute first part of verification t.G + u.H
+ ECP_SECP256K1_generator(&G);
+ GG20_ZKP_generator_2(&H);
+ ECP_SECP256K1_mul2(&G, &H, p->t, p->u);
+
+ // Compute second part of verification e.V
+ if (!ECP_SECP256K1_fromOctet(&H, V))
+ {
+ return GG20_ZKP_INVALID_ECP;
+ }
+
+ ECP_SECP256K1_mul(&H, e);
+
+ // Combine full verification t.G + u.H + e.V
+ ECP_SECP256K1_add(&G, &H);
+
+ // Read commitment and verify
+ if (!ECP_SECP256K1_fromOctet(&H, C))
+ {
+ return GG20_ZKP_INVALID_ECP;
+ }
+
+ if (!ECP_SECP256K1_equals(&G, &H))
+ {
+ return GG20_ZKP_FAIL;
+ }
+
+ return GG20_ZKP_OK;
+}
+
+/* Phase 6 Proof Definitions */
+
+int GG20_ZKP_phase6_commit(csprng *RNG, octet *R, GG20_ZKP_rv *r, GG20_ZKP_phase6_commitment *c)
+{
+ BIG_256_56 q;
+
+ // Read or generate secrets A, B
+ if (RNG != NULL)
+ {
+ BIG_256_56_rcopy(q, CURVE_Order_SECP256K1);
+
+ BIG_256_56_randomnum(r->a, q, RNG);
+ BIG_256_56_randomnum(r->b, q, RNG);
+ }
+
+
+ // Generate commitment BETA = a.G + b.H
+ // Use ALPHA as temporary workspace
+ ECP_SECP256K1_generator(&(c->BETA));
+ GG20_ZKP_generator_2(&(c->ALPHA));
+
+ ECP_SECP256K1_mul2(&(c->BETA), &(c->ALPHA), r->a, r->b);
+
+ // Generate commitment ALPHA = a.R
+ if (!ECP_SECP256K1_fromOctet(&(c->ALPHA), R))
+ {
+ return GG20_ZKP_INVALID_ECP;
+ }
+
+ ECP_SECP256K1_mul(&(c->ALPHA), r->a);
+
+ return GG20_ZKP_OK;
+}
+
+void GG20_ZKP_phase6_challenge(const octet *R, const octet *T, const octet *S, GG20_ZKP_phase6_commitment *c, const octet *ID, const octet *AD, octet *E)
+{
+ hash256 sha;
+
+ BIG_256_56 e;
+ BIG_256_56 q;
+
+ ECP_SECP256K1 G;
+
+ char o[GFS_SECP256K1 + 1];
+ octet O = {0, sizeof(o), o};
+
+ HASH256_init(&sha);
+
+ /* Bind Curve generators */
+ ECP_SECP256K1_generator(&G);
+ ECP_SECP256K1_toOctet(&O, &G, true);
+ HASH_UTILS_hash_oct(&sha, &O);
+
+ GG20_ZKP_generator_2(&G);
+ ECP_SECP256K1_toOctet(&O, &G, true);
+ HASH_UTILS_hash_oct(&sha, &O);
+
+ /* Bind R as an additional generator */
+ HASH_UTILS_hash_oct(&sha, R);
+
+ /* Bind Commitment */
+ ECP_SECP256K1_toOctet(&O, &(c->ALPHA), true);
+ HASH_UTILS_hash_oct(&sha, &O);
+ ECP_SECP256K1_toOctet(&O, &(c->BETA), true);
+ HASH_UTILS_hash_oct(&sha, &O);
+
+ /* Bind Proof Input */
+ HASH_UTILS_hash_oct(&sha, T);
+ HASH_UTILS_hash_oct(&sha, S);
+
+ /* Bind ID and AD */
+ HASH_UTILS_hash_i2osp4(&sha, ID->len);
+ HASH_UTILS_hash_oct(&sha, ID);
+
+ if (AD != NULL)
+ {
+ HASH_UTILS_hash_i2osp4(&sha, AD->len);
+ HASH_UTILS_hash_oct(&sha, AD);
+ }
+
+ // Compute challenge
+ BIG_256_56_rcopy(q, CURVE_Order_SECP256K1);
+ HASH_UTILS_rejection_sample_mod_BIG(&sha, q, e);
+
+ BIG_256_56_toBytes(E->val, e);
+ E->len = MODBYTES_256_56;
+}
+
+void GG20_ZKP_phase6_prove(GG20_ZKP_rv *r, const octet *E, const octet *S, const octet *L, GG20_ZKP_proof *p)
+{
+ // The same values from the Phase 3 Proof can be used here
+ GG20_ZKP_phase3_prove(r, E, S, L, p);
+}
+
+int GG20_ZKP_phase6_verify(octet *R, octet *T, octet *S, GG20_ZKP_phase6_commitment *c, const octet *E, GG20_ZKP_proof *p)
+{
+ ECP_SECP256K1 G;
+ ECP_SECP256K1 H;
+
+ BIG_256_56 e;
+
+ BIG_256_56_fromBytesLen(e, E->val, E->len);
+
+ /* Compute verification for t.R + e.S =? ALPHA */
+ if (!ECP_SECP256K1_fromOctet(&G, R))
+ {
+ return GG20_ZKP_INVALID_ECP;
+ }
+
+ if (!ECP_SECP256K1_fromOctet(&H, S))
+ {
+ return GG20_ZKP_INVALID_ECP;
+ }
+
+ ECP_SECP256K1_mul2(&G, &H, p->t, e);
+
+ if (!ECP_SECP256K1_equals(&G, &(c->ALPHA)))
+ {
+ return GG20_ZKP_FAIL;
+ }
+
+ /* Compute verification for t.G + u.H + e.T =? BETA */
+
+ // Compute first part of verification t.G + u.H
+ ECP_SECP256K1_generator(&G);
+ GG20_ZKP_generator_2(&H);
+ ECP_SECP256K1_mul2(&G, &H, p->t, p->u);
+
+ // Read e and T
+ if (!ECP_SECP256K1_fromOctet(&H, T))
+ {
+ return GG20_ZKP_INVALID_ECP;
+ }
+
+ ECP_SECP256K1_mul(&H, e);
+
+ // Combine full verification t.G + u.H + e.V
+ ECP_SECP256K1_add(&G, &H);
+
+ if (!ECP_SECP256K1_equals(&G, &(c->BETA)))
+ {
+ return GG20_ZKP_FAIL;
+ }
+
+ return GG20_ZKP_OK;
+}
diff --git a/src/mta_zkp.c b/src/mta_zkp.c
new file mode 100644
index 0000000..b362be1
--- /dev/null
+++ b/src/mta_zkp.c
@@ -0,0 +1,318 @@
+/*
+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.
+*/
+
+/**
+ * @file mta_zkp.c
+ * @brief High level wrapping for the MTA proofs based on the Bit Commitment proofs
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "amcl/hash_utils.h"
+#include "amcl/mta_zkp.h"
+
+/* MTA Range Proof */
+
+void MTA_RP_commit(csprng *RNG, PAILLIER_private_key *key, BIT_COMMITMENT_pub *mod, octet *M, MTA_RP_rv *rv, MTA_RP_commitment *c)
+{
+ BIT_COMMITMENT_commit(RNG, key, mod, M, (BIT_COMMITMENT_rv*)rv, (BIT_COMMITMENT_commitment*)c);
+}
+
+void MTA_RP_challenge(PAILLIER_public_key *key, BIT_COMMITMENT_pub *mod, const octet *CT, MTA_RP_commitment *c, const octet *ID, const octet *AD, octet *E)
+{
+ hash256 sha;
+
+
+ BIG_256_56 q;
+ BIG_256_56 t;
+
+ HASH256_init(&sha);
+
+ /* Bind to public parameters */
+ BIT_COMMITMENT_hash_params(&sha, key, mod);
+
+ /* Bind to proof input */
+ HASH_UTILS_hash_oct(&sha, CT);
+
+ /* Bind to proof commitment */
+ BIT_COMMITMENT_hash_commitment(&sha, (BIT_COMMITMENT_commitment*)c);
+
+ /* Bind to ID and optional AD */
+ HASH_UTILS_hash_i2osp4(&sha, ID->len);
+ HASH_UTILS_hash_oct(&sha, ID);
+
+ if (AD != NULL)
+ {
+ HASH_UTILS_hash_i2osp4(&sha, AD->len);
+ HASH_UTILS_hash_oct(&sha, AD);
+ }
+
+ /* Output */
+ BIG_256_56_rcopy(q, CURVE_Order_SECP256K1);
+ HASH_UTILS_rejection_sample_mod_BIG(&sha, q, t);
+
+ BIG_256_56_toBytes(E->val, t);
+ E->len = EGS_SECP256K1;
+}
+
+void MTA_RP_prove(PAILLIER_private_key *key, octet *M, octet *R, MTA_RP_rv *rv, octet *E, MTA_RP_proof *p)
+{
+ BIT_COMMITMENT_prove(key, M, R, (BIT_COMMITMENT_rv*)rv, E, (BIT_COMMITMENT_proof*)p);
+}
+
+int MTA_RP_verify(PAILLIER_public_key *key, BIT_COMMITMENT_priv *mod, octet *CT, MTA_RP_commitment *c, octet *E, MTA_RP_proof *p)
+{
+ return BIT_COMMITMENT_verify(key, mod, CT, (BIT_COMMITMENT_commitment*)c, E, (BIT_COMMITMENT_proof*) p);
+}
+
+void MTA_RP_commitment_toOctets(octet *Z, octet *U, octet *W, MTA_RP_commitment *c)
+{
+ BIT_COMMITMENT_commitment_toOctets(Z, U, W, (BIT_COMMITMENT_commitment*)c);
+}
+
+void MTA_RP_commitment_fromOctets(MTA_RP_commitment *c, octet *Z, octet *U, octet *W)
+{
+ BIT_COMMITMENT_commitment_fromOctets((BIT_COMMITMENT_commitment*)c, Z, U, W);
+}
+
+void MTA_RP_proof_toOctets(octet *S, octet *S1, octet *S2, MTA_RP_proof *p)
+{
+ BIT_COMMITMENT_proof_toOctets(S, S1, S2, (BIT_COMMITMENT_proof*)p);
+}
+
+void MTA_RP_proof_fromOctets(MTA_RP_proof *p, octet *S, octet *S1, octet *S2)
+{
+ BIT_COMMITMENT_proof_fromOctets((BIT_COMMITMENT_proof*)p, S, S1, S2);
+}
+
+void MTA_RP_rv_kill(MTA_RP_rv *rv)
+{
+ BIT_COMMITMENT_rv_kill((BIT_COMMITMENT_rv*)rv);
+}
+
+
+/* MTA Receiver Proof */
+
+void MTA_ZK_commit(csprng *RNG, PAILLIER_public_key *key, BIT_COMMITMENT_pub *mod, octet *X, octet *Y, octet *C1, MTA_ZK_rv *rv, MTA_ZK_commitment *c)
+{
+ BIT_COMMITMENT_muladd_commit(RNG, key, mod, X, Y, C1, (BIT_COMMITMENT_muladd_rv*)rv, (BIT_COMMITMENT_muladd_commitment*)c);
+}
+
+void MTA_ZK_challenge(PAILLIER_public_key *key, BIT_COMMITMENT_pub *mod, const octet *C1, const octet *C2, MTA_ZK_commitment *c, const octet *ID, const octet *AD, octet *E)
+{
+ hash256 sha;
+
+ BIG_256_56 q;
+ BIG_256_56 t;
+
+ HASH256_init(&sha);
+
+ /* Bind to public parameters */
+ BIT_COMMITMENT_hash_params(&sha, key, mod);
+
+ /* Bind to proof input */
+ HASH_UTILS_hash_oct(&sha, C1);
+ HASH_UTILS_hash_oct(&sha, C2);
+
+ /* Bind to proof commitment */
+ BIT_COMMITMENT_hash_muladd_commitment(&sha, c);
+
+ /* Bind to ID and optional AD */
+ HASH_UTILS_hash_i2osp4(&sha, ID->len);
+ HASH_UTILS_hash_oct(&sha, ID);
+
+ if (AD != NULL)
+ {
+ HASH_UTILS_hash_i2osp4(&sha, AD->len);
+ HASH_UTILS_hash_oct(&sha, AD);
+ }
+
+ /* Output */
+ BIG_256_56_rcopy(q, CURVE_Order_SECP256K1);
+ HASH_UTILS_rejection_sample_mod_BIG(&sha, q, t);
+
+ BIG_256_56_toBytes(E->val, t);
+ E->len = EGS_SECP256K1;
+}
+
+void MTA_ZK_prove(PAILLIER_public_key *key, octet *X, octet *Y, octet *R, MTA_ZK_rv *rv, octet *E, MTA_ZK_proof *p)
+{
+ BIT_COMMITMENT_muladd_prove(key, X, Y, R, (BIT_COMMITMENT_muladd_rv*)rv, E, (BIT_COMMITMENT_muladd_proof*)p);
+}
+
+int MTA_ZK_verify(PAILLIER_private_key *key, BIT_COMMITMENT_priv *mod, octet *C1, octet *C2, MTA_ZK_commitment *c, octet *E, MTA_ZK_proof *p)
+{
+ return BIT_COMMITMENT_muladd_verify(key, mod, C1, C2, (BIT_COMMITMENT_muladd_commitment *)c, E, (BIT_COMMITMENT_muladd_proof*)p);
+}
+
+void MTA_ZK_commitment_toOctets(octet *Z, octet *Z1, octet *T, octet *V, octet *W, MTA_ZK_commitment *c)
+{
+ BIT_COMMITMENT_muladd_commitment_toOctets(Z, Z1, T, V, W, c);
+}
+
+void MTA_ZK_commitment_fromOctets(MTA_ZK_commitment *c, octet *Z, octet *Z1, octet *T, octet *V, octet *W)
+{
+ BIT_COMMITMENT_muladd_commitment_fromOctets(c, Z, Z1, T, V, W);
+}
+
+void MTA_ZK_proof_toOctets(octet *S, octet *S1, octet *S2, octet *T1, octet *T2, MTA_ZK_proof *p)
+{
+ BIT_COMMITMENT_muladd_proof_toOctets(S, S1, S2, T1, T2, p);
+}
+
+void MTA_ZK_proof_fromOctets(MTA_ZK_proof *p, octet *S, octet *S1, octet *S2, octet *T1, octet *T2)
+{
+ BIT_COMMITMENT_muladd_proof_fromOctets(p, S, S1, S2, T1, T2);
+}
+
+void MTA_ZK_rv_kill(MTA_ZK_rv *rv)
+{
+ BIT_COMMITMENT_muladd_rv_kill(rv);
+}
+
+/* MTA Receiver Proof with check for known DLOG */
+
+void MTA_ZKWC_commit(csprng *RNG, PAILLIER_public_key *key, BIT_COMMITMENT_pub *mod, octet *X, octet *Y, octet *C1, MTA_ZKWC_rv *rv, MTA_ZKWC_commitment *c)
+{
+ /* Compute base commitment for the range and knowledge ZKP */
+ BIT_COMMITMENT_muladd_commit(RNG, key, mod, X, Y, C1, (BIT_COMMITMENT_muladd_rv*)rv, &(c->mc));
+
+ /* Compute commitment for DLOG knowledge ZKP */
+ ECP_SECP256K1_generator(&(c->U));
+ BIT_COMMITMENT_ECP_commit(&(c->U), rv->alpha);
+}
+
+void MTA_ZKWC_challenge(PAILLIER_public_key *key, BIT_COMMITMENT_pub *mod, const octet *C1, const octet *C2, const octet *X, MTA_ZKWC_commitment *c, const octet *ID, const octet *AD, octet *E)
+{
+ hash256 sha;
+
+ char oct[EFS_SECP256K1 + 1];
+ octet OCT = {0, sizeof(oct), oct};
+
+ ECP_SECP256K1 G;
+
+ BIG_256_56 q;
+ BIG_256_56 t;
+
+ HASH256_init(&sha);
+
+ /* Bind to public parameters */
+ BIT_COMMITMENT_hash_params(&sha, key, mod);
+
+ // Bind to Curve generator
+ ECP_SECP256K1_generator(&G);
+ ECP_SECP256K1_toOctet(&OCT, &G, true);
+ HASH_UTILS_hash_oct(&sha, &OCT);
+
+ /* Bind to proof input */
+ HASH_UTILS_hash_oct(&sha, C1);
+ HASH_UTILS_hash_oct(&sha, C2);
+ HASH_UTILS_hash_oct(&sha, X);
+
+ /* Bind to proof commitment for DLOG */
+ ECP_SECP256K1_toOctet(&OCT, &(c->U), true);
+ HASH_UTILS_hash_oct(&sha, &OCT);
+
+ /* Bind to proof commitment for muladd ZKP */
+ BIT_COMMITMENT_hash_muladd_commitment(&sha, &(c->mc));
+
+ /* Bind to ID and optional AD */
+ HASH_UTILS_hash_i2osp4(&sha, ID->len);
+ HASH_UTILS_hash_oct(&sha, ID);
+
+ if (AD != NULL)
+ {
+ HASH_UTILS_hash_i2osp4(&sha, AD->len);
+ HASH_UTILS_hash_oct(&sha, AD);
+ }
+
+ /* Output */
+ BIG_256_56_rcopy(q, CURVE_Order_SECP256K1);
+ HASH_UTILS_rejection_sample_mod_BIG(&sha, q, t);
+
+ BIG_256_56_toBytes(E->val, t);
+ E->len = EGS_SECP256K1;
+}
+
+void MTA_ZKWC_prove(PAILLIER_public_key *key, octet *X, octet *Y, octet *R, MTA_ZKWC_rv *rv, octet *E, MTA_ZKWC_proof *p)
+{
+ BIT_COMMITMENT_muladd_prove(key, X, Y, R, (BIT_COMMITMENT_muladd_rv*)rv, E, (BIT_COMMITMENT_muladd_proof*)p);
+}
+
+int MTA_ZKWC_verify(PAILLIER_private_key *key, BIT_COMMITMENT_priv *mod, octet *C1, octet *C2, octet *X, MTA_ZKWC_commitment *c, octet *E, MTA_ZKWC_proof *p)
+{
+ int rc;
+
+ ECP_SECP256K1 x;
+ ECP_SECP256K1 g;
+
+ ECP_SECP256K1_generator(&g);
+
+ // Terminate early in case of invalid input
+ rc = ECP_SECP256K1_fromOctet(&x, X);
+ if (rc != 1)
+ {
+ return MTA_INVALID_ECP;
+ }
+
+ /* Verify additional DLOG proof */
+ rc = BIT_COMMITMENT_ECP_verify(&g, &x, &(c->U), E, p->s1);
+ if (rc != BIT_COMMITMENT_OK)
+ {
+ return rc;
+ }
+
+ /* Verify muladd proof*/
+ return BIT_COMMITMENT_muladd_verify(key, mod, C1, C2, &(c->mc), E, p);
+}
+
+void MTA_ZKWC_commitment_toOctets(octet *U, octet *Z, octet *Z1, octet *T, octet *V, octet *W, MTA_ZKWC_commitment *c)
+{
+ BIT_COMMITMENT_muladd_commitment_toOctets(Z, Z1, T, V, W, &(c->mc));
+ ECP_SECP256K1_toOctet(U, &(c->U), true);
+}
+
+int MTA_ZKWC_commitment_fromOctets(MTA_ZKWC_commitment *c, octet *U, octet *Z, octet *Z1, octet *T, octet *V, octet *W)
+{
+ if (ECP_SECP256K1_fromOctet(&(c->U), U) != 1)
+ {
+ return MTA_INVALID_ECP;
+ }
+
+ BIT_COMMITMENT_muladd_commitment_fromOctets(&(c->mc), Z, Z1, T, V, W);
+
+ return MTA_OK;
+}
+
+void MTA_ZKWC_proof_toOctets(octet *S, octet *S1, octet *S2, octet *T1, octet *T2, MTA_ZKWC_proof *p)
+{
+ BIT_COMMITMENT_muladd_proof_toOctets(S, S1, S2, T1, T2, p);
+}
+
+void MTA_ZKWC_proof_fromOctets(MTA_ZKWC_proof *p, octet *S, octet *S1, octet *S2, octet *T1, octet *T2)
+{
+ BIT_COMMITMENT_muladd_proof_fromOctets(p, S, S1, S2, T1, T2);
+}
+
+void MTA_ZKWC_rv_kill(MTA_ZKWC_rv *rv)
+{
+ BIT_COMMITMENT_muladd_rv_kill(rv);
+}
diff --git a/src/schnorr.c b/src/schnorr.c
index 4e72740..cd831c1 100644
--- a/src/schnorr.c
+++ b/src/schnorr.c
@@ -18,16 +18,7 @@ under the License.
*/
#include "amcl/schnorr.h"
-
-static void hash_octet(hash256 *sha, const octet *O)
-{
- int i;
-
- for (i = 0; i < O->len; i++)
- {
- HASH256_process(sha, O->val[i]);
- }
-}
+#include "amcl/hash_utils.h"
void SCHNORR_random_challenge(csprng *RNG, octet *E)
{
@@ -93,20 +84,20 @@ void SCHNORR_challenge(const octet *V, const octet *C, const octet *ID, const oc
// e = H(G,C,V,ID,AD) mod q
HASH256_init(&sha);
- hash_octet(&sha, &O);
- hash_octet(&sha, C);
- hash_octet(&sha, V);
- hash_octet(&sha, ID);
+ HASH_UTILS_hash_oct(&sha, &O);
+ HASH_UTILS_hash_oct(&sha, C);
+ HASH_UTILS_hash_oct(&sha, V);
+
+ HASH_UTILS_hash_i2osp4(&sha, ID->len);
+ HASH_UTILS_hash_oct(&sha, ID);
if (AD != NULL)
{
- hash_octet(&sha, AD);
+ HASH_UTILS_hash_i2osp4(&sha, AD->len);
+ HASH_UTILS_hash_oct(&sha, AD);
}
- HASH256_hash(&sha, o);
-
- BIG_256_56_fromBytesLen(e, o, SHA256);
- BIG_256_56_mod(e, q);
+ HASH_UTILS_rejection_sample_mod_BIG(&sha, q, e);
BIG_256_56_toBytes(E->val, e);
E->len = SGS_SECP256K1;
@@ -244,21 +235,21 @@ void SCHNORR_D_challenge(const octet *R, const octet *V, const octet *C, const o
// e = H(G,R,C,V,ID,AD) mod q
HASH256_init(&sha);
- hash_octet(&sha, &O);
- hash_octet(&sha, R);
- hash_octet(&sha, C);
- hash_octet(&sha, V);
- hash_octet(&sha, ID);
+ HASH_UTILS_hash_oct(&sha, &O);
+ HASH_UTILS_hash_oct(&sha, R);
+ HASH_UTILS_hash_oct(&sha, C);
+ HASH_UTILS_hash_oct(&sha, V);
+
+ HASH_UTILS_hash_i2osp4(&sha, ID->len);
+ HASH_UTILS_hash_oct(&sha, ID);
if (AD != NULL)
{
- hash_octet(&sha, AD);
+ HASH_UTILS_hash_i2osp4(&sha, AD->len);
+ HASH_UTILS_hash_oct(&sha, AD);
}
- HASH256_hash(&sha, o);
-
- BIG_256_56_fromBytesLen(e, o, SHA256);
- BIG_256_56_mod(e, q);
+ HASH_UTILS_rejection_sample_mod_BIG(&sha, q, e);
BIG_256_56_toBytes(E->val, e);
E->len = MODBYTES_256_56;
@@ -275,24 +266,26 @@ void SCHNORR_D_prove(const octet *A, const octet *B, const octet *E, const octet
BIG_256_56_rcopy(q, CURVE_Order_SECP256K1);
BIG_256_56_fromBytesLen(e, E->val, E->len);
- // Generate proof t = a + (e * s) mod the curve order
+ // Generate proof t = a - (e * s) mod the curve order
BIG_256_56_fromBytesLen(x, S->val, S->len);
BIG_256_56_fromBytesLen(r, A->val, A->len);
BIG_256_56_mul(d, e, x);
BIG_256_56_dmod(x, d, q);
+ BIG_256_56_modneg(x, x, q);
BIG_256_56_add(x, x, r);
BIG_256_56_mod(x, q);
BIG_256_56_toBytes(T->val, x);
T->len = SGS_SECP256K1;
- // Generate proof u = b + (e * l) mod the curve order
+ // Generate proof u = b - (e * l) mod the curve order
BIG_256_56_fromBytesLen(x, L->val, L->len);
BIG_256_56_fromBytesLen(r, B->val, B->len);
BIG_256_56_mul(d, e, x);
BIG_256_56_dmod(x, d, q);
+ BIG_256_56_modneg(x, x, q);
BIG_256_56_add(x, x, r);
BIG_256_56_mod(x, q);
@@ -333,16 +326,15 @@ int SCHNORR_D_verify(octet *R, octet *V, octet *C, const octet *E, const octet *
BIG_256_56_fromBytesLen(t, T->val, T->len);
BIG_256_56_fromBytesLen(u, U->val, U->len);
- // Compute verification t.R + u.G
+ // Compute verification t.R + u.G + e.V
ECP_SECP256K1_generator(&G);
ECP_SECP256K1_mul2(&ECPR, &G, t, u);
- // Compute ground truth C + e.V
BIG_256_56_fromBytesLen(t, E->val, E->len);
ECP_SECP256K1_mul(&ECPV, t);
- ECP_SECP256K1_add(&ECPV, &ECPC);
+ ECP_SECP256K1_add(&ECPR, &ECPV);
- if (!ECP_SECP256K1_equals(&ECPV, &ECPR))
+ if (!ECP_SECP256K1_equals(&ECPC, &ECPR))
{
return SCHNORR_FAIL;
}
diff --git a/test/smoke/test_gg20_zkp_phase3_smoke.c b/test/smoke/test_gg20_zkp_phase3_smoke.c
new file mode 100644
index 0000000..c8712b1
--- /dev/null
+++ b/test/smoke/test_gg20_zkp_phase3_smoke.c
@@ -0,0 +1,102 @@
+/*
+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 "amcl/gg20_zkp.h"
+#include "amcl/mpc.h"
+
+void big_245_56_cleaned(BIG_256_56 a, char *name)
+{
+ if (!BIG_256_56_iszilch(a))
+ {
+ printf("FAILURE GG20_ZKP_rv_kill. %s is not clean.\n", name);
+ exit(EXIT_FAILURE);
+ }
+}
+
+/* GG20 Phase 3 ZKP smoke test */
+
+int main()
+{
+ int rc;
+
+ BIG_256_56 s;
+ BIG_256_56 q;
+
+ GG20_ZKP_rv r;
+ GG20_ZKP_proof p;
+
+ char id[32];
+ octet ID = {0, sizeof(id), id};
+
+ char ad[32];
+ octet AD = {0, sizeof(ad), ad};
+
+ char oct_s[GGS_SECP256K1];
+ octet S = {0, sizeof(oct_s), oct_s};
+
+ char oct_l[GGS_SECP256K1];
+ octet L = {0, sizeof(oct_l), oct_l};
+
+ char v[GFS_SECP256K1+1];
+ octet V = {0, sizeof(v), v};
+
+ char c[GFS_SECP256K1+1];
+ octet C = {0, sizeof(c), c};
+
+ char e[GGS_SECP256K1];
+ octet E = {0, sizeof(e), e};
+
+ // Deterministic RNG for testing
+ char seed[32] = {0};
+ csprng RNG;
+ RAND_seed(&RNG, 32, seed);
+
+ // Generate ID and AD
+ OCT_rand(&ID, &RNG, ID.len);
+ OCT_rand(&AD, &RNG, AD.len);
+
+ // Generate s, l and compute V = s.G + l.H
+ BIG_256_56_rcopy(q, CURVE_Order_SECP256K1);
+ BIG_256_56_randomnum(s, q, &RNG);
+
+ BIG_256_56_toBytes(S.val, s);
+ S.len = GGS_SECP256K1;
+
+ MPC_PHASE3_T(&RNG, &S, &L, &V);
+
+ // Run test
+ GG20_ZKP_phase3_commit(&RNG, &r, &C);
+ GG20_ZKP_phase3_challenge(&V, &C, &ID, &AD, &E);
+ GG20_ZKP_phase3_prove(&r, &E, &S, &L, &p);
+
+ rc = GG20_ZKP_phase3_verify(&V, &C, &E, &p);
+ if (rc != GG20_ZKP_OK)
+ {
+ printf("FAILURE GG20_ZKP_phase3_verify. rc %d\n", rc);
+ exit(EXIT_FAILURE);
+ }
+
+ // Clean memory
+ GG20_ZKP_rv_kill(&r);
+ big_245_56_cleaned(r.a, "a");
+ big_245_56_cleaned(r.b, "b");
+
+ printf("SUCCESS\n");
+ exit(EXIT_SUCCESS);
+}
\ No newline at end of file
diff --git a/test/smoke/test_gg20_zkp_phase6_smoke.c b/test/smoke/test_gg20_zkp_phase6_smoke.c
new file mode 100644
index 0000000..1e41f27
--- /dev/null
+++ b/test/smoke/test_gg20_zkp_phase6_smoke.c
@@ -0,0 +1,124 @@
+/*
+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 "amcl/gg20_zkp.h"
+#include "amcl/mpc.h"
+
+void big_245_56_cleaned(BIG_256_56 a, char *name)
+{
+ if (!BIG_256_56_iszilch(a))
+ {
+ printf("FAILURE GG20_ZKP_rv_kill. %s is not clean.\n", name);
+ exit(EXIT_FAILURE);
+ }
+}
+
+/* GG20 Phase 6 ZKP smoke test */
+
+int main()
+{
+ int rc;
+
+ BIG_256_56 s;
+ BIG_256_56 l;
+ BIG_256_56 q;
+
+ ECP_SECP256K1 G;
+
+ GG20_ZKP_rv rv;
+ GG20_ZKP_phase6_commitment c;
+ GG20_ZKP_proof p;
+
+ char id[32];
+ octet ID = {0, sizeof(id), id};
+
+ char ad[32];
+ octet AD = {0, sizeof(ad), ad};
+
+ char oct_s[GGS_SECP256K1];
+ octet S = {0, sizeof(oct_s), oct_s};
+
+ char oct_l[GGS_SECP256K1];
+ octet L = {0, sizeof(oct_l), oct_l};
+
+ char r[GFS_SECP256K1+1];
+ octet R = {0, sizeof(r), r};
+
+ char t[GFS_SECP256K1+1];
+ octet T = {0, sizeof(t), t};
+
+ char ecps[GFS_SECP256K1+1];
+ octet ECPS = {0, sizeof(ecps), ecps};
+
+ char e[GGS_SECP256K1];
+ octet E = {0, sizeof(e), e};
+
+ // Deterministic RNG for testing
+ char seed[32] = {0};
+ csprng RNG;
+ RAND_seed(&RNG, 32, seed);
+
+ // Generate ID and AD
+ OCT_rand(&ID, &RNG, ID.len);
+ OCT_rand(&AD, &RNG, AD.len);
+
+ // Generate s, l and compute V = s.G + l.H
+ BIG_256_56_rcopy(q, CURVE_Order_SECP256K1);
+ BIG_256_56_randomnum(s, q, &RNG);
+
+ BIG_256_56_toBytes(S.val, s);
+ S.len = GGS_SECP256K1;
+
+ MPC_PHASE3_T(&RNG, &S, &L, &T);
+
+ // Generate R and S = s.R
+ BIG_256_56_randomnum(l, q, &RNG);
+
+ ECP_SECP256K1_generator(&G);
+ ECP_SECP256K1_mul(&G, l);
+ ECP_SECP256K1_toOctet(&R, &G, true);
+
+ MPC_ECP_GENERATE_CHECK(&R, &S, &ECPS);
+
+ // Run test
+ rc = GG20_ZKP_phase6_commit(&RNG, &R, &rv, &c);
+ if (rc != GG20_ZKP_OK)
+ {
+ printf("FAILURE GG20_ZKP_phase6_commit. rc %d\n", rc);
+ exit(EXIT_FAILURE);
+ }
+
+ GG20_ZKP_phase6_challenge(&R, &T, &ECPS, &c, &ID, &AD, &E);
+ GG20_ZKP_phase6_prove(&rv, &E, &S, &L, &p);
+
+ rc = GG20_ZKP_phase6_verify(&R, &T, &ECPS, &c, &E, &p);
+ if (rc != GG20_ZKP_OK)
+ {
+ printf("FAILURE GG20_ZKP_phase6_verify. rc %d\n", rc);
+ exit(EXIT_FAILURE);
+ }
+
+ // Clean memory
+ GG20_ZKP_rv_kill(&rv);
+ big_245_56_cleaned(rv.a, "a");
+ big_245_56_cleaned(rv.b, "b");
+
+ printf("SUCCESS\n");
+ exit(EXIT_SUCCESS);
+}
\ No newline at end of file
diff --git a/test/test.c b/test/test.c
index 0e84760..15e0862 100644
--- a/test/test.c
+++ b/test/test.c
@@ -45,6 +45,62 @@ void read_OCTET(FILE *fp, octet *OCT, char *string)
OCT_fromHex(OCT, buff);
}
+void read_OCTET_ARRAY(FILE *fp, octet *OCT_ARRAY, char *string, int n)
+{
+ int i;
+ char *next, *end;
+
+ if (string[0] != '[')
+ {
+ fclose(fp);
+
+ printf("ERROR unexpected character at position 0 at %s\n", string);
+ exit(EXIT_FAILURE);
+ }
+
+ next = string+1;
+
+ for (i = 0; i < n-1; i++)
+ {
+ end = strchr(next, ',');
+ if (end == NULL)
+ {
+ fclose(fp);
+
+ printf("ERROR separator not found at octet %d at %s\n", i, next);
+ exit(EXIT_FAILURE);
+ }
+ *end = '\0';
+
+ OCT_fromHex(OCT_ARRAY+i, next);
+
+ next = end+1;
+ }
+
+ end = strchr(next, ']');
+ if (end == NULL)
+ {
+ fclose(fp);
+
+ printf("ERROR unexpected closing character at %s\n", next);
+ exit(EXIT_FAILURE);
+ }
+
+ *end = '\0';
+
+ OCT_fromHex(OCT_ARRAY+n-1, next);
+}
+
+void read_BIG_256_56(FILE *fp, BIG_256_56 x, char *string)
+{
+ int len = strlen(string);
+ char oct[len/2];
+ octet OCT = {0, sizeof(oct), oct};
+
+ read_OCTET(fp, &OCT, string);
+ BIG_256_56_fromBytesLen(x, OCT.val, OCT.len);
+}
+
void read_FF_2048(FILE *fp, BIG_1024_58 *x, char *string, int n)
{
int len = strlen(string);
@@ -121,6 +177,30 @@ void scan_OCTET(FILE *fp, octet *OCT, char *line, const char *prefix)
}
}
+void scan_OCTET_ARRAY(FILE *fp, octet *OCT_ARRAY, char *line, const char *prefix, int n)
+{
+ if (!strncmp(line, prefix, strlen(prefix)))
+ {
+ line+=strlen(prefix);
+ read_OCTET_ARRAY(fp, OCT_ARRAY, line, n);
+ }
+}
+
+void scan_BIG_256_56(FILE *fp, BIG_256_56 x, char *line, const char *prefix)
+{
+ if (!strncmp(line, prefix, strlen(prefix)))
+ {
+ line+=strlen(prefix);
+ read_BIG_256_56(fp, x, line);
+
+#ifdef DEBUG
+ printf("%s", prefix);
+ BIG_256_56_output(x);
+ printf("\n");
+#endif
+ }
+}
+
void scan_FF_2048(FILE *fp, BIG_1024_58 *x, char *line, const char *prefix, int n)
{
if (!strncmp(line, prefix, strlen(prefix)))
@@ -155,7 +235,6 @@ void scan_ECP_SECP256K1(FILE *fp, ECP_SECP256K1 *P, char *line, const char *pref
{
if (!strncmp(line, prefix, strlen(prefix)))
{
-
line+=strlen(prefix);
read_ECP_SECP256K1(fp, P, line);
@@ -215,6 +294,29 @@ void compare_OCT(FILE* fp, int testNo, char *name, octet *X, octet *Y)
}
}
+void compare_BIG_256_56(FILE* fp, int testNo, char* name, BIG_256_56 x, BIG_256_56 y)
+{
+ if(BIG_256_56_comp(x, y))
+ {
+ if (fp != NULL)
+ {
+ fclose(fp);
+ }
+
+ fprintf(stderr, "FAILURE %s. Test %d\n", name, testNo);
+
+#ifdef DEBUG
+ printf("x = ");
+ BIG_256_56_output(x);
+ printf("\ny = ");
+ BIG_256_56_output(y);
+ printf("\n");
+#endif
+
+ exit(EXIT_FAILURE);
+ }
+}
+
void compare_FF_2048(FILE* fp, int testNo, char* name, BIG_1024_58 *x, BIG_1024_58 *y, int n)
{
if(FF_2048_comp(x, y, n))
diff --git a/test/test.h b/test/test.h
index 98bbe13..e8d1d77 100644
--- a/test/test.h
+++ b/test/test.h
@@ -42,7 +42,24 @@ extern "C"
* @param OCT Output octet
* @param string Input string
*/
-void read_OCTET(FILE *fp, octet *OCT, char *string);
+extern void read_OCTET(FILE *fp, octet *OCT, char *string);
+
+/*! \brief Read string into an octet array
+ *
+ * @param fp TV file pointer to close in case of error
+ * @param OCT_ARRAY Output octet
+ * @param string Input string
+ * @param n Length of the array to read
+ */
+extern void read_OCTET_ARRAY(FILE *fp, octet *OCT_ARRAY, char *string, int n);
+
+/*! \brief Read string into a big_256_56
+ *
+ * @param fp TV file pointer to close in case of error
+ * @param x Output big
+ * @param string Input string
+ */
+extern void read_BIG_256_56(FILE *fp, BIG_256_56 x, char *string);
/*! \brief Read string into an ff_2048
*
@@ -95,6 +112,25 @@ extern void scan_int(int *v, char *line, const char *prefix);
*/
extern void scan_OCTET(FILE *fp, octet *OCT, char *line, const char *prefix);
+/*! \brief Read octet array if the line has the correct prefix
+ *
+ * @param fp TV file pointer to close in case of error
+ * @param OCT_ARRAY Output octet array
+ * @param line TV line
+ * @param prefix Line prefix for the octet to read
+ * @param n Length of the array to read
+ */
+extern void scan_OCTET_ARRAY(FILE *fp, octet *OCT_ARRAY, char *line, const char *prefix, int n);
+
+/*! \brief Read big_256_56 if the line has the correct prefix
+ *
+ * @param fp TV file pointer to close in case of error
+ * @param x Output big
+ * @param line TV line
+ * @param prefix Line prefix for the element to read
+ */
+extern void scan_BIG_256_56(FILE *fp, BIG_256_56 x, char *line, const char *prefix);
+
/*! \brief Read ff_2048 element if the line has the correct prefix
*
* @param fp TV file pointer to close in case of error
@@ -147,6 +183,18 @@ extern void scan_HDLOG_iv(FILE *fp, HDLOG_iter_values V, char *line, const char
*/
extern void compare_OCT(FILE *fp, int testNo, char *name, octet *X, octet *Y);
+/*! \brief Compare two big_256_56 elements
+ *
+ * Compare two big_s and fail the test if they are not equal
+ *
+ * @param fp TV file pointer to close in case of failure
+ * @param testNo Test Vector identifier
+ * @param name Descriptor for the elements compared
+ * @param x First element to compare
+ * @param y Second element to compare
+ */
+extern void compare_BIG_256_56(FILE *fp, int testNo, char* name, BIG_256_56 x, BIG_256_56 y);
+
/*! \brief Compare two ff_2048 elements
*
* Compare two ff_2048 elements and fail the test if they are not equal
diff --git a/testVectors/gg20_zkp/octets.txt b/testVectors/gg20_zkp/octets.txt
new file mode 100644
index 0000000..664c0e4
--- /dev/null
+++ b/testVectors/gg20_zkp/octets.txt
@@ -0,0 +1,59 @@
+TEST = 0,
+ALPHA = 02c6fb6f18f732f8906b11690c41c412103d95e12cb9bf974d10b0239baeeffd3c,
+BETA = 02893028961112ee8c139e6c1991249b737434215d50bd9edabcede1aff24b2afa,
+T = 66acee60b6318fcdbecddd22ef73589e61b8ab63432aa4927898539f93687728,
+U = 2600691de9fb297862476be002ad22a9c5b697f1237793c132bbc8555aab4849,
+
+TEST = 1,
+ALPHA = 033efe70bc113af12c6e1a1e4804a5d6140e36da8438fd238c5245420d46035cb4,
+BETA = 03b0df256256a4d1ebabd3d088f785fa4256e35b15d87c8118982a382eae9a5fd5,
+T = 81fd655525685886f9bb8fef01f00bac1370e1da5872054447a069c2b45a7e9b,
+U = 6910582b4cefb1621e8d09d789cf4342b26b9b077463aaab2fd62aaf5e92f5a7,
+
+TEST = 2,
+ALPHA = 02a58b93a867ef13d8c4ece3c1fd7d88b1ee4fb7b0ae88fd644ca65fa9bbaaa91a,
+BETA = 02bdb475ba532e8e4bdc75c8d3da665524e16897646f133ff1f46debb23db518cd,
+T = 941f3cc74204fc2811f5aa31f33b8e2c5bef4958448c4aa200cee38c4b592206,
+U = 2a5f42f32f32399f69844a4e2bc04cb69d65d69c92e96178e44cced18ac8e167,
+
+TEST = 3,
+ALPHA = 024a9d38c6dd6464dfd5f1c48b54a93d1dbefbc9df6c5d73ed484eb5d2ed2c39ac,
+BETA = 039674b4d13d3fd8bd969959cc69a93b459e9db4cdd93760ee0392ea9c4abeb802,
+T = 34a6c9e13a4e02dc86e248af2a48c5ef8980031d8ebbe316bfbe5e6637db56d8,
+U = 36ba7fa7b2823c14bd756ecd7c06f75195529a5a6b8b945b319ca00558332274,
+
+TEST = 4,
+ALPHA = 0358491775a269318fde1a684fda434c5362d14cfd3cd00dbc625d1f50dbd9f6e8,
+BETA = 037977bcdb620361355bf7d9d29689d90a5fb5a4766905275b9b6ddb31cc4b673d,
+T = ee673c77d320e127ea49093b23d169f6c4345e6d26e65d4499097d208bfaa87b,
+U = 6ecde180aa8a032d7a4b28993e44fc880d83fca83c1cc7831190989c42dd941e,
+
+TEST = 5,
+ALPHA = 02a9f78b24582fa72c45027682e6c578266cfe0087563f03e49a6ab6eba94ae0e6,
+BETA = 03c4ca090151d7a4c1cb178835ff43e4d0e1a93f6efb25661399fd1ed0b43bb98a,
+T = b12bd41c9d68375ea89dd6e20c410175c3812f4251756345d6a66460fa6f89fa,
+U = ddc340dc4f5e73bc95ef16ca641571a4252dab6e620d4e15b476727ec24cc233,
+
+TEST = 6,
+ALPHA = 0337f7a55ec8ecc01d4ec8d9b5c13b671832cf11aceb405f7b1476d2ba46a957fd,
+BETA = 02894aed53ee60156b0cf61d71647424d2cc80de8dde6659a2a04c81073246f2cc,
+T = b1e8f902af4db8af60d5a2f84db34e4bf87ec381a3d1cdee7806c38f978da505,
+U = 2d54c4b7802b98456a9995af65696bb821352cceec9b496304f6c4f3601f02ea,
+
+TEST = 7,
+ALPHA = 0229012eede68a4b0fb89d41c45123567b689de83977e0d4eee23197352051a458,
+BETA = 02132c61a945337a7b9770a9633c7961a64cc0af4d2532ce3412aefeed2e0e796d,
+T = d932de6113c941ac01a12fff7e6fd6700b4d7fb5293559ea6e99b6a61ef213af,
+U = 2074cf4cc1683f5518af734558abab4b41a07b87449fa199896660f978badcbf,
+
+TEST = 8,
+ALPHA = 027dc0edd1eec628621c8210a6749f165a1d9c4fc34d2a8324db59b29a3aea17c5,
+BETA = 033d16586629c904d6fc6e9ed0f28fd0fc7a2f82fb33eedabf980c0b68a53dc2c0,
+T = d5c4fa580680643afdd91650cde82a4a417120adecd04c67d98f7d1254f3b38b,
+U = ddf7c9345fd0590affa8e7b6ef7d56929b097ef16e0c63a7c85a5dd437928775,
+
+TEST = 9,
+ALPHA = 02057f0324b16eddaefde206a00ad6cac24b33ff4b9db9512168485016e557ab30,
+BETA = 036f4486b6f8d2b591ad1f2acdef02dfe6d59f9f933a56e0da30a39d67a5e6aa6e,
+T = 625e09fa9aeb0144f99cf6df869938f3132c4bcba72804d0ab627b35ffd0c19e,
+U = 9c0bf3c5d4a6b0a5933184fffd0365ba4bc72c1a526ca2c7d0d8f4b5d7ca48b0,
diff --git a/testVectors/gg20_zkp/phase3_challenge.json b/testVectors/gg20_zkp/phase3_challenge.json
new file mode 100644
index 0000000..09a44bf
--- /dev/null
+++ b/testVectors/gg20_zkp/phase3_challenge.json
@@ -0,0 +1,82 @@
+[
+ {
+ "TEST": 0,
+ "V": "02e03da4554a06bb9f90cc5d77edcdcc69d96a707f6d8191a8c6fbe8044cb4f363",
+ "C": "034eaa5630192ece97b664c54ab8b111c48f964b263170500b9e109b8fb85d85c3",
+ "ID": "f65b3c27e5698be4ea94d95ce5259ef2",
+ "AD": "",
+ "E": "a8effbed850f9f978a88926f895db5575a2372902a5f116fb1b66e53500d0f29"
+ },
+ {
+ "TEST": 1,
+ "V": "02a5e9c0299060fba18865a71f5073a3d2d2b147e8580f4307cfec444d11e5aa09",
+ "C": "038f8768a2dcd60714d3c19ac06e656867796dbc3808051805c6d6d866e7389a05",
+ "ID": "a81470aaf7afc061dc24193d4446c96e",
+ "AD": "",
+ "E": "598838c9113415caccb6fbd389b758650b1cb3ecc2b72aa24a7dad2bcfa979d9"
+ },
+ {
+ "TEST": 2,
+ "V": "0320280219053d45a0c5c90e73cdefd8a593f4a7be5da01e4d1db9af68aaa23299",
+ "C": "0282616f5db217d92e6c98fe5972e940c0e7d49c87f122fbddd25b79cd3e7218bc",
+ "ID": "03ebed6dacbc4902145678434808e180",
+ "AD": "",
+ "E": "e172dd9e5bf1c1bb56ba8bc773c2d5163fbbe0c67443211d4100e0c8a63de0b9"
+ },
+ {
+ "TEST": 3,
+ "V": "0379b3f04bcb5c09d1bb9f315d1d90c35ee1622f68349dbfc0e234a4aee8f57216",
+ "C": "02307df7d70d833f0116f1f6c0b2fd4108a0514fccc196ed9ad18e7c64dd0d5baf",
+ "ID": "008c44b943f505813212b480e19d261c",
+ "AD": "",
+ "E": "39d2b208df6db374cbb0ab5618965691ab0c811aa0a6b5b7854811b9f034f534"
+ },
+ {
+ "TEST": 4,
+ "V": "02ffdca77078ef81ebf5be576b38eb69ac4dbb29eb4070400629104eb63d9c2df8",
+ "C": "021c674cef387256d884f55c67b808b4d85db2d17abc642e616ef7975a287e101e",
+ "ID": "cf58c2bb64a703b541250d19e9586215",
+ "AD": "",
+ "E": "7c291362f4212c3b022898334435d2cbf9d7c0e0a24d52fecf01cead5ae01bb9"
+ },
+ {
+ "TEST": 5,
+ "V": "03834f82bccf7b71714e90e1898b0d3cfecb599cda83c76d2dac04a9455cfc1748",
+ "C": "035b74645d08ea1c8ddeaf57702564919410cfa837cb24c0ab891b64431ba106d6",
+ "ID": "cc4e19f9a166f5eeace94d5b32157cab",
+ "AD": "09a505518af94a8552547e0a8729af8e",
+ "E": "e63279c737313382adf615739cfdb95393e506a3834451ff2e1e9dfd3fa8e67d"
+ },
+ {
+ "TEST": 6,
+ "V": "037166b6f25b8888aad6007287b284f6bbbcba04622663effa3297cdd9f1a39c3d",
+ "C": "03932b6703940d748f041653451df0b6104e86c7d1dc04261a4c940a15cab64b18",
+ "ID": "4e8e1482f967f3f3c6e84dd27717fe2b",
+ "AD": "f9c26bddde765e5128d1158f987755ff",
+ "E": "73029e753eaf4b1091f1e4da11a17a36906694f9d73cdbf34794d2b5238cece6"
+ },
+ {
+ "TEST": 7,
+ "V": "0265fb889364196c591a5e58f50ec4884aac6042c5734e18931209364be7e64ac5",
+ "C": "035eba13445bad376a4918abfc897e829a1fe6a3277ec8b7929a72b361c838f4c3",
+ "ID": "4399776dc1ec5490710e52f59fb219e4",
+ "AD": "99a2774bd166ac93a6d87dbc2bd523dc",
+ "E": "1f6f52e6872082be4959ab37b5b59119493601103a24f14c39525de08c3458fe"
+ },
+ {
+ "TEST": 8,
+ "V": "03fcc77f61f3d0974dfb272385db0ec7735611bc27640135bad3724585e9250964",
+ "C": "036eed182bb4fe28f7c214e82c4a8914747eae1571f627a59f3b87cb9465635348",
+ "ID": "16f29291d8cd840d76af1b3728f4d3e2",
+ "AD": "d31dfe881b63e7d5bd783c6ed1bc84bb",
+ "E": "914798fb16ac6a91ca18c11cf0ef9b35316e257415c72a9676d25dd5b536f7f6"
+ },
+ {
+ "TEST": 9,
+ "V": "024f0042345303c658b2ee6eb84fb1b0d46deac42fe9221f23a0387f961e021491",
+ "C": "02a8131a3fd62c2413e24a89b069d5856c7ccc9e8d3dd4686bb0cb878d8b7ba229",
+ "ID": "7acce926f027b501739e59438987004e",
+ "AD": "1a9699eaff721e651dc06ff4b69aea64",
+ "E": "0deb6a24b8b0345c01abbccad6b58379bf71c63dc16e89cde479d8613641ac01"
+ }
+]
\ No newline at end of file
diff --git a/testVectors/gg20_zkp/phase3_challenge.txt b/testVectors/gg20_zkp/phase3_challenge.txt
new file mode 100644
index 0000000..473a6ac
--- /dev/null
+++ b/testVectors/gg20_zkp/phase3_challenge.txt
@@ -0,0 +1,70 @@
+TEST = 0,
+V = 02e03da4554a06bb9f90cc5d77edcdcc69d96a707f6d8191a8c6fbe8044cb4f363,
+C = 034eaa5630192ece97b664c54ab8b111c48f964b263170500b9e109b8fb85d85c3,
+ID = f65b3c27e5698be4ea94d95ce5259ef2,
+AD = ,
+E = a8effbed850f9f978a88926f895db5575a2372902a5f116fb1b66e53500d0f29,
+
+TEST = 1,
+V = 02a5e9c0299060fba18865a71f5073a3d2d2b147e8580f4307cfec444d11e5aa09,
+C = 038f8768a2dcd60714d3c19ac06e656867796dbc3808051805c6d6d866e7389a05,
+ID = a81470aaf7afc061dc24193d4446c96e,
+AD = ,
+E = 598838c9113415caccb6fbd389b758650b1cb3ecc2b72aa24a7dad2bcfa979d9,
+
+TEST = 2,
+V = 0320280219053d45a0c5c90e73cdefd8a593f4a7be5da01e4d1db9af68aaa23299,
+C = 0282616f5db217d92e6c98fe5972e940c0e7d49c87f122fbddd25b79cd3e7218bc,
+ID = 03ebed6dacbc4902145678434808e180,
+AD = ,
+E = e172dd9e5bf1c1bb56ba8bc773c2d5163fbbe0c67443211d4100e0c8a63de0b9,
+
+TEST = 3,
+V = 0379b3f04bcb5c09d1bb9f315d1d90c35ee1622f68349dbfc0e234a4aee8f57216,
+C = 02307df7d70d833f0116f1f6c0b2fd4108a0514fccc196ed9ad18e7c64dd0d5baf,
+ID = 008c44b943f505813212b480e19d261c,
+AD = ,
+E = 39d2b208df6db374cbb0ab5618965691ab0c811aa0a6b5b7854811b9f034f534,
+
+TEST = 4,
+V = 02ffdca77078ef81ebf5be576b38eb69ac4dbb29eb4070400629104eb63d9c2df8,
+C = 021c674cef387256d884f55c67b808b4d85db2d17abc642e616ef7975a287e101e,
+ID = cf58c2bb64a703b541250d19e9586215,
+AD = ,
+E = 7c291362f4212c3b022898334435d2cbf9d7c0e0a24d52fecf01cead5ae01bb9,
+
+TEST = 5,
+V = 03834f82bccf7b71714e90e1898b0d3cfecb599cda83c76d2dac04a9455cfc1748,
+C = 035b74645d08ea1c8ddeaf57702564919410cfa837cb24c0ab891b64431ba106d6,
+ID = cc4e19f9a166f5eeace94d5b32157cab,
+AD = 09a505518af94a8552547e0a8729af8e,
+E = e63279c737313382adf615739cfdb95393e506a3834451ff2e1e9dfd3fa8e67d,
+
+TEST = 6,
+V = 037166b6f25b8888aad6007287b284f6bbbcba04622663effa3297cdd9f1a39c3d,
+C = 03932b6703940d748f041653451df0b6104e86c7d1dc04261a4c940a15cab64b18,
+ID = 4e8e1482f967f3f3c6e84dd27717fe2b,
+AD = f9c26bddde765e5128d1158f987755ff,
+E = 73029e753eaf4b1091f1e4da11a17a36906694f9d73cdbf34794d2b5238cece6,
+
+TEST = 7,
+V = 0265fb889364196c591a5e58f50ec4884aac6042c5734e18931209364be7e64ac5,
+C = 035eba13445bad376a4918abfc897e829a1fe6a3277ec8b7929a72b361c838f4c3,
+ID = 4399776dc1ec5490710e52f59fb219e4,
+AD = 99a2774bd166ac93a6d87dbc2bd523dc,
+E = 1f6f52e6872082be4959ab37b5b59119493601103a24f14c39525de08c3458fe,
+
+TEST = 8,
+V = 03fcc77f61f3d0974dfb272385db0ec7735611bc27640135bad3724585e9250964,
+C = 036eed182bb4fe28f7c214e82c4a8914747eae1571f627a59f3b87cb9465635348,
+ID = 16f29291d8cd840d76af1b3728f4d3e2,
+AD = d31dfe881b63e7d5bd783c6ed1bc84bb,
+E = 914798fb16ac6a91ca18c11cf0ef9b35316e257415c72a9676d25dd5b536f7f6,
+
+TEST = 9,
+V = 024f0042345303c658b2ee6eb84fb1b0d46deac42fe9221f23a0387f961e021491,
+C = 02a8131a3fd62c2413e24a89b069d5856c7ccc9e8d3dd4686bb0cb878d8b7ba229,
+ID = 7acce926f027b501739e59438987004e,
+AD = 1a9699eaff721e651dc06ff4b69aea64,
+E = 0deb6a24b8b0345c01abbccad6b58379bf71c63dc16e89cde479d8613641ac01,
+
diff --git a/testVectors/gg20_zkp/phase3_commit.json b/testVectors/gg20_zkp/phase3_commit.json
new file mode 100644
index 0000000..07206f8
--- /dev/null
+++ b/testVectors/gg20_zkp/phase3_commit.json
@@ -0,0 +1,62 @@
+[
+ {
+ "TEST": 0,
+ "A": "a0edd5b4d2c80b907fc54c480297f77c0804573e7c77e28c909ebab9e860de25",
+ "B": "364dc1be76f6846e39274ecf9b00ea8e026531a046f152e28787036bed1ecf18",
+ "C": "030773cfe787c7a9941db71e1c1760db1bbe5d5ff74fcf2a42f729a7d7abba69a2"
+ },
+ {
+ "TEST": 1,
+ "A": "a54f755af7c10d7d97cd06d4782315ae123d42810034f7d4c55f9b870460156e",
+ "B": "7df16cb8e67b2d77035952d2611e21f6e7f51c120b35ea6f1740460d34abe8cc",
+ "C": "03905a11c91f4720700fb8290698788026552d9437c1e359a6f58d71ac9b3f3ce6"
+ },
+ {
+ "TEST": 2,
+ "A": "5f53ca3702ec3da889d0973108ce477a8462f51fbbd8c1bba1124ebf97fcf3fd",
+ "B": "b6e67fbaa4a2d57145853a85085d25ceaea25f65843095eb733a61eff0df6a2d",
+ "C": "031857e5f3eefde534c0a259e6394cb449cf51c1286956682b52b18519e5118a76"
+ },
+ {
+ "TEST": 3,
+ "A": "4d6eb39b268d5720f896ed72ba78e4997cf14e4abe85c432144ea7c95bc678ad",
+ "B": "bbcb79743e4a4995a64d2acb2921da36e6a3e50fd9a8b1a6c1c6adb6d3cebfad",
+ "C": "03e5f510082f59c5287b807ba8d8f1cb379ff0ca00d2d502791bd47552c06a4df6"
+ },
+ {
+ "TEST": 4,
+ "A": "ec435643a44de0eae104b552b1d37b47f4f0f01519d1c3561f2a9455711a831e",
+ "B": "37e83c3516929e9efd4635d421424173545daf91173c71bce2fcd5941bf5e6f4",
+ "C": "0308849364e0a3a5ce1d5afa56cdce1a1135f2d0f81e55f497e7d18148e4e9410f"
+ },
+ {
+ "TEST": 5,
+ "A": "82ebfdea537c424300d95efb7df11bd11d10cc7b6f5b7719d9453d322ffb5b99",
+ "B": "8d8255f6b119d624db24b1cb314ab176ff86a9c4c8b6d8a75f7d27b6e782591e",
+ "C": "038afd7cbc2d0354aece112bbcca28ce0acccd0b5ff57db307cc8fd938c9a57255"
+ },
+ {
+ "TEST": 6,
+ "A": "ffd2f3dfde7003eb5adaf7c102b1e2c2d1720122eb66931d8ffef2f06c5dc5bc",
+ "B": "c05070559e971f0c794b6b310fb47de3b2971b98d99faff9843c1dab9f7f4407",
+ "C": "03a58deb3ec6359cb309d22ad889cdeb77ef229bd43d1ad66ba583f74d33e25aee"
+ },
+ {
+ "TEST": 7,
+ "A": "fa02c28fe4b0ad42a7e268430d2e6ea5bbc4cf5026582e9f143b5b94102280cb",
+ "B": "ac59c363be14ddcc3528fa8a2eb95fe20b577bff7d50e8a210ab62b72d9a138f",
+ "C": "03dc643c3a18a0fa4a38d6d072143d9a351100e6e383b3ee06aa75be806b4aef17"
+ },
+ {
+ "TEST": 8,
+ "A": "498ffb6510deac034014ab028abed96ffdf6191866061c92478966e69ea85dda",
+ "B": "a2a00a33092103346dcefa66f1820aef5180a752475ce17ca9e2e9287999cda8",
+ "C": "02ff67db861bf0a41b24f4de08cb332424aac174fa526993c246d88c3da38dd90a"
+ },
+ {
+ "TEST": 9,
+ "A": "e96afdc9381612b3c8eb6e0ed6f928b24e6513d91c15d8a0cda184746a69bbf5",
+ "B": "2d404a6a440abb043ec2fdd93aefe02617b182cf20d41e69bfee192051188299",
+ "C": "0315dbf65e577707b07175d486337d1a499d7074a3177f9add8660e709492338b8"
+ }
+]
\ No newline at end of file
diff --git a/testVectors/gg20_zkp/phase3_commit.txt b/testVectors/gg20_zkp/phase3_commit.txt
new file mode 100644
index 0000000..4f15b2a
--- /dev/null
+++ b/testVectors/gg20_zkp/phase3_commit.txt
@@ -0,0 +1,50 @@
+TEST = 0,
+A = a0edd5b4d2c80b907fc54c480297f77c0804573e7c77e28c909ebab9e860de25,
+B = 364dc1be76f6846e39274ecf9b00ea8e026531a046f152e28787036bed1ecf18,
+C = 030773cfe787c7a9941db71e1c1760db1bbe5d5ff74fcf2a42f729a7d7abba69a2,
+
+TEST = 1,
+A = a54f755af7c10d7d97cd06d4782315ae123d42810034f7d4c55f9b870460156e,
+B = 7df16cb8e67b2d77035952d2611e21f6e7f51c120b35ea6f1740460d34abe8cc,
+C = 03905a11c91f4720700fb8290698788026552d9437c1e359a6f58d71ac9b3f3ce6,
+
+TEST = 2,
+A = 5f53ca3702ec3da889d0973108ce477a8462f51fbbd8c1bba1124ebf97fcf3fd,
+B = b6e67fbaa4a2d57145853a85085d25ceaea25f65843095eb733a61eff0df6a2d,
+C = 031857e5f3eefde534c0a259e6394cb449cf51c1286956682b52b18519e5118a76,
+
+TEST = 3,
+A = 4d6eb39b268d5720f896ed72ba78e4997cf14e4abe85c432144ea7c95bc678ad,
+B = bbcb79743e4a4995a64d2acb2921da36e6a3e50fd9a8b1a6c1c6adb6d3cebfad,
+C = 03e5f510082f59c5287b807ba8d8f1cb379ff0ca00d2d502791bd47552c06a4df6,
+
+TEST = 4,
+A = ec435643a44de0eae104b552b1d37b47f4f0f01519d1c3561f2a9455711a831e,
+B = 37e83c3516929e9efd4635d421424173545daf91173c71bce2fcd5941bf5e6f4,
+C = 0308849364e0a3a5ce1d5afa56cdce1a1135f2d0f81e55f497e7d18148e4e9410f,
+
+TEST = 5,
+A = 82ebfdea537c424300d95efb7df11bd11d10cc7b6f5b7719d9453d322ffb5b99,
+B = 8d8255f6b119d624db24b1cb314ab176ff86a9c4c8b6d8a75f7d27b6e782591e,
+C = 038afd7cbc2d0354aece112bbcca28ce0acccd0b5ff57db307cc8fd938c9a57255,
+
+TEST = 6,
+A = ffd2f3dfde7003eb5adaf7c102b1e2c2d1720122eb66931d8ffef2f06c5dc5bc,
+B = c05070559e971f0c794b6b310fb47de3b2971b98d99faff9843c1dab9f7f4407,
+C = 03a58deb3ec6359cb309d22ad889cdeb77ef229bd43d1ad66ba583f74d33e25aee,
+
+TEST = 7,
+A = fa02c28fe4b0ad42a7e268430d2e6ea5bbc4cf5026582e9f143b5b94102280cb,
+B = ac59c363be14ddcc3528fa8a2eb95fe20b577bff7d50e8a210ab62b72d9a138f,
+C = 03dc643c3a18a0fa4a38d6d072143d9a351100e6e383b3ee06aa75be806b4aef17,
+
+TEST = 8,
+A = 498ffb6510deac034014ab028abed96ffdf6191866061c92478966e69ea85dda,
+B = a2a00a33092103346dcefa66f1820aef5180a752475ce17ca9e2e9287999cda8,
+C = 02ff67db861bf0a41b24f4de08cb332424aac174fa526993c246d88c3da38dd90a,
+
+TEST = 9,
+A = e96afdc9381612b3c8eb6e0ed6f928b24e6513d91c15d8a0cda184746a69bbf5,
+B = 2d404a6a440abb043ec2fdd93aefe02617b182cf20d41e69bfee192051188299,
+C = 0315dbf65e577707b07175d486337d1a499d7074a3177f9add8660e709492338b8,
+
diff --git a/testVectors/gg20_zkp/phase3_prove.json b/testVectors/gg20_zkp/phase3_prove.json
new file mode 100644
index 0000000..a8a0711
--- /dev/null
+++ b/testVectors/gg20_zkp/phase3_prove.json
@@ -0,0 +1,102 @@
+[
+ {
+ "TEST": 0,
+ "A": "cb9805c14b825c898b03281716fa3baac4fed1d081f26f3335237b2375ecdf25",
+ "B": "275fe3e42d66b3db53cdfc0e6307a4bfbfa10fc11c84fde66cb728b11b99aaba",
+ "E": "a05d5bdd616d9bbc72bee04e72bc045026be6a355183c7704e122f614ab607be",
+ "S": "07051d73757dca22d877ca18610194d6713a815c081c1fccb818cb17f4f55ffd",
+ "L": "64152434654ae61db2a9d9a0132a7dbb9c5eb5c8b491018683d563a10804f436",
+ "T": "66acee60b6318fcdbecddd22ef73589e61b8ab63432aa4927898539f93687728",
+ "U": "2600691de9fb297862476be002ad22a9c5b697f1237793c132bbc8555aab4849"
+ },
+ {
+ "TEST": 1,
+ "A": "9e89d4a2c83d2a5a843cd092969a9c625a62d84a754043e2b4d486f53c615819",
+ "B": "4a2c793806ba9fa56167f178dede03150c9f17993b36c412491e01043c0d9294",
+ "E": "8aefe199192c99baf7da45978063c799e754b252bb40f06d826da05db08b4e28",
+ "S": "983247c2d5eec09633afb1b28db3e7cedfc321cbc8dca864389ddbb139181655",
+ "L": "d932677581e35a7e679eceffa029193173db013b4a3a787c2944c47ea8a6f71c",
+ "T": "81fd655525685886f9bb8fef01f00bac1370e1da5872054447a069c2b45a7e9b",
+ "U": "6910582b4cefb1621e8d09d789cf4342b26b9b077463aaab2fd62aaf5e92f5a7"
+ },
+ {
+ "TEST": 2,
+ "A": "ae01ecfe3747020e4c9300782b2e1db9ab883356dc77a54774f2755bdf1203f3",
+ "B": "749050d6a83aa5ecf943db78f0b686c7d094fd37c95f535849e6c0e16394a491",
+ "E": "aeb915132914f2d4773002d7afb3e4ccd0f7c78be0b40380671cda08480d3e10",
+ "S": "6e1c4094280821e95f6051dd0bc9f2b4009ca84195a9140533f4032ce0fef491",
+ "L": "dd5a97559d9defd22805e35b5b22c35ecd94bc3667069b1e5977c001e377e8e6",
+ "T": "941f3cc74204fc2811f5aa31f33b8e2c5bef4958448c4aa200cee38c4b592206",
+ "U": "2a5f42f32f32399f69844a4e2bc04cb69d65d69c92e96178e44cced18ac8e167"
+ },
+ {
+ "TEST": 3,
+ "A": "ae8caf22f68275ac14099909068c3a36d6a3214412d413e6200bc5734b36b722",
+ "B": "3cf6351ecfa07702ff36111b4805f8f6d150a67c7a04849b6536ff2d702b5f93",
+ "E": "449a3ef8f76e1942386da035a6257e85fd4dcda0b2e537f11b7acc06c55935ef",
+ "S": "3a6086b1b4a564074e366e52531be77d892e74e24ebcbfb96c584555aa95ebef",
+ "L": "e8421eef435bbf01582c6020a23ccdf4b342a019f9b349ffad5e90deb54dccfd",
+ "T": "34a6c9e13a4e02dc86e248af2a48c5ef8980031d8ebbe316bfbe5e6637db56d8",
+ "U": "36ba7fa7b2823c14bd756ecd7c06f75195529a5a6b8b945b319ca00558332274"
+ },
+ {
+ "TEST": 4,
+ "A": "9eec4667cc3c9e82b140d53da7ab12985b5492d6a2c3ba889ce656ca85122ec3",
+ "B": "6a5d1f0ef028747d959292bd4075add723c68f4bd932743cbcd58989b39105dd",
+ "E": "aab7aace82d0f0fe4131e3543dbed99d99b49b254ace9aa506fbd87bfcc1a0ce",
+ "S": "180ada88c2251413676b334e0ebd4e21193a5ce36f56df390be7882fc9b7bb67",
+ "L": "2cd12668c480fe23c13744bffeeca18e9fb50e8fefbd7982105d2701668c9bba",
+ "T": "ee673c77d320e127ea49093b23d169f6c4345e6d26e65d4499097d208bfaa87b",
+ "U": "6ecde180aa8a032d7a4b28993e44fc880d83fca83c1cc7831190989c42dd941e"
+ },
+ {
+ "TEST": 5,
+ "A": "85062da0e3f1dcc4eef63cc5f464df5d8b0645197b93dcc1081668bd9959483f",
+ "B": "38cb62a0a116a027f006401b61da2f4a67bc21af1ee90f0d78b0aad6e7b8660a",
+ "E": "84fca2de11cdf2bdb40bef141908887d904c8cd88f3c8f1fb58684a8cdb6c36b",
+ "S": "ec1928bc7633ea64d958c87f4dce8d1f92f4470c89d2dbd9a0bcab78addb7406",
+ "L": "6c59d9854aa263c7c55b17b25bfc0622e9005e9fede95ff4429bb32253fdd2ab",
+ "T": "b12bd41c9d68375ea89dd6e20c410175c3812f4251756345d6a66460fa6f89fa",
+ "U": "ddc340dc4f5e73bc95ef16ca641571a4252dab6e620d4e15b476727ec24cc233"
+ },
+ {
+ "TEST": 6,
+ "A": "5d0913b12b751ad4d04b3a3b9e50161c7cc7df43dbbac49d0e6ac1db3a09f27d",
+ "B": "7e2a66aae55e73baba851ca3f5ce8b4db1e84bd31d6bebbbb17aa6ef660edf33",
+ "E": "4d06e19d49851e42015e788a57b0668a609f9d5a3dad3e6b17aea969c5a0b8a9",
+ "S": "58cf2c473821475f02f05f488e064dde4f0c512899269594270d45d121615517",
+ "L": "39411ef7b8c30d0de2e3ff6ad210e6b97f6393579f92644acb54a4de0ca63448",
+ "T": "b1e8f902af4db8af60d5a2f84db34e4bf87ec381a3d1cdee7806c38f978da505",
+ "U": "2d54c4b7802b98456a9995af65696bb821352cceec9b496304f6c4f3601f02ea"
+ },
+ {
+ "TEST": 7,
+ "A": "f745d69d473fd9dbe04d96f4faff200d4008f3d1087be44c7a1717bee009f53c",
+ "B": "58759d84dbd02b20caaea6b5e92a2a1c262ad41057aca1a211902b2cf5bb6541",
+ "E": "8376c812f6c88b79d9bc908a1441ba94ac6ca511a860b295c48d8c48cad5fee0",
+ "S": "a982ed831b7fffc7b7f3179c2f5d1fed78b724096e8a22390c7760fe78fde324",
+ "L": "2c4c7be22d125402ba2de4dbf54d838c1cc5bfcb27101ec1f2f77d5afc8a123a",
+ "T": "d932de6113c941ac01a12fff7e6fd6700b4d7fb5293559ea6e99b6a61ef213af",
+ "U": "2074cf4cc1683f5518af734558abab4b41a07b87449fa199896660f978badcbf"
+ },
+ {
+ "TEST": 8,
+ "A": "6ffeee4e0d42c52adfa5a2c42f6f1c5762bb6094b164582c08dcd46b99f920b2",
+ "B": "0151835c109674131c20cafe1778ea2ce772f496269ff3ef55171e69c5840107",
+ "E": "e8803eddc165604f852d3faafd3958255c18e1c692f3663ef0b1798a613b6c30",
+ "S": "ec90afce0a28e498a89a582b67f58fadc45f307bedb981bf6153f2d7fc3ca6cd",
+ "L": "dcbd6545e11499ae13470bd689f3ecb203669e99a5077ab9e1cd8481790520b0",
+ "T": "d5c4fa580680643afdd91650cde82a4a417120adecd04c67d98f7d1254f3b38b",
+ "U": "ddf7c9345fd0590affa8e7b6ef7d56929b097ef16e0c63a7c85a5dd437928775"
+ },
+ {
+ "TEST": 9,
+ "A": "650b0680dec70fa7683a361e8347be4401b3ed90858d5c01b5c3b9d42de6cc12",
+ "B": "b88fbc1e2b93dfaedb0885bb52bb51c841b93941989a7d61e713f93065432e85",
+ "E": "31de91626dff5d62fe193b3710b7ff39798a6f34c02ae2246edf8fd6da555b1c",
+ "S": "af3d203f370b67441bb5cc65348cb54a043985e573958e04eccca61f6a4ada9a",
+ "L": "752508bba08fc69838c6f75ede9edd0ca9ad7bc99e2222dc46c2f91f0e9e96a5",
+ "T": "625e09fa9aeb0144f99cf6df869938f3132c4bcba72804d0ab627b35ffd0c19e",
+ "U": "9c0bf3c5d4a6b0a5933184fffd0365ba4bc72c1a526ca2c7d0d8f4b5d7ca48b0"
+ }
+]
\ No newline at end of file
diff --git a/testVectors/gg20_zkp/phase3_prove.txt b/testVectors/gg20_zkp/phase3_prove.txt
new file mode 100644
index 0000000..7231456
--- /dev/null
+++ b/testVectors/gg20_zkp/phase3_prove.txt
@@ -0,0 +1,90 @@
+TEST = 0,
+A = cb9805c14b825c898b03281716fa3baac4fed1d081f26f3335237b2375ecdf25,
+B = 275fe3e42d66b3db53cdfc0e6307a4bfbfa10fc11c84fde66cb728b11b99aaba,
+E = a05d5bdd616d9bbc72bee04e72bc045026be6a355183c7704e122f614ab607be,
+S = 07051d73757dca22d877ca18610194d6713a815c081c1fccb818cb17f4f55ffd,
+L = 64152434654ae61db2a9d9a0132a7dbb9c5eb5c8b491018683d563a10804f436,
+T = 66acee60b6318fcdbecddd22ef73589e61b8ab63432aa4927898539f93687728,
+U = 2600691de9fb297862476be002ad22a9c5b697f1237793c132bbc8555aab4849,
+
+TEST = 1,
+A = 9e89d4a2c83d2a5a843cd092969a9c625a62d84a754043e2b4d486f53c615819,
+B = 4a2c793806ba9fa56167f178dede03150c9f17993b36c412491e01043c0d9294,
+E = 8aefe199192c99baf7da45978063c799e754b252bb40f06d826da05db08b4e28,
+S = 983247c2d5eec09633afb1b28db3e7cedfc321cbc8dca864389ddbb139181655,
+L = d932677581e35a7e679eceffa029193173db013b4a3a787c2944c47ea8a6f71c,
+T = 81fd655525685886f9bb8fef01f00bac1370e1da5872054447a069c2b45a7e9b,
+U = 6910582b4cefb1621e8d09d789cf4342b26b9b077463aaab2fd62aaf5e92f5a7,
+
+TEST = 2,
+A = ae01ecfe3747020e4c9300782b2e1db9ab883356dc77a54774f2755bdf1203f3,
+B = 749050d6a83aa5ecf943db78f0b686c7d094fd37c95f535849e6c0e16394a491,
+E = aeb915132914f2d4773002d7afb3e4ccd0f7c78be0b40380671cda08480d3e10,
+S = 6e1c4094280821e95f6051dd0bc9f2b4009ca84195a9140533f4032ce0fef491,
+L = dd5a97559d9defd22805e35b5b22c35ecd94bc3667069b1e5977c001e377e8e6,
+T = 941f3cc74204fc2811f5aa31f33b8e2c5bef4958448c4aa200cee38c4b592206,
+U = 2a5f42f32f32399f69844a4e2bc04cb69d65d69c92e96178e44cced18ac8e167,
+
+TEST = 3,
+A = ae8caf22f68275ac14099909068c3a36d6a3214412d413e6200bc5734b36b722,
+B = 3cf6351ecfa07702ff36111b4805f8f6d150a67c7a04849b6536ff2d702b5f93,
+E = 449a3ef8f76e1942386da035a6257e85fd4dcda0b2e537f11b7acc06c55935ef,
+S = 3a6086b1b4a564074e366e52531be77d892e74e24ebcbfb96c584555aa95ebef,
+L = e8421eef435bbf01582c6020a23ccdf4b342a019f9b349ffad5e90deb54dccfd,
+T = 34a6c9e13a4e02dc86e248af2a48c5ef8980031d8ebbe316bfbe5e6637db56d8,
+U = 36ba7fa7b2823c14bd756ecd7c06f75195529a5a6b8b945b319ca00558332274,
+
+TEST = 4,
+A = 9eec4667cc3c9e82b140d53da7ab12985b5492d6a2c3ba889ce656ca85122ec3,
+B = 6a5d1f0ef028747d959292bd4075add723c68f4bd932743cbcd58989b39105dd,
+E = aab7aace82d0f0fe4131e3543dbed99d99b49b254ace9aa506fbd87bfcc1a0ce,
+S = 180ada88c2251413676b334e0ebd4e21193a5ce36f56df390be7882fc9b7bb67,
+L = 2cd12668c480fe23c13744bffeeca18e9fb50e8fefbd7982105d2701668c9bba,
+T = ee673c77d320e127ea49093b23d169f6c4345e6d26e65d4499097d208bfaa87b,
+U = 6ecde180aa8a032d7a4b28993e44fc880d83fca83c1cc7831190989c42dd941e,
+
+TEST = 5,
+A = 85062da0e3f1dcc4eef63cc5f464df5d8b0645197b93dcc1081668bd9959483f,
+B = 38cb62a0a116a027f006401b61da2f4a67bc21af1ee90f0d78b0aad6e7b8660a,
+E = 84fca2de11cdf2bdb40bef141908887d904c8cd88f3c8f1fb58684a8cdb6c36b,
+S = ec1928bc7633ea64d958c87f4dce8d1f92f4470c89d2dbd9a0bcab78addb7406,
+L = 6c59d9854aa263c7c55b17b25bfc0622e9005e9fede95ff4429bb32253fdd2ab,
+T = b12bd41c9d68375ea89dd6e20c410175c3812f4251756345d6a66460fa6f89fa,
+U = ddc340dc4f5e73bc95ef16ca641571a4252dab6e620d4e15b476727ec24cc233,
+
+TEST = 6,
+A = 5d0913b12b751ad4d04b3a3b9e50161c7cc7df43dbbac49d0e6ac1db3a09f27d,
+B = 7e2a66aae55e73baba851ca3f5ce8b4db1e84bd31d6bebbbb17aa6ef660edf33,
+E = 4d06e19d49851e42015e788a57b0668a609f9d5a3dad3e6b17aea969c5a0b8a9,
+S = 58cf2c473821475f02f05f488e064dde4f0c512899269594270d45d121615517,
+L = 39411ef7b8c30d0de2e3ff6ad210e6b97f6393579f92644acb54a4de0ca63448,
+T = b1e8f902af4db8af60d5a2f84db34e4bf87ec381a3d1cdee7806c38f978da505,
+U = 2d54c4b7802b98456a9995af65696bb821352cceec9b496304f6c4f3601f02ea,
+
+TEST = 7,
+A = f745d69d473fd9dbe04d96f4faff200d4008f3d1087be44c7a1717bee009f53c,
+B = 58759d84dbd02b20caaea6b5e92a2a1c262ad41057aca1a211902b2cf5bb6541,
+E = 8376c812f6c88b79d9bc908a1441ba94ac6ca511a860b295c48d8c48cad5fee0,
+S = a982ed831b7fffc7b7f3179c2f5d1fed78b724096e8a22390c7760fe78fde324,
+L = 2c4c7be22d125402ba2de4dbf54d838c1cc5bfcb27101ec1f2f77d5afc8a123a,
+T = d932de6113c941ac01a12fff7e6fd6700b4d7fb5293559ea6e99b6a61ef213af,
+U = 2074cf4cc1683f5518af734558abab4b41a07b87449fa199896660f978badcbf,
+
+TEST = 8,
+A = 6ffeee4e0d42c52adfa5a2c42f6f1c5762bb6094b164582c08dcd46b99f920b2,
+B = 0151835c109674131c20cafe1778ea2ce772f496269ff3ef55171e69c5840107,
+E = e8803eddc165604f852d3faafd3958255c18e1c692f3663ef0b1798a613b6c30,
+S = ec90afce0a28e498a89a582b67f58fadc45f307bedb981bf6153f2d7fc3ca6cd,
+L = dcbd6545e11499ae13470bd689f3ecb203669e99a5077ab9e1cd8481790520b0,
+T = d5c4fa580680643afdd91650cde82a4a417120adecd04c67d98f7d1254f3b38b,
+U = ddf7c9345fd0590affa8e7b6ef7d56929b097ef16e0c63a7c85a5dd437928775,
+
+TEST = 9,
+A = 650b0680dec70fa7683a361e8347be4401b3ed90858d5c01b5c3b9d42de6cc12,
+B = b88fbc1e2b93dfaedb0885bb52bb51c841b93941989a7d61e713f93065432e85,
+E = 31de91626dff5d62fe193b3710b7ff39798a6f34c02ae2246edf8fd6da555b1c,
+S = af3d203f370b67441bb5cc65348cb54a043985e573958e04eccca61f6a4ada9a,
+L = 752508bba08fc69838c6f75ede9edd0ca9ad7bc99e2222dc46c2f91f0e9e96a5,
+T = 625e09fa9aeb0144f99cf6df869938f3132c4bcba72804d0ab627b35ffd0c19e,
+U = 9c0bf3c5d4a6b0a5933184fffd0365ba4bc72c1a526ca2c7d0d8f4b5d7ca48b0,
+
diff --git a/testVectors/gg20_zkp/phase3_verify.json b/testVectors/gg20_zkp/phase3_verify.json
new file mode 100644
index 0000000..ffb54f5
--- /dev/null
+++ b/testVectors/gg20_zkp/phase3_verify.json
@@ -0,0 +1,82 @@
+[
+ {
+ "TEST": 0,
+ "V": "02caf97404649fb0c3322a2ec2a0905aa0dd89e256e08b4543bb8b9a2d91563e63",
+ "C": "02d2e0cf0d7780db39d2f9eb21b8fa5c2c02990898535f30e54374221f9636dd46",
+ "E": "f8a8ee7dbe3c12a674fba0cef4d6cf9fdfd384d41045f9652bdce2a8667aaccb",
+ "T": "73a1ac5734453d3bd41b0044d064dc51fc327d17f4454d99d3055c31f06f7929",
+ "U": "66bfbbf3b5c1cdd5369dd32443c46a9becb74663ee16eae0ac6f3264783fb967"
+ },
+ {
+ "TEST": 1,
+ "V": "0330718a71cfdc42b829e2df4668ee073d8e5f6e9f58de4b1f4a8c9a78fd79a92e",
+ "C": "02bc011ea0ef994372aa0f9f3e0b6df00a0cb525be2faea08165978b6955bffbfb",
+ "E": "1afa41e8af97edf2a0843b7baa5ce134c2ae9cc27042692e9597084d7e396d15",
+ "T": "3accdec2afb6a0c68fc20a2f00aa6d0944f181b8641c5d0838b709080719ad66",
+ "U": "ef97580c9b04576faa4d25edc506ba2c7ddb7d726a78449d320a5e2aa92afd2b"
+ },
+ {
+ "TEST": 2,
+ "V": "02404dd2c8c188bbdd4506ac959f84e425b82a0880a0945755cb715ff58f4bfec1",
+ "C": "0303f889b066feb0888ebefcc5595e184d22a0224ee3db6e2b3e017cccb6934e67",
+ "E": "ff4a29be578c91d68785a031c9eb890d8ef84eedde55b3b45c4bc041ecd144ad",
+ "T": "ad1e1e0952ef6a88110e503b0507870871f0aae4dba46d571afaacc341a05838",
+ "U": "00cc4a14d1fd95bc41fd2b8c722d8c78c552c10f27724748085dfa81ee9c280c"
+ },
+ {
+ "TEST": 3,
+ "V": "034a01512bfb1e41c6ea31a46fa3ca292506a532325559b63e8546ec570e15ec70",
+ "C": "03a2b9796c1afab3ffd6c941eac65c480f77d6adb8d9c202de625d4a638b4d717f",
+ "E": "8be434c5e97ac5235b48ad74abf67b484734609e6d86061bc3baa6ca51d25e13",
+ "T": "338262276b185f23b22f0e81147bc11f3942278648f0dee3c6130a9e4528deb7",
+ "U": "b5007f16c5cec34799d8ab3c11521bf9e8e308595b1428414c6011af7f0a7b0d"
+ },
+ {
+ "TEST": 4,
+ "V": "031f326ee2b6516392b2264bc4250417b7d9c1f8a1d2f9d3982e281547a0d1202f",
+ "C": "0351a76b3dd3e952865a810ebe5f4b817afd2068f88f4dca966be9819066de1bde",
+ "E": "5b631d30d3b0a88d13437c6e0433d4a3029eea4462a7f955db35a35a2d614ff2",
+ "T": "267501982dcd76ac6a33b12f11062aefa1a9e438c70c76fd441c76fcca13d0e6",
+ "U": "a176ca15c29b6983995b7c523ae552bedf55d77b0cae47e5e0d3fe30d80e37d1"
+ },
+ {
+ "TEST": 5,
+ "V": "02e1fafe90dfcbf1c785419d4a4e72befe74523b1c60b43d8b38b10de3f29a6754",
+ "C": "021f475f5670660eed6c5113a816f1e8edfb190373b514cf558e30fa77172b0430",
+ "E": "dae91da06071d586bd11c2fcf9ce825171112974cf2caa1b8050867d6c36d9b9",
+ "T": "7379d9994d8f4ea5bbae8728c70d784e5f9c71daed6a1b531950b89ddc933c09",
+ "U": "3e13309cf6b4867f307c9ae02b9838ee2324f5b61ad42d134fcde4cf21166869"
+ },
+ {
+ "TEST": 6,
+ "V": "0210d5be90b83e654da4267503a9cc00a3610ab948e25f77aebada2b7d12705aa6",
+ "C": "02afd060a0ebd3ce012514dffbc2be0a70b315bbb5d62d3e72e9401be92e71794e",
+ "E": "9b2cde1d21de47296cb8811818c670056ad555104ffd868917920a80982447f2",
+ "T": "ab1e867cc9c890da4f9d8ad31351bd72d3bdd27e9d9a5ef3a796195367cd3671",
+ "U": "8508f58d0262260a4ffacfeb99d2427da4486d362347f3017b9938cc687b68e6"
+ },
+ {
+ "TEST": 7,
+ "V": "0309e693f283a54f188f5c378c353b12cfdcd374b901d86a8532be20f0e27f943f",
+ "C": "02029af8ca721b2daa9d0f9bdb44b0574ca4988c153c65d4c4d557d99838f14da0",
+ "E": "296bf112d3a89ed5bba4e4415635ce694c3ac268040293868505eff1fecd7b78",
+ "T": "dccbf07ca8756eea746abc1a4a8d63713855c7cfdc774f9af5a541d32b3709dc",
+ "U": "36d8502dd38c08eb50e9542a24a76501d327484c2330b04c471ac4d12eeba61b"
+ },
+ {
+ "TEST": 8,
+ "V": "03021294323293aadd733fd13fab1dc576020e56fa3c57523b6d2fa50b1f23098f",
+ "C": "02b14488d16bb85f0886783cda8d9243877846952cbadfe94ddcb778ad684ced31",
+ "E": "ad3227111c986626d930b3a676e8a7fb83bb198d4325b073c3103c4b4d7bb60d",
+ "T": "d928893084dba94030cfef37f55bbbb9d430c7b62585530ccad09028e3486c65",
+ "U": "9c915549fad8e8b1b30d4b611f2a2f342c36419eeffc95c8c8d25149d0552bb3"
+ },
+ {
+ "TEST": 9,
+ "V": "02d00e227702127cbd26940ff8cdfc70ccb864234ec878dd21772a0fb6b1cc0bcc",
+ "C": "028f20c5ae0a3926e3faa7fdd2f1a51c9c097edfb406cfbb4ee4bda4652be346ff",
+ "E": "21be94962dd0c84a42f3b94dc71e6cfcdfd1f6001c471e7b60250acdb2d8556b",
+ "T": "ba6b049fdf7c46e52ce15d07a5cf582c91a380dbd4e896c76569245cf997a9cf",
+ "U": "15247bb2dcdb6d82e4134c1cda043edcff74d7983b8bb488c37decb83f950299"
+ }
+]
\ No newline at end of file
diff --git a/testVectors/gg20_zkp/phase3_verify.txt b/testVectors/gg20_zkp/phase3_verify.txt
new file mode 100644
index 0000000..be8ed49
--- /dev/null
+++ b/testVectors/gg20_zkp/phase3_verify.txt
@@ -0,0 +1,70 @@
+TEST = 0,
+V = 02caf97404649fb0c3322a2ec2a0905aa0dd89e256e08b4543bb8b9a2d91563e63,
+C = 02d2e0cf0d7780db39d2f9eb21b8fa5c2c02990898535f30e54374221f9636dd46,
+E = f8a8ee7dbe3c12a674fba0cef4d6cf9fdfd384d41045f9652bdce2a8667aaccb,
+T = 73a1ac5734453d3bd41b0044d064dc51fc327d17f4454d99d3055c31f06f7929,
+U = 66bfbbf3b5c1cdd5369dd32443c46a9becb74663ee16eae0ac6f3264783fb967,
+
+TEST = 1,
+V = 0330718a71cfdc42b829e2df4668ee073d8e5f6e9f58de4b1f4a8c9a78fd79a92e,
+C = 02bc011ea0ef994372aa0f9f3e0b6df00a0cb525be2faea08165978b6955bffbfb,
+E = 1afa41e8af97edf2a0843b7baa5ce134c2ae9cc27042692e9597084d7e396d15,
+T = 3accdec2afb6a0c68fc20a2f00aa6d0944f181b8641c5d0838b709080719ad66,
+U = ef97580c9b04576faa4d25edc506ba2c7ddb7d726a78449d320a5e2aa92afd2b,
+
+TEST = 2,
+V = 02404dd2c8c188bbdd4506ac959f84e425b82a0880a0945755cb715ff58f4bfec1,
+C = 0303f889b066feb0888ebefcc5595e184d22a0224ee3db6e2b3e017cccb6934e67,
+E = ff4a29be578c91d68785a031c9eb890d8ef84eedde55b3b45c4bc041ecd144ad,
+T = ad1e1e0952ef6a88110e503b0507870871f0aae4dba46d571afaacc341a05838,
+U = 00cc4a14d1fd95bc41fd2b8c722d8c78c552c10f27724748085dfa81ee9c280c,
+
+TEST = 3,
+V = 034a01512bfb1e41c6ea31a46fa3ca292506a532325559b63e8546ec570e15ec70,
+C = 03a2b9796c1afab3ffd6c941eac65c480f77d6adb8d9c202de625d4a638b4d717f,
+E = 8be434c5e97ac5235b48ad74abf67b484734609e6d86061bc3baa6ca51d25e13,
+T = 338262276b185f23b22f0e81147bc11f3942278648f0dee3c6130a9e4528deb7,
+U = b5007f16c5cec34799d8ab3c11521bf9e8e308595b1428414c6011af7f0a7b0d,
+
+TEST = 4,
+V = 031f326ee2b6516392b2264bc4250417b7d9c1f8a1d2f9d3982e281547a0d1202f,
+C = 0351a76b3dd3e952865a810ebe5f4b817afd2068f88f4dca966be9819066de1bde,
+E = 5b631d30d3b0a88d13437c6e0433d4a3029eea4462a7f955db35a35a2d614ff2,
+T = 267501982dcd76ac6a33b12f11062aefa1a9e438c70c76fd441c76fcca13d0e6,
+U = a176ca15c29b6983995b7c523ae552bedf55d77b0cae47e5e0d3fe30d80e37d1,
+
+TEST = 5,
+V = 02e1fafe90dfcbf1c785419d4a4e72befe74523b1c60b43d8b38b10de3f29a6754,
+C = 021f475f5670660eed6c5113a816f1e8edfb190373b514cf558e30fa77172b0430,
+E = dae91da06071d586bd11c2fcf9ce825171112974cf2caa1b8050867d6c36d9b9,
+T = 7379d9994d8f4ea5bbae8728c70d784e5f9c71daed6a1b531950b89ddc933c09,
+U = 3e13309cf6b4867f307c9ae02b9838ee2324f5b61ad42d134fcde4cf21166869,
+
+TEST = 6,
+V = 0210d5be90b83e654da4267503a9cc00a3610ab948e25f77aebada2b7d12705aa6,
+C = 02afd060a0ebd3ce012514dffbc2be0a70b315bbb5d62d3e72e9401be92e71794e,
+E = 9b2cde1d21de47296cb8811818c670056ad555104ffd868917920a80982447f2,
+T = ab1e867cc9c890da4f9d8ad31351bd72d3bdd27e9d9a5ef3a796195367cd3671,
+U = 8508f58d0262260a4ffacfeb99d2427da4486d362347f3017b9938cc687b68e6,
+
+TEST = 7,
+V = 0309e693f283a54f188f5c378c353b12cfdcd374b901d86a8532be20f0e27f943f,
+C = 02029af8ca721b2daa9d0f9bdb44b0574ca4988c153c65d4c4d557d99838f14da0,
+E = 296bf112d3a89ed5bba4e4415635ce694c3ac268040293868505eff1fecd7b78,
+T = dccbf07ca8756eea746abc1a4a8d63713855c7cfdc774f9af5a541d32b3709dc,
+U = 36d8502dd38c08eb50e9542a24a76501d327484c2330b04c471ac4d12eeba61b,
+
+TEST = 8,
+V = 03021294323293aadd733fd13fab1dc576020e56fa3c57523b6d2fa50b1f23098f,
+C = 02b14488d16bb85f0886783cda8d9243877846952cbadfe94ddcb778ad684ced31,
+E = ad3227111c986626d930b3a676e8a7fb83bb198d4325b073c3103c4b4d7bb60d,
+T = d928893084dba94030cfef37f55bbbb9d430c7b62585530ccad09028e3486c65,
+U = 9c915549fad8e8b1b30d4b611f2a2f342c36419eeffc95c8c8d25149d0552bb3,
+
+TEST = 9,
+V = 02d00e227702127cbd26940ff8cdfc70ccb864234ec878dd21772a0fb6b1cc0bcc,
+C = 028f20c5ae0a3926e3faa7fdd2f1a51c9c097edfb406cfbb4ee4bda4652be346ff,
+E = 21be94962dd0c84a42f3b94dc71e6cfcdfd1f6001c471e7b60250acdb2d8556b,
+T = ba6b049fdf7c46e52ce15d07a5cf582c91a380dbd4e896c76569245cf997a9cf,
+U = 15247bb2dcdb6d82e4134c1cda043edcff74d7983b8bb488c37decb83f950299,
+
diff --git a/testVectors/gg20_zkp/phase6_challenge.json b/testVectors/gg20_zkp/phase6_challenge.json
new file mode 100644
index 0000000..1ccb34d
--- /dev/null
+++ b/testVectors/gg20_zkp/phase6_challenge.json
@@ -0,0 +1,112 @@
+[
+ {
+ "TEST": 0,
+ "R": "0354475938e75d0758f68802730fd684e47a39ae17b5cc7c11edede9bc8e2cd5d4",
+ "ECPT": "0309716b9647851724598b9dd81a5a9a5ceb6504d482e70723eb36c9d368889696",
+ "ECPS": "02389a9a1dd9353486be655cdb5ff19a12e7fc7e734642f5f376c331106f70f3f7",
+ "ALPHA": "039482cca8df14a76f75f1ad1999ced9c79e2a8a9273eb829adb054394eaf46025",
+ "BETA": "025f0379e1c8f3903b235a6cc3720e494acaac79bf696a397272f3abece30e7710",
+ "ID": "eeb100ac7e8fba9d1ab74903cdad83f1",
+ "AD": "",
+ "E": "f62cf3a81f5804e49645b5a3f8734adf128989554db41072f3f8b99334171a06"
+ },
+ {
+ "TEST": 1,
+ "R": "02ddb150fb1da230896a8c6927af2940ab173101a3f79e047319d8d63d32395998",
+ "ECPT": "0268afb804eb127a0d4e0d62c124623450d34794ac70659a1f49f8e3c99a245678",
+ "ECPS": "0359a4097cb654ac954abb35b146689434e4858a83ed7d85e394af9db9bf831745",
+ "ALPHA": "025c3e79194dbd97bfd3007eb07b8c38cab7222ca2efac5e9dcd3ca19f85bf78b1",
+ "BETA": "026aae66f4baed01b34473825fd26d4ca81f6381ba9d8479456352814334c5e793",
+ "ID": "353b15ce8cc5970c9f600676246a84c6",
+ "AD": "",
+ "E": "56faf16927b96f0b77c1f893748ffe084395dd56850aab3317b76e76894e2e7b"
+ },
+ {
+ "TEST": 2,
+ "R": "022a34247efebe83ca8b37038e6f77de6ace7d2b965b9c67d2eff94c1d0224f7a3",
+ "ECPT": "02cc5ec6e5b1685492776049d8597330e8c610b4522ea3b0fb102b87e354e53348",
+ "ECPS": "0331eab8a0f1f864d61526027c33f9c11251acca1132aafbd986d14b4bdf802a5e",
+ "ALPHA": "02387d3942d232ae24063e34a32e0746f6cdc1895f3c1b473ac2f4272ba201d6eb",
+ "BETA": "029185494c1b48bf0fd2ad5d3b0be61798194e95c13407ccba81d7f8f284e9e267",
+ "ID": "ef7ac188e34f2fb9e35db42481f26d47",
+ "AD": "",
+ "E": "22e0be495be895a7ebcfdb81b3dd05de631f167c141e47b8ca50b9afac3280bc"
+ },
+ {
+ "TEST": 3,
+ "R": "0390defac91dae4cc3f364d967719c678c0bd4ea251ba1054223fba9688adc3c56",
+ "ECPT": "035034f368f448a6a277225e3cdb124302fdc942eae6aa1b64a680aacf78869d0e",
+ "ECPS": "02a19b8481f7c8de6fb30c5031ae8a15490b0c2a758f9aefaaf15d3904321dad07",
+ "ALPHA": "02ca814f396e313972d00140567b12f7474a527fb9b390afb256fea46a7a7ecfa5",
+ "BETA": "029d318274c93a9ff8fd90073884659c82dafa66d16b19e0f52144521e794cbcc6",
+ "ID": "1b49574f4c21f41b39ce83332f41333d",
+ "AD": "",
+ "E": "2a5792e835e36cd16c486cda418a40d663113ac2c3ee302c17584462a4f41834"
+ },
+ {
+ "TEST": 4,
+ "R": "035ad96d26b6baf8aed78966f0a644ae736a900bde5d3cdde6c387d7d5a0b0f512",
+ "ECPT": "02161555ec9e569529c058c71352d45ac59ab76aab54df7e20f4a87871e6b673b8",
+ "ECPS": "027ca8c30011b57a3c91f716ba2ebd5156794d57bb96ffef78de66004e1b33c4a4",
+ "ALPHA": "025347b0712617cef345b2e4a2e18423b2161aadd98bbcb9c7bd8c1275e12a8971",
+ "BETA": "02cc2306e87e16bd67b48d2fc25870fa4eea231630d2100fcfbc6e81cd3a52b690",
+ "ID": "8f6d9b7701ec269ea270feb2ec91e318",
+ "AD": "",
+ "E": "5c389ad728f051ead0419585143e17f873072fc370f5ab854c0c6ea7bfb716a8"
+ },
+ {
+ "TEST": 5,
+ "R": "0279df7cf044d99369f9c93421bff3f78f6757c177e2f7f87d3567379ec9190c26",
+ "ECPT": "0334b3a774949b3591f28f02397e0c9ec66afac07f9f9e41b21c8057a7fcd4ca00",
+ "ECPS": "0237285d6b3efeceed33001c33f4d5f53de8b373b3fca5bb0b513541780fbdacaf",
+ "ALPHA": "03c71cf5c62fb9a156f9a03c4d906ce1ee8fbd4151ef2dee23aea639fe7c37d528",
+ "BETA": "03109e23bd81982f7785745354c2b028376d5907d1188429d8276d16a217ccd3d0",
+ "ID": "bfa83a06e6d2dd6f1a745ce02b174372",
+ "AD": "b06c21b98910963763693ed9449d98fd",
+ "E": "a6077eaa1c8ec1b012a29d783e07693116cc021289798de10fc739864ddeed31"
+ },
+ {
+ "TEST": 6,
+ "R": "024a4cc9696b93c927c20c3d91b831ee761b492b09b050c121b48ae4062122a747",
+ "ECPT": "0322cb50ba4c6b8532750d6cd19221e781850dfb144540fba3e731d98cb92e3a80",
+ "ECPS": "0251768a7ad18977533e7baf949684efa6b8bec022fa2a90ab909624c9bf4b7faa",
+ "ALPHA": "026cd424b8b53da925091aef993c902f4e26da7edb6ac8693f86151d4fd3a76c85",
+ "BETA": "02eeae4892bd107dfb893d05af3180a1dab884132e4254c71df1a97adf7f36e7ba",
+ "ID": "71db72ad3d3f60cb4125922ea03bf7d0",
+ "AD": "4469883560394592203d768229e0cbfc",
+ "E": "4b51f084be732ef17d0916a6817a1c4f6c700ef8e1d7d37a02ba88227e5017d4"
+ },
+ {
+ "TEST": 7,
+ "R": "0344f9a8b27b2fab7d74a8d8ffc5dccebe4a7ce995ece6f279ae20df44152582f4",
+ "ECPT": "03000d43caf7f3acd69737d304bee2a96d1f53210e94ff5d0c0cc3e8495ae08357",
+ "ECPS": "02b8e0cf56b022d72fc14cf041ee0ba0b49407d051cface598f9eeefe7c1453629",
+ "ALPHA": "03b9b2387f985051979c108062b976d7f3e2919b8290b1f0ef25e9bcbeee9469e4",
+ "BETA": "02144e08ad48e3f3c166956e81849b510ecb75d8ef87a605f7e8f8a0c7abb06122",
+ "ID": "8b32f6690774743069ee5a6d40cc6870",
+ "AD": "2b3846f25ed3365bbd884f83e6f4548c",
+ "E": "3664df952f1c577e7e2df04c389534bad473dc6af295d044d91b0975284a40e8"
+ },
+ {
+ "TEST": 8,
+ "R": "0257f95048f77b44a1798c0bc71679204359d9a5fb3ab703eba3111fc1f7b09c80",
+ "ECPT": "0394b8365a0c5ef360fd3ce65c591ab7622fedb4169968befbe20dcf33908a00a1",
+ "ECPS": "0297fa2ed1cff034cbc79acc1166676d2a7dd4386fb6d186f45fb04f5376d79316",
+ "ALPHA": "025bd9ebc89644a9130ff710ac31017dcd5474d3bca0f916761e70895606295dd9",
+ "BETA": "027d56e955a33e6e5aa13f6a824dd937979768d6e8c11ffe0471643086f252ab4c",
+ "ID": "b25a1c88e887ee364c5116c2f665ce31",
+ "AD": "6a294254b33675dbb59af7ef489755e3",
+ "E": "2e6c16f6cd496d6e02fd7be9b5b0ac01a16fb43bca842274e16f61b90474bef3"
+ },
+ {
+ "TEST": 9,
+ "R": "02d520f3e4ef26290c24c6b6e48b3ecbc6a3dc0d0fa22252c041c04d5955849928",
+ "ECPT": "02479429d2de02de00128138e9203d611fb14a21de594804f614e082e24bcd0e28",
+ "ECPS": "02b71c2b73b5ae3a2bb29bfd7a5ea2683966d5ccd1dcff243325978d049a7d46cf",
+ "ALPHA": "03b85d472305bdf3f2c98d8d7c3cff9b97ca1b5e80660f837043ac67075b1e9737",
+ "BETA": "02d0983aeb40e1829b55d4d87f5c3186147ec14eb2048e817a114986e053e5298f",
+ "ID": "1e43f22b907d8afaaf7d19f04f77f196",
+ "AD": "0b059b699d94059fc7f0664b4f23aa64",
+ "E": "38dd0bdb76aaeb1799b5af882924999a6538c3916af94f2f6e795ce2180497b3"
+ }
+]
\ No newline at end of file
diff --git a/testVectors/gg20_zkp/phase6_challenge.txt b/testVectors/gg20_zkp/phase6_challenge.txt
new file mode 100644
index 0000000..2426765
--- /dev/null
+++ b/testVectors/gg20_zkp/phase6_challenge.txt
@@ -0,0 +1,100 @@
+TEST = 0,
+R = 0354475938e75d0758f68802730fd684e47a39ae17b5cc7c11edede9bc8e2cd5d4,
+ECPT = 0309716b9647851724598b9dd81a5a9a5ceb6504d482e70723eb36c9d368889696,
+ECPS = 02389a9a1dd9353486be655cdb5ff19a12e7fc7e734642f5f376c331106f70f3f7,
+ALPHA = 039482cca8df14a76f75f1ad1999ced9c79e2a8a9273eb829adb054394eaf46025,
+BETA = 025f0379e1c8f3903b235a6cc3720e494acaac79bf696a397272f3abece30e7710,
+ID = eeb100ac7e8fba9d1ab74903cdad83f1,
+AD = ,
+E = f62cf3a81f5804e49645b5a3f8734adf128989554db41072f3f8b99334171a06,
+
+TEST = 1,
+R = 02ddb150fb1da230896a8c6927af2940ab173101a3f79e047319d8d63d32395998,
+ECPT = 0268afb804eb127a0d4e0d62c124623450d34794ac70659a1f49f8e3c99a245678,
+ECPS = 0359a4097cb654ac954abb35b146689434e4858a83ed7d85e394af9db9bf831745,
+ALPHA = 025c3e79194dbd97bfd3007eb07b8c38cab7222ca2efac5e9dcd3ca19f85bf78b1,
+BETA = 026aae66f4baed01b34473825fd26d4ca81f6381ba9d8479456352814334c5e793,
+ID = 353b15ce8cc5970c9f600676246a84c6,
+AD = ,
+E = 56faf16927b96f0b77c1f893748ffe084395dd56850aab3317b76e76894e2e7b,
+
+TEST = 2,
+R = 022a34247efebe83ca8b37038e6f77de6ace7d2b965b9c67d2eff94c1d0224f7a3,
+ECPT = 02cc5ec6e5b1685492776049d8597330e8c610b4522ea3b0fb102b87e354e53348,
+ECPS = 0331eab8a0f1f864d61526027c33f9c11251acca1132aafbd986d14b4bdf802a5e,
+ALPHA = 02387d3942d232ae24063e34a32e0746f6cdc1895f3c1b473ac2f4272ba201d6eb,
+BETA = 029185494c1b48bf0fd2ad5d3b0be61798194e95c13407ccba81d7f8f284e9e267,
+ID = ef7ac188e34f2fb9e35db42481f26d47,
+AD = ,
+E = 22e0be495be895a7ebcfdb81b3dd05de631f167c141e47b8ca50b9afac3280bc,
+
+TEST = 3,
+R = 0390defac91dae4cc3f364d967719c678c0bd4ea251ba1054223fba9688adc3c56,
+ECPT = 035034f368f448a6a277225e3cdb124302fdc942eae6aa1b64a680aacf78869d0e,
+ECPS = 02a19b8481f7c8de6fb30c5031ae8a15490b0c2a758f9aefaaf15d3904321dad07,
+ALPHA = 02ca814f396e313972d00140567b12f7474a527fb9b390afb256fea46a7a7ecfa5,
+BETA = 029d318274c93a9ff8fd90073884659c82dafa66d16b19e0f52144521e794cbcc6,
+ID = 1b49574f4c21f41b39ce83332f41333d,
+AD = ,
+E = 2a5792e835e36cd16c486cda418a40d663113ac2c3ee302c17584462a4f41834,
+
+TEST = 4,
+R = 035ad96d26b6baf8aed78966f0a644ae736a900bde5d3cdde6c387d7d5a0b0f512,
+ECPT = 02161555ec9e569529c058c71352d45ac59ab76aab54df7e20f4a87871e6b673b8,
+ECPS = 027ca8c30011b57a3c91f716ba2ebd5156794d57bb96ffef78de66004e1b33c4a4,
+ALPHA = 025347b0712617cef345b2e4a2e18423b2161aadd98bbcb9c7bd8c1275e12a8971,
+BETA = 02cc2306e87e16bd67b48d2fc25870fa4eea231630d2100fcfbc6e81cd3a52b690,
+ID = 8f6d9b7701ec269ea270feb2ec91e318,
+AD = ,
+E = 5c389ad728f051ead0419585143e17f873072fc370f5ab854c0c6ea7bfb716a8,
+
+TEST = 5,
+R = 0279df7cf044d99369f9c93421bff3f78f6757c177e2f7f87d3567379ec9190c26,
+ECPT = 0334b3a774949b3591f28f02397e0c9ec66afac07f9f9e41b21c8057a7fcd4ca00,
+ECPS = 0237285d6b3efeceed33001c33f4d5f53de8b373b3fca5bb0b513541780fbdacaf,
+ALPHA = 03c71cf5c62fb9a156f9a03c4d906ce1ee8fbd4151ef2dee23aea639fe7c37d528,
+BETA = 03109e23bd81982f7785745354c2b028376d5907d1188429d8276d16a217ccd3d0,
+ID = bfa83a06e6d2dd6f1a745ce02b174372,
+AD = b06c21b98910963763693ed9449d98fd,
+E = a6077eaa1c8ec1b012a29d783e07693116cc021289798de10fc739864ddeed31,
+
+TEST = 6,
+R = 024a4cc9696b93c927c20c3d91b831ee761b492b09b050c121b48ae4062122a747,
+ECPT = 0322cb50ba4c6b8532750d6cd19221e781850dfb144540fba3e731d98cb92e3a80,
+ECPS = 0251768a7ad18977533e7baf949684efa6b8bec022fa2a90ab909624c9bf4b7faa,
+ALPHA = 026cd424b8b53da925091aef993c902f4e26da7edb6ac8693f86151d4fd3a76c85,
+BETA = 02eeae4892bd107dfb893d05af3180a1dab884132e4254c71df1a97adf7f36e7ba,
+ID = 71db72ad3d3f60cb4125922ea03bf7d0,
+AD = 4469883560394592203d768229e0cbfc,
+E = 4b51f084be732ef17d0916a6817a1c4f6c700ef8e1d7d37a02ba88227e5017d4,
+
+TEST = 7,
+R = 0344f9a8b27b2fab7d74a8d8ffc5dccebe4a7ce995ece6f279ae20df44152582f4,
+ECPT = 03000d43caf7f3acd69737d304bee2a96d1f53210e94ff5d0c0cc3e8495ae08357,
+ECPS = 02b8e0cf56b022d72fc14cf041ee0ba0b49407d051cface598f9eeefe7c1453629,
+ALPHA = 03b9b2387f985051979c108062b976d7f3e2919b8290b1f0ef25e9bcbeee9469e4,
+BETA = 02144e08ad48e3f3c166956e81849b510ecb75d8ef87a605f7e8f8a0c7abb06122,
+ID = 8b32f6690774743069ee5a6d40cc6870,
+AD = 2b3846f25ed3365bbd884f83e6f4548c,
+E = 3664df952f1c577e7e2df04c389534bad473dc6af295d044d91b0975284a40e8,
+
+TEST = 8,
+R = 0257f95048f77b44a1798c0bc71679204359d9a5fb3ab703eba3111fc1f7b09c80,
+ECPT = 0394b8365a0c5ef360fd3ce65c591ab7622fedb4169968befbe20dcf33908a00a1,
+ECPS = 0297fa2ed1cff034cbc79acc1166676d2a7dd4386fb6d186f45fb04f5376d79316,
+ALPHA = 025bd9ebc89644a9130ff710ac31017dcd5474d3bca0f916761e70895606295dd9,
+BETA = 027d56e955a33e6e5aa13f6a824dd937979768d6e8c11ffe0471643086f252ab4c,
+ID = b25a1c88e887ee364c5116c2f665ce31,
+AD = 6a294254b33675dbb59af7ef489755e3,
+E = 2e6c16f6cd496d6e02fd7be9b5b0ac01a16fb43bca842274e16f61b90474bef3,
+
+TEST = 9,
+R = 02d520f3e4ef26290c24c6b6e48b3ecbc6a3dc0d0fa22252c041c04d5955849928,
+ECPT = 02479429d2de02de00128138e9203d611fb14a21de594804f614e082e24bcd0e28,
+ECPS = 02b71c2b73b5ae3a2bb29bfd7a5ea2683966d5ccd1dcff243325978d049a7d46cf,
+ALPHA = 03b85d472305bdf3f2c98d8d7c3cff9b97ca1b5e80660f837043ac67075b1e9737,
+BETA = 02d0983aeb40e1829b55d4d87f5c3186147ec14eb2048e817a114986e053e5298f,
+ID = 1e43f22b907d8afaaf7d19f04f77f196,
+AD = 0b059b699d94059fc7f0664b4f23aa64,
+E = 38dd0bdb76aaeb1799b5af882924999a6538c3916af94f2f6e795ce2180497b3,
+
diff --git a/testVectors/gg20_zkp/phase6_commit.json b/testVectors/gg20_zkp/phase6_commit.json
new file mode 100644
index 0000000..8f76a9b
--- /dev/null
+++ b/testVectors/gg20_zkp/phase6_commit.json
@@ -0,0 +1,82 @@
+[
+ {
+ "TEST": 0,
+ "R": "03a9d19d66ca686d47787b0bccc4db0d962056e8b8d03d1ea2329a62667ee0b14e",
+ "A": "a311086946e737cb90f4f3575bd8f17bf004724add7bd7ef9220302903a025f9",
+ "B": "0e1425a719cc271acff9ca0bb140c19c9ad82ea8c2418fbfa0ea47550bcc39d9",
+ "ALPHA": "02c6fb6f18f732f8906b11690c41c412103d95e12cb9bf974d10b0239baeeffd3c",
+ "BETA": "02893028961112ee8c139e6c1991249b737434215d50bd9edabcede1aff24b2afa"
+ },
+ {
+ "TEST": 1,
+ "R": "02dda806c7c882ce7d467871068a6ca69e4dc7e42a912a13275acb71b74d798867",
+ "A": "df884589c960c5dd4638c2472cd1e2008d1fb41a09be81a843b541a22b177c9b",
+ "B": "c33adcc15c9dd5e0b0acf82f854c93b30e182d4b66de8538e30e487e3a7835a7",
+ "ALPHA": "033efe70bc113af12c6e1a1e4804a5d6140e36da8438fd238c5245420d46035cb4",
+ "BETA": "03b0df256256a4d1ebabd3d088f785fa4256e35b15d87c8118982a382eae9a5fd5"
+ },
+ {
+ "TEST": 2,
+ "R": "02073a783927377ec51028e65b5a17702fa4e26ec720490592303393d0d085cb39",
+ "A": "bba11de9d0c4ff9bbb9c674dafa1a27fa02882b2ffaba1d8caac6935ee776f50",
+ "B": "181462ec77ab2d6324a990d3e9395cd1fa7ac8b128354c0882196f388893ea97",
+ "ALPHA": "02a58b93a867ef13d8c4ece3c1fd7d88b1ee4fb7b0ae88fd644ca65fa9bbaaa91a",
+ "BETA": "02bdb475ba532e8e4bdc75c8d3da665524e16897646f133ff1f46debb23db518cd"
+ },
+ {
+ "TEST": 3,
+ "R": "02f83367446b99a2fceade742113410ee82c6edb5eb7a69ce3d11de04edec27446",
+ "A": "4fa23c8f86896304647e1619be5a3451755cb1fe35ff06f3b7e9a71a49ba97ab",
+ "B": "3ea1a7a6c80a63a04b696c307de3caa13b5b1dc9ec7cbc5bb925edc2f7c2b432",
+ "ALPHA": "024a9d38c6dd6464dfd5f1c48b54a93d1dbefbc9df6c5d73ed484eb5d2ed2c39ac",
+ "BETA": "039674b4d13d3fd8bd969959cc69a93b459e9db4cdd93760ee0392ea9c4abeb802"
+ },
+ {
+ "TEST": 4,
+ "R": "033ecc8a569e26ed22ba2788d51c9e93044e349eecced0509099e8924cc385bfe2",
+ "A": "335596410f3b5b5fec92bbc83e17b3821daf182537bc5c6756fe228af1724e41",
+ "B": "06a803ceeab3bf20d3e7b0f94f4b30257bfe05d00e4962aa6325f8bed01a20f2",
+ "ALPHA": "0358491775a269318fde1a684fda434c5362d14cfd3cd00dbc625d1f50dbd9f6e8",
+ "BETA": "037977bcdb620361355bf7d9d29689d90a5fb5a4766905275b9b6ddb31cc4b673d"
+ },
+ {
+ "TEST": 5,
+ "R": "029f8cfb62ad66b310837e3129f71dbcc7b24901a595ac9ab19ceaff26ebfef873",
+ "A": "829bfe5e2c6a0f0d6d53dbff1b07cfd94e2168e35dc854c71e15b54717bb2b62",
+ "B": "512c45b56c25fd7b0e3359b833232dcc523aa4208eba91bd4cf0a66cf48b7d07",
+ "ALPHA": "02a9f78b24582fa72c45027682e6c578266cfe0087563f03e49a6ab6eba94ae0e6",
+ "BETA": "03c4ca090151d7a4c1cb178835ff43e4d0e1a93f6efb25661399fd1ed0b43bb98a"
+ },
+ {
+ "TEST": 6,
+ "R": "03e8fb870790ec9d699ea56804385541888af40400bce96b3a5e23d19107b57fa4",
+ "A": "bca79a26189a3655c35bb74d94c49f22726d4ea23f0572fe8add29607884ea19",
+ "B": "ad446ab7e674ab18f2310081db5782540b701fc0f3c4d3b8367fc21315612966",
+ "ALPHA": "0337f7a55ec8ecc01d4ec8d9b5c13b671832cf11aceb405f7b1476d2ba46a957fd",
+ "BETA": "02894aed53ee60156b0cf61d71647424d2cc80de8dde6659a2a04c81073246f2cc"
+ },
+ {
+ "TEST": 7,
+ "R": "024fc393a6716b185ebdedf856c7fc12d5506b8ad90a6734ee96f8413d6f35dd16",
+ "A": "5fcddb1c976d2dc7ca8ff035251e6f94f542695860890864730ea6d2749cfd95",
+ "B": "187c5cbe3d5b8d6e42743fe4faf09565e1f26a96f66ee55d291137691d6e256a",
+ "ALPHA": "0229012eede68a4b0fb89d41c45123567b689de83977e0d4eee23197352051a458",
+ "BETA": "02132c61a945337a7b9770a9633c7961a64cc0af4d2532ce3412aefeed2e0e796d"
+ },
+ {
+ "TEST": 8,
+ "R": "02e2aba9954d7bedb5e29cdc5808903720a119496e9f6303e0fc1199f13f07d954",
+ "A": "4b94e36c6589eeab2df7988198998cd61ecc7599abf7581ec7571d4572cf761e",
+ "B": "e40a7d67b009563ce732ef1d50e97652afb7b8c5ac81da9ab0e59c228dcf36d3",
+ "ALPHA": "027dc0edd1eec628621c8210a6749f165a1d9c4fc34d2a8324db59b29a3aea17c5",
+ "BETA": "033d16586629c904d6fc6e9ed0f28fd0fc7a2f82fb33eedabf980c0b68a53dc2c0"
+ },
+ {
+ "TEST": 9,
+ "R": "03b175d872b8e3009cb5f81c0c383b7c9603f5f203403d00100da08d1fea20ec85",
+ "A": "16a872b0055ef25fb7fe08bc8eb2e9085d7fe10548d5dc3f64e6f4b5fd807eff",
+ "B": "766d3a5818cb17b0e3c3008bf9e1007db24ded41947cf05619dae8e99a6ca5d0",
+ "ALPHA": "02057f0324b16eddaefde206a00ad6cac24b33ff4b9db9512168485016e557ab30",
+ "BETA": "036f4486b6f8d2b591ad1f2acdef02dfe6d59f9f933a56e0da30a39d67a5e6aa6e"
+ }
+]
\ No newline at end of file
diff --git a/testVectors/gg20_zkp/phase6_commit.txt b/testVectors/gg20_zkp/phase6_commit.txt
new file mode 100644
index 0000000..27a319b
--- /dev/null
+++ b/testVectors/gg20_zkp/phase6_commit.txt
@@ -0,0 +1,70 @@
+TEST = 0,
+R = 03a9d19d66ca686d47787b0bccc4db0d962056e8b8d03d1ea2329a62667ee0b14e,
+A = a311086946e737cb90f4f3575bd8f17bf004724add7bd7ef9220302903a025f9,
+B = 0e1425a719cc271acff9ca0bb140c19c9ad82ea8c2418fbfa0ea47550bcc39d9,
+ALPHA = 02c6fb6f18f732f8906b11690c41c412103d95e12cb9bf974d10b0239baeeffd3c,
+BETA = 02893028961112ee8c139e6c1991249b737434215d50bd9edabcede1aff24b2afa,
+
+TEST = 1,
+R = 02dda806c7c882ce7d467871068a6ca69e4dc7e42a912a13275acb71b74d798867,
+A = df884589c960c5dd4638c2472cd1e2008d1fb41a09be81a843b541a22b177c9b,
+B = c33adcc15c9dd5e0b0acf82f854c93b30e182d4b66de8538e30e487e3a7835a7,
+ALPHA = 033efe70bc113af12c6e1a1e4804a5d6140e36da8438fd238c5245420d46035cb4,
+BETA = 03b0df256256a4d1ebabd3d088f785fa4256e35b15d87c8118982a382eae9a5fd5,
+
+TEST = 2,
+R = 02073a783927377ec51028e65b5a17702fa4e26ec720490592303393d0d085cb39,
+A = bba11de9d0c4ff9bbb9c674dafa1a27fa02882b2ffaba1d8caac6935ee776f50,
+B = 181462ec77ab2d6324a990d3e9395cd1fa7ac8b128354c0882196f388893ea97,
+ALPHA = 02a58b93a867ef13d8c4ece3c1fd7d88b1ee4fb7b0ae88fd644ca65fa9bbaaa91a,
+BETA = 02bdb475ba532e8e4bdc75c8d3da665524e16897646f133ff1f46debb23db518cd,
+
+TEST = 3,
+R = 02f83367446b99a2fceade742113410ee82c6edb5eb7a69ce3d11de04edec27446,
+A = 4fa23c8f86896304647e1619be5a3451755cb1fe35ff06f3b7e9a71a49ba97ab,
+B = 3ea1a7a6c80a63a04b696c307de3caa13b5b1dc9ec7cbc5bb925edc2f7c2b432,
+ALPHA = 024a9d38c6dd6464dfd5f1c48b54a93d1dbefbc9df6c5d73ed484eb5d2ed2c39ac,
+BETA = 039674b4d13d3fd8bd969959cc69a93b459e9db4cdd93760ee0392ea9c4abeb802,
+
+TEST = 4,
+R = 033ecc8a569e26ed22ba2788d51c9e93044e349eecced0509099e8924cc385bfe2,
+A = 335596410f3b5b5fec92bbc83e17b3821daf182537bc5c6756fe228af1724e41,
+B = 06a803ceeab3bf20d3e7b0f94f4b30257bfe05d00e4962aa6325f8bed01a20f2,
+ALPHA = 0358491775a269318fde1a684fda434c5362d14cfd3cd00dbc625d1f50dbd9f6e8,
+BETA = 037977bcdb620361355bf7d9d29689d90a5fb5a4766905275b9b6ddb31cc4b673d,
+
+TEST = 5,
+R = 029f8cfb62ad66b310837e3129f71dbcc7b24901a595ac9ab19ceaff26ebfef873,
+A = 829bfe5e2c6a0f0d6d53dbff1b07cfd94e2168e35dc854c71e15b54717bb2b62,
+B = 512c45b56c25fd7b0e3359b833232dcc523aa4208eba91bd4cf0a66cf48b7d07,
+ALPHA = 02a9f78b24582fa72c45027682e6c578266cfe0087563f03e49a6ab6eba94ae0e6,
+BETA = 03c4ca090151d7a4c1cb178835ff43e4d0e1a93f6efb25661399fd1ed0b43bb98a,
+
+TEST = 6,
+R = 03e8fb870790ec9d699ea56804385541888af40400bce96b3a5e23d19107b57fa4,
+A = bca79a26189a3655c35bb74d94c49f22726d4ea23f0572fe8add29607884ea19,
+B = ad446ab7e674ab18f2310081db5782540b701fc0f3c4d3b8367fc21315612966,
+ALPHA = 0337f7a55ec8ecc01d4ec8d9b5c13b671832cf11aceb405f7b1476d2ba46a957fd,
+BETA = 02894aed53ee60156b0cf61d71647424d2cc80de8dde6659a2a04c81073246f2cc,
+
+TEST = 7,
+R = 024fc393a6716b185ebdedf856c7fc12d5506b8ad90a6734ee96f8413d6f35dd16,
+A = 5fcddb1c976d2dc7ca8ff035251e6f94f542695860890864730ea6d2749cfd95,
+B = 187c5cbe3d5b8d6e42743fe4faf09565e1f26a96f66ee55d291137691d6e256a,
+ALPHA = 0229012eede68a4b0fb89d41c45123567b689de83977e0d4eee23197352051a458,
+BETA = 02132c61a945337a7b9770a9633c7961a64cc0af4d2532ce3412aefeed2e0e796d,
+
+TEST = 8,
+R = 02e2aba9954d7bedb5e29cdc5808903720a119496e9f6303e0fc1199f13f07d954,
+A = 4b94e36c6589eeab2df7988198998cd61ecc7599abf7581ec7571d4572cf761e,
+B = e40a7d67b009563ce732ef1d50e97652afb7b8c5ac81da9ab0e59c228dcf36d3,
+ALPHA = 027dc0edd1eec628621c8210a6749f165a1d9c4fc34d2a8324db59b29a3aea17c5,
+BETA = 033d16586629c904d6fc6e9ed0f28fd0fc7a2f82fb33eedabf980c0b68a53dc2c0,
+
+TEST = 9,
+R = 03b175d872b8e3009cb5f81c0c383b7c9603f5f203403d00100da08d1fea20ec85,
+A = 16a872b0055ef25fb7fe08bc8eb2e9085d7fe10548d5dc3f64e6f4b5fd807eff,
+B = 766d3a5818cb17b0e3c3008bf9e1007db24ded41947cf05619dae8e99a6ca5d0,
+ALPHA = 02057f0324b16eddaefde206a00ad6cac24b33ff4b9db9512168485016e557ab30,
+BETA = 036f4486b6f8d2b591ad1f2acdef02dfe6d59f9f933a56e0da30a39d67a5e6aa6e,
+
diff --git a/testVectors/gg20_zkp/phase6_prove.json b/testVectors/gg20_zkp/phase6_prove.json
new file mode 100644
index 0000000..182f723
--- /dev/null
+++ b/testVectors/gg20_zkp/phase6_prove.json
@@ -0,0 +1,102 @@
+[
+ {
+ "TEST": 0,
+ "A": "c46280bdcfe7041c9b85864a19f551fd76ba019b3ddf225be838b6f8367ff554",
+ "B": "8d6aedfe66bfb78d8b6b93fb36a87dba034a97d22652f3b88800897ce779382d",
+ "E": "bc116191af9b64db4068237e6a44c21eb5d9d0fed4ad2866a204067edfc08dbf",
+ "S": "e2bf8d7db4a2520473ed3ec7ffbbe952811f4ebf12748318474a0c8c6f39454a",
+ "L": "e168ecd5e2c9d342bc0c338e2ea5ac328093cd3719152ef0b9e91e31dc7103b6",
+ "T": "0cf0cdf21c8f45ecad7ab34795b9a1a0b6890be17f48cc99431c52f7ae4a6a5b",
+ "U": "fa09d8bfa7483ee3e0f34f5e6dccb5c34c2380f2bf54dd7dc70fce8ffe54b904"
+ },
+ {
+ "TEST": 1,
+ "A": "f49f8be15d580b34504f7e9d4fa91fa2194709128f9b15eb29075150df727d71",
+ "B": "98d5943dfcf8fcab987a56422d68d3449805aee3cb4ce8d416af1477dd0127f2",
+ "E": "cd41053395c5ea4deddf7ffbe91e6621094fb9c9a5d5fc411bdab67679fdcdcc",
+ "S": "e172f5910de057942c5b988a22d642f537c1f41c499db0c58b69cfa8788388f7",
+ "L": "d37c515f7603e27bda8d2073e81d7b5fb1678e4ffd82ee112024850e13725fdb",
+ "T": "262c67803f4c9824d406184086467d56a71d97df1ea330e4cf72b28aba9ed14a",
+ "U": "1dcb1ba668cff08e8574d083acf92e0f60d767e7686a815ac51ec16cd7238c84"
+ },
+ {
+ "TEST": 2,
+ "A": "351b4bbf2dde9f96dc4512ae30b6750c2710d7c466d541d6835b8aeee171b835",
+ "B": "c187170626360045315129dabba599325912a4a69a4996fb0b262682db02b830",
+ "E": "e6bce745a963b36bce5a47543cef3048ca1c4b9b236f052b0c32e94d6f34693d",
+ "S": "1177001af7747f2458cb04e60ebcb751bd5f927da53a7f930dfd56ca902f0205",
+ "L": "9fd89ecd4f2828ab2eff8cc4289388bfa2be9f94fa090fc06cadaec10615d770",
+ "T": "4e3b6e7412da2122288435f980c9658ac28ebd0064ea33eaa536156f01a0d106",
+ "U": "0a91d097025689b8a94e50f19f55c28dae4d607aee2b91b51e933ba8affc23c1"
+ },
+ {
+ "TEST": 3,
+ "A": "eb994bc958a9cb43e1a6b943e941fcf3c1fe18a68410b7a5896b205d99eac388",
+ "B": "0ed7a273d5e0fb13a57ab567dff28134eb83b3f43a472a4a0e7c5f098c695069",
+ "E": "0a876cb0f03608b1935212bb748a26ef64b617a8e81e6bf0b54e5b1b8ebd5d5d",
+ "S": "f6a73b8752ac0353a447e2e6990d4b8c163e45f840b7fd8d7bc4b7db4863f38a",
+ "L": "d7eb77dc26fbec4db52be2e632d27c6eb9d24db93f728cfa601b430988bea7c5",
+ "T": "743b7bac6dae30896cd051064fc93287376f2da22f760eea74f755785931d619",
+ "U": "fef1d7d796c06dd56a21f54ecbc1a0aecb650d018c937e83a845d50f1322afa9"
+ },
+ {
+ "TEST": 4,
+ "A": "23b7b72a2b11af03b1aeaf05d01bfbed7fde418e699380d4bf93fa067c6c4f6c",
+ "B": "30787257dfcc8aa31d280a1228512313083e75ec8a60dd241c68eca888a09489",
+ "E": "e8277d16a233ddac9a07f16b65c32886441e9499c8359c9d4e0b41748cf2e017",
+ "S": "abdad043c00ac98e6eed683f146a82cffad5959e30fce9e7b9c54aa9074c0bc9",
+ "L": "e2fc682fd024d71cc255df1357a671ea2dc29f079e5360064e402160e216bf10",
+ "T": "14edbb7b5dc688215da48e0b19c638cd81be751f2cb2f85f24645352fb22c70e",
+ "U": "20e87a78d7b2bad5bfc03193f9e37fb648ced02af9b59767b94adca0bbaaa3ac"
+ },
+ {
+ "TEST": 5,
+ "A": "494f89875089d78a7a2f41b3a8b6996f0974f98f659960da6eae1a2d940290fb",
+ "B": "d42667e74c7361d5411e4dcb6c45cba47635d11c81c4558cccbbd9ad479bb85b",
+ "E": "31007a72dfff9162e05c643bdc50f5f8a36021afc2e38fc42169a09bda6ff29f",
+ "S": "9e9a1a632d469e2e564644b0860393fbfa4f37484f35eb2461480b214d526766",
+ "L": "848ae0144f742f7f14b01b001cf221a9ab0db08bfccc79897f5b10e4ec22bb49",
+ "T": "3e0365a79f7384e617d4cf0c510ddb94ec8bdad808bc66892e5769d774a25a18",
+ "U": "487290d3a463d4f7a176d7f6a6615e934030379dae904c534fe9b06da318a7c7"
+ },
+ {
+ "TEST": 6,
+ "A": "55e94add79364194bf46e94d17fcbca0185d0e16f269819041ae3caddfcbf0c6",
+ "B": "43d4b7fac31343c36558581b5fc51213103199c0d414edc26a58a5b02ee3f22e",
+ "E": "42f4f3fb31c702104935721de193f7be5998bd62ffa3857df04d2f7fcbc01efe",
+ "S": "0dac4075445bcaad18313ca539e5bc42f8d1c39efe310ea6211ff5fed3c8cc3d",
+ "L": "831151a6b53173abd585e0cdd1f022177266a1110f089d1a9bdd1385259da3b5",
+ "T": "3de019de8722fa8175a72262abd0acf56e89286703f92f12bf78c149a2770f89",
+ "U": "ef05d65dd4be5c535f062aedd268cd4e962f37500890ab57e24d9eb5a698805c"
+ },
+ {
+ "TEST": 7,
+ "A": "c4e6710e39d30929099ae283806c0773317fc8c441e0b58c9f85f1cac382f756",
+ "B": "b0e6af5e8ccfc10a07561396e37024971850facede8d3d8d6ddb4879c7af43a9",
+ "E": "00b74306805a268c19eccbc082d6d83e2043e7003e51c256648f71fc7290cb07",
+ "S": "6e85ad6abeceb3d09f3a057efb72d3e4efed256b285ae042c4b69319ef7c1f73",
+ "L": "6570c0ec97642edeeace0fb86b217addaed54b969a59261af12f769b0e553f73",
+ "T": "8f602dab8c0e43cce8e4cc27c00f69fa6dd24ee6c4bced176491ff06f6d6b1ea",
+ "U": "c689ba49b0b190ad115d1d8453e9c957d2e404fe7ba7c06f7f911b289950b6a7"
+ },
+ {
+ "TEST": 8,
+ "A": "e7c3f95b6e903e610432a3f91dc94f5061755d869dbb2ea1573f15668654d229",
+ "B": "e5e62572036c81ba0fe43877e0072b16b75233dc011904353eaca882ae148147",
+ "E": "d3b793bf89e953a66f3b6db6f3a1028950fd508524b049a8163ec58a8c239c34",
+ "S": "4d3d25d3cd62a0e6777358279f30fc92a20204dd5d235b5a788430c1103d9a70",
+ "L": "2201e6ea9f8e95f322f09f72d9f335a5c1e71daaa63197b06a55443fc678be8a",
+ "T": "4424c3965b77294a6bf8b7b6a8802ba331681e81d85584a701aca9c5219a173d",
+ "U": "94f29f5fb184adb206c5913c8ac7e4bd72bdce8c822eaf9266db9ee13b78a1ad"
+ },
+ {
+ "TEST": 9,
+ "A": "79f9007692e6ccb44311dffb39650b464a090b74c243ba71b53b5f2864115e84",
+ "B": "ddf6a062e5b0713e44ee603bf76ef50b9c814a90fd070b3a2584c39330a42079",
+ "E": "f01d8981018757bec7ccd7e478593e4d6712a1211f04077fffdbaf4ed774fbb2",
+ "S": "e17f9b31b2d217c0f57ba02a2f444daa402066d8220884477ee52ac868ad74d2",
+ "L": "b96dae35aecb8c199d52b1c94f1a111ab6ac9cec10d961f05ef6ad31fdde0bb0",
+ "T": "9ed876d2dc350ccf23d9891e2455724ec23de37ea8fef76ddb32eae76c98309d",
+ "U": "c8573e32004c8326cb3cf89b266e40232a2bb80b3c67b36798a60e434fd1cfa3"
+ }
+]
\ No newline at end of file
diff --git a/testVectors/gg20_zkp/phase6_prove.txt b/testVectors/gg20_zkp/phase6_prove.txt
new file mode 100644
index 0000000..60902af
--- /dev/null
+++ b/testVectors/gg20_zkp/phase6_prove.txt
@@ -0,0 +1,90 @@
+TEST = 0,
+A = c46280bdcfe7041c9b85864a19f551fd76ba019b3ddf225be838b6f8367ff554,
+B = 8d6aedfe66bfb78d8b6b93fb36a87dba034a97d22652f3b88800897ce779382d,
+E = bc116191af9b64db4068237e6a44c21eb5d9d0fed4ad2866a204067edfc08dbf,
+S = e2bf8d7db4a2520473ed3ec7ffbbe952811f4ebf12748318474a0c8c6f39454a,
+L = e168ecd5e2c9d342bc0c338e2ea5ac328093cd3719152ef0b9e91e31dc7103b6,
+T = 0cf0cdf21c8f45ecad7ab34795b9a1a0b6890be17f48cc99431c52f7ae4a6a5b,
+U = fa09d8bfa7483ee3e0f34f5e6dccb5c34c2380f2bf54dd7dc70fce8ffe54b904,
+
+TEST = 1,
+A = f49f8be15d580b34504f7e9d4fa91fa2194709128f9b15eb29075150df727d71,
+B = 98d5943dfcf8fcab987a56422d68d3449805aee3cb4ce8d416af1477dd0127f2,
+E = cd41053395c5ea4deddf7ffbe91e6621094fb9c9a5d5fc411bdab67679fdcdcc,
+S = e172f5910de057942c5b988a22d642f537c1f41c499db0c58b69cfa8788388f7,
+L = d37c515f7603e27bda8d2073e81d7b5fb1678e4ffd82ee112024850e13725fdb,
+T = 262c67803f4c9824d406184086467d56a71d97df1ea330e4cf72b28aba9ed14a,
+U = 1dcb1ba668cff08e8574d083acf92e0f60d767e7686a815ac51ec16cd7238c84,
+
+TEST = 2,
+A = 351b4bbf2dde9f96dc4512ae30b6750c2710d7c466d541d6835b8aeee171b835,
+B = c187170626360045315129dabba599325912a4a69a4996fb0b262682db02b830,
+E = e6bce745a963b36bce5a47543cef3048ca1c4b9b236f052b0c32e94d6f34693d,
+S = 1177001af7747f2458cb04e60ebcb751bd5f927da53a7f930dfd56ca902f0205,
+L = 9fd89ecd4f2828ab2eff8cc4289388bfa2be9f94fa090fc06cadaec10615d770,
+T = 4e3b6e7412da2122288435f980c9658ac28ebd0064ea33eaa536156f01a0d106,
+U = 0a91d097025689b8a94e50f19f55c28dae4d607aee2b91b51e933ba8affc23c1,
+
+TEST = 3,
+A = eb994bc958a9cb43e1a6b943e941fcf3c1fe18a68410b7a5896b205d99eac388,
+B = 0ed7a273d5e0fb13a57ab567dff28134eb83b3f43a472a4a0e7c5f098c695069,
+E = 0a876cb0f03608b1935212bb748a26ef64b617a8e81e6bf0b54e5b1b8ebd5d5d,
+S = f6a73b8752ac0353a447e2e6990d4b8c163e45f840b7fd8d7bc4b7db4863f38a,
+L = d7eb77dc26fbec4db52be2e632d27c6eb9d24db93f728cfa601b430988bea7c5,
+T = 743b7bac6dae30896cd051064fc93287376f2da22f760eea74f755785931d619,
+U = fef1d7d796c06dd56a21f54ecbc1a0aecb650d018c937e83a845d50f1322afa9,
+
+TEST = 4,
+A = 23b7b72a2b11af03b1aeaf05d01bfbed7fde418e699380d4bf93fa067c6c4f6c,
+B = 30787257dfcc8aa31d280a1228512313083e75ec8a60dd241c68eca888a09489,
+E = e8277d16a233ddac9a07f16b65c32886441e9499c8359c9d4e0b41748cf2e017,
+S = abdad043c00ac98e6eed683f146a82cffad5959e30fce9e7b9c54aa9074c0bc9,
+L = e2fc682fd024d71cc255df1357a671ea2dc29f079e5360064e402160e216bf10,
+T = 14edbb7b5dc688215da48e0b19c638cd81be751f2cb2f85f24645352fb22c70e,
+U = 20e87a78d7b2bad5bfc03193f9e37fb648ced02af9b59767b94adca0bbaaa3ac,
+
+TEST = 5,
+A = 494f89875089d78a7a2f41b3a8b6996f0974f98f659960da6eae1a2d940290fb,
+B = d42667e74c7361d5411e4dcb6c45cba47635d11c81c4558cccbbd9ad479bb85b,
+E = 31007a72dfff9162e05c643bdc50f5f8a36021afc2e38fc42169a09bda6ff29f,
+S = 9e9a1a632d469e2e564644b0860393fbfa4f37484f35eb2461480b214d526766,
+L = 848ae0144f742f7f14b01b001cf221a9ab0db08bfccc79897f5b10e4ec22bb49,
+T = 3e0365a79f7384e617d4cf0c510ddb94ec8bdad808bc66892e5769d774a25a18,
+U = 487290d3a463d4f7a176d7f6a6615e934030379dae904c534fe9b06da318a7c7,
+
+TEST = 6,
+A = 55e94add79364194bf46e94d17fcbca0185d0e16f269819041ae3caddfcbf0c6,
+B = 43d4b7fac31343c36558581b5fc51213103199c0d414edc26a58a5b02ee3f22e,
+E = 42f4f3fb31c702104935721de193f7be5998bd62ffa3857df04d2f7fcbc01efe,
+S = 0dac4075445bcaad18313ca539e5bc42f8d1c39efe310ea6211ff5fed3c8cc3d,
+L = 831151a6b53173abd585e0cdd1f022177266a1110f089d1a9bdd1385259da3b5,
+T = 3de019de8722fa8175a72262abd0acf56e89286703f92f12bf78c149a2770f89,
+U = ef05d65dd4be5c535f062aedd268cd4e962f37500890ab57e24d9eb5a698805c,
+
+TEST = 7,
+A = c4e6710e39d30929099ae283806c0773317fc8c441e0b58c9f85f1cac382f756,
+B = b0e6af5e8ccfc10a07561396e37024971850facede8d3d8d6ddb4879c7af43a9,
+E = 00b74306805a268c19eccbc082d6d83e2043e7003e51c256648f71fc7290cb07,
+S = 6e85ad6abeceb3d09f3a057efb72d3e4efed256b285ae042c4b69319ef7c1f73,
+L = 6570c0ec97642edeeace0fb86b217addaed54b969a59261af12f769b0e553f73,
+T = 8f602dab8c0e43cce8e4cc27c00f69fa6dd24ee6c4bced176491ff06f6d6b1ea,
+U = c689ba49b0b190ad115d1d8453e9c957d2e404fe7ba7c06f7f911b289950b6a7,
+
+TEST = 8,
+A = e7c3f95b6e903e610432a3f91dc94f5061755d869dbb2ea1573f15668654d229,
+B = e5e62572036c81ba0fe43877e0072b16b75233dc011904353eaca882ae148147,
+E = d3b793bf89e953a66f3b6db6f3a1028950fd508524b049a8163ec58a8c239c34,
+S = 4d3d25d3cd62a0e6777358279f30fc92a20204dd5d235b5a788430c1103d9a70,
+L = 2201e6ea9f8e95f322f09f72d9f335a5c1e71daaa63197b06a55443fc678be8a,
+T = 4424c3965b77294a6bf8b7b6a8802ba331681e81d85584a701aca9c5219a173d,
+U = 94f29f5fb184adb206c5913c8ac7e4bd72bdce8c822eaf9266db9ee13b78a1ad,
+
+TEST = 9,
+A = 79f9007692e6ccb44311dffb39650b464a090b74c243ba71b53b5f2864115e84,
+B = ddf6a062e5b0713e44ee603bf76ef50b9c814a90fd070b3a2584c39330a42079,
+E = f01d8981018757bec7ccd7e478593e4d6712a1211f04077fffdbaf4ed774fbb2,
+S = e17f9b31b2d217c0f57ba02a2f444daa402066d8220884477ee52ac868ad74d2,
+L = b96dae35aecb8c199d52b1c94f1a111ab6ac9cec10d961f05ef6ad31fdde0bb0,
+T = 9ed876d2dc350ccf23d9891e2455724ec23de37ea8fef76ddb32eae76c98309d,
+U = c8573e32004c8326cb3cf89b266e40232a2bb80b3c67b36798a60e434fd1cfa3,
+
diff --git a/testVectors/gg20_zkp/phase6_verify.json b/testVectors/gg20_zkp/phase6_verify.json
new file mode 100644
index 0000000..a0f00a5
--- /dev/null
+++ b/testVectors/gg20_zkp/phase6_verify.json
@@ -0,0 +1,112 @@
+[
+ {
+ "TEST": 0,
+ "R": "025653713d2fcd58fd182adc457f0a8a28b5ff627bc7ce08daccfcce3012ae8447",
+ "ECPT": "025198bcf9b5209bd757ebee5e4fef17b9d6ce5b2c9d05dbfce7a79c039064e515",
+ "ECPS": "024b2fb257840247d17265b0be92187bc7d104f8b3c5ff134631dd13a6c4f3706d",
+ "ALPHA": "0311a5de9be61f4992b9b44428a9f829b3b415622db7a6a043664f9b2bc022fabd",
+ "BETA": "0310caaa12677542d646f0c1f5d08f3ef618bfae3068cbad9fc99f22134055b692",
+ "E": "259a141dcfbfdc9685aefdf5468c4b8bf6884832e2777aab04b6a9c46916e96a",
+ "T": "efeef201b47cab80eb0c5c3081f9dd8207d1317074bf3123942c8f8a0a2a637c",
+ "U": "fecadde1a26e91bfc65adf14085d4eacd8beb7df1f4ff630f49d3153e25bb172"
+ },
+ {
+ "TEST": 1,
+ "R": "035cf8c0e804e61b29d1a3016dc0121ec71a6ddbcdf71b407df801570a670efa07",
+ "ECPT": "021a82066441c27e48999632934724d902c7fa36a8da48055a0d87ea36a8eaf609",
+ "ECPS": "0373a864abd8e8cdad5d15339f617a3d6b6f9aa1f47ef8165202a06625e9ceee47",
+ "ALPHA": "0286a478888a1c0f8d2489cfed552aead5773971d72c3228e526156f5891eb3646",
+ "BETA": "03d2ae50e09885a2da1dbfe916d76178c465179122848f00da2219dd9e1156d830",
+ "E": "500865b4c9c81db293fb1b30089de62356b5094696abd04c2c1dcb8344713d24",
+ "T": "7c424818c7dc23091814084d7765e9c25568b4f2d4b9e3e5b8e3fe9064c6a31e",
+ "U": "c20afde07345e45a13195e883513090a249cfbcabd70473e5d0ecd632bef3565"
+ },
+ {
+ "TEST": 2,
+ "R": "0262a372b4d73033a094d2fa82aa093f9ed4d15bd25c4dcc8597d1e0a9d52daacd",
+ "ECPT": "038177b3ea8f0d608b6116235a817f429a4239723a6dd98e1383f85ce32b4f2e24",
+ "ECPS": "03d2819d2c0729446b35f384d2748463c53d7c6fa78e2de760da1fac588e669783",
+ "ALPHA": "0376e6c94dd0a56fcbeb9e7e747f804ec0d2d9f7e19c63170c3d522d20e93e86dd",
+ "BETA": "03ac03b7bfee911df5e567117790e3706136aba8bf1d443b65f0827a5483c93554",
+ "E": "8583cb4346897e0dddf2e3fe352c967c81d0283b04c0d5b7c179c65a29a56873",
+ "T": "b087f672d9df56049c4df01e7a7557f4f8197b48aa1d33a93801509dd4d6e095",
+ "U": "92df0343eaa0ad4ed2d7208faa35b23258a7023fa333483589d6911fa3ace351"
+ },
+ {
+ "TEST": 3,
+ "R": "031a8b4d3d9c89ba80415bc0e4eadb1633b88319b0bf7d6158a7a48b3d9ed9c4cc",
+ "ECPT": "03a4398f43acccc5a879a98b8c686ea8bc8e0ddd8563be29a57264591e1d26a517",
+ "ECPS": "03d0d5a7ac53e8ca512a72f1baa7f0e342daeeda55915a0f966bf35764d6e724fa",
+ "ALPHA": "023e7e2c6ee1b23c4c1141c467d32d31eb3e432451ed7f58f60fe02c5a984cb8ae",
+ "BETA": "0366fd37d5adeab6e25869b63d70a286d8de3d61f63e0efca20b2a864b0c1c1024",
+ "E": "84c194d04479a87829fb884c383bd0c39f0587a1f7a87a9130d4de389e57cde8",
+ "T": "cb7805ab00a7ba8b1c4a6285b9a5317cdfd179d9d805df8cbe1d59370fc6a9cf",
+ "U": "80a0ac137f9aa09c165cdc7e1ca37e9166f391163e0742969c04eb867cf14caf"
+ },
+ {
+ "TEST": 4,
+ "R": "03f705659c214f2a8bf5232ff47f5aa84aa97af71973a09d1bfda985e01b604090",
+ "ECPT": "0234650e123f90ffdcaffa76e8df6ac91475f8039c82dba6b17da4a19ca4685d02",
+ "ECPS": "029d459ddbac6ef76c316b6eda2f5d3aaad93fe8ad31c9239ba03c8980a9eceb0d",
+ "ALPHA": "02d0045014f16eb10254b17ab07fe3ea3753b7996b8823c6c2cb1373ca1b040ad0",
+ "BETA": "03249029b65568a93ea24e109bf50c1c08c06ad7de22c8bff33446c2b1c0625a65",
+ "E": "752198636483dd7e5cf65b04e3d1590b4f105b7480154c3d7b171b470b48798a",
+ "T": "aeb2631fc90e50407e5eadc3d654ce67c57e60b38fb1a1d9aa5a7dade7f65d81",
+ "U": "7fab6242fa551aa24e0088ed76a2bf4baaa7437ef455bf4f6bf76704be6dc5c4"
+ },
+ {
+ "TEST": 5,
+ "R": "02c027fe77da5b05ef3cc17b6737d1cb6130f244b3548713c928aa3e0ba0a54f06",
+ "ECPT": "031ce592dee24708742cb3e82a9dac2f344923b508397bf6fe754075e8819289c1",
+ "ECPS": "02702ae0ba3985031cee549383ec0c268d54d3812fd0bc03fbbeafa4a0f5971fed",
+ "ALPHA": "0225edbb623d849f72b972aa32dccae57590e8645a3cba518ce5413bd679b1e95c",
+ "BETA": "03703c36ca8afa1e630a8eec1917dd7c6cd2551b418980203c9c7de5b3a12b694d",
+ "E": "73a2c0e26289d7d29788c73e8505a9d937c70c3612da4b43d590d117c903fdd1",
+ "T": "34c55dcd770dab187c09723a580566476f15226fb8d43d3f878849937341180f",
+ "U": "5615c91cbb050c8c9695d7f6c7d01b0f9514c548fb6fb209f1632910dbcfdd97"
+ },
+ {
+ "TEST": 6,
+ "R": "02eb33b1c09509f2d9a0a1dcc104e58a20904c0a53c36e37bca75f37ecfe624f00",
+ "ECPT": "027078071c042aab8e30408c33b165d71c662f76431f9e28086dd210eb30579502",
+ "ECPS": "02732f7c260ce6307365a31d7db5994e2610522e32fc6d7388e9adcc92a3817e64",
+ "ALPHA": "039e8630942c599f2fdc9afc4788770f37c17a446471c1e4b2ea61add0997b16ac",
+ "BETA": "038650929e2ab0c8cfc12e6748eedd9a5759f55e698384fea664c760b5a1623fb0",
+ "E": "9a14a622c4f704365308f573ba8758a80289882a2c3466e27cbdeffb58d1a0f6",
+ "T": "68e84f71edd0589309a1da391709c67e61cb238d005c3b51b4a6a028a7116289",
+ "U": "ea6a9937bc7dfc02e473e6afeb04ad5b253b6eb8b4f61d8eb923c801a2ec5624"
+ },
+ {
+ "TEST": 7,
+ "R": "02634853c61bf8dd1cb73136e4aa7bb6952ac43f17d023b703cdfea6edd98879d3",
+ "ECPT": "0235d1bf1139d0ecd0a2bb7338803914b6a210f6ffce3765d26994f0c99a28a8e8",
+ "ECPS": "02cf47d9a0839cb3e776639a59d746ecf02a65cf6225986e6a7d174a26ba33ebb7",
+ "ALPHA": "0202eadd9f208f398998b1abd30c96de38855bc69f81e2ac74a7acba8cf58ebf87",
+ "BETA": "03857b1d22f80064a97cebb390fbd0b4429979d3c0bb1560f3f376692ec20f39b4",
+ "E": "1cc738dd865f4e63a2f32d3e6de6f7c8c8b0ed70087975279d758f799cb2660b",
+ "T": "bc4e6deff64854489892f7e1c1c9d7b479d1a60b40955f3dbe707b6f4fb8b593",
+ "U": "76a9e7b39adec1a642a6726fdb791e039ea1dfdb1de6e7a2f7bed08d2ea90845"
+ },
+ {
+ "TEST": 8,
+ "R": "03e799d910eade8157d1e983ab6fc2cead6a3d9cf73f0560423a7decf0eee4aa86",
+ "ECPT": "03e00884c86423d26f159993eef320f01ce50cbe580e74216cde175827584d2b18",
+ "ECPS": "03da39cfdfdd57449e4ddc93554d98dc5fe63e34c11efae5e0bedbc37d09886373",
+ "ALPHA": "0383db43a93fc170610199805f644c24e4732f3275dc26bc8e4317dd26c63ddb48",
+ "BETA": "02a03043f112c0b8fa3b0dbe5e251d0c5bdfbd8d710e40705c9bee7b0ccf7c595d",
+ "E": "b34c62cd05beb4de7fcf9d6cddf5fd5d7f6a3e13a5ae2e3846e2e8c5a5914de2",
+ "T": "59e601d8f367d80f3306b659cada19d527e4a46ad7afdd7f59fbc47119e545ca",
+ "U": "67155b19d185fce6fe4ba6b93130b6ba34eb44fe9bd9751ac5ab93c4d35842df"
+ },
+ {
+ "TEST": 9,
+ "R": "03e39e29dce344b76227d753c3d630a255cf7f16cdd33a19f72e4152c7a26bb3ef",
+ "ECPT": "023b830a4aa6c6a7aaf8a432fee29c1688d9afdef41e9981ff873861f00dc78c10",
+ "ECPS": "0259dcd1aedeebbed7efd3b70f25975430ca7028ce56aaac38184f28c101252e5c",
+ "ALPHA": "0206efadb74156a84f9483f4cbaa8bac936697675f68689489966d0ceccd44b80a",
+ "BETA": "032f2f5e491dbd761bc286b7cf777dbe5ced9b65506dac5ce25fdf83bdb5ce9546",
+ "E": "4fd40c3f3cfa2dc76d3799d8ce3cb55db9af2abb367a673250ce6def60ec23c5",
+ "T": "8f1b054d6a8443d6d112e66384abfb63f7539889ee83cdaf5fbc87558cca0bc8",
+ "U": "c72702fc9de49fb34e2b48c97ab90b443b7d18afec669f652e6885cd80ffc451"
+ }
+]
\ No newline at end of file
diff --git a/testVectors/gg20_zkp/phase6_verify.txt b/testVectors/gg20_zkp/phase6_verify.txt
new file mode 100644
index 0000000..fed05bb
--- /dev/null
+++ b/testVectors/gg20_zkp/phase6_verify.txt
@@ -0,0 +1,100 @@
+TEST = 0,
+R = 025653713d2fcd58fd182adc457f0a8a28b5ff627bc7ce08daccfcce3012ae8447,
+ECPT = 025198bcf9b5209bd757ebee5e4fef17b9d6ce5b2c9d05dbfce7a79c039064e515,
+ECPS = 024b2fb257840247d17265b0be92187bc7d104f8b3c5ff134631dd13a6c4f3706d,
+ALPHA = 0311a5de9be61f4992b9b44428a9f829b3b415622db7a6a043664f9b2bc022fabd,
+BETA = 0310caaa12677542d646f0c1f5d08f3ef618bfae3068cbad9fc99f22134055b692,
+E = 259a141dcfbfdc9685aefdf5468c4b8bf6884832e2777aab04b6a9c46916e96a,
+T = efeef201b47cab80eb0c5c3081f9dd8207d1317074bf3123942c8f8a0a2a637c,
+U = fecadde1a26e91bfc65adf14085d4eacd8beb7df1f4ff630f49d3153e25bb172,
+
+TEST = 1,
+R = 035cf8c0e804e61b29d1a3016dc0121ec71a6ddbcdf71b407df801570a670efa07,
+ECPT = 021a82066441c27e48999632934724d902c7fa36a8da48055a0d87ea36a8eaf609,
+ECPS = 0373a864abd8e8cdad5d15339f617a3d6b6f9aa1f47ef8165202a06625e9ceee47,
+ALPHA = 0286a478888a1c0f8d2489cfed552aead5773971d72c3228e526156f5891eb3646,
+BETA = 03d2ae50e09885a2da1dbfe916d76178c465179122848f00da2219dd9e1156d830,
+E = 500865b4c9c81db293fb1b30089de62356b5094696abd04c2c1dcb8344713d24,
+T = 7c424818c7dc23091814084d7765e9c25568b4f2d4b9e3e5b8e3fe9064c6a31e,
+U = c20afde07345e45a13195e883513090a249cfbcabd70473e5d0ecd632bef3565,
+
+TEST = 2,
+R = 0262a372b4d73033a094d2fa82aa093f9ed4d15bd25c4dcc8597d1e0a9d52daacd,
+ECPT = 038177b3ea8f0d608b6116235a817f429a4239723a6dd98e1383f85ce32b4f2e24,
+ECPS = 03d2819d2c0729446b35f384d2748463c53d7c6fa78e2de760da1fac588e669783,
+ALPHA = 0376e6c94dd0a56fcbeb9e7e747f804ec0d2d9f7e19c63170c3d522d20e93e86dd,
+BETA = 03ac03b7bfee911df5e567117790e3706136aba8bf1d443b65f0827a5483c93554,
+E = 8583cb4346897e0dddf2e3fe352c967c81d0283b04c0d5b7c179c65a29a56873,
+T = b087f672d9df56049c4df01e7a7557f4f8197b48aa1d33a93801509dd4d6e095,
+U = 92df0343eaa0ad4ed2d7208faa35b23258a7023fa333483589d6911fa3ace351,
+
+TEST = 3,
+R = 031a8b4d3d9c89ba80415bc0e4eadb1633b88319b0bf7d6158a7a48b3d9ed9c4cc,
+ECPT = 03a4398f43acccc5a879a98b8c686ea8bc8e0ddd8563be29a57264591e1d26a517,
+ECPS = 03d0d5a7ac53e8ca512a72f1baa7f0e342daeeda55915a0f966bf35764d6e724fa,
+ALPHA = 023e7e2c6ee1b23c4c1141c467d32d31eb3e432451ed7f58f60fe02c5a984cb8ae,
+BETA = 0366fd37d5adeab6e25869b63d70a286d8de3d61f63e0efca20b2a864b0c1c1024,
+E = 84c194d04479a87829fb884c383bd0c39f0587a1f7a87a9130d4de389e57cde8,
+T = cb7805ab00a7ba8b1c4a6285b9a5317cdfd179d9d805df8cbe1d59370fc6a9cf,
+U = 80a0ac137f9aa09c165cdc7e1ca37e9166f391163e0742969c04eb867cf14caf,
+
+TEST = 4,
+R = 03f705659c214f2a8bf5232ff47f5aa84aa97af71973a09d1bfda985e01b604090,
+ECPT = 0234650e123f90ffdcaffa76e8df6ac91475f8039c82dba6b17da4a19ca4685d02,
+ECPS = 029d459ddbac6ef76c316b6eda2f5d3aaad93fe8ad31c9239ba03c8980a9eceb0d,
+ALPHA = 02d0045014f16eb10254b17ab07fe3ea3753b7996b8823c6c2cb1373ca1b040ad0,
+BETA = 03249029b65568a93ea24e109bf50c1c08c06ad7de22c8bff33446c2b1c0625a65,
+E = 752198636483dd7e5cf65b04e3d1590b4f105b7480154c3d7b171b470b48798a,
+T = aeb2631fc90e50407e5eadc3d654ce67c57e60b38fb1a1d9aa5a7dade7f65d81,
+U = 7fab6242fa551aa24e0088ed76a2bf4baaa7437ef455bf4f6bf76704be6dc5c4,
+
+TEST = 5,
+R = 02c027fe77da5b05ef3cc17b6737d1cb6130f244b3548713c928aa3e0ba0a54f06,
+ECPT = 031ce592dee24708742cb3e82a9dac2f344923b508397bf6fe754075e8819289c1,
+ECPS = 02702ae0ba3985031cee549383ec0c268d54d3812fd0bc03fbbeafa4a0f5971fed,
+ALPHA = 0225edbb623d849f72b972aa32dccae57590e8645a3cba518ce5413bd679b1e95c,
+BETA = 03703c36ca8afa1e630a8eec1917dd7c6cd2551b418980203c9c7de5b3a12b694d,
+E = 73a2c0e26289d7d29788c73e8505a9d937c70c3612da4b43d590d117c903fdd1,
+T = 34c55dcd770dab187c09723a580566476f15226fb8d43d3f878849937341180f,
+U = 5615c91cbb050c8c9695d7f6c7d01b0f9514c548fb6fb209f1632910dbcfdd97,
+
+TEST = 6,
+R = 02eb33b1c09509f2d9a0a1dcc104e58a20904c0a53c36e37bca75f37ecfe624f00,
+ECPT = 027078071c042aab8e30408c33b165d71c662f76431f9e28086dd210eb30579502,
+ECPS = 02732f7c260ce6307365a31d7db5994e2610522e32fc6d7388e9adcc92a3817e64,
+ALPHA = 039e8630942c599f2fdc9afc4788770f37c17a446471c1e4b2ea61add0997b16ac,
+BETA = 038650929e2ab0c8cfc12e6748eedd9a5759f55e698384fea664c760b5a1623fb0,
+E = 9a14a622c4f704365308f573ba8758a80289882a2c3466e27cbdeffb58d1a0f6,
+T = 68e84f71edd0589309a1da391709c67e61cb238d005c3b51b4a6a028a7116289,
+U = ea6a9937bc7dfc02e473e6afeb04ad5b253b6eb8b4f61d8eb923c801a2ec5624,
+
+TEST = 7,
+R = 02634853c61bf8dd1cb73136e4aa7bb6952ac43f17d023b703cdfea6edd98879d3,
+ECPT = 0235d1bf1139d0ecd0a2bb7338803914b6a210f6ffce3765d26994f0c99a28a8e8,
+ECPS = 02cf47d9a0839cb3e776639a59d746ecf02a65cf6225986e6a7d174a26ba33ebb7,
+ALPHA = 0202eadd9f208f398998b1abd30c96de38855bc69f81e2ac74a7acba8cf58ebf87,
+BETA = 03857b1d22f80064a97cebb390fbd0b4429979d3c0bb1560f3f376692ec20f39b4,
+E = 1cc738dd865f4e63a2f32d3e6de6f7c8c8b0ed70087975279d758f799cb2660b,
+T = bc4e6deff64854489892f7e1c1c9d7b479d1a60b40955f3dbe707b6f4fb8b593,
+U = 76a9e7b39adec1a642a6726fdb791e039ea1dfdb1de6e7a2f7bed08d2ea90845,
+
+TEST = 8,
+R = 03e799d910eade8157d1e983ab6fc2cead6a3d9cf73f0560423a7decf0eee4aa86,
+ECPT = 03e00884c86423d26f159993eef320f01ce50cbe580e74216cde175827584d2b18,
+ECPS = 03da39cfdfdd57449e4ddc93554d98dc5fe63e34c11efae5e0bedbc37d09886373,
+ALPHA = 0383db43a93fc170610199805f644c24e4732f3275dc26bc8e4317dd26c63ddb48,
+BETA = 02a03043f112c0b8fa3b0dbe5e251d0c5bdfbd8d710e40705c9bee7b0ccf7c595d,
+E = b34c62cd05beb4de7fcf9d6cddf5fd5d7f6a3e13a5ae2e3846e2e8c5a5914de2,
+T = 59e601d8f367d80f3306b659cada19d527e4a46ad7afdd7f59fbc47119e545ca,
+U = 67155b19d185fce6fe4ba6b93130b6ba34eb44fe9bd9751ac5ab93c4d35842df,
+
+TEST = 9,
+R = 03e39e29dce344b76227d753c3d630a255cf7f16cdd33a19f72e4152c7a26bb3ef,
+ECPT = 023b830a4aa6c6a7aaf8a432fee29c1688d9afdef41e9981ff873861f00dc78c10,
+ECPS = 0259dcd1aedeebbed7efd3b70f25975430ca7028ce56aaac38184f28c101252e5c,
+ALPHA = 0206efadb74156a84f9483f4cbaa8bac936697675f68689489966d0ceccd44b80a,
+BETA = 032f2f5e491dbd761bc286b7cf777dbe5ced9b65506dac5ce25fdf83bdb5ce9546,
+E = 4fd40c3f3cfa2dc76d3799d8ce3cb55db9af2abb367a673250ce6def60ec23c5,
+T = 8f1b054d6a8443d6d112e66384abfb63f7539889ee83cdaf5fbc87558cca0bc8,
+U = c72702fc9de49fb34e2b48c97ab90b443b7d18afec669f652e6885cd80ffc451,
+
diff --git a/testVectors/schnorr/challenge.json b/testVectors/schnorr/challenge.json
index b6a6ff5..89c6f77 100644
--- a/testVectors/schnorr/challenge.json
+++ b/testVectors/schnorr/challenge.json
@@ -1,82 +1,82 @@
[
{
"TEST": 0,
- "V": "03c4e1855e5a0784bef9bb7ddc36f8dc2da6662a6443b4429266681943fb93b76b",
- "C": "0229c5b60e0e3f3298dd3b0c090393a77161be92f9ab446ce103f7928293556325",
- "E": "72470568ba42a1f395874483800cdb0f7cd1d74e550f476fe8bd00a910a43d89",
- "ID": "ddfa4ce8ba4eb4ce3a9e85ff8a597d4a",
+ "V": "02a176790583cb46afccce262a4bc017ed2158220838931508ef057f43f367773d",
+ "C": "024b8ab626b59072b6af4bef79fbf2e9bb06ed624c9ecaa50976149cd8e7c96acc",
+ "E": "039bf63791581ac0be5f994edc2d18f368ebdea8bdf9d96af175556f61902528",
+ "ID": "d5cbc9979fef22eb7f2c7229a555ae78",
"AD": ""
},
{
"TEST": 1,
- "V": "03791b3200f8590630ca3e43d0c13653bd17797f605b6a964d9dc513f92556b90e",
- "C": "0314fa950d98212826f0af0acbcb64aeb671de4fda7cf813e3c1a0fa6ba15497c2",
- "E": "1faaaf805a78d7d077d09c25de23158b7f2b05a1ac8d3508e76e959990de5da9",
- "ID": "e6513d21d4bdac0e2225fcee5fc70882",
+ "V": "0318a8489034bb5c463574df14b2e01ee874d4f1dafd3ccb5bd5a896f70a2a603e",
+ "C": "02cfaa97966c2165c2ac45180fb25c7605e4e7b8df54ca44ded4a51e1ffca2becd",
+ "E": "393f5c11a666f00fa6a2a900b5291f97e0d6ca6a0b3d926d1ef88ad6e8e7bc98",
+ "ID": "21760c2a45dbf928d4bffe84e8eb1580",
"AD": ""
},
{
"TEST": 2,
- "V": "03068dc0ad4aa0de5fdc584bf0c60f480614cae40f63c6857181132110438079e6",
- "C": "02f1ac9f3bfa370e73da6d7c01aff1677be8c214adfc05ee164db9d3c7750f58f8",
- "E": "09ca506983461796d06835e5bafb180f9621df7604ed88c895752121af49bd7d",
- "ID": "64c03cd8b578e70c57ca5348be1a1320",
+ "V": "03f22588a2ed1bad9c268f43d11a5543354c96a6af88dd3ecde41457f0bdb9f502",
+ "C": "03942bd98066baaa416df52d80df211bf9e79e660e30ac8330442ddf2ab5483203",
+ "E": "4c4a3993a2a63bf72178cb80ade4448e28ee0789c6cac67835f41e3402242d2f",
+ "ID": "aad7998056d3a55dcc0bf97a25c11861",
"AD": ""
},
{
"TEST": 3,
- "V": "023c71c88abd5d66e6dc41168f3ee44b6e8d8180309b216653261e491a19552e38",
- "C": "02b7e6856389728b09cc4cdbe1649061fee09973207687ba036abd028151a1e99d",
- "E": "d7a0a7765a99930b002c73d0d260ca3921b27923c547951c779f8aee8b5abb3b",
- "ID": "c164da3fa78d42407450982b1701f64e",
+ "V": "02945b518fcc06a093fbb9f61486ca3e17cb34851b4d1fba2fa9d49ad794ada85c",
+ "C": "028e59bfb66b0d94eeaa8f5646081dd7a040336c28ff05fc7fcc58cfa7cf854e80",
+ "E": "7128b92b5fc492cdae6dc465986da78b513fbcec7c2f59173350bbd98d996164",
+ "ID": "33d06f26117fc7dca35d271ac985157e",
"AD": ""
},
{
"TEST": 4,
- "V": "02fa5f0016e46f8b5f339a46c4c25de8b527fb6824b1f859f20619d016dd58e36c",
- "C": "0371f807cebdc3c1bb9fbeb9168c91248d6c24289e06ca001de2d8348baf6fb90e",
- "E": "c699d59b4e1f4e03d934b7c6d532bffdfaf2066291861eb8b41572b71fc3c17a",
- "ID": "5fe038405254fede5fd901eeedc445f0",
+ "V": "02470debd491384cdf0e01b0e6327206e48a5fdce6040baad766fe2feb2b0bd0d2",
+ "C": "025ccf01a8dc4cc179fde4643681e598adab65ee97bc27c5682973c4e28b577642",
+ "E": "78e39b1a50cfb9510c12df628e74b223ec86332cfc54b09236956bbc833a1597",
+ "ID": "69f1242f71a3e7dbdf5e5d3a95c10b96",
"AD": ""
},
{
"TEST": 5,
- "V": "035cb223c6ebd4c338fef485058f370279a0f67ff519f4348f24b188259134f0f3",
- "C": "03b8c1205f605e441b1e617aef085946560d6fcbd238fdacb545a583c94b8cb2dd",
- "E": "6a3a02bcc5c833b3f34e4e04f29d34da7485b2504d55a7a6a97b518c81b4fc71",
- "ID": "2b68aa2631a9564972dcb3cbd7f9ed3d",
- "AD": "d48cbbf78bd74a2c26e57d2354c9225a"
+ "V": "02cfc213d2bc4ec8e8953ce4a4145b730fb6163362035d15cd162f8a97ebf5e1b4",
+ "C": "03c100078d60bd6b14f9c61a5acab37876df8beb6a1bc95b38c6eba22d59d4012c",
+ "E": "86b7f2deb6b2c6d41b9bfd9ca6c69a99acdd6b4e96b69d6d9b0c786f5517e164",
+ "ID": "9ca5174cb1aa9bae6370d25d6785e341",
+ "AD": "1591f421f41ac4cd8ac5269e4b99e0f9"
},
{
"TEST": 6,
- "V": "025345ca601fe14205ed9cd31514c252ed26a4cf6036af1de95076dcc167768c23",
- "C": "032035339b6cba6446c2c81d29c6afe204d6ada0b636f487150a7959f0014c9377",
- "E": "4ac5512263b781b0be01d0774a4d7b8cebb059b330540cbe805e7213cb30fbc8",
- "ID": "e2283fbb76c2765eb88c8680d98525ee",
- "AD": "6f3678b8dcc8f1b57608367c18076d43"
+ "V": "03480bb05fd84efc13bff7c8b598d3c039c29ec87bdd708ca713f441100a21dd3a",
+ "C": "0300e504f796b9d43c8a405f1f3cc037a36c1cd50816387a6fdaaabded39c1bf18",
+ "E": "ef2dd1f4e70ff6c100400c35e208a2e07e6b1afe271bb965c764f69f0abc17da",
+ "ID": "da6f7ad762b7aee88f4ace681fd1bc66",
+ "AD": "98ba1bf3d76807e3b302e1797d4d3f80"
},
{
"TEST": 7,
- "V": "0231994000293db76ee3403eaffc3e524d7aad7eb347a26eeba1ffb9576e9030f8",
- "C": "036b84067e7d74302a932c73b55d4b41e4ba361857b0081fc668d8a6fbbe27e689",
- "E": "b1d2c1156a3a77a610bc95fd313fc6498c231cad039b6ffce674694c72a00fb2",
- "ID": "ced168e07cdf38765ab691510e9f06ae",
- "AD": "2b972ace06c1956b6410d3f9bb21461c"
+ "V": "033abe7b79955e901a74a238e741a203994f920d4722bb19cf33fec18001631e95",
+ "C": "036ae855d9afca5f9603a5c3c8760700ead0fdd4d410fe2b4b4ec807b99397ef34",
+ "E": "393e98668698d9ebaca2ff6eb5b2a3db0aae25508da09c8004b75333078f3f3a",
+ "ID": "a8294309da772456164b5032d0e8c3a3",
+ "AD": "b42d44242c8d0356c4a35598279d9258"
},
{
"TEST": 8,
- "V": "020f0d1431c74358682de3467bd363466c0725e588af837a3d8f340a4286d9ff57",
- "C": "03ae3b1014391deb514e3b3bc798f9d77980888fb6c0497125494c423ea02838f8",
- "E": "e1af4adc2b3854e1c8405adbdffec39a02e0464217af90e6c6239e274a9cb09b",
- "ID": "798fafd60415b818d4075394c0b1bfdb",
- "AD": "aa40c4178a5af48ad56d692516677eca"
+ "V": "0212802ceb98750059574a30e98ddfdc2923f8e44b0a6d5f331036b2fb7728287e",
+ "C": "02b23ed8faf6d64e9dc4ce13956ac81bf1ef562b397afdc91f60a684816a6f57f3",
+ "E": "ea7aee412a9990829e6963ab2b992f546e1c48d3f79b1564cf0a50678003a130",
+ "ID": "942f4ccccb572383ffc1f03a7d7c63c1",
+ "AD": "828b337445277d7deb1e5f74b8c21efe"
},
{
"TEST": 9,
- "V": "025101370b069de8131800b15ec74854b0a8d21611336a53f020708c8ee84c2fed",
- "C": "024d55b47c8182c7fb9d926323dd9ba785d101f6c354a2be18d7928d73d9c6958c",
- "E": "5e76c14ba93e72462bddc3f16efbb575147210fd3deca55350c59ae5afff6e09",
- "ID": "f1ba4a6b31acc1e72d3f4a2deecf9ed9",
- "AD": "6193b0e56bf856f17ec1c75ae1a4f210"
+ "V": "022a2791c4fb15b75da5d699da051f3ee55219ef10ccd66a49971d49460c104388",
+ "C": "03ea3f63538bb4a6ebb4e3560d946b656f6c2ecd8064fe827e2e08b1c58f9bb6f0",
+ "E": "cff867b78bbb1e7487e3ed124cd029e2c9e231febfeb9169b4e25fdd06665258",
+ "ID": "574f0bbfe941096ddc7f0042d01b4b82",
+ "AD": "f28a3d2395a30ca99a24e78cca947435"
}
]
\ No newline at end of file
diff --git a/testVectors/schnorr/challenge.txt b/testVectors/schnorr/challenge.txt
index f532bb8..1826e83 100644
--- a/testVectors/schnorr/challenge.txt
+++ b/testVectors/schnorr/challenge.txt
@@ -1,70 +1,70 @@
TEST = 0,
-V = 03c4e1855e5a0784bef9bb7ddc36f8dc2da6662a6443b4429266681943fb93b76b,
-C = 0229c5b60e0e3f3298dd3b0c090393a77161be92f9ab446ce103f7928293556325,
-E = 72470568ba42a1f395874483800cdb0f7cd1d74e550f476fe8bd00a910a43d89,
-ID = ddfa4ce8ba4eb4ce3a9e85ff8a597d4a,
+V = 02a176790583cb46afccce262a4bc017ed2158220838931508ef057f43f367773d,
+C = 024b8ab626b59072b6af4bef79fbf2e9bb06ed624c9ecaa50976149cd8e7c96acc,
+E = 039bf63791581ac0be5f994edc2d18f368ebdea8bdf9d96af175556f61902528,
+ID = d5cbc9979fef22eb7f2c7229a555ae78,
AD = ,
TEST = 1,
-V = 03791b3200f8590630ca3e43d0c13653bd17797f605b6a964d9dc513f92556b90e,
-C = 0314fa950d98212826f0af0acbcb64aeb671de4fda7cf813e3c1a0fa6ba15497c2,
-E = 1faaaf805a78d7d077d09c25de23158b7f2b05a1ac8d3508e76e959990de5da9,
-ID = e6513d21d4bdac0e2225fcee5fc70882,
+V = 0318a8489034bb5c463574df14b2e01ee874d4f1dafd3ccb5bd5a896f70a2a603e,
+C = 02cfaa97966c2165c2ac45180fb25c7605e4e7b8df54ca44ded4a51e1ffca2becd,
+E = 393f5c11a666f00fa6a2a900b5291f97e0d6ca6a0b3d926d1ef88ad6e8e7bc98,
+ID = 21760c2a45dbf928d4bffe84e8eb1580,
AD = ,
TEST = 2,
-V = 03068dc0ad4aa0de5fdc584bf0c60f480614cae40f63c6857181132110438079e6,
-C = 02f1ac9f3bfa370e73da6d7c01aff1677be8c214adfc05ee164db9d3c7750f58f8,
-E = 09ca506983461796d06835e5bafb180f9621df7604ed88c895752121af49bd7d,
-ID = 64c03cd8b578e70c57ca5348be1a1320,
+V = 03f22588a2ed1bad9c268f43d11a5543354c96a6af88dd3ecde41457f0bdb9f502,
+C = 03942bd98066baaa416df52d80df211bf9e79e660e30ac8330442ddf2ab5483203,
+E = 4c4a3993a2a63bf72178cb80ade4448e28ee0789c6cac67835f41e3402242d2f,
+ID = aad7998056d3a55dcc0bf97a25c11861,
AD = ,
TEST = 3,
-V = 023c71c88abd5d66e6dc41168f3ee44b6e8d8180309b216653261e491a19552e38,
-C = 02b7e6856389728b09cc4cdbe1649061fee09973207687ba036abd028151a1e99d,
-E = d7a0a7765a99930b002c73d0d260ca3921b27923c547951c779f8aee8b5abb3b,
-ID = c164da3fa78d42407450982b1701f64e,
+V = 02945b518fcc06a093fbb9f61486ca3e17cb34851b4d1fba2fa9d49ad794ada85c,
+C = 028e59bfb66b0d94eeaa8f5646081dd7a040336c28ff05fc7fcc58cfa7cf854e80,
+E = 7128b92b5fc492cdae6dc465986da78b513fbcec7c2f59173350bbd98d996164,
+ID = 33d06f26117fc7dca35d271ac985157e,
AD = ,
TEST = 4,
-V = 02fa5f0016e46f8b5f339a46c4c25de8b527fb6824b1f859f20619d016dd58e36c,
-C = 0371f807cebdc3c1bb9fbeb9168c91248d6c24289e06ca001de2d8348baf6fb90e,
-E = c699d59b4e1f4e03d934b7c6d532bffdfaf2066291861eb8b41572b71fc3c17a,
-ID = 5fe038405254fede5fd901eeedc445f0,
+V = 02470debd491384cdf0e01b0e6327206e48a5fdce6040baad766fe2feb2b0bd0d2,
+C = 025ccf01a8dc4cc179fde4643681e598adab65ee97bc27c5682973c4e28b577642,
+E = 78e39b1a50cfb9510c12df628e74b223ec86332cfc54b09236956bbc833a1597,
+ID = 69f1242f71a3e7dbdf5e5d3a95c10b96,
AD = ,
TEST = 5,
-V = 035cb223c6ebd4c338fef485058f370279a0f67ff519f4348f24b188259134f0f3,
-C = 03b8c1205f605e441b1e617aef085946560d6fcbd238fdacb545a583c94b8cb2dd,
-E = 6a3a02bcc5c833b3f34e4e04f29d34da7485b2504d55a7a6a97b518c81b4fc71,
-ID = 2b68aa2631a9564972dcb3cbd7f9ed3d,
-AD = d48cbbf78bd74a2c26e57d2354c9225a,
+V = 02cfc213d2bc4ec8e8953ce4a4145b730fb6163362035d15cd162f8a97ebf5e1b4,
+C = 03c100078d60bd6b14f9c61a5acab37876df8beb6a1bc95b38c6eba22d59d4012c,
+E = 86b7f2deb6b2c6d41b9bfd9ca6c69a99acdd6b4e96b69d6d9b0c786f5517e164,
+ID = 9ca5174cb1aa9bae6370d25d6785e341,
+AD = 1591f421f41ac4cd8ac5269e4b99e0f9,
TEST = 6,
-V = 025345ca601fe14205ed9cd31514c252ed26a4cf6036af1de95076dcc167768c23,
-C = 032035339b6cba6446c2c81d29c6afe204d6ada0b636f487150a7959f0014c9377,
-E = 4ac5512263b781b0be01d0774a4d7b8cebb059b330540cbe805e7213cb30fbc8,
-ID = e2283fbb76c2765eb88c8680d98525ee,
-AD = 6f3678b8dcc8f1b57608367c18076d43,
+V = 03480bb05fd84efc13bff7c8b598d3c039c29ec87bdd708ca713f441100a21dd3a,
+C = 0300e504f796b9d43c8a405f1f3cc037a36c1cd50816387a6fdaaabded39c1bf18,
+E = ef2dd1f4e70ff6c100400c35e208a2e07e6b1afe271bb965c764f69f0abc17da,
+ID = da6f7ad762b7aee88f4ace681fd1bc66,
+AD = 98ba1bf3d76807e3b302e1797d4d3f80,
TEST = 7,
-V = 0231994000293db76ee3403eaffc3e524d7aad7eb347a26eeba1ffb9576e9030f8,
-C = 036b84067e7d74302a932c73b55d4b41e4ba361857b0081fc668d8a6fbbe27e689,
-E = b1d2c1156a3a77a610bc95fd313fc6498c231cad039b6ffce674694c72a00fb2,
-ID = ced168e07cdf38765ab691510e9f06ae,
-AD = 2b972ace06c1956b6410d3f9bb21461c,
+V = 033abe7b79955e901a74a238e741a203994f920d4722bb19cf33fec18001631e95,
+C = 036ae855d9afca5f9603a5c3c8760700ead0fdd4d410fe2b4b4ec807b99397ef34,
+E = 393e98668698d9ebaca2ff6eb5b2a3db0aae25508da09c8004b75333078f3f3a,
+ID = a8294309da772456164b5032d0e8c3a3,
+AD = b42d44242c8d0356c4a35598279d9258,
TEST = 8,
-V = 020f0d1431c74358682de3467bd363466c0725e588af837a3d8f340a4286d9ff57,
-C = 03ae3b1014391deb514e3b3bc798f9d77980888fb6c0497125494c423ea02838f8,
-E = e1af4adc2b3854e1c8405adbdffec39a02e0464217af90e6c6239e274a9cb09b,
-ID = 798fafd60415b818d4075394c0b1bfdb,
-AD = aa40c4178a5af48ad56d692516677eca,
+V = 0212802ceb98750059574a30e98ddfdc2923f8e44b0a6d5f331036b2fb7728287e,
+C = 02b23ed8faf6d64e9dc4ce13956ac81bf1ef562b397afdc91f60a684816a6f57f3,
+E = ea7aee412a9990829e6963ab2b992f546e1c48d3f79b1564cf0a50678003a130,
+ID = 942f4ccccb572383ffc1f03a7d7c63c1,
+AD = 828b337445277d7deb1e5f74b8c21efe,
TEST = 9,
-V = 025101370b069de8131800b15ec74854b0a8d21611336a53f020708c8ee84c2fed,
-C = 024d55b47c8182c7fb9d926323dd9ba785d101f6c354a2be18d7928d73d9c6958c,
-E = 5e76c14ba93e72462bddc3f16efbb575147210fd3deca55350c59ae5afff6e09,
-ID = f1ba4a6b31acc1e72d3f4a2deecf9ed9,
-AD = 6193b0e56bf856f17ec1c75ae1a4f210,
+V = 022a2791c4fb15b75da5d699da051f3ee55219ef10ccd66a49971d49460c104388,
+C = 03ea3f63538bb4a6ebb4e3560d946b656f6c2ecd8064fe827e2e08b1c58f9bb6f0,
+E = cff867b78bbb1e7487e3ed124cd029e2c9e231febfeb9169b4e25fdd06665258,
+ID = 574f0bbfe941096ddc7f0042d01b4b82,
+AD = f28a3d2395a30ca99a24e78cca947435,
diff --git a/testVectors/schnorr/dchallenge.json b/testVectors/schnorr/dchallenge.json
index 7b7c57c..6d042a9 100644
--- a/testVectors/schnorr/dchallenge.json
+++ b/testVectors/schnorr/dchallenge.json
@@ -1,92 +1,92 @@
[
{
"TEST": 0,
- "R": "038f6876d53b3b8f858feaf34ea139354cc2daf210162f8d89258e36cc89d1ea15",
- "V": "03f17f5e29ec8dc9de0a3284fed2d925efceaba371eb9625bff8dc2b60f78e767d",
- "C": "03d68c95f6691138a14674ae80a31f1cb1ef1da3deb693c4c326c57516d1492dd9",
- "E": "fa45c59892d02bd2e32059b4a3c39a2e822e245de49eff26c4f9d8004565cfd3",
- "ID": "d0085a45525d1436e41889b7b6cae7db",
+ "R": "031f34b29baecc9d2612cb0fc2f76ab044c4e3d680f5fe59cc11c1ae8c89cb2838",
+ "V": "027471aa6cec039a6b451ac6e5e4559ba2c8d287cd75fcf1dfa6c3461f39d3a9f2",
+ "C": "0385559d63ebe60eeecac4b3e54ca5525b3553b2f805bdb7b4e9a05624a63644d4",
+ "E": "731e1fbcb9dfb310e6a23a6e362a0bc6647e7433907ccc5b8d05657fb14aaa56",
+ "ID": "4567587cca20c3912ba02fe14b649829",
"AD": ""
},
{
"TEST": 1,
- "R": "03203ca28db780126db0551ee203f5fdc1a51e2152185eeefaca5abe854cf9e5f6",
- "V": "03f1bf89af15b7f5c1e7cd4f64377cafc61edf2fefc1ee1a06ba60423aaf387f86",
- "C": "03abba83dd5f78cd4c6ec8b56003226fbc78389692eea912826c7ec326aaa854df",
- "E": "a5120e188ee5159db3a53d9033564e7f9f2d6abe26bd7932761820c835285f24",
- "ID": "916500443089980b552495ea07205280",
+ "R": "0371a9bd0dcade30fe1b70bfebf45e6e3df9ee185925d8c1462e1dfa2c1586f502",
+ "V": "0367b4b5a89b2f222682a5b454af779b161f76b6488f4a3e15b25814b88f6b0ed9",
+ "C": "03df434aa5e9fe202e5b75aadda91e7916e03348c9abbf7e6a45d44835969c993a",
+ "E": "a5a05e68ef3c28196de4c1a722c588f345fef6e0a90c2ba783e9832cc71ace28",
+ "ID": "7e5a46b87c3952ffae977101fbe4aa5a",
"AD": ""
},
{
"TEST": 2,
- "R": "038123e9c9495c7c0586715bcb95730d34228ded11cbcd303c9d89306d49a02900",
- "V": "03f72ee114d5945f60bc781575568b96d5296d61fb15775fb9be63c7f7d5b5b2ba",
- "C": "029909e097e12eb3ae0e9afd11b3ed44ff645cbaac2b967c404ca55986a6743af6",
- "E": "a9180558479fa9f5157d26c63b1d434d44902095c7ea2eadeb3fc9cd9ca0374e",
- "ID": "5e452e6dd894d61567d9e475b6c2d230",
+ "R": "02faf84fff3ddc4ca81fdef16a0951230f559db8cfa8ef96b22fe0d1fc84793348",
+ "V": "02f6c3eb625c33ac65c790cfb8a123c5fc96a9162163d94549d50ab77b76668cc4",
+ "C": "02d2a1d5b09ddd0895d3cecddb9e07286dc610fa96bcc646bab100746eda7ba98d",
+ "E": "df26a6994b268ecf1e6e0513b581dbd961615ddb3afb36b0a7e246e0e9f03403",
+ "ID": "2c2d1edbba148f9c9fc9c43f5329dcdc",
"AD": ""
},
{
"TEST": 3,
- "R": "024d05a823ab116021580039cb43a964c24289163fca16772b36018a528dff639d",
- "V": "03e7b821d69776c189e02c853accb62ed61f1dd7e34b976b79a2ae5fb95ab6b3e2",
- "C": "02c7b222f108cc7aa566237e7743519196d36aa7d93e99ab9e4c7d5b35afca4448",
- "E": "5a83f414fb278146866addaee6c90ba4d2fa879c302808137ca06870a25821b7",
- "ID": "06609e8b9b7fb626bb7f2ea8b47f4582",
+ "R": "020d395eca9daf2bde61d683336be0b7158e81060456482f252c6a0902335cbd5b",
+ "V": "02b3bac2f4ae4b5774c0b2118bd282f7bdae2508da4d50a0b6b15bba03161bbbaf",
+ "C": "03cd22d4c01b912fe98482930d17111cc3963d7032e9bc2670a9e3b37f2eddbbf6",
+ "E": "096c19ae7b41bd11a3383c393b8cec0e00d21bdf0d1eaea3b322d7925303c5a5",
+ "ID": "702f48e6c8ada26fd0bdc58271292b5d",
"AD": ""
},
{
"TEST": 4,
- "R": "03453c2a1183008506540c1eb410953699ab6a95591cceb8e38761d897c845761d",
- "V": "037f93df77762c37d253f1afe663322f12f970f23a6a2d204682e13aa76c99b538",
- "C": "03eb1236bc465f35669a0f98649fa852bce6f5bb8770d9096f31fad5cce1767d6d",
- "E": "748ff317b056c57b4fd366678f266d16fcf94f69bfe877fba4393d267f93b658",
- "ID": "7486107a9dbcde68c8e388e24129d9c5",
+ "R": "0349eb8974c86282418e5e1f8156ddacf18a0e9302604e36a55af1ed450471071d",
+ "V": "02e246387da4fceb844492f939b87a37554b93cebc8812e5be44e293380f458758",
+ "C": "03b0e1f9a308984968622bd239bdfd82a95cc6f467b8c5e5ba1c50647f74d5d967",
+ "E": "13dce3548d40c3dcad1b266b90f83157ff9520169eefcb372c5595f91f15440a",
+ "ID": "2a9b11dd314c26d04bc5b6b3fee2f9fb",
"AD": ""
},
{
"TEST": 5,
- "R": "0253090ba3693f7f8865c9d2e7fbabcf19c24b27b03237dc11b653277a18821271",
- "V": "03df3271f482174215145c57515c291ccd3cc258cf9e6b99e9e533f36b22a7f073",
- "C": "0304e404f060065805140a3107c32962d925f3199e48a40f476080b0d7bad112b4",
- "E": "7d0b02747cb75a23135d75717e1717d3524c1c8896cf8b976f0fcdcba142a35f",
- "ID": "9d914a43ecf839b2843e54a42fe4c009",
- "AD": "2164c3ae3e3436b841e740cf809b2795"
+ "R": "030b74e1973bf10a1b5b57656d533bd9bc6c5369a8b50dc02f4da313609c4b4cae",
+ "V": "03e461314f61dcefee5107194a30e09bc001aa9fc1dcb539eb37b9d9b86142a9b9",
+ "C": "02df2d6ec6490963c56cfb47c18fdc03ad0adf48e5598b020cad4fe2a21bb192d8",
+ "E": "7587b910b49680f41a788e79405d378859aeca5a58df58722fc648d8cc6871ed",
+ "ID": "a8dfe3b9507a2f8dd3f8e4c26e5e0303",
+ "AD": "4baa8e08f18f8bc426a726caa9e3f60c"
},
{
"TEST": 6,
- "R": "0393f5387d1e20fc0472b388662238a2a2239e9c5516115f13abc57f7f58430dbf",
- "V": "038e0b62ea7798093e7c512136b69d096cd00c1c84393bf5bb5947bc930f0db31c",
- "C": "02f4bb70005ac5adc974a2ce6093ed2269fef48c8c9f45913ab3684c1fcea90bf4",
- "E": "b0134e65f16518ba896f98363dc5fecd920d9490d57cdbd5f937242f039066d6",
- "ID": "3a7e76440dd7adf8cd622e24c8e4f199",
- "AD": "c47299eaa266b0c1a920deab65fa7cdf"
+ "R": "03bb193bfc8ece97320807a2a7ebbf7b86743e618efea217f98dc721604eb38de4",
+ "V": "028fe6aa66ed30218ba0eab95cece4ebac13b4ba57a1e369ff8f0075235fa25551",
+ "C": "0389a1e979398764bb184b776db5cbab8ec6d5a35ca1afcbc48a0212807b44f78f",
+ "E": "fd095efb0352f3092090a73ab1c8256d6ce91c1200a9ce94cc78ad0972387324",
+ "ID": "3c5335f5b78fd07397d2afa043261d8e",
+ "AD": "af5db16b80f07b104dd2ed17ec9855fa"
},
{
"TEST": 7,
- "R": "0309f0fb8c0e32bb1dcdb5cd810ae1c0b0e1c5418c1f29cb7b7696c139dd37611e",
- "V": "03bb6b807b0be4262af130e34e663f7682032a3eab2fce282c56a7ea35b89c0f96",
- "C": "03cdc87374f522dcff6c16d7be17a432066b7065646c0c6e67d6fe58c5db0dd6a4",
- "E": "d933e039daf386d798cf38f4d5fcea4e587fcd386bac0eeceb92a241b354d71b",
- "ID": "e08c5e4e3eb08d0c54ab91f1bbb472a2",
- "AD": "b5c96c751c18209f8ff8bf369a5ddfc2"
+ "R": "033bdfe6658839c138ab920092342c0bde0ac18b21acebc45c4702327da49d25fe",
+ "V": "02f2805b6468ad19a784b79af287b33e3ec02360d27adc45e49303a5841ba2f96f",
+ "C": "0202f41283ab55d988431ddeb11c1d2ba6072b2310a810199c70add17884652adc",
+ "E": "d1c3151e9d035de98a7d440a1b0355e7aa48b482ded2f6d4d32e3d595b765c4b",
+ "ID": "ca79704548b90cb2f6fcb2691fd9ac4b",
+ "AD": "50bd088a6040960420c2a592c82f11b9"
},
{
"TEST": 8,
- "R": "0217571b58356c8dcc258e8ce7787d90d0557f911cea7747ad97cb1416ff06d57c",
- "V": "025c264cdf73fcfaf7f6afba17009807271b15f85062022c1cc0c3c74e03da35de",
- "C": "03b86b7c0b3ca05fd8975af66f3b9a2f5ab338205aa8dbace6f9a2dce12085ae31",
- "E": "583c9d20a4df474615d0ee2f8762e16ec23db022f1f05d55a3166b95f3009bff",
- "ID": "ee99fe3e0e15220ffcfe792fdd9c1498",
- "AD": "748cf346cf2817b826446cf6af22a503"
+ "R": "02a7d55d997faca384d6784923d49a5ba36b185c0427f56118738736ed304318ac",
+ "V": "024ca8a828ae901debfa693e416540e267e2bf53a4e393cf748352372c44a0c528",
+ "C": "03fd319a8cf14cf7edbb740461035901aff1ba52911a13a8e9a9251b8805edaa6b",
+ "E": "729441880dab1973d24ddce4af1319367a568fe80ee26f0135d677aaf77e04ac",
+ "ID": "14d194a9a7bb50067b75030a2a4b31aa",
+ "AD": "9efbe273c43ef2d3a9ab67907b3db77c"
},
{
"TEST": 9,
- "R": "02e3a46f35ce40e59194a7dd349cd701c9940f58a6d75824094e15c00598f66525",
- "V": "032459eb39f986ec51c24717d6c211717f8d8bb24a951148c2324e410d15528a81",
- "C": "036152bf63d0f3cd012afb9326c260a757c148f30f7de60db2c7819f4eaf74a9ec",
- "E": "9616c3a9c752ecca4bf58eca5ed8853f8c0296f318b98ee7dbefe327d55742bd",
- "ID": "b910c484dbc541799639071705b90234",
- "AD": "9b5fa9d07790980f318bf3a705f5bc58"
+ "R": "021e221451eb615632912423657e9b79fe0ea58c333667893a6c205eaf3a75822a",
+ "V": "0242a2fabc74574a78453dd9db7b0b9eaf32890cb2188f5c855c0723db0d3b92a1",
+ "C": "03409379b58af01fea446e18df1b465a4634806900825200334d5390cc3ae3fc89",
+ "E": "66343214024de8c3f31e4985628f446f43c17c82bbff3b401324124aeb494e9f",
+ "ID": "8151b308bee69f9dfe705c290ce4dea9",
+ "AD": "cace19ad3775febf42974c801012b386"
}
]
\ No newline at end of file
diff --git a/testVectors/schnorr/dchallenge.txt b/testVectors/schnorr/dchallenge.txt
index 10cf669..784697d 100644
--- a/testVectors/schnorr/dchallenge.txt
+++ b/testVectors/schnorr/dchallenge.txt
@@ -1,80 +1,80 @@
TEST = 0,
-R = 038f6876d53b3b8f858feaf34ea139354cc2daf210162f8d89258e36cc89d1ea15,
-V = 03f17f5e29ec8dc9de0a3284fed2d925efceaba371eb9625bff8dc2b60f78e767d,
-C = 03d68c95f6691138a14674ae80a31f1cb1ef1da3deb693c4c326c57516d1492dd9,
-E = fa45c59892d02bd2e32059b4a3c39a2e822e245de49eff26c4f9d8004565cfd3,
-ID = d0085a45525d1436e41889b7b6cae7db,
+R = 031f34b29baecc9d2612cb0fc2f76ab044c4e3d680f5fe59cc11c1ae8c89cb2838,
+V = 027471aa6cec039a6b451ac6e5e4559ba2c8d287cd75fcf1dfa6c3461f39d3a9f2,
+C = 0385559d63ebe60eeecac4b3e54ca5525b3553b2f805bdb7b4e9a05624a63644d4,
+E = 731e1fbcb9dfb310e6a23a6e362a0bc6647e7433907ccc5b8d05657fb14aaa56,
+ID = 4567587cca20c3912ba02fe14b649829,
AD = ,
TEST = 1,
-R = 03203ca28db780126db0551ee203f5fdc1a51e2152185eeefaca5abe854cf9e5f6,
-V = 03f1bf89af15b7f5c1e7cd4f64377cafc61edf2fefc1ee1a06ba60423aaf387f86,
-C = 03abba83dd5f78cd4c6ec8b56003226fbc78389692eea912826c7ec326aaa854df,
-E = a5120e188ee5159db3a53d9033564e7f9f2d6abe26bd7932761820c835285f24,
-ID = 916500443089980b552495ea07205280,
+R = 0371a9bd0dcade30fe1b70bfebf45e6e3df9ee185925d8c1462e1dfa2c1586f502,
+V = 0367b4b5a89b2f222682a5b454af779b161f76b6488f4a3e15b25814b88f6b0ed9,
+C = 03df434aa5e9fe202e5b75aadda91e7916e03348c9abbf7e6a45d44835969c993a,
+E = a5a05e68ef3c28196de4c1a722c588f345fef6e0a90c2ba783e9832cc71ace28,
+ID = 7e5a46b87c3952ffae977101fbe4aa5a,
AD = ,
TEST = 2,
-R = 038123e9c9495c7c0586715bcb95730d34228ded11cbcd303c9d89306d49a02900,
-V = 03f72ee114d5945f60bc781575568b96d5296d61fb15775fb9be63c7f7d5b5b2ba,
-C = 029909e097e12eb3ae0e9afd11b3ed44ff645cbaac2b967c404ca55986a6743af6,
-E = a9180558479fa9f5157d26c63b1d434d44902095c7ea2eadeb3fc9cd9ca0374e,
-ID = 5e452e6dd894d61567d9e475b6c2d230,
+R = 02faf84fff3ddc4ca81fdef16a0951230f559db8cfa8ef96b22fe0d1fc84793348,
+V = 02f6c3eb625c33ac65c790cfb8a123c5fc96a9162163d94549d50ab77b76668cc4,
+C = 02d2a1d5b09ddd0895d3cecddb9e07286dc610fa96bcc646bab100746eda7ba98d,
+E = df26a6994b268ecf1e6e0513b581dbd961615ddb3afb36b0a7e246e0e9f03403,
+ID = 2c2d1edbba148f9c9fc9c43f5329dcdc,
AD = ,
TEST = 3,
-R = 024d05a823ab116021580039cb43a964c24289163fca16772b36018a528dff639d,
-V = 03e7b821d69776c189e02c853accb62ed61f1dd7e34b976b79a2ae5fb95ab6b3e2,
-C = 02c7b222f108cc7aa566237e7743519196d36aa7d93e99ab9e4c7d5b35afca4448,
-E = 5a83f414fb278146866addaee6c90ba4d2fa879c302808137ca06870a25821b7,
-ID = 06609e8b9b7fb626bb7f2ea8b47f4582,
+R = 020d395eca9daf2bde61d683336be0b7158e81060456482f252c6a0902335cbd5b,
+V = 02b3bac2f4ae4b5774c0b2118bd282f7bdae2508da4d50a0b6b15bba03161bbbaf,
+C = 03cd22d4c01b912fe98482930d17111cc3963d7032e9bc2670a9e3b37f2eddbbf6,
+E = 096c19ae7b41bd11a3383c393b8cec0e00d21bdf0d1eaea3b322d7925303c5a5,
+ID = 702f48e6c8ada26fd0bdc58271292b5d,
AD = ,
TEST = 4,
-R = 03453c2a1183008506540c1eb410953699ab6a95591cceb8e38761d897c845761d,
-V = 037f93df77762c37d253f1afe663322f12f970f23a6a2d204682e13aa76c99b538,
-C = 03eb1236bc465f35669a0f98649fa852bce6f5bb8770d9096f31fad5cce1767d6d,
-E = 748ff317b056c57b4fd366678f266d16fcf94f69bfe877fba4393d267f93b658,
-ID = 7486107a9dbcde68c8e388e24129d9c5,
+R = 0349eb8974c86282418e5e1f8156ddacf18a0e9302604e36a55af1ed450471071d,
+V = 02e246387da4fceb844492f939b87a37554b93cebc8812e5be44e293380f458758,
+C = 03b0e1f9a308984968622bd239bdfd82a95cc6f467b8c5e5ba1c50647f74d5d967,
+E = 13dce3548d40c3dcad1b266b90f83157ff9520169eefcb372c5595f91f15440a,
+ID = 2a9b11dd314c26d04bc5b6b3fee2f9fb,
AD = ,
TEST = 5,
-R = 0253090ba3693f7f8865c9d2e7fbabcf19c24b27b03237dc11b653277a18821271,
-V = 03df3271f482174215145c57515c291ccd3cc258cf9e6b99e9e533f36b22a7f073,
-C = 0304e404f060065805140a3107c32962d925f3199e48a40f476080b0d7bad112b4,
-E = 7d0b02747cb75a23135d75717e1717d3524c1c8896cf8b976f0fcdcba142a35f,
-ID = 9d914a43ecf839b2843e54a42fe4c009,
-AD = 2164c3ae3e3436b841e740cf809b2795,
+R = 030b74e1973bf10a1b5b57656d533bd9bc6c5369a8b50dc02f4da313609c4b4cae,
+V = 03e461314f61dcefee5107194a30e09bc001aa9fc1dcb539eb37b9d9b86142a9b9,
+C = 02df2d6ec6490963c56cfb47c18fdc03ad0adf48e5598b020cad4fe2a21bb192d8,
+E = 7587b910b49680f41a788e79405d378859aeca5a58df58722fc648d8cc6871ed,
+ID = a8dfe3b9507a2f8dd3f8e4c26e5e0303,
+AD = 4baa8e08f18f8bc426a726caa9e3f60c,
TEST = 6,
-R = 0393f5387d1e20fc0472b388662238a2a2239e9c5516115f13abc57f7f58430dbf,
-V = 038e0b62ea7798093e7c512136b69d096cd00c1c84393bf5bb5947bc930f0db31c,
-C = 02f4bb70005ac5adc974a2ce6093ed2269fef48c8c9f45913ab3684c1fcea90bf4,
-E = b0134e65f16518ba896f98363dc5fecd920d9490d57cdbd5f937242f039066d6,
-ID = 3a7e76440dd7adf8cd622e24c8e4f199,
-AD = c47299eaa266b0c1a920deab65fa7cdf,
+R = 03bb193bfc8ece97320807a2a7ebbf7b86743e618efea217f98dc721604eb38de4,
+V = 028fe6aa66ed30218ba0eab95cece4ebac13b4ba57a1e369ff8f0075235fa25551,
+C = 0389a1e979398764bb184b776db5cbab8ec6d5a35ca1afcbc48a0212807b44f78f,
+E = fd095efb0352f3092090a73ab1c8256d6ce91c1200a9ce94cc78ad0972387324,
+ID = 3c5335f5b78fd07397d2afa043261d8e,
+AD = af5db16b80f07b104dd2ed17ec9855fa,
TEST = 7,
-R = 0309f0fb8c0e32bb1dcdb5cd810ae1c0b0e1c5418c1f29cb7b7696c139dd37611e,
-V = 03bb6b807b0be4262af130e34e663f7682032a3eab2fce282c56a7ea35b89c0f96,
-C = 03cdc87374f522dcff6c16d7be17a432066b7065646c0c6e67d6fe58c5db0dd6a4,
-E = d933e039daf386d798cf38f4d5fcea4e587fcd386bac0eeceb92a241b354d71b,
-ID = e08c5e4e3eb08d0c54ab91f1bbb472a2,
-AD = b5c96c751c18209f8ff8bf369a5ddfc2,
+R = 033bdfe6658839c138ab920092342c0bde0ac18b21acebc45c4702327da49d25fe,
+V = 02f2805b6468ad19a784b79af287b33e3ec02360d27adc45e49303a5841ba2f96f,
+C = 0202f41283ab55d988431ddeb11c1d2ba6072b2310a810199c70add17884652adc,
+E = d1c3151e9d035de98a7d440a1b0355e7aa48b482ded2f6d4d32e3d595b765c4b,
+ID = ca79704548b90cb2f6fcb2691fd9ac4b,
+AD = 50bd088a6040960420c2a592c82f11b9,
TEST = 8,
-R = 0217571b58356c8dcc258e8ce7787d90d0557f911cea7747ad97cb1416ff06d57c,
-V = 025c264cdf73fcfaf7f6afba17009807271b15f85062022c1cc0c3c74e03da35de,
-C = 03b86b7c0b3ca05fd8975af66f3b9a2f5ab338205aa8dbace6f9a2dce12085ae31,
-E = 583c9d20a4df474615d0ee2f8762e16ec23db022f1f05d55a3166b95f3009bff,
-ID = ee99fe3e0e15220ffcfe792fdd9c1498,
-AD = 748cf346cf2817b826446cf6af22a503,
+R = 02a7d55d997faca384d6784923d49a5ba36b185c0427f56118738736ed304318ac,
+V = 024ca8a828ae901debfa693e416540e267e2bf53a4e393cf748352372c44a0c528,
+C = 03fd319a8cf14cf7edbb740461035901aff1ba52911a13a8e9a9251b8805edaa6b,
+E = 729441880dab1973d24ddce4af1319367a568fe80ee26f0135d677aaf77e04ac,
+ID = 14d194a9a7bb50067b75030a2a4b31aa,
+AD = 9efbe273c43ef2d3a9ab67907b3db77c,
TEST = 9,
-R = 02e3a46f35ce40e59194a7dd349cd701c9940f58a6d75824094e15c00598f66525,
-V = 032459eb39f986ec51c24717d6c211717f8d8bb24a951148c2324e410d15528a81,
-C = 036152bf63d0f3cd012afb9326c260a757c148f30f7de60db2c7819f4eaf74a9ec,
-E = 9616c3a9c752ecca4bf58eca5ed8853f8c0296f318b98ee7dbefe327d55742bd,
-ID = b910c484dbc541799639071705b90234,
-AD = 9b5fa9d07790980f318bf3a705f5bc58,
+R = 021e221451eb615632912423657e9b79fe0ea58c333667893a6c205eaf3a75822a,
+V = 0242a2fabc74574a78453dd9db7b0b9eaf32890cb2188f5c855c0723db0d3b92a1,
+C = 03409379b58af01fea446e18df1b465a4634806900825200334d5390cc3ae3fc89,
+E = 66343214024de8c3f31e4985628f446f43c17c82bbff3b401324124aeb494e9f,
+ID = 8151b308bee69f9dfe705c290ce4dea9,
+AD = cace19ad3775febf42974c801012b386,
diff --git a/testVectors/schnorr/dprove.json b/testVectors/schnorr/dprove.json
index a422c3c..2933611 100644
--- a/testVectors/schnorr/dprove.json
+++ b/testVectors/schnorr/dprove.json
@@ -1,102 +1,102 @@
[
{
"TEST": 0,
- "A": "c3658c336985e9415ac8395a5a97dcd9bd0cb566f7c7fc23e4c53726627fc3d2",
- "B": "c8d085e5ea92fb4086caf99c27ba68d0cf075531f9a45527e49667558d9d79ff",
- "E": "744953855c767494d6f4fdc48e852a54027e2b7aa6c6552c217dd98b152f6395",
- "S": "4ba56d82ab4fd7f34eb58be3e3b1b23c06270f1d4d51d4662742b37700a70a06",
- "L": "3e13bc076f821b97aaabb9b5a65fa5ef7a1c7e200009d2fa11f17a1858d0a52f",
- "T": "2d01dec8512cdd6e880c25053de5f807ed48ebf831de4235754d825b0d1494a5",
- "U": "54bf98385efdb40d39827c52d2f4e6d4df8dc0938655a7b0a57cace7986e895d"
+ "A": "98805901e0372ed6d0a40b6713fefc8287e8d1db602e019f2ed5351409d9706d",
+ "B": "26cc836888ad8d992f6a9147d708fe9a8f2d65fe86004730d12592c7b8b040ef",
+ "E": "1461d3a0ab285ff20abb1f57feab8d5177f48f7886ec7b40295daebb028f3585",
+ "S": "7a576ef122d172a58e5fe6dd5d99420b0ba1c484e3f3c4b7c68f1b61e62c0743",
+ "L": "0886d359c3d6d968e013364166ff8a99c19cbf8cf31682cac557033206616515",
+ "T": "82620066f763e041c98582a702a9c96862acb2ff1e8ddc41453d7de181649109",
+ "U": "b6808109110b2f095dff929e6f70ffb212ed541bea0e9c502393b77354892e06"
},
{
"TEST": 1,
- "A": "931f39d36bfc27283f5b3d791ad3f6df1c55f144fa2b52bd443fc4eb24f26281",
- "B": "b6fdb0f8402d57e166816f281b48c2b5a5c04d6c4ab52be80620feb98118957e",
- "E": "9675ad591af467de8c64a39b438c213d86e5bbba431bb3880c186b4e8282a672",
- "S": "b6683ed0c7f7bb9b53250bb5cbdaf15aa84673d44c011f970b27c4dedc79a7c3",
- "L": "6450fb92cefca0594fe5e37a2fab9eed46fcd44eaee464adf1237b8c3f9855ec",
- "T": "30e4a42f280a7a135654a4af59a445ce09ed5683b7404d575bccf9d7a2c8c760",
- "U": "db60d0b8ba2d3ba0b884774259b8fc40e92595b01ffbc0aa36ee63e3126b194f"
+ "A": "0cb56a12df35413544e656003152984ef3ca4dcdc0521eaf8c64e6bc6c1e64f4",
+ "B": "f0d0b41a157ce4fbb7d1489a35a9292a9613d04a762b4a2877fc00e65e8403ca",
+ "E": "0fd895b69a81143a766bc083b0b2438a056db9c7eaba689bf3eef1a27289a957",
+ "S": "4ca7684fe26ab68f8add3d5c7ffd93cabe7d1a40d6ac7275289c14e949f783cb",
+ "L": "f3183da05f4eacd598ecfee13aafab0a66c4e8305fcdd6a125551b28421e4a18",
+ "T": "9a80b742ac91e1dfabdacc7beda876630da20fdfa68371594f0fc91767f97ef5",
+ "U": "09bd1bcc47053e8eaa41e620e0afcacbeffe9204b94b7adc4ea672791feaeae4"
},
{
"TEST": 2,
- "A": "f65387fd820997e523d1099ff99727dde285bac05a0cd9e63fb75e28284df79d",
- "B": "94d0c8ba02ebde9f728d1fffd0ec743db34192366c42a9063580ea971d8d8d4b",
- "E": "37ce44b6fcd5617c4470e9a83cdb9c2a5057eb71bdf656de4ad1a50cee70334c",
- "S": "626e6215eae0f7f304af9abeac0d5267d9c83cbb9ed0beacb0090faaf0fc18eb",
- "L": "0da04fe6194cc495ccb9d43225f0b29d7ef322665d37347c441b1a054f4a60b4",
- "T": "3e0ff7c4fddb1f58933cf1d5ba9388ff2a6d0e4be347c59bf2be18457c7ab5e7",
- "U": "71ee5b78721471d2ac47073eb92d979477208b44a16e8425293902e134c41d34"
+ "A": "2470fd1f08b27218902e84f7831b145a3397feea9063bb6dbc1dc58043793d36",
+ "B": "aac9c4169145697d2be942b35b477d8f5e05d3380bf4a477b155a0b5b1cdca04",
+ "E": "557b85666a49026cf91b4f1131378a1e6b95bc9bbdc73a7dcd305ccc40005af7",
+ "S": "9f43938ac39a90d371ce160f091ec669b972f8406ca38cde8f14c17461e2294f",
+ "L": "38709c38e13a8d52051f5ddf14266c4179abaf37ef553bdf4871e343e51bcef7",
+ "T": "1e7ab0926591ea57389515a97932c5195f467a65154f1814b8c63990fe5c80d7",
+ "U": "ff9a8a42430a35c1a667887a9cad3241f244e8823884ceb27cb576019fd8b09b"
},
{
"TEST": 3,
- "A": "0e3cebfb2e5ef09c85305b6d400b35ed581729ecac51782cdb8908043d6bf4af",
- "B": "192db7270206618045a6a83cc26babc89eb0f68946bec5b8b99d71a70f391505",
- "E": "b1568c9ef268cb8eca2f95a6b9bfa4fe90f65c368a44fbf105305263cf99b396",
- "S": "57339ac50d52d6778fcd5787c5578d454c31d285d98e53e60dbfaee5eb22b5de",
- "L": "6bffa4f19113e216da05bd988cde2fbbb1553f2f32b03893dad8569f61da8e59",
- "T": "60c391d164811208e890f9b1b596b948b423ceca295a2f5e2bc3066dab605051",
- "U": "a410308bf97a4b2db7f809bdd7193a91191dfdbd7dc20e9d60ffa91602f2ad02"
+ "A": "c5a4d6df2f2764c9218a8e83725f2d7ff489135f7b2ea0f83b06ed307d189540",
+ "B": "ed016425bbb01beca9566bbf781774a5599ec9dcbf85f3e1a10698aaba5a5861",
+ "E": "d046ffb08dcf4e6252943b222d5197bb82b6e564fce6bd772bb27a8e3e5944bb",
+ "S": "cac09fc7c620c462f53d1793aec83182405ffa71f89e6e26a6fb461ad7bf90ac",
+ "L": "53c088a61f158eff3bd18592e595ed15474b1ac60c12fd84f5e4c59a07ccdc3c",
+ "T": "26452cf9fa404db00ae243e45d5a9902a8e11bb4f6025904b04e58bf0b3f513d",
+ "U": "3643906e09efca1b1edfbbe9dd10c3d9aacbadfffba6f3bd539bdfc79fb11f62"
},
{
"TEST": 4,
- "A": "a6720ad0cd437e1fad7b6cb831748de9a4c113d7a4407ac48d1c1c649a32cfa7",
- "B": "b7001f7b29784a455a9de707f496498e776af6cace3281a5d6dc877c3b960feb",
- "E": "de8bd108f9ece11b75fb01241477fb361609105d9874696121c678ceb39dbca1",
- "S": "f03a58d3248464d8a1d77e3107151f69ea0a3217238305e43208adb296d27deb",
- "L": "5ce20cf65990bf869cb82b4d1b8a7a3dea605340419e86968d31266ad7ceb7cb",
- "T": "b7f424831ddbe2061f78e9c505748f30c719d0c813932a957bd62f98dd35bfe4",
- "U": "6f10117963601ad31ef4c6ad7baf3753e4febd6b64e7772d741d5db2d7cdcd18"
+ "A": "2c3cc0f8606707858227db376e49d0539b35bb9a13e09394feda22125802d2fd",
+ "B": "b20fd6417866c586ecbafcd3f3893baedd81897091beca86d6420eaf10d87931",
+ "E": "7c9d86a12b86d6fb2f17f528fa37832f85668dc967e7730e2a5299d59faf60f4",
+ "S": "e73f8faf79981194c4ee0f1eadbd942d6e9297a6f7f2aa48ca384564392f6ef1",
+ "L": "4ce5e76bb95c0930d3fd86dde66b60f6810af5e27d7af9084ab2c1163dd292e5",
+ "T": "ea39d54be9c92890cfb7ee8aba9b6403301dd69df490c29c0ef4a98fde987309",
+ "U": "f8f44f48ab719fa71612f39c74416bcd9dad664c1be35f8b68c39519de49275d"
},
{
"TEST": 5,
- "A": "e064c90e03b7774ecea6f0c5633d9dd98fc6f8416d7baf39cf83df372bbd1a8f",
- "B": "b89bf2b48410d26cd0b2450bc384bde59caecd03d1b534b9dee14c4ffb718cc0",
- "E": "4a12fe6e64639407ad01860b3cdc10e69dc7d6b319a2160abcac5b4cf1a609f9",
- "S": "892a19776ba393756e325ae26eb1be8d058d1978b0cb20dfbbd6f1f514fbdccb",
- "L": "06584dc2fbcb24bd8dcefa2ecb75468ca3ee594cafb7e65223fdb49357e7e2f0",
- "T": "722402d368c0818577f357aad04d9195ea80e0b013d164f89cf7f3c8f2761f14",
- "U": "778d3d0e10ea34e5379297027c1e5f9a0470f126cd19f6bfc21e881652563b5e"
+ "A": "c3df2d0f74fe039e5fbddf583555399f0ab564034eaa5eaa871e734021f77689",
+ "B": "d30ec4e0969fa9cf0dd1c61b725e5b5faac8c96e12f5bfc8ac441180a85357c1",
+ "E": "67bd9cd0b2e0695346b66d07053f26ba60022473f986ab4956b0c20ca5eeb7d4",
+ "S": "e86b00ec424317d9e6c983682b76e0589149c2be2de586515ccb403bb61613ea",
+ "L": "6345b6f3ec1ec358e700f8d19a0dfde21a4a91cc262a1f4673b451c72539a294",
+ "T": "85148b51e33264a188b79df3cac87e78041047e2300678d0d8984ec2af8043ff",
+ "U": "096147a069b0d63da7a85d68047a827cec23c3da65d590345291cbe491e769c3"
},
{
"TEST": 6,
- "A": "1cb8713e7dba86e70d446668d75bc9c992e6c10c9f6ed108ff0006a6d1b0937b",
- "B": "f5cca22f672064914108a628be72e54380471853c91cd92904973944d3671631",
- "E": "f54feab6fc6679e536521834a395893c4dcbb9f5cbd79dc6a9b54661eebb3166",
- "S": "b69c37cc0963f8619645e9bf2f949ef829aace7604835f08579ecff67049782a",
- "L": "e3f71b7a4f66283eab2cc81ae718723105ac4284f668271d53a5053bcb86f449",
- "T": "03fec2defb4cb0037aa1fe3e98062b7d3265e6fe6b96257e961203daa7bb20ab",
- "U": "b9710f2a2824a140aa970cf2aff3d898c9fe0e69352e5ceee4281549bade7ffe"
+ "A": "7f65618bf4531471c0b419bde1c06dcf7f20064fc65a97510658fe81db7eba0b",
+ "B": "1a141938c4c0e7e3ad4f648be35ab96f39b9329129556d8f549e1995d0af503e",
+ "E": "2449978fa5cca2b27e17085429f9071d5d8bbe3f8f53df285eee5f6cc5efe1e5",
+ "S": "f4e7cccc8bf490e705720a33776fab2ec700010dd971b8430abba2cdb77d48e7",
+ "L": "e58b630fc1350574468489f76a6c5fe3298a6174343a261c9af87bdbfe79dd80",
+ "T": "dd0d19687a3ce16fd50720f3f06971089ca91ea50c22d489bcf2c1cdfce6a83c",
+ "U": "dba67e6ef893225ec8a86ffe4f5fba51820117efd25dbbe1dadcd8f9dffe1174"
},
{
"TEST": 7,
- "A": "38c3298372a795c04c9bf3490d01f6f366bf3ac64c6a5c921581be6fb8263922",
- "B": "eb922d0b0694a1e7973742dbff6bfc65cf29cfdf50d22cb7304dc060292adea2",
- "E": "bf22c8d94b8b6005b6790ff357647e61b3cb853994f358e4fca9ddc9e191232b",
- "S": "692622cb87e36d76b72f5726cc47877cbdd20e5f09ed37a69f9e3483432f8832",
- "L": "35459a922c7dee62d1bd2cc240d5ced07bb978f7e2519f93cc5c8f24985593d1",
- "T": "4075007fe3a002a59f723027738a37b90dfe8237dc92588769e3e8bae191ec28",
- "U": "67caf11bef014d06b9f4467c8b520af8ef9cce399be37997d37f34f1e5cfe367"
+ "A": "c712cd92b407de5731a351dfb230b1ae0f65f99184ff97d7e7dbd3d9921ffd1e",
+ "B": "08e02f9c632d3fd1f48bdddcfdaca3588b168f0b6ff4cbaee99356d23d1e355a",
+ "E": "e0eb9c89aa93820c6a81431ca3c3e2d33088f1d0c1bddea749bb91a252425145",
+ "S": "c212f5fe66de61ebf95c0e0797bea72fcf10bb5f4aa903085aef685e35f68220",
+ "L": "234d8df29b1ee7f841b6d74a9bb8139d379df056716187225acc45fcc7d364f3",
+ "T": "3e82ff64fde662cec1730ca59d759c22f191326dbbbeaf09fa2c01a9184782ab",
+ "U": "51e0c8ba1580270fd2b69b37cdde5d28ed42c4de9d69c8676b1863879082bfed"
},
{
"TEST": 8,
- "A": "45776a977fbb24669f0f5b14d7acbead19b1f23e67d8355156e4d2ad835b3ecb",
- "B": "e30e8c0c7b4ada29ae217d87a7ce3a645354b6fa6585650e7e749f6b3c6a8cd6",
- "E": "be816305456e6074737eb32e141a1cef89003ed5448d013a43f890ffa7d9eeb6",
- "S": "b8bea737a5195af618cbc05f7d0af60df5f2f20805074e4b0b16f086134a0d2c",
- "L": "f7ba14eafb15ee44511b0b7fc8f77cc2b0c3a4f7ec77f71286c022eb7ecc284c",
- "T": "0c0c3e3cd44061869ccca4a6b9c449a2b46dbf2e73174822d9b2899cda6349a2",
- "U": "787c5a03a3b443ee3fa7ff3ff90983b15fbd225b91dad900c2e115f9802c43f7"
+ "A": "8c445e5b7ded4cbe35c3ee3f7099c8e934f91af1c40769f8393e41accf99b0e0",
+ "B": "4a1e2a5cf808072ea5c16e1fb30c50937917bcd820d2ca6b576d46ec3921ae9a",
+ "E": "edf5287bd261774cb5bb598cb3cf2a0fceae399bd11052ae3d49981f7eb208e4",
+ "S": "a810da8072d0d8a25d80804a4b42aa271266bfdd9d5a381d16159ca68c99364b",
+ "L": "31029b181072637a6f1c37e78f43a027c5914a9d3e6490ee44a6556e5aa78479",
+ "T": "74929c82affb7002b6498f8eb4fa4a3f3c885555a76ad123ebe509b3e0563095",
+ "U": "eaf7f0aa49345ea20bcf7a0b6455d7ee93a22250578f685a4a47a2a1e00708e3"
},
{
"TEST": 9,
- "A": "a2dad6ce28cf198caa48eaddcdbd925452ece6cad4107559356a055a0fe24893",
- "B": "ecc961fbe43346c86b5d4d39df3dcef0d10b7705e82b6efc150a0af912ee2b6d",
- "E": "789ab333343a7d16cbc282cb8e4e19782443f31c1d49282d7a39229a85a83d38",
- "S": "630f2d213eb0eb0f7bbe51999b55f6e66483e84c3658122b54bc5eec79885df6",
- "L": "49f0f6e0465c04217d317516c0c1b844c96c113adcd4d48144ea83e2389c0d0d",
- "T": "55a5b26fa437690e5cedb136b26d248459ee49801b7ae1423d12be5e6e28dc23",
- "U": "59cf48a53168290f13e8df8ca62f45e2fbb9172e9b9161c95894d5ceef2300ab"
+ "A": "0ee46716e7ff3dd305539228c6b43eaa5e4b62eeff4774040f58e4a525dc3507",
+ "B": "9f89f7464b6d8b6696b993fd8d9d67e340a00ce74d20d451ef12f480cdb586e1",
+ "E": "fe5401db00e97272706a38f44a9e1242842124fb8961b5ee3c1d9c15224755e4",
+ "S": "5c4b0eb387613f0051b3d015470b82f0ad4cb2ae6b8ddf509f43098cd001b025",
+ "L": "3d1e96f31d07cd0ee32e5f427e8649509792443cee564ab9ad271277b14ed16d",
+ "T": "c3c448911a041b09b90f2e70c32f0a46e4c8051f243048473f9f9fc705b89b0e",
+ "U": "ef6ba05a3654d955ab2d5ce2331e1eaac4d6610d89b397deceb87377d15609c2"
}
]
\ No newline at end of file
diff --git a/testVectors/schnorr/dprove.txt b/testVectors/schnorr/dprove.txt
index fca06d2..2d03af3 100644
--- a/testVectors/schnorr/dprove.txt
+++ b/testVectors/schnorr/dprove.txt
@@ -1,90 +1,90 @@
TEST = 0,
-A = c3658c336985e9415ac8395a5a97dcd9bd0cb566f7c7fc23e4c53726627fc3d2,
-B = c8d085e5ea92fb4086caf99c27ba68d0cf075531f9a45527e49667558d9d79ff,
-E = 744953855c767494d6f4fdc48e852a54027e2b7aa6c6552c217dd98b152f6395,
-S = 4ba56d82ab4fd7f34eb58be3e3b1b23c06270f1d4d51d4662742b37700a70a06,
-L = 3e13bc076f821b97aaabb9b5a65fa5ef7a1c7e200009d2fa11f17a1858d0a52f,
-T = 2d01dec8512cdd6e880c25053de5f807ed48ebf831de4235754d825b0d1494a5,
-U = 54bf98385efdb40d39827c52d2f4e6d4df8dc0938655a7b0a57cace7986e895d,
+A = 98805901e0372ed6d0a40b6713fefc8287e8d1db602e019f2ed5351409d9706d,
+B = 26cc836888ad8d992f6a9147d708fe9a8f2d65fe86004730d12592c7b8b040ef,
+E = 1461d3a0ab285ff20abb1f57feab8d5177f48f7886ec7b40295daebb028f3585,
+S = 7a576ef122d172a58e5fe6dd5d99420b0ba1c484e3f3c4b7c68f1b61e62c0743,
+L = 0886d359c3d6d968e013364166ff8a99c19cbf8cf31682cac557033206616515,
+T = 82620066f763e041c98582a702a9c96862acb2ff1e8ddc41453d7de181649109,
+U = b6808109110b2f095dff929e6f70ffb212ed541bea0e9c502393b77354892e06,
TEST = 1,
-A = 931f39d36bfc27283f5b3d791ad3f6df1c55f144fa2b52bd443fc4eb24f26281,
-B = b6fdb0f8402d57e166816f281b48c2b5a5c04d6c4ab52be80620feb98118957e,
-E = 9675ad591af467de8c64a39b438c213d86e5bbba431bb3880c186b4e8282a672,
-S = b6683ed0c7f7bb9b53250bb5cbdaf15aa84673d44c011f970b27c4dedc79a7c3,
-L = 6450fb92cefca0594fe5e37a2fab9eed46fcd44eaee464adf1237b8c3f9855ec,
-T = 30e4a42f280a7a135654a4af59a445ce09ed5683b7404d575bccf9d7a2c8c760,
-U = db60d0b8ba2d3ba0b884774259b8fc40e92595b01ffbc0aa36ee63e3126b194f,
+A = 0cb56a12df35413544e656003152984ef3ca4dcdc0521eaf8c64e6bc6c1e64f4,
+B = f0d0b41a157ce4fbb7d1489a35a9292a9613d04a762b4a2877fc00e65e8403ca,
+E = 0fd895b69a81143a766bc083b0b2438a056db9c7eaba689bf3eef1a27289a957,
+S = 4ca7684fe26ab68f8add3d5c7ffd93cabe7d1a40d6ac7275289c14e949f783cb,
+L = f3183da05f4eacd598ecfee13aafab0a66c4e8305fcdd6a125551b28421e4a18,
+T = 9a80b742ac91e1dfabdacc7beda876630da20fdfa68371594f0fc91767f97ef5,
+U = 09bd1bcc47053e8eaa41e620e0afcacbeffe9204b94b7adc4ea672791feaeae4,
TEST = 2,
-A = f65387fd820997e523d1099ff99727dde285bac05a0cd9e63fb75e28284df79d,
-B = 94d0c8ba02ebde9f728d1fffd0ec743db34192366c42a9063580ea971d8d8d4b,
-E = 37ce44b6fcd5617c4470e9a83cdb9c2a5057eb71bdf656de4ad1a50cee70334c,
-S = 626e6215eae0f7f304af9abeac0d5267d9c83cbb9ed0beacb0090faaf0fc18eb,
-L = 0da04fe6194cc495ccb9d43225f0b29d7ef322665d37347c441b1a054f4a60b4,
-T = 3e0ff7c4fddb1f58933cf1d5ba9388ff2a6d0e4be347c59bf2be18457c7ab5e7,
-U = 71ee5b78721471d2ac47073eb92d979477208b44a16e8425293902e134c41d34,
+A = 2470fd1f08b27218902e84f7831b145a3397feea9063bb6dbc1dc58043793d36,
+B = aac9c4169145697d2be942b35b477d8f5e05d3380bf4a477b155a0b5b1cdca04,
+E = 557b85666a49026cf91b4f1131378a1e6b95bc9bbdc73a7dcd305ccc40005af7,
+S = 9f43938ac39a90d371ce160f091ec669b972f8406ca38cde8f14c17461e2294f,
+L = 38709c38e13a8d52051f5ddf14266c4179abaf37ef553bdf4871e343e51bcef7,
+T = 1e7ab0926591ea57389515a97932c5195f467a65154f1814b8c63990fe5c80d7,
+U = ff9a8a42430a35c1a667887a9cad3241f244e8823884ceb27cb576019fd8b09b,
TEST = 3,
-A = 0e3cebfb2e5ef09c85305b6d400b35ed581729ecac51782cdb8908043d6bf4af,
-B = 192db7270206618045a6a83cc26babc89eb0f68946bec5b8b99d71a70f391505,
-E = b1568c9ef268cb8eca2f95a6b9bfa4fe90f65c368a44fbf105305263cf99b396,
-S = 57339ac50d52d6778fcd5787c5578d454c31d285d98e53e60dbfaee5eb22b5de,
-L = 6bffa4f19113e216da05bd988cde2fbbb1553f2f32b03893dad8569f61da8e59,
-T = 60c391d164811208e890f9b1b596b948b423ceca295a2f5e2bc3066dab605051,
-U = a410308bf97a4b2db7f809bdd7193a91191dfdbd7dc20e9d60ffa91602f2ad02,
+A = c5a4d6df2f2764c9218a8e83725f2d7ff489135f7b2ea0f83b06ed307d189540,
+B = ed016425bbb01beca9566bbf781774a5599ec9dcbf85f3e1a10698aaba5a5861,
+E = d046ffb08dcf4e6252943b222d5197bb82b6e564fce6bd772bb27a8e3e5944bb,
+S = cac09fc7c620c462f53d1793aec83182405ffa71f89e6e26a6fb461ad7bf90ac,
+L = 53c088a61f158eff3bd18592e595ed15474b1ac60c12fd84f5e4c59a07ccdc3c,
+T = 26452cf9fa404db00ae243e45d5a9902a8e11bb4f6025904b04e58bf0b3f513d,
+U = 3643906e09efca1b1edfbbe9dd10c3d9aacbadfffba6f3bd539bdfc79fb11f62,
TEST = 4,
-A = a6720ad0cd437e1fad7b6cb831748de9a4c113d7a4407ac48d1c1c649a32cfa7,
-B = b7001f7b29784a455a9de707f496498e776af6cace3281a5d6dc877c3b960feb,
-E = de8bd108f9ece11b75fb01241477fb361609105d9874696121c678ceb39dbca1,
-S = f03a58d3248464d8a1d77e3107151f69ea0a3217238305e43208adb296d27deb,
-L = 5ce20cf65990bf869cb82b4d1b8a7a3dea605340419e86968d31266ad7ceb7cb,
-T = b7f424831ddbe2061f78e9c505748f30c719d0c813932a957bd62f98dd35bfe4,
-U = 6f10117963601ad31ef4c6ad7baf3753e4febd6b64e7772d741d5db2d7cdcd18,
+A = 2c3cc0f8606707858227db376e49d0539b35bb9a13e09394feda22125802d2fd,
+B = b20fd6417866c586ecbafcd3f3893baedd81897091beca86d6420eaf10d87931,
+E = 7c9d86a12b86d6fb2f17f528fa37832f85668dc967e7730e2a5299d59faf60f4,
+S = e73f8faf79981194c4ee0f1eadbd942d6e9297a6f7f2aa48ca384564392f6ef1,
+L = 4ce5e76bb95c0930d3fd86dde66b60f6810af5e27d7af9084ab2c1163dd292e5,
+T = ea39d54be9c92890cfb7ee8aba9b6403301dd69df490c29c0ef4a98fde987309,
+U = f8f44f48ab719fa71612f39c74416bcd9dad664c1be35f8b68c39519de49275d,
TEST = 5,
-A = e064c90e03b7774ecea6f0c5633d9dd98fc6f8416d7baf39cf83df372bbd1a8f,
-B = b89bf2b48410d26cd0b2450bc384bde59caecd03d1b534b9dee14c4ffb718cc0,
-E = 4a12fe6e64639407ad01860b3cdc10e69dc7d6b319a2160abcac5b4cf1a609f9,
-S = 892a19776ba393756e325ae26eb1be8d058d1978b0cb20dfbbd6f1f514fbdccb,
-L = 06584dc2fbcb24bd8dcefa2ecb75468ca3ee594cafb7e65223fdb49357e7e2f0,
-T = 722402d368c0818577f357aad04d9195ea80e0b013d164f89cf7f3c8f2761f14,
-U = 778d3d0e10ea34e5379297027c1e5f9a0470f126cd19f6bfc21e881652563b5e,
+A = c3df2d0f74fe039e5fbddf583555399f0ab564034eaa5eaa871e734021f77689,
+B = d30ec4e0969fa9cf0dd1c61b725e5b5faac8c96e12f5bfc8ac441180a85357c1,
+E = 67bd9cd0b2e0695346b66d07053f26ba60022473f986ab4956b0c20ca5eeb7d4,
+S = e86b00ec424317d9e6c983682b76e0589149c2be2de586515ccb403bb61613ea,
+L = 6345b6f3ec1ec358e700f8d19a0dfde21a4a91cc262a1f4673b451c72539a294,
+T = 85148b51e33264a188b79df3cac87e78041047e2300678d0d8984ec2af8043ff,
+U = 096147a069b0d63da7a85d68047a827cec23c3da65d590345291cbe491e769c3,
TEST = 6,
-A = 1cb8713e7dba86e70d446668d75bc9c992e6c10c9f6ed108ff0006a6d1b0937b,
-B = f5cca22f672064914108a628be72e54380471853c91cd92904973944d3671631,
-E = f54feab6fc6679e536521834a395893c4dcbb9f5cbd79dc6a9b54661eebb3166,
-S = b69c37cc0963f8619645e9bf2f949ef829aace7604835f08579ecff67049782a,
-L = e3f71b7a4f66283eab2cc81ae718723105ac4284f668271d53a5053bcb86f449,
-T = 03fec2defb4cb0037aa1fe3e98062b7d3265e6fe6b96257e961203daa7bb20ab,
-U = b9710f2a2824a140aa970cf2aff3d898c9fe0e69352e5ceee4281549bade7ffe,
+A = 7f65618bf4531471c0b419bde1c06dcf7f20064fc65a97510658fe81db7eba0b,
+B = 1a141938c4c0e7e3ad4f648be35ab96f39b9329129556d8f549e1995d0af503e,
+E = 2449978fa5cca2b27e17085429f9071d5d8bbe3f8f53df285eee5f6cc5efe1e5,
+S = f4e7cccc8bf490e705720a33776fab2ec700010dd971b8430abba2cdb77d48e7,
+L = e58b630fc1350574468489f76a6c5fe3298a6174343a261c9af87bdbfe79dd80,
+T = dd0d19687a3ce16fd50720f3f06971089ca91ea50c22d489bcf2c1cdfce6a83c,
+U = dba67e6ef893225ec8a86ffe4f5fba51820117efd25dbbe1dadcd8f9dffe1174,
TEST = 7,
-A = 38c3298372a795c04c9bf3490d01f6f366bf3ac64c6a5c921581be6fb8263922,
-B = eb922d0b0694a1e7973742dbff6bfc65cf29cfdf50d22cb7304dc060292adea2,
-E = bf22c8d94b8b6005b6790ff357647e61b3cb853994f358e4fca9ddc9e191232b,
-S = 692622cb87e36d76b72f5726cc47877cbdd20e5f09ed37a69f9e3483432f8832,
-L = 35459a922c7dee62d1bd2cc240d5ced07bb978f7e2519f93cc5c8f24985593d1,
-T = 4075007fe3a002a59f723027738a37b90dfe8237dc92588769e3e8bae191ec28,
-U = 67caf11bef014d06b9f4467c8b520af8ef9cce399be37997d37f34f1e5cfe367,
+A = c712cd92b407de5731a351dfb230b1ae0f65f99184ff97d7e7dbd3d9921ffd1e,
+B = 08e02f9c632d3fd1f48bdddcfdaca3588b168f0b6ff4cbaee99356d23d1e355a,
+E = e0eb9c89aa93820c6a81431ca3c3e2d33088f1d0c1bddea749bb91a252425145,
+S = c212f5fe66de61ebf95c0e0797bea72fcf10bb5f4aa903085aef685e35f68220,
+L = 234d8df29b1ee7f841b6d74a9bb8139d379df056716187225acc45fcc7d364f3,
+T = 3e82ff64fde662cec1730ca59d759c22f191326dbbbeaf09fa2c01a9184782ab,
+U = 51e0c8ba1580270fd2b69b37cdde5d28ed42c4de9d69c8676b1863879082bfed,
TEST = 8,
-A = 45776a977fbb24669f0f5b14d7acbead19b1f23e67d8355156e4d2ad835b3ecb,
-B = e30e8c0c7b4ada29ae217d87a7ce3a645354b6fa6585650e7e749f6b3c6a8cd6,
-E = be816305456e6074737eb32e141a1cef89003ed5448d013a43f890ffa7d9eeb6,
-S = b8bea737a5195af618cbc05f7d0af60df5f2f20805074e4b0b16f086134a0d2c,
-L = f7ba14eafb15ee44511b0b7fc8f77cc2b0c3a4f7ec77f71286c022eb7ecc284c,
-T = 0c0c3e3cd44061869ccca4a6b9c449a2b46dbf2e73174822d9b2899cda6349a2,
-U = 787c5a03a3b443ee3fa7ff3ff90983b15fbd225b91dad900c2e115f9802c43f7,
+A = 8c445e5b7ded4cbe35c3ee3f7099c8e934f91af1c40769f8393e41accf99b0e0,
+B = 4a1e2a5cf808072ea5c16e1fb30c50937917bcd820d2ca6b576d46ec3921ae9a,
+E = edf5287bd261774cb5bb598cb3cf2a0fceae399bd11052ae3d49981f7eb208e4,
+S = a810da8072d0d8a25d80804a4b42aa271266bfdd9d5a381d16159ca68c99364b,
+L = 31029b181072637a6f1c37e78f43a027c5914a9d3e6490ee44a6556e5aa78479,
+T = 74929c82affb7002b6498f8eb4fa4a3f3c885555a76ad123ebe509b3e0563095,
+U = eaf7f0aa49345ea20bcf7a0b6455d7ee93a22250578f685a4a47a2a1e00708e3,
TEST = 9,
-A = a2dad6ce28cf198caa48eaddcdbd925452ece6cad4107559356a055a0fe24893,
-B = ecc961fbe43346c86b5d4d39df3dcef0d10b7705e82b6efc150a0af912ee2b6d,
-E = 789ab333343a7d16cbc282cb8e4e19782443f31c1d49282d7a39229a85a83d38,
-S = 630f2d213eb0eb0f7bbe51999b55f6e66483e84c3658122b54bc5eec79885df6,
-L = 49f0f6e0465c04217d317516c0c1b844c96c113adcd4d48144ea83e2389c0d0d,
-T = 55a5b26fa437690e5cedb136b26d248459ee49801b7ae1423d12be5e6e28dc23,
-U = 59cf48a53168290f13e8df8ca62f45e2fbb9172e9b9161c95894d5ceef2300ab,
+A = 0ee46716e7ff3dd305539228c6b43eaa5e4b62eeff4774040f58e4a525dc3507,
+B = 9f89f7464b6d8b6696b993fd8d9d67e340a00ce74d20d451ef12f480cdb586e1,
+E = fe5401db00e97272706a38f44a9e1242842124fb8961b5ee3c1d9c15224755e4,
+S = 5c4b0eb387613f0051b3d015470b82f0ad4cb2ae6b8ddf509f43098cd001b025,
+L = 3d1e96f31d07cd0ee32e5f427e8649509792443cee564ab9ad271277b14ed16d,
+T = c3c448911a041b09b90f2e70c32f0a46e4c8051f243048473f9f9fc705b89b0e,
+U = ef6ba05a3654d955ab2d5ce2331e1eaac4d6610d89b397deceb87377d15609c2,
diff --git a/testVectors/schnorr/dverify.json b/testVectors/schnorr/dverify.json
index f0bfff8..86e9b88 100644
--- a/testVectors/schnorr/dverify.json
+++ b/testVectors/schnorr/dverify.json
@@ -1,92 +1,92 @@
[
{
"TEST": 0,
- "R": "0337f69333ec13ff263492807e1da7efccf880dda2d3e54062ebe1e56a4ac8114f",
- "V": "03da9f79c96ede4add43f6da69c13c24d441c418ccf9266a0794d4b60139b769f8",
- "C": "03be659529d5b0e5e895c98fe4a1615019a0ef506e8be65a844ea3e846e06ab06c",
- "E": "5d163667398926b52b47f8164fc92795a9cad7e43efe9f71b78fb6b9d623dc10",
- "T": "9b802924c454fa018f220d92c431e927a68bd861f3a823815b5bce9d59291f79",
- "U": "9825d990f6a0219cfe6cd8385ed3124f3d20211b8fc8a53440dbf565d6435e21"
+ "R": "020537773ffc3da376e2f3dabba54b84f3c865ad8acf3d77f72afaf20a5cb44e57",
+ "V": "033b69f8bdf508ca2bebe2518e177b20f12c4d8335f628b318160a5b4201ef93ad",
+ "C": "028053a7ddd2d195913e2e520b1b6be09d6f3dd3b3dcc7f5dad04ba2afc2307d90",
+ "E": "edebdfc8bda2088507f63a7dea84a2a2b704c97e42e48127f68dcea818325d8d",
+ "T": "d1d8e4894b8c5c7262d1aaba981a7a75d31e7bb269890d53116e70be0cdf99d9",
+ "U": "bb7b364ec9d428e273f5e71e689fe1ded08f9805416fb366894fec518b5ab9f8"
},
{
"TEST": 1,
- "R": "0310d9f650695d137ca05adec60b1b78445a40bf403e4f641fe38c2897aaa67769",
- "V": "02555ec03ecd2e1585b708a8fe7a1d514057e3152381de479281e083d783a7beb9",
- "C": "031072f0b4d488f0e8f93aae1957d5894f0dc3a98c1bc7bae8ea86fd8eb3222565",
- "E": "1a45745881d6a22056c4734b068b7d92877a51aead03432774347880f860aa65",
- "T": "52b37b5e9e38d8e26fc1b21fcafc63474cb6539134f9931145804bc925913032",
- "U": "e148e44602200a79114daa2458f09a8a6e372cf1af472eca05ff2c17f12b42a9"
+ "R": "02daa4bb8bfcdd6293e04b68686d3b05c06b195cc880062c2625e3007ea4cfe0c0",
+ "V": "029485b64dc10ac2d0ce3555c94975998af4d9c71d29fe5ae0649bcc7ffce5e7e6",
+ "C": "03874b1fae542def460a696815b5a903c5d37ff7adfc2baa49fb8b9433a25d1509",
+ "E": "587b8ccd7122bb35e02c94b2db3e23f1ee65bccdc8f9e71d034c89b94a090cb8",
+ "T": "b93f24de57b859db76a884313aa730ef18c63e2ca53ad6d2c7d90b337450c16d",
+ "U": "64cc0abb4245a5d37359a324324a7e9e64d115b39ea0a2f5b7d9ad6f210e5c3b"
},
{
"TEST": 2,
- "R": "03903e4bb60f886668c5cdfadd0ddd349cacc4879de7fe8b7fa43ba79a6cbe01b3",
- "V": "03ade35a1e50500a4bc8ed3fecb3f1aa2570a39499044c6282398f4dd071ed6c85",
- "C": "02cbd3a2714376e1f3cab63feb5e9d23b36135b4565e7d4b4a85afae0882baa4ed",
- "E": "450a269d202de9a6d2573b510bcc02f1e7c7d5b4a5779c55fbb4bd25241a1f9f",
- "T": "e96ce1c43cbe59f6f6946dea0ff1f3bc15227da9758308f48a53e4fc4c666249",
- "U": "a42aa5d5efceb63a480e8718d6e7930c3a156ba9ff971bae8538062305e502c7"
+ "R": "02913dc55b4d1e8e89d9e7c3e38702add012aae04a42439f9fe1d5d690d3255566",
+ "V": "023ec4892b5efe9e5db85104034a20b9cca6b7d7129f760b65ea19c33e6f4287a9",
+ "C": "03adab79913fc68007fe6db89ab64240edc864bc1a08dbea210492837707b53458",
+ "E": "d455924c96c02ec532e137a2b288aa04745ecb18cc1000a55613cdf412a46427",
+ "T": "97e10ec3f596284e1efdbb20dfc53593339e5aa9e3117ac3dc7e0087c0ffc831",
+ "U": "2425097f2bdedd1b7294e6c35a036e1968bf5ec0cee387b948f4afc6827566b4"
},
{
"TEST": 3,
- "R": "02ac3a849571574161e53aaf3cb9c8c323c3498e7d329f02d723a6b9b3a1848a67",
- "V": "025fbc82aa7b986a386ad2fa524f085a0e23dadd259a01e2dda66bf79d4fef9fb5",
- "C": "039436f7a6a41ef3e624090f34ac24331fc9b233d03430f263ac62e3b6555817ba",
- "E": "670dcf5cca02ce7bb776e48fd01f06119da99af75581ce715cca828e14627771",
- "T": "b4702324fa24b547850709fc0874809b638aa5e8ef10f8715100d116f5683702",
- "U": "f708022da7a842e68094699df0cd1124a7ae40d17a9bbb5788bf4fec85e9a1b8"
+ "R": "02cb97763b448ee16c0dbdcdef765e2ae257ec129fc7ef992b04850a51137ff5f5",
+ "V": "0211d00ede35b17508461d8d31323a86825bdd0b7458626a76a83705c0f95a5351",
+ "C": "03c4d0adc3e672fb70a9a0138b173d1d09ff23f9e4329035f5a7136c6fd9564849",
+ "E": "83c5149c51cf6a9c246a6b407b0c8dc7b47e99977b1deba413d88437aebe813c",
+ "T": "50ed725d57e38dbda89a2e87fe9cd72dad2434e5583243cb183cf611679e7972",
+ "U": "254066df913b9132a6534451968844058ab803f485642e686e30ac19c78d88f5"
},
{
"TEST": 4,
- "R": "0316ddced170deb5eee2121216c5a714e25ed0cbc5ef5646cc754234f778eb1c0b",
- "V": "03b5302ae8d3061ebeebd34ad3e74f4be7ff11b20d321716f10d4e0a409059b2fa",
- "C": "021e20bf1693d7515137d274938beb4faa5b6e5fa4fe81d2706cd1c9ad04c07a62",
- "E": "7d9690223a556bcbcd86d24b20d85a520199ae39299dfc4f1f1ee36ffeda24e3",
- "T": "d6bab7bb975b18d876909c797fd3c70ee4ab59168d0bdad29620c517e5af324b",
- "U": "a3a0e66ed30df31b1e3195c964a00e731939ea5ea2c9176fc6fdd39c0dde4701"
+ "R": "03c5c2ba8cf4e0ddd06803f2eab8426e7250467e8a521e6e4764f8ed50f99e8ead",
+ "V": "03dcb5f6ead7e81963ab4a3f1f5c6d77e4c079001343b7058e8bff7c5d84f5da4a",
+ "C": "036410928e258ce7800407f127141ae617f5e2e89864b66c1dfa72a401fb5fbb61",
+ "E": "ec74f330ac0ceea0d1c957fb01a07dccd1798d98d33b567b0c931dcc2c3e90ea",
+ "T": "dc77f3cc4b31c8677ef566fc182a8c32bd98188aaa5255062104019dfc3b09dc",
+ "U": "6774443dbc5ecc5bcaf4597f36ede169372611417c53b8445ca56cb92aafe852"
},
{
"TEST": 5,
- "R": "03d28743c72ab145876065f39a3105d9b0f55bb225ef797c0674e65bf85c3439c3",
- "V": "03708abbfa0a807e3540d8aa6c589c6993bcc0238986b317cfecbdc962fb459860",
- "C": "02804191a4f52d8cf6948596122d89c079e4f6212420a263e66a693c1da94c3223",
- "E": "ff5bfd05347b361da4d159a29dae99df2ecdf2eec94fd4ade894398d9c4bc239",
- "T": "4ca83780f3ab9e30e29c87c3cb6fa0eabb3e0f664d2c27a6bce05380c9ae92ae",
- "U": "4edeef14e75585e7fd197c719fd3948f1f420a724d5c3a95eb5bff0bb38681a6"
+ "R": "02d1ee046200382c654c90a02fcc1b025ac15b34d26cb864b7278e359d04779792",
+ "V": "02380955f1798a27cd14802b947ec8b4b57fa206ac44707d3bc0d4beb7e2b1db5e",
+ "C": "02aab91a349d395b360362ca157a005c2cf9feab3ea25a86e62ee6f6bb8948968a",
+ "E": "8e50b3197f779789bcb082d9be490863fd2b68b9357d951b222fc5724e2aedcd",
+ "T": "abc2b26aa50342df17c1adb5d600557d1460fa21360a386af8d4042b86ae87e6",
+ "U": "e9f3f4669b61ace1037c04b0273500cadd2bdac058d1f50fccec4b0b71893c74"
},
{
"TEST": 6,
- "R": "0375cd1b2c2de801df582927c5b7bb823d03544d818dc2b4ff754cdf3ef30c4c03",
- "V": "039fe1711cd9f775105caa6db9cdea37023fccd81d2c03a36141cc15a009e3ee58",
- "C": "03271d03e3c2105cd8dce4e17d7e76cb4174cd1631c8c2dcbdee5ef9d67312b2a4",
- "E": "56eec5122920560f0b88db05c7912d517f1ba492d1f21e9ab747e354df7e6665",
- "T": "f53dc9b0e3580638a7ea996318663d207c73495ebadf47e8061597cf7addb557",
- "U": "af3c5fa843e6bb582820c9f8a7a050f4162980c2aaf15952cb615ec0c86e53ab"
+ "R": "02bb995b6ef4415dac329d0f02aaebf248121e2cf844fce54d947b14e7b1c756c8",
+ "V": "03b4f1b72b07951c4db6ed445f1386fdd9859813b9bbcf3d59b78f2c41a1b0f417",
+ "C": "0258882ae61e1e8549cb4c2af92d479819c87bc02714106eabb1d1e8eaec36b26f",
+ "E": "70bb1893f91f520378838b35a240e65e3153d5b891ffafc7ecdd838c2042cbde",
+ "T": "88e8d7350400868a8d48f630868cbbc2ef97112696b985a3ad0c78d833a33625",
+ "U": "bc4471af39ffe173f59807badbe79ffc9548f6d8fcaa8ecdccf6c3f7797f82cb"
},
{
"TEST": 7,
- "R": "03a487f61837e87c747c2737172b962f79f90f3e485792db349390393c7bbec009",
- "V": "025c58b47fac4b2bc4556782fd0ff5d6f2761520b256150167144bfe1589531d2b",
- "C": "02de1aac64d96206096d82a9782d890593492c33b6fb2cd0eb3d5da13e37a0571e",
- "E": "608e104063ace2a703cdb85d79a9817f7732fada6cd2447af523df25083fe01c",
- "T": "36c6489ecae5ccb524d2f3166bcdfc71b77aac8cc25a61433cd1062e113103aa",
- "U": "b6dadf473f9e7a341848f0a6ea84962694afe9776cd5f45175d6902b64709e96"
+ "R": "038bb34386bc9c7f065136d04f1c62c936ddbe9874235b2b27e378cf7514e34e10",
+ "V": "03a02e15a584f591c5fc8f0b4c1408552433c8547225643eff5414afdbaec8abf2",
+ "C": "021d1064a0e59a75d7e0f8b08d958c6a7f25882dc838acee5a962300e1b02de047",
+ "E": "5623eeafec05f5a592647f78b351f8adca1d4d99aec7992fdc1db4c830a39366",
+ "T": "fea34fc356079b51b529bd6681ba0bd8d01f3417cce03944b21386ca9ddc7e3b",
+ "U": "74071f2a607cbc64255c8d64df7eb5cd31ab8a85d91d6497288c6339ca1fb526"
},
{
"TEST": 8,
- "R": "0345c3278b4d2e9fbb697b4a497bd41b068314b20a3556984286a348195e4bf87d",
- "V": "028c61a27347c094aa299e95dc648cfde1d0ab65ee48a70bbc1d2fddbb43cea989",
- "C": "0369298338f45f3e501e7f46d31ff4010425074b128e557bbc8ac5f80dbf764aa9",
- "E": "9f553102958aecaf0d00130c36f5bc7c42eaa2ace113853ede0001ae5164a07b",
- "T": "a0b325d9e5b895ceae62621c1cf29d9a2fc4498fd1fc9937a63c8f32446080cc",
- "U": "a552b6f899eba8c5c2fdc67d2e8f20420a79002b2a8ed545c1332b2b2675eeb7"
+ "R": "0390d1fe5c60463086f65d1b44dbdf65c001f4e532f763e45646765d06019960de",
+ "V": "03a603e43e1a98b839f6971eb0fe73c7a70130e0c27411fda59617c8365ac6cdf2",
+ "C": "02938dcf17c55d78aa6b871d38ae838ea56d38c321c470527340212c4ada21fbd5",
+ "E": "51902fda78bb40a1eb2099512ae3e4853f596f0be0e73f478a01f4fff9c48e4c",
+ "T": "8daf81313b9aa20c44bbe6daa070618b571ad03df23e390ae7ec2585f1205ffd",
+ "U": "a77503c8846192032f79f882ad9e8e21b7534553c2db6f0e988659c3675b5aa5"
},
{
"TEST": 9,
- "R": "02c9ce032faa136eb3ad72225300a592a620d5a9a9f90bf303fab853e29bb68276",
- "V": "02313802a1e8c0e23d830d0ddbc81f4b9bdf8636f79823a84ba57e3beb8d11c35d",
- "C": "026647a49f2daed3ff69d03c9638bea864f125485af059fe60d640f9e9a0685944",
- "E": "fb92fc530bb01d308afc30190ec261d4474346107f33809abe4bef288891e2cb",
- "T": "f1be16549e065da6bf96466c9330194e92f2dde14fffb883922c98e6361f19f8",
- "U": "e9a57b8486df4a58021fb1f57e3fb8ac5a30a73de5868d6542a196fbf3fc47fb"
+ "R": "025e534768bafa3171b850bcccbfad82702adc69d90f9db32debe7afe7fdd06f1c",
+ "V": "0229bc145f45468201a47c3e62785503d006fa9be41cd5892a65002a7aef0e79cd",
+ "C": "0248d59ed28567a329f442051fb7e91069a136e68751c52d5e592693295ecc0e81",
+ "E": "104b7d4a22cd1cee0d853f5b3d0e4e9a14e5156201b92b4860bcd8a07423e7b0",
+ "T": "b4a9bf92910036da6342cf59bb6b545e7faf8dd3affb4ff1223d1c1805de7884",
+ "U": "4e78b645d5dba4a43f1fd896f62ba089608c4410bb6478de9a2ca9323dd7b0dc"
}
]
\ No newline at end of file
diff --git a/testVectors/schnorr/dverify.txt b/testVectors/schnorr/dverify.txt
index 41b2438..235bf07 100644
--- a/testVectors/schnorr/dverify.txt
+++ b/testVectors/schnorr/dverify.txt
@@ -1,80 +1,80 @@
TEST = 0,
-R = 0337f69333ec13ff263492807e1da7efccf880dda2d3e54062ebe1e56a4ac8114f,
-V = 03da9f79c96ede4add43f6da69c13c24d441c418ccf9266a0794d4b60139b769f8,
-C = 03be659529d5b0e5e895c98fe4a1615019a0ef506e8be65a844ea3e846e06ab06c,
-E = 5d163667398926b52b47f8164fc92795a9cad7e43efe9f71b78fb6b9d623dc10,
-T = 9b802924c454fa018f220d92c431e927a68bd861f3a823815b5bce9d59291f79,
-U = 9825d990f6a0219cfe6cd8385ed3124f3d20211b8fc8a53440dbf565d6435e21,
+R = 020537773ffc3da376e2f3dabba54b84f3c865ad8acf3d77f72afaf20a5cb44e57,
+V = 033b69f8bdf508ca2bebe2518e177b20f12c4d8335f628b318160a5b4201ef93ad,
+C = 028053a7ddd2d195913e2e520b1b6be09d6f3dd3b3dcc7f5dad04ba2afc2307d90,
+E = edebdfc8bda2088507f63a7dea84a2a2b704c97e42e48127f68dcea818325d8d,
+T = d1d8e4894b8c5c7262d1aaba981a7a75d31e7bb269890d53116e70be0cdf99d9,
+U = bb7b364ec9d428e273f5e71e689fe1ded08f9805416fb366894fec518b5ab9f8,
TEST = 1,
-R = 0310d9f650695d137ca05adec60b1b78445a40bf403e4f641fe38c2897aaa67769,
-V = 02555ec03ecd2e1585b708a8fe7a1d514057e3152381de479281e083d783a7beb9,
-C = 031072f0b4d488f0e8f93aae1957d5894f0dc3a98c1bc7bae8ea86fd8eb3222565,
-E = 1a45745881d6a22056c4734b068b7d92877a51aead03432774347880f860aa65,
-T = 52b37b5e9e38d8e26fc1b21fcafc63474cb6539134f9931145804bc925913032,
-U = e148e44602200a79114daa2458f09a8a6e372cf1af472eca05ff2c17f12b42a9,
+R = 02daa4bb8bfcdd6293e04b68686d3b05c06b195cc880062c2625e3007ea4cfe0c0,
+V = 029485b64dc10ac2d0ce3555c94975998af4d9c71d29fe5ae0649bcc7ffce5e7e6,
+C = 03874b1fae542def460a696815b5a903c5d37ff7adfc2baa49fb8b9433a25d1509,
+E = 587b8ccd7122bb35e02c94b2db3e23f1ee65bccdc8f9e71d034c89b94a090cb8,
+T = b93f24de57b859db76a884313aa730ef18c63e2ca53ad6d2c7d90b337450c16d,
+U = 64cc0abb4245a5d37359a324324a7e9e64d115b39ea0a2f5b7d9ad6f210e5c3b,
TEST = 2,
-R = 03903e4bb60f886668c5cdfadd0ddd349cacc4879de7fe8b7fa43ba79a6cbe01b3,
-V = 03ade35a1e50500a4bc8ed3fecb3f1aa2570a39499044c6282398f4dd071ed6c85,
-C = 02cbd3a2714376e1f3cab63feb5e9d23b36135b4565e7d4b4a85afae0882baa4ed,
-E = 450a269d202de9a6d2573b510bcc02f1e7c7d5b4a5779c55fbb4bd25241a1f9f,
-T = e96ce1c43cbe59f6f6946dea0ff1f3bc15227da9758308f48a53e4fc4c666249,
-U = a42aa5d5efceb63a480e8718d6e7930c3a156ba9ff971bae8538062305e502c7,
+R = 02913dc55b4d1e8e89d9e7c3e38702add012aae04a42439f9fe1d5d690d3255566,
+V = 023ec4892b5efe9e5db85104034a20b9cca6b7d7129f760b65ea19c33e6f4287a9,
+C = 03adab79913fc68007fe6db89ab64240edc864bc1a08dbea210492837707b53458,
+E = d455924c96c02ec532e137a2b288aa04745ecb18cc1000a55613cdf412a46427,
+T = 97e10ec3f596284e1efdbb20dfc53593339e5aa9e3117ac3dc7e0087c0ffc831,
+U = 2425097f2bdedd1b7294e6c35a036e1968bf5ec0cee387b948f4afc6827566b4,
TEST = 3,
-R = 02ac3a849571574161e53aaf3cb9c8c323c3498e7d329f02d723a6b9b3a1848a67,
-V = 025fbc82aa7b986a386ad2fa524f085a0e23dadd259a01e2dda66bf79d4fef9fb5,
-C = 039436f7a6a41ef3e624090f34ac24331fc9b233d03430f263ac62e3b6555817ba,
-E = 670dcf5cca02ce7bb776e48fd01f06119da99af75581ce715cca828e14627771,
-T = b4702324fa24b547850709fc0874809b638aa5e8ef10f8715100d116f5683702,
-U = f708022da7a842e68094699df0cd1124a7ae40d17a9bbb5788bf4fec85e9a1b8,
+R = 02cb97763b448ee16c0dbdcdef765e2ae257ec129fc7ef992b04850a51137ff5f5,
+V = 0211d00ede35b17508461d8d31323a86825bdd0b7458626a76a83705c0f95a5351,
+C = 03c4d0adc3e672fb70a9a0138b173d1d09ff23f9e4329035f5a7136c6fd9564849,
+E = 83c5149c51cf6a9c246a6b407b0c8dc7b47e99977b1deba413d88437aebe813c,
+T = 50ed725d57e38dbda89a2e87fe9cd72dad2434e5583243cb183cf611679e7972,
+U = 254066df913b9132a6534451968844058ab803f485642e686e30ac19c78d88f5,
TEST = 4,
-R = 0316ddced170deb5eee2121216c5a714e25ed0cbc5ef5646cc754234f778eb1c0b,
-V = 03b5302ae8d3061ebeebd34ad3e74f4be7ff11b20d321716f10d4e0a409059b2fa,
-C = 021e20bf1693d7515137d274938beb4faa5b6e5fa4fe81d2706cd1c9ad04c07a62,
-E = 7d9690223a556bcbcd86d24b20d85a520199ae39299dfc4f1f1ee36ffeda24e3,
-T = d6bab7bb975b18d876909c797fd3c70ee4ab59168d0bdad29620c517e5af324b,
-U = a3a0e66ed30df31b1e3195c964a00e731939ea5ea2c9176fc6fdd39c0dde4701,
+R = 03c5c2ba8cf4e0ddd06803f2eab8426e7250467e8a521e6e4764f8ed50f99e8ead,
+V = 03dcb5f6ead7e81963ab4a3f1f5c6d77e4c079001343b7058e8bff7c5d84f5da4a,
+C = 036410928e258ce7800407f127141ae617f5e2e89864b66c1dfa72a401fb5fbb61,
+E = ec74f330ac0ceea0d1c957fb01a07dccd1798d98d33b567b0c931dcc2c3e90ea,
+T = dc77f3cc4b31c8677ef566fc182a8c32bd98188aaa5255062104019dfc3b09dc,
+U = 6774443dbc5ecc5bcaf4597f36ede169372611417c53b8445ca56cb92aafe852,
TEST = 5,
-R = 03d28743c72ab145876065f39a3105d9b0f55bb225ef797c0674e65bf85c3439c3,
-V = 03708abbfa0a807e3540d8aa6c589c6993bcc0238986b317cfecbdc962fb459860,
-C = 02804191a4f52d8cf6948596122d89c079e4f6212420a263e66a693c1da94c3223,
-E = ff5bfd05347b361da4d159a29dae99df2ecdf2eec94fd4ade894398d9c4bc239,
-T = 4ca83780f3ab9e30e29c87c3cb6fa0eabb3e0f664d2c27a6bce05380c9ae92ae,
-U = 4edeef14e75585e7fd197c719fd3948f1f420a724d5c3a95eb5bff0bb38681a6,
+R = 02d1ee046200382c654c90a02fcc1b025ac15b34d26cb864b7278e359d04779792,
+V = 02380955f1798a27cd14802b947ec8b4b57fa206ac44707d3bc0d4beb7e2b1db5e,
+C = 02aab91a349d395b360362ca157a005c2cf9feab3ea25a86e62ee6f6bb8948968a,
+E = 8e50b3197f779789bcb082d9be490863fd2b68b9357d951b222fc5724e2aedcd,
+T = abc2b26aa50342df17c1adb5d600557d1460fa21360a386af8d4042b86ae87e6,
+U = e9f3f4669b61ace1037c04b0273500cadd2bdac058d1f50fccec4b0b71893c74,
TEST = 6,
-R = 0375cd1b2c2de801df582927c5b7bb823d03544d818dc2b4ff754cdf3ef30c4c03,
-V = 039fe1711cd9f775105caa6db9cdea37023fccd81d2c03a36141cc15a009e3ee58,
-C = 03271d03e3c2105cd8dce4e17d7e76cb4174cd1631c8c2dcbdee5ef9d67312b2a4,
-E = 56eec5122920560f0b88db05c7912d517f1ba492d1f21e9ab747e354df7e6665,
-T = f53dc9b0e3580638a7ea996318663d207c73495ebadf47e8061597cf7addb557,
-U = af3c5fa843e6bb582820c9f8a7a050f4162980c2aaf15952cb615ec0c86e53ab,
+R = 02bb995b6ef4415dac329d0f02aaebf248121e2cf844fce54d947b14e7b1c756c8,
+V = 03b4f1b72b07951c4db6ed445f1386fdd9859813b9bbcf3d59b78f2c41a1b0f417,
+C = 0258882ae61e1e8549cb4c2af92d479819c87bc02714106eabb1d1e8eaec36b26f,
+E = 70bb1893f91f520378838b35a240e65e3153d5b891ffafc7ecdd838c2042cbde,
+T = 88e8d7350400868a8d48f630868cbbc2ef97112696b985a3ad0c78d833a33625,
+U = bc4471af39ffe173f59807badbe79ffc9548f6d8fcaa8ecdccf6c3f7797f82cb,
TEST = 7,
-R = 03a487f61837e87c747c2737172b962f79f90f3e485792db349390393c7bbec009,
-V = 025c58b47fac4b2bc4556782fd0ff5d6f2761520b256150167144bfe1589531d2b,
-C = 02de1aac64d96206096d82a9782d890593492c33b6fb2cd0eb3d5da13e37a0571e,
-E = 608e104063ace2a703cdb85d79a9817f7732fada6cd2447af523df25083fe01c,
-T = 36c6489ecae5ccb524d2f3166bcdfc71b77aac8cc25a61433cd1062e113103aa,
-U = b6dadf473f9e7a341848f0a6ea84962694afe9776cd5f45175d6902b64709e96,
+R = 038bb34386bc9c7f065136d04f1c62c936ddbe9874235b2b27e378cf7514e34e10,
+V = 03a02e15a584f591c5fc8f0b4c1408552433c8547225643eff5414afdbaec8abf2,
+C = 021d1064a0e59a75d7e0f8b08d958c6a7f25882dc838acee5a962300e1b02de047,
+E = 5623eeafec05f5a592647f78b351f8adca1d4d99aec7992fdc1db4c830a39366,
+T = fea34fc356079b51b529bd6681ba0bd8d01f3417cce03944b21386ca9ddc7e3b,
+U = 74071f2a607cbc64255c8d64df7eb5cd31ab8a85d91d6497288c6339ca1fb526,
TEST = 8,
-R = 0345c3278b4d2e9fbb697b4a497bd41b068314b20a3556984286a348195e4bf87d,
-V = 028c61a27347c094aa299e95dc648cfde1d0ab65ee48a70bbc1d2fddbb43cea989,
-C = 0369298338f45f3e501e7f46d31ff4010425074b128e557bbc8ac5f80dbf764aa9,
-E = 9f553102958aecaf0d00130c36f5bc7c42eaa2ace113853ede0001ae5164a07b,
-T = a0b325d9e5b895ceae62621c1cf29d9a2fc4498fd1fc9937a63c8f32446080cc,
-U = a552b6f899eba8c5c2fdc67d2e8f20420a79002b2a8ed545c1332b2b2675eeb7,
+R = 0390d1fe5c60463086f65d1b44dbdf65c001f4e532f763e45646765d06019960de,
+V = 03a603e43e1a98b839f6971eb0fe73c7a70130e0c27411fda59617c8365ac6cdf2,
+C = 02938dcf17c55d78aa6b871d38ae838ea56d38c321c470527340212c4ada21fbd5,
+E = 51902fda78bb40a1eb2099512ae3e4853f596f0be0e73f478a01f4fff9c48e4c,
+T = 8daf81313b9aa20c44bbe6daa070618b571ad03df23e390ae7ec2585f1205ffd,
+U = a77503c8846192032f79f882ad9e8e21b7534553c2db6f0e988659c3675b5aa5,
TEST = 9,
-R = 02c9ce032faa136eb3ad72225300a592a620d5a9a9f90bf303fab853e29bb68276,
-V = 02313802a1e8c0e23d830d0ddbc81f4b9bdf8636f79823a84ba57e3beb8d11c35d,
-C = 026647a49f2daed3ff69d03c9638bea864f125485af059fe60d640f9e9a0685944,
-E = fb92fc530bb01d308afc30190ec261d4474346107f33809abe4bef288891e2cb,
-T = f1be16549e065da6bf96466c9330194e92f2dde14fffb883922c98e6361f19f8,
-U = e9a57b8486df4a58021fb1f57e3fb8ac5a30a73de5868d6542a196fbf3fc47fb,
+R = 025e534768bafa3171b850bcccbfad82702adc69d90f9db32debe7afe7fdd06f1c,
+V = 0229bc145f45468201a47c3e62785503d006fa9be41cd5892a65002a7aef0e79cd,
+C = 0248d59ed28567a329f442051fb7e91069a136e68751c52d5e592693295ecc0e81,
+E = 104b7d4a22cd1cee0d853f5b3d0e4e9a14e5156201b92b4860bcd8a07423e7b0,
+T = b4a9bf92910036da6342cf59bb6b545e7faf8dd3affb4ff1223d1c1805de7884,
+U = 4e78b645d5dba4a43f1fd896f62ba089608c4410bb6478de9a2ca9323dd7b0dc,