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

[incubator-milagro-MPC] branch add-phase5-api created (now 72c37ec)

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

sandreoli pushed a change to branch add-phase5-api
in repository https://gitbox.apache.org/repos/asf/incubator-milagro-MPC.git.


      at 72c37ec  Add phase 5 benchmark and example

This branch includes the following new commits:

     new a643ae5  Add phase 5 API
     new ebad52d  Add phase 5 tests and test vectors
     new 72c37ec  Add phase 5 benchmark and example

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[incubator-milagro-MPC] 01/03: Add phase 5 API

Posted by sa...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit a643ae5810bc3ae45bb3c7a48dfb4ea7df6bef5f
Author: Samuele Andreoli <sa...@yahoo.it>
AuthorDate: Fri Feb 7 11:53:15 2020 +0000

    Add phase 5 API
---
 include/amcl/mpc.h |  71 ++++++++++++++++++++++++
 src/mpc.c          | 158 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 229 insertions(+)

diff --git a/include/amcl/mpc.h b/include/amcl/mpc.h
index e23e6a8..8818ac7 100644
--- a/include/amcl/mpc.h
+++ b/include/amcl/mpc.h
@@ -33,6 +33,10 @@ under the License.
 extern "C" {
 #endif
 
+#define MPC_OK          0    /**< Execution Successful */
+#define MPC_FAIL        71   /**< Failure */
+#define MPC_INVALID_ECP 72   /**< Input is not a valid point on the curve */
+
 /** \brief ECDSA Sign message
  *
  *  Generate the ECDSA signature on message, M, with outputs (R,S)
@@ -156,6 +160,73 @@ void MPC_SUM_S(octet *S1, octet *S2, octet *S);
  */
 int MPC_SUM_PK(octet *PK1, octet *PK2, octet *PK);
 
+/* MPC Phase 5 API */
+
+/** \brief Generate Commitment for the MPC Phase 5
+ *
+ *  Calculate player Commitment (A, V) for MPC Phase 5
+ *
+ *  <ol>
+ *  <li> \f$ \phi \in_R [0, \ldots, q] \f$
+ *  <li> \f$ \rho \in_R [0, \ldots, q] \f$
+ *  <li> \f$ V = \phi.G + s.R \f$
+ *  <li> \f$ A = \rho.G \f$
+ *  </ol>
+ *
+ *  @param RNG                csprng for random values generation
+ *  @param R                  Reconciled R for the signature
+ *  @param S                  Player signature share
+ *  @param PHI                Random value for the commitment. If RNG is null this is read
+ *  @param RHO                Random value for the commitment. If RNG is null this is read
+ *  @param V                  First component of the player commitment. An ECP in compressed form
+ *  @param A                  Second component of the player commitment. An ECP in compressed form
+ *  @return                   Returns MPC_OK or an error code
+ */
+extern int MPC_PHASE5_commit(csprng *RNG, octet *R, octet *S, octet *PHI, octet *RHO, octet *V, octet *A);
+
+/** \brief Generate Proof for the MPC Phase 5
+ *
+ *  Calculate player Proof (U, T) for MPC Phase 5
+ *
+ *  <ol>
+ *  <li> \f$ m = H(M) \f$
+ *  <li> \f$ A = A1 + A2 \f$
+ *  <li> \f$ V = V1 + V2 \f$
+ *  <li> \f$ U = \rho.(V - m.G - r.PK) \f$
+ *  <li> \f$ T = \phi.A \f$
+ *  </ol>
+ *
+ *  @param PHI                Random value used in the commitment
+ *  @param RHO                Random value used in the commitment
+ *  @param V                  Array with the commitments V from both players. ECPs in compressed form
+ *  @param A                  Array with the commitments A from both players. ECPs in compressed form
+ *  @param PK                 Shared public key for MPC
+ *  @param HM                 Hash of the message being signed
+ *  @param RX                 x component of the reconciled R for the signature
+ *  @param U                  First component of the player proof. An ECP in compressed form
+ *  @param T                  Second component of the player proof. An ECP in compressed form
+ *  @return                   Returns MPC_OK or an error code
+ */
+extern int MPC_PHASE5_prove(octet *PHI, octet *RHO, octet *V[2], octet *A[2], octet *PK, octet *HM, octet *RX, octet *U, octet *T);
+
+/** \brief Verify Proof for the MPC Phase 5
+ *
+ *  Combine player Proofs and verify the consistency of the signature shares
+ *  This does NOT prove that the signature is valid. It only verifies that
+ *  all players know the secret quantities used to generate their shares.
+ *
+ *  <ol>
+ *  <li> \f$ U = U1 + U2 \f$
+ *  <li> \f$ T = T1 + T2 \f$
+ *  <li> \f$ U \stackrel{?}{=} T \f$
+ *  </ol>
+ *
+ *  @param U                  Array with the proofs U from both players. ECPs in compressed form
+ *  @param T                  Array with the proofs T from both players. ECPs in compressed form
+ *  @return                   Returns MPC_OK or an error code
+ */
+extern int MPC_PHASE5_verify(octet *U[2], octet *T[2]);
+
 /*! \brief Write Paillier public key to octets
  *
  *  @param   PUB              Paillier public key
diff --git a/src/mpc.c b/src/mpc.c
index d85f53f..82216f4 100644
--- a/src/mpc.c
+++ b/src/mpc.c
@@ -347,6 +347,164 @@ int MPC_SUM_PK(octet *PK1, octet *PK2, octet *PK)
     return 0;
 }
 
+int MPC_PHASE5_commit(csprng *RNG, octet *R, octet *S, octet *PHI, octet *RHO, octet *V, octet *A)
+{
+    BIG_256_56 ws;
+    BIG_256_56 phi;
+    BIG_256_56 rho;
+
+    ECP_SECP256K1 P1;
+    ECP_SECP256K1 P2;
+
+    if (!ECP_SECP256K1_fromOctet(&P1, R))
+    {
+        return MPC_INVALID_ECP;
+    }
+
+    if (RNG != NULL)
+    {
+        BIG_256_56_rcopy(ws, CURVE_Order_SECP256K1);
+        BIG_256_56_randomnum(phi, ws, RNG);
+        BIG_256_56_randomnum(rho, ws, RNG);
+
+        BIG_256_56_toBytes(PHI->val, phi);
+        BIG_256_56_toBytes(RHO->val, rho);
+        PHI->len = EGS_SECP256K1;
+        RHO->len = EGS_SECP256K1;
+    }
+    else
+    {
+        BIG_256_56_fromBytesLen(phi, PHI->val, PHI->len);
+        BIG_256_56_fromBytesLen(rho, RHO->val, RHO->len);
+    }
+
+    // Compute V = phi.G + s.R
+    BIG_256_56_fromBytesLen(ws, S->val, S->len);
+    ECP_SECP256K1_generator(&P2);
+
+    ECP_SECP256K1_mul2(&P1, &P2, ws, phi);
+
+    // Compute A = rho.G
+    ECP_SECP256K1_mul(&P2, rho);
+
+    // Output ECPs
+    ECP_SECP256K1_toOctet(V, &P1, 1);
+    ECP_SECP256K1_toOctet(A, &P2, 1);
+
+    // Clean memory
+    BIG_256_56_zero(phi);
+    BIG_256_56_zero(rho);
+    BIG_256_56_zero(ws);
+
+    return MPC_OK;
+}
+
+int MPC_PHASE5_prove(octet *PHI, octet *RHO, octet *V[2], octet *A[2], octet *PK, octet *HM, octet *RX, octet *U, octet *T)
+{
+    BIG_256_56 m;
+    BIG_256_56 r;
+    BIG_256_56 ws;
+
+    ECP_SECP256K1 V1;
+    ECP_SECP256K1 V2;
+    ECP_SECP256K1 A1;
+    ECP_SECP256K1 A2;
+    ECP_SECP256K1 K;
+
+    if (!ECP_SECP256K1_fromOctet(&A1, A[0]))
+    {
+        return MPC_INVALID_ECP;
+    }
+
+    if (!ECP_SECP256K1_fromOctet(&A2, A[1]))
+    {
+        return MPC_INVALID_ECP;
+    }
+
+    if (!ECP_SECP256K1_fromOctet(&V1, V[0]))
+    {
+        return MPC_INVALID_ECP;
+    }
+
+    if (!ECP_SECP256K1_fromOctet(&V2, V[1]))
+    {
+        return MPC_INVALID_ECP;
+    }
+
+    if (!ECP_SECP256K1_fromOctet(&K, PK))
+    {
+        return MPC_INVALID_ECP;
+    }
+
+    // Compute A = phi.(A1 + A2)
+    BIG_256_56_fromBytesLen(ws, PHI->val, PHI->len);
+    ECP_SECP256K1_add(&A1, &A2);
+    ECP_SECP256K1_mul(&A1, ws);
+
+    ECP_SECP256K1_toOctet(T, &A1, 1);
+
+    // Compute V = rho.(V1 + V2 - m.G - r.PK)
+    BIG_256_56_fromBytesLen(m,  HM->val,  HM->len);
+    BIG_256_56_fromBytesLen(r,  RX->val,  RX->len);
+    BIG_256_56_fromBytesLen(ws, RHO->val, RHO->len);
+
+    // K = - m.G - r.PK
+    ECP_SECP256K1_generator(&A1);
+    ECP_SECP256K1_neg(&A1);
+    ECP_SECP256K1_neg(&K);
+    ECP_SECP256K1_mul2(&K, &A1, r, m);
+
+    // V = rho.(V1 + V2 + K)
+    ECP_SECP256K1_add(&V1, &V2);
+    ECP_SECP256K1_add(&V1, &K);
+    ECP_SECP256K1_mul(&V1, ws);
+
+    ECP_SECP256K1_toOctet(U, &V1, 1);
+
+    // Clean memory
+    BIG_256_56_zero(ws);
+
+    return MPC_OK;
+}
+
+int MPC_PHASE5_verify(octet *U[2], octet *T[2])
+{
+    ECP_SECP256K1 U1;
+    ECP_SECP256K1 U2;
+    ECP_SECP256K1 T1;
+    ECP_SECP256K1 T2;
+
+    if (!ECP_SECP256K1_fromOctet(&U1, U[0]))
+    {
+        return MPC_INVALID_ECP;
+    }
+
+    if (!ECP_SECP256K1_fromOctet(&U2, U[1]))
+    {
+        return MPC_INVALID_ECP;
+    }
+
+    if (!ECP_SECP256K1_fromOctet(&T1, T[0]))
+    {
+        return MPC_INVALID_ECP;
+    }
+
+    if (!ECP_SECP256K1_fromOctet(&T2, T[1]))
+    {
+        return MPC_INVALID_ECP;
+    }
+
+    ECP_SECP256K1_add(&U1, &U2);
+    ECP_SECP256K1_add(&T1, &T2);
+
+    if (!ECP_SECP256K1_equals(&U1, &T1))
+    {
+        return MPC_FAIL;
+    }
+
+    return MPC_OK;
+}
+
 // Write Paillier public key to octets
 void MPC_DUMP_PAILLIER_PK(PAILLIER_public_key *PUB, octet *N, octet *G, octet *N2)
 {


[incubator-milagro-MPC] 02/03: Add phase 5 tests and test vectors

Posted by sa...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit ebad52da619ffcb3fe708ceec24f8ea2d180ea26
Author: Samuele Andreoli <sa...@yahoo.it>
AuthorDate: Fri Feb 7 11:54:12 2020 +0000

    Add phase 5 tests and test vectors
---
 model/vectors/mpc/genPHASE5.py     | 140 ++++++++++++++++++++++++++
 test/smoke/test_phase5_smoke.c     | 149 +++++++++++++++++++++++++++
 test/test.c                        |   8 ++
 test/unit/CMakeLists.txt           |   9 +-
 test/unit/test_phase5_commit.c     | 132 ++++++++++++++++++++++++
 test/unit/test_phase5_prove.c      | 200 +++++++++++++++++++++++++++++++++++++
 test/unit/test_phase5_verify.c     | 160 +++++++++++++++++++++++++++++
 testVectors/mpc/phase5_commit.json |  92 +++++++++++++++++
 testVectors/mpc/phase5_commit.txt  |  80 +++++++++++++++
 testVectors/mpc/phase5_prove.json  | 142 ++++++++++++++++++++++++++
 testVectors/mpc/phase5_prove.txt   | 130 ++++++++++++++++++++++++
 testVectors/mpc/phase5_verify.json |  72 +++++++++++++
 testVectors/mpc/phase5_verify.txt  |  60 +++++++++++
 13 files changed, 1371 insertions(+), 3 deletions(-)

diff --git a/model/vectors/mpc/genPHASE5.py b/model/vectors/mpc/genPHASE5.py
new file mode 100755
index 0000000..f988e4b
--- /dev/null
+++ b/model/vectors/mpc/genPHASE5.py
@@ -0,0 +1,140 @@
+#!/usr/bin/env python3
+
+"""
+    Generates a set of test vectors for the schnorr zk proof.
+
+    usage: genPHASE5.py -h
+"""
+
+import sys
+sys.path.append("../../")
+
+import json
+import argparse
+from sec256k1 import big, ecp, curve, mpc
+
+def genVector(test_no):
+    """Generate a single test vector
+
+        Use parameters to generate a single test vector
+
+        Args::
+
+            test_no: Test vector identifier
+
+        Returns::
+
+            vector: A test vector
+
+        Raises::
+
+            Exception
+    """
+
+    # Generate distributed keypair
+    x1 = big.rand(curve.r)
+    x2 = big.rand(curve.r)
+    x = (x1 + x2) % curve.r
+    PK = x * ecp.generator()
+
+    # Generate message
+    M = "TEST_MESSAGE_{}".format(test_no).encode('utf-8')
+
+    # Generate ki, sigma, r, R for signature
+    k1 = big.rand(curve.r)
+    k2 = big.rand(curve.r)
+    k = (k1 + k2) % curve.r
+    invk = big.invmodp(k, curve.r)
+
+    R = invk * ecp.generator()
+    r = R.getx() % curve.r
+
+    # Fake additive split of sigma. This is not
+    # what you would get from the MTA, but it is
+    # fine here for testing purposes
+    sigma1 = (k1 * x1 + k1 * x2) % curve.r
+    sigma2 = (k2 * x2 + k2 * x1) % curve.r
+
+    # Generate sigmature shares
+    s1 = mpc.make_signature_share(M, k1, r, sigma1)
+    s2 = mpc.make_signature_share(M, k2, r, sigma2)
+
+    # Check consistency of signature values generated
+    s = (s1 + s2) % curve.r
+    s_gt = (k * (mpc.hashit(M) + r*x)) % curve .r
+    assert s == s_gt, "inconsistent signature values generated"
+
+    # Generate test vector
+    phi1, rho1, V1, A1 = mpc.phase5_commit(s1, R)
+    phi2, rho2, V2, A2 = mpc.phase5_commit(s2, R)
+
+    Vs = [V1, V2]
+    As = [A1, A2]
+
+    U1, T1 = mpc.phase5_prove(rho1, phi1, Vs, As, PK, M, r)
+    U2, T2 = mpc.phase5_prove(rho2, phi2, Vs, As, PK, M, r)
+
+    Us = [U1, U2]
+    Ts = [T1, T2]
+
+    assert mpc.phase5_verify(Us, Ts), "inconsistent test vector"
+
+    vector = {
+        "TEST"  : test_no,
+        "M"     : hex(mpc.hashit(M))[2:].zfill(64),
+        "PK"    : PK.toBytes(True).hex(),
+        "R"     : R.toBytes(True).hex(),
+        "K"     : hex(k1)[2:].zfill(64),
+        "S"     : hex(s1)[2:].zfill(64),
+        "RX"    : hex(r)[2:].zfill(64),
+        "PHI"   : hex(phi1)[2:].zfill(64),
+        "RHO"   : hex(rho1)[2:].zfill(64),
+        "A1"    : A1.toBytes(True).hex(),
+        "A2"    : A2.toBytes(True).hex(),
+        "V1"    : V1.toBytes(True).hex(),
+        "V2"    : V2.toBytes(True).hex(),
+        "U1"    : U1.toBytes(True).hex(),
+        "U2"    : U2.toBytes(True).hex(),
+        "T1"    : T1.toBytes(True).hex(),
+        "T2"    : T2.toBytes(True).hex(),
+    }
+
+    return vector
+
+
+
+vector_fields = {
+    "commit": ["TEST", "S", "R", "PHI", "RHO", "V1", "A1"],
+    "prove": ["TEST", "PHI", "RHO", "V1", "V2", "A1", "A2", "PK", "M", "RX", "U1", "T1"],
+    "verify": ["TEST", "U1", "U2", "T1", "T2",],
+}
+
+if __name__ == '__main__':
+    parser = argparse.ArgumentParser()
+
+    parser.add_argument('-t', dest='type', type=str, default='commit', choices=["commit", "prove", "verify"],
+        help='test vector type')
+    parser.add_argument('-n', dest='n', type=int, default=10,
+        help='number of test vectors to generate')
+
+    args = parser.parse_args()
+
+    vec_type = args.type
+
+    keys = vector_fields[vec_type]
+
+    vectors = []
+
+    for i in range(args.n):
+        vector = genVector(i)
+
+        vector = {k: vector[k] for k in keys}
+        vectors.append(vector)
+
+    json.dump(vectors, open("phase5_{}.json".format(vec_type), "w"), indent=2)
+
+    with open("phase5_{}.txt".format(vec_type), "w") as f:
+        for vector in vectors:
+            for field in keys:
+                f.write("{} = {},\n".format(field, vector[field]))
+            f.write("\n")
diff --git a/test/smoke/test_phase5_smoke.c b/test/smoke/test_phase5_smoke.c
new file mode 100644
index 0000000..2cb81ff
--- /dev/null
+++ b/test/smoke/test_phase5_smoke.c
@@ -0,0 +1,149 @@
+/*
+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.
+*/
+
+// MPC Phase 5 smoke test
+
+#include <amcl/ecdh_SECP256K1.h>
+#include <amcl/mpc.h>
+
+char *M_hex  = "4b7df9714ecf795cfd698129a6f5250cfb64b739ad163da2da93c728c3bd19be";
+char *PK_hex = "022008f40a4f5bc74ac3cbd41986e61e4229afae6658d51845978f18d33fe8318c";
+char *S1_hex = "90c2d9dba55ef93dbfb234d04a2bea475f7067787a57556736c876eced465154";
+char *S2_hex = "8002233d6018c7e1497b42828e517364f0b5b79e9edb8a7d130fa21e76270ee2";
+char *R_hex  = "028ae19ff44d023c774d6526a22bdb47ccfa5e22a91f9994a485660e9f2363da32";
+char *RX_hex = "8ae19ff44d023c774d6526a22bdb47ccfa5e22a91f9994a485660e9f2363da32";
+
+int main()
+{
+    int rc;
+
+    char m[SHA256];
+    octet M = {0, sizeof(m), m};
+
+    char s1[EGS_SECP256K1];
+    octet S1 = {0, sizeof(s1), s1};
+
+    char s2[EGS_SECP256K1];
+    octet S2 = {0, sizeof(s2), s2};
+
+    char rx[EGS_SECP256K1];
+    octet RX = {0, sizeof(rx), rx};
+
+    char pk[EFS_SECP256K1 + 1];
+    octet PK = {0, sizeof(pk), pk};
+
+    char r[EFS_SECP256K1 + 1];
+    octet R = {0, sizeof(r), r};
+
+    char rho1[EGS_SECP256K1];
+    octet RHO1 = {0, sizeof(rho1), rho1};
+
+    char phi1[EGS_SECP256K1];
+    octet PHI1 = {0, sizeof(phi1), phi1};
+
+    char rho2[EGS_SECP256K1];
+    octet RHO2 = {0, sizeof(rho2), rho2};
+
+    char phi2[EGS_SECP256K1];
+    octet PHI2 = {0, sizeof(phi2), phi2};
+
+    char v1[EFS_SECP256K1 + 1];
+    octet V1 = {0, sizeof(v1), v1};
+
+    char v2[EFS_SECP256K1 + 1];
+    octet V2 = {0, sizeof(v2), v2};
+
+    octet *V[2] = {&V1, &V2};
+
+    char a1[EFS_SECP256K1 + 1];
+    octet A1 = {0, sizeof(a1), a1};
+
+    char a2[EFS_SECP256K1 + 1];
+    octet A2 = {0, sizeof(a2), a2};
+
+    octet *A[2] = {&A1, &A2};
+
+    char u1[EFS_SECP256K1 + 1];
+    octet U1 = {0, sizeof(u1), u1};
+
+    char u2[EFS_SECP256K1 + 1];
+    octet U2 = {0, sizeof(u2), u2};
+
+    octet *U[2] = {&U1, &U2};
+
+    char t1[EFS_SECP256K1 + 1];
+    octet T1 = {0, sizeof(t1), t1};
+
+    char t2[EFS_SECP256K1 + 1];
+    octet T2 = {0, sizeof(t2), t2};
+
+    octet *T[2] = {&T1, &T2};
+
+    // Deterministic RNG for testing
+    char seed[32] = {0};
+    csprng RNG;
+    RAND_seed(&RNG, 32, seed);
+
+    // Load input
+    OCT_fromHex(&M,  M_hex);
+    OCT_fromHex(&PK, PK_hex);
+    OCT_fromHex(&S1, S1_hex);
+    OCT_fromHex(&S2, S2_hex);
+    OCT_fromHex(&R,  R_hex);
+    OCT_fromHex(&RX, RX_hex);
+
+    // Run test
+    rc = MPC_PHASE5_commit(&RNG, &R, &S1, &PHI1, &RHO1, V[0], A[0]);
+    if (rc != MPC_OK)
+    {
+        printf("FAILURE MPC_PHASE5_commit player 1. RC %d\n", rc);
+        exit(EXIT_FAILURE);
+    }
+
+    rc = MPC_PHASE5_commit(&RNG, &R, &S2, &PHI2, &RHO2, V[1], A[1]);
+    if (rc != MPC_OK)
+    {
+        printf("FAILURE MPC_PHASE5_commit player 2. RC %d\n", rc);
+        exit(EXIT_FAILURE);
+    }
+
+    rc = MPC_PHASE5_prove(&PHI1, &RHO1, V, A, &PK, &M, &RX, U[0], T[0]);
+    if (rc != MPC_OK)
+    {
+        printf("FAILURE MPC_PHASE5_prove player 1. RC %d\n", rc);
+        exit(EXIT_FAILURE);
+    }
+
+    rc = MPC_PHASE5_prove(&PHI2, &RHO2, V, A, &PK, &M, &RX, U[1], T[1]);
+    if (rc != MPC_OK)
+    {
+        printf("FAILURE MPC_PHASE5_prove player 2. RC %d\n", rc);
+        exit(EXIT_FAILURE);
+    }
+
+    rc = MPC_PHASE5_verify(U, T);
+    if (rc != MPC_OK)
+    {
+        printf("FAILURE MPC_PHASE5_verify. RC %d\n", rc);
+        exit(EXIT_FAILURE);
+    }
+
+    printf("SUCCESS\n");
+    exit(EXIT_SUCCESS);
+}
diff --git a/test/test.c b/test/test.c
index e18f6e9..b739b04 100644
--- a/test/test.c
+++ b/test/test.c
@@ -169,6 +169,14 @@ void compare_OCT(FILE* fp, int testNo, char *name, octet *X, octet *Y)
 #endif
 
         printf("FAILURE %s. Test %d\n", name, testNo);
+
+#ifdef DEBUG
+        printf("X = ");
+        OCT_output(X);
+        printf("Y = ");
+        OCT_output(Y);
+#endif
+
         exit(EXIT_FAILURE);
     }
 }
diff --git a/test/unit/CMakeLists.txt b/test/unit/CMakeLists.txt
index a627306..4fa3bea 100644
--- a/test/unit/CMakeLists.txt
+++ b/test/unit/CMakeLists.txt
@@ -40,9 +40,12 @@ function(amcl_test name source dependencies expected_response)
 endfunction()
 
 # MPC tests
-amcl_test(test_mta test_mta.c amcl_mpc "SUCCESS" "mpc/MTA.txt")
-amcl_test(test_r   test_r.c   amcl_mpc "SUCCESS" "mpc/R.txt")
-amcl_test(test_s   test_s.c   amcl_mpc "SUCCESS" "mpc/S.txt")
+amcl_test(test_mta           test_mta.c           amcl_mpc "SUCCESS" "mpc/MTA.txt")
+amcl_test(test_r             test_r.c             amcl_mpc "SUCCESS" "mpc/R.txt")
+amcl_test(test_s             test_s.c             amcl_mpc "SUCCESS" "mpc/S.txt")
+amcl_test(test_phase5_commit test_phase5_commit.c amcl_mpc "SUCCESS" "mpc/phase5_commit.txt")
+amcl_test(test_phase5_prove  test_phase5_prove.c  amcl_mpc "SUCCESS" "mpc/phase5_prove.txt")
+amcl_test(test_phase5_verify test_phase5_verify.c amcl_mpc "SUCCESS" "mpc/phase5_verify.txt")
 
 # NM Commitment tests
 amcl_test(test_nm_commit test_nm_commit.c amcl_mpc "SUCCESS" "commitments/nm_commit.txt")
diff --git a/test/unit/test_phase5_commit.c b/test/unit/test_phase5_commit.c
new file mode 100644
index 0000000..69708aa
--- /dev/null
+++ b/test/unit/test_phase5_commit.c
@@ -0,0 +1,132 @@
+/*
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+*/
+
+#include <string.h>
+#include "test.h"
+#include "amcl/mpc.h"
+#include "amcl/ecdh_SECP256K1.h"
+
+/* MPC Phase 5 commitment unit test */
+
+#define LINE_LEN 256
+
+int main(int argc, char **argv)
+{
+    if (argc != 2)
+    {
+        printf("usage: ./test_phase5_commit [path to test vector file]\n");
+        exit(EXIT_FAILURE);
+    }
+
+    int rc;
+    int test_run = 0;
+
+    char err_msg[128];
+
+    FILE *fp;
+    char line[LINE_LEN] = {0};
+
+    const char *TESTline = "TEST = ";
+    int testNo = 0;
+
+    char s[EGS_SECP256K1];
+    octet S = {0, sizeof(s), s};
+    const char *Sline = "S = ";
+
+    char r[EFS_SECP256K1 + 1];
+    octet R = {0, sizeof(r), r};
+    const char *Rline = "R = ";
+
+    char phi[EGS_SECP256K1];
+    octet PHI = {0, sizeof(phi), phi};
+    const char *PHIline = "PHI = ";
+
+    char rho[EGS_SECP256K1];
+    octet RHO = {0, sizeof(rho), rho};
+    const char *RHOline = "RHO = ";
+
+    char v_golden[EFS_SECP256K1 + 1];
+    octet V_GOLDEN = {0, sizeof(v_golden), v_golden};
+    const char *Vline = "V1 = ";
+
+    char a_golden[EFS_SECP256K1 + 1];
+    octet A_GOLDEN = {0, sizeof(a_golden), a_golden};
+    const char *Aline = "A1 = ";
+
+    char v[EFS_SECP256K1 + 1];
+    octet V = {0, sizeof(v), v};
+
+    char a[EFS_SECP256K1 + 1];
+    octet A = {0, sizeof(a), a};
+
+    // Line terminating a test vector
+    const char *last_line = Aline;
+
+    fp = fopen(argv[1], "r");
+    if (fp == NULL)
+    {
+        printf("ERROR opening test vector file\n");
+        exit(EXIT_FAILURE);
+    }
+
+    while (fgets(line, LINE_LEN, fp) != NULL)
+    {
+        scan_int(&testNo, line, TESTline);
+
+        // Read input
+        scan_OCTET(fp, &S,   line, Sline);
+        scan_OCTET(fp, &R,   line, Rline);
+        scan_OCTET(fp, &PHI, line, PHIline);
+        scan_OCTET(fp, &RHO, line, RHOline);
+
+        // Read ground truth
+        scan_OCTET(fp, &V_GOLDEN, line, Vline);
+        scan_OCTET(fp, &A_GOLDEN, line, Aline);
+
+        if (!strncmp(line, last_line, strlen(last_line)))
+        {
+            rc = MPC_PHASE5_commit(NULL, &R, &S, &PHI, &RHO, &V, &A);
+            sprintf(err_msg, "FAILURE MPC_PHASE5_commit. RC %d", rc);
+            assert_tv(fp, testNo, err_msg, rc == MPC_OK);
+
+            compare_OCT(fp, testNo, "FAILURE MPC_PHASE5_commit V", &V, &V_GOLDEN);
+            compare_OCT(fp, testNo, "FAILURE MPC_PHASE5_commit A", &A, &A_GOLDEN);
+
+            // Mark that at least one test vector was executed
+            test_run = 1;
+        }
+    }
+
+    fclose(fp);
+
+    if (test_run == 0)
+    {
+        printf("ERROR no test vector was executed\n");
+        exit(EXIT_FAILURE);
+    }
+
+    /* Test unhappy paths */
+
+    rc = MPC_PHASE5_commit(NULL, &S, &S, &PHI, &RHO, &V, &A);
+    sprintf(err_msg, "FAILURE MPC_PHASE5_commit invalid R. RC %d", rc);
+    assert_tv(fp, testNo, err_msg, rc == MPC_INVALID_ECP);
+
+    printf("SUCCESS\n");
+    exit(EXIT_SUCCESS);
+}
diff --git a/test/unit/test_phase5_prove.c b/test/unit/test_phase5_prove.c
new file mode 100644
index 0000000..7661e28
--- /dev/null
+++ b/test/unit/test_phase5_prove.c
@@ -0,0 +1,200 @@
+/*
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+*/
+
+#include <string.h>
+#include "test.h"
+#include "amcl/mpc.h"
+#include "amcl/ecdh_SECP256K1.h"
+
+/* MPC Phase 5 proof unit test */
+
+#define LINE_LEN 256
+
+int main(int argc, char **argv)
+{
+    if (argc != 2)
+    {
+        printf("usage: ./test_phase5_prove [path to test vector file]\n");
+        exit(EXIT_FAILURE);
+    }
+
+    int rc;
+    int test_run = 0;
+
+    char err_msg[128];
+
+    FILE *fp;
+    char line[LINE_LEN] = {0};
+
+    const char *TESTline = "TEST = ";
+    int testNo = 0;
+
+    char phi[EGS_SECP256K1];
+    octet PHI = {0, sizeof(phi), phi};
+    const char *PHIline = "PHI = ";
+
+    char rho[EGS_SECP256K1];
+    octet RHO = {0, sizeof(rho), rho};
+    const char *RHOline = "RHO = ";
+
+    char pk[EFS_SECP256K1 + 1];
+    octet PK = {0, sizeof(pk), pk};
+    const char *PKline = "PK = ";
+
+    char m[SHA256];
+    octet M = {0, sizeof(m), m};
+    const char *Mline = "M = ";
+
+    char rx[EFS_SECP256K1 + 1];
+    octet RX = {0, sizeof(rx), rx};
+    const char *RXline = "RX = ";
+
+    char v1[EFS_SECP256K1 + 1];
+    octet V1 = {0, sizeof(v1), v1};
+    const char *V1line = "V1 = ";
+
+    char v2[EFS_SECP256K1 + 1];
+    octet V2 = {0, sizeof(v2), v2};
+    const char *V2line = "V2 = ";
+
+    octet *V[2] = {&V1, &V2};
+
+    char a1[EFS_SECP256K1 + 1];
+    octet A1 = {0, sizeof(a1), a1};
+    const char *A1line = "A1 = ";
+
+    char a2[EFS_SECP256K1 + 1];
+    octet A2 = {0, sizeof(a2), a2};
+    const char *A2line = "A2 = ";
+
+    octet *A[2] = {&A1, &A2};
+
+    char u_golden[EFS_SECP256K1 + 1];
+    octet U_GOLDEN = {0, sizeof(u_golden), u_golden};
+    const char *Uline = "U1 = ";
+
+    char t_golden[EFS_SECP256K1 + 1];
+    octet T_GOLDEN = {0, sizeof(t_golden), t_golden};
+    const char *Tline = "T1 = ";
+
+    char u[EFS_SECP256K1 + 1];
+    octet U = {0, sizeof(u), u};
+
+    char t[EFS_SECP256K1 + 1];
+    octet T = {0, sizeof(t), t};
+
+    // Line terminating a test vector
+    const char *last_line = Tline;
+
+    fp = fopen(argv[1], "r");
+    if (fp == NULL)
+    {
+        printf("ERROR opening test vector file\n");
+        exit(EXIT_FAILURE);
+    }
+
+    while (fgets(line, LINE_LEN, fp) != NULL)
+    {
+        scan_int(&testNo, line, TESTline);
+
+        // Read input
+        scan_OCTET(fp, &PHI, line, PHIline);
+        scan_OCTET(fp, &RHO, line, RHOline);
+        scan_OCTET(fp, &V1,  line, V1line);
+        scan_OCTET(fp, &V2,  line, V2line);
+        scan_OCTET(fp, &A1,  line, A1line);
+        scan_OCTET(fp, &A2,  line, A2line);
+        scan_OCTET(fp, &PK,  line, PKline);
+        scan_OCTET(fp, &RX,  line, RXline);
+
+        // Read
+        scan_OCTET(fp, &M,   line, Mline);
+
+        // Read ground truth
+        scan_OCTET(fp, &T_GOLDEN, line, Tline);
+        scan_OCTET(fp, &U_GOLDEN, line, Uline);
+
+        if (!strncmp(line, last_line, strlen(last_line)))
+        {
+            rc = MPC_PHASE5_prove(&PHI, &RHO, V, A, &PK, &M, &RX, &U, &T);
+            sprintf(err_msg, "FAILURE MPC_PHASE5_prove. RC %d", rc);
+            assert_tv(fp, testNo, err_msg, rc == MPC_OK);
+
+            compare_OCT(fp, testNo, "FAILURE MPC_PHASE5_prove U", &U, &U_GOLDEN);
+            compare_OCT(fp, testNo, "FAILURE MPC_PHASE5_prove T", &T, &T_GOLDEN);
+
+            // Mark that at least one test vector was executed
+            test_run = 1;
+        }
+    }
+
+    fclose(fp);
+
+    if (test_run == 0)
+    {
+        printf("ERROR no test vector was executed\n");
+        exit(EXIT_FAILURE);
+    }
+
+    /* Test unhappy paths */
+
+    // Invalid V[0]
+    V[0] = &PHI;
+
+    rc = MPC_PHASE5_prove(&PHI, &RHO, V, A, &PK, &M, &RX, &U_GOLDEN, &T_GOLDEN);
+    sprintf(err_msg, "FAILURE MPC_PHASE5_prove invalid V1. RC %d", rc);
+    assert_tv(fp, testNo, err_msg, rc == MPC_INVALID_ECP);
+
+    V[0] = &V1;
+
+    // Invalid V[1]
+    V[1] = &PHI;
+
+    rc = MPC_PHASE5_prove(&PHI, &RHO, V, A, &PK, &M, &RX, &U_GOLDEN, &T_GOLDEN);
+    sprintf(err_msg, "FAILURE MPC_PHASE5_prove invalid V2. RC %d", rc);
+    assert_tv(fp, testNo, err_msg, rc == MPC_INVALID_ECP);
+
+    V[1] = &V2;
+
+    // Invalid A[0]
+    A[0] = &PHI;
+
+    rc = MPC_PHASE5_prove(&PHI, &RHO, V, A, &PK, &M, &RX, &U_GOLDEN, &T_GOLDEN);
+    sprintf(err_msg, "FAILURE MPC_PHASE5_prove invalid A1. RC %d", rc);
+    assert_tv(fp, testNo, err_msg, rc == MPC_INVALID_ECP);
+
+    A[0] = &A1;
+
+    // Invalid A[1]
+    A[1] = &PHI;
+
+    rc = MPC_PHASE5_prove(&PHI, &RHO, V, A, &PK, &M, &RX, &U_GOLDEN, &T_GOLDEN);
+    sprintf(err_msg, "FAILURE MPC_PHASE5_prove invalid A2. RC %d", rc);
+    assert_tv(fp, testNo, err_msg, rc == MPC_INVALID_ECP);
+
+    A[1] = &A2;
+
+    // Invalid PK
+    rc = MPC_PHASE5_prove(&PHI, &RHO, V, A, &PHI, &M, &RX, &U_GOLDEN, &T_GOLDEN);
+    sprintf(err_msg, "FAILURE MPC_PHASE5_prove invalid PK. RC %d", rc);
+    assert_tv(fp, testNo, err_msg, rc == MPC_INVALID_ECP);
+
+    printf("SUCCESS\n");
+    exit(EXIT_SUCCESS);
+}
diff --git a/test/unit/test_phase5_verify.c b/test/unit/test_phase5_verify.c
new file mode 100644
index 0000000..19a4d68
--- /dev/null
+++ b/test/unit/test_phase5_verify.c
@@ -0,0 +1,160 @@
+/*
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+*/
+
+#include <string.h>
+#include "test.h"
+#include "amcl/mpc.h"
+#include "amcl/ecdh_SECP256K1.h"
+
+/* MPC Phase 5 verification unit test */
+
+#define LINE_LEN 256
+
+int main(int argc, char **argv)
+{
+    if (argc != 2)
+    {
+        printf("usage: ./test_phase5_verify [path to test vector file]\n");
+        exit(EXIT_FAILURE);
+    }
+
+    int rc;
+    int test_run = 0;
+
+    char err_msg[128];
+
+    FILE *fp;
+    char line[LINE_LEN] = {0};
+
+    const char *TESTline = "TEST = ";
+    int testNo = 0;
+
+    char u1[EFS_SECP256K1 + 1];
+    octet U1 = {0, sizeof(u1), u1};
+    const char *U1line = "U1 = ";
+
+    char u2[EFS_SECP256K1 + 1];
+    octet U2 = {0, sizeof(u2), u2};
+    const char *U2line = "U2 = ";
+
+    octet *U[2] = {&U1, &U2};
+
+    char t1[EFS_SECP256K1 + 1];
+    octet T1 = {0, sizeof(t1), t1};
+    const char *T1line = "T1 = ";
+
+    char t2[EFS_SECP256K1 + 1];
+    octet T2 = {0, sizeof(t2), t2};
+    const char *T2line = "T2 = ";
+
+    octet *T[2] = {&T1, &T2};
+
+    char zero[EGS_SECP256K1];
+    octet ZERO = {0, sizeof(zero), zero};
+
+    // Line terminating a test vector
+    const char *last_line = T2line;
+
+    fp = fopen(argv[1], "r");
+    if (fp == NULL)
+    {
+        printf("ERROR opening test vector file\n");
+        exit(EXIT_FAILURE);
+    }
+
+    while (fgets(line, LINE_LEN, fp) != NULL)
+    {
+        scan_int(&testNo, line, TESTline);
+
+        // Read input
+        scan_OCTET(fp, &U1, line, U1line);
+        scan_OCTET(fp, &U2, line, U2line);
+        scan_OCTET(fp, &T1, line, T1line);
+        scan_OCTET(fp, &T2, line, T2line);
+
+        if (!strncmp(line, last_line, strlen(last_line)))
+        {
+            rc = MPC_PHASE5_verify(U, T);
+            sprintf(err_msg, "FAILURE MPC_PHASE5_verify. RC %d", rc);
+            assert_tv(fp, testNo, err_msg, rc == MPC_OK);
+
+            // Mark that at least one test vector was executed
+            test_run = 1;
+        }
+    }
+
+    fclose(fp);
+
+    if (test_run == 0)
+    {
+        printf("ERROR no test vector was executed\n");
+        exit(EXIT_FAILURE);
+    }
+
+    /* Test unhappy paths */
+
+    OCT_clear(&ZERO);
+    ZERO.len = ZERO.max;
+
+    // Invalid U[0]
+    U[0] = &ZERO;
+
+    rc = MPC_PHASE5_verify(U, T);
+    sprintf(err_msg, "FAILURE MPC_PHASE5_verify invalid U1. RC %d", rc);
+    assert_tv(fp, testNo, err_msg, rc == MPC_INVALID_ECP);
+
+    U[0] = &U1;
+
+    // Invalid U[1]
+    U[1] = &ZERO;
+
+    rc = MPC_PHASE5_verify(U, T);
+    sprintf(err_msg, "FAILURE MPC_PHASE5_verify invalid U2. RC %d", rc);
+    assert_tv(fp, testNo, err_msg, rc == MPC_INVALID_ECP);
+
+    U[1] = &U2;
+
+    // Invalid T[0]
+    T[0] = &ZERO;
+
+    rc = MPC_PHASE5_verify(U, T);
+    sprintf(err_msg, "FAILURE MPC_PHASE5_verify invalid T1. RC %d", rc);
+    assert_tv(fp, testNo, err_msg, rc == MPC_INVALID_ECP);
+
+    T[0] = &T1;
+
+    // Invalid T[1]
+    T[1] = &ZERO;
+
+    rc = MPC_PHASE5_verify(U, T);
+    sprintf(err_msg, "FAILURE MPC_PHASE5_verify invalid T2. RC %d", rc);
+    assert_tv(fp, testNo, err_msg, rc == MPC_INVALID_ECP);
+
+    T[1] = &T2;
+
+    // Invalid Proof
+    T[1] = T[0];
+
+    rc = MPC_PHASE5_verify(U, T);
+    sprintf(err_msg, "FAILURE MPC_PHASE5_verify invalid proof. RC %d", rc);
+    assert_tv(fp, testNo, err_msg, rc == MPC_FAIL);
+
+    printf("SUCCESS\n");
+    exit(EXIT_SUCCESS);
+}
diff --git a/testVectors/mpc/phase5_commit.json b/testVectors/mpc/phase5_commit.json
new file mode 100644
index 0000000..d4e53af
--- /dev/null
+++ b/testVectors/mpc/phase5_commit.json
@@ -0,0 +1,92 @@
+[
+  {
+    "TEST": 0,
+    "S": "e51b8e40c2ec54655e398e34f79d53038736b0fe7bc43bcb7576e1c2ea69ed0c",
+    "R": "02f666dd56143effb2ff8bd6a577bc0a737a95f6b19e155dd09f990d37b812ba72",
+    "PHI": "a119c5ec63b845317a4e333a0bbb4cb71ad41ee0b336ba896878a916c7da5c17",
+    "RHO": "ee4210e039334382e021991bfc5f459c2ff068e1b5be6f8411b75c07ddac2569",
+    "V1": "025c468de747a1108b5c58fe046cbca604767205eaa1cff74dae28fa65880cfde4",
+    "A1": "039c0085388bf852ce9755623393d96faa3995b3664ed7e156d68dfec9abf06c27"
+  },
+  {
+    "TEST": 1,
+    "S": "3194344513cf907fd8f899a99304c2fde6c6f8c7d29eb4159ba3d83020474edd",
+    "R": "02eb226fc5812bf1a51d426ca7958df8727da296438e5e4f5c717477bd4f0343de",
+    "PHI": "30966890d4f0c7cedf78aa74a7ccf68dd9afdcc7b7cfb5d960a0af1d661b48f6",
+    "RHO": "cc336a062316c18a78c501e887335c0cd9ef96164d931ec8d8fe6ce830685ef5",
+    "V1": "02c606d535292b81294d1331fd13d460f40c5f7682567b3a5ce574f4670e096f9f",
+    "A1": "029d66e1994e5bd735563514058386b5a8afc8ed83b3941a48961b1f00da406b18"
+  },
+  {
+    "TEST": 2,
+    "S": "f9dc1499de92142c078adba273e9aa9c5e54da81e4288a6ac13ee11dbde6cc7b",
+    "R": "0255e23064865c79f6a54e6208670848f8f3e3824985503b05c23e47d60e71f195",
+    "PHI": "c2f27ff77c939e55c463e25899f577464974d70c634ba0672d0f5efb2f5fa687",
+    "RHO": "c0bc20a6d6e91a64d523b8d7d3d6e4ed435d4a89654acf32784ef613c9c35bbc",
+    "V1": "03fc3fe34b51107b76629f593fcb48ab7a6c062c19e1c495df50996a43982ac4c4",
+    "A1": "034b5222a838098348bd658b863ce7e88369b6dea428f7511228e89561e1700cfd"
+  },
+  {
+    "TEST": 3,
+    "S": "78f7379bb01751c6933a568dbd8c868ca19a69519b3673910aecd43dca64902f",
+    "R": "02326c8a3c238a2982aa2d2fe644c10e274fb805fb281622373a6e9b7fc7502c12",
+    "PHI": "e4cfea43fce9c41d67b5ba62d12a3196bd5c6ec66d2352098b72f8b2434e64ce",
+    "RHO": "275e3922bb1f495b32101fe4cf591f00e9faeb882ab319719ad214767f98eb70",
+    "V1": "0272ce75ace35a4eeb416d5b2a240e2c74b542254b6a54e7364c29d9ee464c97dc",
+    "A1": "03fb1fa205064aa919b12a130eb68c7da0f93043e58cbaa77644be81feda4c5d60"
+  },
+  {
+    "TEST": 4,
+    "S": "bb0455894adaba0090823e281ca9847a22931306bb4fcdabd9c3fa205e84131e",
+    "R": "038c03cd239ef925e7f6041dbd7cc2e9692c1fcf0bc24b98897d6f908382b61888",
+    "PHI": "a59b7ad0c41b3e329415c766bb159dbf65e4cce4b5634f49af6994996d804001",
+    "RHO": "c25cce2544f8ac19ca07ca37d0a708f763c86ff7d8803fd179d9595b5978f815",
+    "V1": "02d2e39de79c01a8a420ca2c219a834e28b27765683b6b370c952a39cf56c35dcc",
+    "A1": "031b111341431dbcacf50e63f79e86b17cc96b19e01cb16fa81d3fb062f469adbb"
+  },
+  {
+    "TEST": 5,
+    "S": "5a82ba6fa60daacd7b83961baafd3ca8ed0522ed32e8f41c3ca42a929be3b180",
+    "R": "03e0318ef86d8dc50ef1bac489f555377c7d589644e12f0079735bb7afb8c556bc",
+    "PHI": "3f831fb0cbdc95e149cc3495a9e30fac14489c3f521f855f2a6a555d2befab60",
+    "RHO": "8faa2ef182458cafcaadd991b8f41ec6f4eb8f84872d8a8f553937dba4e7f1a4",
+    "V1": "033049c915878fa102950dd44e6beb08d2311ed208512a78c95f568ee2ca1386cf",
+    "A1": "026e53a32d27a3634bd7e93f70ed809fe902f227efabde0f9657c1edafa38323a5"
+  },
+  {
+    "TEST": 6,
+    "S": "f8ff36371d64a6f66eeb576b1de2eca7db0f5a9aa164ad5fd6f0cf79eb9f1d12",
+    "R": "0281a676e506b858a3c52f892436ef2bcebb6ee917a002e09c42117017b5a21744",
+    "PHI": "7b589d3b2756f6def4b02930069d64e25a814c13c801e46223908834eda9ef10",
+    "RHO": "4b5c5baae8574fcd0a46b7f1de754de5b1269752834a662d5feac4a4d7fda6c2",
+    "V1": "028a8512afffd786454b4ffcddd86f24dc34b9587e9b173ec2ddd328c5821a8ac3",
+    "A1": "020593f2dfac2af071f0ce42fc9bfa39cf57c1cf744c615abaff57c4ba2027b40d"
+  },
+  {
+    "TEST": 7,
+    "S": "839ea29f4f5627aeb5f9d3ca9902b1d346960ff3c747f3f9280632aad788b993",
+    "R": "0267559bd658b429403734bad273b113fbfcc6a600c959f48ad43cccda5e628e35",
+    "PHI": "9f19280d2ba8e63991ffbc8bbb35864c848774e9d0e88e22d25aab8cb7bf3786",
+    "RHO": "6dc19b5df395ef8f3bb3e9c079ed3d2ec5dbf776de46b4a2a37170faef987ddb",
+    "V1": "039b7396e35c9642678f296f842fb5ea4509cd70f8fcbafd473feb3cc0dd9ba059",
+    "A1": "03e765605f6785002cef2e1cade288f35417a790fe81d5dee665437d533256a1cf"
+  },
+  {
+    "TEST": 8,
+    "S": "b7b7a0b9e8a57ffcd4dc611c9d9097adf1e0793c1a2e519a7f3cfb579d84bc1c",
+    "R": "034948e1de149611af157dbb9e188b50734f0726e783c1db5d9dcf3b7159cd8313",
+    "PHI": "fcf4b149c1a1cab3ab06dbe50801a5ccbedc45aeff31e0f0760535081bfaac2d",
+    "RHO": "1039a703df08853f1b9e53fad2381f9b8a92e1c61f21c21195d7f549849b0937",
+    "V1": "0219946e7880117668c48c8f39b6457463a4774d73682dcba0cf03264ed97a72cd",
+    "A1": "02283ed21e357aa474f7b46cf59bdb275f05219ad0daa13c314c4fbf20f1f4f209"
+  },
+  {
+    "TEST": 9,
+    "S": "3e6c3213a3e62fec90b655692568a4d54e9d72eae1f1f8599a2cef0ada5eb028",
+    "R": "031623d89ae0a32372520da25fbf6c7f54fae42cb2205ed6960b00ab42511d5707",
+    "PHI": "cdd4163cfe3d8becc92b0a396d7d5a667ac54cf9354f1d55f7938b20feb43344",
+    "RHO": "f0a3a2d243cfa59065f7d1c6847cb6c317b703d46cecd198f196a40b8b73179b",
+    "V1": "03a93080b4cda427bd40844bd45ed993180216f2e4ed372172f605b5c66fe10810",
+    "A1": "02fcb444d9f100f591bbc5ba66399726205af26291215d927981aef7f4c0e2ddd6"
+  }
+]
\ No newline at end of file
diff --git a/testVectors/mpc/phase5_commit.txt b/testVectors/mpc/phase5_commit.txt
new file mode 100644
index 0000000..820e901
--- /dev/null
+++ b/testVectors/mpc/phase5_commit.txt
@@ -0,0 +1,80 @@
+TEST = 0,
+S = e51b8e40c2ec54655e398e34f79d53038736b0fe7bc43bcb7576e1c2ea69ed0c,
+R = 02f666dd56143effb2ff8bd6a577bc0a737a95f6b19e155dd09f990d37b812ba72,
+PHI = a119c5ec63b845317a4e333a0bbb4cb71ad41ee0b336ba896878a916c7da5c17,
+RHO = ee4210e039334382e021991bfc5f459c2ff068e1b5be6f8411b75c07ddac2569,
+V1 = 025c468de747a1108b5c58fe046cbca604767205eaa1cff74dae28fa65880cfde4,
+A1 = 039c0085388bf852ce9755623393d96faa3995b3664ed7e156d68dfec9abf06c27,
+
+TEST = 1,
+S = 3194344513cf907fd8f899a99304c2fde6c6f8c7d29eb4159ba3d83020474edd,
+R = 02eb226fc5812bf1a51d426ca7958df8727da296438e5e4f5c717477bd4f0343de,
+PHI = 30966890d4f0c7cedf78aa74a7ccf68dd9afdcc7b7cfb5d960a0af1d661b48f6,
+RHO = cc336a062316c18a78c501e887335c0cd9ef96164d931ec8d8fe6ce830685ef5,
+V1 = 02c606d535292b81294d1331fd13d460f40c5f7682567b3a5ce574f4670e096f9f,
+A1 = 029d66e1994e5bd735563514058386b5a8afc8ed83b3941a48961b1f00da406b18,
+
+TEST = 2,
+S = f9dc1499de92142c078adba273e9aa9c5e54da81e4288a6ac13ee11dbde6cc7b,
+R = 0255e23064865c79f6a54e6208670848f8f3e3824985503b05c23e47d60e71f195,
+PHI = c2f27ff77c939e55c463e25899f577464974d70c634ba0672d0f5efb2f5fa687,
+RHO = c0bc20a6d6e91a64d523b8d7d3d6e4ed435d4a89654acf32784ef613c9c35bbc,
+V1 = 03fc3fe34b51107b76629f593fcb48ab7a6c062c19e1c495df50996a43982ac4c4,
+A1 = 034b5222a838098348bd658b863ce7e88369b6dea428f7511228e89561e1700cfd,
+
+TEST = 3,
+S = 78f7379bb01751c6933a568dbd8c868ca19a69519b3673910aecd43dca64902f,
+R = 02326c8a3c238a2982aa2d2fe644c10e274fb805fb281622373a6e9b7fc7502c12,
+PHI = e4cfea43fce9c41d67b5ba62d12a3196bd5c6ec66d2352098b72f8b2434e64ce,
+RHO = 275e3922bb1f495b32101fe4cf591f00e9faeb882ab319719ad214767f98eb70,
+V1 = 0272ce75ace35a4eeb416d5b2a240e2c74b542254b6a54e7364c29d9ee464c97dc,
+A1 = 03fb1fa205064aa919b12a130eb68c7da0f93043e58cbaa77644be81feda4c5d60,
+
+TEST = 4,
+S = bb0455894adaba0090823e281ca9847a22931306bb4fcdabd9c3fa205e84131e,
+R = 038c03cd239ef925e7f6041dbd7cc2e9692c1fcf0bc24b98897d6f908382b61888,
+PHI = a59b7ad0c41b3e329415c766bb159dbf65e4cce4b5634f49af6994996d804001,
+RHO = c25cce2544f8ac19ca07ca37d0a708f763c86ff7d8803fd179d9595b5978f815,
+V1 = 02d2e39de79c01a8a420ca2c219a834e28b27765683b6b370c952a39cf56c35dcc,
+A1 = 031b111341431dbcacf50e63f79e86b17cc96b19e01cb16fa81d3fb062f469adbb,
+
+TEST = 5,
+S = 5a82ba6fa60daacd7b83961baafd3ca8ed0522ed32e8f41c3ca42a929be3b180,
+R = 03e0318ef86d8dc50ef1bac489f555377c7d589644e12f0079735bb7afb8c556bc,
+PHI = 3f831fb0cbdc95e149cc3495a9e30fac14489c3f521f855f2a6a555d2befab60,
+RHO = 8faa2ef182458cafcaadd991b8f41ec6f4eb8f84872d8a8f553937dba4e7f1a4,
+V1 = 033049c915878fa102950dd44e6beb08d2311ed208512a78c95f568ee2ca1386cf,
+A1 = 026e53a32d27a3634bd7e93f70ed809fe902f227efabde0f9657c1edafa38323a5,
+
+TEST = 6,
+S = f8ff36371d64a6f66eeb576b1de2eca7db0f5a9aa164ad5fd6f0cf79eb9f1d12,
+R = 0281a676e506b858a3c52f892436ef2bcebb6ee917a002e09c42117017b5a21744,
+PHI = 7b589d3b2756f6def4b02930069d64e25a814c13c801e46223908834eda9ef10,
+RHO = 4b5c5baae8574fcd0a46b7f1de754de5b1269752834a662d5feac4a4d7fda6c2,
+V1 = 028a8512afffd786454b4ffcddd86f24dc34b9587e9b173ec2ddd328c5821a8ac3,
+A1 = 020593f2dfac2af071f0ce42fc9bfa39cf57c1cf744c615abaff57c4ba2027b40d,
+
+TEST = 7,
+S = 839ea29f4f5627aeb5f9d3ca9902b1d346960ff3c747f3f9280632aad788b993,
+R = 0267559bd658b429403734bad273b113fbfcc6a600c959f48ad43cccda5e628e35,
+PHI = 9f19280d2ba8e63991ffbc8bbb35864c848774e9d0e88e22d25aab8cb7bf3786,
+RHO = 6dc19b5df395ef8f3bb3e9c079ed3d2ec5dbf776de46b4a2a37170faef987ddb,
+V1 = 039b7396e35c9642678f296f842fb5ea4509cd70f8fcbafd473feb3cc0dd9ba059,
+A1 = 03e765605f6785002cef2e1cade288f35417a790fe81d5dee665437d533256a1cf,
+
+TEST = 8,
+S = b7b7a0b9e8a57ffcd4dc611c9d9097adf1e0793c1a2e519a7f3cfb579d84bc1c,
+R = 034948e1de149611af157dbb9e188b50734f0726e783c1db5d9dcf3b7159cd8313,
+PHI = fcf4b149c1a1cab3ab06dbe50801a5ccbedc45aeff31e0f0760535081bfaac2d,
+RHO = 1039a703df08853f1b9e53fad2381f9b8a92e1c61f21c21195d7f549849b0937,
+V1 = 0219946e7880117668c48c8f39b6457463a4774d73682dcba0cf03264ed97a72cd,
+A1 = 02283ed21e357aa474f7b46cf59bdb275f05219ad0daa13c314c4fbf20f1f4f209,
+
+TEST = 9,
+S = 3e6c3213a3e62fec90b655692568a4d54e9d72eae1f1f8599a2cef0ada5eb028,
+R = 031623d89ae0a32372520da25fbf6c7f54fae42cb2205ed6960b00ab42511d5707,
+PHI = cdd4163cfe3d8becc92b0a396d7d5a667ac54cf9354f1d55f7938b20feb43344,
+RHO = f0a3a2d243cfa59065f7d1c6847cb6c317b703d46cecd198f196a40b8b73179b,
+V1 = 03a93080b4cda427bd40844bd45ed993180216f2e4ed372172f605b5c66fe10810,
+A1 = 02fcb444d9f100f591bbc5ba66399726205af26291215d927981aef7f4c0e2ddd6,
+
diff --git a/testVectors/mpc/phase5_prove.json b/testVectors/mpc/phase5_prove.json
new file mode 100644
index 0000000..b190cba
--- /dev/null
+++ b/testVectors/mpc/phase5_prove.json
@@ -0,0 +1,142 @@
+[
+  {
+    "TEST": 0,
+    "PHI": "42e9c17ded15a239981652376f587871860cea8ca80b600314dcd18f5e41f5e4",
+    "RHO": "60952570933cde980fca6d1c57ac4fa0ea72c3d7589eb06c2742b1e87925fc1f",
+    "V1": "0311241c85d737b3fdfc75f09d1168c1108b45fb98f3d2ad3e1f1dd8fec6da1cc6",
+    "V2": "02614a8d747ba485bef570099e6c1521baaedfc6eaba519f11dfc66f9c29942db0",
+    "A1": "029bcf3649d9c39e59d97670677dec4db91e7ae1cb438dac32afb9f98d66a70c2d",
+    "A2": "02f0e3aa5a7829d4d2ace5cc24d40af0e1d6409b4f948ca7c903da3858d6738915",
+    "PK": "020a8d50393669103474fd735586c6e6703ee767124ec06d8ff37e58b9b50ae357",
+    "M": "2d956cc45ebcbb5a69428c45482b11add5e4fe9ff86b9f22586a46707b51599d",
+    "RX": "7055a6caaefd7a40afaa6205ef6974cb7d948f5a33ffdea261d640eaaead27de",
+    "U1": "0310c82c83778a33410dfcb96eded135bb1217ff883fe76942d9fb6d7d29c33beb",
+    "T1": "03f0eb9a901fb930bbfd3f8531bbd43d1a238b5da26c3f4b865d6c41cd23690861"
+  },
+  {
+    "TEST": 1,
+    "PHI": "729c20f8762e01f26eef7f8c782f27a1d22fce57cb7ad511364b0b1adc8d8d15",
+    "RHO": "b75cbd1a48240ce610bba11d43cd8a877bfab77fe3fd1c6e9f1b76f66f82673d",
+    "V1": "0296b2e2b3f15b3b4097bd5f729d513cdae4f4e77a2bc2b74cb3eee9df92b08a53",
+    "V2": "03d9485f11eba4a4d7555ebc9b7fea8448ac76dfcafdd0251dd73f6ba9183f9f97",
+    "A1": "0377b9250db185312550172adff4bdf28d500edb93b045f7c09a1b4185f822eb2c",
+    "A2": "020d70ef5cb3ed3a39b267237825e328e4f16fb0f5c73635a0ccf78267fb831155",
+    "PK": "02f8485cfe45304209ede5aad54be3c33c0567e4285158900d3740ed1151095af2",
+    "M": "f48efdc380db92855fb87f3e100a5ec3192c941556c686b4071a2b66c21ab4e7",
+    "RX": "74a9d4a49613d0cda02d2d572e33787ef8d7b6102407e3648d82aaaae6830ad4",
+    "U1": "023b5bb086e17cf024b4aef5f64cded02c8d58e82dc0b81ca0280dbdab173f7337",
+    "T1": "033b0956620dfd80151e1b311c68296ca416b26a6dcaf17f758f61843fa7f20cca"
+  },
+  {
+    "TEST": 2,
+    "PHI": "4127f3f6854cccd081dac8363f4ca0ed59a6639ddabdd433f3e4bc15768624b7",
+    "RHO": "a58fa6b1939df7b712f2b6df8e9a6e8b5c604274a7e03749e96ee279ac45d16d",
+    "V1": "0324175baf9428de563820db7d6c3d139d9fbd198a701547c11ca54299af537deb",
+    "V2": "03afb4f0dc4842f7f978d866eee5ef05f8dc681e9ff944e39da9ae3431c2d562fe",
+    "A1": "03f999552e871536ad210796d754e93629a87b428ed59945ae1ebf5da012e97c82",
+    "A2": "03910b1d544336770d9a645ebdc5e416890f7a41ee8b65434d50a12e3b5bf618e7",
+    "PK": "0217e6c5058381f34c516f3327ef1d851d1c8fd2cd499c00502f3a0647d670ca5f",
+    "M": "ebc5c6fe5601f1b6910bf144f569cb4322ca9b35ace2197ebde565b3c0dd64f6",
+    "RX": "4d08976f1da7995e5cd8b493821d00921f8f55d95cac211404e4bc86642c112d",
+    "U1": "0223494dfa62fcd7160cb1b12aeda7511b1528bc69bd696b2226fee5152e8c2b94",
+    "T1": "02b9f3113642ea74c3059cae319b780b53a6f3d436552ac31c739908748420a068"
+  },
+  {
+    "TEST": 3,
+    "PHI": "9c50ec01024c7c80a54a6c16087042ed30dd45d1f418b0a53208bae83af056b5",
+    "RHO": "1f95b5145891fe4f166a520505562e02c1e89acf9430f1d4cb33220b6380ef38",
+    "V1": "0200d8ec18cd5ef909f7165fd597cc31acea5373ab559cba0412af6243e8dd99b6",
+    "V2": "039019343f99cd010fe48dd49e1cf0b1e40c4c5e6bad2b515e372f595318492578",
+    "A1": "027f4201b87630b3b075ec58770ee0062660b8dda5ab8cd814b012e3b0c42b8b6a",
+    "A2": "02cf23ba26f71335d1172bf81a237e39ec91af9a06eba84d553355c0e51117face",
+    "PK": "03e071ed02c27c2c34ef68f41e95faa5f6c6a89e74ba8a9d611db5bcc46a84627c",
+    "M": "7ddf90b23c2008e0aa1577a9841e94f2482eaeb19d74208514900a2c179401d6",
+    "RX": "8c18321da2cfa9f5bc1ad17c6b8047f14d87f20fa76fba8aac9f1347b7aab500",
+    "U1": "02a18d5cf7539c6cc684cd6d568f4e7d5a320f0216013e0ced2976e0b69f2b344a",
+    "T1": "024dd37fdfd8efe1d1c5a215b36db61fbd453c0d0e4c00de9198f2b4312975c02e"
+  },
+  {
+    "TEST": 4,
+    "PHI": "f79f1fcf203eb2874c5b436faaf07e4081baeb80ad3b9463107d037f63da0772",
+    "RHO": "4ed51dbdf41e52cae2c47cc480d74222cbf7649ae1a0d3edc340cacb326e3015",
+    "V1": "03c0150ef36692f13fed6487830be2e14d3ceb6cfa220bbc17a9142818ff3d1bf7",
+    "V2": "02f67cb06b73713f0b504a7f2367bc02d26a23e8b7a1ab06da4a584c9c43176aab",
+    "A1": "03c43e32a19af3b48a6ecf73f0fbabc300f8aae821f1fb4304bff40e47c68752d8",
+    "A2": "030f45a6cde8393127d9d491cf3f3a8055e64e521fd38238abf8fbadd907624a22",
+    "PK": "03e1dfa7cf66d2a8c61914030e1fcd4e23b1a3c829068d760a08e95747d23452f1",
+    "M": "cbbaff45d6808bde1886f5c95691aa2817f5a1e1eb19f5ab3c452fedb5aba216",
+    "RX": "9f08a5b179c29f3e8f73333c43c3f3e2760bc6ec9e2653900a420389fbf13571",
+    "U1": "02d87ae8ec1e60079d17b404ef7e7523563132349ed42820e6cbbbcda233dcb798",
+    "T1": "02db5d5856d65a24bfc9ad9db3647eb850d46af66be01dfa7b968cd65cc94b0f19"
+  },
+  {
+    "TEST": 5,
+    "PHI": "7c4da9e90e93a41e814230b20d65a793c6f66b20f7994f16e82e169d6fe93d1a",
+    "RHO": "051d3e656d9f8cfaee6a2d2bb91cb5d1e7b5001087d96fdc63bfa140a848c0e3",
+    "V1": "03c710231600d8b836f17e7b66802f1c1cefbe5b9846337112b03416c9010cb211",
+    "V2": "033cfe84a39bee0c6248b83ed1c12602933560272523812619c9687cbfc8b38040",
+    "A1": "02be99432a6d6cf87efd4323d76662a6924abc2acdd19222928471c7db8ca3e786",
+    "A2": "026da0a9086ead6b0555807cba09d0f93f1788305268ba5dab52bf9b0790cd43c0",
+    "PK": "02771aa3cf848cd12d533108350a5622cfc69298dffc26b438b5c3be760ea4562a",
+    "M": "569d753c4e677b6500541eb0fe705d6f500bff0d2da82d69f6fa89bd33b20115",
+    "RX": "777b142a8000117fca16506bf55c9b64e75af33b5550635e710ccc1db24fa192",
+    "U1": "0272bc0065ab1412d9f75ba9e7d135c7a09f62e8085b202d9037773e78c2b03c58",
+    "T1": "022aa5a3e74856e51b214a4a2587f1ff2b511875e82606bd57c23bdfa82a4005ce"
+  },
+  {
+    "TEST": 6,
+    "PHI": "25c6a0bb417d43c190de60a89e8d3eb14aa687f73ce3d0fe9e99073c667de395",
+    "RHO": "cdfa30a33b2948ec78b930b56ab80745424216f45fee07a53d2b1f3e5af7b475",
+    "V1": "0380e58804318fea8bbb5f2f65ebed3269f7010ac332afba7b3cf6942ac5d54c59",
+    "V2": "036c850b7ba9c00d7c605ee701e542a964eae189dfffc2b123b4d91b94fc917960",
+    "A1": "027403fa494a270057a477fd839760781e9eda2501998699b5af3b7b6ab2d10f1a",
+    "A2": "02cc354b44f8ce3e243cbf52dbaa89ff812ad91075c1d6473ebaf7607f24ad708a",
+    "PK": "0241f39b4993df0135146f71264ef05fc8e50ef19b8a8f05ab30b64863f2089061",
+    "M": "212c526c724b5872abc31a96135bb32ac300ed15b6772aa7506da32c780a0ba6",
+    "RX": "07ee12ae99ff2c1d62152a4ccf6d4c9d8270f9b9400e18380156f1f654ab96aa",
+    "U1": "038008bcd53f72c44e4986afc2b6422e8ac476ad9c78299be3b5c5e16bebaa0756",
+    "T1": "02e2587847318f43343d179ca5169daccd46e7f8686b743024375b5f99ff013d0c"
+  },
+  {
+    "TEST": 7,
+    "PHI": "f8b1bac1540010c5d9184e69144b2be7b65580711d2d31e8b1e38612878b9501",
+    "RHO": "084493c8d744e521570121ba0780d7eba459d83321b7c394cfb8f4ca06291984",
+    "V1": "038df7263f8e31351f32e9419bf8b61768238d051a98fd24a36eb4399f58b203d9",
+    "V2": "03b5fa35fd4725793fd891cbf14d1ad32f68fe8f0ccf9d35ea5ea51fbbff54bf45",
+    "A1": "024175c2e490f9760cc554323f3703839b9642a0afb71ff98f7b6857f2d62a6d1f",
+    "A2": "0297c770c6a5bd3a40a0d5e08a609b4437fe3a416e00ede47208f1820754c995de",
+    "PK": "02082187a353888872e5ce0a000988902473641e862b2c7cb56ba28ac57514edb9",
+    "M": "1ac6bde86b7b86caa709fdafc829d064a926d18a71b36f47cebd8321eda3efee",
+    "RX": "bbedbb0e02e74af6ae4c075c7ac7631de2e21ed310e9e00fa0ab0459e96497a0",
+    "U1": "03cba7f3122a524727b0fccc43cad0b355f821e92b13e6bf3aea465ee34a5a4a46",
+    "T1": "0289c48adcd2a94cc8d078423a895cbaeed18fff4db412264be756766cabbbab16"
+  },
+  {
+    "TEST": 8,
+    "PHI": "d1036f6a337d54fa70e5c939930d4f7b1f24dab01d28d145ea05c7b9b1263bd0",
+    "RHO": "1386ab80c60f36c189ac425811cb8e05c8505b0150ee781e5497cffe2dd2af9e",
+    "V1": "02fe9966c1b7a00359d509e641674932f8bb8a504480ad1f3ce6e3aaadbf6001eb",
+    "V2": "0310693e4782cbbb6ba1e6cd280cbf4901ba332473670ce3c594dd5b061b934efd",
+    "A1": "03a7cb39bfa6055e6c9fea90ebd7c61c9bba05ceb447b169802c265732f65cf6c5",
+    "A2": "031625d142fffe3896c47dc8ff0a22884c6353b96b51a2487526894dc24926d80b",
+    "PK": "024eabcc12a2b906b28ce6ce23c484815a551640038974092485068daf42354693",
+    "M": "7ee4018d7eb57e41630c13b8df4d92baaae783af4eb1a7d8df8163ef1e7ddb5b",
+    "RX": "7a07d53b20e3eb641d0f61a5d76dc385b180de95e431656546889918b8ed71e2",
+    "U1": "02f19a1ec7352bef71ff248ab5cbe45848c8e84f6c2cb047e1181ae9573eb449e0",
+    "T1": "021d9f8945799367f5795eb88623af8f899e70055d8a679aaaa0102d53dca55c9c"
+  },
+  {
+    "TEST": 9,
+    "PHI": "59bbdcf49e8e90a3f625ebc8574baa35ddc41f7800be71920db230e5b790c464",
+    "RHO": "cb41f82b44346b8fa51c05076089cebb937882d2fc77c2a395cb878da4cac558",
+    "V1": "025e39e199f14e9b48abfa549cb6fd68cf902a19f9762a400bb317524d2fc6edcd",
+    "V2": "02f2a908a179a4db10429a12e2ca003342dcb18430c56b1e776a86dec8c598293f",
+    "A1": "03e8684a5693a32f985fbbab6b3250f2c76b558c085f6639bea9e09b5f08f8b829",
+    "A2": "031e667f6984040fa4927e365c45c94c5bc93a54504f7a75412438a8ae29f92f0c",
+    "PK": "029f9e6e7fda7c4fe7c68f1069a093a08600670dc0a05f38bc16c46ffd5d67ac4d",
+    "M": "4b7df9714ecf795cfd698129a6f5250cfb64b739ad163da2da93c728c3bd19be",
+    "RX": "2017c881a593aa3ef98fec5e0b4ad24744ca33bc95490d8eec2e7992333e461a",
+    "U1": "0393de7621eb5fb37edc7364458f8013daecb02c94cc64228ff13984a237ccdd79",
+    "T1": "0267d92ec5c353dd939f527a74a8b1444d0be24e9e3585e490388e2e85a3102d3a"
+  }
+]
\ No newline at end of file
diff --git a/testVectors/mpc/phase5_prove.txt b/testVectors/mpc/phase5_prove.txt
new file mode 100644
index 0000000..a83dad4
--- /dev/null
+++ b/testVectors/mpc/phase5_prove.txt
@@ -0,0 +1,130 @@
+TEST = 0,
+PHI = 42e9c17ded15a239981652376f587871860cea8ca80b600314dcd18f5e41f5e4,
+RHO = 60952570933cde980fca6d1c57ac4fa0ea72c3d7589eb06c2742b1e87925fc1f,
+V1 = 0311241c85d737b3fdfc75f09d1168c1108b45fb98f3d2ad3e1f1dd8fec6da1cc6,
+V2 = 02614a8d747ba485bef570099e6c1521baaedfc6eaba519f11dfc66f9c29942db0,
+A1 = 029bcf3649d9c39e59d97670677dec4db91e7ae1cb438dac32afb9f98d66a70c2d,
+A2 = 02f0e3aa5a7829d4d2ace5cc24d40af0e1d6409b4f948ca7c903da3858d6738915,
+PK = 020a8d50393669103474fd735586c6e6703ee767124ec06d8ff37e58b9b50ae357,
+M = 2d956cc45ebcbb5a69428c45482b11add5e4fe9ff86b9f22586a46707b51599d,
+RX = 7055a6caaefd7a40afaa6205ef6974cb7d948f5a33ffdea261d640eaaead27de,
+U1 = 0310c82c83778a33410dfcb96eded135bb1217ff883fe76942d9fb6d7d29c33beb,
+T1 = 03f0eb9a901fb930bbfd3f8531bbd43d1a238b5da26c3f4b865d6c41cd23690861,
+
+TEST = 1,
+PHI = 729c20f8762e01f26eef7f8c782f27a1d22fce57cb7ad511364b0b1adc8d8d15,
+RHO = b75cbd1a48240ce610bba11d43cd8a877bfab77fe3fd1c6e9f1b76f66f82673d,
+V1 = 0296b2e2b3f15b3b4097bd5f729d513cdae4f4e77a2bc2b74cb3eee9df92b08a53,
+V2 = 03d9485f11eba4a4d7555ebc9b7fea8448ac76dfcafdd0251dd73f6ba9183f9f97,
+A1 = 0377b9250db185312550172adff4bdf28d500edb93b045f7c09a1b4185f822eb2c,
+A2 = 020d70ef5cb3ed3a39b267237825e328e4f16fb0f5c73635a0ccf78267fb831155,
+PK = 02f8485cfe45304209ede5aad54be3c33c0567e4285158900d3740ed1151095af2,
+M = f48efdc380db92855fb87f3e100a5ec3192c941556c686b4071a2b66c21ab4e7,
+RX = 74a9d4a49613d0cda02d2d572e33787ef8d7b6102407e3648d82aaaae6830ad4,
+U1 = 023b5bb086e17cf024b4aef5f64cded02c8d58e82dc0b81ca0280dbdab173f7337,
+T1 = 033b0956620dfd80151e1b311c68296ca416b26a6dcaf17f758f61843fa7f20cca,
+
+TEST = 2,
+PHI = 4127f3f6854cccd081dac8363f4ca0ed59a6639ddabdd433f3e4bc15768624b7,
+RHO = a58fa6b1939df7b712f2b6df8e9a6e8b5c604274a7e03749e96ee279ac45d16d,
+V1 = 0324175baf9428de563820db7d6c3d139d9fbd198a701547c11ca54299af537deb,
+V2 = 03afb4f0dc4842f7f978d866eee5ef05f8dc681e9ff944e39da9ae3431c2d562fe,
+A1 = 03f999552e871536ad210796d754e93629a87b428ed59945ae1ebf5da012e97c82,
+A2 = 03910b1d544336770d9a645ebdc5e416890f7a41ee8b65434d50a12e3b5bf618e7,
+PK = 0217e6c5058381f34c516f3327ef1d851d1c8fd2cd499c00502f3a0647d670ca5f,
+M = ebc5c6fe5601f1b6910bf144f569cb4322ca9b35ace2197ebde565b3c0dd64f6,
+RX = 4d08976f1da7995e5cd8b493821d00921f8f55d95cac211404e4bc86642c112d,
+U1 = 0223494dfa62fcd7160cb1b12aeda7511b1528bc69bd696b2226fee5152e8c2b94,
+T1 = 02b9f3113642ea74c3059cae319b780b53a6f3d436552ac31c739908748420a068,
+
+TEST = 3,
+PHI = 9c50ec01024c7c80a54a6c16087042ed30dd45d1f418b0a53208bae83af056b5,
+RHO = 1f95b5145891fe4f166a520505562e02c1e89acf9430f1d4cb33220b6380ef38,
+V1 = 0200d8ec18cd5ef909f7165fd597cc31acea5373ab559cba0412af6243e8dd99b6,
+V2 = 039019343f99cd010fe48dd49e1cf0b1e40c4c5e6bad2b515e372f595318492578,
+A1 = 027f4201b87630b3b075ec58770ee0062660b8dda5ab8cd814b012e3b0c42b8b6a,
+A2 = 02cf23ba26f71335d1172bf81a237e39ec91af9a06eba84d553355c0e51117face,
+PK = 03e071ed02c27c2c34ef68f41e95faa5f6c6a89e74ba8a9d611db5bcc46a84627c,
+M = 7ddf90b23c2008e0aa1577a9841e94f2482eaeb19d74208514900a2c179401d6,
+RX = 8c18321da2cfa9f5bc1ad17c6b8047f14d87f20fa76fba8aac9f1347b7aab500,
+U1 = 02a18d5cf7539c6cc684cd6d568f4e7d5a320f0216013e0ced2976e0b69f2b344a,
+T1 = 024dd37fdfd8efe1d1c5a215b36db61fbd453c0d0e4c00de9198f2b4312975c02e,
+
+TEST = 4,
+PHI = f79f1fcf203eb2874c5b436faaf07e4081baeb80ad3b9463107d037f63da0772,
+RHO = 4ed51dbdf41e52cae2c47cc480d74222cbf7649ae1a0d3edc340cacb326e3015,
+V1 = 03c0150ef36692f13fed6487830be2e14d3ceb6cfa220bbc17a9142818ff3d1bf7,
+V2 = 02f67cb06b73713f0b504a7f2367bc02d26a23e8b7a1ab06da4a584c9c43176aab,
+A1 = 03c43e32a19af3b48a6ecf73f0fbabc300f8aae821f1fb4304bff40e47c68752d8,
+A2 = 030f45a6cde8393127d9d491cf3f3a8055e64e521fd38238abf8fbadd907624a22,
+PK = 03e1dfa7cf66d2a8c61914030e1fcd4e23b1a3c829068d760a08e95747d23452f1,
+M = cbbaff45d6808bde1886f5c95691aa2817f5a1e1eb19f5ab3c452fedb5aba216,
+RX = 9f08a5b179c29f3e8f73333c43c3f3e2760bc6ec9e2653900a420389fbf13571,
+U1 = 02d87ae8ec1e60079d17b404ef7e7523563132349ed42820e6cbbbcda233dcb798,
+T1 = 02db5d5856d65a24bfc9ad9db3647eb850d46af66be01dfa7b968cd65cc94b0f19,
+
+TEST = 5,
+PHI = 7c4da9e90e93a41e814230b20d65a793c6f66b20f7994f16e82e169d6fe93d1a,
+RHO = 051d3e656d9f8cfaee6a2d2bb91cb5d1e7b5001087d96fdc63bfa140a848c0e3,
+V1 = 03c710231600d8b836f17e7b66802f1c1cefbe5b9846337112b03416c9010cb211,
+V2 = 033cfe84a39bee0c6248b83ed1c12602933560272523812619c9687cbfc8b38040,
+A1 = 02be99432a6d6cf87efd4323d76662a6924abc2acdd19222928471c7db8ca3e786,
+A2 = 026da0a9086ead6b0555807cba09d0f93f1788305268ba5dab52bf9b0790cd43c0,
+PK = 02771aa3cf848cd12d533108350a5622cfc69298dffc26b438b5c3be760ea4562a,
+M = 569d753c4e677b6500541eb0fe705d6f500bff0d2da82d69f6fa89bd33b20115,
+RX = 777b142a8000117fca16506bf55c9b64e75af33b5550635e710ccc1db24fa192,
+U1 = 0272bc0065ab1412d9f75ba9e7d135c7a09f62e8085b202d9037773e78c2b03c58,
+T1 = 022aa5a3e74856e51b214a4a2587f1ff2b511875e82606bd57c23bdfa82a4005ce,
+
+TEST = 6,
+PHI = 25c6a0bb417d43c190de60a89e8d3eb14aa687f73ce3d0fe9e99073c667de395,
+RHO = cdfa30a33b2948ec78b930b56ab80745424216f45fee07a53d2b1f3e5af7b475,
+V1 = 0380e58804318fea8bbb5f2f65ebed3269f7010ac332afba7b3cf6942ac5d54c59,
+V2 = 036c850b7ba9c00d7c605ee701e542a964eae189dfffc2b123b4d91b94fc917960,
+A1 = 027403fa494a270057a477fd839760781e9eda2501998699b5af3b7b6ab2d10f1a,
+A2 = 02cc354b44f8ce3e243cbf52dbaa89ff812ad91075c1d6473ebaf7607f24ad708a,
+PK = 0241f39b4993df0135146f71264ef05fc8e50ef19b8a8f05ab30b64863f2089061,
+M = 212c526c724b5872abc31a96135bb32ac300ed15b6772aa7506da32c780a0ba6,
+RX = 07ee12ae99ff2c1d62152a4ccf6d4c9d8270f9b9400e18380156f1f654ab96aa,
+U1 = 038008bcd53f72c44e4986afc2b6422e8ac476ad9c78299be3b5c5e16bebaa0756,
+T1 = 02e2587847318f43343d179ca5169daccd46e7f8686b743024375b5f99ff013d0c,
+
+TEST = 7,
+PHI = f8b1bac1540010c5d9184e69144b2be7b65580711d2d31e8b1e38612878b9501,
+RHO = 084493c8d744e521570121ba0780d7eba459d83321b7c394cfb8f4ca06291984,
+V1 = 038df7263f8e31351f32e9419bf8b61768238d051a98fd24a36eb4399f58b203d9,
+V2 = 03b5fa35fd4725793fd891cbf14d1ad32f68fe8f0ccf9d35ea5ea51fbbff54bf45,
+A1 = 024175c2e490f9760cc554323f3703839b9642a0afb71ff98f7b6857f2d62a6d1f,
+A2 = 0297c770c6a5bd3a40a0d5e08a609b4437fe3a416e00ede47208f1820754c995de,
+PK = 02082187a353888872e5ce0a000988902473641e862b2c7cb56ba28ac57514edb9,
+M = 1ac6bde86b7b86caa709fdafc829d064a926d18a71b36f47cebd8321eda3efee,
+RX = bbedbb0e02e74af6ae4c075c7ac7631de2e21ed310e9e00fa0ab0459e96497a0,
+U1 = 03cba7f3122a524727b0fccc43cad0b355f821e92b13e6bf3aea465ee34a5a4a46,
+T1 = 0289c48adcd2a94cc8d078423a895cbaeed18fff4db412264be756766cabbbab16,
+
+TEST = 8,
+PHI = d1036f6a337d54fa70e5c939930d4f7b1f24dab01d28d145ea05c7b9b1263bd0,
+RHO = 1386ab80c60f36c189ac425811cb8e05c8505b0150ee781e5497cffe2dd2af9e,
+V1 = 02fe9966c1b7a00359d509e641674932f8bb8a504480ad1f3ce6e3aaadbf6001eb,
+V2 = 0310693e4782cbbb6ba1e6cd280cbf4901ba332473670ce3c594dd5b061b934efd,
+A1 = 03a7cb39bfa6055e6c9fea90ebd7c61c9bba05ceb447b169802c265732f65cf6c5,
+A2 = 031625d142fffe3896c47dc8ff0a22884c6353b96b51a2487526894dc24926d80b,
+PK = 024eabcc12a2b906b28ce6ce23c484815a551640038974092485068daf42354693,
+M = 7ee4018d7eb57e41630c13b8df4d92baaae783af4eb1a7d8df8163ef1e7ddb5b,
+RX = 7a07d53b20e3eb641d0f61a5d76dc385b180de95e431656546889918b8ed71e2,
+U1 = 02f19a1ec7352bef71ff248ab5cbe45848c8e84f6c2cb047e1181ae9573eb449e0,
+T1 = 021d9f8945799367f5795eb88623af8f899e70055d8a679aaaa0102d53dca55c9c,
+
+TEST = 9,
+PHI = 59bbdcf49e8e90a3f625ebc8574baa35ddc41f7800be71920db230e5b790c464,
+RHO = cb41f82b44346b8fa51c05076089cebb937882d2fc77c2a395cb878da4cac558,
+V1 = 025e39e199f14e9b48abfa549cb6fd68cf902a19f9762a400bb317524d2fc6edcd,
+V2 = 02f2a908a179a4db10429a12e2ca003342dcb18430c56b1e776a86dec8c598293f,
+A1 = 03e8684a5693a32f985fbbab6b3250f2c76b558c085f6639bea9e09b5f08f8b829,
+A2 = 031e667f6984040fa4927e365c45c94c5bc93a54504f7a75412438a8ae29f92f0c,
+PK = 029f9e6e7fda7c4fe7c68f1069a093a08600670dc0a05f38bc16c46ffd5d67ac4d,
+M = 4b7df9714ecf795cfd698129a6f5250cfb64b739ad163da2da93c728c3bd19be,
+RX = 2017c881a593aa3ef98fec5e0b4ad24744ca33bc95490d8eec2e7992333e461a,
+U1 = 0393de7621eb5fb37edc7364458f8013daecb02c94cc64228ff13984a237ccdd79,
+T1 = 0267d92ec5c353dd939f527a74a8b1444d0be24e9e3585e490388e2e85a3102d3a,
+
diff --git a/testVectors/mpc/phase5_verify.json b/testVectors/mpc/phase5_verify.json
new file mode 100644
index 0000000..460764b
--- /dev/null
+++ b/testVectors/mpc/phase5_verify.json
@@ -0,0 +1,72 @@
+[
+  {
+    "TEST": 0,
+    "U1": "033f5da68af578469bab4c409a8a8605a4f0d75472d2346c54fc89f9468cfb6465",
+    "U2": "03832fb219980425f747e169537b4d0cb46e575f4396d4839d1bc70cc838becbc7",
+    "T1": "02467f3bebda11b2994ba002fec57774b4364377f2ac5f5ee97ae01cf5fef0b7ce",
+    "T2": "0202030a3b5bf5a0fa12ee2cdaf9753dec7a7a97bb86517d48cab86851f70a2322"
+  },
+  {
+    "TEST": 1,
+    "U1": "0216e4bb925115e198d8cbefa17bb881138139a4624d86b4e9131661e9ff10f297",
+    "U2": "03eee119aaa561be664e78cfc421422533342bc8655402243285d9b2528bdbe0fd",
+    "T1": "0255726c57f1e68b3b264acd445ef883eb8857ea3a2c585744c198158e981cac13",
+    "T2": "03c2aa2ed3040ba2730d41f50353f248cfe56f11081d6180ab4e3ed95c32f8ec9e"
+  },
+  {
+    "TEST": 2,
+    "U1": "0270930f61082c7466ac19214fda624be1b6316873ae6a167043b0c05cdc41386b",
+    "U2": "03b51a351a3d92e1cb07b6a43a18f1461af010d2a7de82f52b1c54cf22241da80d",
+    "T1": "03f072217716e9e29965b268dc336a1dfd047c195f1d716e8e0f659f679d80fd23",
+    "T2": "0225c528beeda5ba01e910b845979619f6e8ca40b27b547dd95b993dea27e04f8c"
+  },
+  {
+    "TEST": 3,
+    "U1": "0369c543585c9e12adb57b66c83c0f0e9a04a4f1fc5d5f216e36fbf1189768ff08",
+    "U2": "02f4a4c14d5b5d94b5196f38b45981c828f88045bb6371956a5d3d693c4e941d99",
+    "T1": "0300602208edd919ae02bd3e655ac4486b0448dcfec4bc715edbe055f1e1dcb0bb",
+    "T2": "03860d7e358f35e3b6fa974cbd5e9c6eee72e8722158773b2e067ecbb37d5c6f1f"
+  },
+  {
+    "TEST": 4,
+    "U1": "02cc71e4d1f81732a8f176018c7fe2cab174ac5589a46c7c5cddc3b92a8cacea58",
+    "U2": "02494af6fd578089b56ed19c44d223453026d28b338d942dbe32ed2691d843ae4f",
+    "T1": "02467aeb6b18ca05c6ae37c53cf9d84c9ed45e0dcfa2c6c3756331465ab43df72b",
+    "T2": "038a031d20e15dd8773143de94f0fa756ec8391fe6f930d43264260874ec0dfcca"
+  },
+  {
+    "TEST": 5,
+    "U1": "0232e33ac5577de12a6560179f763773a3fa771be0e1359be07b5f46c39230e2fb",
+    "U2": "032dfd613face20d59f33c07288d43fec86043aec211e3999966832a6b3d33c19b",
+    "T1": "02e6ecd68c55d7d546de373a2e702eab6f6249666166acf0b06ea369f16f60b04c",
+    "T2": "0206e50c4de02cf149b2b2393f29e02657bcfee165b28dde8043f7a7c510dfff48"
+  },
+  {
+    "TEST": 6,
+    "U1": "0246073f99b3c5c6f3022a53abf7ce6aaf4bd2c1424e8bb12f8a3d5dde5a2683cf",
+    "U2": "0357c6ad172eeb617d71b1f526303ac440eba6ebc2107528209377aa8c6b94494e",
+    "T1": "03524485e619276c5181b5a42d2a7a9b60ec32c0d9347f2960593985f14d1ca1a2",
+    "T2": "026203b02875471607bf3f709534d69e429566788e3a4a0b1ad1f5ad043b3f89fb"
+  },
+  {
+    "TEST": 7,
+    "U1": "026677976aff8866137e6118ddc6df9fef579e10e89d0fb524dffb5ed6f5a94370",
+    "U2": "02c198953702562f1a4c9e64d89b30beaad5ff07d9b1d1d3deac6b2203d359c537",
+    "T1": "0261bbfc24f2abe1a2db8f4c58cce99cdd98094675fc0b041240a5dec0f0dd4ae7",
+    "T2": "022d8229188b6ee201076de07412786ef17b0a179f0ecbbf98154eee98453fc9b8"
+  },
+  {
+    "TEST": 8,
+    "U1": "02691f1531d286c6ec16412c9f5c4354f70d1379bc89e1b74c0308e6b4f57fe591",
+    "U2": "031d181876c0f3c50717b33594a6a6796983dcfea44911c513603ec6cfc060ff63",
+    "T1": "03bbca24e57c42ab254a8f72c7cac20ccf1e0e10b93a160170ac2f103f74ed03ab",
+    "T2": "0315f0b3d52268ddb004ab06bb95a04251f504667be728beb83bb4f5b9b4b914a3"
+  },
+  {
+    "TEST": 9,
+    "U1": "03262fe60ab36974694625b3cfe30db36795366b585b0ba17689075dce2c9eeef4",
+    "U2": "0396277938940d825483b8d7be3e31c6c9d12b02f26089885fa6935756a3ad4a76",
+    "T1": "03da3bb1e00b5cc87ef9d7b338b4d5c7c44cd835a93cb446ccfa6cabae7e505553",
+    "T2": "02d6b9b7fca510b0cfb8cbf001e265b1a7866a68be40fdf659accae5d703ff65f2"
+  }
+]
\ No newline at end of file
diff --git a/testVectors/mpc/phase5_verify.txt b/testVectors/mpc/phase5_verify.txt
new file mode 100644
index 0000000..2380ad6
--- /dev/null
+++ b/testVectors/mpc/phase5_verify.txt
@@ -0,0 +1,60 @@
+TEST = 0,
+U1 = 033f5da68af578469bab4c409a8a8605a4f0d75472d2346c54fc89f9468cfb6465,
+U2 = 03832fb219980425f747e169537b4d0cb46e575f4396d4839d1bc70cc838becbc7,
+T1 = 02467f3bebda11b2994ba002fec57774b4364377f2ac5f5ee97ae01cf5fef0b7ce,
+T2 = 0202030a3b5bf5a0fa12ee2cdaf9753dec7a7a97bb86517d48cab86851f70a2322,
+
+TEST = 1,
+U1 = 0216e4bb925115e198d8cbefa17bb881138139a4624d86b4e9131661e9ff10f297,
+U2 = 03eee119aaa561be664e78cfc421422533342bc8655402243285d9b2528bdbe0fd,
+T1 = 0255726c57f1e68b3b264acd445ef883eb8857ea3a2c585744c198158e981cac13,
+T2 = 03c2aa2ed3040ba2730d41f50353f248cfe56f11081d6180ab4e3ed95c32f8ec9e,
+
+TEST = 2,
+U1 = 0270930f61082c7466ac19214fda624be1b6316873ae6a167043b0c05cdc41386b,
+U2 = 03b51a351a3d92e1cb07b6a43a18f1461af010d2a7de82f52b1c54cf22241da80d,
+T1 = 03f072217716e9e29965b268dc336a1dfd047c195f1d716e8e0f659f679d80fd23,
+T2 = 0225c528beeda5ba01e910b845979619f6e8ca40b27b547dd95b993dea27e04f8c,
+
+TEST = 3,
+U1 = 0369c543585c9e12adb57b66c83c0f0e9a04a4f1fc5d5f216e36fbf1189768ff08,
+U2 = 02f4a4c14d5b5d94b5196f38b45981c828f88045bb6371956a5d3d693c4e941d99,
+T1 = 0300602208edd919ae02bd3e655ac4486b0448dcfec4bc715edbe055f1e1dcb0bb,
+T2 = 03860d7e358f35e3b6fa974cbd5e9c6eee72e8722158773b2e067ecbb37d5c6f1f,
+
+TEST = 4,
+U1 = 02cc71e4d1f81732a8f176018c7fe2cab174ac5589a46c7c5cddc3b92a8cacea58,
+U2 = 02494af6fd578089b56ed19c44d223453026d28b338d942dbe32ed2691d843ae4f,
+T1 = 02467aeb6b18ca05c6ae37c53cf9d84c9ed45e0dcfa2c6c3756331465ab43df72b,
+T2 = 038a031d20e15dd8773143de94f0fa756ec8391fe6f930d43264260874ec0dfcca,
+
+TEST = 5,
+U1 = 0232e33ac5577de12a6560179f763773a3fa771be0e1359be07b5f46c39230e2fb,
+U2 = 032dfd613face20d59f33c07288d43fec86043aec211e3999966832a6b3d33c19b,
+T1 = 02e6ecd68c55d7d546de373a2e702eab6f6249666166acf0b06ea369f16f60b04c,
+T2 = 0206e50c4de02cf149b2b2393f29e02657bcfee165b28dde8043f7a7c510dfff48,
+
+TEST = 6,
+U1 = 0246073f99b3c5c6f3022a53abf7ce6aaf4bd2c1424e8bb12f8a3d5dde5a2683cf,
+U2 = 0357c6ad172eeb617d71b1f526303ac440eba6ebc2107528209377aa8c6b94494e,
+T1 = 03524485e619276c5181b5a42d2a7a9b60ec32c0d9347f2960593985f14d1ca1a2,
+T2 = 026203b02875471607bf3f709534d69e429566788e3a4a0b1ad1f5ad043b3f89fb,
+
+TEST = 7,
+U1 = 026677976aff8866137e6118ddc6df9fef579e10e89d0fb524dffb5ed6f5a94370,
+U2 = 02c198953702562f1a4c9e64d89b30beaad5ff07d9b1d1d3deac6b2203d359c537,
+T1 = 0261bbfc24f2abe1a2db8f4c58cce99cdd98094675fc0b041240a5dec0f0dd4ae7,
+T2 = 022d8229188b6ee201076de07412786ef17b0a179f0ecbbf98154eee98453fc9b8,
+
+TEST = 8,
+U1 = 02691f1531d286c6ec16412c9f5c4354f70d1379bc89e1b74c0308e6b4f57fe591,
+U2 = 031d181876c0f3c50717b33594a6a6796983dcfea44911c513603ec6cfc060ff63,
+T1 = 03bbca24e57c42ab254a8f72c7cac20ccf1e0e10b93a160170ac2f103f74ed03ab,
+T2 = 0315f0b3d52268ddb004ab06bb95a04251f504667be728beb83bb4f5b9b4b914a3,
+
+TEST = 9,
+U1 = 03262fe60ab36974694625b3cfe30db36795366b585b0ba17689075dce2c9eeef4,
+U2 = 0396277938940d825483b8d7be3e31c6c9d12b02f26089885fa6935756a3ad4a76,
+T1 = 03da3bb1e00b5cc87ef9d7b338b4d5c7c44cd835a93cb446ccfa6cabae7e505553,
+T2 = 02d6b9b7fca510b0cfb8cbf001e265b1a7866a68be40fdf659accae5d703ff65f2,
+


[incubator-milagro-MPC] 03/03: Add phase 5 benchmark and example

Posted by sa...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 72c37ec1b98004bdab75ab64603e63257f950ebd
Author: Samuele Andreoli <sa...@yahoo.it>
AuthorDate: Fri Feb 7 11:54:23 2020 +0000

    Add phase 5 benchmark and example
---
 benchmark/bench_phase5.c  | 197 +++++++++++++++++++++++++++++++++++++++++++
 examples/example_phase5.c | 208 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 405 insertions(+)

diff --git a/benchmark/bench_phase5.c b/benchmark/bench_phase5.c
new file mode 100644
index 0000000..c22655e
--- /dev/null
+++ b/benchmark/bench_phase5.c
@@ -0,0 +1,197 @@
+/*
+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 Schnorr's Proof.
+ */
+
+#include "bench.h"
+#include "amcl/ecdh_SECP256K1.h"
+#include "amcl/mpc.h"
+
+#define MIN_TIME    5.0
+#define MIN_ITERS   10
+
+char *M_hex  = "4b7df9714ecf795cfd698129a6f5250cfb64b739ad163da2da93c728c3bd19be";
+char *PK_hex = "022008f40a4f5bc74ac3cbd41986e61e4229afae6658d51845978f18d33fe8318c";
+char *S_hex = "90c2d9dba55ef93dbfb234d04a2bea475f7067787a57556736c876eced465154";
+char *R_hex  = "028ae19ff44d023c774d6526a22bdb47ccfa5e22a91f9994a485660e9f2363da32";
+char *RX_hex = "8ae19ff44d023c774d6526a22bdb47ccfa5e22a91f9994a485660e9f2363da32";
+
+// Commitment random values
+char *RHO_hex = "803ccd21cddad626e15f21b1ad787949e9beef08e6e68a9e00df59dec16ed290";
+char *PHI_hex = "fab4ce512dff74bd9c71c89a14de5b877af45dca0329ee3fcb72611c0784fef3";
+
+// Simulated second player commitment
+char *V2_hex = "03a57c31470773c6468bce4a66cf73d07bede464782b211c9950bd233d66bb436a";
+char *A2_hex = "03ce088cbd6dfc8975c9e618252c8f7ba935bb9938d33eb42e8e64ba71e229af53";
+
+// Simulated second player proof
+char *U2_hex = "0263f7eed14bfe58bee053e4766d36e8befeb4a509c062c12a77dc9225fff9bac6";
+char *T2_hex = "03e1471efad959c8dfe58e8e29d255a9d5ebece0f4fd6d2c30557b54e865ec98e0";
+
+int main()
+{
+    int rc;
+
+    int iterations;
+    clock_t start;
+    double elapsed;
+
+    char m[SHA256];
+    octet M = {0, sizeof(m), m};
+
+    char s[EGS_SECP256K1];
+    octet S = {0, sizeof(s), s};
+
+    char rx[EGS_SECP256K1];
+    octet RX = {0, sizeof(rx), rx};
+
+    char pk[EFS_SECP256K1 + 1];
+    octet PK = {0, sizeof(pk), pk};
+
+    char r[EFS_SECP256K1 + 1];
+    octet R = {0, sizeof(r), r};
+
+    char rho[EGS_SECP256K1];
+    octet RHO = {0, sizeof(rho), rho};
+
+    char phi[EGS_SECP256K1];
+    octet PHI = {0, sizeof(phi), phi};
+
+    char v1[EFS_SECP256K1 + 1];
+    octet V1 = {0, sizeof(v1), v1};
+
+    char v2[EFS_SECP256K1 + 1];
+    octet V2 = {0, sizeof(v2), v2};
+
+    octet *V[2] = {&V1, &V2};
+
+    char a1[EFS_SECP256K1 + 1];
+    octet A1 = {0, sizeof(a1), a1};
+
+    char a2[EFS_SECP256K1 + 1];
+    octet A2 = {0, sizeof(a2), a2};
+
+    octet *A[2] = {&A1, &A2};
+
+    char u1[EFS_SECP256K1 + 1];
+    octet U1 = {0, sizeof(u1), u1};
+
+    char u2[EFS_SECP256K1 + 1];
+    octet U2 = {0, sizeof(u2), u2};
+
+    octet *U[2] = {&U1, &U2};
+
+    char t1[EFS_SECP256K1 + 1];
+    octet T1 = {0, sizeof(t1), t1};
+
+    char t2[EFS_SECP256K1 + 1];
+    octet T2 = {0, sizeof(t2), t2};
+
+    octet *T[2] = {&T1, &T2};
+
+    // Deterministic RNG for testing
+    char seed[32] = {0};
+    csprng RNG;
+    RAND_seed(&RNG, 32, seed);
+
+    // Load input
+    OCT_fromHex(&M,  M_hex);
+    OCT_fromHex(&PK, PK_hex);
+    OCT_fromHex(&S, S_hex);
+    OCT_fromHex(&R,  R_hex);
+    OCT_fromHex(&RX, RX_hex);
+
+    OCT_fromHex(&RHO, RHO_hex);
+    OCT_fromHex(&PHI, PHI_hex);
+
+    OCT_fromHex(&V2, V2_hex);
+    OCT_fromHex(&A2, A2_hex);
+
+    OCT_fromHex(&U2, U2_hex);
+    OCT_fromHex(&T2, T2_hex);
+
+    print_system_info();
+
+    printf("Timing info\n");
+    printf("===========\n");
+
+    iterations = 0;
+    start = clock();
+    do
+    {
+        rc = MPC_PHASE5_commit(NULL, &R, &S, &PHI, &RHO, V[0], A[0]);
+        iterations++;
+        elapsed = (clock() - start) / (double)CLOCKS_PER_SEC;
+    }
+    while (elapsed < MIN_TIME || iterations < MIN_ITERS);
+
+    if (rc != MPC_OK)
+    {
+        printf("FAILURE MPC_PHASE5_commit: %d\n", rc);
+        exit(EXIT_FAILURE);
+    }
+
+    elapsed = MILLISECOND * elapsed / iterations;
+    printf("\tMPC_PHASE5_commit\t\t%8d iterations\t", iterations);
+    printf("%8.2lf ms per iteration\n", elapsed);
+
+    iterations = 0;
+    start = clock();
+    do
+    {
+        rc = MPC_PHASE5_prove(&PHI, &RHO, V, A, &PK, &M, &RX, U[0], T[0]);
+        iterations++;
+        elapsed = (clock() - start) / (double)CLOCKS_PER_SEC;
+    }
+    while (elapsed < MIN_TIME || iterations < MIN_ITERS);
+
+    if (rc != MPC_OK)
+    {
+        printf("FAILURE MPC_PHASE5_prove: %d\n", rc);
+        exit(EXIT_FAILURE);
+    }
+
+    elapsed = MILLISECOND * elapsed / iterations;
+    printf("\tMPC_PHASE5_prove\t\t%8d iterations\t", iterations);
+    printf("%8.2lf ms per iteration\n", elapsed);
+
+    iterations = 0;
+    start = clock();
+    do
+    {
+        rc = MPC_PHASE5_verify(U, T);
+        iterations++;
+        elapsed = (clock() - start) / (double)CLOCKS_PER_SEC;
+    }
+    while (elapsed < MIN_TIME || iterations < MIN_ITERS);
+
+    if (rc != MPC_OK)
+    {
+        printf("FAILURE MPC_PHASE5_verify: %d\n", rc);
+        exit(EXIT_FAILURE);
+    }
+
+    elapsed = MILLISECOND * elapsed / iterations;
+    printf("\tMPC_PHASE5_verify\t\t%8d iterations\t", iterations);
+    printf("%8.2lf ms per iteration\n", elapsed);
+
+    exit(EXIT_SUCCESS);
+}
diff --git a/examples/example_phase5.c b/examples/example_phase5.c
new file mode 100644
index 0000000..33f4039
--- /dev/null
+++ b/examples/example_phase5.c
@@ -0,0 +1,208 @@
+/*
+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.
+*/
+
+// MPC Phase 5 example
+
+#include <amcl/ecdh_SECP256K1.h>
+#include <amcl/mpc.h>
+
+char *M_hex  = "4b7df9714ecf795cfd698129a6f5250cfb64b739ad163da2da93c728c3bd19be";
+char *PK_hex = "022008f40a4f5bc74ac3cbd41986e61e4229afae6658d51845978f18d33fe8318c";
+char *S1_hex = "90c2d9dba55ef93dbfb234d04a2bea475f7067787a57556736c876eced465154";
+char *S2_hex = "8002233d6018c7e1497b42828e517364f0b5b79e9edb8a7d130fa21e76270ee2";
+char *R_hex  = "028ae19ff44d023c774d6526a22bdb47ccfa5e22a91f9994a485660e9f2363da32";
+char *RX_hex = "8ae19ff44d023c774d6526a22bdb47ccfa5e22a91f9994a485660e9f2363da32";
+
+int main()
+{
+    int rc;
+
+    char m[SHA256];
+    octet M = {0, sizeof(m), m};
+
+    char s1[EGS_SECP256K1];
+    octet S1 = {0, sizeof(s1), s1};
+
+    char s2[EGS_SECP256K1];
+    octet S2 = {0, sizeof(s2), s2};
+
+    char rx[EGS_SECP256K1];
+    octet RX = {0, sizeof(rx), rx};
+
+    char pk[EFS_SECP256K1 + 1];
+    octet PK = {0, sizeof(pk), pk};
+
+    char r[EFS_SECP256K1 + 1];
+    octet R = {0, sizeof(r), r};
+
+    char rho1[EGS_SECP256K1];
+    octet RHO1 = {0, sizeof(rho1), rho1};
+
+    char phi1[EGS_SECP256K1];
+    octet PHI1 = {0, sizeof(phi1), phi1};
+
+    char rho2[EGS_SECP256K1];
+    octet RHO2 = {0, sizeof(rho2), rho2};
+
+    char phi2[EGS_SECP256K1];
+    octet PHI2 = {0, sizeof(phi2), phi2};
+
+    char v1[EFS_SECP256K1 + 1];
+    octet V1 = {0, sizeof(v1), v1};
+
+    char v2[EFS_SECP256K1 + 1];
+    octet V2 = {0, sizeof(v2), v2};
+
+    octet *V[2] = {&V1, &V2};
+
+    char a1[EFS_SECP256K1 + 1];
+    octet A1 = {0, sizeof(a1), a1};
+
+    char a2[EFS_SECP256K1 + 1];
+    octet A2 = {0, sizeof(a2), a2};
+
+    octet *A[2] = {&A1, &A2};
+
+    char u1[EFS_SECP256K1 + 1];
+    octet U1 = {0, sizeof(u1), u1};
+
+    char u2[EFS_SECP256K1 + 1];
+    octet U2 = {0, sizeof(u2), u2};
+
+    octet *U[2] = {&U1, &U2};
+
+    char t1[EFS_SECP256K1 + 1];
+    octet T1 = {0, sizeof(t1), t1};
+
+    char t2[EFS_SECP256K1 + 1];
+    octet T2 = {0, sizeof(t2), t2};
+
+    octet *T[2] = {&T1, &T2};
+
+    // Deterministic RNG for testing
+    char seed[32] = {0};
+    csprng RNG;
+    RAND_seed(&RNG, 32, seed);
+
+    // Load input
+    OCT_fromHex(&M,  M_hex);
+    OCT_fromHex(&PK, PK_hex);
+    OCT_fromHex(&S1, S1_hex);
+    OCT_fromHex(&S2, S2_hex);
+    OCT_fromHex(&R,  R_hex);
+    OCT_fromHex(&RX, RX_hex);
+
+    printf("MPC Phase 5 example\n");
+    printf("\nCommon parameters:\n");
+    printf("\tPK = ");
+    OCT_output(&PK);
+    printf("\tR  = ");
+    OCT_output(&R);
+    printf("\tRX = ");
+    OCT_output(&RX);
+    printf("\tM  = ");
+    OCT_output(&M);
+
+    printf("\n[Alice] Signature share\n\tS1 = ");
+    OCT_output(&S1);
+    printf("\n[Bob]   Signature share\n\tS2 = ");
+    OCT_output(&S2);
+
+
+    // Alice - generate commitments and broadcast
+    printf("\n[Alice] Generate commitment\n");
+
+    rc = MPC_PHASE5_commit(&RNG, &R, &S1, &PHI1, &RHO1, V[0], A[0]);
+    if (rc != MPC_OK)
+    {
+        printf("FAILURE MPC_PHASE5_commit Alice. RC %d\n", rc);
+        exit(EXIT_FAILURE);
+    }
+
+    printf("\tPHI = ");
+    OCT_output(&PHI1);
+    printf("\tRHO = ");
+    OCT_output(&RHO1);
+    printf("\tV = ");
+    OCT_output(&V1);
+    printf("\tA = ");
+    OCT_output(&A1);
+
+    // Bob - generate commitments and broadcast
+    printf("\n[Bob]   Generate commitment\n");
+
+    rc = MPC_PHASE5_commit(&RNG, &R, &S2, &PHI2, &RHO2, V[1], A[1]);
+    if (rc != MPC_OK)
+    {
+        printf("FAILURE MPC_PHASE5_commit Bob. RC %d\n", rc);
+        exit(EXIT_FAILURE);
+    }
+
+    printf("\tPHI = ");
+    OCT_output(&PHI2);
+    printf("\tRHO = ");
+    OCT_output(&RHO2);
+    printf("\tV = ");
+    OCT_output(&V2);
+    printf("\tA = ");
+    OCT_output(&A2);
+
+    // Alice - generate proof for commitments and broadcast
+    printf("\n[Alice] Generate proof for commitments\n");
+
+    rc = MPC_PHASE5_prove(&PHI1, &RHO1, V, A, &PK, &M, &RX, U[0], T[0]);
+    if (rc != MPC_OK)
+    {
+        printf("FAILURE MPC_PHASE5_prove Alice. RC %d\n", rc);
+        exit(EXIT_FAILURE);
+    }
+
+    printf("\tU = ");
+    OCT_output(&U1);
+    printf("\tT = ");
+    OCT_output(&T1);
+
+    // Bob - generate proof for commitments and broadcast
+    printf("\n[Bob]   Generate proof for commitments\n");
+
+    rc = MPC_PHASE5_prove(&PHI2, &RHO2, V, A, &PK, &M, &RX, U[1], T[1]);
+    if (rc != MPC_OK)
+    {
+        printf("FAILURE MPC_PHASE5_prove Bob. RC %d\n", rc);
+        exit(EXIT_FAILURE);
+    }
+
+    printf("\tU = ");
+    OCT_output(&U2);
+    printf("\tT = ");
+    OCT_output(&T2);
+
+    // Each player verifies if the total of the proof material is valid
+    printf("\n[Both]  Verification\n");
+
+    rc = MPC_PHASE5_verify(U, T);
+    if (rc == MPC_OK)
+    {
+        printf("\tSuccess!\n");
+    }
+    else
+    {
+        printf("\tFailure!\n");
+    }
+}