@@ -70,6 +70,19 @@ def xelligatorswift(x):
70
70
if t is not None :
71
71
return u , t
72
72
73
+ def ellswift_create ():
74
+ """Generate a (privkey, ellswift_pubkey) pair."""
75
+ priv = random .randrange (1 , GE .ORDER )
76
+ u , t = xelligatorswift ((priv * G ).x )
77
+ return priv .to_bytes (32 , 'big' ), u .to_bytes () + t .to_bytes ()
78
+
79
+ def ellswift_ecdh_xonly (pubkey_theirs , privkey ):
80
+ """Compute X coordinate of shared ECDH point between ellswift pubkey and privkey."""
81
+ u = FE (int .from_bytes (pubkey_theirs [:32 ], 'big' ))
82
+ t = FE (int .from_bytes (pubkey_theirs [32 :], 'big' ))
83
+ d = int .from_bytes (privkey , 'big' )
84
+ return (d * GE .lift_x (xswiftec (u , t ))).x .to_bytes ()
85
+
73
86
74
87
class TestFrameworkEllSwift (unittest .TestCase ):
75
88
def test_elligator_forward (self ):
@@ -92,3 +105,11 @@ def test_elligator_roundtrip(self):
92
105
u , t = xelligatorswift (x )
93
106
x2 = xswiftec (u , t )
94
107
self .assertEqual (x2 , x )
108
+
109
+ def test_ellswift_ecdh_xonly (self ):
110
+ for _ in range (32 ):
111
+ privkey1 , encoding1 = ellswift_create ()
112
+ privkey2 , encoding2 = ellswift_create ()
113
+ shared_secret1 = ellswift_ecdh_xonly (encoding1 , privkey2 )
114
+ shared_secret2 = ellswift_ecdh_xonly (encoding2 , privkey1 )
115
+ assert shared_secret1 == shared_secret2
0 commit comments