    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