{-# LANGUAGE TypeFamilies #-}
-------------------------------------------------
-- |
-- Module      : Crypto.Noise.DH.Curve25519
-- Maintainer  : John Galt <jgalt@centromere.net>
-- Stability   : experimental
-- Portability : POSIX
module Crypto.Noise.DH.Curve25519
  ( -- * Types
    Curve25519
  ) where

import Crypto.Error          (throwCryptoError, maybeCryptoError)
import Crypto.Random.Entropy (getEntropy)
import qualified Crypto.PubKey.Curve25519 as C
import Crypto.Noise.DH
import Data.ByteArray        (ScrubbedBytes, convert)

-- | Represents curve25519.
data Curve25519

instance DH Curve25519 where
  newtype PublicKey Curve25519 = PK25519 C.PublicKey
  newtype SecretKey Curve25519 = SK25519 C.SecretKey

  dhName :: forall (proxy :: * -> *). proxy Curve25519 -> ScrubbedBytes
dhName   proxy Curve25519
_    = ScrubbedBytes
"25519"
  dhLength :: forall (proxy :: * -> *). proxy Curve25519 -> Int
dhLength proxy Curve25519
_    = Int
32
  dhGenKey :: IO (KeyPair Curve25519)
dhGenKey      = IO (KeyPair Curve25519)
genKey
  dhPerform :: SecretKey Curve25519 -> PublicKey Curve25519 -> ScrubbedBytes
dhPerform     = SecretKey Curve25519 -> PublicKey Curve25519 -> ScrubbedBytes
dh
  dhPubToBytes :: PublicKey Curve25519 -> ScrubbedBytes
dhPubToBytes  = PublicKey Curve25519 -> ScrubbedBytes
pubToBytes
  dhBytesToPub :: ScrubbedBytes -> Maybe (PublicKey Curve25519)
dhBytesToPub  = ScrubbedBytes -> Maybe (PublicKey Curve25519)
bytesToPub
  dhSecToBytes :: SecretKey Curve25519 -> ScrubbedBytes
dhSecToBytes  = SecretKey Curve25519 -> ScrubbedBytes
secToBytes
  dhBytesToPair :: ScrubbedBytes -> Maybe (KeyPair Curve25519)
dhBytesToPair = ScrubbedBytes -> Maybe (KeyPair Curve25519)
bytesToPair
  dhPubEq :: PublicKey Curve25519 -> PublicKey Curve25519 -> Bool
dhPubEq       = PublicKey Curve25519 -> PublicKey Curve25519 -> Bool
pubEq

genKey :: IO (KeyPair Curve25519)
genKey :: IO (KeyPair Curve25519)
genKey = do
  ScrubbedBytes
r <- Int -> IO ScrubbedBytes
forall byteArray. ByteArray byteArray => Int -> IO byteArray
getEntropy Int
32 :: IO ScrubbedBytes
  let sk :: SecretKey
sk = CryptoFailable SecretKey -> SecretKey
forall a. CryptoFailable a -> a
throwCryptoError (CryptoFailable SecretKey -> SecretKey)
-> (ScrubbedBytes -> CryptoFailable SecretKey)
-> ScrubbedBytes
-> SecretKey
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ScrubbedBytes -> CryptoFailable SecretKey
forall bs. ByteArrayAccess bs => bs -> CryptoFailable SecretKey
C.secretKey (ScrubbedBytes -> SecretKey) -> ScrubbedBytes -> SecretKey
forall a b. (a -> b) -> a -> b
$ ScrubbedBytes
r
      pk :: PublicKey
pk = SecretKey -> PublicKey
C.toPublic SecretKey
sk
  KeyPair Curve25519 -> IO (KeyPair Curve25519)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (SecretKey -> SecretKey Curve25519
SK25519 SecretKey
sk, PublicKey -> PublicKey Curve25519
PK25519 PublicKey
pk)

dh :: SecretKey Curve25519 -> PublicKey Curve25519 -> ScrubbedBytes
dh :: SecretKey Curve25519 -> PublicKey Curve25519 -> ScrubbedBytes
dh (SK25519 SecretKey
sk) (PK25519 PublicKey
pk) = DhSecret -> ScrubbedBytes
forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
bin -> bout
convert (DhSecret -> ScrubbedBytes) -> DhSecret -> ScrubbedBytes
forall a b. (a -> b) -> a -> b
$ PublicKey -> SecretKey -> DhSecret
C.dh PublicKey
pk SecretKey
sk

pubToBytes :: PublicKey Curve25519 -> ScrubbedBytes
pubToBytes :: PublicKey Curve25519 -> ScrubbedBytes
pubToBytes (PK25519 PublicKey
pk) = PublicKey -> ScrubbedBytes
forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
bin -> bout
convert PublicKey
pk

bytesToPub :: ScrubbedBytes -> Maybe (PublicKey Curve25519)
bytesToPub :: ScrubbedBytes -> Maybe (PublicKey Curve25519)
bytesToPub = (PublicKey -> PublicKey Curve25519)
-> Maybe PublicKey -> Maybe (PublicKey Curve25519)
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap PublicKey -> PublicKey Curve25519
PK25519 (Maybe PublicKey -> Maybe (PublicKey Curve25519))
-> (ScrubbedBytes -> Maybe PublicKey)
-> ScrubbedBytes
-> Maybe (PublicKey Curve25519)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CryptoFailable PublicKey -> Maybe PublicKey
forall a. CryptoFailable a -> Maybe a
maybeCryptoError (CryptoFailable PublicKey -> Maybe PublicKey)
-> (ScrubbedBytes -> CryptoFailable PublicKey)
-> ScrubbedBytes
-> Maybe PublicKey
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ScrubbedBytes -> CryptoFailable PublicKey
forall bs. ByteArrayAccess bs => bs -> CryptoFailable PublicKey
C.publicKey

secToBytes :: SecretKey Curve25519 -> ScrubbedBytes
secToBytes :: SecretKey Curve25519 -> ScrubbedBytes
secToBytes (SK25519 SecretKey
sk) = SecretKey -> ScrubbedBytes
forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
bin -> bout
convert SecretKey
sk

bytesToPair :: ScrubbedBytes -> Maybe (KeyPair Curve25519)
bytesToPair :: ScrubbedBytes -> Maybe (KeyPair Curve25519)
bytesToPair ScrubbedBytes
bs = do
  SecretKey
sk <- CryptoFailable SecretKey -> Maybe SecretKey
forall a. CryptoFailable a -> Maybe a
maybeCryptoError (CryptoFailable SecretKey -> Maybe SecretKey)
-> (ScrubbedBytes -> CryptoFailable SecretKey)
-> ScrubbedBytes
-> Maybe SecretKey
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ScrubbedBytes -> CryptoFailable SecretKey
forall bs. ByteArrayAccess bs => bs -> CryptoFailable SecretKey
C.secretKey (ScrubbedBytes -> Maybe SecretKey)
-> ScrubbedBytes -> Maybe SecretKey
forall a b. (a -> b) -> a -> b
$ ScrubbedBytes
bs
  KeyPair Curve25519 -> Maybe (KeyPair Curve25519)
forall a. a -> Maybe a
forall (m :: * -> *) a. Monad m => a -> m a
return (SecretKey -> SecretKey Curve25519
SK25519 SecretKey
sk, PublicKey -> PublicKey Curve25519
PK25519 (SecretKey -> PublicKey
C.toPublic SecretKey
sk))

pubEq :: PublicKey Curve25519
      -> PublicKey Curve25519
      -> Bool
pubEq :: PublicKey Curve25519 -> PublicKey Curve25519 -> Bool
pubEq (PK25519 PublicKey
a) (PK25519 PublicKey
b) = PublicKey
a PublicKey -> PublicKey -> Bool
forall a. Eq a => a -> a -> Bool
== PublicKey
b