@@ -124,13 +124,15 @@ class QuotientEdwardsPoint(object): | |||||
# Utility functions | # Utility functions | ||||
@classmethod | @classmethod | ||||
def bytesToGf(cls,bytes,mustBeProper=True,mustBePositive=False): | |||||
def bytesToGf(cls,bytes,mustBeProper=True,mustBePositive=False,maskHiBits=False): | |||||
"""Convert little-endian bytes to field element, sanity check length""" | """Convert little-endian bytes to field element, sanity check length""" | ||||
if len(bytes) != cls.encLen: | if len(bytes) != cls.encLen: | ||||
raise InvalidEncodingException("wrong length %d" % len(bytes)) | raise InvalidEncodingException("wrong length %d" % len(bytes)) | ||||
s = dec_le(bytes) | s = dec_le(bytes) | ||||
if mustBeProper and s >= cls.F.modulus(): | |||||
if mustBeProper and s >= cls.F.order(): | |||||
raise InvalidEncodingException("%d out of range!" % s) | raise InvalidEncodingException("%d out of range!" % s) | ||||
bitlen = int(ceil(log(cls.F.order())/log(2))) | |||||
if maskHiBits: s &= 2^bitlen-1 | |||||
s = cls.F(s) | s = cls.F(s) | ||||
if mustBePositive and negative(s): | if mustBePositive and negative(s): | ||||
raise InvalidEncodingException("%d is negative!" % s) | raise InvalidEncodingException("%d is negative!" % s) | ||||
@@ -242,7 +244,7 @@ class RistrettoPoint(QuotientEdwardsPoint): | |||||
@classmethod | @classmethod | ||||
def elligatorSpec(cls,r0): | def elligatorSpec(cls,r0): | ||||
a,d = cls.a,cls.d | a,d = cls.a,cls.d | ||||
r = cls.qnr * cls.bytesToGf(r0)^2 | |||||
r = cls.qnr * cls.bytesToGf(r0,mustBeProper=False,maskHiBits=True)^2 | |||||
den = (d*r-a)*(a*r-d) | den = (d*r-a)*(a*r-d) | ||||
if den == 0: return cls() | if den == 0: return cls() | ||||
n1 = cls.a*(r+1)*(a+d)*(d-a)/den | n1 = cls.a*(r+1)*(a+d)*(d-a)/den | ||||
@@ -258,7 +260,7 @@ class RistrettoPoint(QuotientEdwardsPoint): | |||||
@optimized_version_of("elligatorSpec") | @optimized_version_of("elligatorSpec") | ||||
def elligator(cls,r0): | def elligator(cls,r0): | ||||
a,d = cls.a,cls.d | a,d = cls.a,cls.d | ||||
r0 = cls.bytesToGf(r0) | |||||
r0 = cls.bytesToGf(r0,mustBeProper=False,maskHiBits=True) | |||||
r = cls.qnr * r0^2 | r = cls.qnr * r0^2 | ||||
den = (d*r-a)*(a*r-d) | den = (d*r-a)*(a*r-d) | ||||
num = cls.a*(r+1)*(a+d)*(d-a) | num = cls.a*(r+1)*(a+d)*(d-a) | ||||
@@ -469,7 +471,7 @@ class Decaf_1_1_Point(QuotientEdwardsPoint): | |||||
def elligatorSpec(cls,r0,fromR=False): | def elligatorSpec(cls,r0,fromR=False): | ||||
a,d = cls.a,cls.d | a,d = cls.a,cls.d | ||||
if fromR: r = r0 | if fromR: r = r0 | ||||
else: r = cls.qnr * cls.bytesToGf(r0)^2 | |||||
else: r = cls.qnr * cls.bytesToGf(r0,mustBeProper=False,maskHiBits=True)^2 | |||||
den = (d*r-(d-a))*((d-a)*r-d) | den = (d*r-(d-a))*((d-a)*r-d) | ||||
if den == 0: return cls() | if den == 0: return cls() | ||||
@@ -486,7 +488,7 @@ class Decaf_1_1_Point(QuotientEdwardsPoint): | |||||
@optimized_version_of("elligatorSpec") | @optimized_version_of("elligatorSpec") | ||||
def elligator(cls,r0): | def elligator(cls,r0): | ||||
a,d = cls.a,cls.d | a,d = cls.a,cls.d | ||||
r0 = cls.bytesToGf(r0) | |||||
r0 = cls.bytesToGf(r0,mustBeProper=False,maskHiBits=True) | |||||
r = cls.qnr * r0^2 | r = cls.qnr * r0^2 | ||||
den = (d*r-(d-a))*((d-a)*r-d) | den = (d*r-(d-a))*((d-a)*r-d) | ||||
num = (r+1)*(a-2*d) | num = (r+1)*(a-2*d) | ||||
@@ -693,13 +695,6 @@ def test(cls,n): | |||||
Q2 = Q0*(r+1) | Q2 = Q0*(r+1) | ||||
if Q1 + Q0 != Q2: raise TestFailedException("Scalarmul doesn't work") | if Q1 + Q0 != Q2: raise TestFailedException("Scalarmul doesn't work") | ||||
Q = Q1 | Q = Q1 | ||||
#test(Ed25519Point,100) | |||||
#test(NegEd25519Point,100) | |||||
#test(IsoEd25519Point,100) | |||||
#test(IsoEd448Point,100) | |||||
#test(TwistedEd448GoldilocksPoint,100) | |||||
#test(Ed448GoldilocksPoint,100) | |||||
def testElligator(cls,n): | def testElligator(cls,n): | ||||
@@ -709,7 +704,7 @@ def testElligator(cls,n): | |||||
P = cls.elligator(r) | P = cls.elligator(r) | ||||
if hasattr(P,"invertElligator"): | if hasattr(P,"invertElligator"): | ||||
iv = P.invertElligator() | iv = P.invertElligator() | ||||
modr = bytes(cls.gfToBytes(cls.bytesToGf(r))) | |||||
modr = bytes(cls.gfToBytes(cls.bytesToGf(r,mustBeProper=False,maskHiBits=True))) | |||||
iv2 = P.torque().invertElligator() | iv2 = P.torque().invertElligator() | ||||
if modr not in iv: print "Failed to invert Elligator!" | if modr not in iv: print "Failed to invert Elligator!" | ||||
if len(iv) != len(set(iv)): | if len(iv) != len(set(iv)): | ||||
@@ -723,12 +718,7 @@ def testElligator(cls,n): | |||||
pass # TODO | pass # TODO | ||||
#testElligator(Ed25519Point,100) | |||||
#testElligator(NegEd25519Point,100) | |||||
#testElligator(IsoEd25519Point,100) | |||||
#testElligator(IsoEd448Point,100) | |||||
#testElligator(Ed448GoldilocksPoint,100) | |||||
#testElligator(TwistedEd448GoldilocksPoint,100) | |||||
def gangtest(classes,n): | def gangtest(classes,n): | ||||
print "Gang test",[cls.__name__ for cls in classes] | print "Gang test",[cls.__name__ for cls in classes] | ||||
@@ -756,5 +746,19 @@ def gangtest(classes,n): | |||||
for c,ret in zip(classes,rets): | for c,ret in zip(classes,rets): | ||||
print c,binascii.hexlify(ret) | print c,binascii.hexlify(ret) | ||||
#gangtest([IsoEd448Point,TwistedEd448GoldilocksPoint,Ed448GoldilocksPoint],100) | |||||
#gangtest([Ed25519Point,IsoEd25519Point],100) | |||||
test(Ed25519Point,100) | |||||
test(NegEd25519Point,100) | |||||
test(IsoEd25519Point,100) | |||||
test(IsoEd448Point,100) | |||||
test(TwistedEd448GoldilocksPoint,100) | |||||
test(Ed448GoldilocksPoint,100) | |||||
testElligator(Ed25519Point,100) | |||||
testElligator(NegEd25519Point,100) | |||||
testElligator(IsoEd25519Point,100) | |||||
testElligator(IsoEd448Point,100) | |||||
testElligator(Ed448GoldilocksPoint,100) | |||||
testElligator(TwistedEd448GoldilocksPoint,100) | |||||
gangtest([IsoEd448Point,TwistedEd448GoldilocksPoint,Ed448GoldilocksPoint],100) | |||||
gangtest([Ed25519Point,IsoEd25519Point],100) |
@@ -238,7 +238,7 @@ decaf_error_t API_NS(point_decode) ( | |||||
gf s, s2, num, tmp; | gf s, s2, num, tmp; | ||||
gf_s *tmp2=s2, *ynum=p->z, *isr=p->x, *den=p->t; | gf_s *tmp2=s2, *ynum=p->z, *isr=p->x, *den=p->t; | ||||
mask_t succ = gf_deserialize(s, ser, 1); | |||||
mask_t succ = gf_deserialize(s, ser, 1, 0); | |||||
succ &= bool_to_mask(allow_identity) | ~gf_eq(s, ZERO); | succ &= bool_to_mask(allow_identity) | ~gf_eq(s, ZERO); | ||||
succ &= ~gf_lobit(s); | succ &= ~gf_lobit(s); | ||||
@@ -827,7 +827,7 @@ void API_NS(point_debugging_pscale) ( | |||||
) { | ) { | ||||
gf gfac,tmp; | gf gfac,tmp; | ||||
/* NB this means you'll never pscale by negative numbers for p521 */ | /* NB this means you'll never pscale by negative numbers for p521 */ | ||||
ignore_result(gf_deserialize(gfac,factor,0)); | |||||
ignore_result(gf_deserialize(gfac,factor,0,0)); | |||||
gf_cond_sel(gfac,gfac,ONE,gf_eq(gfac,ZERO)); | gf_cond_sel(gfac,gfac,ONE,gf_eq(gfac,ZERO)); | ||||
gf_mul(tmp,p->x,gfac); | gf_mul(tmp,p->x,gfac); | ||||
gf_copy(q->x,tmp); | gf_copy(q->x,tmp); | ||||
@@ -1143,7 +1143,7 @@ decaf_error_t API_NS(point_decode_like_eddsa_and_ignore_cofactor) ( | |||||
mask_t low = ~word_is_zero(enc2[DECAF_EDDSA_25519_PRIVATE_BYTES-1] & 0x80); | mask_t low = ~word_is_zero(enc2[DECAF_EDDSA_25519_PRIVATE_BYTES-1] & 0x80); | ||||
enc2[DECAF_EDDSA_25519_PRIVATE_BYTES-1] &= ~0x80; | enc2[DECAF_EDDSA_25519_PRIVATE_BYTES-1] &= ~0x80; | ||||
mask_t succ = gf_deserialize(p->y, enc2, 1); | |||||
mask_t succ = gf_deserialize(p->y, enc2, 1, 0); | |||||
#if 7 == 0 | #if 7 == 0 | ||||
succ &= word_is_zero(enc2[DECAF_EDDSA_25519_PRIVATE_BYTES-1]); | succ &= word_is_zero(enc2[DECAF_EDDSA_25519_PRIVATE_BYTES-1]); | ||||
#endif | #endif | ||||
@@ -1243,7 +1243,7 @@ decaf_error_t decaf_x25519 ( | |||||
const uint8_t scalar[X_PRIVATE_BYTES] | const uint8_t scalar[X_PRIVATE_BYTES] | ||||
) { | ) { | ||||
gf x1, x2, z2, x3, z3, t1, t2; | gf x1, x2, z2, x3, z3, t1, t2; | ||||
ignore_result(gf_deserialize(x1,base,1)); | |||||
ignore_result(gf_deserialize(x1,base,1,0)); | |||||
gf_copy(x2,ONE); | gf_copy(x2,ONE); | ||||
gf_copy(z2,ZERO); | gf_copy(z2,ZERO); | ||||
gf_copy(x3,x1); | gf_copy(x3,x1); | ||||
@@ -1314,15 +1314,8 @@ void decaf_ed25519_convert_public_key_to_x25519 ( | |||||
const uint8_t ed[DECAF_EDDSA_25519_PUBLIC_BYTES] | const uint8_t ed[DECAF_EDDSA_25519_PUBLIC_BYTES] | ||||
) { | ) { | ||||
gf y; | gf y; | ||||
{ | |||||
uint8_t enc2[DECAF_EDDSA_25519_PUBLIC_BYTES]; | |||||
memcpy(enc2,ed,sizeof(enc2)); | |||||
/* retrieve y from the ed compressed point */ | |||||
enc2[DECAF_EDDSA_25519_PUBLIC_BYTES-1] &= ~0x80; | |||||
ignore_result(gf_deserialize(y, enc2, 0)); | |||||
decaf_bzero(enc2,sizeof(enc2)); | |||||
} | |||||
const uint8_t mask = (uint8_t)(0xFE<<(6)); | |||||
ignore_result(gf_deserialize(y, ed, 1, mask)); | |||||
{ | { | ||||
gf n,d; | gf n,d; | ||||
@@ -26,7 +26,6 @@ static const int EDWARDS_D = -121665; | |||||
extern const gf RISTRETTO_FACTOR; | extern const gf RISTRETTO_FACTOR; | ||||
/* End of template stuff */ | /* End of template stuff */ | ||||
extern mask_t API_NS(deisogenize) ( | extern mask_t API_NS(deisogenize) ( | ||||
gf_s *__restrict__ s, | gf_s *__restrict__ s, | ||||
gf_s *__restrict__ inv_el_sum, | gf_s *__restrict__ inv_el_sum, | ||||
@@ -42,7 +41,8 @@ void API_NS(point_from_hash_nonuniform) ( | |||||
const unsigned char ser[SER_BYTES] | const unsigned char ser[SER_BYTES] | ||||
) { | ) { | ||||
gf r0,r,a,b,c,N,e; | gf r0,r,a,b,c,N,e; | ||||
ignore_result(gf_deserialize(r0,ser,0)); | |||||
const uint8_t mask = (uint8_t)(0xFE<<(6)); | |||||
ignore_result(gf_deserialize(r0,ser,0,mask)); | |||||
gf_strong_reduce(r0); | gf_strong_reduce(r0); | ||||
gf_sqr(a,r0); | gf_sqr(a,r0); | ||||
gf_mul_qnr(r,a); | gf_mul_qnr(r,a); | ||||
@@ -112,23 +112,6 @@ void API_NS(point_from_hash_uniform) ( | |||||
* log p == 1 mod 8 brainpool curves maybe? | * log p == 1 mod 8 brainpool curves maybe? | ||||
*/ | */ | ||||
#define MAX(A,B) (((A)>(B)) ? (A) : (B)) | #define MAX(A,B) (((A)>(B)) ? (A) : (B)) | ||||
#define PKP_MASK ((1<<(MAX(8*SER_BYTES + 0 - 255,0)))-1) | |||||
#if PKP_MASK != 0 | |||||
static DECAF_INLINE mask_t plus_k_p ( | |||||
uint8_t x[SER_BYTES], | |||||
uint32_t factor_ | |||||
) { | |||||
uint32_t carry = 0; | |||||
uint64_t factor = factor_; | |||||
const uint8_t p[SER_BYTES] = { 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f }; | |||||
for (unsigned int i=0; i<SER_BYTES; i++) { | |||||
uint64_t tmp = carry + p[i] * factor + x[i]; | |||||
/* tmp <= 2^32-1 + (2^32-1)*(2^8-1) + (2^8-1) = 2^40-1 */ | |||||
x[i] = tmp; carry = tmp>>8; | |||||
} | |||||
return word_is_zero(carry); | |||||
} | |||||
#endif | |||||
decaf_error_t | decaf_error_t | ||||
API_NS(invert_elligator_nonuniform) ( | API_NS(invert_elligator_nonuniform) ( | ||||
@@ -136,7 +119,6 @@ API_NS(invert_elligator_nonuniform) ( | |||||
const point_t p, | const point_t p, | ||||
uint32_t hint_ | uint32_t hint_ | ||||
) { | ) { | ||||
/* TODO: test that this can produce sqrt((d-a)/ud) etc. */ | |||||
mask_t hint = hint_; | mask_t hint = hint_; | ||||
mask_t sgn_s = -(hint & 1), | mask_t sgn_s = -(hint & 1), | ||||
sgn_altx = -(hint>>1 & 1), | sgn_altx = -(hint>>1 & 1), | ||||
@@ -198,15 +180,14 @@ API_NS(invert_elligator_nonuniform) ( | |||||
gf_serialize(recovered_hash,b,0); | gf_serialize(recovered_hash,b,0); | ||||
#else | #else | ||||
gf_serialize(recovered_hash,b,1); | gf_serialize(recovered_hash,b,1); | ||||
#if PKP_MASK != 0 | |||||
/* Add a multiple of p to make the result either almost-onto or completely onto. */ | |||||
#if COFACTOR == 8 | |||||
succ &= plus_k_p(recovered_hash, (hint >> 4) & PKP_MASK); | |||||
#else | |||||
succ &= plus_k_p(recovered_hash, (hint >> 3) & PKP_MASK); | |||||
#endif | |||||
#endif | |||||
#endif | #endif | ||||
#if 7 | |||||
#if COFACTOR==8 | |||||
recovered_hash[SER_BYTES-1] ^= (hint>>4)<<7; | |||||
#else | |||||
recovered_hash[SER_BYTES-1] ^= (hint>>3)<<7; | |||||
#endif | |||||
#endif | |||||
return decaf_succeed_if(mask_to_bool(succ)); | return decaf_succeed_if(mask_to_bool(succ)); | ||||
} | } | ||||
@@ -238,7 +238,7 @@ decaf_error_t API_NS(point_decode) ( | |||||
gf s, s2, num, tmp; | gf s, s2, num, tmp; | ||||
gf_s *tmp2=s2, *ynum=p->z, *isr=p->x, *den=p->t; | gf_s *tmp2=s2, *ynum=p->z, *isr=p->x, *den=p->t; | ||||
mask_t succ = gf_deserialize(s, ser, 1); | |||||
mask_t succ = gf_deserialize(s, ser, 1, 0); | |||||
succ &= bool_to_mask(allow_identity) | ~gf_eq(s, ZERO); | succ &= bool_to_mask(allow_identity) | ~gf_eq(s, ZERO); | ||||
succ &= ~gf_lobit(s); | succ &= ~gf_lobit(s); | ||||
@@ -827,7 +827,7 @@ void API_NS(point_debugging_pscale) ( | |||||
) { | ) { | ||||
gf gfac,tmp; | gf gfac,tmp; | ||||
/* NB this means you'll never pscale by negative numbers for p521 */ | /* NB this means you'll never pscale by negative numbers for p521 */ | ||||
ignore_result(gf_deserialize(gfac,factor,0)); | |||||
ignore_result(gf_deserialize(gfac,factor,0,0)); | |||||
gf_cond_sel(gfac,gfac,ONE,gf_eq(gfac,ZERO)); | gf_cond_sel(gfac,gfac,ONE,gf_eq(gfac,ZERO)); | ||||
gf_mul(tmp,p->x,gfac); | gf_mul(tmp,p->x,gfac); | ||||
gf_copy(q->x,tmp); | gf_copy(q->x,tmp); | ||||
@@ -1143,7 +1143,7 @@ decaf_error_t API_NS(point_decode_like_eddsa_and_ignore_cofactor) ( | |||||
mask_t low = ~word_is_zero(enc2[DECAF_EDDSA_448_PRIVATE_BYTES-1] & 0x80); | mask_t low = ~word_is_zero(enc2[DECAF_EDDSA_448_PRIVATE_BYTES-1] & 0x80); | ||||
enc2[DECAF_EDDSA_448_PRIVATE_BYTES-1] &= ~0x80; | enc2[DECAF_EDDSA_448_PRIVATE_BYTES-1] &= ~0x80; | ||||
mask_t succ = gf_deserialize(p->y, enc2, 1); | |||||
mask_t succ = gf_deserialize(p->y, enc2, 1, 0); | |||||
#if 0 == 0 | #if 0 == 0 | ||||
succ &= word_is_zero(enc2[DECAF_EDDSA_448_PRIVATE_BYTES-1]); | succ &= word_is_zero(enc2[DECAF_EDDSA_448_PRIVATE_BYTES-1]); | ||||
#endif | #endif | ||||
@@ -1243,7 +1243,7 @@ decaf_error_t decaf_x448 ( | |||||
const uint8_t scalar[X_PRIVATE_BYTES] | const uint8_t scalar[X_PRIVATE_BYTES] | ||||
) { | ) { | ||||
gf x1, x2, z2, x3, z3, t1, t2; | gf x1, x2, z2, x3, z3, t1, t2; | ||||
ignore_result(gf_deserialize(x1,base,1)); | |||||
ignore_result(gf_deserialize(x1,base,1,0)); | |||||
gf_copy(x2,ONE); | gf_copy(x2,ONE); | ||||
gf_copy(z2,ZERO); | gf_copy(z2,ZERO); | ||||
gf_copy(x3,x1); | gf_copy(x3,x1); | ||||
@@ -1314,15 +1314,8 @@ void decaf_ed448_convert_public_key_to_x448 ( | |||||
const uint8_t ed[DECAF_EDDSA_448_PUBLIC_BYTES] | const uint8_t ed[DECAF_EDDSA_448_PUBLIC_BYTES] | ||||
) { | ) { | ||||
gf y; | gf y; | ||||
{ | |||||
uint8_t enc2[DECAF_EDDSA_448_PUBLIC_BYTES]; | |||||
memcpy(enc2,ed,sizeof(enc2)); | |||||
/* retrieve y from the ed compressed point */ | |||||
enc2[DECAF_EDDSA_448_PUBLIC_BYTES-1] &= ~0x80; | |||||
ignore_result(gf_deserialize(y, enc2, 0)); | |||||
decaf_bzero(enc2,sizeof(enc2)); | |||||
} | |||||
const uint8_t mask = (uint8_t)(0xFE<<(7)); | |||||
ignore_result(gf_deserialize(y, ed, 1, mask)); | |||||
{ | { | ||||
gf n,d; | gf n,d; | ||||
@@ -26,7 +26,6 @@ static const int EDWARDS_D = -39081; | |||||
extern const gf RISTRETTO_FACTOR; | extern const gf RISTRETTO_FACTOR; | ||||
/* End of template stuff */ | /* End of template stuff */ | ||||
extern mask_t API_NS(deisogenize) ( | extern mask_t API_NS(deisogenize) ( | ||||
gf_s *__restrict__ s, | gf_s *__restrict__ s, | ||||
gf_s *__restrict__ inv_el_sum, | gf_s *__restrict__ inv_el_sum, | ||||
@@ -42,7 +41,8 @@ void API_NS(point_from_hash_nonuniform) ( | |||||
const unsigned char ser[SER_BYTES] | const unsigned char ser[SER_BYTES] | ||||
) { | ) { | ||||
gf r0,r,a,b,c,N,e; | gf r0,r,a,b,c,N,e; | ||||
ignore_result(gf_deserialize(r0,ser,0)); | |||||
const uint8_t mask = (uint8_t)(0xFE<<(7)); | |||||
ignore_result(gf_deserialize(r0,ser,0,mask)); | |||||
gf_strong_reduce(r0); | gf_strong_reduce(r0); | ||||
gf_sqr(a,r0); | gf_sqr(a,r0); | ||||
gf_mul_qnr(r,a); | gf_mul_qnr(r,a); | ||||
@@ -112,23 +112,6 @@ void API_NS(point_from_hash_uniform) ( | |||||
* log p == 1 mod 8 brainpool curves maybe? | * log p == 1 mod 8 brainpool curves maybe? | ||||
*/ | */ | ||||
#define MAX(A,B) (((A)>(B)) ? (A) : (B)) | #define MAX(A,B) (((A)>(B)) ? (A) : (B)) | ||||
#define PKP_MASK ((1<<(MAX(8*SER_BYTES + 0 - 448,0)))-1) | |||||
#if PKP_MASK != 0 | |||||
static DECAF_INLINE mask_t plus_k_p ( | |||||
uint8_t x[SER_BYTES], | |||||
uint32_t factor_ | |||||
) { | |||||
uint32_t carry = 0; | |||||
uint64_t factor = factor_; | |||||
const uint8_t p[SER_BYTES] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; | |||||
for (unsigned int i=0; i<SER_BYTES; i++) { | |||||
uint64_t tmp = carry + p[i] * factor + x[i]; | |||||
/* tmp <= 2^32-1 + (2^32-1)*(2^8-1) + (2^8-1) = 2^40-1 */ | |||||
x[i] = tmp; carry = tmp>>8; | |||||
} | |||||
return word_is_zero(carry); | |||||
} | |||||
#endif | |||||
decaf_error_t | decaf_error_t | ||||
API_NS(invert_elligator_nonuniform) ( | API_NS(invert_elligator_nonuniform) ( | ||||
@@ -136,7 +119,6 @@ API_NS(invert_elligator_nonuniform) ( | |||||
const point_t p, | const point_t p, | ||||
uint32_t hint_ | uint32_t hint_ | ||||
) { | ) { | ||||
/* TODO: test that this can produce sqrt((d-a)/ud) etc. */ | |||||
mask_t hint = hint_; | mask_t hint = hint_; | ||||
mask_t sgn_s = -(hint & 1), | mask_t sgn_s = -(hint & 1), | ||||
sgn_altx = -(hint>>1 & 1), | sgn_altx = -(hint>>1 & 1), | ||||
@@ -198,15 +180,14 @@ API_NS(invert_elligator_nonuniform) ( | |||||
gf_serialize(recovered_hash,b,0); | gf_serialize(recovered_hash,b,0); | ||||
#else | #else | ||||
gf_serialize(recovered_hash,b,1); | gf_serialize(recovered_hash,b,1); | ||||
#if PKP_MASK != 0 | |||||
/* Add a multiple of p to make the result either almost-onto or completely onto. */ | |||||
#if COFACTOR == 8 | |||||
succ &= plus_k_p(recovered_hash, (hint >> 4) & PKP_MASK); | |||||
#else | |||||
succ &= plus_k_p(recovered_hash, (hint >> 3) & PKP_MASK); | |||||
#endif | |||||
#endif | |||||
#endif | #endif | ||||
#if 0 | |||||
#if COFACTOR==8 | |||||
recovered_hash[SER_BYTES-1] ^= (hint>>4)<<0; | |||||
#else | |||||
recovered_hash[SER_BYTES-1] ^= (hint>>3)<<0; | |||||
#endif | |||||
#endif | |||||
return decaf_succeed_if(mask_to_bool(succ)); | return decaf_succeed_if(mask_to_bool(succ)); | ||||
} | } | ||||
@@ -86,7 +86,7 @@ mask_t gf_lobit (const gf x); | |||||
mask_t gf_hibit (const gf x); | mask_t gf_hibit (const gf x); | ||||
void gf_serialize (uint8_t *serial, const gf x,int with_highbit); | void gf_serialize (uint8_t *serial, const gf x,int with_highbit); | ||||
mask_t gf_deserialize (gf x, const uint8_t serial[SER_BYTES],int with_highbit); | |||||
mask_t gf_deserialize (gf x, const uint8_t serial[SER_BYTES],int with_hibit,uint8_t hi_nmask); | |||||
#ifdef __cplusplus | #ifdef __cplusplus | ||||
@@ -61,13 +61,16 @@ mask_t gf_lobit(const gf x) { | |||||
} | } | ||||
/** Deserialize from wire format; return -1 on success and 0 on failure. */ | /** 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) { | |||||
mask_t gf_deserialize (gf x, const uint8_t serial[SER_BYTES], int with_hibit, uint8_t hi_nmask) { | |||||
unsigned int j=0, fill=0; | unsigned int j=0, fill=0; | ||||
dword_t buffer = 0; | dword_t buffer = 0; | ||||
dsword_t scarry = 0; | dsword_t scarry = 0; | ||||
const unsigned nbytes = with_hibit ? X_SER_BYTES : SER_BYTES; | |||||
UNROLL for (unsigned int i=0; i<NLIMBS; i++) { | UNROLL for (unsigned int i=0; i<NLIMBS; i++) { | ||||
UNROLL while (fill < LIMB_PLACE_VALUE(LIMBPERM(i)) && j < (with_hibit ? X_SER_BYTES : SER_BYTES)) { | |||||
buffer |= ((dword_t)serial[j]) << fill; | |||||
UNROLL while (fill < LIMB_PLACE_VALUE(LIMBPERM(i)) && j < nbytes) { | |||||
uint8_t sj = serial[j]; | |||||
if (j==nbytes-1) sj &= ~hi_nmask; | |||||
buffer |= ((dword_t)sj) << fill; | |||||
fill += 8; | fill += 8; | ||||
j++; | j++; | ||||
} | } | ||||
@@ -86,7 +86,7 @@ mask_t gf_lobit (const gf x); | |||||
mask_t gf_hibit (const gf x); | mask_t gf_hibit (const gf x); | ||||
void gf_serialize (uint8_t *serial, const gf x,int with_highbit); | void gf_serialize (uint8_t *serial, const gf x,int with_highbit); | ||||
mask_t gf_deserialize (gf x, const uint8_t serial[SER_BYTES],int with_highbit); | |||||
mask_t gf_deserialize (gf x, const uint8_t serial[SER_BYTES],int with_hibit,uint8_t hi_nmask); | |||||
#ifdef __cplusplus | #ifdef __cplusplus | ||||
@@ -61,13 +61,16 @@ mask_t gf_lobit(const gf x) { | |||||
} | } | ||||
/** Deserialize from wire format; return -1 on success and 0 on failure. */ | /** 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) { | |||||
mask_t gf_deserialize (gf x, const uint8_t serial[SER_BYTES], int with_hibit, uint8_t hi_nmask) { | |||||
unsigned int j=0, fill=0; | unsigned int j=0, fill=0; | ||||
dword_t buffer = 0; | dword_t buffer = 0; | ||||
dsword_t scarry = 0; | dsword_t scarry = 0; | ||||
const unsigned nbytes = with_hibit ? X_SER_BYTES : SER_BYTES; | |||||
UNROLL for (unsigned int i=0; i<NLIMBS; i++) { | UNROLL for (unsigned int i=0; i<NLIMBS; i++) { | ||||
UNROLL while (fill < LIMB_PLACE_VALUE(LIMBPERM(i)) && j < (with_hibit ? X_SER_BYTES : SER_BYTES)) { | |||||
buffer |= ((dword_t)serial[j]) << fill; | |||||
UNROLL while (fill < LIMB_PLACE_VALUE(LIMBPERM(i)) && j < nbytes) { | |||||
uint8_t sj = serial[j]; | |||||
if (j==nbytes-1) sj &= ~hi_nmask; | |||||
buffer |= ((dword_t)sj) << fill; | |||||
fill += 8; | fill += 8; | ||||
j++; | j++; | ||||
} | } | ||||
@@ -670,6 +670,16 @@ void decaf_255_point_from_hash_uniform ( | |||||
* inverse sampling, this function succeeds or fails | * inverse sampling, this function succeeds or fails | ||||
* independently for different "which" values. | * independently for different "which" values. | ||||
* | * | ||||
* This function isn't guaranteed to find every possible | |||||
* preimage, but it finds all except a small finite number. | |||||
* In particular, when the number of bits in the modulus isn't | |||||
* a multiple of 8 (i.e. for curve25519), it sets the high bits | |||||
* independently, which enables the generated data to be uniform. | |||||
* But it doesn't add p, so you'll never get exactly p from this | |||||
* function. This might change in the future, especially if | |||||
* we ever support eg Brainpool curves, where this could cause | |||||
* real nonuniformity. | |||||
* | |||||
* @param [out] recovered_hash Encoded data. | * @param [out] recovered_hash Encoded data. | ||||
* @param [in] pt The point to encode. | * @param [in] pt The point to encode. | ||||
* @param [in] which A value determining which inverse point | * @param [in] which A value determining which inverse point | ||||
@@ -670,6 +670,16 @@ void decaf_448_point_from_hash_uniform ( | |||||
* inverse sampling, this function succeeds or fails | * inverse sampling, this function succeeds or fails | ||||
* independently for different "which" values. | * independently for different "which" values. | ||||
* | * | ||||
* This function isn't guaranteed to find every possible | |||||
* preimage, but it finds all except a small finite number. | |||||
* In particular, when the number of bits in the modulus isn't | |||||
* a multiple of 8 (i.e. for curve25519), it sets the high bits | |||||
* independently, which enables the generated data to be uniform. | |||||
* But it doesn't add p, so you'll never get exactly p from this | |||||
* function. This might change in the future, especially if | |||||
* we ever support eg Brainpool curves, where this could cause | |||||
* real nonuniformity. | |||||
* | |||||
* @param [out] recovered_hash Encoded data. | * @param [out] recovered_hash Encoded data. | ||||
* @param [in] pt The point to encode. | * @param [in] pt The point to encode. | ||||
* @param [in] which A value determining which inverse point | * @param [in] which A value determining which inverse point | ||||
@@ -227,7 +227,7 @@ decaf_error_t API_NS(point_decode) ( | |||||
gf s, s2, num, tmp; | gf s, s2, num, tmp; | ||||
gf_s *tmp2=s2, *ynum=p->z, *isr=p->x, *den=p->t; | gf_s *tmp2=s2, *ynum=p->z, *isr=p->x, *den=p->t; | ||||
mask_t succ = gf_deserialize(s, ser, 1); | |||||
mask_t succ = gf_deserialize(s, ser, 1, 0); | |||||
succ &= bool_to_mask(allow_identity) | ~gf_eq(s, ZERO); | succ &= bool_to_mask(allow_identity) | ~gf_eq(s, ZERO); | ||||
succ &= ~gf_lobit(s); | succ &= ~gf_lobit(s); | ||||
@@ -816,7 +816,7 @@ void API_NS(point_debugging_pscale) ( | |||||
) { | ) { | ||||
gf gfac,tmp; | gf gfac,tmp; | ||||
/* NB this means you'll never pscale by negative numbers for p521 */ | /* NB this means you'll never pscale by negative numbers for p521 */ | ||||
ignore_result(gf_deserialize(gfac,factor,0)); | |||||
ignore_result(gf_deserialize(gfac,factor,0,0)); | |||||
gf_cond_sel(gfac,gfac,ONE,gf_eq(gfac,ZERO)); | gf_cond_sel(gfac,gfac,ONE,gf_eq(gfac,ZERO)); | ||||
gf_mul(tmp,p->x,gfac); | gf_mul(tmp,p->x,gfac); | ||||
gf_copy(q->x,tmp); | gf_copy(q->x,tmp); | ||||
@@ -1132,7 +1132,7 @@ decaf_error_t API_NS(point_decode_like_eddsa_and_ignore_cofactor) ( | |||||
mask_t low = ~word_is_zero(enc2[DECAF_EDDSA_$(gf_shortname)_PRIVATE_BYTES-1] & 0x80); | mask_t low = ~word_is_zero(enc2[DECAF_EDDSA_$(gf_shortname)_PRIVATE_BYTES-1] & 0x80); | ||||
enc2[DECAF_EDDSA_$(gf_shortname)_PRIVATE_BYTES-1] &= ~0x80; | enc2[DECAF_EDDSA_$(gf_shortname)_PRIVATE_BYTES-1] &= ~0x80; | ||||
mask_t succ = gf_deserialize(p->y, enc2, 1); | |||||
mask_t succ = gf_deserialize(p->y, enc2, 1, 0); | |||||
#if $(gf_bits % 8) == 0 | #if $(gf_bits % 8) == 0 | ||||
succ &= word_is_zero(enc2[DECAF_EDDSA_$(gf_shortname)_PRIVATE_BYTES-1]); | succ &= word_is_zero(enc2[DECAF_EDDSA_$(gf_shortname)_PRIVATE_BYTES-1]); | ||||
#endif | #endif | ||||
@@ -1232,7 +1232,7 @@ decaf_error_t decaf_x$(gf_shortname) ( | |||||
const uint8_t scalar[X_PRIVATE_BYTES] | const uint8_t scalar[X_PRIVATE_BYTES] | ||||
) { | ) { | ||||
gf x1, x2, z2, x3, z3, t1, t2; | gf x1, x2, z2, x3, z3, t1, t2; | ||||
ignore_result(gf_deserialize(x1,base,1)); | |||||
ignore_result(gf_deserialize(x1,base,1,0)); | |||||
gf_copy(x2,ONE); | gf_copy(x2,ONE); | ||||
gf_copy(z2,ZERO); | gf_copy(z2,ZERO); | ||||
gf_copy(x3,x1); | gf_copy(x3,x1); | ||||
@@ -1303,15 +1303,8 @@ void decaf_ed$(gf_shortname)_convert_public_key_to_x$(gf_shortname) ( | |||||
const uint8_t ed[DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES] | const uint8_t ed[DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES] | ||||
) { | ) { | ||||
gf y; | gf y; | ||||
{ | |||||
uint8_t enc2[DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES]; | |||||
memcpy(enc2,ed,sizeof(enc2)); | |||||
/* retrieve y from the ed compressed point */ | |||||
enc2[DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES-1] &= ~0x80; | |||||
ignore_result(gf_deserialize(y, enc2, 0)); | |||||
decaf_bzero(enc2,sizeof(enc2)); | |||||
} | |||||
const uint8_t mask = (uint8_t)(0xFE<<($((gf_bits-1)%8))); | |||||
ignore_result(gf_deserialize(y, ed, 1, mask)); | |||||
{ | { | ||||
gf n,d; | gf n,d; | ||||
@@ -15,7 +15,6 @@ static const int EDWARDS_D = $(d); | |||||
extern const gf RISTRETTO_FACTOR; | extern const gf RISTRETTO_FACTOR; | ||||
/* End of template stuff */ | /* End of template stuff */ | ||||
extern mask_t API_NS(deisogenize) ( | extern mask_t API_NS(deisogenize) ( | ||||
gf_s *__restrict__ s, | gf_s *__restrict__ s, | ||||
gf_s *__restrict__ inv_el_sum, | gf_s *__restrict__ inv_el_sum, | ||||
@@ -31,7 +30,8 @@ void API_NS(point_from_hash_nonuniform) ( | |||||
const unsigned char ser[SER_BYTES] | const unsigned char ser[SER_BYTES] | ||||
) { | ) { | ||||
gf r0,r,a,b,c,N,e; | gf r0,r,a,b,c,N,e; | ||||
ignore_result(gf_deserialize(r0,ser,0)); | |||||
const uint8_t mask = (uint8_t)(0xFE<<($((gf_bits-1)%8))); | |||||
ignore_result(gf_deserialize(r0,ser,0,mask)); | |||||
gf_strong_reduce(r0); | gf_strong_reduce(r0); | ||||
gf_sqr(a,r0); | gf_sqr(a,r0); | ||||
gf_mul_qnr(r,a); | gf_mul_qnr(r,a); | ||||
@@ -101,23 +101,6 @@ void API_NS(point_from_hash_uniform) ( | |||||
* log p == 1 mod 8 brainpool curves maybe? | * log p == 1 mod 8 brainpool curves maybe? | ||||
*/ | */ | ||||
#define MAX(A,B) (((A)>(B)) ? (A) : (B)) | #define MAX(A,B) (((A)>(B)) ? (A) : (B)) | ||||
#define PKP_MASK ((1<<(MAX(8*SER_BYTES + $(elligator_onto) - $(gf_bits),0)))-1) | |||||
#if PKP_MASK != 0 | |||||
static DECAF_INLINE mask_t plus_k_p ( | |||||
uint8_t x[SER_BYTES], | |||||
uint32_t factor_ | |||||
) { | |||||
uint32_t carry = 0; | |||||
uint64_t factor = factor_; | |||||
const uint8_t p[SER_BYTES] = { $(ser(modulus,8)) }; | |||||
for (unsigned int i=0; i<SER_BYTES; i++) { | |||||
uint64_t tmp = carry + p[i] * factor + x[i]; | |||||
/* tmp <= 2^32-1 + (2^32-1)*(2^8-1) + (2^8-1) = 2^40-1 */ | |||||
x[i] = tmp; carry = tmp>>8; | |||||
} | |||||
return word_is_zero(carry); | |||||
} | |||||
#endif | |||||
decaf_error_t | decaf_error_t | ||||
API_NS(invert_elligator_nonuniform) ( | API_NS(invert_elligator_nonuniform) ( | ||||
@@ -125,7 +108,6 @@ API_NS(invert_elligator_nonuniform) ( | |||||
const point_t p, | const point_t p, | ||||
uint32_t hint_ | uint32_t hint_ | ||||
) { | ) { | ||||
/* TODO: test that this can produce sqrt((d-a)/ud) etc. */ | |||||
mask_t hint = hint_; | mask_t hint = hint_; | ||||
mask_t sgn_s = -(hint & 1), | mask_t sgn_s = -(hint & 1), | ||||
sgn_altx = -(hint>>1 & 1), | sgn_altx = -(hint>>1 & 1), | ||||
@@ -187,15 +169,14 @@ API_NS(invert_elligator_nonuniform) ( | |||||
gf_serialize(recovered_hash,b,0); | gf_serialize(recovered_hash,b,0); | ||||
#else | #else | ||||
gf_serialize(recovered_hash,b,1); | gf_serialize(recovered_hash,b,1); | ||||
#if PKP_MASK != 0 | |||||
/* Add a multiple of p to make the result either almost-onto or completely onto. */ | |||||
#if COFACTOR == 8 | |||||
succ &= plus_k_p(recovered_hash, (hint >> 4) & PKP_MASK); | |||||
#else | |||||
succ &= plus_k_p(recovered_hash, (hint >> 3) & PKP_MASK); | |||||
#endif | |||||
#endif | |||||
#endif | #endif | ||||
#if $(gf_bits%8) | |||||
#if COFACTOR==8 | |||||
recovered_hash[SER_BYTES-1] ^= (hint>>4)<<$(gf_bits%8); | |||||
#else | |||||
recovered_hash[SER_BYTES-1] ^= (hint>>3)<<$(gf_bits%8); | |||||
#endif | |||||
#endif | |||||
return decaf_succeed_if(mask_to_bool(succ)); | return decaf_succeed_if(mask_to_bool(succ)); | ||||
} | } | ||||
@@ -655,6 +655,16 @@ void $(c_ns)_point_from_hash_uniform ( | |||||
* inverse sampling, this function succeeds or fails | * inverse sampling, this function succeeds or fails | ||||
* independently for different "which" values. | * independently for different "which" values. | ||||
* | * | ||||
* This function isn't guaranteed to find every possible | |||||
* preimage, but it finds all except a small finite number. | |||||
* In particular, when the number of bits in the modulus isn't | |||||
* a multiple of 8 (i.e. for curve25519), it sets the high bits | |||||
* independently, which enables the generated data to be uniform. | |||||
* But it doesn't add p, so you'll never get exactly p from this | |||||
* function. This might change in the future, especially if | |||||
* we ever support eg Brainpool curves, where this could cause | |||||
* real nonuniformity. | |||||
* | |||||
* @param [out] recovered_hash Encoded data. | * @param [out] recovered_hash Encoded data. | ||||
* @param [in] pt The point to encode. | * @param [in] pt The point to encode. | ||||
* @param [in] which A value determining which inverse point | * @param [in] which A value determining which inverse point | ||||
@@ -71,7 +71,7 @@ mask_t gf_lobit (const gf x); | |||||
mask_t gf_hibit (const gf x); | mask_t gf_hibit (const gf x); | ||||
void gf_serialize (uint8_t *serial, const gf x,int with_highbit); | void gf_serialize (uint8_t *serial, const gf x,int with_highbit); | ||||
mask_t gf_deserialize (gf x, const uint8_t serial[SER_BYTES],int with_highbit); | |||||
mask_t gf_deserialize (gf x, const uint8_t serial[SER_BYTES],int with_hibit,uint8_t hi_nmask); | |||||
#ifdef __cplusplus | #ifdef __cplusplus | ||||
@@ -50,13 +50,16 @@ mask_t gf_lobit(const gf x) { | |||||
} | } | ||||
/** Deserialize from wire format; return -1 on success and 0 on failure. */ | /** 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) { | |||||
mask_t gf_deserialize (gf x, const uint8_t serial[SER_BYTES], int with_hibit, uint8_t hi_nmask) { | |||||
unsigned int j=0, fill=0; | unsigned int j=0, fill=0; | ||||
dword_t buffer = 0; | dword_t buffer = 0; | ||||
dsword_t scarry = 0; | dsword_t scarry = 0; | ||||
const unsigned nbytes = with_hibit ? X_SER_BYTES : SER_BYTES; | |||||
UNROLL for (unsigned int i=0; i<NLIMBS; i++) { | UNROLL for (unsigned int i=0; i<NLIMBS; i++) { | ||||
UNROLL while (fill < LIMB_PLACE_VALUE(LIMBPERM(i)) && j < (with_hibit ? X_SER_BYTES : SER_BYTES)) { | |||||
buffer |= ((dword_t)serial[j]) << fill; | |||||
UNROLL while (fill < LIMB_PLACE_VALUE(LIMBPERM(i)) && j < nbytes) { | |||||
uint8_t sj = serial[j]; | |||||
if (j==nbytes-1) sj &= ~hi_nmask; | |||||
buffer |= ((dword_t)sj) << fill; | |||||
fill += 8; | fill += 8; | ||||
j++; | j++; | ||||
} | } | ||||
@@ -0,0 +1,290 @@ | |||||
template <typename Group> struct base_multiples; | |||||
/* Examples for multiples of base point */ | |||||
template <> struct base_multiples<IsoEd25519> { | |||||
static const int count = 16; | |||||
static const uint8_t values[count][IsoEd25519::Point::SER_BYTES]; | |||||
}; | |||||
const uint8_t base_multiples<IsoEd25519>::values | |||||
[base_multiples<IsoEd25519>::count][IsoEd25519::Point::SER_BYTES] = { | |||||
/* Copy-pasted from Dalek, thanks Isis Lovecruft and Henry de Valence */ | |||||
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, | |||||
{226, 242, 174, 10, 106, 188, 78, 113, 168, 132, 169, 97, 197, 0, 81, 95, 88, 227, 11, 106, 165, 130, 221, 141, 182, 166, 89, 69, 224, 141, 45, 118}, | |||||
{106, 73, 50, 16, 247, 73, 156, 209, 127, 236, 181, 16, 174, 12, 234, 35, 161, 16, 232, 213, 185, 1, 248, 172, 173, 211, 9, 92, 115, 163, 185, 25}, | |||||
{148, 116, 31, 93, 93, 82, 117, 94, 206, 79, 35, 240, 68, 238, 39, 213, 209, 234, 30, 43, 209, 150, 180, 98, 22, 107, 22, 21, 42, 157, 2, 89}, | |||||
{218, 128, 134, 39, 115, 53, 139, 70, 111, 250, 223, 224, 179, 41, 58, 179, 217, 253, 83, 197, 234, 108, 149, 83, 88, 245, 104, 50, 45, 175, 106, 87}, | |||||
{232, 130, 177, 49, 1, 107, 82, 193, 211, 51, 112, 128, 24, 124, 247, 104, 66, 62, 252, 203, 181, 23, 187, 73, 90, 184, 18, 196, 22, 15, 244, 78}, | |||||
{246, 71, 70, 211, 201, 43, 19, 5, 14, 216, 216, 2, 54, 167, 240, 0, 124, 59, 63, 150, 47, 91, 167, 147, 209, 154, 96, 30, 187, 29, 244, 3}, | |||||
{68, 245, 53, 32, 146, 110, 200, 31, 189, 90, 56, 120, 69, 190, 183, 223, 133, 169, 106, 36, 236, 225, 135, 56, 189, 207, 166, 167, 130, 42, 23, 109}, | |||||
{144, 50, 147, 216, 242, 40, 126, 190, 16, 226, 55, 77, 193, 165, 62, 11, 200, 135, 229, 146, 105, 159, 2, 208, 119, 213, 38, 60, 221, 85, 96, 28}, | |||||
{2, 98, 42, 206, 143, 115, 3, 163, 28, 175, 198, 63, 143, 196, 143, 220, 22, 225, 200, 200, 210, 52, 178, 240, 214, 104, 82, 130, 169, 7, 96, 49}, | |||||
{32, 112, 111, 215, 136, 178, 114, 10, 30, 210, 165, 218, 212, 149, 43, 1, 244, 19, 188, 240, 231, 86, 77, 232, 205, 200, 22, 104, 158, 45, 185, 95}, | |||||
{188, 232, 63, 139, 165, 221, 47, 165, 114, 134, 76, 36, 186, 24, 16, 249, 82, 43, 198, 0, 74, 254, 149, 135, 122, 199, 50, 65, 202, 253, 171, 66}, | |||||
{228, 84, 158, 225, 107, 154, 160, 48, 153, 202, 32, 140, 103, 173, 175, 202, 250, 76, 63, 62, 78, 83, 3, 222, 96, 38, 227, 202, 143, 248, 68, 96}, | |||||
{170, 82, 224, 0, 223, 46, 22, 245, 95, 177, 3, 47, 195, 59, 196, 39, 66, 218, 214, 189, 90, 143, 192, 190, 1, 103, 67, 108, 89, 72, 80, 31}, | |||||
{70, 55, 107, 128, 244, 9, 178, 157, 194, 181, 246, 240, 197, 37, 145, 153, 8, 150, 229, 113, 111, 65, 71, 124, 211, 0, 133, 171, 127, 16, 48, 30}, | |||||
{224, 196, 24, 247, 200, 217, 196, 205, 215, 57, 91, 147, 234, 18, 79, 58, 217, 144, 33, 187, 104, 29, 252, 51, 2, 169, 217, 154, 46, 83, 230, 78} | |||||
}; | |||||
template <> struct base_multiples<Ed448Goldilocks> { | |||||
static const int count = 16; | |||||
static const uint8_t values[count][Ed448Goldilocks::Point::SER_BYTES]; | |||||
}; | |||||
const uint8_t base_multiples<Ed448Goldilocks>::values[][Ed448Goldilocks::Point::SER_BYTES] = { | |||||
/* Computed using SAGE script */ | |||||
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, | |||||
{0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66, | |||||
0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66, | |||||
0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33, | |||||
0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33}, | |||||
{0xc8,0x98,0xeb,0x4f,0x87,0xf9,0x7c,0x56,0x4c,0x6f,0xd6,0x1f,0xc7,0xe4, | |||||
0x96,0x89,0x31,0x4a,0x1f,0x81,0x8e,0xc8,0x5e,0xeb,0x3b,0xd5,0x51,0x4a, | |||||
0xc8,0x16,0xd3,0x87,0x78,0xf6,0x9e,0xf3,0x47,0xa8,0x9f,0xca,0x81,0x7e, | |||||
0x66,0xde,0xfd,0xed,0xce,0x17,0x8c,0x7c,0xc7,0x09,0xb2,0x11,0x6e,0x75}, | |||||
{0xa0,0xc0,0x9b,0xf2,0xba,0x72,0x08,0xfd,0xa0,0xf4,0xbf,0xe3,0xd0,0xf5, | |||||
0xb2,0x9a,0x54,0x30,0x12,0x30,0x6d,0x43,0x83,0x1b,0x5a,0xdc,0x6f,0xe7, | |||||
0xf8,0x59,0x6f,0xa3,0x08,0x76,0x3d,0xb1,0x54,0x68,0x32,0x3b,0x11,0xcf, | |||||
0x6e,0x4a,0xeb,0x8c,0x18,0xfe,0x44,0x67,0x8f,0x44,0x54,0x5a,0x69,0xbc}, | |||||
{0xb4,0x6f,0x18,0x36,0xaa,0x28,0x7c,0x0a,0x5a,0x56,0x53,0xf0,0xec,0x5e, | |||||
0xf9,0xe9,0x03,0xf4,0x36,0xe2,0x1c,0x15,0x70,0xc2,0x9a,0xd9,0xe5,0xf5, | |||||
0x96,0xda,0x97,0xee,0xaf,0x17,0x15,0x0a,0xe3,0x0b,0xcb,0x31,0x74,0xd0, | |||||
0x4b,0xc2,0xd7,0x12,0xc8,0xc7,0x78,0x9d,0x7c,0xb4,0xfd,0xa1,0x38,0xf4}, | |||||
{0x1c,0x5b,0xbe,0xcf,0x47,0x41,0xdf,0xaa,0xe7,0x9d,0xb7,0x2d,0xfa,0xce, | |||||
0x00,0xea,0xaa,0xc5,0x02,0xc2,0x06,0x09,0x34,0xb6,0xea,0xae,0xca,0x6a, | |||||
0x20,0xbd,0x3d,0xa9,0xe0,0xbe,0x87,0x77,0xf7,0xd0,0x20,0x33,0xd1,0xb1, | |||||
0x58,0x84,0x23,0x22,0x81,0xa4,0x1f,0xc7,0xf8,0x0e,0xed,0x04,0xaf,0x5e}, | |||||
{0x86,0xff,0x01,0x82,0xd4,0x0f,0x7f,0x9e,0xdb,0x78,0x62,0x51,0x58,0x21, | |||||
0xbd,0x67,0xbf,0xd6,0x16,0x5a,0x3c,0x44,0xde,0x95,0xd7,0xdf,0x79,0xb8, | |||||
0x77,0x9c,0xcf,0x64,0x60,0xe3,0xc6,0x8b,0x70,0xc1,0x6a,0xaa,0x28,0x0f, | |||||
0x2d,0x7b,0x3f,0x22,0xd7,0x45,0xb9,0x7a,0x89,0x90,0x6c,0xfc,0x47,0x6c}, | |||||
{0x50,0x2b,0xcb,0x68,0x42,0xeb,0x06,0xf0,0xe4,0x90,0x32,0xba,0xe8,0x7c, | |||||
0x55,0x4c,0x03,0x1d,0x6d,0x4d,0x2d,0x76,0x94,0xef,0xbf,0x9c,0x46,0x8d, | |||||
0x48,0x22,0x0c,0x50,0xf8,0xca,0x28,0x84,0x33,0x64,0xd7,0x0c,0xee,0x92, | |||||
0xd6,0xfe,0x24,0x6e,0x61,0x44,0x8f,0x9d,0xb9,0x80,0x8b,0x3b,0x24,0x08}, | |||||
{0x0c,0x98,0x10,0xf1,0xe2,0xeb,0xd3,0x89,0xca,0xa7,0x89,0x37,0x4d,0x78, | |||||
0x00,0x79,0x74,0xef,0x4d,0x17,0x22,0x73,0x16,0xf4,0x0e,0x57,0x8b,0x33, | |||||
0x68,0x27,0xda,0x3f,0x6b,0x48,0x2a,0x47,0x94,0xeb,0x6a,0x39,0x75,0xb9, | |||||
0x71,0xb5,0xe1,0x38,0x8f,0x52,0xe9,0x1e,0xa2,0xf1,0xbc,0xb0,0xf9,0x12}, | |||||
{0x20,0xd4,0x1d,0x85,0xa1,0x8d,0x56,0x57,0xa2,0x96,0x40,0x32,0x15,0x63, | |||||
0xbb,0xd0,0x4c,0x2f,0xfb,0xd0,0xa3,0x7a,0x7b,0xa4,0x3a,0x4f,0x7d,0x26, | |||||
0x3c,0xe2,0x6f,0xaf,0x4e,0x1f,0x74,0xf9,0xf4,0xb5,0x90,0xc6,0x92,0x29, | |||||
0xae,0x57,0x1f,0xe3,0x7f,0xa6,0x39,0xb5,0xb8,0xeb,0x48,0xbd,0x9a,0x55}, | |||||
{0xe6,0xb4,0xb8,0xf4,0x08,0xc7,0x01,0x0d,0x06,0x01,0xe7,0xed,0xa0,0xc3, | |||||
0x09,0xa1,0xa4,0x27,0x20,0xd6,0xd0,0x6b,0x57,0x59,0xfd,0xc4,0xe1,0xef, | |||||
0xe2,0x2d,0x07,0x6d,0x6c,0x44,0xd4,0x2f,0x50,0x8d,0x67,0xbe,0x46,0x29, | |||||
0x14,0xd2,0x8b,0x8e,0xdc,0xe3,0x2e,0x70,0x94,0x30,0x51,0x64,0xaf,0x17}, | |||||
{0xbe,0x88,0xbb,0xb8,0x6c,0x59,0xc1,0x3d,0x8e,0x9d,0x09,0xab,0x98,0x10, | |||||
0x5f,0x69,0xc2,0xd1,0xdd,0x13,0x4d,0xbc,0xd3,0xb0,0x86,0x36,0x58,0xf5, | |||||
0x31,0x59,0xdb,0x64,0xc0,0xe1,0x39,0xd1,0x80,0xf3,0xc8,0x9b,0x82,0x96, | |||||
0xd0,0xae,0x32,0x44,0x19,0xc0,0x6f,0xa8,0x7f,0xc7,0xda,0xaf,0x34,0xc1}, | |||||
{0xa4,0x56,0xf9,0x36,0x97,0x69,0xe8,0xf0,0x89,0x02,0x12,0x4a,0x03,0x14, | |||||
0xc7,0xa0,0x65,0x37,0xa0,0x6e,0x32,0x41,0x1f,0x4f,0x93,0x41,0x59,0x50, | |||||
0xa1,0x7b,0xad,0xfa,0x74,0x42,0xb6,0x21,0x74,0x34,0xa3,0xa0,0x5e,0xf4, | |||||
0x5b,0xe5,0xf1,0x0b,0xd7,0xb2,0xef,0x8e,0xa0,0x0c,0x43,0x1e,0xde,0xc5}, | |||||
{0x18,0x6e,0x45,0x2c,0x44,0x66,0xaa,0x43,0x83,0xb4,0xc0,0x02,0x10,0xd5, | |||||
0x2e,0x79,0x22,0xdb,0xf9,0x77,0x1e,0x8b,0x47,0xe2,0x29,0xa9,0xb7,0xb7, | |||||
0x3c,0x8d,0x10,0xfd,0x7e,0xf0,0xb6,0xe4,0x15,0x30,0xf9,0x1f,0x24,0xa3, | |||||
0xed,0x9a,0xb7,0x1f,0xa3,0x8b,0x98,0xb2,0xfe,0x47,0x46,0xd5,0x1d,0x68}, | |||||
{0x4a,0xe7,0xfd,0xca,0xe9,0x45,0x3f,0x19,0x5a,0x8e,0xad,0x5c,0xbe,0x1a, | |||||
0x7b,0x96,0x99,0x67,0x3b,0x52,0xc4,0x0a,0xb2,0x79,0x27,0x46,0x48,0x87, | |||||
0xbe,0x53,0x23,0x7f,0x7f,0x3a,0x21,0xb9,0x38,0xd4,0x0d,0x0e,0xc9,0xe1, | |||||
0x5b,0x1d,0x51,0x30,0xb1,0x3f,0xfe,0xd8,0x13,0x73,0xa5,0x3e,0x2b,0x43}, | |||||
{0x84,0x19,0x81,0xc3,0xbf,0xee,0xc3,0xf6,0x0c,0xfe,0xca,0x75,0xd9,0xd8, | |||||
0xdc,0x17,0xf4,0x6c,0xf0,0x10,0x6f,0x24,0x22,0xb5,0x9a,0xec,0x58,0x0a, | |||||
0x58,0xf3,0x42,0x27,0x2e,0x3a,0x5e,0x57,0x5a,0x05,0x5d,0xdb,0x05,0x13, | |||||
0x90,0xc5,0x4c,0x24,0xc6,0xec,0xb1,0xe0,0xac,0xeb,0x07,0x5f,0x60,0x56}, | |||||
}; | |||||
template <typename Group> struct elligator_examples; | |||||
/* Examples for Elligator */ | |||||
template <> struct elligator_examples<IsoEd25519> { | |||||
static const int count = 16; | |||||
static const uint8_t inputs[count][IsoEd25519::Point::HASH_BYTES]; | |||||
static const uint8_t outputs[count][IsoEd25519::Point::SER_BYTES]; | |||||
}; | |||||
const uint8_t elligator_examples<IsoEd25519>::inputs | |||||
[elligator_examples<IsoEd25519>::count][IsoEd25519::Point::HASH_BYTES] = { | |||||
/* Copy-pasted from Dalek, thanks Isis Lovecruft and Henry de Valence */ | |||||
{184, 249, 135, 49, 253, 123, 89, 113, 67, 160, 6, 239, 7, 105, 211, 41, 192, 249, 185, 57, 9, 102, 70, 198, 15, 127, 7, 26, 160, 102, 134, 71}, | |||||
{229, 14, 241, 227, 75, 9, 118, 60, 128, 153, 226, 21, 183, 217, 91, 136, 98, 0, 231, 156, 124, 77, 82, 139, 142, 134, 164, 169, 169, 62, 250, 52}, | |||||
{115, 109, 36, 220, 180, 223, 99, 6, 204, 169, 19, 29, 169, 68, 84, 23, 21, 109, 189, 149, 127, 205, 91, 102, 172, 35, 112, 35, 134, 69, 186, 34}, | |||||
{16, 49, 96, 107, 171, 199, 164, 9, 129, 16, 64, 62, 241, 63, 132, 173, 209, 160, 112, 215, 105, 50, 157, 81, 253, 105, 1, 154, 229, 25, 120, 83}, | |||||
{156, 131, 161, 162, 236, 251, 5, 187, 167, 171, 17, 178, 148, 210, 90, 207, 86, 21, 79, 161, 167, 215, 234, 1, 136, 242, 182, 248, 38, 85, 79, 86}, | |||||
{251, 177, 124, 54, 18, 101, 75, 235, 245, 186, 19, 46, 133, 157, 229, 64, 10, 136, 181, 185, 78, 144, 254, 167, 137, 49, 107, 10, 61, 10, 21, 25}, | |||||
{232, 193, 20, 68, 240, 77, 186, 77, 183, 40, 44, 86, 150, 31, 198, 212, 76, 81, 3, 217, 197, 8, 126, 128, 126, 152, 164, 208, 153, 44, 189, 77}, | |||||
{173, 229, 149, 177, 37, 230, 30, 69, 61, 56, 172, 190, 219, 115, 167, 194, 71, 134, 59, 75, 28, 244, 118, 26, 162, 97, 64, 16, 15, 189, 30, 64}, | |||||
{106, 71, 61, 107, 250, 117, 42, 151, 91, 202, 212, 100, 52, 188, 190, 21, 125, 218, 31, 18, 253, 241, 160, 133, 57, 242, 3, 164, 189, 68, 111, 75}, | |||||
{112, 204, 182, 90, 220, 198, 120, 73, 173, 107, 193, 17, 227, 40, 162, 36, 150, 141, 235, 55, 172, 183, 12, 39, 194, 136, 43, 153, 244, 118, 91, 89}, | |||||
{111, 24, 203, 123, 254, 189, 11, 162, 51, 196, 163, 136, 204, 143, 10, 222, 33, 112, 81, 205, 34, 35, 8, 66, 90, 6, 164, 58, 170, 177, 34, 25}, | |||||
{225, 183, 30, 52, 236, 82, 6, 183, 109, 25, 227, 181, 25, 82, 41, 193, 80, 77, 161, 80, 242, 203, 79, 204, 136, 245, 131, 110, 237, 106, 3, 58}, | |||||
{207, 246, 38, 56, 30, 86, 176, 90, 27, 200, 61, 42, 221, 27, 56, 210, 79, 178, 189, 120, 68, 193, 120, 167, 77, 185, 53, 197, 124, 128, 191, 126}, | |||||
{1, 136, 215, 80, 240, 46, 63, 147, 16, 244, 230, 207, 82, 189, 74, 50, 106, 169, 138, 86, 30, 131, 214, 202, 166, 125, 251, 228, 98, 24, 36, 21}, | |||||
{210, 207, 228, 56, 155, 116, 207, 54, 84, 195, 251, 215, 249, 199, 116, 75, 109, 239, 196, 251, 194, 246, 252, 228, 70, 146, 156, 35, 25, 39, 241, 4}, | |||||
{34, 116, 123, 9, 8, 40, 93, 189, 9, 103, 57, 103, 66, 227, 3, 2, 157, 107, 134, 219, 202, 74, 230, 154, 78, 107, 219, 195, 214, 14, 84, 80} | |||||
}; | |||||
const uint8_t elligator_examples<IsoEd25519>::outputs | |||||
[elligator_examples<IsoEd25519>::count][IsoEd25519::Point::SER_BYTES] = { | |||||
/* Copy-pasted from Dalek, thanks Isis Lovecruft and Henry de Valence */ | |||||
{176, 157, 237, 97, 66, 29, 140, 166, 168, 94, 26, 157, 212, 216, 229, 160, 195, 246, 232, 239, 169, 112, 63, 193, 64, 32, 152, 69, 11, 190, 246, 86}, | |||||
{234, 141, 77, 203, 181, 225, 250, 74, 171, 62, 15, 118, 78, 212, 150, 19, 131, 14, 188, 238, 194, 244, 141, 138, 166, 162, 83, 122, 228, 201, 19, 26}, | |||||
{232, 231, 51, 92, 5, 168, 80, 36, 173, 179, 104, 68, 186, 149, 68, 40, 140, 170, 27, 103, 99, 140, 21, 242, 43, 62, 250, 134, 208, 255, 61, 89}, | |||||
{208, 120, 140, 129, 177, 179, 237, 159, 252, 160, 28, 13, 206, 5, 211, 241, 192, 218, 1, 97, 130, 241, 20, 169, 119, 46, 246, 29, 79, 80, 77, 84}, | |||||
{202, 11, 236, 145, 58, 12, 181, 157, 209, 6, 213, 88, 75, 147, 11, 119, 191, 139, 47, 142, 33, 36, 153, 193, 223, 183, 178, 8, 205, 120, 248, 110}, | |||||
{26, 66, 231, 67, 203, 175, 116, 130, 32, 136, 62, 253, 215, 46, 5, 214, 166, 248, 108, 237, 216, 71, 244, 173, 72, 133, 82, 6, 143, 240, 104, 41}, | |||||
{40, 157, 102, 96, 201, 223, 200, 197, 150, 181, 106, 83, 103, 126, 143, 33, 145, 230, 78, 6, 171, 146, 210, 143, 112, 5, 245, 23, 183, 138, 18, 120}, | |||||
{220, 37, 27, 203, 239, 196, 176, 131, 37, 66, 188, 243, 185, 250, 113, 23, 167, 211, 154, 243, 168, 215, 54, 171, 159, 36, 195, 81, 13, 150, 43, 43}, | |||||
{232, 121, 176, 222, 183, 196, 159, 90, 238, 193, 105, 52, 101, 167, 244, 170, 121, 114, 196, 6, 67, 152, 80, 185, 221, 7, 83, 105, 176, 208, 224, 121}, | |||||
{226, 181, 183, 52, 241, 163, 61, 179, 221, 207, 220, 73, 245, 242, 25, 236, 67, 84, 179, 222, 167, 62, 167, 182, 32, 9, 92, 30, 165, 127, 204, 68}, | |||||
{226, 119, 16, 242, 200, 139, 240, 87, 11, 222, 92, 146, 156, 243, 46, 119, 65, 59, 1, 248, 92, 183, 50, 175, 87, 40, 206, 53, 208, 220, 148, 13}, | |||||
{70, 240, 79, 112, 54, 157, 228, 146, 74, 122, 216, 88, 232, 62, 158, 13, 14, 146, 115, 117, 176, 222, 90, 225, 244, 23, 94, 190, 150, 7, 136, 96}, | |||||
{22, 71, 241, 103, 45, 193, 195, 144, 183, 101, 154, 50, 39, 68, 49, 110, 51, 44, 62, 0, 229, 113, 72, 81, 168, 29, 73, 106, 102, 40, 132, 24}, | |||||
{196, 133, 107, 11, 130, 105, 74, 33, 204, 171, 133, 221, 174, 193, 241, 36, 38, 179, 196, 107, 219, 185, 181, 253, 228, 47, 155, 42, 231, 73, 41, 78}, | |||||
{58, 255, 225, 197, 115, 208, 160, 143, 39, 197, 82, 69, 143, 235, 92, 170, 74, 40, 57, 11, 171, 227, 26, 185, 217, 207, 90, 185, 197, 190, 35, 60}, | |||||
{88, 43, 92, 118, 223, 136, 105, 145, 238, 186, 115, 8, 214, 112, 153, 253, 38, 108, 205, 230, 157, 130, 11, 66, 101, 85, 253, 110, 110, 14, 148, 112} | |||||
}; | |||||
template <> struct elligator_examples<Ed448Goldilocks> { | |||||
static const int count = 16; | |||||
static const uint8_t inputs[count] [Ed448Goldilocks::Point::HASH_BYTES]; | |||||
static const uint8_t outputs[count][Ed448Goldilocks::Point::SER_BYTES]; | |||||
}; | |||||
const uint8_t elligator_examples<Ed448Goldilocks>::inputs | |||||
[elligator_examples<Ed448Goldilocks>::count][Ed448Goldilocks::Point::HASH_BYTES] = { | |||||
/* Computed using SAGE script */ | |||||
{0x2d,0x86,0xa1,0x42,0x33,0x8d,0xe2,0x74,0x80,0x63,0x54,0xc4,0x3e,0x29, | |||||
0xaf,0x70,0x5a,0xa9,0xa1,0x89,0x3e,0x6f,0xd3,0xee,0x2e,0x95,0x22,0xc9, | |||||
0xce,0xb4,0x0b,0xe2,0x44,0x1b,0xac,0x8a,0x4f,0x78,0x06,0x43,0x43,0x89, | |||||
0x25,0xd7,0x91,0x46,0x98,0x8b,0x1c,0xa1,0x12,0xda,0x71,0x4d,0xe9,0x2a}, | |||||
{0xee,0x79,0x8e,0xe0,0x86,0xde,0x1f,0x5a,0x57,0xa2,0xca,0x28,0xdb,0x84, | |||||
0x51,0xd3,0x06,0xcb,0xb9,0xee,0x22,0x27,0xc4,0x97,0xf4,0xa6,0x7a,0x69, | |||||
0x06,0xd7,0xeb,0xbc,0x7a,0xa8,0x5f,0x94,0x6f,0xf9,0xdf,0xf7,0x9e,0x1b, | |||||
0x7e,0x88,0xd9,0x7e,0x3a,0xd4,0xa4,0xe0,0xa1,0x20,0x32,0x32,0x3a,0xb7}, | |||||
{0x2e,0x1b,0x10,0x93,0xb3,0x47,0x75,0x97,0x66,0x46,0x49,0xb0,0xb7,0xc6, | |||||
0xac,0x1f,0x9b,0xb7,0x5d,0xd9,0xfd,0xb5,0x08,0x96,0xcb,0xaa,0x06,0x15, | |||||
0xc5,0x25,0x43,0x6d,0x62,0x54,0xec,0x13,0xd9,0x19,0x0e,0xa4,0x25,0xe5, | |||||
0xba,0x80,0xee,0xfc,0x25,0x9b,0xcd,0x1e,0x2a,0x5a,0xf0,0x0e,0x8a,0x9e}, | |||||
{0x8a,0x59,0x3f,0xb9,0x9c,0x04,0xb5,0xc0,0x50,0xc9,0x0d,0xc7,0x90,0x93, | |||||
0x65,0x89,0x41,0x5b,0x9b,0xd6,0x78,0x3d,0x9e,0x92,0x5e,0x63,0x4b,0x87, | |||||
0x81,0x4f,0xd1,0xda,0x2a,0x36,0xcd,0x80,0x45,0xbb,0x6c,0x36,0xd6,0x7e, | |||||
0xb8,0x2c,0x17,0x84,0x01,0x35,0x6b,0xe8,0x40,0x42,0x9c,0x78,0x0c,0x70}, | |||||
{0x80,0xb2,0x5f,0xfc,0xfb,0xd8,0x0b,0x83,0xa7,0x86,0xc1,0x07,0x6d,0x3a, | |||||
0x23,0xd8,0x50,0x49,0xfd,0x4c,0x51,0x91,0x92,0xa7,0xd1,0xe8,0x52,0x38, | |||||
0x93,0x6e,0x1c,0x09,0x22,0x15,0xc8,0x0b,0x2d,0x9d,0xd1,0x3d,0x88,0x49, | |||||
0x82,0x9d,0x7f,0x6a,0x38,0x2a,0x5a,0xce,0x05,0x16,0x6e,0x4b,0x08,0x5b}, | |||||
{0xc1,0x15,0x77,0x32,0xc6,0xd2,0xba,0xf4,0x48,0x88,0x7a,0x1c,0x4a,0x2a, | |||||
0x90,0xb4,0x0b,0x07,0x84,0x0f,0xf9,0x62,0xda,0x1f,0x71,0x91,0x05,0x8c, | |||||
0xb9,0x37,0xdf,0xe5,0xce,0xb2,0x5e,0x34,0x4e,0x33,0xfc,0x9d,0xf0,0xc6, | |||||
0x8e,0x99,0xcb,0x35,0x07,0xaa,0xfe,0xb9,0xa6,0xc9,0x66,0x75,0xbb,0xf1}, | |||||
{0xa5,0x50,0x98,0x77,0xa2,0xbb,0xe8,0x0d,0x07,0xc2,0x3b,0x26,0x46,0x73, | |||||
0x85,0xf9,0x7c,0x16,0xbe,0x48,0x82,0x40,0x0f,0x31,0x80,0x0e,0x15,0xdd, | |||||
0x43,0x9e,0x52,0x34,0x43,0xcf,0x94,0x68,0x88,0x59,0xb7,0x62,0x64,0x3d, | |||||
0x64,0xbe,0xda,0x91,0xf7,0x50,0xac,0x6e,0x00,0x16,0xaf,0xaf,0xd3,0x09}, | |||||
{0xbd,0x9b,0xe4,0xe9,0x20,0x93,0xcf,0x24,0x40,0x79,0xa6,0xff,0x63,0xad, | |||||
0x01,0xe1,0x9c,0xae,0x6d,0x80,0x65,0xed,0x83,0xbb,0x05,0x2e,0x14,0xe2, | |||||
0x39,0x04,0x8e,0x3b,0x8a,0xeb,0x90,0xe9,0x35,0xbe,0xbe,0x29,0x24,0x1e, | |||||
0x34,0x4d,0xc9,0x0d,0x31,0xd0,0x4e,0x99,0xd6,0xa1,0xad,0xca,0x8b,0x38}, | |||||
{0xc3,0x5e,0xfb,0xe1,0xab,0xee,0x01,0xf9,0xe4,0x5e,0x03,0x84,0xfa,0x2f, | |||||
0x94,0x3a,0x6e,0x8f,0x56,0x11,0x86,0x4b,0x55,0x5f,0x18,0x6c,0x7c,0xf8, | |||||
0xe3,0x4c,0xc6,0x27,0xcb,0xa5,0x85,0xfb,0xcf,0xc4,0x26,0x84,0xeb,0x30, | |||||
0xbe,0x62,0x23,0x5c,0x1e,0x10,0xe8,0x82,0xca,0x42,0x19,0xa8,0xc4,0x85}, | |||||
{0x3c,0x30,0x0f,0xed,0xd9,0x86,0x6f,0x6a,0xfa,0xbc,0x14,0x3e,0x1f,0x73, | |||||
0x0a,0xf6,0xea,0xda,0xc0,0x20,0x7e,0x00,0x88,0x88,0xb6,0xeb,0x79,0xa2, | |||||
0xf7,0xe6,0xe6,0x7e,0xd0,0x1e,0x71,0xaf,0x64,0x77,0x7b,0x90,0xbf,0x61, | |||||
0x0a,0x5e,0x36,0xca,0xd0,0xcd,0x88,0xef,0x88,0x3a,0x9b,0x6a,0xb8,0x13}, | |||||
{0x11,0xf8,0x2f,0x21,0xe4,0x61,0x64,0x36,0xe6,0x9e,0xd8,0xe3,0x57,0x03, | |||||
0xcc,0xcd,0x1f,0x65,0xaa,0x75,0xf0,0x7e,0x8a,0xfa,0xa3,0x35,0x29,0xcc, | |||||
0x22,0x58,0xeb,0x2b,0x0f,0xb1,0x82,0x71,0x0f,0xfc,0x67,0xd1,0xe0,0xd0, | |||||
0xde,0x37,0x3d,0x4f,0xd2,0xd5,0xb1,0x7b,0x58,0xb3,0xc7,0xd4,0x73,0x12}, | |||||
{0x3d,0xbd,0xcf,0x91,0xe8,0x35,0xa8,0x30,0xfd,0x8a,0xf9,0xc6,0x9d,0xc1, | |||||
0x30,0x66,0xdf,0x1e,0x24,0x44,0x8b,0x91,0x78,0xa0,0x99,0xbb,0x07,0x57, | |||||
0x3e,0xfe,0xc4,0x8e,0xab,0x2c,0x11,0x9b,0xcb,0xbb,0x82,0x8d,0x20,0xc1, | |||||
0x64,0x7d,0x42,0x31,0xdf,0xeb,0x9b,0xd0,0x86,0xf2,0x6d,0xb7,0x7e,0x71}, | |||||
{0xac,0x8b,0xf3,0x02,0x0a,0x1c,0x73,0x3a,0x59,0x10,0x92,0xb6,0x7a,0x32, | |||||
0x23,0xca,0x2f,0xab,0x64,0x53,0xd2,0x25,0xba,0x83,0x2e,0x34,0xd0,0xc4, | |||||
0xbf,0xca,0x95,0x2b,0xe3,0x2d,0x39,0x76,0xca,0x73,0x8c,0x5a,0xb3,0xdd, | |||||
0xc9,0xc7,0x62,0x70,0x78,0x41,0x83,0x72,0xdb,0x77,0x0f,0x17,0xb5,0x5c}, | |||||
{0xf6,0xc5,0x5d,0x6b,0x46,0x97,0xd6,0xf8,0x3d,0x6e,0xcc,0xc4,0xdb,0x2f, | |||||
0x72,0xf8,0xf2,0xf6,0x7e,0x75,0x24,0xff,0x91,0xd6,0xf6,0xc8,0xa7,0x56, | |||||
0xab,0x03,0x96,0x7a,0x64,0x89,0x42,0x71,0xe7,0x1e,0x71,0xd8,0x95,0x72, | |||||
0x9f,0x06,0x31,0xfd,0x7c,0x0d,0xe1,0xc2,0x73,0xc0,0x90,0x92,0x43,0x23}, | |||||
{0x9b,0x30,0x03,0x76,0xa4,0xb9,0x5e,0xa2,0x02,0x4b,0xdb,0xd9,0x7a,0x96, | |||||
0x93,0xc3,0xf6,0x0a,0xe0,0xbb,0xdb,0xda,0xfc,0x47,0x09,0x27,0x8b,0x65, | |||||
0x34,0xc8,0xa2,0xd5,0xff,0x9b,0xb3,0xd2,0x10,0xd9,0x49,0xd5,0xbf,0x09, | |||||
0x49,0x19,0xb9,0x0d,0x2f,0x0f,0xf9,0x82,0xed,0x92,0x79,0x95,0xdc,0x60}, | |||||
{0x90,0x95,0x7d,0x59,0x78,0x10,0xb2,0x7b,0x84,0x9a,0x69,0x1f,0x5d,0x27, | |||||
0xd5,0x48,0x96,0x3d,0x35,0x4a,0xe9,0xe2,0x9a,0xd5,0x9a,0x23,0x0a,0x15, | |||||
0x5a,0xaa,0x6f,0xe7,0xc5,0x4c,0x82,0xd5,0x08,0x14,0xd8,0xfd,0xcd,0x2d, | |||||
0x3b,0xb1,0xe5,0x53,0xa8,0x41,0xf9,0x71,0xd7,0x24,0xa4,0x64,0x7a,0xba} | |||||
}; | |||||
const uint8_t elligator_examples<Ed448Goldilocks>::outputs | |||||
[elligator_examples<Ed448Goldilocks>::count][Ed448Goldilocks::Point::SER_BYTES] = { | |||||
/* Computed using SAGE script */ | |||||
{0xa6,0x99,0x3b,0x5a,0x6c,0xbb,0x40,0x71,0x6e,0xb2,0xaf,0xa1,0x53,0x05, | |||||
0x27,0x75,0xd2,0x55,0xff,0x2f,0x64,0x4e,0x2f,0x91,0x32,0xb4,0x04,0xfc, | |||||
0x80,0x68,0x08,0x09,0x40,0x43,0xf7,0xa2,0xe4,0x7c,0x0a,0xd9,0x27,0x2f, | |||||
0x53,0x33,0x2d,0x21,0xf4,0x07,0x70,0xd6,0x60,0xa8,0xf1,0xf1,0xed,0x23}, | |||||
{0xde,0x6a,0x92,0x82,0xee,0x9f,0x8f,0xa9,0xb0,0x2c,0xa9,0x5e,0xd4,0xbf, | |||||
0x7f,0x87,0xb7,0x1f,0xc3,0x64,0xbc,0x75,0xd5,0x71,0xf2,0xe9,0xa7,0x07, | |||||
0xf7,0x16,0x66,0xb2,0xdf,0x06,0x55,0xf2,0x00,0x2e,0x1c,0x84,0x23,0x9e, | |||||
0xed,0x70,0xde,0xd8,0xa6,0x92,0xaf,0x39,0x52,0x03,0x38,0xc7,0xc9,0xef}, | |||||
{0x02,0x51,0x0b,0x4c,0x16,0xa7,0x01,0xa1,0x68,0x82,0xb5,0x1e,0xc5,0xd1, | |||||
0x4e,0x25,0x18,0x5b,0x7a,0x8c,0xd3,0x12,0xc3,0xcf,0xc0,0x7c,0x11,0x00, | |||||
0x40,0xd0,0x01,0xad,0x59,0x0a,0xd7,0x2d,0xc3,0x07,0x74,0xd8,0x2b,0x1a, | |||||
0x91,0xb9,0xe3,0x6c,0x42,0x3e,0x93,0x7d,0x26,0x4b,0x2d,0x99,0xd6,0xb6}, | |||||
{0x9c,0x64,0x7b,0x77,0x1c,0x28,0x82,0x64,0xe8,0x0f,0xc8,0x11,0x4c,0x58, | |||||
0xdb,0x46,0xe8,0xf0,0x66,0x6c,0x10,0xd7,0xf5,0x6b,0xa8,0x56,0xae,0x67, | |||||
0x09,0x2a,0xa8,0x8c,0x42,0x16,0x65,0x2e,0x6a,0x12,0x9c,0x1b,0x40,0x90, | |||||
0xca,0xab,0xe3,0x9a,0xfd,0x35,0x2b,0xe4,0xdc,0x40,0x99,0x81,0x9c,0x59}, | |||||
{0x06,0xe9,0x16,0x29,0xce,0x93,0x48,0x6a,0xd3,0xa7,0xe7,0x29,0xf0,0x1c, | |||||
0x4d,0x29,0x4a,0x4b,0xde,0xef,0xaf,0x48,0x32,0x04,0xc1,0x67,0xdf,0xe8, | |||||
0xf0,0xc9,0xd2,0x32,0x50,0x6f,0xa5,0x21,0xf5,0x30,0x0e,0x19,0xa0,0x00, | |||||
0x43,0x24,0x50,0x8b,0x39,0x0a,0x6f,0x25,0x81,0x4f,0xc8,0x68,0x3a,0xa4}, | |||||
{0x68,0x11,0x77,0xb0,0x76,0xc9,0xe5,0x53,0xc7,0xe5,0x7a,0x22,0xe7,0x59, | |||||
0x05,0x96,0xe3,0x48,0x2d,0xe2,0x3f,0x28,0x55,0xa8,0xaf,0x82,0xcc,0x51, | |||||
0x6c,0x52,0xa9,0x37,0x35,0xed,0x3d,0xde,0x91,0xb8,0x21,0x0b,0xad,0x64, | |||||
0xb1,0x7d,0x0c,0x1d,0x7c,0x14,0xcc,0xc1,0x52,0x6c,0xc4,0x14,0x0f,0x11}, | |||||
{0x68,0x05,0x63,0x1c,0x06,0xf6,0xd0,0xb5,0xcc,0xf7,0x1f,0xea,0x2e,0x4c, | |||||
0xdf,0x3e,0xa3,0x10,0x4a,0x44,0xa8,0x21,0x20,0x5a,0x25,0x01,0x4c,0x9a, | |||||
0x17,0xac,0x43,0x33,0xbb,0xf6,0xbb,0x28,0x9b,0x42,0x57,0xcc,0xd7,0xf7, | |||||
0xbb,0x11,0xe5,0xc4,0xdd,0xd8,0x6d,0xa9,0x53,0x19,0xdc,0x47,0x04,0x4d}, | |||||
{0x4c,0x0e,0x89,0x30,0xee,0x39,0xf2,0xa7,0x43,0xd1,0x79,0x74,0x5b,0x4c, | |||||
0x94,0x0f,0xf5,0x8f,0x53,0x99,0x57,0x32,0x31,0x3d,0x7e,0xe7,0x8c,0xa2, | |||||
0xde,0xca,0x42,0xa4,0x8f,0x00,0x40,0xc7,0x9a,0x7e,0xd5,0x47,0x00,0x0b, | |||||
0x20,0x8b,0x95,0x94,0xce,0xc4,0xe3,0xe9,0xdf,0x5c,0x01,0x38,0xb8,0xaa}, | |||||
{0x48,0xc3,0x3a,0x47,0x66,0x05,0xfe,0x0f,0xbb,0x33,0xd3,0x7b,0x67,0x2a, | |||||
0xac,0x14,0xd7,0xc6,0x2b,0x84,0x56,0xd2,0x77,0x60,0x8f,0xc2,0x90,0x6d, | |||||
0x03,0x87,0x1d,0x39,0x59,0xdd,0x4a,0x4c,0xaf,0xab,0xe7,0xc2,0x5b,0x6f, | |||||
0x59,0xc9,0xa9,0xd1,0x7c,0x72,0x4d,0x97,0x55,0x52,0x98,0xc9,0xdf,0x3f}, | |||||
{0x0a,0x0c,0x08,0x9d,0x50,0x5d,0x30,0xd1,0xce,0x91,0xcf,0x36,0x96,0xca, | |||||
0x76,0x10,0xa4,0xe5,0x4a,0xf6,0xf6,0x05,0xcd,0x68,0xff,0x30,0x3c,0xb5, | |||||
0x0b,0xbd,0xba,0xb9,0x90,0x36,0x51,0xed,0x6b,0xdc,0x35,0xf2,0xa8,0x0b, | |||||
0xc7,0x64,0xe3,0x50,0xf8,0xa2,0x3f,0x70,0x03,0xdc,0xd3,0xaa,0x36,0x4f}, | |||||
{0x56,0x21,0x3f,0x80,0x39,0x79,0xce,0x00,0x33,0xa2,0xaa,0x9b,0xcc,0xb8, | |||||
0x51,0x3b,0x82,0x0b,0x15,0x52,0xe8,0x14,0x75,0x86,0x4a,0x48,0xfe,0x60, | |||||
0xe9,0x22,0x73,0xa8,0xf2,0xe5,0x7a,0x77,0xb8,0x1a,0xf1,0x74,0x6e,0x42, | |||||
0xe6,0x47,0xcc,0xc6,0xfa,0x54,0xe0,0xd0,0x7c,0xdd,0x33,0x76,0xc2,0x39}, | |||||
{0xf4,0x8f,0xa8,0x82,0xb5,0x2f,0x79,0xf1,0x8f,0x33,0xac,0xfc,0x23,0x71, | |||||
0x5e,0x8f,0x3e,0x6c,0xcf,0x8e,0xa8,0x7a,0x3f,0xc0,0x71,0xcd,0xb1,0xeb, | |||||
0xd2,0x96,0xf2,0x9e,0x83,0x15,0x78,0xa9,0x21,0x29,0x1d,0x3c,0x80,0x13, | |||||
0x52,0x59,0x45,0x96,0xa1,0x7d,0x27,0x68,0xe2,0xc2,0x86,0x32,0x13,0x7d}, | |||||
{0xaa,0x3b,0x6c,0x33,0xc2,0x7a,0x5a,0x25,0xf9,0x45,0x20,0x30,0x56,0x73, | |||||
0x32,0xe1,0x70,0x5b,0xdf,0x72,0x45,0xef,0xd8,0x98,0x60,0x2c,0xcf,0x79, | |||||
0x93,0x4c,0xa7,0x40,0xed,0x8a,0x12,0xc7,0xee,0x82,0x1e,0x99,0x22,0x52, | |||||
0x1a,0xb8,0xbf,0xca,0x3a,0x1d,0xb9,0x16,0xe4,0x66,0x78,0xc5,0x1f,0x81}, | |||||
{0xba,0x1c,0xfd,0xca,0x84,0x4f,0x16,0x71,0x6a,0x77,0xba,0x74,0x7a,0x1f, | |||||
0x46,0xd2,0x9f,0xfa,0x90,0x3a,0x74,0xe5,0xf2,0x14,0xfb,0xef,0x06,0x67, | |||||
0x67,0x7d,0xcf,0x9b,0xb0,0x2a,0xf7,0xe3,0x4d,0x27,0x02,0xea,0xdb,0xbe, | |||||
0x80,0xeb,0xcf,0x94,0x4c,0x2a,0x54,0x2a,0x98,0x35,0x59,0xd9,0x24,0x8a}, | |||||
{0x50,0xdf,0xb7,0xe7,0x92,0x92,0xf3,0xb0,0x4e,0x0d,0x5c,0x73,0x8a,0xf2, | |||||
0xba,0xc6,0xda,0xdf,0x00,0xe5,0x37,0x7b,0xbf,0xc1,0xe7,0x13,0xe1,0xda, | |||||
0x5f,0xa1,0xa3,0xc2,0xfd,0x4b,0x10,0x81,0x0d,0x99,0xcf,0x8f,0xca,0x91, | |||||
0x37,0x3e,0x47,0x8a,0x84,0xab,0xcd,0x65,0xdf,0xf9,0x27,0x3c,0x13,0xf1}, | |||||
{0xe4,0xe1,0xa4,0x8d,0x1d,0x72,0xe2,0x72,0x3b,0x09,0x09,0xf9,0x7f,0xcd, | |||||
0x57,0x0d,0xdf,0x8c,0xdc,0x47,0xdf,0x6d,0xfa,0x6a,0x8d,0x67,0x45,0x4f, | |||||
0x6b,0x44,0x6d,0xbf,0xf3,0x41,0x1c,0x57,0x1c,0xf0,0x77,0x14,0x06,0xf6, | |||||
0x8c,0xb9,0xa3,0x40,0x34,0x70,0xd6,0x36,0xe5,0xa6,0xce,0x1b,0x84,0xcc} | |||||
}; |
@@ -20,6 +20,8 @@ using namespace decaf; | |||||
static bool passing = true; | static bool passing = true; | ||||
static const long NTESTS = 10000; | static const long NTESTS = 10000; | ||||
#include "ristretto_vectors.inc.cxx" | |||||
class Test { | class Test { | ||||
public: | public: | ||||
bool passing_now; | bool passing_now; | ||||
@@ -219,7 +221,6 @@ static void test_elligator() { | |||||
if (i==4 && elli_patho.size()) b1 = elli_patho; | if (i==4 && elli_patho.size()) b1 = elli_patho; | ||||
len = b1.size(); | len = b1.size(); | ||||
Point s = Point::from_hash(b1), ss=s; | Point s = Point::from_hash(b1), ss=s; | ||||
for (unsigned int j=0; j<(i&3); j++) ss = ss.debugging_torque(); | for (unsigned int j=0; j<(i&3); j++) ss = ss.debugging_torque(); | ||||
@@ -292,6 +293,14 @@ static void test_elligator() { | |||||
Point t(rng); | Point t(rng); | ||||
point_check(test,t,t,t,0,0,t,Point::from_hash(t.steg_encode(rng)),"steg round-trip"); | point_check(test,t,t,t,0,0,t,Point::from_hash(t.steg_encode(rng)),"steg round-trip"); | ||||
FixedArrayBuffer<Point::HASH_BYTES> b3(rng), b4(b3); | |||||
t = Point::from_hash(b3); | |||||
for (unsigned j=0; j<256; j+=2<<((Group::bits()-1)%8)) { | |||||
b4[Point::HASH_BYTES-1] = b3[Point::HASH_BYTES-1] ^ j; | |||||
Point u = Point::from_hash(b4); | |||||
point_check(test,t,t,t,0,0,t,u,"elligator twiddle high bits"); | |||||
} | |||||
} | } | ||||
} | } | ||||
@@ -605,6 +614,23 @@ static void test_convert_eddsa_to_x() { | |||||
} | } | ||||
} | } | ||||
static void test_dalek_vectors() { | |||||
Test test("Test vectors from Dalek"); | |||||
Point p = Point::base(), q; | |||||
for (unsigned i=0; i<base_multiples<Group>::count; i++) { | |||||
if (!decaf_memeq(q.serialize().data(),base_multiples<Group>::values[i],Point::SER_BYTES)) { | |||||
test.fail(); | |||||
printf(" Failed test vector for %d * base point.\n", i); | |||||
} | |||||
q += p; | |||||
} | |||||
for (unsigned i=0; i<elligator_examples<Group>::count; i++) { | |||||
Point r = Point::from_hash(FixedBlock<Point::HASH_BYTES>(elligator_examples<Group>::inputs[i])); | |||||
Point s = Point(FixedBlock<Point::SER_BYTES>(elligator_examples<Group>::outputs[i])); | |||||
point_check(test,r,r,r,0,0,r,s,"elligator test vector"); | |||||
} | |||||
} | |||||
static void run() { | static void run() { | ||||
printf("Testing %s:\n",Group::name()); | printf("Testing %s:\n",Group::name()); | ||||
test_arithmetic(); | test_arithmetic(); | ||||
@@ -614,6 +640,7 @@ static void run() { | |||||
test_convert_eddsa_to_x(); | test_convert_eddsa_to_x(); | ||||
test_cfrg_crypto(); | test_cfrg_crypto(); | ||||
test_cfrg_vectors(); | test_cfrg_vectors(); | ||||
test_dalek_vectors(); | |||||
printf("\n"); | printf("\n"); | ||||
} | } | ||||