| @@ -23,7 +23,6 @@ def M_to_E(P): | |||||
| if maybe(): X,Y = Y,-X | if maybe(): X,Y = Y,-X | ||||
| # OK, have point in ed | # OK, have point in ed | ||||
| return X,Y | return X,Y | ||||
| def decaf_encode_from_E(X,Y): | def decaf_encode_from_E(X,Y): | ||||
| assert X^2 + Y^2 == 1 + d*X^2*Y^2 | assert X^2 + Y^2 == 1 + d*X^2*Y^2 | ||||
| @@ -38,6 +37,43 @@ def decaf_encode_from_E(X,Y): | |||||
| if not qpositive(s): s = -s | if not qpositive(s): s = -s | ||||
| return s | return s | ||||
| def isqrt(x): | |||||
| assert(x.is_square()) | |||||
| if x == 0: return 0 | |||||
| else: return 1/sqrt(x) | |||||
| def decaf_encode_from_E_c(X,Y): | |||||
| Z = F.random_element() | |||||
| T = X*Y*Z | |||||
| X = X*Z | |||||
| Y = Y*Z | |||||
| assert X^2 + Y^2 == Z^2 + d*T^2 | |||||
| # Precompute | |||||
| sd = sqrt(F(1-d)) | |||||
| zx = Z^2-X^2 | |||||
| TZ = T*Z | |||||
| assert zx.is_square | |||||
| ooAll = isqrt(zx*TZ^2) | |||||
| osx = ooAll * TZ | |||||
| ooTZ = ooAll * zx * osx | |||||
| floop = qpositive(T^2 * ooTZ) | |||||
| if floop: | |||||
| frob = zx * ooTZ | |||||
| else: | |||||
| frob = sd | |||||
| Y = -X | |||||
| osx *= frob | |||||
| if qpositive(-2*osx*Z) != floop: osx = -osx | |||||
| s = Y*(ooTZ*Z + osx) | |||||
| if not qpositive(s): s = -s | |||||
| return s | |||||
| def is_rotation((X,Y),(x,y)): | def is_rotation((X,Y),(x,y)): | ||||
| return x*Y == X*y or x*X == -y*Y | return x*Y == X*y or x*X == -y*Y | ||||
| @@ -49,13 +85,36 @@ def decaf_decode_to_E(s): | |||||
| X,Y = 2*s / (1+s^2), (1-s^2) / t | X,Y = 2*s / (1+s^2), (1-s^2) / t | ||||
| assert qpositive(X*Y) | assert qpositive(X*Y) | ||||
| return X,Y | return X,Y | ||||
| def decaf_decode_to_E_c(s): | |||||
| assert qpositive(s) | |||||
| s2 = s^2 | |||||
| s21 = 1+s2 | |||||
| t2 = s21^2 - 4*d*s2 | |||||
| alt = s21*s | |||||
| the = isqrt(t2*alt^2) | |||||
| oot = the * alt | |||||
| the *= t2 | |||||
| tos = the * s21 | |||||
| X = 2 * (tos-the) * oot | |||||
| Y = (1-s2) * oot | |||||
| if not qpositive(tos): Y = -Y | |||||
| assert qpositive(X*Y) | |||||
| return X,Y | |||||
| def test(): | def test(): | ||||
| P = 2*M.random_point() | P = 2*M.random_point() | ||||
| X,Y = M_to_E(P) | X,Y = M_to_E(P) | ||||
| s = decaf_encode_from_E(X,Y) | s = decaf_encode_from_E(X,Y) | ||||
| assert s == decaf_encode_from_E_c(X,Y) | |||||
| XX,YY = decaf_decode_to_E(s) | XX,YY = decaf_decode_to_E(s) | ||||
| XX2,YY2 = decaf_decode_to_E_c(s) | |||||
| assert is_rotation((X,Y),(XX,YY)) | assert is_rotation((X,Y),(XX,YY)) | ||||
| assert is_rotation((X,Y),(XX2,YY2)) | |||||