-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathPoint.py
115 lines (97 loc) · 3.48 KB
/
Point.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
import unittest
from FieldElement import FieldElement
class Point:
def __init__(self, x, y, a, b):
self.a = a
self.b = b
self.x = x
self.y = y
if self.x is None or self.y is None:
return
if self.y ** 2 != self.x ** 3 + a * x + b:
raise ValueError('({} {}) is not on the curve'.format(x, y))
def __repr__(self):
if self.x is None:
return 'Point(infinity)'
elif isinstance(self.x, FieldElement):
return 'Point({},{})_{}_{} FieldElement({})'.format(
self.x.num, self.y.num, self.a.num, self.b.num, self.x.prime)
else:
return 'Point({},{})_{}_{}'.format(self.x, self.y, self.a, self.b)
def __eq__(self, other):
return self.a == other.a and self.b == other.b and self.x == other.x and self.y == other.y
def __ne__(self, other):
return not self.__eq__(other)
def __add__(self, other):
if self.a != other.a or self.b != other.b:
raise TypeError('Points {}, {} are not on the same curve'.format(self, other))
if self.x is None or self.y is None:
return other
if other.x is None or other.y is None:
return self
if self.x != other.x:
s = (other.y - self.y) / (other.x - self.x)
new_x = s * s - self.x - other.x
new_y = s * (self.x - new_x) - self.y
return self.__class__(new_x, new_y, self.a, self.b)
if self.y != other.y or self.y == 0 * self.x:
return self.__class__(None, None, self.a, self.b)
s = (3 * (self.x ** 2) + self.a) / (2 * self.y)
new_x = s * s - 2 * self.x
new_y = s * (self.x - new_x) - self.y
return self.__class__(new_x, new_y, self.a, self.b)
def __rmul__(self, coefficient):
coef = coefficient
current = self
result = self.__class__(None, None, self.a, self.b)
while coef:
if coef & 1:
result += current
current += current
coef >>= 1
return result
class PointTest(unittest.TestCase):
def test_ne(self):
a = Point(x=3, y=-7, a=5, b=7)
b = Point(x=18, y=77, a=5, b=7)
self.assertTrue(a != b)
self.assertFalse(a != a)
def test_on_curve(self):
with self.assertRaises(ValueError):
Point(x=-2, y=4, a=5, b=7)
# these should not raise an error
Point(x=3, y=-7, a=5, b=7)
Point(x=18, y=77, a=5, b=7)
def test_add0(self):
a = Point(x=None, y=None, a=5, b=7)
b = Point(x=2, y=5, a=5, b=7)
c = Point(x=2, y=-5, a=5, b=7)
self.assertEqual(a + b, b)
self.assertEqual(b + a, b)
self.assertEqual(b + c, a)
def test_add1(self):
a = Point(x=3, y=7, a=5, b=7)
b = Point(x=-1, y=-1, a=5, b=7)
self.assertEqual(a + b, Point(x=2, y=-5, a=5, b=7))
def test_add2(self):
a = Point(x=-1, y=1, a=5, b=7)
self.assertEqual(a + a, Point(x=18, y=-77, a=5, b=7))
if __name__ == '__main__':
P1 = Point(-1, -1, 5, 7)
P2 = Point(-1, 1 ,5, 7)
P3 = Point(2, 5, 5, 7)
inf = Point(None, None, 5, 7)
print(P1 == P2)
print(P1 + inf)
print(inf + P2)
print(P1 + P2)
print(P1 + P1)
#print(P2 + P3)
#print(P3 + P2)
prime = 223
a = FieldElement(0, prime)
b = FieldElement(7, prime)
x = FieldElement(15, prime)
y = FieldElement(86, prime)
p = Point(x, y, a, b)
print(7 * p)