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

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

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)
 {