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