module Crypto.PubKey.ECC.DH (
Curve,
PublicPoint,
PrivateNumber,
SharedKey (..),
generatePrivate,
calculatePublic,
getShared,
tryGetShared,
) where
import Crypto.Error (
CryptoError (..),
CryptoFailable (..),
throwCryptoError,
)
import Crypto.Number.Generate (generateMax)
import Crypto.Number.Serialize (i2ospOf_)
import Crypto.PubKey.DH (SharedKey (..))
import Crypto.PubKey.ECC.Prim (isPointInSubgroup, isPointValid, pointMul)
import Crypto.PubKey.ECC.Types (
Curve,
Point (..),
PrivateNumber,
PublicPoint,
common_curve,
curveSizeBits,
ecc_g,
ecc_n,
)
import Crypto.Random.Types
generatePrivate :: MonadRandom m => Curve -> m PrivateNumber
generatePrivate :: forall (m :: * -> *). MonadRandom m => Curve -> m PrivateNumber
generatePrivate Curve
curve = PrivateNumber -> m PrivateNumber
forall (m :: * -> *).
MonadRandom m =>
PrivateNumber -> m PrivateNumber
generateMax 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
calculatePublic :: Curve -> PrivateNumber -> PublicPoint
calculatePublic :: Curve -> PrivateNumber -> PublicPoint
calculatePublic Curve
curve 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
getShared :: Curve -> PrivateNumber -> PublicPoint -> SharedKey
getShared :: Curve -> PrivateNumber -> PublicPoint -> SharedKey
getShared Curve
curve PrivateNumber
db PublicPoint
qa = CryptoFailable SharedKey -> SharedKey
forall a. CryptoFailable a -> a
throwCryptoError (CryptoFailable SharedKey -> SharedKey)
-> CryptoFailable SharedKey -> SharedKey
forall a b. (a -> b) -> a -> b
$ Curve -> PrivateNumber -> PublicPoint -> CryptoFailable SharedKey
tryGetShared Curve
curve PrivateNumber
db PublicPoint
qa
tryGetShared :: Curve -> PrivateNumber -> PublicPoint -> CryptoFailable SharedKey
tryGetShared :: Curve -> PrivateNumber -> PublicPoint -> CryptoFailable SharedKey
tryGetShared Curve
curve PrivateNumber
db PublicPoint
qa
| Bool -> Bool
not (Curve -> PublicPoint -> Bool
isPointValid Curve
curve PublicPoint
qa) = CryptoError -> CryptoFailable SharedKey
forall a. CryptoError -> CryptoFailable a
CryptoFailed CryptoError
CryptoError_PointCoordinatesInvalid
| Bool -> Bool
not (Curve -> PublicPoint -> Bool
isPointInSubgroup Curve
curve PublicPoint
qa) = CryptoError -> CryptoFailable SharedKey
forall a. CryptoError -> CryptoFailable a
CryptoFailed CryptoError
CryptoError_PointSubgroupInvalid
| Bool
otherwise = case Curve -> PrivateNumber -> PublicPoint -> PublicPoint
pointMul Curve
curve PrivateNumber
db PublicPoint
qa of
Point PrivateNumber
x PrivateNumber
_ -> SharedKey -> CryptoFailable SharedKey
forall a. a -> CryptoFailable a
CryptoPassed (SharedKey -> CryptoFailable SharedKey)
-> SharedKey -> CryptoFailable SharedKey
forall a b. (a -> b) -> a -> b
$ ScrubbedBytes -> SharedKey
SharedKey (ScrubbedBytes -> SharedKey) -> ScrubbedBytes -> SharedKey
forall a b. (a -> b) -> a -> b
$ Int -> PrivateNumber -> ScrubbedBytes
forall ba. ByteArray ba => Int -> PrivateNumber -> ba
i2ospOf_ ((Int
nbBits Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
7) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`div` Int
8) PrivateNumber
x
PublicPoint
PointO -> CryptoError -> CryptoFailable SharedKey
forall a. CryptoError -> CryptoFailable a
CryptoFailed CryptoError
CryptoError_ScalarMultiplicationInvalid
where
nbBits :: Int
nbBits = Curve -> Int
curveSizeBits Curve
curve