From 14dd101ddf72b85365e040d7feee4e4a8689909d Mon Sep 17 00:00:00 2001 From: Loup Vaillant Date: Fri, 21 Feb 2020 23:17:29 +0100 Subject: [PATCH] Elligator script: use x25519_pk test vectors We're now reading the `x25519_pk.all.vec` generated by Libsodium in `x25519.c`, to make sure scalarmult is correctly implemented in the Python script. While we're at it, we also use them to generate Elligator 2 vectors. Any addition to the X25519 public key generation will automatically benefit Elligator 2 as well TODO: update the makefile to make sure the vectors are generated before we run `elligator.py` --- tests/gen/elligator.py | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/tests/gen/elligator.py b/tests/gen/elligator.py index 1759967..925e88b 100755 --- a/tests/gen/elligator.py +++ b/tests/gen/elligator.py @@ -179,10 +179,11 @@ def from_edwards(point): return (u, v) # entire key generation chain -def full_cycle_check(scalar): +def full_cycle_check(scalar, u): fe(scalar).print() xy = scalarbase(scalar) uv = from_edwards(xy) + if (uv[0] != u): raise ValueError('Test vector failure') uv[0].print() uv[1].print() if can_curve_to_hash(uv): @@ -190,18 +191,37 @@ def full_cycle_check(scalar): print('01:') # Success h.print() # actual value for the hash c = hash_to_curve(h) - if c != uv: - print('Round trip failure') + if c != uv: raise ValueError('Round trip failure') else: print('00:') # Failure print('00:') # dummy value for the hash -private = 0 -for v in range(20): - for i in range(32): - private += (v+i) * 2**(8*i) +# read test vectors: +def read_vector(vector): # vector: little endian hex number + cut = vector[:64] # remove final ':' character + acc = 0 # final sum + pos = 1 # power of 256 + for b in bytes.fromhex(cut): + acc += b * pos + pos *= 256 + return acc + +def read_test_vectors(): + vectors = [] + with open("x25519_pk.all.vec") as f: + lines = [x.strip() for x in f.readlines() if x.strip()] + for i in range(len(lines) // 2): + private = read_vector(lines[i*2 ]) + public = read_vector(lines[i*2 + 1]) + vectors.append((private, fe(public))) + return vectors + +vectors = read_test_vectors() +for v in vectors: + private = v[0] + public = v[1] print('') - full_cycle_check(private) + full_cycle_check(private, public) # fast point addition & scalar multiplication with affine coordinates: # x = X/Z, y = Y/Z. We can multiply Z instead of dividing X and Y. -- 2.47.3