]> git.codecow.com Git - Monocypher.git/commitdiff
Elligator script: use x25519_pk test vectors
authorLoup Vaillant <loup@loup-vaillant.fr>
Fri, 21 Feb 2020 22:17:29 +0000 (23:17 +0100)
committerLoup Vaillant <loup@loup-vaillant.fr>
Fri, 21 Feb 2020 22:17:29 +0000 (23:17 +0100)
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

index 17599671c1e195d60b259474be77da00d19ff2f2..925e88b1d648943b6c96587e2d68500f1faaef07 100755 (executable)
@@ -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.