Browse Source

add ristretto widget. elligator is correct, but inverse is not yet

master
Michael Hamburg 7 years ago
parent
commit
c82e7ae7a7
17 changed files with 217 additions and 34 deletions
  1. +8
    -1
      Makefile
  2. +0
    -8
      src/GENERATED/c/curve25519/decaf.c
  3. +3
    -3
      src/GENERATED/c/curve25519/elligator.c
  4. +0
    -8
      src/GENERATED/c/ed448goldilocks/decaf.c
  5. +3
    -3
      src/GENERATED/c/ed448goldilocks/elligator.c
  6. +2
    -0
      src/GENERATED/c/p25519/f_field.h
  7. +8
    -0
      src/GENERATED/c/p25519/f_generic.c
  8. +2
    -0
      src/GENERATED/c/p448/f_field.h
  9. +8
    -0
      src/GENERATED/c/p448/f_generic.c
  10. +3
    -0
      src/GENERATED/include/decaf/point_255.hxx
  11. +3
    -0
      src/GENERATED/include/decaf/point_448.hxx
  12. +0
    -8
      src/per_curve/decaf.tmpl.c
  13. +3
    -3
      src/per_curve/elligator.tmpl.c
  14. +3
    -0
      src/per_curve/point.tmpl.hxx
  15. +2
    -0
      src/per_field/f_field.tmpl.h
  16. +8
    -0
      src/per_field/f_generic.tmpl.c
  17. +161
    -0
      test/ristretto.cxx

+ 8
- 1
Makefile View File

@@ -85,7 +85,7 @@ LIBCOMPONENTS = $(BUILD_OBJ)/utils.o $(BUILD_OBJ)/shake.o $(BUILD_OBJ)/sha512.o

BENCHCOMPONENTS = $(BUILD_OBJ)/bench.o $(BUILD_OBJ)/shake.o

all: lib $(BUILD_IBIN)/test $(BUILD_IBIN)/bench $(BUILD_BIN)/shakesum
all: lib $(BUILD_IBIN)/test $(BUILD_BIN)/ristretto $(BUILD_IBIN)/bench $(BUILD_BIN)/shakesum

scan: clean
scan-build --use-analyzer=`which clang` \
@@ -101,6 +101,13 @@ else
$(LDXX) $(LDFLAGS) -Wl,-rpath,`pwd`/$(BUILD_LIB) -o $@ $< -L$(BUILD_LIB) -ldecaf
endif

$(BUILD_BIN)/ristretto: $(BUILD_OBJ)/ristretto.o lib
ifeq ($(UNAME),Darwin)
$(LDXX) $(LDFLAGS) -o $@ $< -L$(BUILD_LIB) -ldecaf
else
$(LDXX) $(LDFLAGS) -Wl,-rpath,`pwd`/$(BUILD_LIB) -o $@ $< -L$(BUILD_LIB) -ldecaf
endif

# Internal test programs, which are not part of the final build/bin directory.
$(BUILD_IBIN)/test_ct: $(BUILD_OBJ)/test_ct.o lib
ifeq ($(UNAME),Darwin)


+ 0
- 8
src/GENERATED/c/curve25519/decaf.c View File

@@ -127,14 +127,6 @@ gf_invert(gf y, const gf x, int assert_nonzero) {
gf_copy(y, t2);
}

/** Return high bit of x = low bit of 2x mod p */
static mask_t gf_lobit(const gf x) {
gf y;
gf_copy(y,x);
gf_strong_reduce(y);
return -(y->limb[0]&1);
}

/** identity = (0,1) */
const point_t API_NS(point_identity) = {{{{{0}}},{{{1}}},{{{1}}},{{{0}}}}};



+ 3
- 3
src/GENERATED/c/curve25519/elligator.c View File

@@ -25,10 +25,10 @@ static const int EDWARDS_D = -121665;

extern void API_NS(deisogenize) (
gf_s *__restrict__ s,
gf_s *__restrict__ minus_t_over_s,
gf_s *__restrict__ altx,
const point_t p,
mask_t toggle_hibit_s,
mask_t toggle_hibit_t_over_s,
mask_t toggle_altx,
mask_t toggle_rotation
);

@@ -61,7 +61,7 @@ void API_NS(point_from_hash_nonuniform) (
/* s@a = +-|N.e| */
gf_mul(a,N,e);
gf_cond_neg(a,gf_hibit(a)^square); /* NB this is - what is listed in the paper */
gf_cond_neg(a,gf_lobit(a) ^ ~square);
/* t@b = -+ cN(r-1)((a-2d)e)^2 - 1 */
gf_mulw(c,e,1-2*EDWARDS_D); /* (a-2d)e */


+ 0
- 8
src/GENERATED/c/ed448goldilocks/decaf.c View File

@@ -127,14 +127,6 @@ gf_invert(gf y, const gf x, int assert_nonzero) {
gf_copy(y, t2);
}

/** Return high bit of x = low bit of 2x mod p */
static mask_t gf_lobit(const gf x) {
gf y;
gf_copy(y,x);
gf_strong_reduce(y);
return -(y->limb[0]&1);
}

/** identity = (0,1) */
const point_t API_NS(point_identity) = {{{{{0}}},{{{1}}},{{{1}}},{{{0}}}}};



+ 3
- 3
src/GENERATED/c/ed448goldilocks/elligator.c View File

@@ -25,10 +25,10 @@ static const int EDWARDS_D = -39081;

extern void API_NS(deisogenize) (
gf_s *__restrict__ s,
gf_s *__restrict__ minus_t_over_s,
gf_s *__restrict__ altx,
const point_t p,
mask_t toggle_hibit_s,
mask_t toggle_hibit_t_over_s,
mask_t toggle_altx,
mask_t toggle_rotation
);

@@ -61,7 +61,7 @@ void API_NS(point_from_hash_nonuniform) (
/* s@a = +-|N.e| */
gf_mul(a,N,e);
gf_cond_neg(a,gf_hibit(a)^square); /* NB this is - what is listed in the paper */
gf_cond_neg(a,gf_lobit(a) ^ ~square);
/* t@b = -+ cN(r-1)((a-2d)e)^2 - 1 */
gf_mulw(c,e,1-2*EDWARDS_D); /* (a-2d)e */


+ 2
- 0
src/GENERATED/c/p25519/f_field.h View File

@@ -38,6 +38,7 @@ typedef struct gf_25519_s {
#define gf_s gf_25519_s
#define gf_eq gf_25519_eq
#define gf_hibit gf_25519_hibit
#define gf_lobit gf_25519_lobit
#define gf_copy gf_25519_copy
#define gf_add gf_25519_add
#define gf_sub gf_25519_sub
@@ -81,6 +82,7 @@ void gf_mulw_unsigned (gf_s *__restrict__ out, const gf a, uint32_t b);
void gf_sqr (gf_s *__restrict__ out, const gf a);
mask_t gf_isr(gf a, const gf x); /** a^2 x = 1, QNR, or 0 if x=0. Return true if successful */
mask_t gf_eq (const gf x, const gf y);
mask_t gf_lobit (const gf x);
mask_t gf_hibit (const gf x);

void gf_serialize (uint8_t *serial, const gf x,int with_highbit);


+ 8
- 0
src/GENERATED/c/p25519/f_generic.c View File

@@ -52,6 +52,14 @@ mask_t gf_hibit(const gf x) {
return -(y->limb[0]&1);
}

/** Return high bit of x = low bit of 2x mod p */
mask_t gf_lobit(const gf x) {
gf y;
gf_copy(y,x);
gf_strong_reduce(y);
return -(y->limb[0]&1);
}

/** Deserialize from wire format; return -1 on success and 0 on failure. */
mask_t gf_deserialize (gf x, const uint8_t serial[SER_BYTES], int with_hibit) {
unsigned int j=0, fill=0;


+ 2
- 0
src/GENERATED/c/p448/f_field.h View File

@@ -38,6 +38,7 @@ typedef struct gf_448_s {
#define gf_s gf_448_s
#define gf_eq gf_448_eq
#define gf_hibit gf_448_hibit
#define gf_lobit gf_448_lobit
#define gf_copy gf_448_copy
#define gf_add gf_448_add
#define gf_sub gf_448_sub
@@ -81,6 +82,7 @@ void gf_mulw_unsigned (gf_s *__restrict__ out, const gf a, uint32_t b);
void gf_sqr (gf_s *__restrict__ out, const gf a);
mask_t gf_isr(gf a, const gf x); /** a^2 x = 1, QNR, or 0 if x=0. Return true if successful */
mask_t gf_eq (const gf x, const gf y);
mask_t gf_lobit (const gf x);
mask_t gf_hibit (const gf x);

void gf_serialize (uint8_t *serial, const gf x,int with_highbit);


+ 8
- 0
src/GENERATED/c/p448/f_generic.c View File

@@ -52,6 +52,14 @@ mask_t gf_hibit(const gf x) {
return -(y->limb[0]&1);
}

/** Return high bit of x = low bit of 2x mod p */
mask_t gf_lobit(const gf x) {
gf y;
gf_copy(y,x);
gf_strong_reduce(y);
return -(y->limb[0]&1);
}

/** Deserialize from wire format; return -1 on success and 0 on failure. */
mask_t gf_deserialize (gf x, const uint8_t serial[SER_BYTES], int with_hibit) {
unsigned int j=0, fill=0;


+ 3
- 0
src/GENERATED/include/decaf/point_255.hxx View File

@@ -58,6 +58,9 @@ struct IsoEd25519 {
/** The name of the curve */
static inline const char *name() { return "Iso-Ed25519"; }

/** The name of the curve */
static inline int bits() { return 255; }

/** The curve's cofactor (removed, but useful for testing) */
static const int REMOVED_COFACTOR = 8;



+ 3
- 0
src/GENERATED/include/decaf/point_448.hxx View File

@@ -58,6 +58,9 @@ struct Ed448Goldilocks {
/** The name of the curve */
static inline const char *name() { return "Ed448-Goldilocks"; }

/** The name of the curve */
static inline int bits() { return 448; }

/** The curve's cofactor (removed, but useful for testing) */
static const int REMOVED_COFACTOR = 4;



+ 0
- 8
src/per_curve/decaf.tmpl.c View File

@@ -116,14 +116,6 @@ gf_invert(gf y, const gf x, int assert_nonzero) {
gf_copy(y, t2);
}

/** Return high bit of x = low bit of 2x mod p */
static mask_t gf_lobit(const gf x) {
gf y;
gf_copy(y,x);
gf_strong_reduce(y);
return -(y->limb[0]&1);
}

/** identity = (0,1) */
const point_t API_NS(point_identity) = {{{{{0}}},{{{1}}},{{{1}}},{{{0}}}}};



+ 3
- 3
src/per_curve/elligator.tmpl.c View File

@@ -14,10 +14,10 @@ static const int EDWARDS_D = $(d);

extern void API_NS(deisogenize) (
gf_s *__restrict__ s,
gf_s *__restrict__ minus_t_over_s,
gf_s *__restrict__ altx,
const point_t p,
mask_t toggle_hibit_s,
mask_t toggle_hibit_t_over_s,
mask_t toggle_altx,
mask_t toggle_rotation
);

@@ -50,7 +50,7 @@ void API_NS(point_from_hash_nonuniform) (
/* s@a = +-|N.e| */
gf_mul(a,N,e);
gf_cond_neg(a,gf_hibit(a)^square); /* NB this is - what is listed in the paper */
gf_cond_neg(a,gf_lobit(a) ^ ~square);
/* t@b = -+ cN(r-1)((a-2d)e)^2 - 1 */
gf_mulw(c,e,1-2*EDWARDS_D); /* (a-2d)e */


+ 3
- 0
src/per_curve/point.tmpl.hxx View File

@@ -45,6 +45,9 @@ struct $(cxx_ns) {
/** The name of the curve */
static inline const char *name() { return "$(name)"; }

/** The name of the curve */
static inline int bits() { return $(gf_bits); }

/** The curve's cofactor (removed, but useful for testing) */
static const int REMOVED_COFACTOR = $(cofactor);



+ 2
- 0
src/per_field/f_field.tmpl.h View File

@@ -23,6 +23,7 @@ typedef struct gf_$(gf_shortname)_s {
#define gf_s gf_$(gf_shortname)_s
#define gf_eq gf_$(gf_shortname)_eq
#define gf_hibit gf_$(gf_shortname)_hibit
#define gf_lobit gf_$(gf_shortname)_lobit
#define gf_copy gf_$(gf_shortname)_copy
#define gf_add gf_$(gf_shortname)_add
#define gf_sub gf_$(gf_shortname)_sub
@@ -66,6 +67,7 @@ void gf_mulw_unsigned (gf_s *__restrict__ out, const gf a, uint32_t b);
void gf_sqr (gf_s *__restrict__ out, const gf a);
mask_t gf_isr(gf a, const gf x); /** a^2 x = 1, QNR, or 0 if x=0. Return true if successful */
mask_t gf_eq (const gf x, const gf y);
mask_t gf_lobit (const gf x);
mask_t gf_hibit (const gf x);

void gf_serialize (uint8_t *serial, const gf x,int with_highbit);


+ 8
- 0
src/per_field/f_generic.tmpl.c View File

@@ -41,6 +41,14 @@ mask_t gf_hibit(const gf x) {
return -(y->limb[0]&1);
}

/** Return high bit of x = low bit of 2x mod p */
mask_t gf_lobit(const gf x) {
gf y;
gf_copy(y,x);
gf_strong_reduce(y);
return -(y->limb[0]&1);
}

/** Deserialize from wire format; return -1 on success and 0 on failure. */
mask_t gf_deserialize (gf x, const uint8_t serial[SER_BYTES], int with_hibit) {
unsigned int j=0, fill=0;


+ 161
- 0
test/ristretto.cxx View File

@@ -0,0 +1,161 @@
/**
* @file ristretto.cxx
* @author Mike Hamburg
*
* @copyright
* Copyright (c) 2015 Cryptography Research, Inc. \n
* Released under the MIT License. See LICENSE.txt for license information.
*
* @brief Ristretto implementation widget
*/

#include <decaf.hxx>
#include <stdio.h>
using namespace decaf;

inline int hexi(char c) {
if (c >= '0' && c < '9') return c-'0';
if (c >= 'a' && c < 'f') return c-'a'+0xa;
if (c >= 'A' && c < 'F') return c-'A'+0xa;
return -1;
}

int parsehex(uint8_t *out, size_t sizeof_out, const char *hex) {
size_t l = strlen(hex);
if (l%2 != 0) {
fprintf(stderr,"String should be hex, but has odd length\n: %s\n", hex);
return -1;
} else if (l/2 > sizeof_out) {
fprintf(stderr,"Argument is too long: %s\n", hex);
return -1;
}
memset(out,0,sizeof_out);
int ret1,ret2;
for (size_t i=0; i<l/2; i++) {
if ( (ret1 = hexi(hex[2*i ])) < 0
|| (ret2 = hexi(hex[2*i+1])) < 0) {
fprintf(stderr,"Invalid hex %s\n",hex);
return -1;
}
out[i] = ret1*16+ret2;
}
return 0;
}

void printhex(const uint8_t *in, size_t sizeof_in) {
for (; sizeof_in > 0; in++,sizeof_in--) {
printf("%02x",*in);
}
}


static int g_argc = 0;
static char **g_argv = NULL;
static int error = 0;
static int done = 0;

void usage() {
const char *me=g_argv[0];
if (!me) me = "ristretto";
for (unsigned i=0; g_argv[0][i]; i++) {
if (g_argv[0][i] == '/' && g_argv[0][i+1] != 0 && g_argv[0][i+1] != '/') {
me = &g_argv[0][i];
}
}
fprintf(stderr,"Usage: %s [points] [operations] ...\n", me);
fprintf(stderr," -b 255|448: Set which group to use (sometimes inferred from lengths)\n");
fprintf(stderr,"\n");
fprintf(stderr," Ways to create points:\n");
fprintf(stderr," [hex]: Point from point data as hex\n");
fprintf(stderr," -e [hex]: Create point by hashing to curve using elligator\n");
fprintf(stderr," base: Base point of curve\n");
fprintf(stderr,"\n");
fprintf(stderr," Operations:\n");
fprintf(stderr," -n [point]: negative of point\n");
fprintf(stderr," -s [scalar] * [point]: Hash to curve using elligator\n");
fprintf(stderr," [point] + [point]: Add two poitns\n");
fprintf(stderr,"\n");
fprintf(stderr," NB: this is a debugging widget. It doesn't yet have order of operations.\n");
fprintf(stderr," *** DON'T USE THIS UTILITY FOR ACTUAL CRYPTO! ***\n");
fprintf(stderr," It's only for debugging!\n");
fprintf(stderr,"\n");
exit(-2);
}

template<typename Group> class Run {
public:
static void run() {
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, scalarempty=true, neg=false;
if (done || error) return;
for (int i=1; i<g_argc && !error; i++) {
bool point = false;
if (!strcmp(g_argv[i],"-b") && ++i<g_argc) {
if (atoi(g_argv[i]) == Group::bits()) continue;
else return;
} else if (!strcmp(g_argv[i],"+")) {
if (elligator || scalar || empty) usage();
plus = true;
} else if (!strcmp(g_argv[i],"-n")) {
neg = !neg;
} else if (!strcmp(g_argv[i],"*")) {
if (elligator || scalar || scalarempty) usage();
mul = true;
} else if (!strcmp(g_argv[i],"-s")) {
if (elligator || scalar || !scalarempty) usage();
scalar = true;
} else if (!strcmp(g_argv[i],"-e")) {
if (elligator || scalar) usage();
elligator = true;
} else if (!strcmp(g_argv[i],"base")) {
if (elligator || scalar) usage();
b = b.base();
point = true;
} else if ((strlen(g_argv[i]) == 2*sizeof(tmp)
|| ((scalar || elligator) && strlen(g_argv[i]) <= 2*sizeof(tmp)))
&& !(error=parsehex(tmp,sizeof(tmp),g_argv[i]))) {
if (scalar) {
s = Block(tmp,sizeof(tmp)); scalar=false; scalarempty=false;
} else if (elligator) {
point = true;
b.set_to_hash(Block(tmp,sizeof(tmp))); elligator=false;
} else if (DECAF_SUCCESS != b.decode(Block(tmp,sizeof(tmp)))) {
fprintf(stderr,"Error: %s isn't in the group\n",g_argv[i]);
error = -1;
} else {
point = true;
}
} else if (error || !empty) usage();

if (point) {
if (neg) { b = -b; neg = false; }
if (mul) { b *= s; mul=false; }
if (empty) { a = b; empty=false; }
else if (plus) { a += b; plus=false; }
else usage();
}
}
if (!error && !empty) {
a.serialize_into(tmp);
printhex(tmp,sizeof(tmp));
printf("\n");
done = true;
}
}
};

int main(int argc, char **argv) {
g_argc = argc;
g_argv = argv;
run_for_all_curves<Run>();
if (!done) usage();
return (error<0) ? -error : error;
}

Loading…
Cancel
Save