module Crypto.PubKey.ECC.DH (
    Curve
  , PublicPoint
  , PrivateNumber
  , SharedKey(..)
  , generatePrivate
  , calculatePublic
  , getShared
  ) where

import Crypto.Number.Generate (generateMax)
import Crypto.PubKey.ECC.Prim (pointMul)
import Crypto.Random (CPRG)
import Crypto.Types.PubKey.DH (SharedKey(..))
import Crypto.Types.PubKey.ECC (PublicPoint, PrivateNumber, Curve, Point(..))
import Crypto.Types.PubKey.ECC (ecc_n, ecc_g, common_curve)

-- | Generating a private number d.
generatePrivate :: CPRG g => g -> Curve -> (PrivateNumber, g)
generatePrivate :: g -> Curve -> (PrivateNumber, g)
generatePrivate rng :: g
rng curve :: Curve
curve = g -> PrivateNumber -> (PrivateNumber, g)
forall g. CPRG g => g -> PrivateNumber -> (PrivateNumber, g)
generateMax g
rng PrivateNumber
n
  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

-- | Generating a public point Q.
calculatePublic :: Curve -> PrivateNumber -> PublicPoint
calculatePublic :: Curve -> PrivateNumber -> PublicPoint
calculatePublic curve :: Curve
curve d :: PrivateNumber
d = PublicPoint
q
  where
    g :: PublicPoint
g = CurveCommon -> PublicPoint
ecc_g (CurveCommon -> PublicPoint) -> CurveCommon -> PublicPoint
forall a b. (a -> b) -> a -> b
$ Curve -> CurveCommon
common_curve Curve
curve
    q :: PublicPoint
q = Curve -> PrivateNumber -> PublicPoint -> PublicPoint
pointMul Curve
curve PrivateNumber
d PublicPoint
g

-- | Generating a shared key using our private number and
--   the other party public point.
getShared :: Curve -> PrivateNumber -> PublicPoint -> SharedKey
getShared :: Curve -> PrivateNumber -> PublicPoint -> SharedKey
getShared curve :: Curve
curve db :: PrivateNumber
db qa :: PublicPoint
qa = PrivateNumber -> SharedKey
SharedKey PrivateNumber
x
  where
    Point x :: PrivateNumber
x _ = Curve -> PrivateNumber -> PublicPoint -> PublicPoint
pointMul Curve
curve PrivateNumber
db PublicPoint
qa