@@ -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] | |||
) { | |||
@@ -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. */ | |||
@@ -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<DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES> &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<DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES> &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; | |||
} | |||
@@ -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; | |||
@@ -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; | |||
@@ -48,7 +48,7 @@ typedef class PrivateKeyBase<PREHASHED> 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 */ | |||
@@ -397,7 +397,9 @@ static void test_ec() { | |||
q=p; | |||
for (int j=1; j<Group::REMOVED_COFACTOR; j<<=1) q = q.times_two(); | |||
decaf_error_t error = r.decode_like_eddsa_noexcept(p.encode_like_eddsa()); | |||
decaf_error_t error = r.decode_like_eddsa_and_ignore_cofactor_noexcept( | |||
p.mul_by_cofactor_and_encode_like_eddsa() | |||
); | |||
if (error != DECAF_SUCCESS) { | |||
test.fail(); | |||
printf(" Decode like EdDSA failed."); | |||