utils/split-pieces, pub/ed25519.c: New utility makes field-element constants.
authorMark Wooding <mdw@distorted.org.uk>
Wed, 10 May 2017 20:06:03 +0000 (21:06 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Sun, 14 May 2017 13:58:42 +0000 (14:58 +0100)
It seems to make slightly different (but equivalent) constants from the
machinery in `utils/curve25519.sage'.  Replace the constants in
`pub/ed25519.c' with the new ones.

pub/ed25519.c
utils/split-pieces [new file with mode: 0755]

index e8a8d78..217cbeb 100644 (file)
@@ -90,11 +90,11 @@ const key_fetchdef ed25519_privfetch[] = {
     -14297830,  -7645148,  16144683, -16471763,  27570974,
      -2696100, -26142465,   8378389,  20764389,   8758491
   }, by_pieces[] = {
-    -26843560,  -6710886,  13421773, -13421773,  26843546,
-      6710886, -13421773,  13421773, -26843546,  26843546
+    -26843541,  -6710886,  13421773, -13421773,  26843546,
+      6710886, -13421773,  13421773, -26843546,  -6710886
   }, d_pieces[] = {
-    -10913629,  13857413, -15372611,   6949391,    114729,
-     -8787816,  -6275908,  -3247719, -18696448,  21499316
+    -10913610,  13857413, -15372611,   6949391,    114729,
+     -8787816,  -6275908,  -3247719, -18696448, -12055116
   };
 #endif
 #if F25519_IMPL == 10
@@ -104,13 +104,13 @@ const key_fetchdef ed25519_privfetch[] = {
       75,  236, -308,  421,   92,  439,  -35,  400,  452,
       82,  -40,  160,  441,  -51,  437, -365,  134
   }, by_pieces[] = {
-    -424,  410, -410,  410, -410, -102,  205, -205,  205,
+    -405,  410, -410,  410, -410, -102,  205, -205,  205,
     -205,  205, -410,  410, -410,  410,  102, -205,  205,
-    -205,  205, -205,  410, -410,  410, -410,  410
+    -205,  205, -205,  410, -410,  410, -410, -102
   }, d_pieces[] = {
-     163, -418,  310, -216, -178, -133,  367, -315, -380,
+     182, -418,  310, -216, -178, -133,  367, -315, -380,
     -351, -182, -255,    2,  152, -390, -136,  -52, -383,
-    -412, -398,  -12,  448, -469, -196,   55,  328
+    -412, -398,  -12,  448, -469, -196,   55, -184
   };
 #endif
 
diff --git a/utils/split-pieces b/utils/split-pieces
new file mode 100755 (executable)
index 0000000..473e2fe
--- /dev/null
@@ -0,0 +1,83 @@
+#! /usr/bin/python
+
+from sys import argv, exit
+from itertools import cycle, izip
+import re as RX
+
+def bad_usage():
+  exit('usage: split-pieces { scaf WD | qf WD/N|WD,WD,... } N N ...')
+
+ARGC = 1
+def getarg(must = True):
+  global ARGC
+  if ARGC < len(argv): ARGC += 1; return argv[ARGC - 1]
+  elif must: bad_usage()
+  else: return None
+
+class ScafConvert (object):
+  def __init__(me, piecewd):
+    me.piecewd = piecewd
+    me.fmt = '0x%%0%dx' % ((piecewd + 3)/4)
+    me.mask = (1 << piecewd) - 1
+  @classmethod
+  def parse(cls):
+    return ScafConvert(int(getarg()))
+  def hack(me, n):
+    nn = []
+    while n:
+      nn.append(me.fmt % (n&me.mask))
+      n >>= me.piecewd
+    return nn
+  def unhack(me, nn):
+    return sum(n << i*me.piecewd for i, n in enumerate(nn))
+
+class QfConvert (object):
+  def __init__(me, p, wdseq):
+    me.p = p
+    me.wdseq = wdseq
+  @classmethod
+  def parse(cls):
+    p = eval(getarg())
+    arg = getarg()
+    if '/' in arg:
+      wd, n = map(int, arg.split('/'))
+      seq = [(wd*(i + 1) + n - 1)/n - (wd*i + n - 1)/n for i in xrange(n)]
+    else:
+      seq = map(int, arg.split(','))
+    print ";; piece widths = %r" % seq
+    return QfConvert(p, seq)
+  def hack(me, n):
+    if 2*n >= me.p: n -= p
+    nn = []
+    wds = cycle(me.wdseq)
+    while n:
+      wd = wds.next()
+      lim = 1 << wd; m = lim - 1
+      d = n&m; n >>= wd
+      if d >= lim/2: d -= lim; n += 1
+      nn.append(str(d))
+    return nn
+  def unhack(me, nn):
+    a = o = 0
+    for n, w in izip(nn, cycle(me.wdseq)):
+      a += n << o
+      o += w
+    if a < 0: a += me.p
+    return a
+
+R_split = RX.compile(r',\s*|\s+')
+def spliteval(arg): return map(eval, R_split.split(arg.strip()))
+
+convmap = { 'scaf': ScafConvert,
+            'unscaf': ScafConvert,
+            'qf': QfConvert,
+            'unqf': QfConvert }
+op = getarg()
+cvt = convmap[op].parse()
+if op.startswith('un'): prepare, conv, format = spliteval, cvt.unhack, str
+else: prepare, conv, format = eval, cvt.hack, lambda vv: ', '.join(vv)
+
+while True:
+  val = getarg(must = False)
+  if val is None: break
+  print format(conv(prepare(val)))