| @@ -28,21 +28,24 @@ def eddsa_to_decaf(x,y): | |||||
| def isqrt_trick(to_isr,to_inv): | def isqrt_trick(to_isr,to_inv): | ||||
| to_sqrt = to_isr*to_inv^2 | to_sqrt = to_isr*to_inv^2 | ||||
| if to_sqrt == 0: return 0,0 # This happens automatically in C; just to avoid problems in SAGE | |||||
| if to_sqrt == 0: return 0,0,0 # This happens automatically in C; just to avoid problems in SAGE | |||||
| if not is_square(to_sqrt): raise Exception("Not square in isqrt_trick!") | if not is_square(to_sqrt): raise Exception("Not square in isqrt_trick!") | ||||
| tmp = 1/sqrt(to_sqrt) | tmp = 1/sqrt(to_sqrt) | ||||
| isr = tmp * to_inv | isr = tmp * to_inv | ||||
| inv = tmp * isr * to_isr | inv = tmp * isr * to_isr | ||||
| assert isr^2 == 1/to_isr | assert isr^2 == 1/to_isr | ||||
| assert inv == 1/to_inv | assert inv == 1/to_inv | ||||
| return isr, inv | |||||
| return isr, inv, tmp | |||||
| def eddsa_to_decaf_opt(x,y,z=None): | def eddsa_to_decaf_opt(x,y,z=None): | ||||
| """ | """ | ||||
| Optimized version of eddsa_to_decaf. | |||||
| Uses only one isqrt. | |||||
| Optimized version of eddsa_to_decaf. Uses only one isqrt. | |||||
| There's probably some way to further optimize if you have a T-coord, | |||||
| but whatever. | |||||
| """ | """ | ||||
| if z is None: | if z is None: | ||||
| # Pretend that we're in projective | # Pretend that we're in projective | ||||
| @@ -50,15 +53,15 @@ def eddsa_to_decaf_opt(x,y,z=None): | |||||
| x *= z | x *= z | ||||
| y *= z | y *= z | ||||
| isr,inv = isqrt_trick(z^2-y^2,x*y) | |||||
| inv *= magic | |||||
| isr,inv,tmp = isqrt_trick(z^2-y^2,x*y) | |||||
| minv = inv*magic*z | |||||
| rotate = hibit(inv*z^2) | |||||
| rotate = hibit(minv*z) | |||||
| if rotate: | if rotate: | ||||
| isr *= (z^2-y^2)*inv | |||||
| isr = tmp*(z^2-y^2)*magic | |||||
| y = ii*x | y = ii*x | ||||
| if hibit(2*inv*y*z) != rotate: y = -y | |||||
| if hibit(2*minv*y) != rotate: y = -y | |||||
| s = (z-y) * isr | s = (z-y) * isr | ||||
| if hibit(s): s = -s | if hibit(s): s = -s | ||||
| @@ -85,3 +88,24 @@ def decaf_to_eddsa(s): | |||||
| if y == 0 or lobit(t/y): raise Exception("invalid: t/y has high bit") | if y == 0 or lobit(t/y): raise Exception("invalid: t/y has high bit") | ||||
| assert y^2 - x^2 == 1+d*x^2*y^2 | assert y^2 - x^2 == 1+d*x^2*y^2 | ||||
| return (x,y) | return (x,y) | ||||
| def decaf_to_eddsa_opt(s): | |||||
| """ | |||||
| Convert a Decaf representation to an EdDSA point, in a manner compatible | |||||
| with libdecaf. | |||||
| """ | |||||
| if s == 0: return (0,1) | |||||
| if hibit(s): raise Exception("invalid: s has high bit") | |||||
| if not is_square(s^4 + (2-4*dM)*s^2 + 1): raise Exception("invalid: not on curve") | |||||
| t = sqrt(s^4 + (2-4*dM)*s^2 + 1)/s | |||||
| if hibit(t): t = -t | |||||
| y = (1-s^2)/(1+s^2) | |||||
| x = 2*magic/t | |||||
| if y == 0 or lobit(t/y): raise Exception("invalid: t/y has high bit") | |||||
| assert y^2 - x^2 == 1+d*x^2*y^2 | |||||
| return (x,y) | |||||
| print [s == eddsa_to_decaf(*decaf_to_eddsa(s)) for _,_,s,_,_,_ in points] | |||||
| print [s == eddsa_to_decaf_opt(*decaf_to_eddsa_opt(s)) for _,_,s,_,_,_ in points] | |||||