-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathCurve.hs
179 lines (136 loc) · 4.67 KB
/
Curve.hs
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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
module Data.Curve
(
-- * Elliptic curves
Curve(..)
, mul
, mul'
-- ** Elliptic curve forms
, Form(..)
-- ** Elliptic curve coordinates
, Coordinates(..)
) where
import Protolude
import Control.Monad.Random (MonadRandom, Random(..), getRandom)
import Data.Field.Galois (GaloisField, PrimeField, fromP)
import Data.Group (Group(..))
import GHC.Natural (Natural)
import Test.QuickCheck (Arbitrary(..))
import Text.PrettyPrint.Leijen.Text (Pretty)
-------------------------------------------------------------------------------
-- Types
-------------------------------------------------------------------------------
-- | Elliptic curves.
class (GaloisField q, PrimeField r, Arbitrary (Point f c e q r),
Eq (Point f c e q r), Generic (Point f c e q r), Group (Point f c e q r),
NFData (Point f c e q r), Pretty (Point f c e q r), Random (Point f c e q r),
Show (Point f c e q r)) => Curve (f :: Form) (c :: Coordinates) e q r where
{-# MINIMAL add, char, cof, dbl, def, disc, frob, fromA, gen,
id, inv, order, point, pointX, toA, yX #-}
-- | Curve point.
data family Point f c e q r :: *
-- Parameters
-- | Curve characteristic.
char :: Point f c e q r -> Natural
-- | Curve cofactor.
cof :: Point f c e q r -> Natural
-- | Curve well-defined.
def :: Point f c e q r -> Bool
-- | Curve discriminant.
disc :: Point f c e q r -> q
-- | Curve order.
order :: Point f c e q r -> Natural
-- Operations
-- | Point addition.
add :: Point f c e q r -> Point f c e q r -> Point f c e q r
-- | Point doubling.
dbl :: Point f c e q r -> Point f c e q r
-- | Point identity.
id :: Point f c e q r
-- | Point inversion.
inv :: Point f c e q r -> Point f c e q r
-- Functions
-- | Frobenius endomorphism.
frob :: Point f c e q r -> Point f c e q r
-- | Transform from affine coordinates.
fromA :: Curve f 'Affine e q r => Point f 'Affine e q r -> Point f c e q r
-- | Curve generator.
gen :: Point f c e q r
-- | Get point from X and Y coordinates.
point :: q -> q -> Maybe (Point f c e q r)
-- | Get point from X coordinate.
pointX :: q -> Maybe (Point f c e q r)
-- | Random point.
rnd :: MonadRandom m => m (Point f c e q r)
rnd = getRandom
-- | Transform to affine coordinates.
toA :: Curve f 'Affine e q r => Point f c e q r -> Point f 'Affine e q r
-- | Get Y coordinate from X coordinate.
yX :: Point f c e q r -> q -> Maybe q
-- | Point multiplication by field element.
mul :: Curve f c e q r => Point f c e q r -> r -> Point f c e q r
mul = (. fromP) . mul'
{-# INLINABLE mul #-}
-- | Point multiplication by integral element.
mul' :: (Curve f c e q r, Integral n) => Point f c e q r -> n -> Point f c e q r
mul' p n
| n < 0 = inv $ mul' p (-n)
| n == 0 = id
| n == 1 = p
| even n = p'
| otherwise = add p p'
where
p' = mul' (dbl p) (div n 2)
{-# INLINABLE mul' #-}
{-# SPECIALISE mul' ::
Curve f c e q r => Point f c e q r -> Int -> Point f c e q r,
Curve f c e q r => Point f c e q r -> Integer -> Point f c e q r,
Curve f c e q r => Point f c e q r -> Natural -> Point f c e q r,
Curve f c e q r => Point f c e q r -> Word -> Point f c e q r
#-}
-- | Curve forms.
data Form = Binary
| Edwards
| Montgomery
| Weierstrass
-- | Curve coordinates.
data Coordinates = Affine
| Jacobian
| Projective
-------------------------------------------------------------------------------
-- Instances
-------------------------------------------------------------------------------
-- Elliptic curve points are arbitrary.
instance Curve f c e q r => Arbitrary (Point f c e q r) where
-- Arbitrary group element.
arbitrary = mul gen <$> arbitrary
{- Arbitrary curve point.
arbitrary = suchThatMap arbitrary pointX
-}
{-# INLINABLE arbitrary #-}
-- Elliptic curve points are groups.
instance Curve f c e q r => Group (Point f c e q r) where
invert = inv
{-# INLINABLE invert #-}
pow = mul'
{-# INLINABLE pow #-}
-- Elliptic curve points are monoids.
instance Curve f c e q r => Monoid (Point f c e q r) where
mempty = id
{-# INLINABLE mempty #-}
-- Elliptic curve points are random.
instance Curve f c e q r => Random (Point f c e q r) where
-- Random group element.
random = first (mul gen) . random
{- Random curve point.
random g = case pointX x of
Just p -> (p, g')
_ -> random g'
where
(x, g') = random g
-}
{-# INLINABLE random #-}
randomR = panic "Curve.randomR: not implemented."
-- Elliptic curve points are semigroups.
instance Curve f c e q r => Semigroup (Point f c e q r) where
p <> q = if p == q then dbl p else add p q
{-# INLINABLE (<>) #-}