EllipticCurve( ︠07d3ebc2-97b1-4d70-8020-a14e7b88a2e2︠ F2 = GF((2^255)-19) # y^2 == x^3 + 486662*x^2 + x) Curve25519 = EllipticCurve(F2, [0, 486662, 0, 1, 0]) P25519 = Curve25519.point([9,F2(9^3 + 486662*9^2 + 9).sqrt()]) print(Curve25519) print "basepoint", P25519 ︡1038c7dd-aa6f-4e38-aeb9-a14e00cc761b︡{"stdout":"Elliptic Curve defined by y^2 = x^3 + 486662*x^2 + x over Finite Field of size 57896044618658097711785492504343953926634992332820282019728792003956564819949\n"}︡{"stdout":"basepoint (9 : 14781619447589544791020593568409986887264606134616475288964881837755586237401 : 1)\n"}︡ ︠a9cbbf98-2fd0-4f98-b249-3984a5b896a9︠ F1 = GF((2^251)-9) #x^2 + y^2 = 1 − 1174*x^2*y^2 Curve1174 = EllipticCurve(F1,[0,4/1175-2,0,1,0]) print(Curve1174) ︡61b54f21-45a1-4589-b7eb-295dde27ba00︡{"stdout":"Elliptic Curve defined by y^2 = x^3 + 3276669759268734891773391703437338669039342119261743620691033760223924732354*x^2 + x over Finite Field of size 3618502788666131106986593281521497120414687020801267626233049500247285301239\n"}︡ ︠d86c6cea-de54-4b3a-b31c-deccf6a6ac02︠ secret = randrange(P25519.order()) print 'secret', secret public = P25519 * secret print 'public', public ︡c642653f-c3d5-4955-be10-d30b8648dad8︡{"stdout":"secret 1467490697454842568936475396114863822922126114013609471608883888030173455623\n"}︡{"stdout":"public (14181934965252511487015101029388688573760508176091550377448791623325663079263 : 27550729654639090468645035001871244348239408328781753808485607098532078341262 : 1)\n"}︡ ︠5d682a48-288d-474f-8855-18ee6c238901︠ E = EllipticCurve(GF(1009),[5,1]); E g = E.gens()[0]; (g, g.order()) rA = randrange(g.order()); RA = rA*g; (rA, RA) rB = randrange(g.order()); RB = rB*g; (rB, RB) kA = rA*RB; kA kB = rB*RA; kB ︡15ba0f65-4892-4d53-995e-f99af15f51b4︡{"stdout":"Elliptic Curve defined by y^2 = x^3 + 5*x + 1 over Finite Field of size 1009\n"}︡{"stdout":"((930 : 789 : 1), 1039)\n"}︡{"stdout":"(505, (414 : 616 : 1))\n"}︡{"stdout":"(534, (414 : 393 : 1))\n"}︡{"stdout":"(99 : 106 : 1)\n"}︡{"stdout":"(99 : 106 : 1)\n"}︡ ︠745cc051-3da0-4ed7-a030-6d114c6a2976︠ # encryption n = randrange(g.order()); NA = n*g; Sa = n*RB; # use Sa to derive symmetric key K, and send(NA, enc(Sa, plain)) sb = NA * rB; (Sa, sb) # use sb to derive symmetric key K and dec(sb, cipher) ︡d9f0b4fe-3ab2-405e-9dc3-87e23e1dc834︡{"stdout":"((738 : 535 : 1), (738 : 535 : 1))\n"}︡ ︠9d00511c-c93c-4ae5-adbc-2b4772dd8ed6︠ ## SHA256(message) h = 0x7aac4de65f04b1b03d97537e03005247e10a41321811f948a85c2fe3bab5ce5d # sign(rA, h) ## ephemeral key Alice uses to sign her message k = randrange(g.order()) K = k*g # get the x coordinate of the ephemeral key t = ZZ(K[0]) # t = the x coordinate of K s = (h + rA*t)/k % g.order() ###### verify(h, t, s, RA) w = (1/s) % g.order() u = (w*h) % g.order() v = (w*t) % g.order() F = u*g H = v*RA # uses Alice's public key, A Q = F + H ## Q should be the same as K (Q, K) ︡7e51522c-de88-46fc-8ff9-698065fb969b︡{"stdout":"((631 : 359 : 1), (631 : 359 : 1))\n"}︡ ︠96710cf3-6d66-4a36-8b4a-50750eeb2fba︠ pts = [ g * x for x in range(g.order()) ] plot(sum([ plot(p, hue = 0.1) for p in pts ]), aspect_ratio = 1) ︡796a48d9-df0f-427d-b69e-391d1b695728︡{"once":false,"file":{"show":true,"uuid":"17f5c0da-01cd-4427-b1c4-db514aafdef9","filename":"/mnt/home/9BvEx3BA/.sage/temp/compute5a/12367/tmp_EgmBUQ.png"}}︡ ︠d1a34580-fbad-4fef-814a-992a4532d201︠