From e22c96717184c8675104877fa31f5db2077b6252 Mon Sep 17 00:00:00 2001 From: Michael Hamburg Date: Wed, 2 Mar 2016 13:21:45 -0800 Subject: [PATCH] change eddsa encoding names to show that they multiply_by_cofactor --- src/per_curve/decaf.tmpl.c | 4 ++-- src/per_curve/decaf.tmpl.h | 9 +-------- src/per_curve/decaf.tmpl.hxx | 16 +++++++--------- src/per_curve/eddsa.tmpl.c | 19 ++++++++++++------- src/per_curve/eddsa.tmpl.h | 23 ++++++++++++++++------- src/per_curve/eddsa.tmpl.hxx | 2 +- test/test_decaf.cxx | 4 +++- 7 files changed, 42 insertions(+), 35 deletions(-) diff --git a/src/per_curve/decaf.tmpl.c b/src/per_curve/decaf.tmpl.c index 955b339..ed018c9 100644 --- a/src/per_curve/decaf.tmpl.c +++ b/src/per_curve/decaf.tmpl.c @@ -1047,7 +1047,7 @@ decaf_error_t API_NS(direct_scalarmul) ( return succ; } -void API_NS(point_encode_like_eddsa) ( +void API_NS(point_mul_by_cofactor_and_encode_like_eddsa) ( uint8_t enc[DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES], const point_t p ) { @@ -1135,7 +1135,7 @@ void API_NS(point_encode_like_eddsa) ( } -decaf_error_t API_NS(point_decode_like_eddsa) ( +decaf_error_t API_NS(point_decode_like_eddsa_and_ignore_cofactor) ( point_t p, const uint8_t enc[DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES] ) { diff --git a/src/per_curve/decaf.tmpl.h b/src/per_curve/decaf.tmpl.h index cf2d5b4..ed3b127 100644 --- a/src/per_curve/decaf.tmpl.h +++ b/src/per_curve/decaf.tmpl.h @@ -75,14 +75,7 @@ extern const $(c_ns)_scalar_t $(c_ns)_scalar_zero API_VIS; /** The identity point on the curve. */ extern const $(c_ns)_point_t $(c_ns)_point_identity API_VIS; -/** An arbitrarily chosen base point on the curve. - * @warning TODO: this is subject to change. It is currently - * the preimage of the X$(gf_shortname) base point. Sometime - * soon, we will merge and finalize support for X$(gf_shortname) - * and Ed$(gf_shortname) integration. This might make some - * multiple of the current basepoint (eg twice it, or the cofactor - * times it) more convenient API-wise, and trigger a changeover. - */ +/** An arbitrarily chosen base point on the curve. */ extern const $(c_ns)_point_t $(c_ns)_point_base API_VIS; /** Precomputed table for the base point on the curve. */ diff --git a/src/per_curve/decaf.tmpl.hxx b/src/per_curve/decaf.tmpl.hxx index bf929c6..b48ee41 100644 --- a/src/per_curve/decaf.tmpl.hxx +++ b/src/per_curve/decaf.tmpl.hxx @@ -315,24 +315,22 @@ public: * @return DECAF_FAILURE the string was the wrong length, or wasn't the encoding of a point. * Contents of the point are undefined. */ - inline decaf_error_t WARN_UNUSED decode_like_eddsa_noexcept ( + inline decaf_error_t WARN_UNUSED decode_like_eddsa_and_ignore_cofactor_noexcept ( const FixedBlock &buffer ) NOEXCEPT { - return $(c_ns)_point_decode_like_eddsa(p,buffer.data()); + return $(c_ns)_point_decode_like_eddsa_and_ignore_cofactor(p,buffer.data()); } - inline void decode_like_eddsa ( + inline void decode_like_eddsa_and_ignore_cofactor ( const FixedBlock &buffer ) throw(CryptoException) { - if (DECAF_SUCCESS != decode_like_eddsa_noexcept(buffer)) throw(CryptoException()); + if (DECAF_SUCCESS != decode_like_eddsa_and_ignore_cofactor_noexcept(buffer)) throw(CryptoException()); } - /** - * Encode like EdDSA. FIXME: and multiply by the cofactor... - */ - inline SecureBuffer encode_like_eddsa() const { + /** Multiply out cofactor and encode like EdDSA. */ + inline SecureBuffer mul_by_cofactor_and_encode_like_eddsa() const { SecureBuffer ret(DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES); - $(c_ns)_point_encode_like_eddsa(ret.data(),p); + $(c_ns)_point_mul_by_cofactor_and_encode_like_eddsa(ret.data(),p); return ret; } diff --git a/src/per_curve/eddsa.tmpl.c b/src/per_curve/eddsa.tmpl.c index 76240e7..943cfde 100644 --- a/src/per_curve/eddsa.tmpl.c +++ b/src/per_curve/eddsa.tmpl.c @@ -85,15 +85,20 @@ void decaf_ed$(gf_shortname)_derive_public_key ( API_NS(scalar_t) secret_scalar; API_NS(scalar_decode_long)(secret_scalar, secret_scalar_ser, sizeof(secret_scalar_ser)); - /* TODO: write documentation for why (due to isogenies) this needs to be quartered/eighthed */ - for (unsigned int c = 1; c < COFACTOR/EDDSA_BASE_POINT_RATIO; c <<= 1) { + /* Since we are going to mul_by_cofactor during encoding, divide by it here. + * However, the EdDSA base point is not the same as the decaf base point if + * the sigma isogeny is in use: the EdDSA base point is on Etwist_d/(1-d) and + * the decaf base point is on Etwist_d, and when converted it effectively + * picks up a factor of 2 from the isogenies. So we might start at 2 instead of 1. + */ + for (unsigned int c = EDDSA_BASE_POINT_RATIO; c < COFACTOR; c <<= 1) { API_NS(scalar_halve)(secret_scalar,secret_scalar); } API_NS(point_t) p; API_NS(precomputed_scalarmul)(p,API_NS(precomputed_base),secret_scalar); - API_NS(point_encode_like_eddsa)(pubkey, p); + API_NS(point_mul_by_cofactor_and_encode_like_eddsa)(pubkey, p); /* Cleanup */ API_NS(scalar_destroy)(secret_scalar); @@ -155,13 +160,13 @@ void decaf_ed$(gf_shortname)_sign ( /* Scalarmul to create the nonce-point */ API_NS(scalar_t) nonce_scalar_2; API_NS(scalar_halve)(nonce_scalar_2,nonce_scalar); - for (unsigned int c = 2; c < COFACTOR/EDDSA_BASE_POINT_RATIO; c <<= 1) { + for (unsigned int c = 2*EDDSA_BASE_POINT_RATIO; c < COFACTOR; c <<= 1) { API_NS(scalar_halve)(nonce_scalar_2,nonce_scalar_2); } API_NS(point_t) p; API_NS(precomputed_scalarmul)(p,API_NS(precomputed_base),nonce_scalar_2); - API_NS(point_encode_like_eddsa)(nonce_point, p); + API_NS(point_mul_by_cofactor_and_encode_like_eddsa)(nonce_point, p); API_NS(point_destroy)(p); API_NS(scalar_destroy)(nonce_scalar_2); } @@ -209,10 +214,10 @@ decaf_error_t decaf_ed$(gf_shortname)_verify ( const uint8_t context_len = 0; #endif API_NS(point_t) pk_point, r_point; - decaf_error_t error = API_NS(point_decode_like_eddsa)(pk_point,pubkey); + decaf_error_t error = API_NS(point_decode_like_eddsa_and_ignore_cofactor)(pk_point,pubkey); if (DECAF_SUCCESS != error) { return error; } - error = API_NS(point_decode_like_eddsa)(r_point,signature); + error = API_NS(point_decode_like_eddsa_and_ignore_cofactor)(r_point,signature); if (DECAF_SUCCESS != error) { return error; } API_NS(scalar_t) challenge_scalar; diff --git a/src/per_curve/eddsa.tmpl.h b/src/per_curve/eddsa.tmpl.h index 7bc894f..5d3f94e 100644 --- a/src/per_curve/eddsa.tmpl.h +++ b/src/per_curve/eddsa.tmpl.h @@ -41,6 +41,11 @@ void decaf_ed$(gf_shortname)_derive_public_key ( * @param [in] message The message to sign. * @param [in] message_len The length of the message. * @param [in] prehashed Nonzero if the message is actually the hash of something you want to sign. + * + * @warning For Ed25519, it is unsafe to use the same key for both prehashed and non-prehashed + * messages, at least without some very careful protocol-level disambiguation. For Ed448 it is + * safe. The C++ wrapper is designed to make it harder to screw this up, but this C code gives + * you no seat belt. */ void decaf_ed$(gf_shortname)_sign ( uint8_t signature[DECAF_EDDSA_$(gf_shortname)_SIGNATURE_BYTES], @@ -67,6 +72,11 @@ void decaf_ed$(gf_shortname)_sign ( * @param [in] message The message to verify. * @param [in] message_len The length of the message. * @param [in] prehashed Nonzero if the message is actually the hash of something you want to verify. + * + * @warning For Ed25519, it is unsafe to use the same key for both prehashed and non-prehashed + * messages, at least without some very careful protocol-level disambiguation. For Ed448 it is + * safe. The C++ wrapper is designed to make it harder to screw this up, but this C code gives + * you no seat belt. */ decaf_error_t decaf_ed$(gf_shortname)_verify ( const uint8_t signature[DECAF_EDDSA_$(gf_shortname)_SIGNATURE_BYTES], @@ -84,26 +94,25 @@ decaf_error_t decaf_ed$(gf_shortname)_verify ( /** * @brief EdDSA point encoding. Used internally, exposed externally. + * Multiplies the point by the current cofactor first. * * @param [out] enc The encoded point. * @param [in] p The point. - * - * FIXME: encode and decode aren't inverses of each other: they - * multiply by a factor. Rename to reflect this once the base - * point doctrine is worked out. */ -void $(c_ns)_point_encode_like_eddsa ( +void $(c_ns)_point_mul_by_cofactor_and_encode_like_eddsa ( uint8_t enc[DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES], const $(c_ns)_point_t p ) API_VIS NONNULL NOINLINE; /** - * @brief EdDSA point encoding. + * @brief EdDSA point decoding. Remember that while points on the + * EdDSA curves have cofactor information, Decaf ignores (quotients + * out) all cofactor information. * * @param [out] enc The encoded point. * @param [in] p The point. */ -decaf_error_t $(c_ns)_point_decode_like_eddsa ( +decaf_error_t $(c_ns)_point_decode_like_eddsa_and_ignore_cofactor ( $(c_ns)_point_t p, const uint8_t enc[DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES] ) API_VIS NONNULL NOINLINE; diff --git a/src/per_curve/eddsa.tmpl.hxx b/src/per_curve/eddsa.tmpl.hxx index 8e03d24..5ee4cd0 100644 --- a/src/per_curve/eddsa.tmpl.hxx +++ b/src/per_curve/eddsa.tmpl.hxx @@ -48,7 +48,7 @@ typedef class PrivateKeyBase PrivateKeyPh; """) /** @endcond */ -/** Prehash context for EdDSA. TODO: test me! */ +/** Prehash context for EdDSA. */ class Prehash : public $(re.sub(r"SHAKE(\d+)",r"SHAKE<\1>", eddsa_hash.upper())) { public: /** Do we support contexts for signatures? If not, they must always be NULL */ diff --git a/test/test_decaf.cxx b/test/test_decaf.cxx index 6bc7236..eb7eb5b 100644 --- a/test/test_decaf.cxx +++ b/test/test_decaf.cxx @@ -397,7 +397,9 @@ static void test_ec() { q=p; for (int j=1; j