| /* |
| 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 ECDSA smoke test |
| |
| #include <amcl/randapi.h> |
| #include <amcl/ecdh_SECP256K1.h> |
| #include <amcl/mta.h> |
| #include <amcl/mpc.h> |
| |
| int test(csprng *RNG) |
| { |
| int rc; |
| |
| // Paillier Keys |
| PAILLIER_private_key PRIV1; |
| PAILLIER_public_key PUB1; |
| PAILLIER_private_key PRIV2; |
| PAILLIER_public_key PUB2; |
| |
| char k1[EGS_SECP256K1]; |
| octet K1 = {0,sizeof(k1),k1}; |
| |
| char w1[EGS_SECP256K1]; |
| octet W1 = {0,sizeof(w1),w1}; |
| |
| char gamma2[EGS_SECP256K1]; |
| octet GAMMA2 = {0,sizeof(gamma2),gamma2}; |
| |
| char ca11[FS_4096]; |
| octet CA11 = {0,sizeof(ca11),ca11}; |
| |
| char r11[FS_2048]; |
| octet R11 = {0,sizeof(r11),r11}; |
| |
| char cb12[FS_4096]; |
| octet CB12 = {0,sizeof(cb12),cb12}; |
| |
| char r12[FS_2048]; |
| octet R12 = {0,sizeof(r12),r12}; |
| |
| char z12[EGS_SECP256K1]; |
| octet Z12 = {0,sizeof(z12),z12}; |
| |
| char beta2[EGS_SECP256K1]; |
| octet BETA2 = {0,sizeof(beta2),beta2}; |
| |
| char alpha1[EGS_SECP256K1]; |
| octet ALPHA1 = {0,sizeof(alpha1),alpha1}; |
| |
| char k2[EGS_SECP256K1]; |
| octet K2 = {0,sizeof(k2),k2}; |
| |
| char w2[EGS_SECP256K1]; |
| octet W2 = {0,sizeof(w2),w2}; |
| |
| char gamma1[EGS_SECP256K1]; |
| octet GAMMA1 = {0,sizeof(gamma1),gamma1}; |
| |
| char ca22[FS_4096]; |
| octet CA22 = {0,sizeof(ca22),ca22}; |
| |
| char r22[FS_2048]; |
| octet R22 = {0,sizeof(r22),r22}; |
| |
| char cb21[FS_4096]; |
| octet CB21 = {0,sizeof(cb21),cb21}; |
| |
| char r21[FS_2048]; |
| octet R21 = {0,sizeof(r21),r21}; |
| |
| char z21[EGS_SECP256K1]; |
| octet Z21 = {0,sizeof(z21),z21}; |
| |
| char beta1[EGS_SECP256K1]; |
| octet BETA1 = {0,sizeof(beta1),beta1}; |
| |
| char alpha2[EGS_SECP256K1]; |
| octet ALPHA2 = {0,sizeof(alpha2),alpha2}; |
| |
| char sum1[EGS_SECP256K1]; |
| octet SUM1 = {0,sizeof(sum1),sum1}; |
| |
| char sum2[EGS_SECP256K1]; |
| octet SUM2 = {0,sizeof(sum2),sum2}; |
| |
| char invkgamma[EGS_SECP256K1]; |
| octet INVKGAMMA = {0,sizeof(invkgamma),invkgamma}; |
| |
| char gammapt1[EFS_SECP256K1+1]; |
| octet GAMMAPT1 = {0,sizeof(gammapt1),gammapt1}; |
| |
| char gammapt2[EFS_SECP256K1+1]; |
| octet GAMMAPT2 = {0,sizeof(gammapt2),gammapt2}; |
| |
| char sig_r[EGS_SECP256K1]; |
| octet SIG_R = {0,sizeof(sig_r),sig_r}; |
| |
| char pk1[EFS_SECP256K1+1]; |
| octet PK1 = {0,sizeof(pk1),pk1}; |
| |
| char pk2[EFS_SECP256K1+1]; |
| octet PK2 = {0,sizeof(pk2),pk2}; |
| |
| char pk[EFS_SECP256K1+1]; |
| octet PK = {0,sizeof(pk),pk}; |
| |
| char sig_s1[EGS_SECP256K1]; |
| octet SIG_S1 = {0,sizeof(sig_s1),sig_s1}; |
| |
| char sig_s2[EGS_SECP256K1]; |
| octet SIG_S2 = {0,sizeof(sig_s2),sig_s2}; |
| |
| char sig_s[EGS_SECP256K1]; |
| octet SIG_S = {0,sizeof(sig_s),sig_s}; |
| |
| char m[2000]; |
| octet M = {0,sizeof(m),m}; |
| |
| char hm[32]; |
| octet HM = {0,sizeof(hm),hm}; |
| |
| char nc_ecp[2 * EFS_SECP256K1 + 1]; |
| octet NC_ECP = {0, sizeof(nc_ecp), nc_ecp}; |
| |
| ECP_SECP256K1 P; |
| |
| printf("Generating Paillier key pair one\n"); |
| PAILLIER_KEY_PAIR(RNG, NULL, NULL, &PUB1, &PRIV1); |
| |
| printf("Generating Paillier key pair two\n"); |
| PAILLIER_KEY_PAIR(RNG, NULL, NULL, &PUB2, &PRIV2); |
| |
| printf("Generating ECDSA key pair one\n"); |
| ECP_SECP256K1_KEY_PAIR_GENERATE(RNG,&W1,&NC_ECP); |
| |
| // Convert to compressed form |
| rc=ECP_SECP256K1_fromOctet(&P, &NC_ECP); |
| if (!rc) |
| { |
| fprintf(stderr, "ERROR ECP_SECP256K1_fromOctet PK1 rc\n"); |
| exit(EXIT_FAILURE); |
| } |
| |
| ECP_SECP256K1_toOctet(&PK1, &P, true); |
| |
| rc=ECP_SECP256K1_PUBLIC_KEY_VALIDATE(&PK1); |
| if (rc!=0) |
| { |
| fprintf(stderr, "ERROR ECP_SECP256K1_PUBLIC_KEY_VALIDATE rc: %d\n", rc); |
| exit(EXIT_FAILURE); |
| } |
| |
| printf("Generating ECDSA key pair two\n"); |
| ECP_SECP256K1_KEY_PAIR_GENERATE(RNG,&W2,&NC_ECP); |
| |
| // Convert to compressed form |
| rc=ECP_SECP256K1_fromOctet(&P, &NC_ECP); |
| if (!rc) |
| { |
| fprintf(stderr, "ERROR ECP_SECP256K1_fromOctet PK2 rc"); |
| exit(EXIT_FAILURE); |
| } |
| |
| ECP_SECP256K1_toOctet(&PK2, &P, true); |
| |
| rc=ECP_SECP256K1_PUBLIC_KEY_VALIDATE(&PK2); |
| if (rc!=0) |
| { |
| fprintf(stderr, "ERROR ECP_SECP256K1_PUBLIC_KEY_VALIDATE rc: %d\n", rc); |
| exit(EXIT_FAILURE); |
| } |
| |
| printf("Generating GAMMA pair one\n"); |
| ECP_SECP256K1_KEY_PAIR_GENERATE(RNG,&GAMMA1,&NC_ECP); |
| |
| // Convert to compressed form |
| rc=ECP_SECP256K1_fromOctet(&P, &NC_ECP); |
| if (!rc) |
| { |
| fprintf(stderr, "ERROR ECP_SECP256K1_fromOctet GAMMAPT1\n"); |
| exit(EXIT_FAILURE); |
| } |
| |
| ECP_SECP256K1_toOctet(&GAMMAPT1, &P, true); |
| |
| rc=ECP_SECP256K1_PUBLIC_KEY_VALIDATE(&GAMMAPT1); |
| if (rc!=0) |
| { |
| fprintf(stderr, "ERROR ECP_SECP256K1_PUBLIC_KEY_VALIDATE rc: %d\n", rc); |
| exit(EXIT_FAILURE); |
| } |
| |
| printf("Generating GAMMA pair two\n"); |
| ECP_SECP256K1_KEY_PAIR_GENERATE(RNG,&GAMMA2,&NC_ECP); |
| |
| // Convert to compressed form |
| rc=ECP_SECP256K1_fromOctet(&P, &NC_ECP); |
| if (!rc) |
| { |
| fprintf(stderr, "ERROR ECP_SECP256K1_fromOctet GAMMAPT2\n"); |
| exit(EXIT_FAILURE); |
| } |
| |
| ECP_SECP256K1_toOctet(&GAMMAPT2, &P, true); |
| |
| rc=ECP_SECP256K1_PUBLIC_KEY_VALIDATE(&GAMMAPT2); |
| if (rc!=0) |
| { |
| fprintf(stderr, "ERROR ECP_SECP256K1_PUBLIC_KEY_VALIDATE rc: %d\n", rc); |
| exit(EXIT_FAILURE); |
| } |
| |
| printf("Generating K1\n"); |
| ECP_SECP256K1_KEY_PAIR_GENERATE(RNG,&K1,&NC_ECP); |
| |
| printf("Generating K2\n"); |
| ECP_SECP256K1_KEY_PAIR_GENERATE(RNG,&K2,&NC_ECP); |
| |
| OCT_jstring(&M,"test message"); |
| printf("M: "); |
| OCT_output(&M); |
| |
| // ALPHA1 + BETA2 = K1 * GAMMA2 |
| MPC_MTA_CLIENT1(RNG, &PUB1, &K1, &CA11, &R11); |
| |
| printf("CA11: "); |
| OCT_output(&CA11); |
| printf("\n"); |
| |
| MPC_MTA_SERVER(RNG, &PUB1, &GAMMA2, &CA11, &Z12, &R12, &CB12, &BETA2); |
| |
| printf("CB12: "); |
| OCT_output(&CB12); |
| printf("\n"); |
| |
| printf("BETA2: "); |
| OCT_output(&BETA2); |
| printf("\n"); |
| |
| MPC_MTA_CLIENT2(&PRIV1, &CB12, &ALPHA1); |
| |
| printf("ALPHA1: "); |
| OCT_output(&ALPHA1); |
| printf("\n"); |
| |
| // ALPHA2 + BETA1 = K2 * GAMMA1 |
| MPC_MTA_CLIENT1(RNG, &PUB2, &K2, &CA22, &R22); |
| |
| printf("CA22: "); |
| OCT_output(&CA22); |
| printf("\n"); |
| |
| MPC_MTA_SERVER(RNG, &PUB2, &GAMMA1, &CA22, &Z21, &R21, &CB21, &BETA1); |
| |
| printf("CB21: "); |
| OCT_output(&CB21); |
| printf("\n"); |
| |
| printf("BETA1: "); |
| OCT_output(&BETA1); |
| printf("\n"); |
| |
| MPC_MTA_CLIENT2(&PRIV2, &CB21, &ALPHA2); |
| |
| printf("ALPHA2: "); |
| OCT_output(&ALPHA2); |
| printf("\n"); |
| |
| // sum = K1.GAMMA1 + alpha1 + beta1 |
| MPC_SUM_MTA(&K1, &GAMMA1, &ALPHA1, &BETA1, &SUM1); |
| |
| printf("SUM1: "); |
| OCT_output(&SUM1); |
| printf("\n"); |
| |
| // sum = K2.GAMMA2 + alpha2 + beta2 |
| MPC_SUM_MTA(&K2, &GAMMA2, &ALPHA2, &BETA2, &SUM2); |
| |
| printf("SUM2: "); |
| OCT_output(&SUM2); |
| printf("\n"); |
| |
| // Calculate the inverse of kgamma |
| MPC_INVKGAMMA(&SUM1, &SUM2, &INVKGAMMA); |
| |
| printf("INVKGAMMA: "); |
| OCT_output(&INVKGAMMA); |
| printf("\n"); |
| |
| // Calculate the R signature component |
| rc = MPC_R(&INVKGAMMA, &GAMMAPT1, &GAMMAPT2, &SIG_R, NULL); |
| if (rc) |
| { |
| fprintf(stderr, "FAILURE MPC_R rc: %d\n", rc); |
| exit(EXIT_FAILURE); |
| } |
| |
| // ALPHA1 + BETA2 = K1 * W2 |
| MPC_MTA_CLIENT1(NULL, &PUB1, &K1, &CA11, &R11); |
| |
| printf("CA11: "); |
| OCT_output(&CA11); |
| printf("\n"); |
| |
| MPC_MTA_SERVER(NULL, &PUB1, &W2, &CA11, &Z12, &R12, &CB12, &BETA2); |
| |
| printf("CB12: "); |
| OCT_output(&CB12); |
| printf("\n"); |
| |
| printf("BETA2: "); |
| OCT_output(&BETA2); |
| printf("\n"); |
| |
| MPC_MTA_CLIENT2(&PRIV1, &CB12, &ALPHA1); |
| |
| printf("ALPHA1: "); |
| OCT_output(&ALPHA1); |
| printf("\n"); |
| |
| // ALPHA2 + BETA1 = K2 * W1 |
| MPC_MTA_CLIENT1(NULL, &PUB2, &K2, &CA22, &R22); |
| |
| printf("CA22: "); |
| OCT_output(&CA22); |
| printf("\n"); |
| |
| MPC_MTA_SERVER(NULL, &PUB2, &W1, &CA22, &Z21, &R21, &CB21, &BETA1); |
| |
| printf("CB21: "); |
| OCT_output(&CB21); |
| printf("\n"); |
| |
| printf("BETA1: "); |
| OCT_output(&BETA1); |
| printf("\n"); |
| |
| MPC_MTA_CLIENT2(&PRIV2, &CB21, &ALPHA2); |
| |
| printf("ALPHA2: "); |
| OCT_output(&ALPHA2); |
| printf("\n"); |
| |
| // sum = K1.W1 + alpha1 + beta1 |
| MPC_SUM_MTA(&K1, &W1, &ALPHA1, &BETA1, &SUM1); |
| |
| printf("SUM1: "); |
| OCT_output(&SUM1); |
| printf("\n"); |
| |
| // sum = K2.W2 + alpha2 + beta2 |
| MPC_SUM_MTA(&K2, &W2, &ALPHA2, &BETA2, &SUM2); |
| |
| printf("SUM2: "); |
| OCT_output(&SUM2); |
| printf("\n"); |
| |
| // Calculate the message hash |
| MPC_HASH(HASH_TYPE_SECP256K1, &M, &HM); |
| |
| // Calculate the S1 signature component |
| rc = MPC_S(&HM, &SIG_R, &K1, &SUM1, &SIG_S1); |
| if (rc) |
| { |
| fprintf(stderr, "FAILURE MPC_S rc: %d\n", rc); |
| exit(EXIT_FAILURE); |
| } |
| |
| printf("SIG_S1: "); |
| OCT_output(&SIG_S1); |
| printf("\n"); |
| |
| // Calculate the S2 signature component |
| rc = MPC_S(&HM, &SIG_R, &K2, &SUM2, &SIG_S2); |
| if (rc) |
| { |
| fprintf(stderr, "FAILURE MPC_S rc: %d\n", rc); |
| exit(EXIT_FAILURE); |
| } |
| |
| printf("SIG_S2: "); |
| OCT_output(&SIG_S2); |
| printf("\n"); |
| |
| // Sum S signature component |
| MPC_SUM_S(&SIG_S1, &SIG_S2, &SIG_S); |
| |
| printf("SIG_R: "); |
| OCT_output(&SIG_R); |
| printf("\n"); |
| |
| printf("SIG_S: "); |
| OCT_output(&SIG_S); |
| printf("\n"); |
| |
| // Sum ECDSA public keys |
| rc = MPC_SUM_PK(&PK1, &PK2, &PK); |
| if (rc) |
| { |
| fprintf(stderr, "FAILURE MPC_SUM_PK rc: %d\n", rc); |
| exit(EXIT_FAILURE); |
| } |
| |
| printf("PK: "); |
| OCT_output(&PK); |
| printf("\n"); |
| |
| rc = MPC_ECDSA_VERIFY(&HM,&PK,&SIG_R,&SIG_S); |
| if (rc!=0) |
| { |
| fprintf(stderr, "FAILURE ECP_SECP256K1_VP_DSA rc: %d\n", rc); |
| exit(EXIT_FAILURE); |
| } |
| else |
| { |
| printf("ECDSA succeeded\n"); |
| } |
| |
| printf("SUCCESS\n"); |
| exit(EXIT_SUCCESS); |
| } |
| |
| int main() |
| { |
| char* seedHex = "78d0fb6705ce77dee47d03eb5b9c5d30"; |
| char seed[16] = {0}; |
| octet SEED = {sizeof(seed),sizeof(seed),seed}; |
| |
| // CSPRNG |
| csprng RNG; |
| |
| // fake random source |
| OCT_fromHex(&SEED,seedHex); |
| |
| // initialise strong RNG |
| CREATE_CSPRNG(&RNG,&SEED); |
| |
| printf("ECDSA MPC example\n"); |
| test(&RNG); |
| |
| KILL_CSPRNG(&RNG); |
| } |