-- | Signature generation.
module Crypto.PubKey.ECC.Generate where

import Crypto.Random.Types
import Crypto.PubKey.ECC.Types
import Crypto.PubKey.ECC.ECDSA
import Crypto.Number.Generate
import Crypto.PubKey.ECC.Prim

-- | Generate Q given d.
--
-- /WARNING:/ Vulnerable to timing attacks.
generateQ :: Curve
          -> Integer
          -> Point
generateQ :: Curve -> Integer -> Point
generateQ Curve
curve Integer
d = Curve -> Integer -> Point -> Point
pointMul Curve
curve Integer
d Point
g
  where g :: Point
g = CurveCommon -> Point
ecc_g (CurveCommon -> Point) -> CurveCommon -> Point
forall a b. (a -> b) -> a -> b
$ Curve -> CurveCommon
common_curve Curve
curve

-- | Generate a pair of (private, public) key.
--
-- /WARNING:/ Vulnerable to timing attacks.
generate :: MonadRandom m
         => Curve -- ^ Elliptic Curve
         -> m (PublicKey, PrivateKey)
generate :: forall (m :: * -> *).
MonadRandom m =>
Curve -> m (PublicKey, PrivateKey)
generate Curve
curve = do
    Integer
d <- Integer -> Integer -> m Integer
forall (m :: * -> *).
MonadRandom m =>
Integer -> Integer -> m Integer
generateBetween Integer
1 (Integer
n Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
1)
    let q :: Point
q = Curve -> Integer -> Point
generateQ Curve
curve Integer
d
    (PublicKey, PrivateKey) -> m (PublicKey, PrivateKey)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Curve -> Point -> PublicKey
PublicKey Curve
curve Point
q, Curve -> Integer -> PrivateKey
PrivateKey Curve
curve Integer
d)
  where
        n :: Integer
n = CurveCommon -> Integer
ecc_n (CurveCommon -> Integer) -> CurveCommon -> Integer
forall a b. (a -> b) -> a -> b
$ Curve -> CurveCommon
common_curve Curve
curve