    -- |
    -- Module      : Crypto.PubKey.ECC.DH
    -- License     : BSD-style
    -- Maintainer  : Vincent Hanquez <vincent@snarc.org>
    -- Stability   : experimental
    -- Portability : unknown
    --
    -- Elliptic curve Diffie Hellman
    --
    module Crypto.PubKey.ECC.DH
        (
          Curve
        , PublicPoint
        , PrivateNumber
        , SharedKey(..)
        , generatePrivate
        , calculatePublic
        , getShared
        ) where

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

    -- | Generating a private number d.
    generatePrivate :: MonadRandom m => Curve -> m PrivateNumber
    generatePrivate curve = generateMax n
      where
        n = ecc_n $ common_curve curve

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

    -- | Generating a shared key using our private number and
    --   the other party public point.
    getShared :: Curve -> PrivateNumber -> PublicPoint -> SharedKey
    getShared curve db qa = SharedKey $ i2ospOf_ ((nbBits + 7) `div` 8) x
      where
        Point x _ = pointMul curve db qa
        nbBits    = curveSizeBits curve