module Codec.Crypto.ECC.Base (EC(..),
getBitLength,
geta,
getb,
getp,
getr,
ECPF(..),
getCurve,
getx,
gety,
getz,
getaz4,
getxA,
getyA,
padd,
pdouble,
modinv,
pmul,
ison,
binary)
where
import qualified Data.F2 as F2
import Data.Bits (testBit)
import Data.List as L (length)
import Numeric (showIntAtBase)
import Data.Char (intToDigit)
import Crypto.Types (BitLength)
import Data.Serialize (Serialize,put,get)
import Control.Applicative ((<$>),(<*>))
data EC a where
ECi :: (BitLength, Integer, Integer, Integer,Integer) -> EC Integer
ECb :: (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)) = put l >> put a >> put b >> put p >> put r
get = (ECi) <$> ((,,,,) <$> get <*> get <*> get <*> get <*> 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 _) = put 'a' >> (put $ getCurve pt) >> (put $ getx pt) >> (put $ gety pt)
put pt@(ECPp _) = put 'p' >> (put $ getCurve pt) >> (put $ getx pt) >> (put $ gety pt) >> (put $ getz pt)
put pt@(ECPj _) = put 'j' >> (put $ getCurve pt) >> (put $ getx pt) >> (put $ gety pt) >> (put $ getz pt)
put pt@(ECPmj _) = put 'j' >> (put $ getCurve pt) >> (put $ getx pt) >> (put $ gety pt) >> (put $ getz pt) >> (put $ getaz4 pt)
put pt@(ECPInfI _) = put 'i' >> (put $ getCurve pt)
get = do
t <- get
case t of
'a' -> (ECPa) <$> ((,,) <$> get <*> get <*> get)
'p' -> (ECPp) <$> ((,,,) <$> get <*> get <*> get <*> get)
'j' -> (ECPj) <$> ((,,,) <$> get <*> get <*> get <*> get)
'm' -> (ECPmj) <$> ((,,,,) <$> get <*> get <*> get <*> get <*> get)
'i' -> (ECPInfI) <$> 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.mul` (F2.bininv z p)) `F2.reduceBy` 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.mul` (F2.bininv z p)) `F2.reduceBy` 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 `F2.add` (y1 `F2.mul` (F2.bininv x1 p)))
x3 = (lambda `F2.pow` (F2.fromInteger 2)) `F2.add` lambda `F2.add` alpha `F2.reduceBy` p
y3 = (lambda `F2.mul` (x1 `F2.add` x3)) `F2.add` x3 `F2.add` y1 `F2.reduceBy` 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` (F2.fromInteger 2)) `F2.reduceBy` p
b = (a `F2.add` (y1 `F2.mul` z1)) `F2.reduceBy` p
c = (x1 `F2.mul` z1) `F2.reduceBy` p
d = (c `F2.pow` (F2.fromInteger 2)) `F2.reduceBy` p
e = ((b `F2.pow` (F2.fromInteger 2)) `F2.add` (b `F2.mul` c) `F2.add` (alpha `F2.mul` d)) `F2.reduceBy` p
x3 = (c `F2.mul` e) `F2.reduceBy` p
y3 = (((b `F2.add` c) `F2.mul` e) `F2.add` ((a `F2.pow` (F2.fromInteger 2)) `F2.mul` c)) `F2.reduceBy` p
z3 = (c `F2.mul` d) `F2.reduceBy` 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` (F2.fromInteger 2)) `F2.add` (x `F2.mul` y)) `F2.reduceBy` p == ((x `F2.pow` (F2.fromInteger 3)) `F2.add` (alpha `F2.mul` (x `F2.pow` (F2.fromInteger 2))) `F2.add` beta) `F2.reduceBy` 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` (F2.fromInteger 2)) `F2.add` (x `F2.mul` y)) `F2.reduceBy` p == ((x `F2.pow` (F2.fromInteger 3)) `F2.add` (alpha `F2.mul` (x `F2.pow` (F2.fromInteger 2))) `F2.add` beta) `F2.reduceBy` 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 _)
| ((F2.length x1 == F2.length x2) && (x1==x2)), (F2.length y1 == F2.length y2 && F2.length x2 == F2.length y2) && (y1==(x2 `F2.add` y2)), curve==curve' = ECPInfF2 curve
| (F2.length x1 == F2.length x2) && (F2.length y1 == F2.length y2) && a==b = pdouble a
| otherwise =
let lambda = ((y1 `F2.add` y2) `F2.mul` (F2.bininv (x1 `F2.add` x2) p)) `F2.reduceBy` p
x3 = ((lambda `F2.pow` (F2.fromInteger 2)) `F2.add` lambda `F2.add` x1 `F2.add` x2 `F2.add` alpha) `F2.reduceBy` p
y3 = ((lambda `F2.mul` (x1 `F2.add` x3)) `F2.add` x3 `F2.add` y1) `F2.reduceBy` 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 _)
| ((F2.length x1 == F2.length x2) && (x1==x2)),((F2.length y1 == F2.length y2 && F2.length x2 == F2.length y2) && y1==(x2 `F2.add` y2)) = ECPInfF2 curve
| (F2.length x1 == F2.length x2) && (F2.length y1 == F2.length y2) && p1==p2 = pdouble p1
| otherwise =
let a = ((y1 `F2.mul` z2) `F2.add` (z1 `F2.mul` y2)) `F2.reduceBy` p
b = ((x1 `F2.mul` z2) `F2.add` (z1 `F2.mul` x2)) `F2.reduceBy` p
c = (x1 `F2.mul` z1) `F2.reduceBy` p
d = (c `F2.pow` (F2.fromInteger 2)) `F2.reduceBy` p
e = ((((a `F2.pow` (F2.fromInteger 2)) `F2.add` (a `F2.mul` b) `F2.add` (alpha `F2.mul` c)) `F2.mul` d) `F2.add` (b `F2.mul` c)) `F2.reduceBy` p
x3 = (b `F2.mul` e) `F2.reduceBy` p
y3 = (((c `F2.mul` ((a `F2.mul` x1) `F2.add` (y1 `F2.mul` b))) `F2.mul` z2) `F2.add` ((a `F2.add` b) `F2.mul` e)) `F2.reduceBy` p
z3 = ((b `F2.pow` (F2.fromInteger 3)) `F2.mul` d) `F2.reduceBy` 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 (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 (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 (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 (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 (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 (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 (showIntAtBase 2 intToDigit) []