Commit c82e7ae7 authored by Michael Hamburg's avatar Michael Hamburg

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

parent 263d4549
......@@ -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)
......
......@@ -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}}}}};
......
......@@ -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 */
......
......@@ -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}}}}};
......
......@@ -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 */
......
......@@ -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);
......
......@@ -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;
......
......@@ -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);
......
......@@ -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;
......
......@@ -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;
......
......@@ -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;
......
......@@ -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}}}}};
......
......@@ -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 */
......
......@@ -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);
......
......@@ -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);
......
......@@ -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;
......
/**
* @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;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment