-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathMontgomery.hs
141 lines (111 loc) · 3.61 KB
/
Montgomery.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
{-# OPTIONS -fno-warn-orphans #-}
module Data.Curve.Montgomery
( module Data.Curve
, Point(..)
-- * Montgomery curves
, MCurve(..)
, MPoint
-- ** Montgomery affine curves
, MACurve(..)
, MAPoint
) where
import Protolude
import Data.Field.Galois as F (GaloisField, PrimeField, frob, sr)
import GHC.Natural (Natural)
import Text.PrettyPrint.Leijen.Text (Pretty(..))
import Data.Curve
-------------------------------------------------------------------------------
-- Montgomery form
-------------------------------------------------------------------------------
-- | Montgomery points.
type MPoint = Point 'Montgomery
-- | Montgomery curves.
class (GaloisField q, PrimeField r, Curve 'Montgomery c e q r) => MCurve c e q r where
{-# MINIMAL a_, b_, h_, q_, r_ #-}
a_ :: MPoint c e q r -> q -- ^ Coefficient @A@.
b_ :: MPoint c e q r -> q -- ^ Coefficient @B@.
h_ :: MPoint c e q r -> Natural -- ^ Curve cofactor.
q_ :: MPoint c e q r -> Natural -- ^ Curve characteristic.
r_ :: MPoint c e q r -> Natural -- ^ Curve order.
-------------------------------------------------------------------------------
-- Affine coordinates
-------------------------------------------------------------------------------
-- | Montgomery affine points.
type MAPoint = MPoint 'Affine
-- | Montgomery affine curves @By^2 = x^3 + Ax^2 + x@.
class MCurve 'Affine e q r => MACurve e q r where
{-# MINIMAL gA_ #-}
gA_ :: MAPoint e q r -- ^ Curve generator.
-- Montgomery affine curves are elliptic curves.
instance MACurve e q r => Curve 'Montgomery 'Affine e q r where
data instance Point 'Montgomery 'Affine e q r = A q q -- ^ Affine point.
| O -- ^ Infinite point.
deriving (Eq, Generic, NFData, Read, Show)
add p O = p
add O q = q
add (A x1 y1) (A x2 y2)
| x1 == x2 = O
| otherwise = A x3 y3
where
a = a_ (witness :: MAPoint e q r)
b = b_ (witness :: MAPoint e q r)
l = (y2 - y1) / (x2 - x1)
x3 = b * l * l - a - x1 - x2
y3 = l * (x1 - x3) - y1
{-# INLINABLE add #-}
char = q_
{-# INLINABLE char #-}
cof = h_
{-# INLINABLE cof #-}
dbl O = O
dbl (A x y)
| y == 0 = O
| otherwise = A x' y'
where
a = a_ (witness :: MAPoint e q r)
b = b_ (witness :: MAPoint e q r)
by = b * y
l = (x * (x + x + x + a + a) + 1) / (by + by)
x' = b * l * l - a - x - x
y' = l * (x - x') - y
{-# INLINABLE dbl #-}
def O = True
def (A x y) = b * y * y == (((x + a) * x) + 1) * x
where
a = a_ (witness :: MAPoint e q r)
b = b_ (witness :: MAPoint e q r)
{-# INLINABLE def #-}
disc _ = b * (a * a - 4)
where
a = a_ (witness :: MAPoint e q r)
b = b_ (witness :: MAPoint e q r)
{-# INLINABLE disc #-}
frob O = O
frob (A x y) = A (F.frob x) (F.frob y)
{-# INLINABLE frob #-}
fromA = identity
{-# INLINABLE fromA #-}
gen = gA_
{-# INLINABLE gen #-}
id = O
{-# INLINABLE id #-}
inv O = O
inv (A x y) = A x (-y)
{-# INLINABLE inv #-}
order = r_
{-# INLINABLE order #-}
point x y = let p = A x y in if def p then Just p else Nothing
{-# INLINABLE point #-}
pointX x = A x <$> yX (witness :: MAPoint e q r) x
{-# INLINABLE pointX #-}
toA = identity
{-# INLINABLE toA #-}
yX _ x = sr ((((x + a) * x) + 1) * x / b)
where
a = a_ (witness :: MAPoint e q r)
b = b_ (witness :: MAPoint e q r)
{-# INLINABLE yX #-}
-- Montgomery affine points are pretty.
instance MACurve e q r => Pretty (MAPoint e q r) where
pretty (A x y) = pretty (x, y)
pretty O = "O"