├── a ├── d ├── shape ├── rigid ├── l ├── p ├── x0 ├── x1 ├── y0 ├── y1 ├── run.sh ├── LICENSE ├── README.md ├── .gitignore ├── findCurve.sage └── verify.sage /a: -------------------------------------------------------------------------------- 1 | 168700 2 | -------------------------------------------------------------------------------- /d: -------------------------------------------------------------------------------- 1 | 168696 2 | -------------------------------------------------------------------------------- /shape: -------------------------------------------------------------------------------- 1 | tedwards 2 | -------------------------------------------------------------------------------- /rigid: -------------------------------------------------------------------------------- 1 | fully rigid 2 | -------------------------------------------------------------------------------- /l: -------------------------------------------------------------------------------- 1 | 2736030358979909402780800718157159386076813972158567259200215660948447373041 2 | -------------------------------------------------------------------------------- /p: -------------------------------------------------------------------------------- 1 | 21888242871839275222246405745257275088548364400416034343698204186575808495617 2 | -------------------------------------------------------------------------------- /x0: -------------------------------------------------------------------------------- 1 | 995203441582195749578291179787384436505546430278305826713579947235728471134 2 | -------------------------------------------------------------------------------- /x1: -------------------------------------------------------------------------------- 1 | 5299619240641551281634865583518297030282874472190772894086521144482721001553 2 | -------------------------------------------------------------------------------- /y0: -------------------------------------------------------------------------------- 1 | 5472060717959818805561601436314318772137091100104008585924551046643952123905 2 | -------------------------------------------------------------------------------- /y1: -------------------------------------------------------------------------------- 1 | 16950150798460657717958625567821834550301663161624707787222815936182638968203 2 | -------------------------------------------------------------------------------- /run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | sage verify.sage . 3 | grep -Rn '.' verify-* |grep '^verify-.*:1:' |sed 's/:1:/ = /' 4 | 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017 The Zcash developers 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | baby\_Jubjub supporting evidence 2 | -------------------------- 3 | 4 | This repository contains supporting evidence that the twisted Edwards curve 5 | 168700.x^2 + y^2 = 1 + 168696.x^2.y^2 of rational points over 6 | GF(21888242871839275222246405745257275088548364400416034343698204186575808495617), 7 | also called babyJubJub based upone ["Jubjub"](https://z.cash/technology/jubjub.html), 8 | satisfies the [SafeCurves criteria](https://safecurves.cr.yp.to/index.html). 9 | 10 | The script ``verify.sage`` is based on 11 | [this script from the SafeCurves site](https://safecurves.cr.yp.to/verify.html), 12 | modified by [Daira Hopwood](https://github.com/daira) 13 | 14 | * to support twisted Edwards curves; 15 | * to generate a file 'primes' containing the primes needed for primality proofs, 16 | if it is not already present; 17 | * to change the directory in which Pocklington proof files are generated 18 | (``proof/`` rather than ``../../../proof``), and to create that directory 19 | if it does not exist. 20 | 21 | Prerequisites: 22 | 23 | * apt-get install sagemath 24 | * pip install sortedcontainers 25 | 26 | Run ``sage verify.sage .``, or ``./run.sh`` to also print out the results. 27 | 28 | You can generate the curve by running `sage findCurve.sage 168698` 29 | This is the lowest A=168698 of a montgomary curve that statifies the 30 | critieria defined in [ref7748](https://tools.ietf.org/html/rfc7748) 31 | 32 | Note that the "rigidity" criterion cannot be checked automatically. 33 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | 49 | # Translations 50 | *.mo 51 | *.pot 52 | 53 | # Django stuff: 54 | *.log 55 | local_settings.py 56 | 57 | # Flask stuff: 58 | instance/ 59 | .webassets-cache 60 | 61 | # Scrapy stuff: 62 | .scrapy 63 | 64 | # Sphinx documentation 65 | docs/_build/ 66 | 67 | # PyBuilder 68 | target/ 69 | 70 | # Jupyter Notebook 71 | .ipynb_checkpoints 72 | 73 | # pyenv 74 | .python-version 75 | 76 | # celery beat schedule file 77 | celerybeat-schedule 78 | 79 | # SageMath parsed files 80 | *.sage.py 81 | 82 | # dotenv 83 | .env 84 | 85 | # virtualenv 86 | .venv 87 | venv/ 88 | ENV/ 89 | 90 | # Spyder project settings 91 | .spyderproject 92 | .spyproject 93 | 94 | # Rope project settings 95 | .ropeproject 96 | 97 | # mkdocs documentation 98 | /site 99 | 100 | # mypy 101 | .mypy_cache/ 102 | 103 | -------------------------------------------------------------------------------- /findCurve.sage: -------------------------------------------------------------------------------- 1 | #https://www.heise.de/netze/rfc/rfcs/rfc7748.shtml 2 | import sys 3 | import pdb 4 | 5 | def findCurve(prime, curveCofactor, twistCofactor, _A): 6 | F = GF(prime) 7 | A = _A 8 | while A < _A + 100000: 9 | print A 10 | if (A-2.) % 4 != 0: 11 | A+=1. 12 | continue 13 | try: 14 | E = EllipticCurve(F, [0, A, 0, 1, 0]) 15 | except: 16 | A+=1. 17 | continue 18 | groupOrder = E.order() 19 | if (groupOrder % curveCofactor != 0 or not is_prime(groupOrder // curveCofactor)): 20 | A+=1 21 | continue 22 | 23 | twistOrder = 2*(prime+1)-groupOrder 24 | if (twistOrder % twistCofactor != 0 or 25 | not is_prime(twistOrder // twistCofactor)): 26 | A+=1 27 | continue 28 | return A, E 29 | 30 | def find1Mod4(prime, curveCofactor, twistCofactor, A): 31 | assert((prime % 4) == 1) 32 | return findCurve(prime, curveCofactor, twistCofactor, A) 33 | 34 | def findGenPoint(prime, A, EC, N): 35 | F = GF(prime) 36 | for uInt in range(1, 1e3): 37 | u = F(uInt) 38 | v2 = u^3 + A*u^2 + u 39 | if not v2.is_square(): 40 | continue 41 | v = v2.sqrt() 42 | 43 | point = EC(u, v) 44 | pointOrder = point.order() 45 | if pointOrder == N: 46 | return point 47 | 48 | def mont_to_ted(u, v , r): 49 | x = Mod(u / v, r) 50 | y = Mod((u-1)/(u+1), r) 51 | return(x, y) 52 | 53 | def ted_to_mont(x, y , r): 54 | u = Mod((1 + y )/ ( 1 - y) , r) 55 | v = Mod((1 + y ) / ( (1 - y) * x) , r ) 56 | return(u,v) 57 | 58 | def isOnEd(x,y,r,a,d): 59 | return Mod(Mod(a,r)*(x**2),r) + Mod(y**2 , r) - 1 - Mod(d,r)*(Mod(x**2,r))*(Mod(y**2,r)) == 0 60 | 61 | prime = 21888242871839275222246405745257275088548364400416034343698204186575808495617 62 | Fr = GF(prime) 63 | h = 8 # cofactor 64 | 65 | A = int(sys.argv[1]) 66 | A, EC = find1Mod4(prime, h, 4, A) 67 | 68 | # A = 170214 another candidate 69 | B = 1 70 | a = A + 2 / B 71 | d = A - 2 / B 72 | 73 | print "a " , a , "d " , d , sqrt(d) 74 | # check we have a safe twist 75 | assert(not d.is_square()) 76 | assert(a*d*(a-d)!=0) 77 | 78 | s = factor(EC.order()) 79 | print ("l : " , s) 80 | N = h * s # order of the curve 81 | print (factor(EC.quadratic_twist().order())) 82 | 83 | # get generator point 84 | u_gen, v_gen, w_gen = findGenPoint(prime, A, EC, N) 85 | # find that generator point on the edwards curve 86 | gen_x, gen_y = mont_to_ted(u_gen, v_gen, prime) 87 | # make sure the generator point is on the twisted edwards curve 88 | assert(isOnEd(gen_x, gen_y, prime, a , d)) 89 | # go back to montgomery 90 | u , v = ted_to_mont(gen_x, gen_y, prime) 91 | # confirm we are back where we started from 92 | assert (u == u_gen) 93 | assert (v == v_gen) 94 | 95 | # get base point on montgorery curve by multiplying the generator point by h 96 | base_x , base_y, base_z = h*EC(u_gen, v_gen) 97 | # find the same points on twisted edwards curve 98 | base_x , base_y = mont_to_ted(base_x , base_y, prime) 99 | 100 | # the generator is on the twisted edwards curve 101 | assert(isOnEd(base_x,base_y, prime , a , d)) 102 | 103 | print ("generator :" , gen_x, gen_y) 104 | print ("base :", base_x, base_y) 105 | -------------------------------------------------------------------------------- /verify.sage: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | from errno import ENOENT, EEXIST 4 | from sortedcontainers import SortedSet 5 | 6 | 7 | def readfile(fn): 8 | fd = open(fn,'r') 9 | r = fd.read() 10 | fd.close() 11 | return r 12 | 13 | def writefile(fn,s): 14 | fd = open(fn,'w') 15 | fd.write(s) 16 | fd.close() 17 | 18 | def expand2(n): 19 | s = "" 20 | 21 | while n != 0: 22 | j = 16 23 | while 2**j < abs(n): j += 1 24 | if 2**j - abs(n) > abs(n) - 2**(j-1): j -= 1 25 | 26 | if abs(abs(n) - 2**j) > 2**(j - 10): 27 | if n > 0: 28 | if s != "": s += " + " 29 | s += str(n) 30 | else: 31 | s += " - " + str(-n) 32 | n = 0 33 | elif n > 0: 34 | if s != "": s += " + " 35 | s += "2^" + str(j) 36 | n -= 2**j 37 | else: 38 | s += " - 2^" + str(j) 39 | n += 2**j 40 | 41 | return s 42 | 43 | def requirement(fn,istrue): 44 | writefile(fn,str(istrue) + '\n') 45 | return istrue 46 | 47 | def verify(): 48 | try: 49 | os.mkdir('proof') 50 | except OSError as e: 51 | if e.errno != EEXIST: raise 52 | 53 | try: 54 | s = set(map(Integer, readfile('primes').split())) 55 | except IOError, e: 56 | if e.errno != ENOENT: raise 57 | s = set() 58 | 59 | needtofactor = SortedSet() 60 | V = SortedSet() # distinct verified primes 61 | verify_primes(V, s, needtofactor) 62 | verify_pass(V, needtofactor) 63 | 64 | old = V 65 | needtofactor.update(V) 66 | while len(needtofactor) > len(old): 67 | k = len(needtofactor) - len(old) 68 | sys.stdout.write('Factoring %d integer%s' % (k, '' if k == 1 else 's')) 69 | sys.stdout.flush() 70 | for x in needtofactor: 71 | if x not in old: 72 | for (y, z) in factor(x): 73 | s.add(y) 74 | sys.stdout.write('.') 75 | sys.stdout.flush() 76 | 77 | print('') 78 | 79 | old = needtofactor.copy() 80 | verify_primes(V, s, needtofactor) 81 | 82 | writefile('primes', '\n'.join(map(str, s)) + '\n') 83 | writefile('verify-primes', '\n' + 84 | ''.join(('2\n' if v == 2 else 85 | '%s\n' % (v,v)) for v in V) + 86 | '\n') 87 | 88 | verify_pass(V, needtofactor) 89 | 90 | 91 | def verify_primes(V, s, needtofactor): 92 | for n in sorted(s): 93 | if not n.is_prime() or n in V: continue 94 | needtofactor.add(n-1) 95 | if n == 2: 96 | V.add(n) 97 | continue 98 | for trybase in primes(2,10000): 99 | base = Integers(n)(trybase) 100 | if base^(n-1) != 1: continue 101 | proof = 'Primality proof for n = %s:\n' % n 102 | proof += '

Take b = %s.\n' % base 103 | proof += '

b^(n-1) mod n = 1.\n' 104 | f = factor(1) 105 | for v in reversed(V): 106 | if f.prod()^2 <= n: 107 | if n % v == 1: 108 | u = base^((n-1)/v)-1 109 | if u.is_unit(): 110 | if v == 2: 111 | proof += '

2 is prime.\n' 112 | else: 113 | proof += '

%s is prime.\n' % (v,v) 114 | proof += '
b^((n-1)/%s)-1 mod n = %s, which is a unit, inverse %s.\n' % (v,u,1/u) 115 | f *= factor(v)^(n-1).valuation(v) 116 | if f.prod()^2 <= n: continue 117 | if n % f.prod() != 1: continue 118 | proof += '

(%s) divides n-1.\n' % f 119 | proof += '

(%s)^2 > n.\n' % f 120 | proof += "

n is prime by Pocklington's theorem.\n" 121 | proof += '\n' 122 | writefile('proof/%s.html' % n,proof) 123 | V.add(n) 124 | break 125 | 126 | 127 | def verify_pass(V, needtofactor): 128 | p = Integer(readfile('p')) 129 | k = GF(p) 130 | kz. = k[] 131 | l = Integer(readfile('l')) 132 | x0 = Integer(readfile('x0')) 133 | y0 = Integer(readfile('y0')) 134 | x1 = Integer(readfile('x1')) 135 | y1 = Integer(readfile('y1')) 136 | shape = readfile('shape').strip() 137 | rigid = readfile('rigid').strip() 138 | 139 | safefield = True 140 | safeeq = True 141 | safebase = True 142 | saferho = True 143 | safetransfer = True 144 | safedisc = True 145 | saferigid = True 146 | safeladder = True 147 | safetwist = True 148 | safecomplete = True 149 | safeind = True 150 | 151 | pstatus = 'Unverified' 152 | if not p.is_prime(): pstatus = 'False' 153 | needtofactor.add(p) 154 | if p in V: pstatus = 'True' 155 | if pstatus != 'True': safefield = False 156 | writefile('verify-pisprime',pstatus + '\n') 157 | 158 | pstatus = 'Unverified' 159 | if not l.is_prime(): pstatus = 'False' 160 | needtofactor.add(l) 161 | if l in V: pstatus = 'True' 162 | if pstatus != 'True': safebase = False 163 | writefile('verify-lisprime',pstatus + '\n') 164 | 165 | writefile('expand2-p','= %s\n' % expand2(p)) 166 | writefile('expand2-l','
= %s\n' % expand2(l)) 167 | 168 | writefile('hex-p',hex(p) + '\n') 169 | writefile('hex-l',hex(l) + '\n') 170 | writefile('hex-x0',hex(x0) + '\n') 171 | writefile('hex-x1',hex(x1) + '\n') 172 | writefile('hex-y0',hex(y0) + '\n') 173 | writefile('hex-y1',hex(y1) + '\n') 174 | 175 | gcdlpis1 = gcd(l,p) == 1 176 | safetransfer &= requirement('verify-gcdlp1',gcdlpis1) 177 | 178 | writefile('verify-movsafe','Unverified\n') 179 | writefile('verify-embeddingdegree','Unverified\n') 180 | if gcdlpis1 and l.is_prime(): 181 | u = Integers(l)(p) 182 | d = l-1 183 | needtofactor.add(d) 184 | for v in V: 185 | while d % v == 0: d /= v 186 | if d == 1: 187 | d = l-1 188 | for v in V: 189 | while d % v == 0: 190 | if u^(d/v) != 1: break 191 | d /= v 192 | safetransfer &= requirement('verify-movsafe',(l-1)/d <= 100) 193 | writefile('verify-embeddingdegree','%s
= (l-1)/%s\n' % (d,(l-1)/d)) 194 | 195 | t = p+1-l*round((p+1)/l) 196 | if l^2 > 16*p: 197 | writefile('verify-trace','%s\n' % t) 198 | f = factor(1) 199 | d = (p+1-t)/l 200 | needtofactor.add(d) 201 | for v in V: 202 | while d % v == 0: 203 | d //= v 204 | f *= factor(v) 205 | writefile('verify-cofactor','%s\n' % f) 206 | else: 207 | writefile('verify-trace','Unverified\n') 208 | writefile('verify-cofactor','Unverified\n') 209 | 210 | D = t^2-4*p 211 | needtofactor.add(D) 212 | for v in V: 213 | while D % v^2 == 0: D /= v^2 214 | if prod([v for v in V if D % v == 0]) != -D: 215 | writefile('verify-disc','Unverified\n') 216 | writefile('verify-discisbig','Unverified\n') 217 | safedisc = False 218 | else: 219 | f = -prod([factor(v) for v in V if D % v == 0]) 220 | if D % 4 != 1: 221 | D *= 4 222 | f = factor(4) * f 223 | Dbits = (log(-D)/log(2)).numerical_approx() 224 | writefile('verify-disc','%s
= %s
≈ -2^%.1f\n' % (D,f,Dbits)) 225 | safedisc &= requirement('verify-discisbig',D < -2^100) 226 | 227 | pi4 = 0.78539816339744830961566084581987572105 228 | rho = log(pi4*l)/log(4) 229 | writefile('verify-rho','%.1f\n' % rho) 230 | saferho &= requirement('verify-rhoabove100',rho.numerical_approx() >= 100) 231 | 232 | twistl = 'Unverified' 233 | d = p+1+t 234 | needtofactor.add(d) 235 | for v in V: 236 | while d % v == 0: d /= v 237 | if d == 1: 238 | d = p+1+t 239 | for v in V: 240 | if d % v == 0: 241 | if twistl == 'Unverified' or v > twistl: twistl = v 242 | 243 | writefile('verify-twistl','%s\n' % twistl) 244 | writefile('verify-twistembeddingdegree','Unverified\n') 245 | writefile('verify-twistmovsafe','Unverified\n') 246 | if twistl == 'Unverified': 247 | writefile('hex-twistl','Unverified\n') 248 | writefile('expand2-twistl','Unverified\n') 249 | writefile('verify-twistcofactor','Unverified\n') 250 | writefile('verify-gcdtwistlp1','Unverified\n') 251 | writefile('verify-twistrho','Unverified\n') 252 | safetwist = False 253 | else: 254 | writefile('hex-twistl',hex(twistl) + '\n') 255 | writefile('expand2-twistl','
= %s\n' % expand2(twistl)) 256 | f = factor(1) 257 | d = (p+1+t)/twistl 258 | needtofactor.add(d) 259 | for v in V: 260 | while d % v == 0: 261 | d //= v 262 | f *= factor(v) 263 | writefile('verify-twistcofactor','%s\n' % f) 264 | gcdtwistlpis1 = gcd(twistl,p) == 1 265 | safetwist &= requirement('verify-gcdtwistlp1',gcdtwistlpis1) 266 | 267 | movsafe = 'Unverified' 268 | embeddingdegree = 'Unverified' 269 | if gcdtwistlpis1 and twistl.is_prime(): 270 | u = Integers(twistl)(p) 271 | d = twistl-1 272 | needtofactor.add(d) 273 | for v in V: 274 | while d % v == 0: d /= v 275 | if d == 1: 276 | d = twistl-1 277 | for v in V: 278 | while d % v == 0: 279 | if u^(d/v) != 1: break 280 | d /= v 281 | safetwist &= requirement('verify-twistmovsafe',(twistl-1)/d <= 100) 282 | writefile('verify-twistembeddingdegree',"%s
= (l'-1)/%s\n" % (d,(twistl-1)/d)) 283 | 284 | rho = log(pi4*twistl)/log(4) 285 | writefile('verify-twistrho','%.1f\n' % rho) 286 | safetwist &= requirement('verify-twistrhoabove100',rho.numerical_approx() >= 100) 287 | 288 | precomp = 0 289 | joint = l 290 | needtofactor.add(p+1-t) 291 | needtofactor.add(p+1+t) 292 | for v in V: 293 | d1 = p+1-t 294 | d2 = p+1+t 295 | while d1 % v == 0 or d2 % v == 0: 296 | if d1 % v == 0: d1 //= v 297 | if d2 % v == 0: d2 //= v 298 | # best case for attack: cyclic; each power is usable 299 | # also assume that kangaroo is as efficient as rho 300 | if v + sqrt(pi4*joint/v) < sqrt(pi4*joint): 301 | precomp += v 302 | joint /= v 303 | 304 | rho = log(precomp + sqrt(pi4 * joint))/log(2) 305 | writefile('verify-jointrho','%.1f\n' % rho) 306 | safetwist &= requirement('verify-jointrhoabove100',rho.numerical_approx() >= 100) 307 | 308 | 309 | x0 = k(x0) 310 | y0 = k(y0) 311 | x1 = k(x1) 312 | y1 = k(y1) 313 | 314 | if shape in ('edwards', 'tedwards'): 315 | d = Integer(readfile('d')) 316 | a = 1 317 | if shape == 'tedwards': 318 | a = Integer(readfile('a')) 319 | 320 | writefile('verify-shape','Twisted Edwards\n') 321 | writefile('verify-equation','%sx^2+y^2 = 1%+dx^2y^2\n' % (a, d)) 322 | if a == 1: 323 | writefile('verify-shape','Edwards\n') 324 | writefile('verify-equation','x^2+y^2 = 1%+dx^2y^2\n' % d) 325 | 326 | a = k(a) 327 | d = k(d) 328 | elliptic = a*d*(a-d) 329 | level0 = a*x0^2+y0^2-1-d*x0^2*y0^2 330 | level1 = a*x1^2+y1^2-1-d*x1^2*y1^2 331 | 332 | if shape == 'montgomery': 333 | writefile('verify-shape','Montgomery\n') 334 | A = Integer(readfile('A')) 335 | B = Integer(readfile('B')) 336 | equation = '%sy^2 = x^3%+dx^2+x' % (B,A) 337 | if B == 1: 338 | equation = 'y^2 = x^3%+dx^2+x' % A 339 | writefile('verify-equation',equation + '\n') 340 | 341 | A = k(A) 342 | B = k(B) 343 | elliptic = B*(A^2-4) 344 | level0 = B*y0^2-x0^3-A*x0^2-x0 345 | level1 = B*y1^2-x1^3-A*x1^2-x1 346 | 347 | if shape == 'shortw': 348 | writefile('verify-shape','short Weierstrass\n') 349 | a = Integer(readfile('a')) 350 | b = Integer(readfile('b')) 351 | writefile('verify-equation','y^2 = x^3%+dx%+d\n' % (a,b)) 352 | 353 | a = k(a) 354 | b = k(b) 355 | elliptic = 4*a^3+27*b^2 356 | level0 = y0^2-x0^3-a*x0-b 357 | level1 = y1^2-x1^3-a*x1-b 358 | 359 | writefile('verify-elliptic',str(elliptic) + '\n') 360 | safeeq &= requirement('verify-iselliptic',elliptic != 0) 361 | safebase &= requirement('verify-isoncurve0',level0 == 0) 362 | safebase &= requirement('verify-isoncurve1',level1 == 0) 363 | 364 | if shape in ('edwards', 'tedwards'): 365 | A = 2*(a+d)/(a-d) 366 | B = 4/(a-d) 367 | x0,y0 = (1+y0)/(1-y0),((1+y0)/(1-y0))/x0 368 | x1,y1 = (1+y1)/(1-y1),((1+y1)/(1-y1))/x1 369 | shape = 'montgomery' 370 | 371 | if shape == 'montgomery': 372 | a = (3-A^2)/(3*B^2) 373 | b = (2*A^3-9*A)/(27*B^3) 374 | x0,y0 = (x0+A/3)/B,y0/B 375 | x1,y1 = (x1+A/3)/B,y1/B 376 | shape = 'shortw' 377 | 378 | try: 379 | E = EllipticCurve([a,b]) 380 | numorder2 = 0 381 | numorder4 = 0 382 | for P in E(0).division_points(4): 383 | if P != 0 and 2*P == 0: 384 | numorder2 += 1 385 | if 2*P != 0 and 4*P == 0: 386 | numorder4 += 1 387 | writefile('verify-numorder2',str(numorder2) + '\n') 388 | writefile('verify-numorder4',str(numorder4) + '\n') 389 | completesingle = False 390 | completemulti = False 391 | if numorder4 == 2 and numorder2 == 1: 392 | # complete edwards form, and montgomery with unique point of order 2 393 | completesingle = True 394 | completemulti = True 395 | # should extend this to allow complete twisted hessian 396 | safecomplete &= requirement('verify-completesingle',completesingle) 397 | safecomplete &= requirement('verify-completemulti',completemulti) 398 | safecomplete &= requirement('verify-ltimesbase1is0',l * E([x1,y1]) == 0) 399 | writefile('verify-ltimesbase1',str(l * E([x1,y1])) + '\n') 400 | writefile('verify-cofactorbase01',str(((p+1-t)//l) * E([x0,y0]) == E([x1,y1])) + '\n') 401 | except: 402 | writefile('verify-numorder2','Unverified\n') 403 | writefile('verify-numorder4','Unverified\n') 404 | writefile('verify-ltimesbase1','Unverified\n') 405 | writefile('verify-cofactorbase01','Unverified\n') 406 | safecomplete = False 407 | 408 | montladder = False 409 | for r,e in (z^3+a*z+b).roots(): 410 | if (3*r^2+a).is_square(): 411 | montladder = True 412 | safeladder &= requirement('verify-montladder',montladder) 413 | 414 | indistinguishability = False 415 | elligator2 = False 416 | if (p+1-t) % 2 == 0: 417 | if b != 0: 418 | indistinguishability = True 419 | elligator2 = True 420 | safeind &= requirement('verify-indistinguishability',indistinguishability) 421 | writefile('verify-ind-notes','Elligator 2: %s.\n' % ['No','Yes'][elligator2]) 422 | 423 | saferigid &= (rigid == 'fully rigid' or rigid == 'somewhat rigid') 424 | 425 | safecurve = True 426 | safecurve &= requirement('verify-safefield',safefield) 427 | safecurve &= requirement('verify-safeeq',safeeq) 428 | safecurve &= requirement('verify-safebase',safebase) 429 | safecurve &= requirement('verify-saferho',saferho) 430 | safecurve &= requirement('verify-safetransfer',safetransfer) 431 | safecurve &= requirement('verify-safedisc',safedisc) 432 | safecurve &= requirement('verify-saferigid',saferigid) 433 | safecurve &= requirement('verify-safeladder',safeladder) 434 | safecurve &= requirement('verify-safetwist',safetwist) 435 | safecurve &= requirement('verify-safecomplete',safecomplete) 436 | safecurve &= requirement('verify-safeind',safeind) 437 | requirement('verify-safecurve',safecurve) 438 | 439 | originaldir = os.open('.',os.O_RDONLY) 440 | for i in range(1,len(sys.argv)): 441 | os.fchdir(originaldir) 442 | os.chdir(sys.argv[i]) 443 | verify() 444 | 445 | --------------------------------------------------------------------------------