\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
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
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}