**Approach (brief)** I provide Python-style code implementing parameterized birational maps between a twisted Edwards curve a x^2 + y^2 = 1 + d x^2 y^2and a short Weierstrass curve Y^2 = X^3 + A X + BMost practical pipelines go Edwards <-> Montgomery <-> short Weierstrass; the exact algebraic map depends on curve parameters (a,d) and choice of isomorphism constants. The implementation below is parameterized and checks identity, denominator = 0 (undefined map), and documents special cases (e.g., Ed25519).Important notes for cryptographers:- Ensure field char != 2,3.- For Ed25519 (a = -1, d = -121665/121666) there is a Montgomery equivalent; mapping directly to short Weierstrass requires choosing a Weierstrass model and field sqrt constants — not canonical. Beware cofactor and point validation when converting keys.Code (parameterized; fill model-specific constants for a given conversion):python
# python 3 style pseudocode for finite-field elements (supports .inv(), .is_zero())
class FFElement: ...
# Example: use integers mod p with inverse, zero check, etc.
class TwistedEdwards:
def __init__(self, a, d, field):
self.a = a
self.d = d
self.F = field
class Weierstrass:
def __init__(self, A, B, field):
self.A = A
self.B = B
self.F = field
def edwards_to_weierstrass(P, E: TwistedEdwards, W: Weierstrass, params):
# params contains map constants computed from curve isomorphism:
# example params = { 'alpha':..., 'beta':..., 'gamma':... } dependent on models
# P = (x,y) or None for identity
if P is None: # identity on Edwards
return None # identity on Weierstrass
x, y = P
F = E.F
# Common denominator checks (these arise in rational maps)
denom1 = (F.one - y)
if denom1.is_zero():
raise ValueError("Mapping undefined: denominator (1-y) == 0")
# Example canonical-like map via Montgomery-style u = (1+y)/(1-y)
u = (F.one + y) * denom1.inv()
# Next step depends on a; convert u->X via linear transform:
# X = alpha * u + beta
X = params['alpha'] * u + params.get('beta', F.zero)
# v = u / x (note: x must be non-zero)
if x.is_zero():
raise ValueError("Mapping undefined: x == 0")
v = u * x.inv()
# Y = gamma * v + delta (gamma/delta from chosen isomorphism)
Y = params.get('gamma', F.one) * v + params.get('delta', F.zero)
# Validate (X,Y) satisfies Weierstrass (optionally)
lhs = Y * Y
rhs = X * X * X + W.A * X + W.B
if lhs != rhs:
raise ValueError("Converted point does not satisfy target Weierstrass equation")
return (X, Y)
def weierstrass_to_edwards(Q, W: Weierstrass, E: TwistedEdwards, params):
# Inverse birational map; Q = (X,Y) or None
if Q is None:
return None
X, Y = Q
F = W.F
# Inverse linear transforms
u = (X - params.get('beta', F.zero)) * params['alpha'].inv()
# check denominator for x computation
# compute x = u / v where v = something like Y/gamma - delta
vnum = Y - params.get('delta', F.zero)
if params.get('gamma', F.one).is_zero():
raise ValueError("Invalid params: gamma == 0")
v = vnum * params['gamma'].inv()
if v.is_zero():
raise ValueError("Mapping undefined: v == 0")
x = u * v.inv()
# y from u = (1+y)/(1-y) => y = (u-1)/(u+1)
denom = (u + F.one)
if denom.is_zero():
raise ValueError("Mapping undefined: u + 1 == 0")
y = (u - F.one) * denom.inv()
# Validate Edwards equation
lhs = E.a * x * x + y * y
rhs = F.one + E.d * x * x * y * y
if lhs != rhs:
raise ValueError("Converted point does not satisfy Edwards equation")
return (x, y)
Special cases and correctness checks- Identity: map None <-> None.- Denominators: check (1 - y), x, (u + 1), v etc.; these correspond to points mapping to the point at infinity or undefined rational points.- Field characteristic: requires char != 2,3 for short Weierstrass formulas.- Curve-specific constants: for Ed25519 you must compute the exact alpha/beta/gamma/delta used in the standard birational equivalence to the Montgomery form first, then to your chosen Weierstrass curve. Many libraries convert Edwards <-> Montgomery; converting further to short Weierstrass requires additional linear transforms and possible square roots.- Cofactor and subgroup membership: after mapping, verify the point is on the correct prime-order subgroup (multiply by cofactor or check scalar multiplication) before using as public key.- Testing: validate with multiple known points including edge cases: (0,1), (0,-1), points with x=0 or y=±1, and random samples.Trade-offs and reasoning- I keep maps parameterized because concrete rational formulas depend on the chosen target Weierstrass model. This approach lets a cryptographer plug-in constants derived algebraically for a specific curve (e.g., derive them from Edwards->Montgomery then Montgomery->Weierstrass).- Strict denominator checks prevent accidental creation of point-at-infinity or incorrect points — critical in cryptographic implementations.