{-# LANGUAGE ScopedTypeVariables #-}
module Crypto.ECC.Simple.Prim
( scalarGenerate
, scalarFromInteger
, pointAdd
, pointNegate
, pointDouble
, pointBaseMul
, pointMul
, pointAddTwoMuls
, pointFromIntegers
, isPointAtInfinity
, isPointValid
) where
import Data.Maybe
import Data.Proxy
import Crypto.Number.ModArithmetic
import Crypto.Number.F2m
import Crypto.Number.Generate (generateBetween)
import Crypto.ECC.Simple.Types
import Crypto.Error
import Crypto.Random
scalarGenerate :: forall randomly curve . (MonadRandom randomly, Curve curve) => randomly (Scalar curve)
scalarGenerate :: forall (randomly :: * -> *) curve.
(MonadRandom randomly, Curve curve) =>
randomly (Scalar curve)
scalarGenerate =
forall curve. Integer -> Scalar curve
Scalar forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (m :: * -> *).
MonadRandom m =>
Integer -> Integer -> m Integer
generateBetween Integer
1 (Integer
n forall a. Num a => a -> a -> a
- Integer
1)
where
n :: Integer
n = forall curve. CurveParameters curve -> Integer
curveEccN forall a b. (a -> b) -> a -> b
$ forall curve (proxy :: * -> *).
Curve curve =>
proxy curve -> CurveParameters curve
curveParameters (forall {k} (t :: k). Proxy t
Proxy :: Proxy curve)
scalarFromInteger :: forall curve . Curve curve => Integer -> CryptoFailable (Scalar curve)
scalarFromInteger :: forall curve.
Curve curve =>
Integer -> CryptoFailable (Scalar curve)
scalarFromInteger Integer
n
| Integer
n forall a. Ord a => a -> a -> Bool
< Integer
0 Bool -> Bool -> Bool
|| Integer
n forall a. Ord a => a -> a -> Bool
>= Integer
mx = forall a. CryptoError -> CryptoFailable a
CryptoFailed forall a b. (a -> b) -> a -> b
$ CryptoError
CryptoError_EcScalarOutOfBounds
| Bool
otherwise = forall a. a -> CryptoFailable a
CryptoPassed forall a b. (a -> b) -> a -> b
$ forall curve. Integer -> Scalar curve
Scalar Integer
n
where
mx :: Integer
mx = case forall curve (proxy :: * -> *).
Curve curve =>
proxy curve -> CurveType
curveType (forall {k} (t :: k). Proxy t
Proxy :: Proxy curve) of
CurveBinary (CurveBinaryParam Integer
b) -> Integer
b
CurvePrime (CurvePrimeParam Integer
p) -> Integer
p
pointNegate :: Curve curve => Point curve -> Point curve
pointNegate :: forall curve. Curve curve => Point curve -> Point curve
pointNegate Point curve
PointO = forall curve. Point curve
PointO
pointNegate point :: Point curve
point@(Point Integer
x Integer
y) =
case forall curve (proxy :: * -> *).
Curve curve =>
proxy curve -> CurveType
curveType Point curve
point of
CurvePrime (CurvePrimeParam Integer
p) -> forall curve. Integer -> Integer -> Point curve
Point Integer
x (Integer
p forall a. Num a => a -> a -> a
- Integer
y)
CurveBinary {} -> forall curve. Integer -> Integer -> Point curve
Point Integer
x (Integer
x Integer -> Integer -> Integer
`addF2m` Integer
y)
pointAdd :: Curve curve => Point curve -> Point curve -> Point curve
pointAdd :: forall curve.
Curve curve =>
Point curve -> Point curve -> Point curve
pointAdd Point curve
PointO Point curve
PointO = forall curve. Point curve
PointO
pointAdd Point curve
PointO Point curve
q = Point curve
q
pointAdd Point curve
p Point curve
PointO = Point curve
p
pointAdd Point curve
p Point curve
q
| Point curve
p forall a. Eq a => a -> a -> Bool
== Point curve
q = forall curve. Curve curve => Point curve -> Point curve
pointDouble Point curve
p
| Point curve
p forall a. Eq a => a -> a -> Bool
== forall curve. Curve curve => Point curve -> Point curve
pointNegate Point curve
q = forall curve. Point curve
PointO
pointAdd point :: Point curve
point@(Point Integer
xp Integer
yp) (Point Integer
xq Integer
yq) =
case CurveType
ty of
CurvePrime (CurvePrimeParam Integer
pr) -> forall a. a -> Maybe a -> a
fromMaybe forall curve. Point curve
PointO forall a b. (a -> b) -> a -> b
$ do
Integer
s <- Integer -> Integer -> Integer -> Maybe Integer
divmod (Integer
yp forall a. Num a => a -> a -> a
- Integer
yq) (Integer
xp forall a. Num a => a -> a -> a
- Integer
xq) Integer
pr
let xr :: Integer
xr = (Integer
s forall a b. (Num a, Integral b) => a -> b -> a
^ (Int
2::Int) forall a. Num a => a -> a -> a
- Integer
xp forall a. Num a => a -> a -> a
- Integer
xq) forall a. Integral a => a -> a -> a
`mod` Integer
pr
yr :: Integer
yr = (Integer
s forall a. Num a => a -> a -> a
* (Integer
xp forall a. Num a => a -> a -> a
- Integer
xr) forall a. Num a => a -> a -> a
- Integer
yp) forall a. Integral a => a -> a -> a
`mod` Integer
pr
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall curve. Integer -> Integer -> Point curve
Point Integer
xr Integer
yr
CurveBinary (CurveBinaryParam Integer
fx) -> forall a. a -> Maybe a -> a
fromMaybe forall curve. Point curve
PointO forall a b. (a -> b) -> a -> b
$ do
Integer
s <- Integer -> Integer -> Integer -> Maybe Integer
divF2m Integer
fx (Integer
yp Integer -> Integer -> Integer
`addF2m` Integer
yq) (Integer
xp Integer -> Integer -> Integer
`addF2m` Integer
xq)
let xr :: Integer
xr = Integer -> Integer -> Integer -> Integer
mulF2m Integer
fx Integer
s Integer
s Integer -> Integer -> Integer
`addF2m` Integer
s Integer -> Integer -> Integer
`addF2m` Integer
xp Integer -> Integer -> Integer
`addF2m` Integer
xq Integer -> Integer -> Integer
`addF2m` Integer
a
yr :: Integer
yr = Integer -> Integer -> Integer -> Integer
mulF2m Integer
fx Integer
s (Integer
xp Integer -> Integer -> Integer
`addF2m` Integer
xr) Integer -> Integer -> Integer
`addF2m` Integer
xr Integer -> Integer -> Integer
`addF2m` Integer
yp
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall curve. Integer -> Integer -> Point curve
Point Integer
xr Integer
yr
where
ty :: CurveType
ty = forall curve (proxy :: * -> *).
Curve curve =>
proxy curve -> CurveType
curveType Point curve
point
cc :: CurveParameters curve
cc = forall curve (proxy :: * -> *).
Curve curve =>
proxy curve -> CurveParameters curve
curveParameters Point curve
point
a :: Integer
a = forall curve. CurveParameters curve -> Integer
curveEccA CurveParameters curve
cc
pointDouble :: Curve curve => Point curve -> Point curve
pointDouble :: forall curve. Curve curve => Point curve -> Point curve
pointDouble Point curve
PointO = forall curve. Point curve
PointO
pointDouble point :: Point curve
point@(Point Integer
xp Integer
yp) =
case CurveType
ty of
CurvePrime (CurvePrimeParam Integer
pr) -> forall a. a -> Maybe a -> a
fromMaybe forall curve. Point curve
PointO forall a b. (a -> b) -> a -> b
$ do
Integer
lambda <- Integer -> Integer -> Integer -> Maybe Integer
divmod (Integer
3 forall a. Num a => a -> a -> a
* Integer
xp forall a b. (Num a, Integral b) => a -> b -> a
^ (Int
2::Int) forall a. Num a => a -> a -> a
+ Integer
a) (Integer
2 forall a. Num a => a -> a -> a
* Integer
yp) Integer
pr
let xr :: Integer
xr = (Integer
lambda forall a b. (Num a, Integral b) => a -> b -> a
^ (Int
2::Int) forall a. Num a => a -> a -> a
- Integer
2 forall a. Num a => a -> a -> a
* Integer
xp) forall a. Integral a => a -> a -> a
`mod` Integer
pr
yr :: Integer
yr = (Integer
lambda forall a. Num a => a -> a -> a
* (Integer
xp forall a. Num a => a -> a -> a
- Integer
xr) forall a. Num a => a -> a -> a
- Integer
yp) forall a. Integral a => a -> a -> a
`mod` Integer
pr
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall curve. Integer -> Integer -> Point curve
Point Integer
xr Integer
yr
CurveBinary (CurveBinaryParam Integer
fx)
| Integer
xp forall a. Eq a => a -> a -> Bool
== Integer
0 -> forall curve. Point curve
PointO
| Bool
otherwise -> forall a. a -> Maybe a -> a
fromMaybe forall curve. Point curve
PointO forall a b. (a -> b) -> a -> b
$ do
Integer
s <- forall (m :: * -> *) a. Monad m => a -> m a
return forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> Integer -> Integer
addF2m Integer
xp forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Integer -> Integer -> Integer -> Maybe Integer
divF2m Integer
fx Integer
yp Integer
xp
let xr :: Integer
xr = Integer -> Integer -> Integer -> Integer
mulF2m Integer
fx Integer
s Integer
s Integer -> Integer -> Integer
`addF2m` Integer
s Integer -> Integer -> Integer
`addF2m` Integer
a
yr :: Integer
yr = Integer -> Integer -> Integer -> Integer
mulF2m Integer
fx Integer
xp Integer
xp Integer -> Integer -> Integer
`addF2m` Integer -> Integer -> Integer -> Integer
mulF2m Integer
fx Integer
xr (Integer
s Integer -> Integer -> Integer
`addF2m` Integer
1)
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall curve. Integer -> Integer -> Point curve
Point Integer
xr Integer
yr
where
ty :: CurveType
ty = forall curve (proxy :: * -> *).
Curve curve =>
proxy curve -> CurveType
curveType Point curve
point
cc :: CurveParameters curve
cc = forall curve (proxy :: * -> *).
Curve curve =>
proxy curve -> CurveParameters curve
curveParameters Point curve
point
a :: Integer
a = forall curve. CurveParameters curve -> Integer
curveEccA CurveParameters curve
cc
pointBaseMul :: Curve curve => Scalar curve -> Point curve
pointBaseMul :: forall curve. Curve curve => Scalar curve -> Point curve
pointBaseMul Scalar curve
n = forall curve.
Curve curve =>
Scalar curve -> Point curve -> Point curve
pointMul Scalar curve
n (forall curve. CurveParameters curve -> Point curve
curveEccG forall a b. (a -> b) -> a -> b
$ forall curve (proxy :: * -> *).
Curve curve =>
proxy curve -> CurveParameters curve
curveParameters (forall {k} (t :: k). Proxy t
Proxy :: Proxy curve))
pointMul :: Curve curve => Scalar curve -> Point curve -> Point curve
pointMul :: forall curve.
Curve curve =>
Scalar curve -> Point curve -> Point curve
pointMul Scalar curve
_ Point curve
PointO = forall curve. Point curve
PointO
pointMul (Scalar Integer
n) Point curve
p
| Integer
n forall a. Eq a => a -> a -> Bool
== Integer
0 = forall curve. Point curve
PointO
| Integer
n forall a. Eq a => a -> a -> Bool
== Integer
1 = Point curve
p
| forall a. Integral a => a -> Bool
odd Integer
n = forall curve.
Curve curve =>
Point curve -> Point curve -> Point curve
pointAdd Point curve
p (forall curve.
Curve curve =>
Scalar curve -> Point curve -> Point curve
pointMul (forall curve. Integer -> Scalar curve
Scalar (Integer
n forall a. Num a => a -> a -> a
- Integer
1)) Point curve
p)
| Bool
otherwise = forall curve.
Curve curve =>
Scalar curve -> Point curve -> Point curve
pointMul (forall curve. Integer -> Scalar curve
Scalar (Integer
n forall a. Integral a => a -> a -> a
`div` Integer
2)) (forall curve. Curve curve => Point curve -> Point curve
pointDouble Point curve
p)
pointAddTwoMuls :: Curve curve => Scalar curve -> Point curve -> Scalar curve -> Point curve -> Point curve
pointAddTwoMuls :: forall curve.
Curve curve =>
Scalar curve
-> Point curve -> Scalar curve -> Point curve -> Point curve
pointAddTwoMuls Scalar curve
_ Point curve
PointO Scalar curve
_ Point curve
PointO = forall curve. Point curve
PointO
pointAddTwoMuls Scalar curve
_ Point curve
PointO Scalar curve
n2 Point curve
p2 = forall curve.
Curve curve =>
Scalar curve -> Point curve -> Point curve
pointMul Scalar curve
n2 Point curve
p2
pointAddTwoMuls Scalar curve
n1 Point curve
p1 Scalar curve
_ Point curve
PointO = forall curve.
Curve curve =>
Scalar curve -> Point curve -> Point curve
pointMul Scalar curve
n1 Point curve
p1
pointAddTwoMuls (Scalar Integer
n1) Point curve
p1 (Scalar Integer
n2) Point curve
p2 = forall {a} {a}. (Integral a, Integral a) => (a, a) -> Point curve
go (Integer
n1, Integer
n2)
where
p0 :: Point curve
p0 = forall curve.
Curve curve =>
Point curve -> Point curve -> Point curve
pointAdd Point curve
p1 Point curve
p2
go :: (a, a) -> Point curve
go (a
0, a
0 ) = forall curve. Point curve
PointO
go (a
k1, a
k2) =
let q :: Point curve
q = forall curve. Curve curve => Point curve -> Point curve
pointDouble forall a b. (a -> b) -> a -> b
$ (a, a) -> Point curve
go (a
k1 forall a. Integral a => a -> a -> a
`div` a
2, a
k2 forall a. Integral a => a -> a -> a
`div` a
2)
in case (forall a. Integral a => a -> Bool
odd a
k1, forall a. Integral a => a -> Bool
odd a
k2) of
(Bool
True , Bool
True ) -> forall curve.
Curve curve =>
Point curve -> Point curve -> Point curve
pointAdd Point curve
p0 Point curve
q
(Bool
True , Bool
False ) -> forall curve.
Curve curve =>
Point curve -> Point curve -> Point curve
pointAdd Point curve
p1 Point curve
q
(Bool
False , Bool
True ) -> forall curve.
Curve curve =>
Point curve -> Point curve -> Point curve
pointAdd Point curve
p2 Point curve
q
(Bool
False , Bool
False ) -> Point curve
q
isPointAtInfinity :: Point curve -> Bool
isPointAtInfinity :: forall curve. Point curve -> Bool
isPointAtInfinity Point curve
PointO = Bool
True
isPointAtInfinity Point curve
_ = Bool
False
pointFromIntegers :: forall curve . Curve curve => (Integer, Integer) -> CryptoFailable (Point curve)
pointFromIntegers :: forall curve.
Curve curve =>
(Integer, Integer) -> CryptoFailable (Point curve)
pointFromIntegers (Integer
x,Integer
y)
| forall curve (proxy :: * -> *).
Curve curve =>
proxy curve -> Integer -> Integer -> Bool
isPointValid (forall {k} (t :: k). Proxy t
Proxy :: Proxy curve) Integer
x Integer
y = forall a. a -> CryptoFailable a
CryptoPassed forall a b. (a -> b) -> a -> b
$ forall curve. Integer -> Integer -> Point curve
Point Integer
x Integer
y
| Bool
otherwise = forall a. CryptoError -> CryptoFailable a
CryptoFailed forall a b. (a -> b) -> a -> b
$ CryptoError
CryptoError_PointCoordinatesInvalid
isPointValid :: Curve curve => proxy curve -> Integer -> Integer -> Bool
isPointValid :: forall curve (proxy :: * -> *).
Curve curve =>
proxy curve -> Integer -> Integer -> Bool
isPointValid proxy curve
proxy Integer
x Integer
y =
case CurveType
ty of
CurvePrime (CurvePrimeParam Integer
p) ->
let a :: Integer
a = forall curve. CurveParameters curve -> Integer
curveEccA CurveParameters curve
cc
b :: Integer
b = forall curve. CurveParameters curve -> Integer
curveEccB CurveParameters curve
cc
eqModP :: Integer -> Integer -> Bool
eqModP Integer
z1 Integer
z2 = (Integer
z1 forall a. Integral a => a -> a -> a
`mod` Integer
p) forall a. Eq a => a -> a -> Bool
== (Integer
z2 forall a. Integral a => a -> a -> a
`mod` Integer
p)
isValid :: Integer -> Bool
isValid Integer
e = Integer
e forall a. Ord a => a -> a -> Bool
>= Integer
0 Bool -> Bool -> Bool
&& Integer
e forall a. Ord a => a -> a -> Bool
< Integer
p
in Integer -> Bool
isValid Integer
x Bool -> Bool -> Bool
&& Integer -> Bool
isValid Integer
y Bool -> Bool -> Bool
&& (Integer
y forall a b. (Num a, Integral b) => a -> b -> a
^ (Int
2 :: Int)) Integer -> Integer -> Bool
`eqModP` (Integer
x forall a b. (Num a, Integral b) => a -> b -> a
^ (Int
3 :: Int) forall a. Num a => a -> a -> a
+ Integer
a forall a. Num a => a -> a -> a
* Integer
x forall a. Num a => a -> a -> a
+ Integer
b)
CurveBinary (CurveBinaryParam Integer
fx) ->
let a :: Integer
a = forall curve. CurveParameters curve -> Integer
curveEccA CurveParameters curve
cc
b :: Integer
b = forall curve. CurveParameters curve -> Integer
curveEccB CurveParameters curve
cc
add :: Integer -> Integer -> Integer
add = Integer -> Integer -> Integer
addF2m
mul :: Integer -> Integer -> Integer
mul = Integer -> Integer -> Integer -> Integer
mulF2m Integer
fx
isValid :: Integer -> Bool
isValid Integer
e = Integer -> Integer -> Integer
modF2m Integer
fx Integer
e forall a. Eq a => a -> a -> Bool
== Integer
e
in forall (t :: * -> *). Foldable t => t Bool -> Bool
and [ Integer -> Bool
isValid Integer
x
, Integer -> Bool
isValid Integer
y
, ((((Integer
x Integer -> Integer -> Integer
`add` Integer
a) Integer -> Integer -> Integer
`mul` Integer
x Integer -> Integer -> Integer
`add` Integer
y) Integer -> Integer -> Integer
`mul` Integer
x) Integer -> Integer -> Integer
`add` Integer
b Integer -> Integer -> Integer
`add` (Integer -> Integer -> Integer
squareF2m Integer
fx Integer
y)) forall a. Eq a => a -> a -> Bool
== Integer
0
]
where
ty :: CurveType
ty = forall curve (proxy :: * -> *).
Curve curve =>
proxy curve -> CurveType
curveType proxy curve
proxy
cc :: CurveParameters curve
cc = forall curve (proxy :: * -> *).
Curve curve =>
proxy curve -> CurveParameters curve
curveParameters proxy curve
proxy
divmod :: Integer -> Integer -> Integer -> Maybe Integer
divmod :: Integer -> Integer -> Integer -> Maybe Integer
divmod Integer
y Integer
x Integer
m = do
Integer
i <- Integer -> Integer -> Maybe Integer
inverse (Integer
x forall a. Integral a => a -> a -> a
`mod` Integer
m) Integer
m
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Integer
y forall a. Num a => a -> a -> a
* Integer
i forall a. Integral a => a -> a -> a
`mod` Integer
m