Browse Source

eddsa key generation, at least for goldilocks. needs parameterized hash function; sign/verify; rename; put in right place

master
Michael Hamburg 9 years ago
parent
commit
d0e74a585a
5 changed files with 157 additions and 3 deletions
  1. +1
    -1
      Makefile
  2. +54
    -2
      src/per_curve/decaf.tmpl.c
  3. +33
    -0
      src/per_curve/decaf.tmpl.h
  4. +19
    -0
      src/per_curve/decaf.tmpl.hxx
  5. +50
    -0
      test/test_decaf.cxx

+ 1
- 1
Makefile View File

@@ -166,7 +166,7 @@ endef
define define_curve

LIBCOMPONENTS += $$(BUILD_OBJ)/$(1)/decaf.o $$(BUILD_OBJ)/$(1)/elligator.o $$(BUILD_OBJ)/$(1)/scalar.o \
$$(BUILD_OBJ)/$(1)/crypto.o $$(BUILD_OBJ)/$(1)/decaf_tables.o
$$(BUILD_OBJ)/$(1)/crypto.o $$(BUILD_OBJ)/$(1)/eddsa.o $$(BUILD_OBJ)/$(1)/decaf_tables.o
PER_OBJ_DIRS += $$(BUILD_OBJ)/$(1)
GLOBAL_HEADERS_OF_$(1) = $(BUILD_INC)/decaf/decaf_$(3).h $(BUILD_INC)/decaf/decaf_$(3).hxx \
$(BUILD_INC)/decaf/crypto_$(3).h $(BUILD_INC)/decaf/crypto_$(3).hxx


+ 54
- 2
src/per_curve/decaf.tmpl.c View File

@@ -91,7 +91,6 @@ gf_invert(gf y, const gf x) {
gf_copy(y, t2);
}

#if COFACTOR==8
/** Return high bit of x = low bit of 2x mod p */
static mask_t gf_lobit(const gf x) {
gf y;
@@ -99,7 +98,6 @@ static mask_t gf_lobit(const gf x) {
gf_strong_reduce(y);
return -(y->limb[0]&1);
}
#endif

/** identity = (0,1) */
const point_t API_NS(point_identity) = {{{{{0}}},{{{1}}},{{{1}}},{{{0}}}}};
@@ -1046,6 +1044,60 @@ decaf_error_t API_NS(direct_scalarmul) (
return succ;
}

void API_NS(point_encode_like_eddsa) (
uint8_t enc[$(C_NS)_EDDSA_PUBLIC_BYTES],
const point_t p
) {
/* The point is now on the twisted curve. Move it to untwisted. */
gf x, y, z, t;
#if IMAGINE_TWIST
{
/* TODO: make sure cofactor is clear */
point_t q;
API_NS(point_double)(q,p);
gf_div_qnr(x, q->x);
gf_copy(y, q->y);
gf_copy(z, q->z);
API_NS(point_destroy(q));
}
#else
{
/* 4-isogeny: 2xy/(y^+x^2), (y^2-x^2)/(2z^2-y^2+x^2) */
gf u;
gf_sqr ( x, p->x );
gf_sqr ( t, p->y );
gf_add( u, x, t ); // x^2 + y^2
gf_add( z, p->y, p->x );
gf_sqr ( y, z); // (x+y)^2
gf_sub ( y, y, u ); // 2xy
gf_sub ( z, t, x ); // y^2 - x^2
gf_sqr ( x, p->z ); // z^2
gf_add ( t, x, x); // 2z^2
gf_sub ( t, t, z); // 2z^2 - y^2 + x^2
gf_mul ( x, t, y ); // (2z^2 - y^2 + x^2)(2xy)
gf_mul ( y, z, u ); // (y^2 - x^2)(x^2 + y^2)
gf_mul ( z, u, t ); // (x^2 + y^2)(2z^2 - y^2 + x^2)
decaf_bzero(t,sizeof(u));
}
#endif
/* Affinize */
gf_invert(z,z);
gf_mul(t,x,z);
gf_mul(x,y,z);
/* Encode */
enc[$(C_NS)_EDDSA_PRIVATE_BYTES-1] = 0;
gf_serialize(enc, x, 1);
enc[$(C_NS)_EDDSA_PRIVATE_BYTES-1] |= 0x80 &~ gf_lobit(t);

decaf_bzero(x,sizeof(x));
decaf_bzero(y,sizeof(y));
decaf_bzero(z,sizeof(z));
decaf_bzero(t,sizeof(t));
}

decaf_error_t API_NS(x_direct_scalarmul) (
uint8_t out[X_PUBLIC_BYTES],
const uint8_t base[X_PUBLIC_BYTES],


+ 33
- 0
src/per_curve/decaf.tmpl.h View File

@@ -37,6 +37,16 @@ typedef struct gf_$(gf_shortname)_s {
/** Number of bits in the "which" field of an elligator inverse */
#define $(C_NS)_INVERT_ELLIGATOR_WHICH_BITS $(ceil_log2(cofactor) + 7 + elligator_onto - ((gf_bits-2) % 8))

/* TODO: move to a different file? */
/** Number of bytes in an EdDSA public key. */
#define $(C_NS)_EDDSA_PUBLIC_BYTES $((gf_bits)/8 + 1) /* TODO: change name? */

/** Number of bytes in an EdDSA private key. */
#define $(C_NS)_EDDSA_PRIVATE_BYTES $(C_NS)_EDDSA_PUBLIC_BYTES /* TODO: change name? */

/** Number of bytes in an EdDSA private key. */
#define $(C_NS)_EDDSA_SIGNATURE_BYTES ($(C_NS)_PUBLIC_BYTES + $(C_NS)_PRIVATE_BYTES) /* TODO: change name? */

/** Number of bytes in an x$(gf_shortname) public key */
#define X$(gf_shortname)_PUBLIC_BYTES $((gf_bits-1)/8 + 1)

@@ -404,6 +414,29 @@ void $(c_ns)_x_base_scalarmul (
const uint8_t scalar[X$(gf_shortname)_PRIVATE_BYTES]
) API_VIS NONNULL NOINLINE;

/**
* @brief EdDSA key generation. This function uses a different (non-Decaf)
* encoding.
*
* @param [out] pubkey The public key.
* @param [in] privkey The private key.
*/
void $(c_ns)_eddsa_derive_public_key (
uint8_t pubkey[$(C_NS)_EDDSA_PUBLIC_BYTES],
const uint8_t privkey[$(C_NS)_EDDSA_PRIVATE_BYTES]
) API_VIS NONNULL NOINLINE;

/**
* @brief EdDSA point encoding.
*
* @param [out] enc The encoded point.
* @param [in] p The point.
*/
void $(c_ns)_point_encode_like_eddsa (
uint8_t enc[$(C_NS)_EDDSA_PUBLIC_BYTES],
const $(c_ns)_point_t p
) API_VIS NONNULL NOINLINE;

/**
* @brief Precompute a table for fast scalar multiplication.
* Some implementations do not include precomputed points; for


+ 19
- 0
src/per_curve/decaf.tmpl.hxx View File

@@ -649,6 +649,25 @@ public:
}
};


struct EdDSA {
public:
/** The size of a public key */
static const size_t PUBLIC_BYTES = $(C_NS)_EDDSA_PUBLIC_BYTES;
/** The size of a private key */
static const size_t PRIVATE_BYTES = $(C_NS)_EDDSA_PRIVATE_BYTES;
/* TODO: make into a nice class. Change name. Possibly move to another include file. */
static inline SecureBuffer generate_key (
const FixedBlock<PRIVATE_BYTES> &secret
) {
SecureBuffer out(PUBLIC_BYTES);
$(c_ns)_eddsa_derive_public_key(out.data(), secret.data());
return out;
}
};

}; /* struct $(cxx_ns) */

/** @cond internal */


+ 50
- 0
test/test_decaf.cxx View File

@@ -56,6 +56,7 @@ template<typename Group> struct Tests {
typedef typename Group::Scalar Scalar;
typedef typename Group::Point Point;
typedef typename Group::DhLadder DhLadder;
typedef typename Group::EdDSA EdDSA;
typedef typename Group::Precomputed Precomputed;

static void print(const char *name, const Scalar &x) {
@@ -455,6 +456,8 @@ static void test_cfrg_crypto() {
}
}

static const Block eddsa_sk, eddsa_pk;

static void test_cfrg_vectors() {
Test test("CFRG test vectors");
SecureBuffer k = DhLadder::base_point();
@@ -462,6 +465,24 @@ static void test_cfrg_vectors() {
int the_ntests = (NTESTS < 1000000) ? 1000 : 1000000;

/* EdDSA */
if (eddsa_sk.size()) {
SecureBuffer eddsa_pk2 = EdDSA::generate_key(eddsa_sk);
if (!memeq(SecureBuffer(eddsa_pk), eddsa_pk2)) {
test.fail();
printf(" EdDSA vectors disagree.");
printf("\n Correct: ");
for (unsigned i=0; i<eddsa_pk.size(); i++) printf("%02x", eddsa_pk[i]);
printf("\n Incorrect: ");

for (unsigned i=0; i<eddsa_pk.size(); i++) printf("%02x", eddsa_pk2[i]);
printf("\n");
}
}
/* X25519/X448 */
for (int i=0; i<the_ntests && test.passing_now; i++) {
SecureBuffer n = DhLadder::shared_secret(u,k);
u = k; k = n;
@@ -500,6 +521,7 @@ static void run() {

}; /* template<GroupId GROUP> struct Tests */

/* X25519, X448 test vectors */
template<> const uint8_t Tests<IsoEd25519>::rfc7748_1[32] = {
0x42,0x2c,0x8e,0x7a,0x62,0x27,0xd7,0xbc,
0xa1,0x35,0x0b,0x3e,0x2b,0xb7,0x27,0x9f,
@@ -576,8 +598,36 @@ const uint8_t elli_patho_448[56] = {
template<> const Block Tests<Ed448Goldilocks>::elli_patho(elli_patho_448,56);
template<> const Block Tests<IsoEd25519>::elli_patho(NULL,0);

/* EdDSA test vectors */
const uint8_t ed448_eddsa_sk[57] = {
0x6c,0x82,0xa5,0x62,0xcb,0x80,0x8d,0x10,
0xd6,0x32,0xbe,0x89,0xc8,0x51,0x3e,0xbf,
0x6c,0x92,0x9f,0x34,0xdd,0xfa,0x8c,0x9f,
0x63,0xc9,0x96,0x0e,0xf6,0xe3,0x48,0xa3,
0x52,0x8c,0x8a,0x3f,0xcc,0x2f,0x04,0x4e,
0x39,0xa3,0xfc,0x5b,0x94,0x49,0x2f,0x8f,
0x03,0x2e,0x75,0x49,0xa2,0x00,0x98,0xf9,
0x5b
};
const uint8_t ed448_eddsa_pk[57] = {
0x5f,0xd7,0x44,0x9b,0x59,0xb4,0x61,0xfd,
0x2c,0xe7,0x87,0xec,0x61,0x6a,0xd4,0x6a,
0x1d,0xa1,0x34,0x24,0x85,0xa7,0x0e,0x1f,
0x8a,0x0e,0xa7,0x5d,0x80,0xe9,0x67,0x78,
0xed,0xf1,0x24,0x76,0x9b,0x46,0xc7,0x06,
0x1b,0xd6,0x78,0x3d,0xf1,0xe5,0x0f,0x6c,
0xd1,0xfa,0x1a,0xbe,0xaf,0xe8,0x25,0x61,
0x80
};
template<> const Block Tests<Ed448Goldilocks>::eddsa_sk(ed448_eddsa_sk,57);
template<> const Block Tests<Ed448Goldilocks>::eddsa_pk(ed448_eddsa_pk,57);

template<> const Block Tests<IsoEd25519>::eddsa_sk(NULL,0); /* TODO */
template<> const Block Tests<IsoEd25519>::eddsa_pk(NULL,0); /* TODO */

int main(int argc, char **argv) {
(void) argc; (void) argv;
run_for_all_curves<Tests>();
if (passing) printf("Passed all tests.\n");
return passing ? 0 : 1;


Loading…
Cancel
Save