{-# LANGUAGE DeriveDataTypeable, GeneralizedNewtypeDeriving, DeriveGeneric, ForeignFunctionInterface #-} -- | -- Module : Crypto.Saltine.Internal.Stream -- Copyright : (c) Max Amanshauser 2021 -- License : MIT -- -- Maintainer : max@lambdalifting.org -- Stability : experimental -- Portability : non-portable -- module Crypto.Saltine.Internal.Stream ( stream_keybytes , stream_noncebytes , c_stream , c_stream_xor , Key(..) , Nonce(..) ) where import Control.DeepSeq (NFData) import Crypto.Saltine.Class import Crypto.Saltine.Core.Hash (shorthash) import Crypto.Saltine.Internal.Hash (nullShKey) import Crypto.Saltine.Internal.Util as U import Data.ByteString (ByteString) import Data.Data (Data, Typeable) import Data.Hashable (Hashable) import Data.Monoid import Foreign.C import Foreign.Ptr import GHC.Generics (Generic) import qualified Data.ByteString as S -- | An opaque 'stream' cryptographic key. newtype Key = Key { unKey :: ByteString } deriving (Ord, Hashable, Data, Typeable, Generic, NFData) instance Eq Key where Key a == Key b = U.compare a b instance Show Key where show k = "Stream.Key {hashesTo = \"" <> (bin2hex . shorthash nullShKey $ encode k) <> "\"}" instance IsEncoding Key where decode v = if S.length v == stream_keybytes then Just (Key v) else Nothing {-# INLINE decode #-} encode (Key v) = v {-# INLINE encode #-} -- | An opaque 'stream' nonce. newtype Nonce = Nonce { unNonce :: ByteString } deriving (Eq, Ord, Hashable, Data, Typeable, Generic, NFData) instance Show Nonce where show k = "Stream.Nonce " <> bin2hex (encode k) instance IsNonce Nonce where zero = Nonce (S.replicate stream_noncebytes 0) nudge (Nonce n) = Nonce (nudgeBS n) instance IsEncoding Nonce where decode v = if S.length v == stream_noncebytes then Just (Nonce v) else Nothing {-# INLINE decode #-} encode (Nonce v) = v {-# INLINE encode #-} stream_keybytes, stream_noncebytes :: Int -- Streams -- | The size of a key for the cryptographic stream generation stream_keybytes = fromIntegral c_crypto_stream_keybytes -- | The size of a nonce for the cryptographic stream generation stream_noncebytes = fromIntegral c_crypto_stream_noncebytes -- src/libsodium/crypto_stream/crypto_stream.c -- src/libsodium/include/sodium/crypto_stream.h foreign import ccall "crypto_stream_keybytes" c_crypto_stream_keybytes :: CSize foreign import ccall "crypto_stream_noncebytes" c_crypto_stream_noncebytes :: CSize foreign import ccall "crypto_stream" c_stream :: Ptr CChar -- ^ Stream output buffer -> CULLong -- ^ Length of stream to generate -> Ptr CChar -- ^ Constant nonce buffer -> Ptr CChar -- ^ Constant key buffer -> IO CInt -- ^ Always 0 foreign import ccall "crypto_stream_xor" c_stream_xor :: Ptr CChar -- ^ Ciphertext output buffer -> Ptr CChar -- ^ Constant message buffer -> CULLong -- ^ Length of message buffer -> Ptr CChar -- ^ Constant nonce buffer -> Ptr CChar -- ^ Constant key buffer -> IO CInt -- ^ Always 0