This is an automated email from the ASF dual-hosted git repository. kmccusker pushed a commit to branch bls-sss in repository https://gitbox.apache.org/repos/asf/incubator-milagro-crypto-c.git
commit db8d27d0cc9987bed2d0c9531d6fe605e8833bb4 Author: Kealan McCusker <[email protected]> AuthorDate: Mon Aug 26 14:25:04 2019 +0100 added BLS SSS to BLS library --- VERSION | 2 +- examples/CMakeLists.txt | 4 + examples/example_bls_ZZZ.c.in | 16 ++- examples/example_bls_sss_ZZZ.c.in | 242 +++++++++++++++++++++++++++++++++++++ include/bls.h.in | 57 +++++++-- include/bls192.h.in | 33 ++++++ include/bls256.h.in | 33 ++++++ src/bls.c.in | 216 +++++++++++++++++++++++++++++++++ src/bls192.c.in | 216 +++++++++++++++++++++++++++++++++ src/bls256.c.in | 216 +++++++++++++++++++++++++++++++++ test/CMakeLists.txt | 1 + test/test_bls_ZZZ.c.in | 6 +- test/test_bls_sss_ZZZ.c.in | 243 ++++++++++++++++++++++++++++++++++++++ 13 files changed, 1265 insertions(+), 20 deletions(-) diff --git a/VERSION b/VERSION index 7dea76e..9084fa2 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.0.1 +1.1.0 diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index d81e923..785630e 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -50,6 +50,10 @@ foreach(curve ${AMCL_CURVE}) amcl_configure_file_curve(example_bls_ZZZ.c.in example_bls_${TC}.c "${curve}" example_bls_${TC}_GEN_SRCS) add_executable(example_bls_${TC} ${example_bls_${TC}_GEN_SRCS}) target_link_libraries(example_bls_${TC} PRIVATE amcl_bls_${TC}) + + amcl_configure_file_curve(example_bls_sss_ZZZ.c.in example_bls_sss_${TC}.c "${curve}" example_bls_sss_${TC}_GEN_SRCS) + add_executable(example_bls_sss_${TC} ${example_bls_sss_${TC}_GEN_SRCS}) + target_link_libraries(example_bls_sss_${TC} PRIVATE amcl_bls_${TC}) endif() endforeach() diff --git a/examples/example_bls_ZZZ.c.in b/examples/example_bls_ZZZ.c.in index 736e54d..d171a9d 100644 --- a/examples/example_bls_ZZZ.c.in +++ b/examples/example_bls_ZZZ.c.in @@ -16,9 +16,18 @@ specific language governing permissions and limitations under the License. */ -/* Build executable after installation: +/* + BLS example code. + + Build executable after installation: - gcc -O0 -g ./testbls_ZZZ.c $(pkg-config --libs --cflags amcl) -o testbls_ZZZ + 1. Change headers; + + #include "bls_ZZZ.h" -> #include <amcl/bls_ZZZ.h> + + 2. Build code + + gcc -O0 -g ./example_bls_ZZZ.c $(pkg-config --libs --cflags amcl) -o example_bls_ZZZ */ @@ -269,12 +278,11 @@ int main() OCT_fromHex(&SEED,seedHex); printf("SEED: "); OCT_output(&SEED); - printf("\n"); // initialise strong RNG CREATE_CSPRNG(&RNG,&SEED); - printf("\nTesting BLS signature for curve ZZZ\n"); + printf("\nBLS example for curve ZZZ\n"); bls(&RNG); KILL_CSPRNG(&RNG); diff --git a/examples/example_bls_sss_ZZZ.c.in b/examples/example_bls_sss_ZZZ.c.in new file mode 100644 index 0000000..c325d68 --- /dev/null +++ b/examples/example_bls_sss_ZZZ.c.in @@ -0,0 +1,242 @@ +/* +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. +*/ + +/* + BLS Shamir Secret Sharing example code. + + Build executable after installation: + + 1. Change headers; + + #include "bls_ZZZ.h" -> #include <amcl/bls_ZZZ.h> + + 2. Build code + + gcc -O0 -g ./example_bls_sss_ZZZ.c $(pkg-config --libs --cflags amcl) -o example_bls_sss_ZZZ + +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "config_curve_ZZZ.h" +#include "randapi.h" + +#if CURVE_SECURITY_ZZZ == 128 +#include "bls_ZZZ.h" +#elif CURVE_SECURITY_ZZZ == 192 +#include "bls192_ZZZ.h" +#elif CURVE_SECURITY_ZZZ == 256 +#include "bls256_ZZZ.h" +#endif + +// Support multiple security levels +#if CURVE_SECURITY_ZZZ == 128 +#define G2LEN 4*BFS_ZZZ +#elif CURVE_SECURITY_ZZZ == 192 +#define G2LEN 8*BFS_ZZZ +#elif CURVE_SECURITY_ZZZ == 256 +#define G2LEN 16*BFS_ZZZ +#endif + +static char message[]="test message"; + +int bls_sss(csprng *RNG) +{ + int rc; + int n=4; + int k=3; + + char ski[BGS_ZZZ]; + octet SKI = {0,sizeof(ski),ski}; + char pki[G2LEN]; + octet PKI = {0,sizeof(pki),pki}; + + char sko[BGS_ZZZ]; + octet SKO = {sizeof(sko),sizeof(sko),sko}; + char skr[BGS_ZZZ]; + octet SKR = {sizeof(skr),sizeof(skr),skr}; + + char sigi[BFS_ZZZ+1]; + octet SIGI = {0,sizeof(sigi),sigi}; + char sigr[BFS_ZZZ+1]; + octet SIGR = {0,sizeof(sigr),sigr}; + + // Secret shares + char x[n][BGS_ZZZ]; + octet X[n]; + char y[n][BGS_ZZZ]; + octet Y[n]; + + for(int i=0; i<n; i++) + { + memset(&y[i], 0, sizeof(y[i])); + Y[i].max = BGS_ZZZ; + Y[i].len = BGS_ZZZ; + Y[i].val = y[i]; + memset(&x[i], 0, sizeof(x[i])); + X[i].max = BGS_ZZZ; + X[i].len = BGS_ZZZ; + X[i].val = x[i]; + } + + // Generate key pair + BLS_ZZZ_KEY_PAIR_GENERATE(RNG,&SKI,&PKI); + + printf("Private key SKI: "); + OCT_output(&SKI); + printf("Public key PKI: "); + OCT_output(&PKI); + printf("\n"); + + // Sign the message + BLS_ZZZ_SIGN(&SIGI,message,&SKI); + + printf("SIGI: "); + OCT_output(&SIGI); + + // Verify signature + rc=BLS_ZZZ_VERIFY(&SIGI,message,&PKI); + if (rc!=BLS_OK) + { + printf("Error: Invalid Signature\n"); + return 1; + } + printf("Success: Signature is valid\n"); + + // Make shares of BLS secret key + rc = BLS_ZZZ_MAKE_SHARES(k, n, RNG, X, Y, &SKI, &SKO); + if (rc!=BLS_OK) + { + printf("Error: BLS_ZZZ_MAKE_SHARES\n"); + return 1; + } + + for(int i=0; i<n; i++) + { + printf("X[%d] ", i); + OCT_output(&X[i]); + printf("Y[%d] ", i); + OCT_output(&Y[i]); + } + + printf("SKO: "); + OCT_output(&SKO); + + if (!OCT_comp(&SKI,&SKO)) + { + printf("FAILURE SKI != SKO"); + return 1; + } + + // Recover BLS secret key + rc = BLS_ZZZ_RECOVER_SECRET(k, X, Y, &SKR); + if (rc!=BLS_OK) + { + printf("Error: BLS_ZZZ_RECOVER_SECRET\n"); + return 1; + } + printf("SKR: "); + OCT_output(&SKR); + + if (!OCT_comp(&SKR,&SKO)) + { + printf("FAILURE SKR != SKO"); + return 1; + } + + // Generate public keys and signatures using shares + char pks[n][G2LEN]; + octet PKS[n]; + char sigs[n][BFS_ZZZ+1]; + octet SIGS[n]; + for(int i=0; i<n; i++) + { + memset(&sigs[i], 0, sizeof(sigs[i])); + SIGS[i].max = BFS_ZZZ+1; + SIGS[i].len = BFS_ZZZ+1; + SIGS[i].val = sigs[i]; + memset(&PKS[i], 0, sizeof(PKS[i])); + PKS[i].max = G2LEN; + PKS[i].len = G2LEN; + PKS[i].val = pks[i]; + BLS_ZZZ_KEY_PAIR_GENERATE(NULL,&Y[i],&PKS[i]); + BLS_ZZZ_SIGN(&SIGS[i],message,&Y[i]); + } + + for(int i=0; i<n; i++) + { + printf("PKS[%d] ", i); + OCT_output(&PKS[i]); + } + + for(int i=0; i<n; i++) + { + printf("SIGS[%d] ", i); + OCT_output(&SIGS[i]); + } + printf("\n\n"); + + // Recover BLS signature + rc = BLS_ZZZ_RECOVER_SIGNATURE(k, X, SIGS, &SIGR); + if (rc!=BLS_OK) + { + printf("Error: BLS_ZZZ_RECOVER_SIGNATURE\n"); + return 1; + } + printf("SIGR: "); + OCT_output(&SIGR); + + if (!OCT_comp(&SIGR,&SIGI)) + { + printf("FAILURE SIGR != SIGI"); + return 1; + } + + return 0; +} + + +int main() +{ +#ifdef DEBUG + printf("%d bit build\n",CHUNK); +#endif + + char* seedHex = "78d0fb6705ce77dee47d03eb5b9c5d30"; + char seed[16] = {0}; + octet SEED = {sizeof(seed),sizeof(seed),seed}; + + // CSPRNG + csprng RNG; + + // fake random source + OCT_fromHex(&SEED,seedHex); + printf("SEED: "); + OCT_output(&SEED); + + // initialise strong RNG + CREATE_CSPRNG(&RNG,&SEED); + + printf("\nBLS SSS example for curve ZZZ\n"); + bls_sss(&RNG); + + KILL_CSPRNG(&RNG); +} + + diff --git a/include/bls.h.in b/include/bls.h.in index b500802..13332b2 100644 --- a/include/bls.h.in +++ b/include/bls.h.in @@ -75,39 +75,72 @@ int BLS_ZZZ_VERIFY(octet *SIG,char *m,octet *W); /** @brief Add two members from the group G1 * - @param R1 member of G1 - @param R2 member of G1 - @param R member of G1. R = R1+R2 + @param R1 member of G1 + @param R2 member of G1 + @param R member of G1. R = R1+R2 @return Zero for success or else an error code */ int BLS_ZZZ_ADD_G1(octet *R1,octet *R2,octet *R); /** @brief Add two members from the group G2 * - @param W1 member of G2 - @param W2 member of G2 - @param W member of G2. W = W1+W2 + @param W1 member of G2 + @param W2 member of G2 + @param W member of G2. W = W1+W2 @return Zero for success or else an error code */ int BLS_ZZZ_ADD_G2(octet *W1,octet *W2,octet *W); /** @brief Multiply a member group G1 by an integer * - @param P integer - @param R member of G1 - @param T member of G1. T=P*R + @param P integer + @param R member of G1 + @param T member of G1. T=P*R @return Zero for success or else an error code */ int BLS_ZZZ_MUL_G1(octet *P,octet *R,octet *T); /** @brief Multiply a member group G2 by an integer * - @param P integer - @param R member of G2 - @param T member of G2. T=P*R + @param P integer + @param R member of G2 + @param T member of G2. T=P*R @return Zero for success or else an error code */ int BLS_ZZZ_MUL_G2(octet *P,octet *R,octet *T); +/** @brief Use Shamir's secret sharing to distribute BLS secret keys + * + @param k Threshold + @param n Number of shares + @param RNG Pointer to a cryptographically secure random number generator + @param X Output X values + @param Y Output Y values. Valid BLS secret keys + @param SKI Input secret key to be shared. Ignored if set to NULL + @param SKO Secret key that is shared + @return Zero for success or else an error code + */ +int BLS_ZZZ_MAKE_SHARES(int k, int n, csprng *RNG, octet* X, octet* Y, octet* SKI, octet* SKO); + +/** @brief Use Shamir's secret sharing to recover a BLS secret key + * + @param k Threshold + @param X Output X values + @param Y Output Y values. Valid BLS secret keys + @param SK Secret key that is recovered + @return Zero for success or else an error code + */ +int BLS_ZZZ_RECOVER_SECRET(int k, octet* X, octet* Y, octet* SK); + +/** @brief Use Shamir's secret sharing to recover a BLS signature + * + @param k Threshold + @param X Output X values + @param Y Output Y values. Valid BLS secret keys + @param SIG Signature that is recovered + @return Zero for success or else an error code + */ +int BLS_ZZZ_RECOVER_SIGNATURE(int k, octet* X, octet* Y, octet* SIG); + #endif diff --git a/include/bls192.h.in b/include/bls192.h.in index b7d22cc..88355d0 100644 --- a/include/bls192.h.in +++ b/include/bls192.h.in @@ -109,6 +109,39 @@ int BLS_ZZZ_MUL_G1(octet *P,octet *R,octet *T); */ int BLS_ZZZ_MUL_G2(octet *P,octet *R,octet *T); +/** @brief Use Shamir's secret sharing to distribute BLS secret keys + * + @param k Threshold + @param n Number of shares + @param RNG Pointer to a cryptographically secure random number generator + @param X Output X values + @param Y Output Y values. Valid BLS secret keys + @param SKI Input secret key to be shared. Ignored if set to NULL + @param SKO Secret key that is shared + @return Zero for success or else an error code + */ +int BLS_ZZZ_MAKE_SHARES(int k, int n, csprng *RNG, octet* X, octet* Y, octet* SKI, octet* SKO); + +/** @brief Use Shamir's secret sharing to recover a BLS secret key + * + @param k Threshold + @param X Output X values + @param Y Output Y values. Valid BLS secret keys + @param SK Secret key that is recovered + @return Zero for success or else an error code + */ +int BLS_ZZZ_RECOVER_SECRET(int k, octet* X, octet* Y, octet* SK); + +/** @brief Use Shamir's secret sharing to recover a BLS signature + * + @param k Threshold + @param X Output X values + @param Y Output Y values. Valid BLS secret keys + @param SIG Signature that is recovered + @return Zero for success or else an error code + */ +int BLS_ZZZ_RECOVER_SIGNATURE(int k, octet* X, octet* Y, octet* SIG); + #endif diff --git a/include/bls256.h.in b/include/bls256.h.in index cc2d94e..b5b8add 100644 --- a/include/bls256.h.in +++ b/include/bls256.h.in @@ -109,6 +109,39 @@ int BLS_ZZZ_MUL_G1(octet *P,octet *R,octet *T); */ int BLS_ZZZ_MUL_G2(octet *P,octet *R,octet *T); +/** @brief Use Shamir's secret sharing to distribute BLS secret keys + * + @param k Threshold + @param n Number of shares + @param RNG Pointer to a cryptographically secure random number generator + @param X Output X values + @param Y Output Y values. Valid BLS secret keys + @param SKI Input secret key to be shared. Ignored if set to NULL + @param SKO Secret key that is shared + @return Zero for success or else an error code + */ +int BLS_ZZZ_MAKE_SHARES(int k, int n, csprng *RNG, octet* X, octet* Y, octet* SKI, octet* SKO); + +/** @brief Use Shamir's secret sharing to recover a BLS secret key + * + @param k Threshold + @param X Output X values + @param Y Output Y values. Valid BLS secret keys + @param SK Secret key that is recovered + @return Zero for success or else an error code + */ +int BLS_ZZZ_RECOVER_SECRET(int k, octet* X, octet* Y, octet* SK); + +/** @brief Use Shamir's secret sharing to recover a BLS signature + * + @param k Threshold + @param X Output X values + @param Y Output Y values. Valid BLS secret keys + @param SIG Signature that is recovered + @return Zero for success or else an error code + */ +int BLS_ZZZ_RECOVER_SIGNATURE(int k, octet* X, octet* Y, octet* SIG); + #endif diff --git a/src/bls.c.in b/src/bls.c.in index 6868ba8..1903a58 100644 --- a/src/bls.c.in +++ b/src/bls.c.in @@ -25,6 +25,61 @@ under the License. #include <time.h> #include "bls_ZZZ.h" +// Polynomial interpolation coefficients +static int recover_coefficients(int k, octet* X, octet* COEFS) +{ + BIG_XXX r; + BIG_XXX_rcopy(r,CURVE_Order_ZZZ); + + BIG_XXX x2[k]; + BIG_XXX coefs[k]; + + for(int i=0; i<k; i++) + { + BIG_XXX_fromBytes(x2[i],X[i].val); + } + + for(int i=0; i<k; i++) + { + BIG_XXX numerator; + BIG_XXX_one(numerator); + BIG_XXX denominator; + BIG_XXX_one(denominator); + for(int j=0; j<k; j++) + { + // others = all - current + // current = x2[i] + if (i != j) + { + // numerator = numerator * other + BIG_XXX_modmul(numerator,numerator,x2[j],r); + + // other - current + BIG_XXX s; + BIG_XXX c; + + // c = -current + BIG_XXX_sub(c,r,x2[i]); + BIG_XXX_add(s,x2[j],c); + + // denominator = denominator * s + BIG_XXX_modmul(denominator,denominator,s,r); + + } + + } + BIG_XXX_moddiv(coefs[i], numerator, denominator, r); + } + + // Output coefficients + for(int i=0; i<k; i++) + { + BIG_XXX_toBytes(COEFS[i].val,coefs[i]); + } + return 0; + +} + /* hash a message to an ECP point, using SHA3 */ static void BLS_HASHIT(ECP_ZZZ *P,char *m) { @@ -191,3 +246,164 @@ int BLS_ZZZ_MUL_G2(octet *P,octet *R,octet *T) return BLS_OK; } + +int BLS_ZZZ_MAKE_SHARES(int k, int n, csprng *RNG, octet* X, octet* Y, octet* SKI, octet* SKO) +{ + BIG_XXX y2[n]; + BIG_XXX r; + BIG_XXX_rcopy(r,CURVE_Order_ZZZ); + + // Generate polynomial: f(x) = a_0 + a_1x + a_2x^2 ... a_{k-1}x^{k-1} + BIG_XXX poly[k]; + for(int i=0; i<k; i++) + { + BIG_XXX_randomnum(poly[i],r,RNG); + } + + // Use predefined secret + if (SKI != NULL) + { + BIG_XXX_fromBytes(poly[0],SKI->val); + } + + /* Calculate f(x) = a_0 + a_1x + a_2x^2 ... a_{k-1}x^{k-1} + a0 is the secret */ + int x=0; + for(int j=0; j<n; j++) + { + x++; + BIG_XXX xb; + BIG_XXX_zero(y2[j]); + BIG_XXX_zero(xb); + BIG_XXX_inc(xb,x); + + // Output X shares + BIG_XXX_toBytes(X[j].val,xb); + + // y2[j] is the accmulator + for(int i=k-1; i>=0; i--) + { + BIG_XXX_modmul(y2[j],y2[j],xb,r); + BIG_XXX_add(y2[j],poly[i],y2[j]); + } + } + + // Output Y shares + for(int j=0; j<n; j++) + { + BIG_XXX_toBytes(Y[j].val,y2[j]); + } + + // Output secret + BIG_XXX_toBytes(SKO->val,poly[0]); + + return BLS_OK; +} + +int BLS_ZZZ_RECOVER_SECRET(int k, octet* X, octet* Y, octet* SK) +{ + int rc=0; + BIG_XXX r; + BIG_XXX_rcopy(r,CURVE_Order_ZZZ); + + BIG_XXX y[k]; + BIG_XXX coefs[k]; + + BIG_XXX secret; + BIG_XXX prod; + BIG_XXX_zero(secret); + + char coefs2[k][BGS_ZZZ]; + octet COEFS[k]; + for(int i=0; i<k; i++) + { + memset(&coefs2[i], 0, sizeof(coefs2[i])); + COEFS[i].max = BGS_ZZZ; + COEFS[i].len = BGS_ZZZ; + COEFS[i].val = coefs2[i]; + } + + rc = recover_coefficients(k, X, COEFS); + if (rc) + { + return rc; + } + + for(int i=0; i<k; i++) + { + BIG_XXX_fromBytes(y[i],Y[i].val); + BIG_XXX_fromBytes(coefs[i],COEFS[i].val); + BIG_XXX_modmul(prod,y[i],coefs[i],r); + BIG_XXX_add(secret, secret, prod); + + if (BIG_XXX_comp(secret,r) == 1) + { + BIG_XXX_sub(secret,secret,r); + } + } + + // Output secret + BIG_XXX_toBytes(SK->val,secret); + + return BLS_OK; +} + +int BLS_ZZZ_RECOVER_SIGNATURE(int k, octet* X, octet* Y, octet* SIG) +{ + int rc = 0; + char product[k][BFS_ZZZ+1]; + octet PRODUCT[k]; + + char coefs[k][BGS_ZZZ]; + octet COEFS[k]; + for(int i=0; i<k; i++) + { + memset(&coefs[i], 0, sizeof(coefs[i])); + COEFS[i].max = BGS_ZZZ; + COEFS[i].len = BGS_ZZZ; + COEFS[i].val = coefs[i]; + } + + rc = recover_coefficients(k, X, COEFS); + if (rc) + { + return rc; + } + + + for(int i=0; i<k; i++) + { + memset(&product[i], 0, sizeof(product[i])); + PRODUCT[i].max = BFS_ZZZ+1; + PRODUCT[i].len = BFS_ZZZ+1; + PRODUCT[i].val = product[i]; + } + + for(int i=0; i<k; i++) + { + rc = BLS_ZZZ_MUL_G1(&COEFS[i], &Y[i], &PRODUCT[i]); + if (rc != BLS_OK) + { + return rc; + } + } + + BLS_ZZZ_ADD_G1(&PRODUCT[0],&PRODUCT[1],SIG); + if (rc != BLS_OK) + { + return rc; + } + + for(int i=2; i<k; i++) + { + BLS_ZZZ_ADD_G1(&PRODUCT[i],SIG,SIG); + if (rc != BLS_OK) + { + return rc; + } + } + + return BLS_OK; +} + + diff --git a/src/bls192.c.in b/src/bls192.c.in index 617a94e..1c86954 100644 --- a/src/bls192.c.in +++ b/src/bls192.c.in @@ -25,6 +25,61 @@ under the License. #include <time.h> #include "bls192_ZZZ.h" +// Polynomial interpolation coefficients +static int recover_coefficients(int k, octet* X, octet* COEFS) +{ + BIG_XXX r; + BIG_XXX_rcopy(r,CURVE_Order_ZZZ); + + BIG_XXX x2[k]; + BIG_XXX coefs[k]; + + for(int i=0; i<k; i++) + { + BIG_XXX_fromBytes(x2[i],X[i].val); + } + + for(int i=0; i<k; i++) + { + BIG_XXX numerator; + BIG_XXX_one(numerator); + BIG_XXX denominator; + BIG_XXX_one(denominator); + for(int j=0; j<k; j++) + { + // others = all - current + // current = x2[i] + if (i != j) + { + // numerator = numerator * other + BIG_XXX_modmul(numerator,numerator,x2[j],r); + + // other - current + BIG_XXX s; + BIG_XXX c; + + // c = -current + BIG_XXX_sub(c,r,x2[i]); + BIG_XXX_add(s,x2[j],c); + + // denominator = denominator * s + BIG_XXX_modmul(denominator,denominator,s,r); + + } + + } + BIG_XXX_moddiv(coefs[i], numerator, denominator, r); + } + + // Output coefficients + for(int i=0; i<k; i++) + { + BIG_XXX_toBytes(COEFS[i].val,coefs[i]); + } + return 0; + +} + /* hash a message to an ECP point, using SHA3 */ static void BLS_HASHIT(ECP_ZZZ *P,char *m) { @@ -191,3 +246,164 @@ int BLS_ZZZ_MUL_G2(octet *P,octet *R,octet *T) return BLS_OK; } + +int BLS_ZZZ_MAKE_SHARES(int k, int n, csprng *RNG, octet* X, octet* Y, octet* SKI, octet* SKO) +{ + BIG_XXX y2[n]; + BIG_XXX r; + BIG_XXX_rcopy(r,CURVE_Order_ZZZ); + + // Generate polynomial: f(x) = a_0 + a_1x + a_2x^2 ... a_{k-1}x^{k-1} + BIG_XXX poly[k]; + for(int i=0; i<k; i++) + { + BIG_XXX_randomnum(poly[i],r,RNG); + } + + // Use predefined secret + if (SKI != NULL) + { + BIG_XXX_fromBytes(poly[0],SKI->val); + } + + /* Calculate f(x) = a_0 + a_1x + a_2x^2 ... a_{k-1}x^{k-1} + a0 is the secret */ + int x=0; + for(int j=0; j<n; j++) + { + x++; + BIG_XXX xb; + BIG_XXX_zero(y2[j]); + BIG_XXX_zero(xb); + BIG_XXX_inc(xb,x); + + // Output X shares + BIG_XXX_toBytes(X[j].val,xb); + + // y2[j] is the accmulator + for(int i=k-1; i>=0; i--) + { + BIG_XXX_modmul(y2[j],y2[j],xb,r); + BIG_XXX_add(y2[j],poly[i],y2[j]); + } + } + + // Output Y shares + for(int j=0; j<n; j++) + { + BIG_XXX_toBytes(Y[j].val,y2[j]); + } + + // Output secret + BIG_XXX_toBytes(SKO->val,poly[0]); + + return BLS_OK; +} + +int BLS_ZZZ_RECOVER_SECRET(int k, octet* X, octet* Y, octet* SK) +{ + int rc=0; + BIG_XXX r; + BIG_XXX_rcopy(r,CURVE_Order_ZZZ); + + BIG_XXX y[k]; + BIG_XXX coefs[k]; + + BIG_XXX secret; + BIG_XXX prod; + BIG_XXX_zero(secret); + + char coefs2[k][BGS_ZZZ]; + octet COEFS[k]; + for(int i=0; i<k; i++) + { + memset(&coefs2[i], 0, sizeof(coefs2[i])); + COEFS[i].max = BGS_ZZZ; + COEFS[i].len = BGS_ZZZ; + COEFS[i].val = coefs2[i]; + } + + rc = recover_coefficients(k, X, COEFS); + if (rc) + { + return rc; + } + + for(int i=0; i<k; i++) + { + BIG_XXX_fromBytes(y[i],Y[i].val); + BIG_XXX_fromBytes(coefs[i],COEFS[i].val); + BIG_XXX_modmul(prod,y[i],coefs[i],r); + BIG_XXX_add(secret, secret, prod); + + if (BIG_XXX_comp(secret,r) == 1) + { + BIG_XXX_sub(secret,secret,r); + } + } + + // Output secret + BIG_XXX_toBytes(SK->val,secret); + + return BLS_OK; +} + +int BLS_ZZZ_RECOVER_SIGNATURE(int k, octet* X, octet* Y, octet* SIG) +{ + int rc = 0; + char product[k][BFS_ZZZ+1]; + octet PRODUCT[k]; + + char coefs[k][BGS_ZZZ]; + octet COEFS[k]; + for(int i=0; i<k; i++) + { + memset(&coefs[i], 0, sizeof(coefs[i])); + COEFS[i].max = BGS_ZZZ; + COEFS[i].len = BGS_ZZZ; + COEFS[i].val = coefs[i]; + } + + rc = recover_coefficients(k, X, COEFS); + if (rc) + { + return rc; + } + + + for(int i=0; i<k; i++) + { + memset(&product[i], 0, sizeof(product[i])); + PRODUCT[i].max = BFS_ZZZ+1; + PRODUCT[i].len = BFS_ZZZ+1; + PRODUCT[i].val = product[i]; + } + + for(int i=0; i<k; i++) + { + rc = BLS_ZZZ_MUL_G1(&COEFS[i], &Y[i], &PRODUCT[i]); + if (rc != BLS_OK) + { + return rc; + } + } + + BLS_ZZZ_ADD_G1(&PRODUCT[0],&PRODUCT[1],SIG); + if (rc != BLS_OK) + { + return rc; + } + + for(int i=2; i<k; i++) + { + BLS_ZZZ_ADD_G1(&PRODUCT[i],SIG,SIG); + if (rc != BLS_OK) + { + return rc; + } + } + + return BLS_OK; +} + + diff --git a/src/bls256.c.in b/src/bls256.c.in index 18a8ab2..8e3ca1e 100644 --- a/src/bls256.c.in +++ b/src/bls256.c.in @@ -25,6 +25,61 @@ under the License. #include <time.h> #include "bls256_ZZZ.h" +// Polynomial interpolation coefficients +static int recover_coefficients(int k, octet* X, octet* COEFS) +{ + BIG_XXX r; + BIG_XXX_rcopy(r,CURVE_Order_ZZZ); + + BIG_XXX x2[k]; + BIG_XXX coefs[k]; + + for(int i=0; i<k; i++) + { + BIG_XXX_fromBytes(x2[i],X[i].val); + } + + for(int i=0; i<k; i++) + { + BIG_XXX numerator; + BIG_XXX_one(numerator); + BIG_XXX denominator; + BIG_XXX_one(denominator); + for(int j=0; j<k; j++) + { + // others = all - current + // current = x2[i] + if (i != j) + { + // numerator = numerator * other + BIG_XXX_modmul(numerator,numerator,x2[j],r); + + // other - current + BIG_XXX s; + BIG_XXX c; + + // c = -current + BIG_XXX_sub(c,r,x2[i]); + BIG_XXX_add(s,x2[j],c); + + // denominator = denominator * s + BIG_XXX_modmul(denominator,denominator,s,r); + + } + + } + BIG_XXX_moddiv(coefs[i], numerator, denominator, r); + } + + // Output coefficients + for(int i=0; i<k; i++) + { + BIG_XXX_toBytes(COEFS[i].val,coefs[i]); + } + return 0; + +} + /* hash a message to an ECP point, using SHA3 */ static void BLS_HASHIT(ECP_ZZZ *P,char *m) { @@ -191,3 +246,164 @@ int BLS_ZZZ_MUL_G2(octet *P,octet *R,octet *T) return BLS_OK; } + +int BLS_ZZZ_MAKE_SHARES(int k, int n, csprng *RNG, octet* X, octet* Y, octet* SKI, octet* SKO) +{ + BIG_XXX y2[n]; + BIG_XXX r; + BIG_XXX_rcopy(r,CURVE_Order_ZZZ); + + // Generate polynomial: f(x) = a_0 + a_1x + a_2x^2 ... a_{k-1}x^{k-1} + BIG_XXX poly[k]; + for(int i=0; i<k; i++) + { + BIG_XXX_randomnum(poly[i],r,RNG); + } + + // Use predefined secret + if (SKI != NULL) + { + BIG_XXX_fromBytes(poly[0],SKI->val); + } + + /* Calculate f(x) = a_0 + a_1x + a_2x^2 ... a_{k-1}x^{k-1} + a0 is the secret */ + int x=0; + for(int j=0; j<n; j++) + { + x++; + BIG_XXX xb; + BIG_XXX_zero(y2[j]); + BIG_XXX_zero(xb); + BIG_XXX_inc(xb,x); + + // Output X shares + BIG_XXX_toBytes(X[j].val,xb); + + // y2[j] is the accmulator + for(int i=k-1; i>=0; i--) + { + BIG_XXX_modmul(y2[j],y2[j],xb,r); + BIG_XXX_add(y2[j],poly[i],y2[j]); + } + } + + // Output Y shares + for(int j=0; j<n; j++) + { + BIG_XXX_toBytes(Y[j].val,y2[j]); + } + + // Output secret + BIG_XXX_toBytes(SKO->val,poly[0]); + + return BLS_OK; +} + +int BLS_ZZZ_RECOVER_SECRET(int k, octet* X, octet* Y, octet* SK) +{ + int rc=0; + BIG_XXX r; + BIG_XXX_rcopy(r,CURVE_Order_ZZZ); + + BIG_XXX y[k]; + BIG_XXX coefs[k]; + + BIG_XXX secret; + BIG_XXX prod; + BIG_XXX_zero(secret); + + char coefs2[k][BGS_ZZZ]; + octet COEFS[k]; + for(int i=0; i<k; i++) + { + memset(&coefs2[i], 0, sizeof(coefs2[i])); + COEFS[i].max = BGS_ZZZ; + COEFS[i].len = BGS_ZZZ; + COEFS[i].val = coefs2[i]; + } + + rc = recover_coefficients(k, X, COEFS); + if (rc) + { + return rc; + } + + for(int i=0; i<k; i++) + { + BIG_XXX_fromBytes(y[i],Y[i].val); + BIG_XXX_fromBytes(coefs[i],COEFS[i].val); + BIG_XXX_modmul(prod,y[i],coefs[i],r); + BIG_XXX_add(secret, secret, prod); + + if (BIG_XXX_comp(secret,r) == 1) + { + BIG_XXX_sub(secret,secret,r); + } + } + + // Output secret + BIG_XXX_toBytes(SK->val,secret); + + return BLS_OK; +} + +int BLS_ZZZ_RECOVER_SIGNATURE(int k, octet* X, octet* Y, octet* SIG) +{ + int rc = 0; + char product[k][BFS_ZZZ+1]; + octet PRODUCT[k]; + + char coefs[k][BGS_ZZZ]; + octet COEFS[k]; + for(int i=0; i<k; i++) + { + memset(&coefs[i], 0, sizeof(coefs[i])); + COEFS[i].max = BGS_ZZZ; + COEFS[i].len = BGS_ZZZ; + COEFS[i].val = coefs[i]; + } + + rc = recover_coefficients(k, X, COEFS); + if (rc) + { + return rc; + } + + + for(int i=0; i<k; i++) + { + memset(&product[i], 0, sizeof(product[i])); + PRODUCT[i].max = BFS_ZZZ+1; + PRODUCT[i].len = BFS_ZZZ+1; + PRODUCT[i].val = product[i]; + } + + for(int i=0; i<k; i++) + { + rc = BLS_ZZZ_MUL_G1(&COEFS[i], &Y[i], &PRODUCT[i]); + if (rc != BLS_OK) + { + return rc; + } + } + + BLS_ZZZ_ADD_G1(&PRODUCT[0],&PRODUCT[1],SIG); + if (rc != BLS_OK) + { + return rc; + } + + for(int i=2; i<k; i++) + { + BLS_ZZZ_ADD_G1(&PRODUCT[i],SIG,SIG); + if (rc != BLS_OK) + { + return rc; + } + } + + return BLS_OK; +} + + diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 9636194..c350acc 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -209,6 +209,7 @@ foreach(curve ${AMCL_CURVE}) ################################################ if(BUILD_BLS) amcl_curve_test(${curve} test_bls_${TC} test_bls_ZZZ.c.in amcl_bls_${TC} "SUCCESS") + amcl_curve_test(${curve} test_bls_sss_${TC} test_bls_sss_ZZZ.c.in amcl_bls_${TC} "SUCCESS") endif() endif() diff --git a/test/test_bls_ZZZ.c.in b/test/test_bls_ZZZ.c.in index 92c4154..6a85fa8 100644 --- a/test/test_bls_ZZZ.c.in +++ b/test/test_bls_ZZZ.c.in @@ -44,7 +44,7 @@ static char message[]="test message"; -int bls(csprng *RNG) +int test(csprng *RNG) { int rc; @@ -278,8 +278,8 @@ int main() // initialise strong RNG CREATE_CSPRNG(&RNG,&SEED); - printf("\nTesting BLS signature for curve ZZZ\n"); - if (!bls(&RNG)) + printf("\nTest BLS for curve ZZZ\n"); + if (!test(&RNG)) { printf("SUCCESS\n"); } diff --git a/test/test_bls_sss_ZZZ.c.in b/test/test_bls_sss_ZZZ.c.in new file mode 100644 index 0000000..d7c6fc1 --- /dev/null +++ b/test/test_bls_sss_ZZZ.c.in @@ -0,0 +1,243 @@ +/* + 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. +*/ + +// smoke test for BLS SSS + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "config_curve_ZZZ.h" +#include "randapi.h" + +#if CURVE_SECURITY_ZZZ == 128 +#include "bls_ZZZ.h" +#elif CURVE_SECURITY_ZZZ == 192 +#include "bls192_ZZZ.h" +#elif CURVE_SECURITY_ZZZ == 256 +#include "bls256_ZZZ.h" +#endif + +// Support multiple security levels +#if CURVE_SECURITY_ZZZ == 128 +#define G2LEN 4*BFS_ZZZ +#elif CURVE_SECURITY_ZZZ == 192 +#define G2LEN 8*BFS_ZZZ +#elif CURVE_SECURITY_ZZZ == 256 +#define G2LEN 16*BFS_ZZZ +#endif + +static char message[]="test message"; + +int test(csprng *RNG) +{ + int rc; + int n=4; + int k=3; + + char ski[BGS_ZZZ]; + octet SKI = {0,sizeof(ski),ski}; + char pki[G2LEN]; + octet PKI = {0,sizeof(pki),pki}; + + char sko[BGS_ZZZ]; + octet SKO = {sizeof(sko),sizeof(sko),sko}; + char skr[BGS_ZZZ]; + octet SKR = {sizeof(skr),sizeof(skr),skr}; + + char sigi[BFS_ZZZ+1]; + octet SIGI = {0,sizeof(sigi),sigi}; + char sigr[BFS_ZZZ+1]; + octet SIGR = {0,sizeof(sigr),sigr}; + + // Secret shares + char x[n][BGS_ZZZ]; + octet X[n]; + char y[n][BGS_ZZZ]; + octet Y[n]; + + for(int i=0; i<n; i++) + { + memset(&y[i], 0, sizeof(y[i])); + Y[i].max = BGS_ZZZ; + Y[i].len = BGS_ZZZ; + Y[i].val = y[i]; + memset(&x[i], 0, sizeof(x[i])); + X[i].max = BGS_ZZZ; + X[i].len = BGS_ZZZ; + X[i].val = x[i]; + } + + // Generate key pair + BLS_ZZZ_KEY_PAIR_GENERATE(RNG,&SKI,&PKI); + + printf("Private key SKI: "); + OCT_output(&SKI); + printf("Public key PKI: "); + OCT_output(&PKI); + printf("\n"); + + // Sign the message + BLS_ZZZ_SIGN(&SIGI,message,&SKI); + + printf("SIGI: "); + OCT_output(&SIGI); + + // Verify signature + rc=BLS_ZZZ_VERIFY(&SIGI,message,&PKI); + if (rc!=BLS_OK) + { + printf("Test Failed Invalid Signature\n"); + return 1; + } + printf("Test Passed valid signature is valid\n"); + + // Make shares of BLS secret key + rc = BLS_ZZZ_MAKE_SHARES(k, n, RNG, X, Y, &SKI, &SKO); + if (rc!=BLS_OK) + { + printf("Test Failed BLS_ZZZ_MAKE_SHARES\n"); + return 1; + } + printf("Test Passed BLS_ZZZ_MAKE_SHARES\n"); + + for(int i=0; i<n; i++) + { + printf("X[%d] ", i); + OCT_output(&X[i]); + printf("Y[%d] ", i); + OCT_output(&Y[i]); + } + + printf("SKO: "); + OCT_output(&SKO); + + if (!OCT_comp(&SKI,&SKO)) + { + printf("Test Failed SKI != SKO\n"); + return 1; + } + printf("Test Passed SKI == SKO\n"); + + // Recover BLS secret key + rc = BLS_ZZZ_RECOVER_SECRET(k, X, Y, &SKR); + if (rc!=BLS_OK) + { + printf("Test Failed BLS_ZZZ_RECOVER_SECRET\n"); + return 1; + } + printf("Test Passed BLS_ZZZ_RECOVER_SECRET\n"); + printf("SKR: "); + OCT_output(&SKR); + + if (!OCT_comp(&SKR,&SKO)) + { + printf("Test Failed SKR != SKO\n"); + return 1; + } + printf("Test Passed SKR == SKO\n"); + + // Generate public keys and signatures using shares + char pks[n][G2LEN]; + octet PKS[n]; + char sigs[n][BFS_ZZZ+1]; + octet SIGS[n]; + for(int i=0; i<n; i++) + { + memset(&sigs[i], 0, sizeof(sigs[i])); + SIGS[i].max = BFS_ZZZ+1; + SIGS[i].len = BFS_ZZZ+1; + SIGS[i].val = sigs[i]; + memset(&PKS[i], 0, sizeof(PKS[i])); + PKS[i].max = G2LEN; + PKS[i].len = G2LEN; + PKS[i].val = pks[i]; + BLS_ZZZ_KEY_PAIR_GENERATE(NULL,&Y[i],&PKS[i]); + BLS_ZZZ_SIGN(&SIGS[i],message,&Y[i]); + } + + for(int i=0; i<n; i++) + { + printf("PKS[%d] ", i); + OCT_output(&PKS[i]); + } + + for(int i=0; i<n; i++) + { + printf("SIGS[%d] ", i); + OCT_output(&SIGS[i]); + } + printf("\n\n"); + + // Recover BLS signature + rc = BLS_ZZZ_RECOVER_SIGNATURE(k, X, SIGS, &SIGR); + if (rc!=BLS_OK) + { + printf("Test Failed BLS_ZZZ_RECOVER_SIGNATURE\n"); + return 1; + } + printf("Test Passed BLS_ZZZ_RECOVER_SIGNATURE\n"); + printf("SIGR: "); + OCT_output(&SIGR); + + if (!OCT_comp(&SIGR,&SIGI)) + { + printf("Test Failed SIGR != SIGI\n"); + return 1; + } + printf("Test Passed SIGR == SIGI\n"); + + return 0; +} + + +int main() +{ +#ifdef DEBUG + printf("%d bit build\n",CHUNK); +#endif + + char* seedHex = "78d0fb6705ce77dee47d03eb5b9c5d30"; + char seed[16] = {0}; + octet SEED = {sizeof(seed),sizeof(seed),seed}; + + // CSPRNG + csprng RNG; + + // fake random source + OCT_fromHex(&SEED,seedHex); + printf("SEED: "); + OCT_output(&SEED); + + // initialise strong RNG + CREATE_CSPRNG(&RNG,&SEED); + + printf("\nTest BLS SSS for curve ZZZ\n"); + if (!test(&RNG)) + { + printf("SUCCESS\n"); + } + else + { + printf("FAILURE\n"); + } + + KILL_CSPRNG(&RNG); +} + +
