module Botan.PubKey.KeyAgreement where

import qualified Data.ByteString as ByteString

import Data.Bool

import Botan.Low.PubKey (PubKey(..), PrivKey(..))
import qualified Botan.Low.PubKey.KeyAgreement as Low
import qualified Botan.Low.RNG as Low

import Botan.Error
import Botan.Hash
import Botan.Prelude
import Botan.PubKey
import Botan.KDF
import Botan.RNG

data KeyAgreement
    = DHKA DLGroup
    | ECDHKA ECGroup
    | Curve25519KA

keyAgreementToPK :: KeyAgreement -> PK
keyAgreementToPK :: KeyAgreement -> PK
keyAgreementToPK (DHKA DLGroup
dlg) = (DLGroup -> PK
DH DLGroup
dlg)
keyAgreementToPK (ECDHKA ECGroup
ecg) = (ECGroup -> PK
ECDH ECGroup
ecg)
keyAgreementToPK KeyAgreement
Curve25519KA = PK
Curve25519

type KAPublicKey = ByteString
type KASharedSecret = ByteString

newKeyAgreementKey :: KeyAgreement -> IO PrivKey
newKeyAgreementKey :: KeyAgreement -> IO PrivKey
newKeyAgreementKey KeyAgreement
ka = do
    RNG
rng <- RNGType -> IO RNG
forall (m :: * -> *). MonadIO m => RNGType -> m RNG
newRNG RNGType
System
    PK -> RNG -> IO PrivKey
privKeyCreatePKIO (KeyAgreement -> PK
keyAgreementToPK KeyAgreement
ka) RNG
rng

exportKeyAgreementPublicKey :: PrivKey -> IO KAPublicKey
exportKeyAgreementPublicKey :: PrivKey -> IO KDFName
exportKeyAgreementPublicKey = PrivKey -> IO KDFName
Low.keyAgreementExportPublic

newKeyAgreementKeyPair :: KeyAgreement -> IO (PrivKey, KAPublicKey)
newKeyAgreementKeyPair :: KeyAgreement -> IO (PrivKey, KDFName)
newKeyAgreementKeyPair KeyAgreement
ka = do
    PrivKey
sk <- KeyAgreement -> IO PrivKey
newKeyAgreementKey KeyAgreement
ka
    KDFName
pk <- PrivKey -> IO KDFName
exportKeyAgreementPublicKey PrivKey
sk
    (PrivKey, KDFName) -> IO (PrivKey, KDFName)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (PrivKey
sk,KDFName
pk)

newKeyAgreement :: PrivKey -> KDF -> IO Low.KeyAgreement
newKeyAgreement :: PrivKey -> KDF -> IO KeyAgreement
newKeyAgreement PrivKey
sk KDF
kdf = PrivKey -> KDFName -> IO KeyAgreement
Low.keyAgreementCreate PrivKey
sk (KDF -> KDFName
kdfName KDF
kdf)

deriveKeyAgreementSharedSecret :: Low.KeyAgreement -> KAPublicKey -> ByteString -> IO KASharedSecret
deriveKeyAgreementSharedSecret :: KeyAgreement -> KDFName -> KDFName -> IO KDFName
deriveKeyAgreementSharedSecret = KeyAgreement -> KDFName -> KDFName -> IO KDFName
Low.keyAgreement

keyAgreement :: PrivKey -> KAPublicKey -> KDF -> ByteString -> IO KASharedSecret
keyAgreement :: PrivKey -> KDFName -> KDF -> KDFName -> IO KDFName
keyAgreement PrivKey
sk KDFName
pk KDF
kdf KDFName
salt = do
    KeyAgreement
ka <- PrivKey -> KDF -> IO KeyAgreement
newKeyAgreement PrivKey
sk KDF
kdf
    KeyAgreement -> KDFName -> KDFName -> IO KDFName
deriveKeyAgreementSharedSecret KeyAgreement
ka KDFName
pk KDFName
salt




-- import Botan.RNG (rngCtxInitIO, RNG (System))
-- import Botan.Low.PubKey.KeyAgreement



--

newRNGCtx :: IO Low.RNG
newRNGCtx :: IO RNG
newRNGCtx = RNGType -> IO RNG
forall (m :: * -> *). MonadIO m => RNGType -> m RNG
newRNG RNGType
System

type ECDHPub = ByteString

newKeyPair :: PK -> Low.RNG -> IO (ECDHPub, PrivKey)
newKeyPair :: PK -> RNG -> IO (KDFName, PrivKey)
newKeyPair PK
pk RNG
rng = do
    PrivKey
sk <- PK -> RNG -> IO PrivKey
privKeyCreatePKIO PK
pk RNG
rng
    KDFName
pk <- PrivKey -> IO KDFName
Low.keyAgreementExportPublic PrivKey
sk
    (KDFName, PrivKey) -> IO (KDFName, PrivKey)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (KDFName
pk,PrivKey
sk)

newECDHKeyPair :: Low.RNG -> IO (ECDHPub, PrivKey)
newECDHKeyPair :: RNG -> IO (KDFName, PrivKey)
newECDHKeyPair = PK -> RNG -> IO (KDFName, PrivKey)
newKeyPair (ECGroup -> PK
ECDH ECGroup
Secp256k1)

testECDH :: IO Bool
testECDH :: IO Bool
testECDH = do
    RNG
rng <- IO RNG
newRNGCtx
    (KDFName
pka, PrivKey
ska) <- RNG -> IO (KDFName, PrivKey)
newECDHKeyPair RNG
rng
    (KDFName
pkb, PrivKey
skb) <- RNG -> IO (KDFName, PrivKey)
newECDHKeyPair RNG
rng
    -- ecdh k1 p2 == ecdh k2 p1 
    String -> IO ()
forall a. Show a => a -> IO ()
print String
"making a"
    KeyAgreement
ctxa <- PrivKey -> KDFName -> IO KeyAgreement
Low.keyAgreementCreate PrivKey
ska KDFName
"KDF2(SHA-256)"
    String -> IO ()
forall a. Show a => a -> IO ()
print String
"making b"
    KeyAgreement
ctxb <- PrivKey -> KDFName -> IO KeyAgreement
Low.keyAgreementCreate PrivKey
skb KDFName
"KDF2(SHA-256)"
    String -> IO ()
forall a. Show a => a -> IO ()
print String
"agreeing a"
    KDFName
a <- KeyAgreement -> KDFName -> KDFName -> IO KDFName
Low.keyAgreement KeyAgreement
ctxa KDFName
pkb KDFName
""
    String -> IO ()
forall a. Show a => a -> IO ()
print String
"agreeing b"
    KDFName
b <- KeyAgreement -> KDFName -> KDFName -> IO KDFName
Low.keyAgreement KeyAgreement
ctxb KDFName
pka KDFName
""
    String -> IO ()
forall a. Show a => a -> IO ()
print String
"comparing"
    Bool -> IO Bool
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool -> IO Bool) -> Bool -> IO Bool
forall a b. (a -> b) -> a -> b
$ KDFName
a KDFName -> KDFName -> Bool
forall a. Eq a => a -> a -> Bool
== KDFName
b
{-
import Botan.RNG
import Botan.PubKey
import Botan.Low.PubKey.KeyAgreement
kty = ECDH Secp256k1
keys <- replicateM 10 $ privKeyCreatePKIO kty rng
:{
ka k = do
:}
-}