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

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

-- | 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