{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Crypto.PubKey.Ed25519
( SecretKey
, PublicKey
, Signature
, publicKeySize
, secretKeySize
, signatureSize
, signature
, publicKey
, secretKey
, toPublic
, sign
, verify
, generateSecretKey
) where
import Data.Word
import Foreign.C.Types
import Foreign.Ptr
import Crypto.Error
import Crypto.Internal.ByteArray (ByteArrayAccess, Bytes,
ScrubbedBytes, withByteArray)
import qualified Crypto.Internal.ByteArray as B
import Crypto.Internal.Compat
import Crypto.Internal.Imports
import Crypto.Random
newtype SecretKey = SecretKey ScrubbedBytes
deriving (Int -> SecretKey -> ShowS
[SecretKey] -> ShowS
SecretKey -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [SecretKey] -> ShowS
$cshowList :: [SecretKey] -> ShowS
show :: SecretKey -> String
$cshow :: SecretKey -> String
showsPrec :: Int -> SecretKey -> ShowS
$cshowsPrec :: Int -> SecretKey -> ShowS
Show,SecretKey -> SecretKey -> Bool
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
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 :: forall p. SecretKey -> Ptr p -> IO ()
$ccopyByteArrayToPtr :: forall p. SecretKey -> Ptr p -> IO ()
withByteArray :: forall p a. 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 -> ()
forall a. (a -> ()) -> NFData a
rnf :: SecretKey -> ()
$crnf :: SecretKey -> ()
NFData)
newtype PublicKey = PublicKey Bytes
deriving (Int -> PublicKey -> ShowS
[PublicKey] -> ShowS
PublicKey -> String
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
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
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 :: forall p. PublicKey -> Ptr p -> IO ()
$ccopyByteArrayToPtr :: forall p. PublicKey -> Ptr p -> IO ()
withByteArray :: forall p a. 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 -> ()
forall a. (a -> ()) -> NFData a
rnf :: PublicKey -> ()
$crnf :: PublicKey -> ()
NFData)
newtype Signature = Signature Bytes
deriving (Int -> Signature -> ShowS
[Signature] -> ShowS
Signature -> String
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
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
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 :: forall p. Signature -> Ptr p -> IO ()
$ccopyByteArrayToPtr :: forall p. Signature -> Ptr p -> IO ()
withByteArray :: forall p a. 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 -> ()
forall a. (a -> ()) -> NFData a
rnf :: Signature -> ()
$crnf :: Signature -> ()
NFData)
publicKey :: ByteArrayAccess ba => ba -> CryptoFailable PublicKey
publicKey :: forall ba. ByteArrayAccess ba => ba -> CryptoFailable PublicKey
publicKey ba
bs
| forall ba. ByteArrayAccess ba => ba -> Int
B.length ba
bs forall a. Eq a => a -> a -> Bool
== Int
publicKeySize =
forall a. a -> CryptoFailable a
CryptoPassed forall a b. (a -> b) -> a -> b
$ Bytes -> PublicKey
PublicKey forall a b. (a -> b) -> a -> b
$ forall bs1 bs2 p.
(ByteArrayAccess bs1, ByteArray bs2) =>
bs1 -> (Ptr p -> IO ()) -> bs2
B.copyAndFreeze ba
bs (\Ptr Any
_ -> forall (m :: * -> *) a. Monad m => a -> m a
return ())
| Bool
otherwise =
forall a. CryptoError -> CryptoFailable a
CryptoFailed forall a b. (a -> b) -> a -> b
$ CryptoError
CryptoError_PublicKeySizeInvalid
secretKey :: ByteArrayAccess ba => ba -> CryptoFailable SecretKey
secretKey :: forall ba. ByteArrayAccess ba => ba -> CryptoFailable SecretKey
secretKey ba
bs
| forall ba. ByteArrayAccess ba => ba -> Int
B.length ba
bs forall a. Eq a => a -> a -> Bool
== Int
secretKeySize = forall a. IO a -> a
unsafeDoIO forall a b. (a -> b) -> a -> b
$ forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray ba
bs forall {p}. p -> IO (CryptoFailable SecretKey)
initialize
| Bool
otherwise = forall a. CryptoError -> CryptoFailable a
CryptoFailed CryptoError
CryptoError_SecretKeyStructureInvalid
where
initialize :: p -> IO (CryptoFailable SecretKey)
initialize p
inp = do
Bool
valid <- forall {m :: * -> *} {p}. Monad m => p -> m Bool
isValidPtr p
inp
if Bool
valid
then (forall a. a -> CryptoFailable a
CryptoPassed forall b c a. (b -> c) -> (a -> b) -> a -> c
. ScrubbedBytes -> SecretKey
SecretKey) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall bs1 bs2 p.
(ByteArrayAccess bs1, ByteArray bs2) =>
bs1 -> (Ptr p -> IO ()) -> IO bs2
B.copy ba
bs (\Ptr Any
_ -> forall (m :: * -> *) a. Monad m => a -> m a
return ())
else forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a. CryptoError -> CryptoFailable a
CryptoFailed CryptoError
CryptoError_SecretKeyStructureInvalid
isValidPtr :: p -> m Bool
isValidPtr p
_ =
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True
{-# NOINLINE secretKey #-}
signature :: ByteArrayAccess ba => ba -> CryptoFailable Signature
signature :: forall ba. ByteArrayAccess ba => ba -> CryptoFailable Signature
signature ba
bs
| forall ba. ByteArrayAccess ba => ba -> Int
B.length ba
bs forall a. Eq a => a -> a -> Bool
== Int
signatureSize =
forall a. a -> CryptoFailable a
CryptoPassed forall a b. (a -> b) -> a -> b
$ Bytes -> Signature
Signature forall a b. (a -> b) -> a -> b
$ forall bs1 bs2 p.
(ByteArrayAccess bs1, ByteArray bs2) =>
bs1 -> (Ptr p -> IO ()) -> bs2
B.copyAndFreeze ba
bs (\Ptr Any
_ -> forall (m :: * -> *) a. Monad m => a -> m a
return ())
| Bool
otherwise =
forall a. CryptoError -> CryptoFailable a
CryptoFailed CryptoError
CryptoError_SecretKeyStructureInvalid
toPublic :: SecretKey -> PublicKey
toPublic :: SecretKey -> PublicKey
toPublic (SecretKey ScrubbedBytes
sec) = Bytes -> PublicKey
PublicKey forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>
forall a p. ByteArray a => Int -> (Ptr p -> IO ()) -> a
B.allocAndFreeze Int
publicKeySize forall a b. (a -> b) -> a -> b
$ \Ptr PublicKey
result ->
forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray ScrubbedBytes
sec forall a b. (a -> b) -> a -> b
$ \Ptr SecretKey
psec ->
Ptr SecretKey -> Ptr PublicKey -> IO ()
ccrypton_ed25519_publickey Ptr SecretKey
psec Ptr PublicKey
result
{-# NOINLINE toPublic #-}
sign :: ByteArrayAccess ba => SecretKey -> PublicKey -> ba -> Signature
sign :: forall ba.
ByteArrayAccess ba =>
SecretKey -> PublicKey -> ba -> Signature
sign SecretKey
secret PublicKey
public ba
message =
Bytes -> Signature
Signature forall a b. (a -> b) -> a -> b
$ forall a p. ByteArray a => Int -> (Ptr p -> IO ()) -> a
B.allocAndFreeze Int
signatureSize forall a b. (a -> b) -> a -> b
$ \Ptr Signature
sig ->
forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray SecretKey
secret forall a b. (a -> b) -> a -> b
$ \Ptr SecretKey
sec ->
forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray PublicKey
public forall a b. (a -> b) -> a -> b
$ \Ptr PublicKey
pub ->
forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray ba
message forall a b. (a -> b) -> a -> b
$ \Ptr Word8
msg ->
Ptr Word8
-> CSize
-> Ptr SecretKey
-> Ptr PublicKey
-> Ptr Signature
-> IO ()
ccrypton_ed25519_sign Ptr Word8
msg (forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
msgLen) Ptr SecretKey
sec Ptr PublicKey
pub Ptr Signature
sig
where
!msgLen :: Int
msgLen = forall ba. ByteArrayAccess ba => ba -> Int
B.length ba
message
verify :: ByteArrayAccess ba => PublicKey -> ba -> Signature -> Bool
verify :: forall ba.
ByteArrayAccess ba =>
PublicKey -> ba -> Signature -> Bool
verify PublicKey
public ba
message Signature
signatureVal = forall a. IO a -> a
unsafeDoIO forall a b. (a -> b) -> a -> b
$
forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray Signature
signatureVal forall a b. (a -> b) -> a -> b
$ \Ptr Signature
sig ->
forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray PublicKey
public forall a b. (a -> b) -> a -> b
$ \Ptr PublicKey
pub ->
forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray ba
message forall a b. (a -> b) -> a -> b
$ \Ptr Word8
msg -> do
CInt
r <- Ptr Word8 -> CSize -> Ptr PublicKey -> Ptr Signature -> IO CInt
ccrypton_ed25519_sign_open Ptr Word8
msg (forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
msgLen) Ptr PublicKey
pub Ptr Signature
sig
forall (m :: * -> *) a. Monad m => a -> m a
return (CInt
r forall a. Eq a => a -> a -> Bool
== CInt
0)
where
!msgLen :: Int
msgLen = forall ba. ByteArrayAccess ba => ba -> Int
B.length ba
message
generateSecretKey :: MonadRandom m => m SecretKey
generateSecretKey :: forall (m :: * -> *). MonadRandom m => m SecretKey
generateSecretKey = ScrubbedBytes -> SecretKey
SecretKey forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (m :: * -> *) byteArray.
(MonadRandom m, ByteArray byteArray) =>
Int -> m byteArray
getRandomBytes Int
secretKeySize
publicKeySize :: Int
publicKeySize :: Int
publicKeySize = Int
32
secretKeySize :: Int
secretKeySize :: Int
secretKeySize = Int
32
signatureSize :: Int
signatureSize :: Int
signatureSize = Int
64
foreign import ccall "crypton_ed25519_publickey"
ccrypton_ed25519_publickey :: Ptr SecretKey
-> Ptr PublicKey
-> IO ()
foreign import ccall "crypton_ed25519_sign_open"
ccrypton_ed25519_sign_open :: Ptr Word8
-> CSize
-> Ptr PublicKey
-> Ptr Signature
-> IO CInt
foreign import ccall "crypton_ed25519_sign"
ccrypton_ed25519_sign :: Ptr Word8
-> CSize
-> Ptr SecretKey
-> Ptr PublicKey
-> Ptr Signature
-> IO ()