kokke / tiny-ECDH-c

Small portable Elliptic-Curve Diffie-Hellman in C
The Unlicense
254 stars 65 forks source link

7 of 10 "working" #28

Closed smurfd closed 2 years ago

smurfd commented 2 years ago

hey, love your stuff. Very readable code!

have however botched it some and rewrote the sign and verify functions where i got these below to "match". I write in quotes because i have tried to dumb it down as much as possible and i probably skip some important steps... also thought maby it could spark some idea for you :)

#define ECC_CURVE NIST_B163
#define ECC_CURVE NIST_K163
#define ECC_CURVE NIST_B233
#define ECC_CURVE NIST_K233
#define ECC_CURVE NIST_K409
#define ECC_CURVE NIST_B571
#define ECC_CURVE NIST_K571

ecdh_example.c

sign((const uint8_t*)prv, msg, k, signature);
verify((const uint8_t*)pub, msg, (const uint8_t*)signature);

ecdh.c

void compress_signature(uint8_t* sig1, uint8_t* sig2, uint8_t* signature) {
  for (int i=0; i<ECC_PRV_KEY_SIZE; i++) {
    signature[i] = sig1[i];
    signature[i+ECC_PRV_KEY_SIZE] = sig2[i];
  }
}

void decompress_signature(const uint8_t* signature, uint8_t* sig1, uint8_t* sig2) {
  for (int i=0; i<ECC_PRV_KEY_SIZE; i++) {
    sig1[i] = signature[i];
    sig2[i] = signature[i+ECC_PRV_KEY_SIZE];
  }
}

void sign(const uint8_t* private_key, uint8_t* hash, uint8_t* random_k, uint8_t* signature) {
  gf2elem_t r, s, z, k;
  uint8_t sig1[ECC_PRV_KEY_SIZE], sig2[ECC_PRV_KEY_SIZE];
  int nbits = bitvec_degree(base_order);

  bitvec_set_zero(r);
  bitvec_set_zero(s);
  bitvec_copy(z, (uint32_t*)hash);

  for (int i = (nbits - 1); i < BITVEC_NBITS; ++i) {
    bitvec_clr_bit(z, i);
  }
  bitvec_copy(k, (uint32_t*)random_k);

  gf2point_copy(r, s, base_x, base_y);
  gf2point_mul(r, s, k);

  gf2field_inv(s, k);
  gf2field_mul(r, r, (uint32_t*)private_key);
  gf2field_add(r, r, z);
  nbits = bitvec_degree(r);
  for (int i = (nbits - 1); i < BITVEC_NBITS; ++i) {
    bitvec_clr_bit(r, i);
  }
  gf2field_mul(s, s, r);
  nbits = bitvec_degree(s);
  bitvec_copy((uint32_t*)sig1, (uint32_t*)r);
  bitvec_copy((uint32_t*)sig2, (uint32_t*)s);
  compress_signature(sig1, sig2, signature);
}

void verify(const uint8_t* public_key, uint8_t* hash, const uint8_t* signature) {
  gf2elem_t r, s, z, k, w, u1, u2, x, y;
  uint8_t rr[ECC_PRV_KEY_SIZE], ss[ECC_PRV_KEY_SIZE];  
  int nbits = bitvec_degree(base_order);

  bitvec_copy(z, (uint32_t*)hash);
  decompress_signature(signature, rr, ss); 
  bitvec_copy(r, (uint32_t*)rr);
  bitvec_copy(s, (uint32_t*)ss);

  gf2field_inv(w, s);
  gf2field_mul(u1, z, w);
  gf2field_mul(u2, r, w);

  bitvec_degree(u1);
  bitvec_degree(u2);

  bitvec_copy(x, base_x);
  bitvec_copy(y, base_y);

  gf2point_mul(u1, u1, x);
  gf2point_mul(u2, u2, (uint32_t*)public_key);
  gf2point_add(x, y, u1, u2);

  if (bitvec_degree(r) == bitvec_degree(x)) {
    printf("Matching\n"); 
  } else {
    printf("Not matching\n");
  } 
}