libsodium-bindings-0.0.1.0: src/LibSodium/Bindings/CryptoSign.hs
{-# LANGUAGE CApiFFI #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE Trustworthy #-}
-- |
-- Module: LibSodium.Bindings.Signing
-- Description: Direct bindings to the public-key signing algorithm ed25519 implemented in Libsodium
-- Copyright: (C) Hécate Moonlight 2022
-- License: BSD-3-Clause
-- Maintainer: The Haskell Cryptography Group
-- Stability: Stable
-- Portability: GHC only
module LibSodium.Bindings.CryptoSign
( -- * Introduction
-- $introduction
-- * Key pair generation
cryptoSignKeyPair
, cryptoSignSeedKeyPair
-- * Combined mode
, cryptoSign
, cryptoSignOpen
-- * Detached Mode
-- $detachedMode
, cryptoSignDetached
, cryptoSignVerifyDetached
-- * Multi-part messages
-- $mpm
, CryptoSignState
, withSignState
, cryptoSignInit
, cryptoSignUpdate
, cryptoSignFinalCreate
, cryptoSignFinalVerify
, cryptoSignED25519SkToSeed
, cryptoSignED25519SkToPk
-- * Constants
, cryptoSignStateBytes
, cryptoSignPublicKeyBytes
, cryptoSignSecretKeyBytes
, cryptoSignBytes
, cryptoSignSeedBytes
)
where
import Foreign (Ptr, allocaBytes)
import Foreign.C (CInt (..), CSize (..), CUChar (..), CULLong (..))
-- $introduction
--
-- When signing with public-key cryptography, a signer generates a key pair consisting of:
--
-- * A secret key, which you can use to append a signature to any number of messages.
-- * A public key, which anybody can use to verify that the signature appended to a
-- message was issued by the creator of the public key.
--
-- Verifiers need to already know and ultimately trust a public key before messages signed using
-- it can be verified.
--
-- Warning: this is different from authenticated encryption. Appending a signature does not change
-- the representation of the message itself.
-------------------------
-- Key pair generation --
-------------------------
-- | Randomly generate a secret key and a corresponding public key.
--
-- /See:/ [crypto_sign_keypair()](https://doc.libsodium.org/public-key_cryptography/public-key_signatures#key-pair-generation)
--
-- @since 0.0.1.0
foreign import capi "sodium.h crypto_sign_keypair"
cryptoSignKeyPair
:: Ptr CUChar
-- ^ A pointer to the buffer holding the public key. It has a length of 'cryptoSignPublicKeyBytes' bytes.
-> Ptr CUChar
-- ^ A pointer to the buffer holding the secret key. It has a length of 'cryptoSignSecretKeyBytes' bytes.
-> IO CInt
-- ^ Returns 0 on success, -1 on error.
-- | Derive a keypair (secret key and public key) from a seed.
-- It is deterministic.
--
-- /See:/ [crypto_sign_seed_keypair()](https://doc.libsodium.org/public-key_cryptography/public-key_signatures#key-pair-generation)
--
-- @since 0.0.1.0
foreign import capi "sodium.h crypto_sign_seed_keypair"
cryptoSignSeedKeyPair
:: Ptr CUChar
-- ^ A pointer to the buffer holding the public key. It has a length of 'cryptoSignPublicKeyBytes'.
-> Ptr CUChar
-- ^ A pointer to the buffer holding the secret key. It has a length of 'cryptoSignSecretKeyBytes'.
-> Ptr CUChar
-- ^ A pointer to the seed. It has a length of 'cryptoSignSeedBytes'.
-> IO CInt
-- ^ Returns 0 on success, -1 on error.
-------------------
-- Combined Mode --
-------------------
-- | Prepend a signature to a message, using the secret key.
--
-- The signed message, which includes the signature plus an unaltered copy of the message, is put
-- into the signed message buffer, and is of length 'cryptoSignBytes' + @length of the message@ bytes.
--
-- If the pointer to the length of the signed message is not a 'Foreign.nullPtr',
-- then the actual length of the signed message is stored in it.
--
-- /See:/ [crypto_sign()](https://doc.libsodium.org/public-key_cryptography/public-key_signatures#combined-mode)
--
-- @since 0.0.1.0
foreign import capi "sodium.h crypto_sign"
cryptoSign
:: Ptr CUChar
-- ^ Pointer to the signed message.
-> Ptr CULLong
-- ^ Pointer to the length of the signed message.
-> Ptr CUChar
-- ^ Pointer to the message to sign.
-> CULLong
-- ^ Length of the message.
-> Ptr CUChar
-- ^ Pointer to the secret key.
-> IO CInt
-- ^ Returns 0 on success, -1 on error.
-- | Check that the signed message has a valid signature for the public key.
--
-- On success, it puts the message, without the signature into the first buffer.
-- The length of the message will be stored in the , if the pointer is not a 'Foreign.nullPtr'.
--
-- /See:/ [crypto_sign_open()](https://doc.libsodium.org/public-key_cryptography/public-key_signatures#key-pair-generation)
--
-- @since 0.0.1.0
foreign import capi "sodium.h crypto_sign_open"
cryptoSignOpen
:: Ptr CUChar
-- ^ Pointer to the buffer holding the message without the signature.
-> Ptr CULLong
-- ^ Pointer to the buffer holding the length of the message, if it
-- is not a 'Foreign.nullPtr'.
-> Ptr CUChar
-- ^ Pointer to the signed message.
-> CULLong
-- ^ Length of the signed message.
-> Ptr CUChar
-- ^ Pointer to the public key.
-> IO CInt
-- ^ On success, the function returns 0
-- If the signature isn't valid, then the function returns -1.
-------------------
-- Detached Mode --
-------------------
-- $detachedMode
--
-- In detached mode, the signature is stored without attaching a copy of the original message to it.
-- | Sign the message using the secret key and put the signature into a buffer, which can be up to
-- 'cryptoSignBytes' bytes long.
-- The actual length of the signature is put into a buffer if its pointer is not 'Foreign.nullPtr'.
-- It is safe to ignore the length of the signature and always consider a signature as 'cryptoSignBytes' bytes long;
-- shorter signatures will be transparently padded with zeros if necessary.
--
-- /See:/ [crypto_sign_detached()](https://doc.libsodium.org/public-key_cryptography/public-key_signatures#detached-mode)
--
-- @since 0.0.1.0
foreign import capi "sodium.h crypto_sign_detached"
cryptoSignDetached
:: Ptr CUChar
-- ^ Pointer to the signature.
-> Ptr CULLong
-- ^ Pointer to the length of the signature.
-> Ptr CUChar
-- ^ Pointer to the message to sign.
-> CULLong
-- ^ Length of the message.
-> Ptr CUChar
-- ^ Pointer to the secret key.
-> IO CInt
-- ^ Returns 0 on success, -1 on error.
-- | Verify that the signature is valid for the message, using the
-- signer's public key.
--
-- /See:/ [crypto_sign_verify_detached()](https://doc.libsodium.org/public-key_cryptography/public-key_signatures#detached-mode)
--
-- @since 0.0.1.0
foreign import capi "sodium.h crypto_sign_verify_detached"
cryptoSignVerifyDetached
:: Ptr CUChar
-- ^ Pointer to the signature
-> Ptr CUChar
-- ^ Pointer to the message
-> CULLong
-- ^ Length of the message
-> Ptr CUChar
-- ^ Pointer to the signer's public key
-> IO CInt
-- ^ Returns 0 on success, -1 on error.
-------------------------
-- Multi-part messages --
-------------------------
-- $mpm
-- If the message you're trying to sign doesn't fit in memory, then it can be provided as a sequence
-- of arbitrarily-sized chunks.
-- This uses the @Ed25519ph@ signature system, which pre-hashes the message. In other words,
-- what gets signed is not the message itself but its image through a hash function. If the message
-- can fit in memory and be supplied as a single chunk, then the single-part API should be
-- preferred.
--
-- == Note
--
-- @Ed25519ph(m)@ is intentionally not equivalent to @Ed25519(SHA512(m))@. If, for
-- some reason, you need to pre-hash the message yourself, then use the multi-part
-- 'LibSodium.Bindings.GenericHashing' module and sign the 512-bit output.
-- | Opaque tag representing the hash state struct @crypto_sign_state@ used by the C API.
--
-- It is of size 'cryptoSignStateBytes'.
--
-- To use a 'CryptoSignState', use 'withSignState'.
--
-- @since 0.0.1.0
data CryptoSignState
-- | Perform an operation with a 'CryptoSignState' of size 'cryptoSignStateBytes' allocated
-- and deallocated automatically.
--
-- ⚠️ The return value of 'withSignState' __MUST NOT__ leak the 'CryptoSignState'.
--
-- Please refer to the documentation of 'Foreign.allocaBytes' for more operational details.
--
-- @since 0.0.1.0
withSignState :: (Ptr CryptoSignState -> IO a) -> IO a
withSignState action = do
let size :: Int = fromIntegral cryptoSignStateBytes
allocaBytes size action
-- | Initialise the 'CryptoSignState' state.
--
-- It must be called before the first 'cryptoSignUpdate' call.
--
-- /See:/ [crypto_sign_init()](https://doc.libsodium.org/public-key_cryptography/public-key_signatures#multi-part-messages)
--
-- @since 0.0.1.0
foreign import capi "sodium.h crypto_sign_init"
cryptoSignInit
:: Ptr CryptoSignState
-- ^ A pointer to the cryptographic state. Cannot be 'Foreign.nullPtr'.
-> IO CInt
-- ^ Returns 0 on success, -1 on error.
-- | Add a new chunk to the message that will eventually be signed.
--
-- After all parts have been supplied, 'cryptoSignFinalCreate' or 'cryptoSignFinalVerify'
-- can be used.
--
-- /See:/ [crypto_sign_update()](https://doc.libsodium.org/public-key_cryptography/public-key_signatures#multi-part-messages)
--
-- @since 0.0.1.0
foreign import capi "sodium.h crypto_sign_update"
cryptoSignUpdate
:: Ptr CryptoSignState
-- ^ A pointer to an initialized cryptographic state. Cannot be 'Foreign.nullPtr'.
-> Ptr CUChar
-- ^ Pointer to the new chunk to sign.
-> CULLong
-- ^ Length of the new chunk.
-> IO CInt
-- ^ Returns 0 on success, -1 on error.
-- | Compute a signature for the previously supplied message
-- using the secret key, and put it into the signature buffer.
--
-- If the pointer to the length of the signature is not a 'Foreign.nullPtr',
-- then the length of the signature is stored at this address.
-- It is safe to ignore the length of the signature and always consider
-- a signature as 'cryptoSignBytes' bytes long;
-- shorter signatures will be transparently padded with zeros if necessary.
--
-- /See:/ [crypto_sign_final_create()](https://doc.libsodium.org/public-key_cryptography/public-key_signatures#multi-part-messages)
--
-- @since 0.0.1.0
foreign import capi "sodium.h crypto_sign_final_create"
cryptoSignFinalCreate
:: Ptr CryptoSignState
-- ^ A pointer to an initialized cryptographic state. Cannot be 'Foreign.nullPtr'.
-> Ptr CUChar
-- ^ Pointer to the signature. Cannot be 'Foreign.nullPtr'.
-> Ptr CULLong
-- ^ A pointer to the length of the signature. Can be 'Foreign.nullPtr'.
-> Ptr CUChar
-- ^ Pointer to the secret key. Cannot be 'Foreign.nullPtr'.
-> IO CInt
-- ^ Returns 0 on success, -1 on error.
-- | Verify that the signature is valid using the public key
-- for the message whose content has been previously supplied using 'cryptoSignUpdate'.
--
-- /See:/ [crypto_sign_final_verify()](https://doc.libsodium.org/public-key_cryptography/public-key_signatures#multi-part-messages)
--
-- @since 0.0.1.0
foreign import capi "sodium.h crypto_sign_final_verify"
cryptoSignFinalVerify
:: Ptr CryptoSignState
-- ^ A pointer to an initialized cryptographic state. Cannot be 'Foreign.nullPtr'.
-> Ptr CUChar
-- ^ Pointer to the signature.
-> Ptr CUChar
-- ^ Pointer to the public key.
-> IO CInt
-- ^ Returns 0 on success, -1 on error.
-- | This function extracts the seed from the
-- secret key secret key and copies it into the buffer holding the seed.
-- The size of the seed will be equal to 'cryptoSignSeedBytes'.
--
-- /See:/ [crypto_sign_ed25519_sk_to_seed()](https://doc.libsodium.org/public-key_cryptography/public-key_signatures#extracting-the-seed-and-the-public-key-from-the-secret-key)
--
-- @since 0.0.1.0
foreign import capi "sodium.h crypto_sign_ed25519_sk_to_seed"
cryptoSignED25519SkToSeed
:: Ptr CUChar
-- ^ Pointer to the seed.
-> Ptr CUChar
-- ^ Pointer to the secret key.
-> IO CInt
-- ^ Returns 0 on success, -1 on error.
-- | This function extracts the public key from the secret key secret key
-- and copies it into public key.
-- The size of public key will be equal to 'cryptoSignPublicKeyBytes'.
--
-- /See:/ [crypto_sign_ed25519_sk_to_pk()](https://doc.libsodium.org/public-key_cryptography/public-key_signatures#extracting-the-seed-and-the-public-key-from-the-secret-key)
--
-- @since 0.0.1.0
foreign import capi "sodium.h crypto_sign_ed25519_sk_to_pk"
cryptoSignED25519SkToPk
:: Ptr CUChar
-- ^ Pointer to the public key.
-> Ptr CUChar
-- ^ Pointer to the secret key.
-> IO CInt
-- ^ Returns 0 on success, -1 on error.
---------------
-- Constants --
---------------
-- | The amount of memory needed to store a 'CryptoSignState'.
--
-- /See:/ [crypto_sign_statebytes](https://doc.libsodium.org/public-key_cryptography/public-key_signatures#constants)
--
-- @since 0.0.1.0
foreign import capi "sodium.h crypto_sign_statebytes"
cryptoSignStateBytes :: CSize
-- |
--
-- /See:/ [crypto_sign_PUBLICKEYBYTES](https://doc.libsodium.org/public-key_cryptography/public-key_signatures#constants)
--
-- @since 0.0.1.0
foreign import capi "sodium.h value crypto_sign_PUBLICKEYBYTES"
cryptoSignPublicKeyBytes :: CSize
-- |
--
-- /See:/ [crypto_sign_SECRETKEYBYTES](https://doc.libsodium.org/public-key_cryptography/public-key_signatures#constants)
--
-- @since 0.0.1.0
foreign import capi "sodium.h value crypto_sign_SECRETKEYBYTES"
cryptoSignSecretKeyBytes :: CSize
-- |
--
-- /See:/ [crypto_sign_BYTES](https://doc.libsodium.org/public-key_cryptography/public-key_signatures#constants)
--
-- @since 0.0.1.0
foreign import capi "sodium.h value crypto_sign_BYTES"
cryptoSignBytes :: CSize
-- |
--
-- /See:/ [crypto_sign_SEEDBYTES](https://doc.libsodium.org/public-key_cryptography/public-key_signatures#constants)
--
-- @since 0.0.1.0
foreign import capi "sodium.h value crypto_sign_SEEDBYTES"
cryptoSignSeedBytes :: CSize