bitcoin-hs-0.0.1: Bitcoin/Crypto/EC/DiffieHellman.hs
-- | Diffie-Hellman key exchange
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Bitcoin.Crypto.EC.DiffieHellman where
--------------------------------------------------------------------------------
import Data.Word
import Bitcoin.Misc.OctetStream
import Bitcoin.Crypto.Word256
import Bitcoin.Crypto.FiniteField.Fast.Fp
import Bitcoin.Crypto.EC.Curve
import Bitcoin.Crypto.EC.Projective
import Bitcoin.Crypto.EC.Key
--------------------------------------------------------------------------------
newtype SharedSecret = SharedSecret [Word8] deriving (Eq,Ord,Show,OctetStream)
--------------------------------------------------------------------------------
-- | Given your private key and somebody else's public key, this compute
-- a (256 bit) shared secret.
--
-- This is actually very simple: since @pubkey = G * privkey@, the shared
-- secret will be simply @G * privkey1 * privkey2@.
--
-- This can fail if for example an invalid pubkey is given, and
-- in some other special circumstances.
--
diffieHellmanPrimitive :: PrivKey -> PubKey -> Maybe SharedSecret
diffieHellmanPrimitive (PrivKey d) pk =
case uncompressPubKey pk of
Nothing -> Nothing
Just full@(FullPubKey x y) -> case isValidPubKey full of
False -> Nothing
True -> case fromECProj (mulECP (toECProj $ mkECPoint x y) d) of
ECInfinity -> Nothing
ECPoint zx zy -> Just (SharedSecret $ word256ToWord8ListLE $ unFp zx) -- zx=0 doesn't seem to be on the curve, so this is always nonzero
_ -> Nothing -- shouldn't happen, but totality is always good.
--------------------------------------------------------------------------------