Skip to content

Commit

Permalink
C implementation of mercurial sigs
Browse files Browse the repository at this point in the history
  • Loading branch information
burkh4rt committed Aug 7, 2020
1 parent c12f8e7 commit dfd8591
Show file tree
Hide file tree
Showing 2 changed files with 173 additions and 0 deletions.
11 changes: 11 additions & 0 deletions c/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
cmake_minimum_required(VERSION 3.15)
project(dac_hg_sigs LANGUAGES C)

set(CMAKE_C_STANDARD 99)
set(CMAKE_C_FLAGS "-O3" )
set(CMAKE_C_COMPILER /usr/bin/gcc)

add_subdirectory(miracl_core_c_bn254/)
add_executable(dac_hg_sigs mercurial_signature_scheme.c)

target_link_libraries(dac_hg_sigs miracl_core_c_bn254)
162 changes: 162 additions & 0 deletions c/mercurial_signature_scheme.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
#include <assert.h>

#include "miracl_core_c_bn254/pair_BN254.h"
#include "miracl_core_c_bn254/big_256_56.h"

typedef ECP_BN254 ECP;
typedef ECP2_BN254 ECP2;
typedef FP12_BN254 FP12;
typedef BIG_256_56 BIG;

/* signature type */
typedef struct {ECP Z; ECP Y; ECP2 Yhat;} sigma_t;

/* public parameters */
typedef struct {ECP P; ECP2 Phat; BIG r;} PP_t;

/* hard-code key (& message) length */
#define ell 4

/* generate public key pk, secret key sk pairing as arrays of length ell */
void KeyGen(PP_t * PP, ECP2 *pk, BIG *sk, csprng *rng) {
for (int i = 0; i < ell; i++) {
BIG_256_56_randomnum(sk[i], PP->r, rng);
ECP2_BN254_copy(&pk[i], &PP->Phat);
ECP2_BN254_mul(&pk[i], sk[i]);
};
};

/* sign a message M with sk */
void Sign(PP_t * PP, BIG *sk, ECP * M, sigma_t * sigma, csprng *rng) {
BIG y, y_inv;
ECP factor;
BIG_256_56_randomnum(y, PP->r, rng);
BIG_256_56_invmodp(y_inv, y, PP->r);
ECP_BN254_copy(&(sigma->Z), &M[0]);
ECP_BN254_mul(&(sigma->Z), sk[0]);
for (int i = 1; i < ell; i++) {
ECP_BN254_copy(&factor, &M[i]);
ECP_BN254_mul(&factor,sk[i]);
ECP_BN254_add(&(sigma->Z),&factor);
};
ECP_BN254_mul(&(sigma->Z),y);
ECP_BN254_copy(&(sigma->Y), &PP->P);
ECP2_BN254_copy(&(sigma->Yhat), &PP->Phat);
ECP_BN254_mul(&(sigma->Y), y_inv);
ECP2_BN254_mul(&(sigma->Yhat), y_inv);
};

/* verify that signature sigma is valid for pk and M */
bool Verify(PP_t * PP, ECP2 *pk, ECP * M, sigma_t * sigma) {
FP12 q1, q2, q3, q4, factor;
PAIR_BN254_ate(&q1, &pk[0], &M[0]);
PAIR_BN254_fexp(&q1);
for (int i = 1; i < ell; i++) {
PAIR_BN254_ate(&factor, &pk[i], &M[i]);
PAIR_BN254_fexp(&factor);
FP12_BN254_mul(&q1, &factor);
};
PAIR_BN254_ate(&q2, &(sigma->Yhat), &(sigma->Z));
PAIR_BN254_fexp(&q2);
PAIR_BN254_ate(&q3, &PP->Phat, &(sigma->Y));
PAIR_BN254_fexp(&q3);
PAIR_BN254_ate(&q4, &(sigma->Yhat), &PP->P);
PAIR_BN254_fexp(&q4);
return (bool) FP12_BN254_equals(&q1,&q2) & (bool) FP12_BN254_equals(&q3,&q4);
};

/* convert sk with randomness rho */
void ConvertSK(PP_t * PP, BIG *sk, BIG rho) {
for (int i = 0; i < ell; i++) {
BIG_256_56_modmul(sk[i], sk[i], rho, PP->r);
};
};

/* convert pk with randomness rho */
void ConvertPK(PP_t * PP, ECP2 *pk, BIG rho) {
for (int i = 0; i < ell; i++) {
ECP2_BN254_mul(&pk[i], rho);
};
};

/* convert signature sigma */
void ConvertSig(PP_t * PP, ECP2 *pk, ECP * M, sigma_t * sigma, BIG rho, csprng *rng) {
BIG psi, psi_inv;
BIG_256_56_randomnum(psi, PP->r, rng);
BIG_256_56_invmodp(psi_inv, psi, PP->r);
ECP_BN254_mul(&(sigma->Z), rho);
ECP_BN254_mul(&(sigma->Z), psi);
ECP_BN254_mul(&(sigma->Y), psi_inv);
ECP2_BN254_mul(&(sigma->Yhat), psi_inv);
};

/* change representation of equivalence class for M & sigma */
void ChangeRep(PP_t * PP, ECP2 *pk, ECP * M, sigma_t * sigma, BIG mu, csprng *rng) {
BIG psi, psi_inv;
BIG_256_56_randomnum(psi, PP->r, rng);
BIG_256_56_invmodp(psi_inv, psi, PP->r);
for (int i = 0; i < ell; i++) {
ECP_BN254_mul(&M[i], mu);
};
ECP_BN254_mul(&(sigma->Z), mu);
ECP_BN254_mul(&(sigma->Z), psi);
ECP_BN254_mul(&(sigma->Y), psi_inv);
ECP2_BN254_mul(&(sigma->Yhat), psi_inv);
};


int main() {
// initialize rng
csprng RNG;
char pr[10];
for (int i = 1; i < 10; i++) pr[i] = (char) random();
RAND_seed(&RNG, 10, pr);

// initialize scheme public parameters
PP_t PP;
ECP2_BN254_generator(&PP.Phat);
ECP_BN254_generator(&PP.P);
BIG_256_56_rcopy(PP.r, CURVE_Order_BN254);

// allocate signature
sigma_t sigma;

// generate random message
ECP M[ell];
BIG rand;
for (int j=0; j<ell; j++) {
BIG_256_56_randomnum(rand, PP.r, &RNG);
ECP_BN254_hap2point(&M[j], rand);
}


// test KeyGen(), Sign(), and Verify()
BIG sk[ell];
ECP2 pk[ell];
KeyGen(&PP, pk, sk, &RNG);
Sign(&PP,sk,M,&sigma,&RNG);
assert(Verify(&PP,pk,M,&sigma));

// test ConvertPK() and ConvertSig()
BIG rho;
BIG_256_56_randomnum(rho, PP.r, &RNG);
ConvertPK(&PP,pk, rho);
ConvertSig(&PP,pk,M,&sigma,rho,&RNG);
assert(Verify(&PP,pk,M,&sigma));

// test ChangeRep()
BIG mu;
BIG_256_56_randomnum(mu, PP.r, &RNG);
ChangeRep(&PP,pk,M,&sigma,mu,&RNG);
assert(Verify(&PP,pk,M,&sigma));

// test ConvertSK(), ConvertPK(), and Verify
KeyGen(&PP, pk, sk, &RNG);
BIG_256_56_randomnum(rho, PP.r, &RNG);
ConvertPK(&PP,pk, rho);
ConvertSK(&PP,sk, rho);
Sign(&PP,sk,M,&sigma,&RNG);
assert(Verify(&PP,pk,M,&sigma));

return 0;
}

0 comments on commit dfd8591

Please sign in to comment.