\subsection{Key Pair}

A Key Pair is a pair of Secret Key and Public Key.  A new key pair is generated
using the \texttt{crypto\_box\_keypair} function of the NaCl crypto library.  Two
separate calls to the key pair generation function must return distinct key
pairs.  See the \href{https://nacl.cr.yp.to/box.html}{NaCl documentation} for
details.

A Public Key can be computed from a Secret Key using the NaCl function
\texttt{crypto\_scalarmult\_base}, which computes the scalar product of a
standard group element and the Secret Key.  See the
\href{https://nacl.cr.yp.to/scalarmult.html}{NaCl documentation} for details.

\begin{code}
{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneric      #-}
{-# LANGUAGE OverloadedStrings  #-}
{-# LANGUAGE StrictData         #-}
module Network.Tox.Crypto.KeyPair where

import qualified Crypto.Saltine.Class           as Sodium (decode, encode)
import qualified Crypto.Saltine.Core.Box        as Sodium (Keypair (..),
                                                           newKeypair)
import qualified Crypto.Saltine.Core.ScalarMult as Sodium (multBase)
import           Data.Binary                    (Binary)
import           Data.MessagePack               (MessagePack (..))
import           Data.Typeable                  (Typeable)
import           GHC.Generics                   (Generic)
import           Test.QuickCheck.Arbitrary      (Arbitrary, arbitrary)

import           Network.Tox.Crypto.Key         (Key (..))
import qualified Network.Tox.Crypto.Key         as Key


{-------------------------------------------------------------------------------
 -
 - :: Implementation.
 -
 ------------------------------------------------------------------------------}


data KeyPair = KeyPair
  { KeyPair -> SecretKey
secretKey :: Key.SecretKey
  , KeyPair -> PublicKey
publicKey :: Key.PublicKey
  }
  deriving (KeyPair -> KeyPair -> Bool
(KeyPair -> KeyPair -> Bool)
-> (KeyPair -> KeyPair -> Bool) -> Eq KeyPair
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: KeyPair -> KeyPair -> Bool
$c/= :: KeyPair -> KeyPair -> Bool
== :: KeyPair -> KeyPair -> Bool
$c== :: KeyPair -> KeyPair -> Bool
Eq, Int -> KeyPair -> ShowS
[KeyPair] -> ShowS
KeyPair -> String
(Int -> KeyPair -> ShowS)
-> (KeyPair -> String) -> ([KeyPair] -> ShowS) -> Show KeyPair
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [KeyPair] -> ShowS
$cshowList :: [KeyPair] -> ShowS
show :: KeyPair -> String
$cshow :: KeyPair -> String
showsPrec :: Int -> KeyPair -> ShowS
$cshowsPrec :: Int -> KeyPair -> ShowS
Show, ReadPrec [KeyPair]
ReadPrec KeyPair
Int -> ReadS KeyPair
ReadS [KeyPair]
(Int -> ReadS KeyPair)
-> ReadS [KeyPair]
-> ReadPrec KeyPair
-> ReadPrec [KeyPair]
-> Read KeyPair
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [KeyPair]
$creadListPrec :: ReadPrec [KeyPair]
readPrec :: ReadPrec KeyPair
$creadPrec :: ReadPrec KeyPair
readList :: ReadS [KeyPair]
$creadList :: ReadS [KeyPair]
readsPrec :: Int -> ReadS KeyPair
$creadsPrec :: Int -> ReadS KeyPair
Read, (forall x. KeyPair -> Rep KeyPair x)
-> (forall x. Rep KeyPair x -> KeyPair) -> Generic KeyPair
forall x. Rep KeyPair x -> KeyPair
forall x. KeyPair -> Rep KeyPair x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep KeyPair x -> KeyPair
$cfrom :: forall x. KeyPair -> Rep KeyPair x
Generic, Typeable)

instance Binary KeyPair
instance MessagePack KeyPair


newKeyPair :: IO KeyPair
newKeyPair :: IO KeyPair
newKeyPair = do
  Sodium.Keypair SecretKey
sk PublicKey
pk <- IO Keypair
Sodium.newKeypair
  KeyPair -> IO KeyPair
forall (m :: * -> *) a. Monad m => a -> m a
return (KeyPair -> IO KeyPair) -> KeyPair -> IO KeyPair
forall a b. (a -> b) -> a -> b
$ SecretKey -> PublicKey -> KeyPair
KeyPair (SecretKey -> SecretKey
forall a. a -> Key a
Key SecretKey
sk) (PublicKey -> PublicKey
forall a. a -> Key a
Key PublicKey
pk)


fromSecretKey :: Key.SecretKey -> KeyPair
fromSecretKey :: SecretKey -> KeyPair
fromSecretKey SecretKey
sk =
  let
    skBytes :: ByteString
skBytes = SecretKey -> ByteString
forall a. IsEncoding a => a -> ByteString
Sodium.encode SecretKey
sk
    Just Scalar
skScalar = ByteString -> Maybe Scalar
forall a. IsEncoding a => ByteString -> Maybe a
Sodium.decode ByteString
skBytes
    pkGroupElement :: GroupElement
pkGroupElement = Scalar -> GroupElement
Sodium.multBase Scalar
skScalar
    pkBytes :: ByteString
pkBytes = GroupElement -> ByteString
forall a. IsEncoding a => a -> ByteString
Sodium.encode GroupElement
pkGroupElement
    Just PublicKey
pk = ByteString -> Maybe PublicKey
forall a. IsEncoding a => ByteString -> Maybe a
Sodium.decode ByteString
pkBytes
  in
  SecretKey -> PublicKey -> KeyPair
KeyPair SecretKey
sk PublicKey
pk


{-------------------------------------------------------------------------------
 -
 - :: Tests.
 -
 ------------------------------------------------------------------------------}


instance Arbitrary KeyPair where
  arbitrary :: Gen KeyPair
arbitrary =
    SecretKey -> KeyPair
fromSecretKey (SecretKey -> KeyPair) -> Gen SecretKey -> Gen KeyPair
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen SecretKey
forall a. Arbitrary a => Gen a
arbitrary
\end{code}