forked from jimmysong/programmingbitcoin
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathecc.py
More file actions
116 lines (97 loc) · 3.7 KB
/
ecc.py
File metadata and controls
116 lines (97 loc) · 3.7 KB
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
116
from unittest import TestCase
# tag::source1[]
class FieldElement:
def __init__(self, num, prime):
if num >= prime or num < 0: # <1>
error = 'Num {} not in field range 0 to {}'.format(
num, prime - 1)
raise ValueError(error)
self.num = num # <2>
self.prime = prime
def __repr__(self):
return 'FieldElement_{}({})'.format(self.prime, self.num)
def __eq__(self, other):
if other is None:
return False
return self.num == other.num and self.prime == other.prime # <3>
# end::source1[]
def __ne__(self, other):
# this should be the inverse of the == operator
raise NotImplementedError
# tag::source2[]
def __add__(self, other):
if self.prime != other.prime: # <1>
raise TypeError('Cannot add two numbers in different Fields')
num = (self.num + other.num) % self.prime # <2>
return self.__class__(num, self.prime) # <3>
# end::source2[]
def __sub__(self, other):
if self.prime != other.prime:
raise TypeError('Cannot subtract two numbers in different Fields')
# self.num and other.num are the actual values
# self.prime is what we need to mod against
# We return an element of the same class
raise NotImplementedError
def __mul__(self, other):
if self.prime != other.prime:
raise TypeError('Cannot multiply two numbers in different Fields')
# self.num and other.num are the actual values
# self.prime is what we need to mod against
# We return an element of the same class
raise NotImplementedError
# tag::source3[]
def __pow__(self, exponent):
n = exponent % (self.prime - 1) # <1>
num = pow(self.num, n, self.prime)
return self.__class__(num, self.prime)
# end::source3[]
def __truediv__(self, other):
if self.prime != other.prime:
raise TypeError('Cannot divide two numbers in different Fields')
# use fermat's little theorem:
# self.num**(p-1) % p == 1
# this means:
# 1/n == pow(n, p-2, p)
# We return an element of the same class
raise NotImplementedError
class FieldElementTest(TestCase):
def test_ne(self):
a = FieldElement(2, 31)
b = FieldElement(2, 31)
c = FieldElement(15, 31)
self.assertEqual(a, b)
self.assertTrue(a != c)
self.assertFalse(a != b)
def test_add(self):
a = FieldElement(2, 31)
b = FieldElement(15, 31)
self.assertEqual(a + b, FieldElement(17, 31))
a = FieldElement(17, 31)
b = FieldElement(21, 31)
self.assertEqual(a + b, FieldElement(7, 31))
def test_sub(self):
a = FieldElement(29, 31)
b = FieldElement(4, 31)
self.assertEqual(a - b, FieldElement(25, 31))
a = FieldElement(15, 31)
b = FieldElement(30, 31)
self.assertEqual(a - b, FieldElement(16, 31))
def test_mul(self):
a = FieldElement(24, 31)
b = FieldElement(19, 31)
self.assertEqual(a * b, FieldElement(22, 31))
def test_pow(self):
a = FieldElement(17, 31)
self.assertEqual(a**3, FieldElement(15, 31))
a = FieldElement(5, 31)
b = FieldElement(18, 31)
self.assertEqual(a**5 * b, FieldElement(16, 31))
def test_div(self):
a = FieldElement(3, 31)
b = FieldElement(24, 31)
self.assertEqual(a / b, FieldElement(4, 31))
a = FieldElement(17, 31)
self.assertEqual(a**-3, FieldElement(29, 31))
a = FieldElement(4, 31)
b = FieldElement(11, 31)
self.assertEqual(a**-4 * b, FieldElement(13, 31))