-- |
-- Module      : Crypto.PubKey.Ed25519
-- License     : BSD-style
-- Maintainer  : Vincent Hanquez <vincent@snarc.org>
-- Stability   : experimental
-- Portability : unknown
--
-- Ed25519 support
--
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE BangPatterns #-}
module Crypto.ECC.Ed25519Donna
    ( SecretKey(..)
    , PublicKey(..)
    , Signature
    -- * Smart constructors
    , signature
    , publicKey
    , secretKey
    -- * methods
    , toPublic
    , sign
    , verify
    , publicAdd
    , secretAdd
    ) where

import           Control.DeepSeq
import           Data.Word
import           Foreign.Ptr
import           Foreign.C.Types

import           Data.ByteArray (ByteArrayAccess, withByteArray, ScrubbedBytes, Bytes)
import qualified Data.ByteArray as B
import           Crypto.Error
import           Foreign.Storable
import           System.IO.Unsafe
import           Crypto.Hash (hashWith, SHA512(..))
import           Data.ByteArray (alloc)
import           Data.Bits
import           Control.Monad

unsafeDoIO :: IO a -> a
unsafeDoIO :: IO a -> a
unsafeDoIO = IO a -> a
forall a. IO a -> a
unsafeDupablePerformIO
{-# NOINLINE unsafeDoIO #-}

-- | An Ed25519 Secret key
newtype SecretKey = SecretKey ScrubbedBytes
    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,SecretKey -> Int
SecretKey -> Ptr p -> IO ()
SecretKey -> (Ptr p -> IO a) -> IO a
(SecretKey -> Int)
-> (forall p a. SecretKey -> (Ptr p -> IO a) -> IO a)
-> (forall p. SecretKey -> Ptr p -> IO ())
-> ByteArrayAccess SecretKey
forall p. SecretKey -> Ptr p -> IO ()
forall ba.
(ba -> Int)
-> (forall p a. ba -> (Ptr p -> IO a) -> IO a)
-> (forall p. ba -> Ptr p -> IO ())
-> ByteArrayAccess ba
forall p a. SecretKey -> (Ptr p -> IO a) -> IO a
copyByteArrayToPtr :: SecretKey -> Ptr p -> IO ()
$ccopyByteArrayToPtr :: forall p. SecretKey -> Ptr p -> IO ()
withByteArray :: SecretKey -> (Ptr p -> IO a) -> IO a
$cwithByteArray :: forall p a. SecretKey -> (Ptr p -> IO a) -> IO a
length :: SecretKey -> Int
$clength :: SecretKey -> Int
ByteArrayAccess,SecretKey -> ()
(SecretKey -> ()) -> NFData SecretKey
forall a. (a -> ()) -> NFData a
rnf :: SecretKey -> ()
$crnf :: SecretKey -> ()
NFData)

-- | An Ed25519 public key
newtype PublicKey = PublicKey Bytes
    deriving (Int -> PublicKey -> ShowS
[PublicKey] -> ShowS
PublicKey -> String
(Int -> PublicKey -> ShowS)
-> (PublicKey -> String)
-> ([PublicKey] -> ShowS)
-> Show PublicKey
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [PublicKey] -> ShowS
$cshowList :: [PublicKey] -> ShowS
show :: PublicKey -> String
$cshow :: PublicKey -> String
showsPrec :: Int -> PublicKey -> ShowS
$cshowsPrec :: Int -> PublicKey -> ShowS
Show,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,PublicKey -> Int
PublicKey -> Ptr p -> IO ()
PublicKey -> (Ptr p -> IO a) -> IO a
(PublicKey -> Int)
-> (forall p a. PublicKey -> (Ptr p -> IO a) -> IO a)
-> (forall p. PublicKey -> Ptr p -> IO ())
-> ByteArrayAccess PublicKey
forall p. PublicKey -> Ptr p -> IO ()
forall ba.
(ba -> Int)
-> (forall p a. ba -> (Ptr p -> IO a) -> IO a)
-> (forall p. ba -> Ptr p -> IO ())
-> ByteArrayAccess ba
forall p a. PublicKey -> (Ptr p -> IO a) -> IO a
copyByteArrayToPtr :: PublicKey -> Ptr p -> IO ()
$ccopyByteArrayToPtr :: forall p. PublicKey -> Ptr p -> IO ()
withByteArray :: PublicKey -> (Ptr p -> IO a) -> IO a
$cwithByteArray :: forall p a. PublicKey -> (Ptr p -> IO a) -> IO a
length :: PublicKey -> Int
$clength :: PublicKey -> Int
ByteArrayAccess,PublicKey -> ()
(PublicKey -> ()) -> NFData PublicKey
forall a. (a -> ()) -> NFData a
rnf :: PublicKey -> ()
$crnf :: PublicKey -> ()
NFData)

-- | An Ed25519 signature
newtype Signature = Signature Bytes
    deriving (Int -> Signature -> ShowS
[Signature] -> ShowS
Signature -> String
(Int -> Signature -> ShowS)
-> (Signature -> String)
-> ([Signature] -> ShowS)
-> Show Signature
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Signature] -> ShowS
$cshowList :: [Signature] -> ShowS
show :: Signature -> String
$cshow :: Signature -> String
showsPrec :: Int -> Signature -> ShowS
$cshowsPrec :: Int -> Signature -> ShowS
Show,Signature -> Signature -> Bool
(Signature -> Signature -> Bool)
-> (Signature -> Signature -> Bool) -> Eq Signature
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Signature -> Signature -> Bool
$c/= :: Signature -> Signature -> Bool
== :: Signature -> Signature -> Bool
$c== :: Signature -> Signature -> Bool
Eq,Signature -> Int
Signature -> Ptr p -> IO ()
Signature -> (Ptr p -> IO a) -> IO a
(Signature -> Int)
-> (forall p a. Signature -> (Ptr p -> IO a) -> IO a)
-> (forall p. Signature -> Ptr p -> IO ())
-> ByteArrayAccess Signature
forall p. Signature -> Ptr p -> IO ()
forall ba.
(ba -> Int)
-> (forall p a. ba -> (Ptr p -> IO a) -> IO a)
-> (forall p. ba -> Ptr p -> IO ())
-> ByteArrayAccess ba
forall p a. Signature -> (Ptr p -> IO a) -> IO a
copyByteArrayToPtr :: Signature -> Ptr p -> IO ()
$ccopyByteArrayToPtr :: forall p. Signature -> Ptr p -> IO ()
withByteArray :: Signature -> (Ptr p -> IO a) -> IO a
$cwithByteArray :: forall p a. Signature -> (Ptr p -> IO a) -> IO a
length :: Signature -> Int
$clength :: Signature -> Int
ByteArrayAccess,Signature -> ()
(Signature -> ()) -> NFData Signature
forall a. (a -> ()) -> NFData a
rnf :: Signature -> ()
$crnf :: Signature -> ()
NFData)

-- | Try to build a public key from a bytearray
publicKey :: ByteArrayAccess ba => ba -> CryptoFailable PublicKey
publicKey :: ba -> CryptoFailable PublicKey
publicKey ba
bs
    | ba -> Int
forall ba. ByteArrayAccess ba => ba -> Int
B.length ba
bs Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
publicKeySize =
        PublicKey -> CryptoFailable PublicKey
forall a. a -> CryptoFailable a
CryptoPassed (PublicKey -> CryptoFailable PublicKey)
-> PublicKey -> CryptoFailable PublicKey
forall a b. (a -> b) -> a -> b
$ Bytes -> PublicKey
PublicKey (Bytes -> PublicKey) -> Bytes -> PublicKey
forall a b. (a -> b) -> a -> b
$ ba -> (Ptr Any -> IO ()) -> Bytes
forall bs1 bs2 p.
(ByteArrayAccess bs1, ByteArray bs2) =>
bs1 -> (Ptr p -> IO ()) -> bs2
B.copyAndFreeze ba
bs (\Ptr Any
_ -> () -> IO ()
forall (m :: Type -> Type) a. Monad m => a -> m a
return ())
    | Bool
otherwise =
        CryptoError -> CryptoFailable PublicKey
forall a. CryptoError -> CryptoFailable a
CryptoFailed (CryptoError -> CryptoFailable PublicKey)
-> CryptoError -> CryptoFailable PublicKey
forall a b. (a -> b) -> a -> b
$ CryptoError
CryptoError_PublicKeySizeInvalid

-- | Try to build a secret key from a bytearray
secretKey :: ByteArrayAccess ba => ba -> CryptoFailable SecretKey
secretKey :: ba -> CryptoFailable SecretKey
secretKey ba
bs
    | ba -> Int
forall ba. ByteArrayAccess ba => ba -> Int
B.length ba
bs Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
32 = IO (CryptoFailable SecretKey) -> CryptoFailable SecretKey
forall a. IO a -> a
unsafePerformIO IO (CryptoFailable SecretKey)
verifyAndTweak
    | Bool
otherwise         = CryptoError -> CryptoFailable SecretKey
forall a. CryptoError -> CryptoFailable a
CryptoFailed CryptoError
CryptoError_SecretKeySizeInvalid
  where
    k :: Digest SHA512
k = SHA512 -> ba -> Digest SHA512
forall ba alg.
(ByteArrayAccess ba, HashAlgorithm alg) =>
alg -> ba -> Digest alg
hashWith SHA512
SHA512 ba
bs
    verifyAndTweak :: IO (CryptoFailable SecretKey)
    verifyAndTweak :: IO (CryptoFailable SecretKey)
verifyAndTweak = Digest SHA512
-> (Ptr Word8 -> IO (CryptoFailable SecretKey))
-> IO (CryptoFailable SecretKey)
forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray Digest SHA512
k ((Ptr Word8 -> IO (CryptoFailable SecretKey))
 -> IO (CryptoFailable SecretKey))
-> (Ptr Word8 -> IO (CryptoFailable SecretKey))
-> IO (CryptoFailable SecretKey)
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
inp -> do
        Word8
b0  <- Ptr Word8 -> Int -> IO Word8
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff Ptr Word8
inp Int
0 :: IO Word8
        Word8
b31 <- Ptr Word8 -> Int -> IO Word8
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff Ptr Word8
inp Int
31
        if Word8 -> Int -> Bool
forall a. Bits a => a -> Int -> Bool
testBit Word8
b31 Int
5
            then CryptoFailable SecretKey -> IO (CryptoFailable SecretKey)
forall (m :: Type -> Type) a. Monad m => a -> m a
return (CryptoFailable SecretKey -> IO (CryptoFailable SecretKey))
-> CryptoFailable SecretKey -> IO (CryptoFailable SecretKey)
forall a b. (a -> b) -> a -> b
$ CryptoError -> CryptoFailable SecretKey
forall a. CryptoError -> CryptoFailable a
CryptoFailed CryptoError
CryptoError_SecretKeyStructureInvalid
            else SecretKey -> CryptoFailable SecretKey
forall a. a -> CryptoFailable a
CryptoPassed (SecretKey -> CryptoFailable SecretKey)
-> (ScrubbedBytes -> SecretKey)
-> ScrubbedBytes
-> CryptoFailable SecretKey
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ScrubbedBytes -> SecretKey
SecretKey (ScrubbedBytes -> CryptoFailable SecretKey)
-> IO ScrubbedBytes -> IO (CryptoFailable SecretKey)
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> (Int -> (Ptr Word8 -> IO ()) -> IO ScrubbedBytes
forall ba p. ByteArray ba => Int -> (Ptr p -> IO ()) -> IO ba
alloc Int
64 ((Ptr Word8 -> IO ()) -> IO ScrubbedBytes)
-> (Ptr Word8 -> IO ()) -> IO ScrubbedBytes
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
outp -> do
                    Ptr Word8 -> Int -> Word8 -> IO ()
forall a. Storable a => Ptr a -> Int -> a -> IO ()
pokeElemOff Ptr Word8
outp Int
0 (Word8
b0 Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.&. Word8
0xf8) -- clear lowest 3 bits
                    [Int] -> (Int -> IO ()) -> IO ()
forall (t :: Type -> Type) (m :: Type -> Type) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [Int
1..Int
30] ((Int -> IO ()) -> IO ()) -> (Int -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Int
i -> Ptr Word8 -> Int -> IO Word8
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff Ptr Word8
inp Int
i IO Word8 -> (Word8 -> IO ()) -> IO ()
forall (m :: Type -> Type) a b. Monad m => m a -> (a -> m b) -> m b
>>= Ptr Word8 -> Int -> Word8 -> IO ()
forall a. Storable a => Ptr a -> Int -> a -> IO ()
pokeElemOff Ptr Word8
outp Int
i
                    Ptr Word8 -> Int -> Word8 -> IO ()
forall a. Storable a => Ptr a -> Int -> a -> IO ()
pokeElemOff Ptr Word8
outp Int
31 ((Word8
b31 Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.&. Word8
0x1f) Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.|. Word8
0x40) -- clear highest bit and 3rd bit, and set 2nd highest.
                    [Int] -> (Int -> IO ()) -> IO ()
forall (t :: Type -> Type) (m :: Type -> Type) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [Int
32..Int
63] ((Int -> IO ()) -> IO ()) -> (Int -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Int
i -> Ptr Word8 -> Int -> IO Word8
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff Ptr Word8
inp Int
i IO Word8 -> (Word8 -> IO ()) -> IO ()
forall (m :: Type -> Type) a b. Monad m => m a -> (a -> m b) -> m b
>>= Ptr Word8 -> Int -> Word8 -> IO ()
forall a. Storable a => Ptr a -> Int -> a -> IO ()
pokeElemOff Ptr Word8
outp Int
i
                    )

-- | Try to build a signature from a bytearray
signature :: ByteArrayAccess ba => ba -> CryptoFailable Signature
signature :: ba -> CryptoFailable Signature
signature ba
bs
    | ba -> Int
forall ba. ByteArrayAccess ba => ba -> Int
B.length ba
bs Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
signatureSize =
        Signature -> CryptoFailable Signature
forall a. a -> CryptoFailable a
CryptoPassed (Signature -> CryptoFailable Signature)
-> Signature -> CryptoFailable Signature
forall a b. (a -> b) -> a -> b
$ Bytes -> Signature
Signature (Bytes -> Signature) -> Bytes -> Signature
forall a b. (a -> b) -> a -> b
$ ba -> (Ptr Any -> IO ()) -> Bytes
forall bs1 bs2 p.
(ByteArrayAccess bs1, ByteArray bs2) =>
bs1 -> (Ptr p -> IO ()) -> bs2
B.copyAndFreeze ba
bs (\Ptr Any
_ -> () -> IO ()
forall (m :: Type -> Type) a. Monad m => a -> m a
return ())
    | Bool
otherwise =
        -- missing a SignatureSizeInvalid error, so use another one
        CryptoError -> CryptoFailable Signature
forall a. CryptoError -> CryptoFailable a
CryptoFailed (CryptoError -> CryptoFailable Signature)
-> CryptoError -> CryptoFailable Signature
forall a b. (a -> b) -> a -> b
$ CryptoError
CryptoError_SecretKeySizeInvalid

-- | Create a public key from a secret key
toPublic :: SecretKey -> PublicKey
toPublic :: SecretKey -> PublicKey
toPublic (SecretKey ScrubbedBytes
sec) = Bytes -> PublicKey
PublicKey (Bytes -> PublicKey) -> Bytes -> PublicKey
forall a b. (a -> b) -> a -> b
$
    Int -> (Ptr PublicKey -> IO ()) -> Bytes
forall a p. ByteArray a => Int -> (Ptr p -> IO ()) -> a
B.allocAndFreeze Int
publicKeySize ((Ptr PublicKey -> IO ()) -> Bytes)
-> (Ptr PublicKey -> IO ()) -> Bytes
forall a b. (a -> b) -> a -> b
$ \Ptr PublicKey
result ->
    ScrubbedBytes -> (Ptr SecretKey -> IO ()) -> IO ()
forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray ScrubbedBytes
sec              ((Ptr SecretKey -> IO ()) -> IO ())
-> (Ptr SecretKey -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Ptr SecretKey
psec   ->
        Ptr SecretKey -> Ptr PublicKey -> IO ()
ccryptonite_ed25519_publickey Ptr SecretKey
psec Ptr PublicKey
result
{-# NOINLINE toPublic #-}

publicAdd :: PublicKey -> PublicKey -> PublicKey
publicAdd :: PublicKey -> PublicKey -> PublicKey
publicAdd PublicKey
p1 PublicKey
p2 =
    Bytes -> PublicKey
PublicKey (Bytes -> PublicKey) -> Bytes -> PublicKey
forall a b. (a -> b) -> a -> b
$ Int -> (Ptr PublicKey -> IO ()) -> Bytes
forall a p. ByteArray a => Int -> (Ptr p -> IO ()) -> a
B.allocAndFreeze Int
publicKeySize ((Ptr PublicKey -> IO ()) -> Bytes)
-> (Ptr PublicKey -> IO ()) -> Bytes
forall a b. (a -> b) -> a -> b
$ \Ptr PublicKey
result ->
        PublicKey -> (Ptr PublicKey -> IO ()) -> IO ()
forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray PublicKey
p1 ((Ptr PublicKey -> IO ()) -> IO ())
-> (Ptr PublicKey -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Ptr PublicKey
v1 ->
        PublicKey -> (Ptr PublicKey -> IO ()) -> IO ()
forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray PublicKey
p2 ((Ptr PublicKey -> IO ()) -> IO ())
-> (Ptr PublicKey -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Ptr PublicKey
v2 ->
            Ptr PublicKey -> Ptr PublicKey -> Ptr PublicKey -> IO ()
ccryptonite_ed25519_point_add Ptr PublicKey
v1 Ptr PublicKey
v2 Ptr PublicKey
result

secretAdd :: SecretKey -> SecretKey -> SecretKey
secretAdd :: SecretKey -> SecretKey -> SecretKey
secretAdd SecretKey
p1 SecretKey
p2 =
    ScrubbedBytes -> SecretKey
SecretKey (ScrubbedBytes -> SecretKey) -> ScrubbedBytes -> SecretKey
forall a b. (a -> b) -> a -> b
$ Int -> (Ptr SecretKey -> IO ()) -> ScrubbedBytes
forall a p. ByteArray a => Int -> (Ptr p -> IO ()) -> a
B.allocAndFreeze Int
secretKeySize ((Ptr SecretKey -> IO ()) -> ScrubbedBytes)
-> (Ptr SecretKey -> IO ()) -> ScrubbedBytes
forall a b. (a -> b) -> a -> b
$ \Ptr SecretKey
result ->
        SecretKey -> (Ptr SecretKey -> IO ()) -> IO ()
forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray SecretKey
p1 ((Ptr SecretKey -> IO ()) -> IO ())
-> (Ptr SecretKey -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Ptr SecretKey
v1 ->
        SecretKey -> (Ptr SecretKey -> IO ()) -> IO ()
forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray SecretKey
p2 ((Ptr SecretKey -> IO ()) -> IO ())
-> (Ptr SecretKey -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Ptr SecretKey
v2 ->
            Ptr SecretKey -> Ptr SecretKey -> Ptr SecretKey -> IO ()
ccryptonite_ed25519_scalar_add Ptr SecretKey
v1 Ptr SecretKey
v2 Ptr SecretKey
result

-- | Sign a message using the key pair
sign :: (ByteArrayAccess msg, ByteArrayAccess salt) => SecretKey -> salt -> PublicKey -> msg -> Signature
sign :: SecretKey -> salt -> PublicKey -> msg -> Signature
sign SecretKey
secret salt
salt PublicKey
public msg
message =
    Bytes -> Signature
Signature (Bytes -> Signature) -> Bytes -> Signature
forall a b. (a -> b) -> a -> b
$ Int -> (Ptr Signature -> IO ()) -> Bytes
forall a p. ByteArray a => Int -> (Ptr p -> IO ()) -> a
B.allocAndFreeze Int
signatureSize ((Ptr Signature -> IO ()) -> Bytes)
-> (Ptr Signature -> IO ()) -> Bytes
forall a b. (a -> b) -> a -> b
$ \Ptr Signature
sig ->
        SecretKey -> (Ptr SecretKey -> IO ()) -> IO ()
forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray SecretKey
secret  ((Ptr SecretKey -> IO ()) -> IO ())
-> (Ptr SecretKey -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Ptr SecretKey
sec   ->
        PublicKey -> (Ptr PublicKey -> IO ()) -> IO ()
forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray PublicKey
public  ((Ptr PublicKey -> IO ()) -> IO ())
-> (Ptr PublicKey -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Ptr PublicKey
pub   ->
        salt -> (Ptr Word8 -> IO ()) -> IO ()
forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray salt
salt    ((Ptr Word8 -> IO ()) -> IO ()) -> (Ptr Word8 -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
saltP ->
        msg -> (Ptr Word8 -> IO ()) -> IO ()
forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray msg
message ((Ptr Word8 -> IO ()) -> IO ()) -> (Ptr Word8 -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
msg   ->
             Ptr Word8
-> CSize
-> Ptr Word8
-> CSize
-> Ptr SecretKey
-> Ptr PublicKey
-> Ptr Signature
-> IO ()
ccryptonite_ed25519_sign Ptr Word8
msg (Int -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
msgLen) Ptr Word8
saltP (Int -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
saltLen) Ptr SecretKey
sec Ptr PublicKey
pub Ptr Signature
sig
  where
    !msgLen :: Int
msgLen  = msg -> Int
forall ba. ByteArrayAccess ba => ba -> Int
B.length msg
message
    !saltLen :: Int
saltLen = salt -> Int
forall ba. ByteArrayAccess ba => ba -> Int
B.length salt
salt

-- | Verify a message
verify :: ByteArrayAccess ba => PublicKey -> ba -> Signature -> Bool
verify :: PublicKey -> ba -> Signature -> Bool
verify PublicKey
public ba
message Signature
signatureVal = IO Bool -> Bool
forall a. IO a -> a
unsafeDoIO (IO Bool -> Bool) -> IO Bool -> Bool
forall a b. (a -> b) -> a -> b
$
    Signature -> (Ptr Signature -> IO Bool) -> IO Bool
forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray Signature
signatureVal ((Ptr Signature -> IO Bool) -> IO Bool)
-> (Ptr Signature -> IO Bool) -> IO Bool
forall a b. (a -> b) -> a -> b
$ \Ptr Signature
sig ->
    PublicKey -> (Ptr PublicKey -> IO Bool) -> IO Bool
forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray PublicKey
public       ((Ptr PublicKey -> IO Bool) -> IO Bool)
-> (Ptr PublicKey -> IO Bool) -> IO Bool
forall a b. (a -> b) -> a -> b
$ \Ptr PublicKey
pub ->
    ba -> (Ptr Word8 -> IO Bool) -> IO Bool
forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray ba
message      ((Ptr Word8 -> IO Bool) -> IO Bool)
-> (Ptr Word8 -> IO Bool) -> IO Bool
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
msg -> do
      CInt
r <- Ptr Word8 -> CSize -> Ptr PublicKey -> Ptr Signature -> IO CInt
ccryptonite_ed25519_sign_open Ptr Word8
msg (Int -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
msgLen) Ptr PublicKey
pub Ptr Signature
sig
      Bool -> IO Bool
forall (m :: Type -> Type) a. Monad m => a -> m a
return (CInt
r CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
== CInt
0)
  where
    !msgLen :: Int
msgLen = ba -> Int
forall ba. ByteArrayAccess ba => ba -> Int
B.length ba
message

publicKeySize :: Int
publicKeySize :: Int
publicKeySize = Int
32

secretKeySize :: Int
secretKeySize :: Int
secretKeySize = Int
64

signatureSize :: Int
signatureSize :: Int
signatureSize = Int
64

foreign import ccall "cardano_crypto_ed25519_publickey"
    ccryptonite_ed25519_publickey :: Ptr SecretKey -- secret key
                                  -> Ptr PublicKey -- public key
                                  -> IO ()

foreign import ccall "cardano_crypto_ed25519_sign_open"
    ccryptonite_ed25519_sign_open :: Ptr Word8     -- message
                                  -> CSize         -- message len
                                  -> Ptr PublicKey -- public
                                  -> Ptr Signature -- signature
                                  -> IO CInt

foreign import ccall "cardano_crypto_ed25519_sign"
    ccryptonite_ed25519_sign :: Ptr Word8     -- message
                             -> CSize         -- message len
                             -> Ptr Word8     -- salt
                             -> CSize         -- salt len
                             -> Ptr SecretKey -- secret
                             -> Ptr PublicKey -- public
                             -> Ptr Signature -- signature
                             -> IO ()

foreign import ccall "cardano_crypto_ed25519_point_add"
    ccryptonite_ed25519_point_add :: Ptr PublicKey -- p1
                                  -> Ptr PublicKey -- p2
                                  -> Ptr PublicKey -- p1 + p2
                                  -> IO ()

foreign import ccall "cardano_crypto_ed25519_scalar_add"
    ccryptonite_ed25519_scalar_add :: Ptr SecretKey -- s1
                                   -> Ptr SecretKey -- s2
                                   -> Ptr SecretKey -- s1 + s2
                                   -> IO ()