module Crypto.Sign.Ed25519
(
PublicKey(..)
, SecretKey(..)
, createKeypair
, sign
, verify
, Signature(..)
, sign'
, verify'
) where
import Foreign.C.Types
import Foreign.ForeignPtr (withForeignPtr)
import Foreign.Marshal.Alloc (alloca)
import Foreign.Ptr
import Foreign.Storable
import System.IO.Unsafe (unsafePerformIO)
import Data.ByteString as S
import Data.ByteString.Internal as SI
import Data.ByteString.Unsafe as SU
import Data.Word
newtype SecretKey = SecretKey { unSecretKey :: ByteString }
deriving (Eq, Show, Ord)
newtype PublicKey = PublicKey { unPublicKey :: ByteString }
deriving (Eq, Show, Ord)
createKeypair :: IO (PublicKey, SecretKey)
createKeypair = do
pk <- SI.mallocByteString cryptoSignPUBLICKEYBYTES
sk <- SI.mallocByteString cryptoSignSECRETKEYBYTES
_ <- withForeignPtr pk $ \ppk -> do
_ <- withForeignPtr sk $ \psk -> do
_ <- c_crypto_sign_keypair ppk psk
return ()
return ()
return (PublicKey $ SI.fromForeignPtr pk 0 cryptoSignPUBLICKEYBYTES,
SecretKey $ SI.fromForeignPtr sk 0 cryptoSignSECRETKEYBYTES)
sign :: SecretKey
-> ByteString
-> ByteString
sign (SecretKey sk) xs =
unsafePerformIO . SU.unsafeUseAsCStringLen xs $ \(mstr,mlen) ->
SU.unsafeUseAsCString sk $ \psk ->
SI.createAndTrim (mlen+cryptoSignBYTES) $ \out ->
alloca $ \smlen -> do
_ <- (c_crypto_sign out smlen mstr (fromIntegral mlen) psk)
fromIntegral `fmap` peek smlen
verify :: PublicKey
-> ByteString
-> Bool
verify (PublicKey pk) xs =
unsafePerformIO . SU.unsafeUseAsCStringLen xs $ \(smstr,smlen) ->
SU.unsafeUseAsCString pk $ \ppk ->
alloca $ \pmlen -> do
out <- SI.mallocByteString smlen
r <- withForeignPtr out $ \pout ->
c_crypto_sign_open pout pmlen smstr (fromIntegral smlen) ppk
return (r == 0)
newtype Signature = Signature { unSignature :: ByteString }
deriving (Eq, Show, Ord)
sign' :: SecretKey
-> ByteString
-> Signature
sign' sk xs =
let sm = sign sk xs
l = S.length sm
in Signature $! S.take (l S.length xs) sm
verify' :: PublicKey
-> ByteString
-> Signature
-> Bool
verify' pk xs (Signature sig) = verify pk (sig `S.append` xs)
cryptoSignSECRETKEYBYTES :: Int
cryptoSignSECRETKEYBYTES = 64
cryptoSignPUBLICKEYBYTES :: Int
cryptoSignPUBLICKEYBYTES = 32
cryptoSignBYTES :: Int
cryptoSignBYTES = 64
foreign import ccall unsafe "ed25519_sign_keypair"
c_crypto_sign_keypair :: Ptr Word8 -> Ptr Word8 -> IO CInt
foreign import ccall unsafe "ed25519_sign"
c_crypto_sign :: Ptr Word8 -> Ptr CULLong ->
Ptr CChar -> CULLong -> Ptr CChar -> IO CULLong
foreign import ccall unsafe "ed25519_sign_open"
c_crypto_sign_open :: Ptr Word8 -> Ptr CULLong ->
Ptr CChar -> CULLong -> Ptr CChar -> IO CInt