From 45eb0e14d35b738225f32da9d407b741b7f1c4bb Mon Sep 17 00:00:00 2001 From: Michael Hamburg Date: Sun, 15 Oct 2017 16:54:30 -0700 Subject: [PATCH] change the misleading mul_by_cofactor functions to mul_by_ratio, and create ENCODE_RATIO and DECODE_ratio constants to represent this --- src/GENERATED/c/curve25519/decaf.c | 28 ++++------- src/GENERATED/c/curve25519/eddsa.c | 26 +++++----- src/GENERATED/c/ed448goldilocks/decaf.c | 28 ++++------- src/GENERATED/c/ed448goldilocks/eddsa.c | 26 +++++----- src/GENERATED/include/decaf/ed255.h | 36 +++++++++++--- src/GENERATED/include/decaf/ed448.h | 36 +++++++++++--- src/GENERATED/include/decaf/point_255.h | 21 +++++++- src/GENERATED/include/decaf/point_255.hxx | 59 ++++++++++++++--------- src/GENERATED/include/decaf/point_448.h | 21 +++++++- src/GENERATED/include/decaf/point_448.hxx | 59 ++++++++++++++--------- src/generator/curve_data.py | 4 ++ src/per_curve/decaf.tmpl.c | 28 ++++------- src/per_curve/eddsa.tmpl.c | 25 ++++------ src/per_curve/eddsa.tmpl.h | 36 +++++++++++--- src/per_curve/point.tmpl.h | 21 +++++++- src/per_curve/point.tmpl.hxx | 59 ++++++++++++++--------- test/ristretto.cxx | 20 +++++--- test/test_decaf.cxx | 22 +++++++-- 18 files changed, 356 insertions(+), 199 deletions(-) diff --git a/src/GENERATED/c/curve25519/decaf.c b/src/GENERATED/c/curve25519/decaf.c index de5d3e7..b27328d 100644 --- a/src/GENERATED/c/curve25519/decaf.c +++ b/src/GENERATED/c/curve25519/decaf.c @@ -1040,7 +1040,7 @@ decaf_error_t API_NS(direct_scalarmul) ( return succ; } -void API_NS(point_mul_by_cofactor_and_encode_like_eddsa) ( +void API_NS(point_mul_by_ratio_and_encode_like_eddsa) ( uint8_t enc[DECAF_EDDSA_25519_PUBLIC_BYTES], const point_t p ) { @@ -1133,7 +1133,7 @@ void API_NS(point_mul_by_cofactor_and_encode_like_eddsa) ( } -decaf_error_t API_NS(point_decode_like_eddsa_and_ignore_cofactor) ( +decaf_error_t API_NS(point_decode_like_eddsa_and_mul_by_ratio) ( point_t p, const uint8_t enc[DECAF_EDDSA_25519_PUBLIC_BYTES] ) { @@ -1352,13 +1352,16 @@ void decaf_x25519_generate_key ( decaf_x25519_derive_public_key(out,scalar); } -void API_NS(point_mul_by_cofactor_and_encode_like_x25519) ( +void API_NS(point_mul_by_ratio_and_encode_like_x25519) ( uint8_t out[X_PUBLIC_BYTES], const point_t p ) { point_t q; +#if COFACTOR == 8 point_double_internal(q,p,1); - for (unsigned i=1; it,q->x,0); /* 1/x */ gf_mul(q->z,q->t,q->y); /* y/x */ gf_sqr(q->y,q->z); /* (y/x)^2 */ @@ -1384,24 +1387,13 @@ void decaf_x25519_derive_public_key ( scalar_t the_scalar; API_NS(scalar_decode_long)(the_scalar,scalar2,sizeof(scalar2)); - /* We're gonna isogenize by 2, so divide by 2. - * - * Why by 2, even though it's a 4-isogeny? - * - * The isogeny map looks like - * Montgomery <-2-> Jacobi <-2-> Edwards - * - * Since the Jacobi base point is the PREimage of the iso to - * the Montgomery curve, and we're going - * Jacobi -> Edwards -> Jacobi -> Montgomery, - * we pick up only a factor of 2 over Jacobi -> Montgomery. - */ - for (unsigned i=1; it,q->x,0); /* 1/x */ gf_mul(q->z,q->t,q->y); /* y/x */ gf_sqr(q->y,q->z); /* (y/x)^2 */ @@ -1384,24 +1387,13 @@ void decaf_x448_derive_public_key ( scalar_t the_scalar; API_NS(scalar_decode_long)(the_scalar,scalar2,sizeof(scalar2)); - /* We're gonna isogenize by 2, so divide by 2. - * - * Why by 2, even though it's a 4-isogeny? - * - * The isogeny map looks like - * Montgomery <-2-> Jacobi <-2-> Edwards - * - * Since the Jacobi base point is the PREimage of the iso to - * the Montgomery curve, and we're going - * Jacobi -> Edwards -> Jacobi -> Montgomery, - * we pick up only a factor of 2 over Jacobi -> Montgomery. - */ - for (unsigned i=1; i &buffer ) DECAF_NOEXCEPT { - return decaf_255_point_decode_like_eddsa_and_ignore_cofactor(p,buffer.data()); + return decaf_255_point_decode_like_eddsa_and_mul_by_ratio(p,buffer.data()); } - - inline void decode_like_eddsa_and_ignore_cofactor ( + + /** + * Decode from EDDSA, multiply by EDDSA_DECODE_RATIO, and ignore any + * remaining cofactor information. + * @throw CryptoException if the input point was invalid. + */ + inline void decode_like_eddsa_and_mul_by_ratio( const FixedBlock &buffer ) /*throw(CryptoException)*/ { - if (DECAF_SUCCESS != decode_like_eddsa_and_ignore_cofactor_noexcept(buffer)) throw(CryptoException()); + if (DECAF_SUCCESS != decode_like_eddsa_and_mul_by_ratio_noexcept(buffer)) throw(CryptoException()); } - /** Multiply out cofactor and encode like EdDSA. */ - inline SecureBuffer mul_by_cofactor_and_encode_like_eddsa() const { + /** Multiply by EDDSA_ENCODE_RATIO and encode like EdDSA. */ + inline SecureBuffer mul_by_ratio_and_encode_like_eddsa() const { SecureBuffer ret(DECAF_EDDSA_25519_PUBLIC_BYTES); - decaf_255_point_mul_by_cofactor_and_encode_like_eddsa(ret.data(),p); + decaf_255_point_mul_by_ratio_and_encode_like_eddsa(ret.data(),p); return ret; } - /** Multiply out cofactor and encode like X25519/X448. */ - inline SecureBuffer mul_by_cofactor_and_encode_like_ladder() const { - SecureBuffer ret(LADDER_BYTES); - decaf_255_point_mul_by_cofactor_and_encode_like_x25519(ret.data(),p); - return ret; - } - - /** Multiply out cofactor and encode like EdDSA. */ - inline void mul_by_cofactor_and_encode_like_eddsa( + /** Multiply by EDDSA_ENCODE_RATIO and encode like EdDSA. */ + inline void mul_by_ratio_and_encode_like_eddsa( FixedBuffer &out ) const { - decaf_255_point_mul_by_cofactor_and_encode_like_eddsa(out.data(),p); + decaf_255_point_mul_by_ratio_and_encode_like_eddsa(out.data(),p); + } + + /** Multiply by LADDER_ENCODE_RATIO and encode like X25519/X448. */ + inline SecureBuffer mul_by_ratio_and_encode_like_ladder() const { + SecureBuffer ret(LADDER_BYTES); + decaf_255_point_mul_by_ratio_and_encode_like_x25519(ret.data(),p); + return ret; } - /** Multiply out cofactor and encode like X25519/X448. */ - inline void mul_by_cofactor_and_encode_like_ladder( + /** Multiply by LADDER_ENCODE_RATIO and encode like X25519/X448. */ + inline void mul_by_ratio_and_encode_like_ladder( FixedBuffer &out ) const { - decaf_255_point_mul_by_cofactor_and_encode_like_x25519(out.data(),p); + decaf_255_point_mul_by_ratio_and_encode_like_x25519(out.data(),p); } /** diff --git a/src/GENERATED/include/decaf/point_448.h b/src/GENERATED/include/decaf/point_448.h index 03286dd..bc1cb43 100644 --- a/src/GENERATED/include/decaf/point_448.h +++ b/src/GENERATED/include/decaf/point_448.h @@ -55,6 +55,9 @@ typedef struct gf_448_s { /** The cofactor the curve would have, if we hadn't removed it */ #define DECAF_448_REMOVED_COFACTOR 4 +/** X448 encoding ratio. */ +#define DECAF_X448_ENCODE_RATIO 2 + /** Number of bytes in an x448 public key */ #define DECAF_X448_PUBLIC_BYTES 56 @@ -401,12 +404,26 @@ decaf_error_t decaf_x448 ( ) DECAF_API_VIS DECAF_NONNULL DECAF_WARN_UNUSED DECAF_NOINLINE; /** - * @brief Multiply a point by the cofactor, then encode it like RFC 7748 + * @brief Multiply a point by DECAF_X448_ENCODE_RATIO, + * then encode it like RFC 7748. + * + * This function is mainly used internally, but is exported in case + * it will be useful. + * + * The ratio is necessary because the internal representation doesn't + * track the cofactor information, so on output we must clear the cofactor. + * This would multiply by the cofactor, but in fact internally libdecaf's + * points are always even, so it multiplies by half the cofactor instead. + * + * As it happens, this aligns with the base point definitions; that is, + * if you pass the Decaf/Ristretto base point to this function, the result + * will be DECAF_X448_ENCODE_RATIO times the X448 + * base point. * * @param [out] out The scaled and encoded point. * @param [in] p The point to be scaled and encoded. */ -void decaf_448_point_mul_by_cofactor_and_encode_like_x448 ( +void decaf_448_point_mul_by_ratio_and_encode_like_x448 ( uint8_t out[DECAF_X448_PUBLIC_BYTES], const decaf_448_point_t p ) DECAF_API_VIS DECAF_NONNULL; diff --git a/src/GENERATED/include/decaf/point_448.hxx b/src/GENERATED/include/decaf/point_448.hxx index adcb6ae..3718778 100644 --- a/src/GENERATED/include/decaf/point_448.hxx +++ b/src/GENERATED/include/decaf/point_448.hxx @@ -64,9 +64,6 @@ static inline int bits() { return 448; } /** The curve's cofactor (removed, but useful for testing) */ static const int REMOVED_COFACTOR = 4; -/** The curve's cofactor (removed, but useful for testing) */ -static const int EDDSA_RATIO = 4; - /** Residue class of field modulus: p == this mod 2*(this-1) */ static const int FIELD_MODULUS_TYPE = 3; @@ -263,6 +260,15 @@ public: /** Bytes required for EdDSA encoding */ static const size_t LADDER_BYTES = DECAF_X448_PUBLIC_BYTES; + + /** Ratio due to EdDSA encoding */ + static const int EDDSA_ENCODE_RATIO = DECAF_448_EDDSA_ENCODE_RATIO; + + /** Ratio due to EdDSA decoding */ + static const int EDDSA_DECODE_RATIO = DECAF_448_EDDSA_DECODE_RATIO; + + /** Ratio due to ladder decoding */ + static const int LADDER_ENCODE_RATIO = DECAF_X448_ENCODE_RATIO; /** * Size of a stegged element. @@ -348,44 +354,49 @@ 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 DECAF_WARN_UNUSED decode_like_eddsa_and_ignore_cofactor_noexcept ( + inline decaf_error_t DECAF_WARN_UNUSED decode_like_eddsa_and_mul_by_ratio_noexcept ( const FixedBlock &buffer ) DECAF_NOEXCEPT { - return decaf_448_point_decode_like_eddsa_and_ignore_cofactor(p,buffer.data()); + return decaf_448_point_decode_like_eddsa_and_mul_by_ratio(p,buffer.data()); } - - inline void decode_like_eddsa_and_ignore_cofactor ( + + /** + * Decode from EDDSA, multiply by EDDSA_DECODE_RATIO, and ignore any + * remaining cofactor information. + * @throw CryptoException if the input point was invalid. + */ + inline void decode_like_eddsa_and_mul_by_ratio( const FixedBlock &buffer ) /*throw(CryptoException)*/ { - if (DECAF_SUCCESS != decode_like_eddsa_and_ignore_cofactor_noexcept(buffer)) throw(CryptoException()); + if (DECAF_SUCCESS != decode_like_eddsa_and_mul_by_ratio_noexcept(buffer)) throw(CryptoException()); } - /** Multiply out cofactor and encode like EdDSA. */ - inline SecureBuffer mul_by_cofactor_and_encode_like_eddsa() const { + /** Multiply by EDDSA_ENCODE_RATIO and encode like EdDSA. */ + inline SecureBuffer mul_by_ratio_and_encode_like_eddsa() const { SecureBuffer ret(DECAF_EDDSA_448_PUBLIC_BYTES); - decaf_448_point_mul_by_cofactor_and_encode_like_eddsa(ret.data(),p); + decaf_448_point_mul_by_ratio_and_encode_like_eddsa(ret.data(),p); return ret; } - /** Multiply out cofactor and encode like X25519/X448. */ - inline SecureBuffer mul_by_cofactor_and_encode_like_ladder() const { - SecureBuffer ret(LADDER_BYTES); - decaf_448_point_mul_by_cofactor_and_encode_like_x448(ret.data(),p); - return ret; - } - - /** Multiply out cofactor and encode like EdDSA. */ - inline void mul_by_cofactor_and_encode_like_eddsa( + /** Multiply by EDDSA_ENCODE_RATIO and encode like EdDSA. */ + inline void mul_by_ratio_and_encode_like_eddsa( FixedBuffer &out ) const { - decaf_448_point_mul_by_cofactor_and_encode_like_eddsa(out.data(),p); + decaf_448_point_mul_by_ratio_and_encode_like_eddsa(out.data(),p); + } + + /** Multiply by LADDER_ENCODE_RATIO and encode like X25519/X448. */ + inline SecureBuffer mul_by_ratio_and_encode_like_ladder() const { + SecureBuffer ret(LADDER_BYTES); + decaf_448_point_mul_by_ratio_and_encode_like_x448(ret.data(),p); + return ret; } - /** Multiply out cofactor and encode like X25519/X448. */ - inline void mul_by_cofactor_and_encode_like_ladder( + /** Multiply by LADDER_ENCODE_RATIO and encode like X25519/X448. */ + inline void mul_by_ratio_and_encode_like_ladder( FixedBuffer &out ) const { - decaf_448_point_mul_by_cofactor_and_encode_like_x448(out.data(),p); + decaf_448_point_mul_by_ratio_and_encode_like_x448(out.data(),p); } /** diff --git a/src/generator/curve_data.py b/src/generator/curve_data.py index dd88ac2..8e7e8d9 100644 --- a/src/generator/curve_data.py +++ b/src/generator/curve_data.py @@ -33,6 +33,8 @@ curve_data = { "trace": -0xa6f7cef517bce6b2c09318d2e7ae9f7a, "mont_base": 9, "rist_base": "e2f2ae0a6abc4e71a884a961c500515f58e30b6aa582dd8db6a65945e08d2d76", + "eddsa_encode_ratio": 4, + "x_encode_ratio": 4, "combs":comb_config(3,5,17), "wnaf":wnaf_config(5,3), @@ -44,6 +46,8 @@ curve_data = { "eddsa_sigma_iso": 1 }, "ed448goldilocks" : { + "eddsa_encode_ratio": 4, + "x_encode_ratio": 2, "altname": None, "name" : "Ed448-Goldilocks", "cofactor" : 4, diff --git a/src/per_curve/decaf.tmpl.c b/src/per_curve/decaf.tmpl.c index 525ced6..6ec7cc6 100644 --- a/src/per_curve/decaf.tmpl.c +++ b/src/per_curve/decaf.tmpl.c @@ -1029,7 +1029,7 @@ decaf_error_t API_NS(direct_scalarmul) ( return succ; } -void API_NS(point_mul_by_cofactor_and_encode_like_eddsa) ( +void API_NS(point_mul_by_ratio_and_encode_like_eddsa) ( uint8_t enc[DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES], const point_t p ) { @@ -1122,7 +1122,7 @@ void API_NS(point_mul_by_cofactor_and_encode_like_eddsa) ( } -decaf_error_t API_NS(point_decode_like_eddsa_and_ignore_cofactor) ( +decaf_error_t API_NS(point_decode_like_eddsa_and_mul_by_ratio) ( point_t p, const uint8_t enc[DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES] ) { @@ -1341,13 +1341,16 @@ void decaf_x$(gf_shortname)_generate_key ( decaf_x$(gf_shortname)_derive_public_key(out,scalar); } -void API_NS(point_mul_by_cofactor_and_encode_like_x$(gf_shortname)) ( +void API_NS(point_mul_by_ratio_and_encode_like_x$(gf_shortname)) ( uint8_t out[X_PUBLIC_BYTES], const point_t p ) { point_t q; +#if COFACTOR == 8 point_double_internal(q,p,1); - for (unsigned i=1; it,q->x,0); /* 1/x */ gf_mul(q->z,q->t,q->y); /* y/x */ gf_sqr(q->y,q->z); /* (y/x)^2 */ @@ -1373,24 +1376,13 @@ void decaf_x$(gf_shortname)_derive_public_key ( scalar_t the_scalar; API_NS(scalar_decode_long)(the_scalar,scalar2,sizeof(scalar2)); - /* We're gonna isogenize by 2, so divide by 2. - * - * Why by 2, even though it's a 4-isogeny? - * - * The isogeny map looks like - * Montgomery <-2-> Jacobi <-2-> Edwards - * - * Since the Jacobi base point is the PREimage of the iso to - * the Montgomery curve, and we're going - * Jacobi -> Edwards -> Jacobi -> Montgomery, - * we pick up only a factor of 2 over Jacobi -> Montgomery. - */ - for (unsigned i=1; i &buffer ) DECAF_NOEXCEPT { - return $(c_ns)_point_decode_like_eddsa_and_ignore_cofactor(p,buffer.data()); + return $(c_ns)_point_decode_like_eddsa_and_mul_by_ratio(p,buffer.data()); } - - inline void decode_like_eddsa_and_ignore_cofactor ( + + /** + * Decode from EDDSA, multiply by EDDSA_DECODE_RATIO, and ignore any + * remaining cofactor information. + * @throw CryptoException if the input point was invalid. + */ + inline void decode_like_eddsa_and_mul_by_ratio( const FixedBlock &buffer ) /*throw(CryptoException)*/ { - if (DECAF_SUCCESS != decode_like_eddsa_and_ignore_cofactor_noexcept(buffer)) throw(CryptoException()); + if (DECAF_SUCCESS != decode_like_eddsa_and_mul_by_ratio_noexcept(buffer)) throw(CryptoException()); } - /** Multiply out cofactor and encode like EdDSA. */ - inline SecureBuffer mul_by_cofactor_and_encode_like_eddsa() const { + /** Multiply by EDDSA_ENCODE_RATIO and encode like EdDSA. */ + inline SecureBuffer mul_by_ratio_and_encode_like_eddsa() const { SecureBuffer ret(DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES); - $(c_ns)_point_mul_by_cofactor_and_encode_like_eddsa(ret.data(),p); + $(c_ns)_point_mul_by_ratio_and_encode_like_eddsa(ret.data(),p); return ret; } - /** Multiply out cofactor and encode like X25519/X448. */ - inline SecureBuffer mul_by_cofactor_and_encode_like_ladder() const { - SecureBuffer ret(LADDER_BYTES); - $(c_ns)_point_mul_by_cofactor_and_encode_like_x$(gf_shortname)(ret.data(),p); - return ret; - } - - /** Multiply out cofactor and encode like EdDSA. */ - inline void mul_by_cofactor_and_encode_like_eddsa( + /** Multiply by EDDSA_ENCODE_RATIO and encode like EdDSA. */ + inline void mul_by_ratio_and_encode_like_eddsa( FixedBuffer &out ) const { - $(c_ns)_point_mul_by_cofactor_and_encode_like_eddsa(out.data(),p); + $(c_ns)_point_mul_by_ratio_and_encode_like_eddsa(out.data(),p); + } + + /** Multiply by LADDER_ENCODE_RATIO and encode like X25519/X448. */ + inline SecureBuffer mul_by_ratio_and_encode_like_ladder() const { + SecureBuffer ret(LADDER_BYTES); + $(c_ns)_point_mul_by_ratio_and_encode_like_x$(gf_shortname)(ret.data(),p); + return ret; } - /** Multiply out cofactor and encode like X25519/X448. */ - inline void mul_by_cofactor_and_encode_like_ladder( + /** Multiply by LADDER_ENCODE_RATIO and encode like X25519/X448. */ + inline void mul_by_ratio_and_encode_like_ladder( FixedBuffer &out ) const { - $(c_ns)_point_mul_by_cofactor_and_encode_like_x$(gf_shortname)(out.data(),p); + $(c_ns)_point_mul_by_ratio_and_encode_like_x$(gf_shortname)(out.data(),p); } /** diff --git a/test/ristretto.cxx b/test/ristretto.cxx index ad480c2..897c95f 100644 --- a/test/ristretto.cxx +++ b/test/ristretto.cxx @@ -70,7 +70,7 @@ void usage() { fprintf(stderr," -D: Display output in EdDSA format (times clearing ratio)\n"); fprintf(stderr," -R: Display raw xyzt\n"); fprintf(stderr," -C: Display output in X[25519|448] format\n"); - fprintf(stderr," -H: ... divide by clearing ratio first\n"); + fprintf(stderr," -H: ... divide by encoding ratio first\n"); fprintf(stderr,"\n"); fprintf(stderr," Ways to create points:\n"); fprintf(stderr," [hex]: Point from point data as hex\n"); @@ -97,7 +97,7 @@ public: uint8_t tmp[Group::Point::SER_BYTES]; typename Group::Point a,b; typename Group::Scalar s; - bool plus=false, empty=true, elligator=false, mul=false, scalar=false, + bool plus=false, empty=true, elligator=false, mul=false, scalar=false, div=false, torque=false, scalarempty=true, neg=false, einv=false, like_eddsa=false, like_x=false, decoeff=false, raw=false; if (done || error) return; for (int i=1; i::PrivateKey priv(rng); typename EdDSA::PublicKey pub(priv); @@ -569,7 +568,22 @@ static void test_eddsa() { } catch(CryptoException) { test.fail(); printf(" Signature validation failed on sig %d\n", i); - } + } + + /* Test encode_like and torque */ + Point p(rng); + SecureBuffer p1 = p.mul_by_ratio_and_encode_like_eddsa(); + SecureBuffer p2 = p.debugging_torque().mul_by_ratio_and_encode_like_eddsa(); + if (!memeq(p1,p2)) { + test.fail(); + printf(" Torque and encode like EdDSA failed\n"); + } + SecureBuffer p3 = p.mul_by_ratio_and_encode_like_ladder(); + SecureBuffer p4 = p.debugging_torque().mul_by_ratio_and_encode_like_ladder(); + if (!memeq(p3,p4)) { + test.fail(); + printf(" Torque and encode like ladder failed\n"); + } } }