aboutsummaryrefslogtreecommitdiffstats
path: root/ecc.hs
blob: 01ef90e252177086790b5ffc8a9be7bf551063be (plain)
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
data FieldElement =
  FieldElement
    { number :: Int
    , prime  :: Int
    }
  deriving (Eq)

instance Show FieldElement where
  show a = "FieldElement_" ++ show (prime a) ++ " " ++ show (number a)

instance Num FieldElement where
  (FieldElement a b) + (FieldElement c d)
    | b /= d = error "Distinct Fields"
    | otherwise = FieldElement (mod (a + c) b) b
  (FieldElement a b) * (FieldElement c d)
    | b /= d = error "Distinct Fields"
    | otherwise = FieldElement (mod (a * c) b) b
  abs a = a
  signum _ = 1
  negate (FieldElement a b) = FieldElement (mod (b - a) b) b
  fromInteger _ = error "can't transform"

instance Fractional FieldElement where
  recip a = a ^ (prime a - 2)
  fromRational _ = error "can't transform"

assert :: Bool -> Bool
assert False = error "WRONG"
assert x     = x

aa =
  let a = FieldElement 2 31
      b = FieldElement 15 31
   in assert
        (and
           [ a + b == FieldElement 17 31
           , a /= b
           , a - b == FieldElement 18 31
           ])

bb =
  let a = FieldElement 19 31
      b = FieldElement 24 31
   in a * b

data ECPoint
  = Infinity
  | ECPoint
      { x :: Double
      , y :: Double
      , a :: Double
      , b :: Double
      }
  deriving (Eq)

instance Show ECPoint where
  show Infinity = "ECPoint(Infinity)"
  show p =
    "ECPoint(" ++
    show (x p) ++ ", " ++ show (y p) ++ ")_" ++ show (a p) ++ "_" ++ show (b p)

validECPoint :: ECPoint -> Bool
validECPoint Infinity = True
validECPoint p = (y p)^2 == (x p)^3 + (a p) * (x p) + (b p)

add :: ECPoint -> ECPoint -> ECPoint
add Infinity p = p
add p Infinity = p
add p q
  | (a p) /= (a q) || (b p) /= (b q) = error "point not on same curve"
  | (x p) == (x q) && (y p) /= (y q) = Infinity
  | (x p) /= (x q) =
    let slope = ((y q) - (y p)) / ((x q) - (x p))
        new_x = slope ^ 2 - (x p) - (x q)
        new_y = slope * (x p - new_x) - (y p)
     in ECPoint new_x new_y (a p) (b p)
  | (x p) == (x q) && (y p) == 0 = Infinity
  | p == q =
    let slope = (3 * (x p) ^ 2 + (a p)) / (2 * (y p))
        new_x = slope ^ 2 - (x p) - (x q)
        new_y = slope * (x p - new_x) - (y p)
     in ECPoint new_x new_y (a p) (b p)
  | otherwise = error "Unexpected case of points"


cc =
  let a = ECPoint 3 (-7) 5 7
      b = ECPoint 18 77 5 7
      c = ECPoint (-1) (-1) 5 7
   in ( validECPoint a
      , validECPoint b
      , validECPoint c
      , a /= b
      , a == a
      , add Infinity a
      , add a (ECPoint 3 7 5 7)
      , add (ECPoint 3 7 5 7) c
      , add c c)