module Codec.Crypto.ECC.Base (EC(..),
getBitLength,
geta,
getb,
getp,
getr,
ECPF(..),
getCurve,
getx,
gety,
getz,
getaz4,
getxA,
getyA,
padd,
pdouble,
modinv,
pmul,
ison)
where
import qualified Data.F2 as F2
import qualified Data.Bits as B (testBit)
import qualified Data.List as L (length)
import qualified Numeric as N (showIntAtBase)
import qualified Data.Char as DC (intToDigit)
import qualified Crypto.Types as CT (BitLength)
import Data.Serialize as S (Serialize,put,get)
import Control.Applicative ((<$>),(<*>))
data EC a where
ECi :: CT.BitLength -> Integer -> Integer -> Integer -> Integer -> EC Integer
ECb :: CT.BitLength -> F2.F2 -> F2.F2 -> F2.F2 -> F2.F2 -> EC F2.F2
instance Eq (EC a) where
(ECi l a b p r) == (ECi l' a' b' p' r') = l==l' && a==a' && b==b' && p==p' && r==r'
(ECb l a b p r) == (ECb l' a' b' p' r') = l==l' && a==a' && b==b' && p==p' && r==r'
_ == _ = False
instance Show (EC a) where
show (ECi l a b p r) = "Curve with length" ++ show l ++", y^2=x^3+" ++ show a ++ "*x+" ++ show b ++ " mod " ++ show p ++ " and group order " ++ show r
show (ECb l a b p r) = "Curve with length" ++ show l ++", y^2=x^3+" ++ show a ++ "*x+" ++ show b ++ " mod " ++ show p ++ " and group order " ++ show r
instance Serialize (EC Integer) where
put (ECi l a b p r) = S.put l >> S.put a >> S.put b >> S.put p >> S.put r
get = (ECi) <$> S.get <*> S.get <*> S.get <*> S.get <*> S.get
instance Serialize (EC F2.F2) where
put (ECb l a b p r) = S.put l >> S.put a >> S.put b >> S.put p >> S.put r
get = (ECb) <$> S.get <*> S.get <*> S.get <*> S.get <*> S.get
getBitLength :: EC a -> Int
getBitLength (ECi l _ _ _ _) = l
getBitLength (ECb l _ _ _ _) = l
geta :: EC a -> a
geta (ECi _ a _ _ _) = a
geta (ECb _ a _ _ _) = a
getb :: EC a -> a
getb (ECi _ _ b _ _) = b
getb (ECb _ _ b _ _) = b
getp :: EC a -> a
getp (ECi _ _ _ p _) = p
getp (ECb _ _ _ p _) = p
getr :: EC a -> a
getr (ECi _ _ _ _ r) = r
getr (ECb _ _ _ _ r) = r
data ECPF a where
ECPa :: EC Integer -> Integer -> Integer -> ECPF Integer
ECPp ::EC Integer -> Integer -> Integer -> Integer -> ECPF Integer
ECPj :: EC Integer -> Integer -> Integer -> Integer -> ECPF Integer
ECPmj :: EC Integer -> Integer -> Integer -> Integer -> Integer -> ECPF Integer
ECPaF2 :: EC F2.F2 -> F2.F2 -> F2.F2 -> ECPF F2.F2
ECPpF2 :: EC F2.F2 -> F2.F2 -> F2.F2 -> F2.F2 -> ECPF F2.F2
ECPInfI :: EC Integer -> ECPF Integer
ECPInfF2 :: EC F2.F2 -> ECPF F2.F2
instance Eq (ECPF a) where
(ECPa curve x y) == (ECPa curve' x' y') = curve==curve' && x==x' && y==y'
(ECPp curve x y z) == (ECPp curve' x' y' z') = curve==curve' && x==x' && y==y' && z==z'
(ECPj curve x y z) == (ECPj curve' x' y' z') = curve==curve' && x==x' && y==y' && z==z'
(ECPmj curve x y z az4) == (ECPmj curve' x' y' z' az4') = curve==curve' && x==x' && y==y' && z==z' && az4==az4'
(ECPaF2 curve x y) == (ECPaF2 curve' x' y') = curve==curve' && x==x' && y==y'
(ECPpF2 curve x y z) == (ECPpF2 curve' x' y' z') = curve==curve' && x==x' && y==y' && z==z'
(ECPInfI curve) == (ECPInfI curve') = curve==curve'
(ECPInfF2 curve) == (ECPInfF2 curve') = curve==curve'
_ == _ = False
instance Show (ECPF a) where
show (ECPa curve x y) = show (curve,x,y)
show (ECPp curve x y z) = show (curve,x,y,z)
show (ECPj curve x y z) = show (curve,x,y,z)
show (ECPmj curve x y z az4) = show (curve,x,y,z,az4)
show (ECPaF2 curve x y) = show (curve,x,y)
show (ECPpF2 curve x y z) = show (curve,x,y,z)
show (ECPInfI curve) = show "Point at Infinity on the " ++ show curve
show (ECPInfF2 curve) = show "Point at Infinity on the " ++ show curve
instance Serialize (ECPF Integer) where
put pt@(ECPa _ _ _) = S.put "a" >> (S.put $ getCurve pt) >> (S.put $ getx pt) >> (S.put $ gety pt)
put pt@(ECPp _ _ _ _) = S.put "p" >> (S.put $ getCurve pt) >> (S.put $ getx pt) >> (S.put $ gety pt) >> (S.put $ getz pt)
put pt@(ECPj _ _ _ _) = S.put "j" >> (S.put $ getCurve pt) >> (S.put $ getx pt) >> (S.put $ gety pt) >> (S.put $ getz pt)
put pt@(ECPmj _ _ _ _ _) = S.put "j" >> (S.put $ getCurve pt) >> (S.put $ getx pt) >> (S.put $ gety pt) >> (S.put $ getz pt) >> (S.put $ getaz4 pt)
put pt@(ECPInfI _) = S.put "i" >> (S.put $ getCurve pt)
get = do
t <- S.get
case t of
"a" -> (ECPa) <$> S.get <*> S.get <*> S.get
"p" -> (ECPp) <$> S.get <*> S.get <*> S.get <*> S.get
"j" -> (ECPj) <$> S.get <*> S.get <*> S.get <*> S.get
"m" -> (ECPmj) <$> S.get <*> S.get <*> S.get <*> S.get <*> S.get
"i" -> (ECPInfI) <$> S.get
_ -> fail "Wrong format!"
instance Serialize (ECPF F2.F2) where
put pt@(ECPaF2 _ _ _) = S.put "a2" >> (S.put $ getCurve pt) >> (S.put $ getx pt) >> (S.put $ gety pt)
put pt@(ECPpF2 _ _ _ _) = S.put "p2" >> (S.put $ getCurve pt) >> (S.put $ getx pt) >> (S.put $ gety pt) >> (S.put $ getz pt)
put pt@(ECPInfF2 _) = S.put "i2" >> (S.put $ getCurve pt)
get = do
t <- S.get
case t of
"a2" -> (ECPaF2) <$> S.get <*> S.get <*> S.get
"p2" -> (ECPpF2) <$> S.get <*> S.get <*> S.get <*> S.get
"i2" -> (ECPInfF2) <$> S.get
_ -> fail "Wrong format!"
getCurve :: ECPF a -> EC a
getCurve (ECPa curve _ _) = curve
getCurve (ECPp curve _ _ _) = curve
getCurve (ECPj curve _ _ _) = curve
getCurve (ECPmj curve _ _ _ _) = curve
getCurve (ECPaF2 curve _ _) = curve
getCurve (ECPpF2 curve _ _ _) = curve
getCurve (ECPInfI c) = c
getCurve (ECPInfF2 c) = c
getx :: ECPF a -> a
getx (ECPa _ x _) = x
getx (ECPp _ x _ _) = x
getx (ECPj _ x _ _) = x
getx (ECPmj _ x _ _ _) = x
getx (ECPaF2 _ x _) = x
getx (ECPpF2 _ x _ _) = x
getx (ECPInfI _) = undefined
getx (ECPInfF2 _) = undefined
gety :: ECPF a -> a
gety (ECPa _ _ y) = y
gety (ECPp _ _ y _) = y
gety (ECPj _ _ y _) = y
gety (ECPmj _ _ y _ _) = y
gety (ECPaF2 _ _ y) = y
gety (ECPpF2 _ _ y _) = y
gety (ECPInfI _) = undefined
gety (ECPInfF2 _) = undefined
getz :: ECPF a -> a
getz (ECPa _ _ _) = undefined
getz (ECPp _ _ _ z) = z
getz (ECPj _ _ _ z) = z
getz (ECPmj _ _ _ z _) = z
getz (ECPaF2 _ _ _) = undefined
getz (ECPpF2 _ _ _ z) = z
getz (ECPInfI _) = undefined
getz (ECPInfF2 _) = undefined
getaz4 :: ECPF a -> a
getaz4 (ECPa _ _ _) = undefined
getaz4 (ECPp _ _ _ _) = undefined
getaz4 (ECPj _ _ _ _) = undefined
getaz4 (ECPmj _ _ _ _ az4) = az4
getaz4 (ECPaF2 _ _ _) = undefined
getaz4 (ECPpF2 _ _ _ _) = undefined
getaz4 (ECPInfI _) = undefined
getaz4 (ECPInfF2 _) = undefined
getxA :: ECPF a -> a
getxA pt@(ECPa _ _ _) = getx pt
getxA pt@(ECPp _ _ _ _) =
let p = getp $ getCurve pt
x = getx pt
z = getz pt
in (x * (modinv z p)) `mod` p
getxA pt@(ECPj _ _ _ _) =
let p = getp $ getCurve pt
x = getx pt
z = getz pt
in (x * (modinv (z^(2::Int)) p)) `mod` p
getxA pt@(ECPmj _ _ _ _ _) =
let p = getp $ getCurve pt
x = getx pt
z = getz pt
in (x * (modinv (z^(2::Int)) p)) `mod` p
getxA pt@(ECPaF2 _ _ _) = getx pt
getxA pt@(ECPpF2 _ _ _ _) =
let p = getp $ getCurve pt
x = getx pt
z = getz pt
in (x * (F2.bininv z p)) `F2.mod` p
getxA (ECPInfI _) = undefined
getxA (ECPInfF2 _) = undefined
getyA :: ECPF a -> a
getyA pt@(ECPa _ _ _) = gety pt
getyA pt@(ECPp _ _ _ _) =
let p = getp $ getCurve pt
y = gety pt
z = getz pt
in (y * (modinv z p)) `mod` p
getyA pt@(ECPj _ _ _ _) =
let p = getp $ getCurve pt
y = gety pt
z = getz pt
in (y * (modinv (z^(3::Int)) p)) `mod` p
getyA pt@(ECPmj _ _ _ _ _) =
let p = getp $ getCurve pt
y = gety pt
z = getz pt
in (y * (modinv (z^(3::Int)) p)) `mod` p
getyA pt@(ECPaF2 _ _ _) = gety pt
getyA pt@(ECPpF2 _ _ _ _) =
let p = getp $ getCurve pt
y = gety pt
z = getz pt
in (y * (F2.bininv z p)) `F2.mod` p
getyA (ECPInfI _) = undefined
getyA (ECPInfF2 _) = undefined
pdouble :: (ECPF a) -> (ECPF a)
pdouble pt@(ECPInfI _) = pt
pdouble pt@(ECPInfF2 _) = pt
pdouble pt@(ECPa _ _ _) =
let curve = getCurve pt
alpha = geta curve
p = getp curve
x1 = getx pt
y1 = gety pt
lambda = ((3*x1^(2::Int)+alpha)*(modinv (2*y1) p)) `mod` p
x3 = (lambda^(2::Int) 2*x1) `mod` p
y3 = (lambda*(x1x3)y1) `mod` p
in ECPa curve x3 y3
pdouble pt@(ECPp _ _ _ _) =
let curve = getCurve pt
alpha = geta curve
p = getp curve
x1 = getx pt
y1 = gety pt
z1 = getz pt
a = (alpha*z1^(2::Int)+3*x1^(2::Int)) `mod` p
b = (y1*z1) `mod` p
c = (x1*y1*b) `mod` p
d = (a^(2::Int)8*c) `mod` p
x3 = (2*b*d) `mod` p
y3 = (a*(4*cd)8*y1^(2::Int)*b^(2::Int)) `mod` p
z3 = (8*b^(3::Int)) `mod` p
in ECPp curve x3 y3 z3
pdouble pt@(ECPj _ _ _ _) =
let curve = getCurve pt
alpha = geta curve
p = getp curve
x1 = getx pt
y1 = gety pt
z1 = getz pt
a = 4*x1*y1^(2::Int) `mod` p
b = (3*x1^(2::Int) + alpha*z1^(4::Int)) `mod` p
x3 = (2*a + b^(2::Int)) `mod` p
y3 = (8*y1^(4::Int) + b*(ax3)) `mod` p
z3 = 2*y1*z1 `mod` p
in ECPj curve x3 y3 z3
pdouble pt@(ECPmj _ _ _ _ _) =
let curve = getCurve pt
p = getp curve
x1 = getx pt
y1 = gety pt
z1 = getz pt
z1' = getaz4 pt
s = 4*x1*y1^(2::Int) `mod` p
u = 8*y1^(4::Int) `mod` p
m = (3*x1^(2::Int) + z1') `mod` p
t = (2*s + m^(2::Int)) `mod` p
x3 = t
y3 = (m*(s t) u) `mod` p
z3 = 2*y1*z1 `mod` p
z3' = 2*u*z1' `mod` p
in ECPmj curve x3 y3 z3 z3'
pdouble pt@(ECPaF2 _ _ _) =
let curve = getCurve pt
alpha = geta curve
p = getp curve
x1 = getx pt
y1 = gety pt
lambda = (x1 + (y1 * (F2.bininv x1 p)))
x3 = (lambda `F2.pow` (fromInteger 2)) + lambda + alpha `F2.mod` p
y3 = (lambda * (x1 + x3)) + x3 + y1 `F2.mod` p
in ECPaF2 curve x3 y3
pdouble pt@(ECPpF2 _ _ _ _) =
let curve = getCurve pt
alpha = geta curve
p = getp curve
x1 = getx pt
y1 = gety pt
z1 = getz pt
a = (x1 `F2.pow` (fromInteger 2)) `F2.mod` p
b = (a + (y1 * z1)) `F2.mod` p
c = (x1 * z1) `F2.mod` p
d = (c `F2.pow` (fromInteger 2)) `F2.mod` p
e = ((b `F2.pow` (fromInteger 2)) + (b * c) + (alpha * d)) `F2.mod` p
x3 = (c * e) `F2.mod` p
y3 = (((b + c) * e) + ((a `F2.pow` (fromInteger 2)) * c)) `F2.mod` p
z3 = (c * d) `F2.mod` p
in ECPpF2 curve x3 y3 z3
ison :: ECPF a -> Bool
ison pt@(ECPa _ _ _) =
let curve = getCurve pt
alpha = geta curve
beta = getb curve
p = getp curve
x = getxA pt
y = getyA pt
in (y^(2::Int)) `mod` p == (x^(3::Int)+alpha*x+beta) `mod` p
ison pt@(ECPp _ _ _ _) =
let curve = getCurve pt
alpha = geta curve
beta = getb curve
p = getp curve
x = getxA pt
y = getyA pt
in (y^(2::Int)) `mod` p == (x^(3::Int)+alpha*x+beta) `mod` p
ison pt@(ECPj _ _ _ _) =
let curve = getCurve pt
alpha = geta curve
beta = getb curve
p = getp curve
x = getxA pt
y = getyA pt
in (y^(2::Int)) `mod` p == (x^(3::Int)+alpha*x+beta) `mod` p
ison pt@(ECPmj _ _ _ _ _) =
let curve = getCurve pt
alpha = geta curve
beta = getb curve
p = getp curve
x = getxA pt
y = getyA pt
in (y^(2::Int)) `mod` p == (x^(3::Int)+alpha*x+beta) `mod` p
ison pt@(ECPaF2 _ _ _) =
let curve = getCurve pt
alpha = geta curve
beta = getb curve
p = getp curve
x = getxA pt
y = getyA pt
in ((y `F2.pow` (fromInteger 2)) + (x * y)) `F2.mod` p == ((x `F2.pow` (fromInteger 3)) + (alpha * (x `F2.pow` (fromInteger 2))) + beta) `F2.mod` p
ison pt@(ECPpF2 _ _ _ _) =
let curve = getCurve pt
alpha = geta curve
beta = getb curve
p = getp curve
x = getxA pt
y = getyA pt
in ((y `F2.pow` (fromInteger 2)) + (x * y)) `F2.mod` p == ((x `F2.pow` (fromInteger 3)) + (alpha * (x `F2.pow` (fromInteger 2))) + beta) `F2.mod` p
ison (ECPInfI _) = True
ison (ECPInfF2 _) = True
eeukl :: (Integral a ) => a -> a -> (a, a, a)
eeukl a 0 = (a,1,0)
eeukl a b = let (d,s,t) = eeukl b (a `mod` b)
in (d,t,s(div a b)*t)
modinv :: (Integral a) => a
-> a
-> a
modinv a m = let (x,y,_) = eeukl a m
in if x == 1
then mod y m
else undefined
padd :: (ECPF a) -> (ECPF a) -> (ECPF a)
padd pt@(ECPInfI _) _ = pt
padd _ pt@(ECPInfI _) = pt
padd pt@(ECPInfF2 _) _ = pt
padd _ pt@(ECPInfF2 _) = pt
padd a@(ECPa _ _ _) b@(ECPa _ _ _)
| x1==x2,y1==(y2),curve==curve' = ECPInfI curve
| a==b = pdouble a
| otherwise =
let lambda = ((y2y1)*(modinv (x2x1) p)) `mod` p
x3 = (lambda^(2::Int) x1 x2) `mod` p
y3 = (lambda*(x1x3)y1) `mod` p
in if curve==curve' then ECPa curve x3 y3
else undefined
where curve = getCurve a
p = getp curve
x1 = getx a
y1 = gety a
curve' = getCurve b
x2 = getx b
y2 = gety b
padd p1@(ECPp _ _ _ _) p2@(ECPp _ _ _ _)
| x1==x2,y1==(y2),curve==curve' = ECPInfI curve
| p1==p2 = pdouble p1
| otherwise =
let a = (y2*z1 y1*z2) `mod` p
b = (x2*z1 x1*z2) `mod` p
c = (a^(2::Int)*z1*z2 b^(3::Int) 2*b^(2::Int)*x1*z2) `mod` p
x3 = (b*c) `mod` p
y3 = (a*(b^(2::Int)*x1*z2c)b^(3::Int)*y1*z2) `mod` p
z3 = (b^(3::Int)*z1*z2) `mod` p
in if curve==curve' then ECPp curve x3 y3 z3
else undefined
where curve = getCurve p1
p = getp curve
x1 = getx p1
y1 = gety p1
z1 = getz p1
curve' = getCurve p2
x2 = getx p2
y2 = gety p2
z2 = getz p2
padd p1@(ECPj _ _ _ _) p2@(ECPj _ _ _ _)
| x1==x2,y1==(y2),curve==curve' = ECPInfI curve
| p1==p2 = pdouble p1
| otherwise =
let a = (x1*z2^(2::Int)) `mod` p
b = (x2*z1^(2::Int)) `mod` p
c = (y1*z2^(3::Int)) `mod` p
d = (y2*z1^(3::Int)) `mod` p
e = (b a) `mod` p
f = (d c) `mod` p
x3 = (e^(3::Int) 2*a*e^(2::Int) + f^(2::Int)) `mod` p
y3 = (c*e^(3::Int) + f*(a*e^(2::Int) x3)) `mod` p
z3 = (z1*z2*e) `mod` p
in if curve==curve' then ECPj curve x3 y3 z3
else undefined
where curve = getCurve p1
p = getp curve
x1 = getx p1
y1 = gety p1
z1 = getz p1
curve' = getCurve p2
x2 = getx p2
y2 = gety p2
z2 = getz p2
padd p1@(ECPmj _ _ _ _ _) p2@(ECPmj _ _ _ _ _)
| x1==x2,y1==(y2),curve==curve' = ECPInfI curve
| p1==p2 = pdouble p1
| otherwise =
let u1 = (x1*z2^(2::Int)) `mod` p
u2 = (x2*z1^(2::Int)) `mod` p
s1 = (y1*z2^(3::Int)) `mod` p
s2 = (y2*z1^(3::Int)) `mod` p
h = (u2 u1) `mod` p
r = (s2 s1) `mod` p
x3 = (h^(3::Int) 2*u1*h^(2::Int) + r^(2::Int)) `mod` p
y3 = (s1*h^(3::Int) + r*(u1*h^(2::Int) x3)) `mod` p
z3 = (z1*z2*h) `mod` p
z3' = (alpha*z3^(4::Int)) `mod` p
in if curve==curve' then ECPmj curve x3 y3 z3 z3'
else undefined
where curve = getCurve p1
alpha = geta curve
p = getp curve
x1 = getx p1
y1 = gety p1
z1 = getz p1
curve' = getCurve p2
x2 = getx p2
y2 = gety p2
z2 = getz p2
padd a@(ECPaF2 _ _ _) b@(ECPaF2 _ _ _)
| x1==x2, y1==(x2 + y2), curve==curve' = ECPInfF2 curve
| a==b = pdouble a
| otherwise =
let lambda = ((y1 + y2) * (F2.bininv (x1 + x2) p)) `F2.mod` p
x3 = ((lambda `F2.pow` (fromInteger 2)) + lambda + x1 + x2 + alpha) `F2.mod` p
y3 = ((lambda * (x1 + x3)) + x3 + y1) `F2.mod` p
in if curve==curve' then ECPaF2 curve x3 y3
else undefined
where curve = getCurve a
alpha = geta curve
p = getp curve
x1 = getx a
y1 = gety a
curve' = getCurve b
x2 = getx b
y2 = gety b
padd p1@(ECPpF2 _ _ _ _) p2@(ECPpF2 _ _ _ _)
| x1==x2,y1==(x2 + y2) = ECPInfF2 curve
| p1==p2 = pdouble p1
| otherwise =
let a = ((y1 * z2) + (z1 * y2)) `F2.mod` p
b = ((x1 * z2) + (z1 * x2)) `F2.mod` p
c = (x1 * z1) `F2.mod` p
d = (c `F2.pow` (fromInteger 2)) `F2.mod` p
e = ((((a `F2.pow` (fromInteger 2)) + (a * b) + (alpha * c)) * d) + (b * c)) `F2.mod` p
x3 = (b * e) `F2.mod` p
y3 = (((c * ((a * x1) + (y1 * b))) * z2) + ((a + b) * e)) `F2.mod` p
z3 = ((b `F2.pow` (fromInteger 3)) * d) `F2.mod` p
in if curve==curve' then ECPpF2 curve x3 y3 z3
else undefined
where curve = getCurve p1
alpha = geta curve
p = getp curve
x1 = getx p1
y1 = gety p1
z1 = getz p1
curve' = getCurve p2
x2 = getx p2
y2 = gety p2
z2 = getz p2
padd _ _ = undefined
pmul :: (ECPF a) -> Integer -> (ECPF a)
pmul = montgladder
montgladder :: (ECPF a) -> Integer -> (ECPF a)
montgladder b@(ECPa _ _ _) k' =
let p = getp $ getCurve b
k = k' `mod` (p 1)
ex !p1 !p2 i
| i < 0 = p1
| not (B.testBit k i) = ex (pdouble p1) (padd p1 p2) (i 1)
| otherwise = ex (padd p1 p2) (pdouble p2) (i 1)
in ex b (pdouble b) ((L.length (binary k)) 2)
montgladder b@(ECPp _ _ _ _) k' =
let p = getp $ getCurve b
k = k' `mod` (p 1)
ex !p1 !p2 i
| i < 0 = p1
| not (B.testBit k i) = ex (pdouble p1) (padd p1 p2) (i 1)
| otherwise = ex (padd p1 p2) (pdouble p2) (i 1)
in ex b (pdouble b) ((L.length (binary k)) 2)
montgladder b@(ECPj _ _ _ _) k' =
let p = getp $ getCurve b
k = k' `mod` (p 1)
ex !p1 !p2 i
| i < 0 = p1
| not (B.testBit k i) = ex (pdouble p1) (padd p1 p2) (i 1)
| otherwise = ex (padd p1 p2) (pdouble p2) (i 1)
in ex b (pdouble b) ((L.length (binary k)) 2)
montgladder b@(ECPmj _ _ _ _ _) k' =
let p = getp $ getCurve b
k = k' `mod` (p 1)
ex !p1 !p2 i
| i < 0 = p1
| not (B.testBit k i) = ex (pdouble p1) (padd p1 p2) (i 1)
| otherwise = ex (padd p1 p2) (pdouble p2) (i 1)
in ex b (pdouble b) ((L.length (binary k)) 2)
montgladder b@(ECPaF2 _ _ _) k' =
let p = getp $ getCurve b
k = k' `mod` ((F2.toInteger p) 1)
ex !p1 !p2 i
| i < 0 = p1
| not (B.testBit k i) = ex (pdouble p1) (padd p1 p2) (i 1)
| otherwise = ex (padd p1 p2) (pdouble p2) (i 1)
in ex b (pdouble b) ((L.length (binary k)) 2)
montgladder b@(ECPpF2 _ _ _ _) k' =
let p = getp $ getCurve b
k = k' `mod` ((F2.toInteger p) 1)
ex !p1 !p2 i
| i < 0 = p1
| not (B.testBit k i) = ex (pdouble p1) (padd p1 p2) (i 1)
| otherwise = ex (padd p1 p2) (pdouble p2) (i 1)
in ex b (pdouble b) ((L.length (binary k)) 2)
montgladder b@(ECPInfI _) _ = b
montgladder b@(ECPInfF2 _) _ = b
binary :: Integer -> String
binary = flip (N.showIntAtBase 2 DC.intToDigit) []