module Crypto.PubKey.ECC.Prim
( scalarGenerate
, pointAdd
, pointNegate
, pointDouble
, pointBaseMul
, pointMul
, pointAddTwoMuls
, isPointAtInfinity
, isPointValid
) where
import Data.Maybe
import Crypto.Number.ModArithmetic
import Crypto.Number.F2m
import Crypto.Number.Generate (generateBetween)
import Crypto.PubKey.ECC.Types
import Crypto.Random
scalarGenerate :: MonadRandom randomly => Curve -> randomly PrivateNumber
scalarGenerate :: Curve -> randomly PrivateNumber
scalarGenerate Curve
curve = PrivateNumber -> PrivateNumber -> randomly PrivateNumber
forall (m :: * -> *).
MonadRandom m =>
PrivateNumber -> PrivateNumber -> m PrivateNumber
generateBetween PrivateNumber
1 (PrivateNumber
n PrivateNumber -> PrivateNumber -> PrivateNumber
forall a. Num a => a -> a -> a
- PrivateNumber
1)
where
n :: PrivateNumber
n = CurveCommon -> PrivateNumber
ecc_n (CurveCommon -> PrivateNumber) -> CurveCommon -> PrivateNumber
forall a b. (a -> b) -> a -> b
$ Curve -> CurveCommon
common_curve Curve
curve
pointNegate :: Curve -> Point -> Point
pointNegate :: Curve -> Point -> Point
pointNegate Curve
_ Point
PointO = Point
PointO
pointNegate (CurveFP CurvePrime
c) (Point PrivateNumber
x PrivateNumber
y) = PrivateNumber -> PrivateNumber -> Point
Point PrivateNumber
x (CurvePrime -> PrivateNumber
ecc_p CurvePrime
c PrivateNumber -> PrivateNumber -> PrivateNumber
forall a. Num a => a -> a -> a
- PrivateNumber
y)
pointNegate CurveF2m{} (Point PrivateNumber
x PrivateNumber
y) = PrivateNumber -> PrivateNumber -> Point
Point PrivateNumber
x (PrivateNumber
x PrivateNumber -> PrivateNumber -> PrivateNumber
`addF2m` PrivateNumber
y)
pointAdd :: Curve -> Point -> Point -> Point
pointAdd :: Curve -> Point -> Point -> Point
pointAdd Curve
_ Point
PointO Point
PointO = Point
PointO
pointAdd Curve
_ Point
PointO Point
q = Point
q
pointAdd Curve
_ Point
p Point
PointO = Point
p
pointAdd Curve
c Point
p Point
q
| Point
p Point -> Point -> Bool
forall a. Eq a => a -> a -> Bool
== Point
q = Curve -> Point -> Point
pointDouble Curve
c Point
p
| Point
p Point -> Point -> Bool
forall a. Eq a => a -> a -> Bool
== Curve -> Point -> Point
pointNegate Curve
c Point
q = Point
PointO
pointAdd (CurveFP (CurvePrime PrivateNumber
pr CurveCommon
_)) (Point PrivateNumber
xp PrivateNumber
yp) (Point PrivateNumber
xq PrivateNumber
yq)
= Point -> Maybe Point -> Point
forall a. a -> Maybe a -> a
fromMaybe Point
PointO (Maybe Point -> Point) -> Maybe Point -> Point
forall a b. (a -> b) -> a -> b
$ do
PrivateNumber
s <- PrivateNumber
-> PrivateNumber -> PrivateNumber -> Maybe PrivateNumber
divmod (PrivateNumber
yp PrivateNumber -> PrivateNumber -> PrivateNumber
forall a. Num a => a -> a -> a
- PrivateNumber
yq) (PrivateNumber
xp PrivateNumber -> PrivateNumber -> PrivateNumber
forall a. Num a => a -> a -> a
- PrivateNumber
xq) PrivateNumber
pr
let xr :: PrivateNumber
xr = (PrivateNumber
s PrivateNumber -> Int -> PrivateNumber
forall a b. (Num a, Integral b) => a -> b -> a
^ (Int
2::Int) PrivateNumber -> PrivateNumber -> PrivateNumber
forall a. Num a => a -> a -> a
- PrivateNumber
xp PrivateNumber -> PrivateNumber -> PrivateNumber
forall a. Num a => a -> a -> a
- PrivateNumber
xq) PrivateNumber -> PrivateNumber -> PrivateNumber
forall a. Integral a => a -> a -> a
`mod` PrivateNumber
pr
yr :: PrivateNumber
yr = (PrivateNumber
s PrivateNumber -> PrivateNumber -> PrivateNumber
forall a. Num a => a -> a -> a
* (PrivateNumber
xp PrivateNumber -> PrivateNumber -> PrivateNumber
forall a. Num a => a -> a -> a
- PrivateNumber
xr) PrivateNumber -> PrivateNumber -> PrivateNumber
forall a. Num a => a -> a -> a
- PrivateNumber
yp) PrivateNumber -> PrivateNumber -> PrivateNumber
forall a. Integral a => a -> a -> a
`mod` PrivateNumber
pr
Point -> Maybe Point
forall (m :: * -> *) a. Monad m => a -> m a
return (Point -> Maybe Point) -> Point -> Maybe Point
forall a b. (a -> b) -> a -> b
$ PrivateNumber -> PrivateNumber -> Point
Point PrivateNumber
xr PrivateNumber
yr
pointAdd (CurveF2m (CurveBinary PrivateNumber
fx CurveCommon
cc)) (Point PrivateNumber
xp PrivateNumber
yp) (Point PrivateNumber
xq PrivateNumber
yq)
= Point -> Maybe Point -> Point
forall a. a -> Maybe a -> a
fromMaybe Point
PointO (Maybe Point -> Point) -> Maybe Point -> Point
forall a b. (a -> b) -> a -> b
$ do
PrivateNumber
s <- PrivateNumber
-> PrivateNumber -> PrivateNumber -> Maybe PrivateNumber
divF2m PrivateNumber
fx (PrivateNumber
yp PrivateNumber -> PrivateNumber -> PrivateNumber
`addF2m` PrivateNumber
yq) (PrivateNumber
xp PrivateNumber -> PrivateNumber -> PrivateNumber
`addF2m` PrivateNumber
xq)
let xr :: PrivateNumber
xr = PrivateNumber -> PrivateNumber -> PrivateNumber -> PrivateNumber
mulF2m PrivateNumber
fx PrivateNumber
s PrivateNumber
s PrivateNumber -> PrivateNumber -> PrivateNumber
`addF2m` PrivateNumber
s PrivateNumber -> PrivateNumber -> PrivateNumber
`addF2m` PrivateNumber
xp PrivateNumber -> PrivateNumber -> PrivateNumber
`addF2m` PrivateNumber
xq PrivateNumber -> PrivateNumber -> PrivateNumber
`addF2m` PrivateNumber
a
yr :: PrivateNumber
yr = PrivateNumber -> PrivateNumber -> PrivateNumber -> PrivateNumber
mulF2m PrivateNumber
fx PrivateNumber
s (PrivateNumber
xp PrivateNumber -> PrivateNumber -> PrivateNumber
`addF2m` PrivateNumber
xr) PrivateNumber -> PrivateNumber -> PrivateNumber
`addF2m` PrivateNumber
xr PrivateNumber -> PrivateNumber -> PrivateNumber
`addF2m` PrivateNumber
yp
Point -> Maybe Point
forall (m :: * -> *) a. Monad m => a -> m a
return (Point -> Maybe Point) -> Point -> Maybe Point
forall a b. (a -> b) -> a -> b
$ PrivateNumber -> PrivateNumber -> Point
Point PrivateNumber
xr PrivateNumber
yr
where a :: PrivateNumber
a = CurveCommon -> PrivateNumber
ecc_a CurveCommon
cc
pointDouble :: Curve -> Point -> Point
pointDouble :: Curve -> Point -> Point
pointDouble Curve
_ Point
PointO = Point
PointO
pointDouble (CurveFP (CurvePrime PrivateNumber
pr CurveCommon
cc)) (Point PrivateNumber
xp PrivateNumber
yp) = Point -> Maybe Point -> Point
forall a. a -> Maybe a -> a
fromMaybe Point
PointO (Maybe Point -> Point) -> Maybe Point -> Point
forall a b. (a -> b) -> a -> b
$ do
PrivateNumber
lambda <- PrivateNumber
-> PrivateNumber -> PrivateNumber -> Maybe PrivateNumber
divmod (PrivateNumber
3 PrivateNumber -> PrivateNumber -> PrivateNumber
forall a. Num a => a -> a -> a
* PrivateNumber
xp PrivateNumber -> Int -> PrivateNumber
forall a b. (Num a, Integral b) => a -> b -> a
^ (Int
2::Int) PrivateNumber -> PrivateNumber -> PrivateNumber
forall a. Num a => a -> a -> a
+ PrivateNumber
a) (PrivateNumber
2 PrivateNumber -> PrivateNumber -> PrivateNumber
forall a. Num a => a -> a -> a
* PrivateNumber
yp) PrivateNumber
pr
let xr :: PrivateNumber
xr = (PrivateNumber
lambda PrivateNumber -> Int -> PrivateNumber
forall a b. (Num a, Integral b) => a -> b -> a
^ (Int
2::Int) PrivateNumber -> PrivateNumber -> PrivateNumber
forall a. Num a => a -> a -> a
- PrivateNumber
2 PrivateNumber -> PrivateNumber -> PrivateNumber
forall a. Num a => a -> a -> a
* PrivateNumber
xp) PrivateNumber -> PrivateNumber -> PrivateNumber
forall a. Integral a => a -> a -> a
`mod` PrivateNumber
pr
yr :: PrivateNumber
yr = (PrivateNumber
lambda PrivateNumber -> PrivateNumber -> PrivateNumber
forall a. Num a => a -> a -> a
* (PrivateNumber
xp PrivateNumber -> PrivateNumber -> PrivateNumber
forall a. Num a => a -> a -> a
- PrivateNumber
xr) PrivateNumber -> PrivateNumber -> PrivateNumber
forall a. Num a => a -> a -> a
- PrivateNumber
yp) PrivateNumber -> PrivateNumber -> PrivateNumber
forall a. Integral a => a -> a -> a
`mod` PrivateNumber
pr
Point -> Maybe Point
forall (m :: * -> *) a. Monad m => a -> m a
return (Point -> Maybe Point) -> Point -> Maybe Point
forall a b. (a -> b) -> a -> b
$ PrivateNumber -> PrivateNumber -> Point
Point PrivateNumber
xr PrivateNumber
yr
where a :: PrivateNumber
a = CurveCommon -> PrivateNumber
ecc_a CurveCommon
cc
pointDouble (CurveF2m (CurveBinary PrivateNumber
fx CurveCommon
cc)) (Point PrivateNumber
xp PrivateNumber
yp)
| PrivateNumber
xp PrivateNumber -> PrivateNumber -> Bool
forall a. Eq a => a -> a -> Bool
== PrivateNumber
0 = Point
PointO
| Bool
otherwise = Point -> Maybe Point -> Point
forall a. a -> Maybe a -> a
fromMaybe Point
PointO (Maybe Point -> Point) -> Maybe Point -> Point
forall a b. (a -> b) -> a -> b
$ do
PrivateNumber
s <- PrivateNumber -> Maybe PrivateNumber
forall (m :: * -> *) a. Monad m => a -> m a
return (PrivateNumber -> Maybe PrivateNumber)
-> (PrivateNumber -> PrivateNumber)
-> PrivateNumber
-> Maybe PrivateNumber
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PrivateNumber -> PrivateNumber -> PrivateNumber
addF2m PrivateNumber
xp (PrivateNumber -> Maybe PrivateNumber)
-> Maybe PrivateNumber -> Maybe PrivateNumber
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< PrivateNumber
-> PrivateNumber -> PrivateNumber -> Maybe PrivateNumber
divF2m PrivateNumber
fx PrivateNumber
yp PrivateNumber
xp
let xr :: PrivateNumber
xr = PrivateNumber -> PrivateNumber -> PrivateNumber -> PrivateNumber
mulF2m PrivateNumber
fx PrivateNumber
s PrivateNumber
s PrivateNumber -> PrivateNumber -> PrivateNumber
`addF2m` PrivateNumber
s PrivateNumber -> PrivateNumber -> PrivateNumber
`addF2m` PrivateNumber
a
yr :: PrivateNumber
yr = PrivateNumber -> PrivateNumber -> PrivateNumber -> PrivateNumber
mulF2m PrivateNumber
fx PrivateNumber
xp PrivateNumber
xp PrivateNumber -> PrivateNumber -> PrivateNumber
`addF2m` PrivateNumber -> PrivateNumber -> PrivateNumber -> PrivateNumber
mulF2m PrivateNumber
fx PrivateNumber
xr (PrivateNumber
s PrivateNumber -> PrivateNumber -> PrivateNumber
`addF2m` PrivateNumber
1)
Point -> Maybe Point
forall (m :: * -> *) a. Monad m => a -> m a
return (Point -> Maybe Point) -> Point -> Maybe Point
forall a b. (a -> b) -> a -> b
$ PrivateNumber -> PrivateNumber -> Point
Point PrivateNumber
xr PrivateNumber
yr
where a :: PrivateNumber
a = CurveCommon -> PrivateNumber
ecc_a CurveCommon
cc
pointBaseMul :: Curve -> Integer -> Point
pointBaseMul :: Curve -> PrivateNumber -> Point
pointBaseMul Curve
c PrivateNumber
n = Curve -> PrivateNumber -> Point -> Point
pointMul Curve
c PrivateNumber
n (CurveCommon -> Point
ecc_g (CurveCommon -> Point) -> CurveCommon -> Point
forall a b. (a -> b) -> a -> b
$ Curve -> CurveCommon
common_curve Curve
c)
pointMul :: Curve -> Integer -> Point -> Point
pointMul :: Curve -> PrivateNumber -> Point -> Point
pointMul Curve
_ PrivateNumber
_ Point
PointO = Point
PointO
pointMul Curve
c PrivateNumber
n Point
p
| PrivateNumber
n PrivateNumber -> PrivateNumber -> Bool
forall a. Ord a => a -> a -> Bool
< PrivateNumber
0 = Curve -> PrivateNumber -> Point -> Point
pointMul Curve
c (-PrivateNumber
n) (Curve -> Point -> Point
pointNegate Curve
c Point
p)
| PrivateNumber
n PrivateNumber -> PrivateNumber -> Bool
forall a. Eq a => a -> a -> Bool
== PrivateNumber
0 = Point
PointO
| PrivateNumber
n PrivateNumber -> PrivateNumber -> Bool
forall a. Eq a => a -> a -> Bool
== PrivateNumber
1 = Point
p
| PrivateNumber -> Bool
forall a. Integral a => a -> Bool
odd PrivateNumber
n = Curve -> Point -> Point -> Point
pointAdd Curve
c Point
p (Curve -> PrivateNumber -> Point -> Point
pointMul Curve
c (PrivateNumber
n PrivateNumber -> PrivateNumber -> PrivateNumber
forall a. Num a => a -> a -> a
- PrivateNumber
1) Point
p)
| Bool
otherwise = Curve -> PrivateNumber -> Point -> Point
pointMul Curve
c (PrivateNumber
n PrivateNumber -> PrivateNumber -> PrivateNumber
forall a. Integral a => a -> a -> a
`div` PrivateNumber
2) (Curve -> Point -> Point
pointDouble Curve
c Point
p)
pointAddTwoMuls :: Curve -> Integer -> Point -> Integer -> Point -> Point
pointAddTwoMuls :: Curve -> PrivateNumber -> Point -> PrivateNumber -> Point -> Point
pointAddTwoMuls Curve
_ PrivateNumber
_ Point
PointO PrivateNumber
_ Point
PointO = Point
PointO
pointAddTwoMuls Curve
c PrivateNumber
_ Point
PointO PrivateNumber
n2 Point
p2 = Curve -> PrivateNumber -> Point -> Point
pointMul Curve
c PrivateNumber
n2 Point
p2
pointAddTwoMuls Curve
c PrivateNumber
n1 Point
p1 PrivateNumber
_ Point
PointO = Curve -> PrivateNumber -> Point -> Point
pointMul Curve
c PrivateNumber
n1 Point
p1
pointAddTwoMuls Curve
c PrivateNumber
n1 Point
p1 PrivateNumber
n2 Point
p2
| PrivateNumber
n1 PrivateNumber -> PrivateNumber -> Bool
forall a. Ord a => a -> a -> Bool
< PrivateNumber
0 = Curve -> PrivateNumber -> Point -> PrivateNumber -> Point -> Point
pointAddTwoMuls Curve
c (-PrivateNumber
n1) (Curve -> Point -> Point
pointNegate Curve
c Point
p1) PrivateNumber
n2 Point
p2
| PrivateNumber
n2 PrivateNumber -> PrivateNumber -> Bool
forall a. Ord a => a -> a -> Bool
< PrivateNumber
0 = Curve -> PrivateNumber -> Point -> PrivateNumber -> Point -> Point
pointAddTwoMuls Curve
c PrivateNumber
n1 Point
p1 (-PrivateNumber
n2) (Curve -> Point -> Point
pointNegate Curve
c Point
p2)
| Bool
otherwise = (PrivateNumber, PrivateNumber) -> Point
forall a a. (Integral a, Integral a) => (a, a) -> Point
go (PrivateNumber
n1, PrivateNumber
n2)
where
p0 :: Point
p0 = Curve -> Point -> Point -> Point
pointAdd Curve
c Point
p1 Point
p2
go :: (a, a) -> Point
go (a
0, a
0 ) = Point
PointO
go (a
k1, a
k2) =
let q :: Point
q = Curve -> Point -> Point
pointDouble Curve
c (Point -> Point) -> Point -> Point
forall a b. (a -> b) -> a -> b
$ (a, a) -> Point
go (a
k1 a -> a -> a
forall a. Integral a => a -> a -> a
`div` a
2, a
k2 a -> a -> a
forall a. Integral a => a -> a -> a
`div` a
2)
in case (a -> Bool
forall a. Integral a => a -> Bool
odd a
k1, a -> Bool
forall a. Integral a => a -> Bool
odd a
k2) of
(Bool
True , Bool
True ) -> Curve -> Point -> Point -> Point
pointAdd Curve
c Point
p0 Point
q
(Bool
True , Bool
False ) -> Curve -> Point -> Point -> Point
pointAdd Curve
c Point
p1 Point
q
(Bool
False , Bool
True ) -> Curve -> Point -> Point -> Point
pointAdd Curve
c Point
p2 Point
q
(Bool
False , Bool
False ) -> Point
q
isPointAtInfinity :: Point -> Bool
isPointAtInfinity :: Point -> Bool
isPointAtInfinity Point
PointO = Bool
True
isPointAtInfinity Point
_ = Bool
False
isPointValid :: Curve -> Point -> Bool
isPointValid :: Curve -> Point -> Bool
isPointValid Curve
_ Point
PointO = Bool
True
isPointValid (CurveFP (CurvePrime PrivateNumber
p CurveCommon
cc)) (Point PrivateNumber
x PrivateNumber
y) =
PrivateNumber -> Bool
isValid PrivateNumber
x Bool -> Bool -> Bool
&& PrivateNumber -> Bool
isValid PrivateNumber
y Bool -> Bool -> Bool
&& (PrivateNumber
y PrivateNumber -> Int -> PrivateNumber
forall a b. (Num a, Integral b) => a -> b -> a
^ (Int
2 :: Int)) PrivateNumber -> PrivateNumber -> Bool
`eqModP` (PrivateNumber
x PrivateNumber -> Int -> PrivateNumber
forall a b. (Num a, Integral b) => a -> b -> a
^ (Int
3 :: Int) PrivateNumber -> PrivateNumber -> PrivateNumber
forall a. Num a => a -> a -> a
+ PrivateNumber
a PrivateNumber -> PrivateNumber -> PrivateNumber
forall a. Num a => a -> a -> a
* PrivateNumber
x PrivateNumber -> PrivateNumber -> PrivateNumber
forall a. Num a => a -> a -> a
+ PrivateNumber
b)
where a :: PrivateNumber
a = CurveCommon -> PrivateNumber
ecc_a CurveCommon
cc
b :: PrivateNumber
b = CurveCommon -> PrivateNumber
ecc_b CurveCommon
cc
eqModP :: PrivateNumber -> PrivateNumber -> Bool
eqModP PrivateNumber
z1 PrivateNumber
z2 = (PrivateNumber
z1 PrivateNumber -> PrivateNumber -> PrivateNumber
forall a. Integral a => a -> a -> a
`mod` PrivateNumber
p) PrivateNumber -> PrivateNumber -> Bool
forall a. Eq a => a -> a -> Bool
== (PrivateNumber
z2 PrivateNumber -> PrivateNumber -> PrivateNumber
forall a. Integral a => a -> a -> a
`mod` PrivateNumber
p)
isValid :: PrivateNumber -> Bool
isValid PrivateNumber
e = PrivateNumber
e PrivateNumber -> PrivateNumber -> Bool
forall a. Ord a => a -> a -> Bool
>= PrivateNumber
0 Bool -> Bool -> Bool
&& PrivateNumber
e PrivateNumber -> PrivateNumber -> Bool
forall a. Ord a => a -> a -> Bool
< PrivateNumber
p
isPointValid (CurveF2m (CurveBinary PrivateNumber
fx CurveCommon
cc)) (Point PrivateNumber
x PrivateNumber
y) =
[Bool] -> Bool
forall (t :: * -> *). Foldable t => t Bool -> Bool
and [ PrivateNumber -> Bool
isValid PrivateNumber
x
, PrivateNumber -> Bool
isValid PrivateNumber
y
, ((((PrivateNumber
x PrivateNumber -> PrivateNumber -> PrivateNumber
`add` PrivateNumber
a) PrivateNumber -> PrivateNumber -> PrivateNumber
`mul` PrivateNumber
x PrivateNumber -> PrivateNumber -> PrivateNumber
`add` PrivateNumber
y) PrivateNumber -> PrivateNumber -> PrivateNumber
`mul` PrivateNumber
x) PrivateNumber -> PrivateNumber -> PrivateNumber
`add` PrivateNumber
b PrivateNumber -> PrivateNumber -> PrivateNumber
`add` (PrivateNumber -> PrivateNumber -> PrivateNumber
squareF2m PrivateNumber
fx PrivateNumber
y)) PrivateNumber -> PrivateNumber -> Bool
forall a. Eq a => a -> a -> Bool
== PrivateNumber
0
]
where a :: PrivateNumber
a = CurveCommon -> PrivateNumber
ecc_a CurveCommon
cc
b :: PrivateNumber
b = CurveCommon -> PrivateNumber
ecc_b CurveCommon
cc
add :: PrivateNumber -> PrivateNumber -> PrivateNumber
add = PrivateNumber -> PrivateNumber -> PrivateNumber
addF2m
mul :: PrivateNumber -> PrivateNumber -> PrivateNumber
mul = PrivateNumber -> PrivateNumber -> PrivateNumber -> PrivateNumber
mulF2m PrivateNumber
fx
isValid :: PrivateNumber -> Bool
isValid PrivateNumber
e = PrivateNumber -> PrivateNumber -> PrivateNumber
modF2m PrivateNumber
fx PrivateNumber
e PrivateNumber -> PrivateNumber -> Bool
forall a. Eq a => a -> a -> Bool
== PrivateNumber
e
divmod :: Integer -> Integer -> Integer -> Maybe Integer
divmod :: PrivateNumber
-> PrivateNumber -> PrivateNumber -> Maybe PrivateNumber
divmod PrivateNumber
y PrivateNumber
x PrivateNumber
m = do
PrivateNumber
i <- PrivateNumber -> PrivateNumber -> Maybe PrivateNumber
inverse (PrivateNumber
x PrivateNumber -> PrivateNumber -> PrivateNumber
forall a. Integral a => a -> a -> a
`mod` PrivateNumber
m) PrivateNumber
m
PrivateNumber -> Maybe PrivateNumber
forall (m :: * -> *) a. Monad m => a -> m a
return (PrivateNumber -> Maybe PrivateNumber)
-> PrivateNumber -> Maybe PrivateNumber
forall a b. (a -> b) -> a -> b
$ PrivateNumber
y PrivateNumber -> PrivateNumber -> PrivateNumber
forall a. Num a => a -> a -> a
* PrivateNumber
i PrivateNumber -> PrivateNumber -> PrivateNumber
forall a. Integral a => a -> a -> a
`mod` PrivateNumber
m