{-# LANGUAGE DeriveDataTypeable, GeneralizedNewtypeDeriving, DeriveGeneric #-}

-- |
-- Module      : Crypto.Saltine.Core.Sign
-- Copyright   : (c) Joseph Abrahamson 2013
-- License     : MIT
--
-- Maintainer  : me@jspha.com
-- Stability   : experimental
-- Portability : non-portable
--
-- Signatures: "Crypto.Saltine.Core.Sign"
--
-- The 'newKeypair' function randomly generates a secret key and a
-- corresponding public key. The 'sign' function signs a message
-- 'ByteString' using the signer's secret key and returns the
-- resulting signed message. The 'signOpen' function verifies the
-- signature in a signed message using the signer's public key then
-- returns the message without its signature.
--
-- "Crypto.Saltine.Core.Sign" is an EdDSA signature using
-- elliptic-curve Curve25519 (see: <http://ed25519.cr.yp.to/>). See
-- also, \"Daniel J. Bernstein, Niels Duif, Tanja Lange, Peter
-- Schwabe, Bo-Yin Yang. High-speed high-security signatures. Journal
-- of Cryptographic Engineering 2 (2012), 77–89.\"
-- <http://ed25519.cr.yp.to/ed25519-20110926.pdf>.
--
-- This is current information as of 2013 June 6.

module Crypto.Saltine.Core.Sign (
  SecretKey, PublicKey, Keypair,
  newKeypair,
  sign, signOpen,
  signDetached, signVerifyDetached
  ) where

import           Crypto.Saltine.Class
import           Crypto.Saltine.Internal.Util
import qualified Crypto.Saltine.Internal.ByteSizes as Bytes

import           Foreign.C
import           Foreign.Ptr
import           Foreign.Marshal.Alloc
import           Foreign.Storable
import           System.IO.Unsafe
import qualified Data.ByteString                   as S
import           Data.ByteString                     (ByteString)
import           Data.Data (Data, Typeable)
import           Data.Hashable (Hashable)
import           GHC.Generics (Generic)


-- $types

-- | An opaque 'box' cryptographic secret key.
newtype SecretKey = SK ByteString deriving (SecretKey -> SecretKey -> Bool
(SecretKey -> SecretKey -> Bool)
-> (SecretKey -> SecretKey -> Bool) -> Eq SecretKey
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: SecretKey -> SecretKey -> Bool
$c/= :: SecretKey -> SecretKey -> Bool
== :: SecretKey -> SecretKey -> Bool
$c== :: SecretKey -> SecretKey -> Bool
Eq, Eq SecretKey
Eq SecretKey =>
(SecretKey -> SecretKey -> Ordering)
-> (SecretKey -> SecretKey -> Bool)
-> (SecretKey -> SecretKey -> Bool)
-> (SecretKey -> SecretKey -> Bool)
-> (SecretKey -> SecretKey -> Bool)
-> (SecretKey -> SecretKey -> SecretKey)
-> (SecretKey -> SecretKey -> SecretKey)
-> Ord SecretKey
SecretKey -> SecretKey -> Bool
SecretKey -> SecretKey -> Ordering
SecretKey -> SecretKey -> SecretKey
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: SecretKey -> SecretKey -> SecretKey
$cmin :: SecretKey -> SecretKey -> SecretKey
max :: SecretKey -> SecretKey -> SecretKey
$cmax :: SecretKey -> SecretKey -> SecretKey
>= :: SecretKey -> SecretKey -> Bool
$c>= :: SecretKey -> SecretKey -> Bool
> :: SecretKey -> SecretKey -> Bool
$c> :: SecretKey -> SecretKey -> Bool
<= :: SecretKey -> SecretKey -> Bool
$c<= :: SecretKey -> SecretKey -> Bool
< :: SecretKey -> SecretKey -> Bool
$c< :: SecretKey -> SecretKey -> Bool
compare :: SecretKey -> SecretKey -> Ordering
$ccompare :: SecretKey -> SecretKey -> Ordering
$cp1Ord :: Eq SecretKey
Ord, Int -> SecretKey -> Int
SecretKey -> Int
(Int -> SecretKey -> Int)
-> (SecretKey -> Int) -> Hashable SecretKey
forall a. (Int -> a -> Int) -> (a -> Int) -> Hashable a
hash :: SecretKey -> Int
$chash :: SecretKey -> Int
hashWithSalt :: Int -> SecretKey -> Int
$chashWithSalt :: Int -> SecretKey -> Int
Hashable, Typeable SecretKey
DataType
Constr
Typeable SecretKey =>
(forall (c :: * -> *).
 (forall d b. Data d => c (d -> b) -> d -> c b)
 -> (forall g. g -> c g) -> SecretKey -> c SecretKey)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c SecretKey)
-> (SecretKey -> Constr)
-> (SecretKey -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c SecretKey))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c SecretKey))
-> ((forall b. Data b => b -> b) -> SecretKey -> SecretKey)
-> (forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> SecretKey -> r)
-> (forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> SecretKey -> r)
-> (forall u. (forall d. Data d => d -> u) -> SecretKey -> [u])
-> (forall u.
    Int -> (forall d. Data d => d -> u) -> SecretKey -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> SecretKey -> m SecretKey)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> SecretKey -> m SecretKey)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> SecretKey -> m SecretKey)
-> Data SecretKey
SecretKey -> DataType
SecretKey -> Constr
(forall b. Data b => b -> b) -> SecretKey -> SecretKey
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> SecretKey -> c SecretKey
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c SecretKey
forall a.
Typeable a =>
(forall (c :: * -> *).
 (forall d b. Data d => c (d -> b) -> d -> c b)
 -> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall u. Int -> (forall d. Data d => d -> u) -> SecretKey -> u
forall u. (forall d. Data d => d -> u) -> SecretKey -> [u]
forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> SecretKey -> r
forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> SecretKey -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> SecretKey -> m SecretKey
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> SecretKey -> m SecretKey
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c SecretKey
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> SecretKey -> c SecretKey
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c SecretKey)
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c SecretKey)
$cSK :: Constr
$tSecretKey :: DataType
gmapMo :: (forall d. Data d => d -> m d) -> SecretKey -> m SecretKey
$cgmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> SecretKey -> m SecretKey
gmapMp :: (forall d. Data d => d -> m d) -> SecretKey -> m SecretKey
$cgmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> SecretKey -> m SecretKey
gmapM :: (forall d. Data d => d -> m d) -> SecretKey -> m SecretKey
$cgmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> SecretKey -> m SecretKey
gmapQi :: Int -> (forall d. Data d => d -> u) -> SecretKey -> u
$cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> SecretKey -> u
gmapQ :: (forall d. Data d => d -> u) -> SecretKey -> [u]
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> SecretKey -> [u]
gmapQr :: (r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> SecretKey -> r
$cgmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> SecretKey -> r
gmapQl :: (r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> SecretKey -> r
$cgmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> SecretKey -> r
gmapT :: (forall b. Data b => b -> b) -> SecretKey -> SecretKey
$cgmapT :: (forall b. Data b => b -> b) -> SecretKey -> SecretKey
dataCast2 :: (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c SecretKey)
$cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c SecretKey)
dataCast1 :: (forall d. Data d => c (t d)) -> Maybe (c SecretKey)
$cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c SecretKey)
dataTypeOf :: SecretKey -> DataType
$cdataTypeOf :: SecretKey -> DataType
toConstr :: SecretKey -> Constr
$ctoConstr :: SecretKey -> Constr
gunfold :: (forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c SecretKey
$cgunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c SecretKey
gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> SecretKey -> c SecretKey
$cgfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> SecretKey -> c SecretKey
$cp1Data :: Typeable SecretKey
Data, Typeable, (forall x. SecretKey -> Rep SecretKey x)
-> (forall x. Rep SecretKey x -> SecretKey) -> Generic SecretKey
forall x. Rep SecretKey x -> SecretKey
forall x. SecretKey -> Rep SecretKey x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep SecretKey x -> SecretKey
$cfrom :: forall x. SecretKey -> Rep SecretKey x
Generic)

instance IsEncoding SecretKey where
  decode :: ByteString -> Maybe SecretKey
decode v :: ByteString
v = if ByteString -> Int
S.length ByteString
v Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
Bytes.signSK
           then SecretKey -> Maybe SecretKey
forall a. a -> Maybe a
Just (ByteString -> SecretKey
SK ByteString
v)
           else Maybe SecretKey
forall a. Maybe a
Nothing
  {-# INLINE decode #-}
  encode :: SecretKey -> ByteString
encode (SK v :: ByteString
v) = ByteString
v
  {-# INLINE encode #-}

-- | An opaque 'box' cryptographic public key.
newtype PublicKey = PK ByteString deriving (PublicKey -> PublicKey -> Bool
(PublicKey -> PublicKey -> Bool)
-> (PublicKey -> PublicKey -> Bool) -> Eq PublicKey
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: PublicKey -> PublicKey -> Bool
$c/= :: PublicKey -> PublicKey -> Bool
== :: PublicKey -> PublicKey -> Bool
$c== :: PublicKey -> PublicKey -> Bool
Eq, Eq PublicKey
Eq PublicKey =>
(PublicKey -> PublicKey -> Ordering)
-> (PublicKey -> PublicKey -> Bool)
-> (PublicKey -> PublicKey -> Bool)
-> (PublicKey -> PublicKey -> Bool)
-> (PublicKey -> PublicKey -> Bool)
-> (PublicKey -> PublicKey -> PublicKey)
-> (PublicKey -> PublicKey -> PublicKey)
-> Ord PublicKey
PublicKey -> PublicKey -> Bool
PublicKey -> PublicKey -> Ordering
PublicKey -> PublicKey -> PublicKey
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: PublicKey -> PublicKey -> PublicKey
$cmin :: PublicKey -> PublicKey -> PublicKey
max :: PublicKey -> PublicKey -> PublicKey
$cmax :: PublicKey -> PublicKey -> PublicKey
>= :: PublicKey -> PublicKey -> Bool
$c>= :: PublicKey -> PublicKey -> Bool
> :: PublicKey -> PublicKey -> Bool
$c> :: PublicKey -> PublicKey -> Bool
<= :: PublicKey -> PublicKey -> Bool
$c<= :: PublicKey -> PublicKey -> Bool
< :: PublicKey -> PublicKey -> Bool
$c< :: PublicKey -> PublicKey -> Bool
compare :: PublicKey -> PublicKey -> Ordering
$ccompare :: PublicKey -> PublicKey -> Ordering
$cp1Ord :: Eq PublicKey
Ord, Typeable PublicKey
DataType
Constr
Typeable PublicKey =>
(forall (c :: * -> *).
 (forall d b. Data d => c (d -> b) -> d -> c b)
 -> (forall g. g -> c g) -> PublicKey -> c PublicKey)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c PublicKey)
-> (PublicKey -> Constr)
-> (PublicKey -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c PublicKey))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c PublicKey))
-> ((forall b. Data b => b -> b) -> PublicKey -> PublicKey)
-> (forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> PublicKey -> r)
-> (forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> PublicKey -> r)
-> (forall u. (forall d. Data d => d -> u) -> PublicKey -> [u])
-> (forall u.
    Int -> (forall d. Data d => d -> u) -> PublicKey -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> PublicKey -> m PublicKey)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> PublicKey -> m PublicKey)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> PublicKey -> m PublicKey)
-> Data PublicKey
PublicKey -> DataType
PublicKey -> Constr
(forall b. Data b => b -> b) -> PublicKey -> PublicKey
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> PublicKey -> c PublicKey
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c PublicKey
forall a.
Typeable a =>
(forall (c :: * -> *).
 (forall d b. Data d => c (d -> b) -> d -> c b)
 -> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall u. Int -> (forall d. Data d => d -> u) -> PublicKey -> u
forall u. (forall d. Data d => d -> u) -> PublicKey -> [u]
forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> PublicKey -> r
forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> PublicKey -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> PublicKey -> m PublicKey
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> PublicKey -> m PublicKey
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c PublicKey
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> PublicKey -> c PublicKey
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c PublicKey)
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c PublicKey)
$cPK :: Constr
$tPublicKey :: DataType
gmapMo :: (forall d. Data d => d -> m d) -> PublicKey -> m PublicKey
$cgmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> PublicKey -> m PublicKey
gmapMp :: (forall d. Data d => d -> m d) -> PublicKey -> m PublicKey
$cgmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> PublicKey -> m PublicKey
gmapM :: (forall d. Data d => d -> m d) -> PublicKey -> m PublicKey
$cgmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> PublicKey -> m PublicKey
gmapQi :: Int -> (forall d. Data d => d -> u) -> PublicKey -> u
$cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> PublicKey -> u
gmapQ :: (forall d. Data d => d -> u) -> PublicKey -> [u]
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> PublicKey -> [u]
gmapQr :: (r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> PublicKey -> r
$cgmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> PublicKey -> r
gmapQl :: (r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> PublicKey -> r
$cgmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> PublicKey -> r
gmapT :: (forall b. Data b => b -> b) -> PublicKey -> PublicKey
$cgmapT :: (forall b. Data b => b -> b) -> PublicKey -> PublicKey
dataCast2 :: (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c PublicKey)
$cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c PublicKey)
dataCast1 :: (forall d. Data d => c (t d)) -> Maybe (c PublicKey)
$cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c PublicKey)
dataTypeOf :: PublicKey -> DataType
$cdataTypeOf :: PublicKey -> DataType
toConstr :: PublicKey -> Constr
$ctoConstr :: PublicKey -> Constr
gunfold :: (forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c PublicKey
$cgunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c PublicKey
gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> PublicKey -> c PublicKey
$cgfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> PublicKey -> c PublicKey
$cp1Data :: Typeable PublicKey
Data, Typeable, Int -> PublicKey -> Int
PublicKey -> Int
(Int -> PublicKey -> Int)
-> (PublicKey -> Int) -> Hashable PublicKey
forall a. (Int -> a -> Int) -> (a -> Int) -> Hashable a
hash :: PublicKey -> Int
$chash :: PublicKey -> Int
hashWithSalt :: Int -> PublicKey -> Int
$chashWithSalt :: Int -> PublicKey -> Int
Hashable, (forall x. PublicKey -> Rep PublicKey x)
-> (forall x. Rep PublicKey x -> PublicKey) -> Generic PublicKey
forall x. Rep PublicKey x -> PublicKey
forall x. PublicKey -> Rep PublicKey x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep PublicKey x -> PublicKey
$cfrom :: forall x. PublicKey -> Rep PublicKey x
Generic)

instance IsEncoding PublicKey where
  decode :: ByteString -> Maybe PublicKey
decode v :: ByteString
v = if ByteString -> Int
S.length ByteString
v Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
Bytes.signPK
           then PublicKey -> Maybe PublicKey
forall a. a -> Maybe a
Just (ByteString -> PublicKey
PK ByteString
v)
           else Maybe PublicKey
forall a. Maybe a
Nothing
  {-# INLINE decode #-}
  encode :: PublicKey -> ByteString
encode (PK v :: ByteString
v) = ByteString
v
  {-# INLINE encode #-}

-- | A convenience type for keypairs
type Keypair = (SecretKey, PublicKey)

-- | Creates a random key of the correct size for 'sign' and
-- 'signOpen' of form @(secretKey, publicKey)@.
newKeypair :: IO Keypair
newKeypair :: IO Keypair
newKeypair = do
  -- This is a little bizarre and a likely source of errors.
  -- _err ought to always be 0.
  ((_err :: CInt
_err, sk :: ByteString
sk), pk :: ByteString
pk) <- Int
-> (Ptr CChar -> IO (CInt, ByteString))
-> IO ((CInt, ByteString), ByteString)
forall b. Int -> (Ptr CChar -> IO b) -> IO (b, ByteString)
buildUnsafeByteString' Int
Bytes.signPK ((Ptr CChar -> IO (CInt, ByteString))
 -> IO ((CInt, ByteString), ByteString))
-> (Ptr CChar -> IO (CInt, ByteString))
-> IO ((CInt, ByteString), ByteString)
forall a b. (a -> b) -> a -> b
$ \pkbuf :: Ptr CChar
pkbuf ->
    Int -> (Ptr CChar -> IO CInt) -> IO (CInt, ByteString)
forall b. Int -> (Ptr CChar -> IO b) -> IO (b, ByteString)
buildUnsafeByteString' Int
Bytes.signSK ((Ptr CChar -> IO CInt) -> IO (CInt, ByteString))
-> (Ptr CChar -> IO CInt) -> IO (CInt, ByteString)
forall a b. (a -> b) -> a -> b
$ \skbuf :: Ptr CChar
skbuf ->
      Ptr CChar -> Ptr CChar -> IO CInt
c_sign_keypair Ptr CChar
pkbuf Ptr CChar
skbuf
  Keypair -> IO Keypair
forall (m :: * -> *) a. Monad m => a -> m a
return (ByteString -> SecretKey
SK ByteString
sk, ByteString -> PublicKey
PK ByteString
pk)

-- | Augments a message with a signature forming a \"signed
-- message\".
sign :: SecretKey
     -> ByteString
     -- ^ Message
     -> ByteString
     -- ^ Signed message
sign :: SecretKey -> ByteString -> ByteString
sign (SK k :: ByteString
k) m :: ByteString
m = IO ByteString -> ByteString
forall a. IO a -> a
unsafePerformIO (IO ByteString -> ByteString) -> IO ByteString -> ByteString
forall a b. (a -> b) -> a -> b
$
  (Ptr CULLong -> IO ByteString) -> IO ByteString
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr CULLong -> IO ByteString) -> IO ByteString)
-> (Ptr CULLong -> IO ByteString) -> IO ByteString
forall a b. (a -> b) -> a -> b
$ \psmlen :: Ptr CULLong
psmlen -> do
    (_err :: CInt
_err, sm :: ByteString
sm) <- Int -> (Ptr CChar -> IO CInt) -> IO (CInt, ByteString)
forall b. Int -> (Ptr CChar -> IO b) -> IO (b, ByteString)
buildUnsafeByteString' (Int
len Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
Bytes.sign) ((Ptr CChar -> IO CInt) -> IO (CInt, ByteString))
-> (Ptr CChar -> IO CInt) -> IO (CInt, ByteString)
forall a b. (a -> b) -> a -> b
$ \psmbuf :: Ptr CChar
psmbuf ->
      [ByteString] -> ([CStringLen] -> IO CInt) -> IO CInt
forall b. [ByteString] -> ([CStringLen] -> IO b) -> IO b
constByteStrings [ByteString
k, ByteString
m] (([CStringLen] -> IO CInt) -> IO CInt)
-> ([CStringLen] -> IO CInt) -> IO CInt
forall a b. (a -> b) -> a -> b
$ \[(pk :: Ptr CChar
pk, _), (pm :: Ptr CChar
pm, _)] ->
        Ptr CChar
-> Ptr CULLong -> Ptr CChar -> CULLong -> Ptr CChar -> IO CInt
c_sign Ptr CChar
psmbuf Ptr CULLong
psmlen Ptr CChar
pm (Int -> CULLong
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len) Ptr CChar
pk
    CULLong
smlen <- Ptr CULLong -> IO CULLong
forall a. Storable a => Ptr a -> IO a
peek Ptr CULLong
psmlen
    ByteString -> IO ByteString
forall (m :: * -> *) a. Monad m => a -> m a
return (ByteString -> IO ByteString) -> ByteString -> IO ByteString
forall a b. (a -> b) -> a -> b
$ Int -> ByteString -> ByteString
S.take (CULLong -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral CULLong
smlen) ByteString
sm
  where len :: Int
len = ByteString -> Int
S.length ByteString
m

-- | Checks a \"signed message\" returning 'Just' the original message
-- iff the signature was generated using the 'SecretKey' corresponding
-- to the given 'PublicKey'. Returns 'Nothing' otherwise.
signOpen :: PublicKey
         -> ByteString
         -- ^ Signed message
         -> Maybe ByteString
         -- ^ Maybe the restored message
signOpen :: PublicKey -> ByteString -> Maybe ByteString
signOpen (PK k :: ByteString
k) sm :: ByteString
sm = IO (Maybe ByteString) -> Maybe ByteString
forall a. IO a -> a
unsafePerformIO (IO (Maybe ByteString) -> Maybe ByteString)
-> IO (Maybe ByteString) -> Maybe ByteString
forall a b. (a -> b) -> a -> b
$
  (Ptr CULLong -> IO (Maybe ByteString)) -> IO (Maybe ByteString)
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr CULLong -> IO (Maybe ByteString)) -> IO (Maybe ByteString))
-> (Ptr CULLong -> IO (Maybe ByteString)) -> IO (Maybe ByteString)
forall a b. (a -> b) -> a -> b
$ \pmlen :: Ptr CULLong
pmlen -> do
    (err :: CInt
err, m :: ByteString
m) <- Int -> (Ptr CChar -> IO CInt) -> IO (CInt, ByteString)
forall b. Int -> (Ptr CChar -> IO b) -> IO (b, ByteString)
buildUnsafeByteString' Int
smlen ((Ptr CChar -> IO CInt) -> IO (CInt, ByteString))
-> (Ptr CChar -> IO CInt) -> IO (CInt, ByteString)
forall a b. (a -> b) -> a -> b
$ \pmbuf :: Ptr CChar
pmbuf ->
      [ByteString] -> ([CStringLen] -> IO CInt) -> IO CInt
forall b. [ByteString] -> ([CStringLen] -> IO b) -> IO b
constByteStrings [ByteString
k, ByteString
sm] (([CStringLen] -> IO CInt) -> IO CInt)
-> ([CStringLen] -> IO CInt) -> IO CInt
forall a b. (a -> b) -> a -> b
$ \[(pk :: Ptr CChar
pk, _), (psm :: Ptr CChar
psm, _)] ->
        Ptr CChar
-> Ptr CULLong -> Ptr CChar -> CULLong -> Ptr CChar -> IO CInt
c_sign_open Ptr CChar
pmbuf Ptr CULLong
pmlen Ptr CChar
psm (Int -> CULLong
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
smlen) Ptr CChar
pk
    CULLong
mlen <- Ptr CULLong -> IO CULLong
forall a. Storable a => Ptr a -> IO a
peek Ptr CULLong
pmlen
    case CInt
err of
      0 -> Maybe ByteString -> IO (Maybe ByteString)
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe ByteString -> IO (Maybe ByteString))
-> Maybe ByteString -> IO (Maybe ByteString)
forall a b. (a -> b) -> a -> b
$ ByteString -> Maybe ByteString
forall a. a -> Maybe a
Just (ByteString -> Maybe ByteString) -> ByteString -> Maybe ByteString
forall a b. (a -> b) -> a -> b
$ Int -> ByteString -> ByteString
S.take (CULLong -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral CULLong
mlen) ByteString
m
      _ -> Maybe ByteString -> IO (Maybe ByteString)
forall (m :: * -> *) a. Monad m => a -> m a
return   Maybe ByteString
forall a. Maybe a
Nothing
  where smlen :: Int
smlen = ByteString -> Int
S.length ByteString
sm

-- | Returns just the signature for a message using a SecretKey.
signDetached :: SecretKey
             -> ByteString
             -- ^ Message
             -> ByteString
             -- ^ Signature
signDetached :: SecretKey -> ByteString -> ByteString
signDetached (SK k :: ByteString
k) m :: ByteString
m = IO ByteString -> ByteString
forall a. IO a -> a
unsafePerformIO (IO ByteString -> ByteString) -> IO ByteString -> ByteString
forall a b. (a -> b) -> a -> b
$
    (Ptr CULLong -> IO ByteString) -> IO ByteString
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr CULLong -> IO ByteString) -> IO ByteString)
-> (Ptr CULLong -> IO ByteString) -> IO ByteString
forall a b. (a -> b) -> a -> b
$ \psmlen :: Ptr CULLong
psmlen -> do
        (_err :: CInt
_err, sm :: ByteString
sm) <- Int -> (Ptr CChar -> IO CInt) -> IO (CInt, ByteString)
forall b. Int -> (Ptr CChar -> IO b) -> IO (b, ByteString)
buildUnsafeByteString' Int
Bytes.sign ((Ptr CChar -> IO CInt) -> IO (CInt, ByteString))
-> (Ptr CChar -> IO CInt) -> IO (CInt, ByteString)
forall a b. (a -> b) -> a -> b
$ \sigbuf :: Ptr CChar
sigbuf ->
            [ByteString] -> ([CStringLen] -> IO CInt) -> IO CInt
forall b. [ByteString] -> ([CStringLen] -> IO b) -> IO b
constByteStrings [ByteString
k, ByteString
m] (([CStringLen] -> IO CInt) -> IO CInt)
-> ([CStringLen] -> IO CInt) -> IO CInt
forall a b. (a -> b) -> a -> b
$ \[(pk :: Ptr CChar
pk, _), (pm :: Ptr CChar
pm, _)] ->
                Ptr CChar
-> Ptr CULLong -> Ptr CChar -> CULLong -> Ptr CChar -> IO CInt
c_sign_detached Ptr CChar
sigbuf Ptr CULLong
psmlen Ptr CChar
pm (Int -> CULLong
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len) Ptr CChar
pk
        CULLong
smlen <- Ptr CULLong -> IO CULLong
forall a. Storable a => Ptr a -> IO a
peek Ptr CULLong
psmlen
        ByteString -> IO ByteString
forall (m :: * -> *) a. Monad m => a -> m a
return (ByteString -> IO ByteString) -> ByteString -> IO ByteString
forall a b. (a -> b) -> a -> b
$ Int -> ByteString -> ByteString
S.take (CULLong -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral CULLong
smlen) ByteString
sm
  where len :: Int
len = ByteString -> Int
S.length ByteString
m

-- | Returns @True@ if the signature is valid for the given public key and
-- message.
signVerifyDetached :: PublicKey
                   -> ByteString
                   -- ^ Signature
                   -> ByteString
                   -- ^ Message
                   -> Bool
signVerifyDetached :: PublicKey -> ByteString -> ByteString -> Bool
signVerifyDetached (PK k :: ByteString
k) sig :: ByteString
sig sm :: ByteString
sm = IO Bool -> Bool
forall a. IO a -> a
unsafePerformIO (IO Bool -> Bool) -> IO Bool -> Bool
forall a b. (a -> b) -> a -> b
$
    [ByteString] -> ([CStringLen] -> IO Bool) -> IO Bool
forall b. [ByteString] -> ([CStringLen] -> IO b) -> IO b
constByteStrings [ByteString
k, ByteString
sig, ByteString
sm] (([CStringLen] -> IO Bool) -> IO Bool)
-> ([CStringLen] -> IO Bool) -> IO Bool
forall a b. (a -> b) -> a -> b
$ \[(pk :: Ptr CChar
pk, _), (psig :: Ptr CChar
psig, _), (psm :: Ptr CChar
psm, _)] -> do
        CInt
res <- Ptr CChar -> Ptr CChar -> CULLong -> Ptr CChar -> IO CInt
c_sign_verify_detached Ptr CChar
psig Ptr CChar
psm (Int -> CULLong
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len) Ptr CChar
pk
        Bool -> IO Bool
forall (m :: * -> *) a. Monad m => a -> m a
return (CInt
res CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
== 0)
  where len :: Int
len = ByteString -> Int
S.length ByteString
sm


foreign import ccall "crypto_sign_keypair"
  c_sign_keypair :: Ptr CChar
                 -- ^ Public key output buffer
                 -> Ptr CChar
                 -- ^ Secret key output buffer
                 -> IO CInt
                 -- ^ Always 0

foreign import ccall "crypto_sign"
  c_sign :: Ptr CChar
         -- ^ Signed message output buffer
         -> Ptr CULLong
         -- ^ Length of signed message
         -> Ptr CChar
         -- ^ Constant message buffer
         -> CULLong
         -- ^ Length of message input buffer
         -> Ptr CChar
         -- ^ Constant secret key buffer
         -> IO CInt
         -- ^ Always 0

foreign import ccall "crypto_sign_open"
  c_sign_open :: Ptr CChar
              -- ^ Message output buffer
              -> Ptr CULLong
              -- ^ Length of message
              -> Ptr CChar
              -- ^ Constant signed message buffer
              -> CULLong
              -- ^ Length of signed message buffer
              -> Ptr CChar
              -- ^ Public key buffer
              -> IO CInt
              -- ^ 0 if signature is verifiable, -1 otherwise

foreign import ccall "crypto_sign_detached"
    c_sign_detached :: Ptr CChar
                    -- ^ Signature output buffer
                    -> Ptr CULLong
                    -- ^ Length of the signature
                    -> Ptr CChar
                    -- ^ Constant message buffer
                    -> CULLong
                    -- ^ Length of message buffer
                    -> Ptr CChar
                    -- ^ Constant secret key buffer
                    -> IO CInt
foreign import ccall "crypto_sign_verify_detached"
    c_sign_verify_detached :: Ptr CChar
                           -- ^ Signature buffer
                           -> Ptr CChar
                           -- ^ Constant signed message buffer
                           -> CULLong
                           -- ^ Length of signed message buffer
                           -> Ptr CChar
                           -- ^ Public key buffer
                           -> IO CInt