packages feed

saltine 0.1.1.1 → 0.2.0.0

raw patch · 64 files changed

+5247/−1504 lines, 64 filesdep +criteriondep +deepseqdep +textdep ~basedep ~bytestringPVP ok

version bump matches the API change (PVP)

Dependencies added: criterion, deepseq, text

Dependency ranges changed: base, bytestring

API changes (from Hackage documentation)

- Crypto.Saltine.Core.AEAD: aead :: Key -> Nonce -> ByteString -> ByteString -> ByteString
- Crypto.Saltine.Core.AEAD: aeadDetached :: Key -> Nonce -> ByteString -> ByteString -> (ByteString, ByteString)
- Crypto.Saltine.Core.AEAD: aeadOpen :: Key -> Nonce -> ByteString -> ByteString -> Maybe ByteString
- Crypto.Saltine.Core.AEAD: aeadOpenDetached :: Key -> Nonce -> ByteString -> ByteString -> ByteString -> Maybe ByteString
- Crypto.Saltine.Core.AEAD: data Key
- Crypto.Saltine.Core.AEAD: data Nonce
- Crypto.Saltine.Core.AEAD: instance Crypto.Saltine.Class.IsEncoding Crypto.Saltine.Core.AEAD.Key
- Crypto.Saltine.Core.AEAD: instance Crypto.Saltine.Class.IsEncoding Crypto.Saltine.Core.AEAD.Nonce
- Crypto.Saltine.Core.AEAD: instance Crypto.Saltine.Class.IsNonce Crypto.Saltine.Core.AEAD.Nonce
- Crypto.Saltine.Core.AEAD: instance Data.Data.Data Crypto.Saltine.Core.AEAD.Key
- Crypto.Saltine.Core.AEAD: instance Data.Data.Data Crypto.Saltine.Core.AEAD.Nonce
- Crypto.Saltine.Core.AEAD: instance Data.Hashable.Class.Hashable Crypto.Saltine.Core.AEAD.Key
- Crypto.Saltine.Core.AEAD: instance Data.Hashable.Class.Hashable Crypto.Saltine.Core.AEAD.Nonce
- Crypto.Saltine.Core.AEAD: instance GHC.Classes.Eq Crypto.Saltine.Core.AEAD.Key
- Crypto.Saltine.Core.AEAD: instance GHC.Classes.Eq Crypto.Saltine.Core.AEAD.Nonce
- Crypto.Saltine.Core.AEAD: instance GHC.Classes.Ord Crypto.Saltine.Core.AEAD.Key
- Crypto.Saltine.Core.AEAD: instance GHC.Classes.Ord Crypto.Saltine.Core.AEAD.Nonce
- Crypto.Saltine.Core.AEAD: instance GHC.Generics.Generic Crypto.Saltine.Core.AEAD.Key
- Crypto.Saltine.Core.AEAD: instance GHC.Generics.Generic Crypto.Saltine.Core.AEAD.Nonce
- Crypto.Saltine.Core.AEAD: newKey :: IO Key
- Crypto.Saltine.Core.AEAD: newNonce :: IO Nonce
- Crypto.Saltine.Core.Auth: instance Crypto.Saltine.Class.IsEncoding Crypto.Saltine.Core.Auth.Authenticator
- Crypto.Saltine.Core.Auth: instance Crypto.Saltine.Class.IsEncoding Crypto.Saltine.Core.Auth.Key
- Crypto.Saltine.Core.Auth: instance Data.Data.Data Crypto.Saltine.Core.Auth.Authenticator
- Crypto.Saltine.Core.Auth: instance Data.Data.Data Crypto.Saltine.Core.Auth.Key
- Crypto.Saltine.Core.Auth: instance Data.Hashable.Class.Hashable Crypto.Saltine.Core.Auth.Authenticator
- Crypto.Saltine.Core.Auth: instance Data.Hashable.Class.Hashable Crypto.Saltine.Core.Auth.Key
- Crypto.Saltine.Core.Auth: instance GHC.Classes.Eq Crypto.Saltine.Core.Auth.Authenticator
- Crypto.Saltine.Core.Auth: instance GHC.Classes.Eq Crypto.Saltine.Core.Auth.Key
- Crypto.Saltine.Core.Auth: instance GHC.Classes.Ord Crypto.Saltine.Core.Auth.Authenticator
- Crypto.Saltine.Core.Auth: instance GHC.Classes.Ord Crypto.Saltine.Core.Auth.Key
- Crypto.Saltine.Core.Auth: instance GHC.Generics.Generic Crypto.Saltine.Core.Auth.Authenticator
- Crypto.Saltine.Core.Auth: instance GHC.Generics.Generic Crypto.Saltine.Core.Auth.Key
- Crypto.Saltine.Core.Box: instance Crypto.Saltine.Class.IsEncoding Crypto.Saltine.Core.Box.CombinedKey
- Crypto.Saltine.Core.Box: instance Crypto.Saltine.Class.IsEncoding Crypto.Saltine.Core.Box.Nonce
- Crypto.Saltine.Core.Box: instance Crypto.Saltine.Class.IsEncoding Crypto.Saltine.Core.Box.PublicKey
- Crypto.Saltine.Core.Box: instance Crypto.Saltine.Class.IsEncoding Crypto.Saltine.Core.Box.SecretKey
- Crypto.Saltine.Core.Box: instance Crypto.Saltine.Class.IsNonce Crypto.Saltine.Core.Box.Nonce
- Crypto.Saltine.Core.Box: instance Data.Data.Data Crypto.Saltine.Core.Box.CombinedKey
- Crypto.Saltine.Core.Box: instance Data.Data.Data Crypto.Saltine.Core.Box.Nonce
- Crypto.Saltine.Core.Box: instance Data.Data.Data Crypto.Saltine.Core.Box.PublicKey
- Crypto.Saltine.Core.Box: instance Data.Data.Data Crypto.Saltine.Core.Box.SecretKey
- Crypto.Saltine.Core.Box: instance Data.Hashable.Class.Hashable Crypto.Saltine.Core.Box.CombinedKey
- Crypto.Saltine.Core.Box: instance Data.Hashable.Class.Hashable Crypto.Saltine.Core.Box.Nonce
- Crypto.Saltine.Core.Box: instance Data.Hashable.Class.Hashable Crypto.Saltine.Core.Box.PublicKey
- Crypto.Saltine.Core.Box: instance Data.Hashable.Class.Hashable Crypto.Saltine.Core.Box.SecretKey
- Crypto.Saltine.Core.Box: instance GHC.Classes.Eq Crypto.Saltine.Core.Box.CombinedKey
- Crypto.Saltine.Core.Box: instance GHC.Classes.Eq Crypto.Saltine.Core.Box.Nonce
- Crypto.Saltine.Core.Box: instance GHC.Classes.Eq Crypto.Saltine.Core.Box.PublicKey
- Crypto.Saltine.Core.Box: instance GHC.Classes.Eq Crypto.Saltine.Core.Box.SecretKey
- Crypto.Saltine.Core.Box: instance GHC.Classes.Ord Crypto.Saltine.Core.Box.CombinedKey
- Crypto.Saltine.Core.Box: instance GHC.Classes.Ord Crypto.Saltine.Core.Box.Nonce
- Crypto.Saltine.Core.Box: instance GHC.Classes.Ord Crypto.Saltine.Core.Box.PublicKey
- Crypto.Saltine.Core.Box: instance GHC.Classes.Ord Crypto.Saltine.Core.Box.SecretKey
- Crypto.Saltine.Core.Box: instance GHC.Generics.Generic Crypto.Saltine.Core.Box.CombinedKey
- Crypto.Saltine.Core.Box: instance GHC.Generics.Generic Crypto.Saltine.Core.Box.Nonce
- Crypto.Saltine.Core.Box: instance GHC.Generics.Generic Crypto.Saltine.Core.Box.PublicKey
- Crypto.Saltine.Core.Box: instance GHC.Generics.Generic Crypto.Saltine.Core.Box.SecretKey
- Crypto.Saltine.Core.Box: type Keypair = (SecretKey, PublicKey)
- Crypto.Saltine.Core.Hash: instance Crypto.Saltine.Class.IsEncoding Crypto.Saltine.Core.Hash.GenerichashKey
- Crypto.Saltine.Core.Hash: instance Crypto.Saltine.Class.IsEncoding Crypto.Saltine.Core.Hash.ShorthashKey
- Crypto.Saltine.Core.Hash: instance Data.Data.Data Crypto.Saltine.Core.Hash.GenerichashKey
- Crypto.Saltine.Core.Hash: instance Data.Data.Data Crypto.Saltine.Core.Hash.GenerichashOutLen
- Crypto.Saltine.Core.Hash: instance Data.Data.Data Crypto.Saltine.Core.Hash.ShorthashKey
- Crypto.Saltine.Core.Hash: instance Data.Hashable.Class.Hashable Crypto.Saltine.Core.Hash.GenerichashKey
- Crypto.Saltine.Core.Hash: instance Data.Hashable.Class.Hashable Crypto.Saltine.Core.Hash.GenerichashOutLen
- Crypto.Saltine.Core.Hash: instance Data.Hashable.Class.Hashable Crypto.Saltine.Core.Hash.ShorthashKey
- Crypto.Saltine.Core.Hash: instance GHC.Classes.Eq Crypto.Saltine.Core.Hash.GenerichashKey
- Crypto.Saltine.Core.Hash: instance GHC.Classes.Eq Crypto.Saltine.Core.Hash.GenerichashOutLen
- Crypto.Saltine.Core.Hash: instance GHC.Classes.Eq Crypto.Saltine.Core.Hash.ShorthashKey
- Crypto.Saltine.Core.Hash: instance GHC.Classes.Ord Crypto.Saltine.Core.Hash.GenerichashKey
- Crypto.Saltine.Core.Hash: instance GHC.Classes.Ord Crypto.Saltine.Core.Hash.GenerichashOutLen
- Crypto.Saltine.Core.Hash: instance GHC.Classes.Ord Crypto.Saltine.Core.Hash.ShorthashKey
- Crypto.Saltine.Core.Hash: instance GHC.Generics.Generic Crypto.Saltine.Core.Hash.GenerichashKey
- Crypto.Saltine.Core.Hash: instance GHC.Generics.Generic Crypto.Saltine.Core.Hash.GenerichashOutLen
- Crypto.Saltine.Core.Hash: instance GHC.Generics.Generic Crypto.Saltine.Core.Hash.ShorthashKey
- Crypto.Saltine.Core.OneTimeAuth: instance Crypto.Saltine.Class.IsEncoding Crypto.Saltine.Core.OneTimeAuth.Authenticator
- Crypto.Saltine.Core.OneTimeAuth: instance Crypto.Saltine.Class.IsEncoding Crypto.Saltine.Core.OneTimeAuth.Key
- Crypto.Saltine.Core.OneTimeAuth: instance Data.Data.Data Crypto.Saltine.Core.OneTimeAuth.Authenticator
- Crypto.Saltine.Core.OneTimeAuth: instance Data.Data.Data Crypto.Saltine.Core.OneTimeAuth.Key
- Crypto.Saltine.Core.OneTimeAuth: instance Data.Hashable.Class.Hashable Crypto.Saltine.Core.OneTimeAuth.Authenticator
- Crypto.Saltine.Core.OneTimeAuth: instance Data.Hashable.Class.Hashable Crypto.Saltine.Core.OneTimeAuth.Key
- Crypto.Saltine.Core.OneTimeAuth: instance GHC.Classes.Eq Crypto.Saltine.Core.OneTimeAuth.Authenticator
- Crypto.Saltine.Core.OneTimeAuth: instance GHC.Classes.Eq Crypto.Saltine.Core.OneTimeAuth.Key
- Crypto.Saltine.Core.OneTimeAuth: instance GHC.Classes.Ord Crypto.Saltine.Core.OneTimeAuth.Authenticator
- Crypto.Saltine.Core.OneTimeAuth: instance GHC.Classes.Ord Crypto.Saltine.Core.OneTimeAuth.Key
- Crypto.Saltine.Core.OneTimeAuth: instance GHC.Generics.Generic Crypto.Saltine.Core.OneTimeAuth.Authenticator
- Crypto.Saltine.Core.OneTimeAuth: instance GHC.Generics.Generic Crypto.Saltine.Core.OneTimeAuth.Key
- Crypto.Saltine.Core.ScalarMult: instance Crypto.Saltine.Class.IsEncoding Crypto.Saltine.Core.ScalarMult.GroupElement
- Crypto.Saltine.Core.ScalarMult: instance Crypto.Saltine.Class.IsEncoding Crypto.Saltine.Core.ScalarMult.Scalar
- Crypto.Saltine.Core.ScalarMult: instance Data.Data.Data Crypto.Saltine.Core.ScalarMult.GroupElement
- Crypto.Saltine.Core.ScalarMult: instance Data.Data.Data Crypto.Saltine.Core.ScalarMult.Scalar
- Crypto.Saltine.Core.ScalarMult: instance Data.Hashable.Class.Hashable Crypto.Saltine.Core.ScalarMult.GroupElement
- Crypto.Saltine.Core.ScalarMult: instance Data.Hashable.Class.Hashable Crypto.Saltine.Core.ScalarMult.Scalar
- Crypto.Saltine.Core.ScalarMult: instance GHC.Classes.Eq Crypto.Saltine.Core.ScalarMult.GroupElement
- Crypto.Saltine.Core.ScalarMult: instance GHC.Classes.Eq Crypto.Saltine.Core.ScalarMult.Scalar
- Crypto.Saltine.Core.ScalarMult: instance GHC.Classes.Ord Crypto.Saltine.Core.ScalarMult.GroupElement
- Crypto.Saltine.Core.ScalarMult: instance GHC.Classes.Ord Crypto.Saltine.Core.ScalarMult.Scalar
- Crypto.Saltine.Core.ScalarMult: instance GHC.Generics.Generic Crypto.Saltine.Core.ScalarMult.GroupElement
- Crypto.Saltine.Core.ScalarMult: instance GHC.Generics.Generic Crypto.Saltine.Core.ScalarMult.Scalar
- Crypto.Saltine.Core.SecretBox: instance Crypto.Saltine.Class.IsEncoding Crypto.Saltine.Core.SecretBox.Key
- Crypto.Saltine.Core.SecretBox: instance Crypto.Saltine.Class.IsEncoding Crypto.Saltine.Core.SecretBox.Nonce
- Crypto.Saltine.Core.SecretBox: instance Crypto.Saltine.Class.IsNonce Crypto.Saltine.Core.SecretBox.Nonce
- Crypto.Saltine.Core.SecretBox: instance Data.Data.Data Crypto.Saltine.Core.SecretBox.Key
- Crypto.Saltine.Core.SecretBox: instance Data.Data.Data Crypto.Saltine.Core.SecretBox.Nonce
- Crypto.Saltine.Core.SecretBox: instance Data.Hashable.Class.Hashable Crypto.Saltine.Core.SecretBox.Key
- Crypto.Saltine.Core.SecretBox: instance Data.Hashable.Class.Hashable Crypto.Saltine.Core.SecretBox.Nonce
- Crypto.Saltine.Core.SecretBox: instance GHC.Classes.Eq Crypto.Saltine.Core.SecretBox.Key
- Crypto.Saltine.Core.SecretBox: instance GHC.Classes.Eq Crypto.Saltine.Core.SecretBox.Nonce
- Crypto.Saltine.Core.SecretBox: instance GHC.Classes.Ord Crypto.Saltine.Core.SecretBox.Key
- Crypto.Saltine.Core.SecretBox: instance GHC.Classes.Ord Crypto.Saltine.Core.SecretBox.Nonce
- Crypto.Saltine.Core.SecretBox: instance GHC.Generics.Generic Crypto.Saltine.Core.SecretBox.Key
- Crypto.Saltine.Core.SecretBox: instance GHC.Generics.Generic Crypto.Saltine.Core.SecretBox.Nonce
- Crypto.Saltine.Core.Sign: instance Crypto.Saltine.Class.IsEncoding Crypto.Saltine.Core.Sign.PublicKey
- Crypto.Saltine.Core.Sign: instance Crypto.Saltine.Class.IsEncoding Crypto.Saltine.Core.Sign.SecretKey
- Crypto.Saltine.Core.Sign: instance Data.Data.Data Crypto.Saltine.Core.Sign.PublicKey
- Crypto.Saltine.Core.Sign: instance Data.Data.Data Crypto.Saltine.Core.Sign.SecretKey
- Crypto.Saltine.Core.Sign: instance Data.Hashable.Class.Hashable Crypto.Saltine.Core.Sign.PublicKey
- Crypto.Saltine.Core.Sign: instance Data.Hashable.Class.Hashable Crypto.Saltine.Core.Sign.SecretKey
- Crypto.Saltine.Core.Sign: instance GHC.Classes.Eq Crypto.Saltine.Core.Sign.PublicKey
- Crypto.Saltine.Core.Sign: instance GHC.Classes.Eq Crypto.Saltine.Core.Sign.SecretKey
- Crypto.Saltine.Core.Sign: instance GHC.Classes.Ord Crypto.Saltine.Core.Sign.PublicKey
- Crypto.Saltine.Core.Sign: instance GHC.Classes.Ord Crypto.Saltine.Core.Sign.SecretKey
- Crypto.Saltine.Core.Sign: instance GHC.Generics.Generic Crypto.Saltine.Core.Sign.PublicKey
- Crypto.Saltine.Core.Sign: instance GHC.Generics.Generic Crypto.Saltine.Core.Sign.SecretKey
- Crypto.Saltine.Core.Sign: type Keypair = (SecretKey, PublicKey)
- Crypto.Saltine.Core.Stream: instance Crypto.Saltine.Class.IsEncoding Crypto.Saltine.Core.Stream.Key
- Crypto.Saltine.Core.Stream: instance Crypto.Saltine.Class.IsEncoding Crypto.Saltine.Core.Stream.Nonce
- Crypto.Saltine.Core.Stream: instance Crypto.Saltine.Class.IsNonce Crypto.Saltine.Core.Stream.Nonce
- Crypto.Saltine.Core.Stream: instance Data.Data.Data Crypto.Saltine.Core.Stream.Key
- Crypto.Saltine.Core.Stream: instance Data.Data.Data Crypto.Saltine.Core.Stream.Nonce
- Crypto.Saltine.Core.Stream: instance Data.Hashable.Class.Hashable Crypto.Saltine.Core.Stream.Key
- Crypto.Saltine.Core.Stream: instance Data.Hashable.Class.Hashable Crypto.Saltine.Core.Stream.Nonce
- Crypto.Saltine.Core.Stream: instance GHC.Classes.Eq Crypto.Saltine.Core.Stream.Key
- Crypto.Saltine.Core.Stream: instance GHC.Classes.Eq Crypto.Saltine.Core.Stream.Nonce
- Crypto.Saltine.Core.Stream: instance GHC.Classes.Ord Crypto.Saltine.Core.Stream.Key
- Crypto.Saltine.Core.Stream: instance GHC.Classes.Ord Crypto.Saltine.Core.Stream.Nonce
- Crypto.Saltine.Core.Stream: instance GHC.Generics.Generic Crypto.Saltine.Core.Stream.Key
- Crypto.Saltine.Core.Stream: instance GHC.Generics.Generic Crypto.Saltine.Core.Stream.Nonce
- Crypto.Saltine.Internal.ByteSizes: aead_xchacha20poly1305_ietf_ABYTES :: Int
- Crypto.Saltine.Internal.ByteSizes: auth :: Int
- Crypto.Saltine.Internal.ByteSizes: authKey :: Int
- Crypto.Saltine.Internal.ByteSizes: boxBeforeNM :: Int
- Crypto.Saltine.Internal.ByteSizes: boxBoxZero :: Int
- Crypto.Saltine.Internal.ByteSizes: boxMac :: Int
- Crypto.Saltine.Internal.ByteSizes: boxNonce :: Int
- Crypto.Saltine.Internal.ByteSizes: boxPK :: Int
- Crypto.Saltine.Internal.ByteSizes: boxSK :: Int
- Crypto.Saltine.Internal.ByteSizes: boxZero :: Int
- Crypto.Saltine.Internal.ByteSizes: generichashKeyLenMax :: Int
- Crypto.Saltine.Internal.ByteSizes: generichashOutLenMax :: Int
- Crypto.Saltine.Internal.ByteSizes: hash :: Int
- Crypto.Saltine.Internal.ByteSizes: mult :: Int
- Crypto.Saltine.Internal.ByteSizes: multScalar :: Int
- Crypto.Saltine.Internal.ByteSizes: onetime :: Int
- Crypto.Saltine.Internal.ByteSizes: onetimeKey :: Int
- Crypto.Saltine.Internal.ByteSizes: sealedBox :: Int
- Crypto.Saltine.Internal.ByteSizes: secretBoxBoxZero :: Int
- Crypto.Saltine.Internal.ByteSizes: secretBoxKey :: Int
- Crypto.Saltine.Internal.ByteSizes: secretBoxMac :: Int
- Crypto.Saltine.Internal.ByteSizes: secretBoxNonce :: Int
- Crypto.Saltine.Internal.ByteSizes: secretBoxZero :: Int
- Crypto.Saltine.Internal.ByteSizes: shorthash :: Int
- Crypto.Saltine.Internal.ByteSizes: shorthashKey :: Int
- Crypto.Saltine.Internal.ByteSizes: sign :: Int
- Crypto.Saltine.Internal.ByteSizes: signPK :: Int
- Crypto.Saltine.Internal.ByteSizes: signSK :: Int
- Crypto.Saltine.Internal.ByteSizes: streamKey :: Int
- Crypto.Saltine.Internal.ByteSizes: streamNonce :: Int
+ Crypto.Saltine.Core.AEAD.AES256GCM: aead :: Key -> Nonce -> ByteString -> ByteString -> ByteString
+ Crypto.Saltine.Core.AEAD.AES256GCM: aeadDetached :: Key -> Nonce -> ByteString -> ByteString -> (ByteString, ByteString)
+ Crypto.Saltine.Core.AEAD.AES256GCM: aeadOpen :: Key -> Nonce -> ByteString -> ByteString -> Maybe ByteString
+ Crypto.Saltine.Core.AEAD.AES256GCM: aeadOpenDetached :: Key -> Nonce -> ByteString -> ByteString -> ByteString -> Maybe ByteString
+ Crypto.Saltine.Core.AEAD.AES256GCM: aead_aes256gcm_available :: Bool
+ Crypto.Saltine.Core.AEAD.AES256GCM: data Key
+ Crypto.Saltine.Core.AEAD.AES256GCM: data Nonce
+ Crypto.Saltine.Core.AEAD.AES256GCM: newKey :: IO Key
+ Crypto.Saltine.Core.AEAD.AES256GCM: newNonce :: IO Nonce
+ Crypto.Saltine.Core.AEAD.ChaCha20Poly1305: aead :: Key -> Nonce -> ByteString -> ByteString -> ByteString
+ Crypto.Saltine.Core.AEAD.ChaCha20Poly1305: aeadDetached :: Key -> Nonce -> ByteString -> ByteString -> (ByteString, ByteString)
+ Crypto.Saltine.Core.AEAD.ChaCha20Poly1305: aeadOpen :: Key -> Nonce -> ByteString -> ByteString -> Maybe ByteString
+ Crypto.Saltine.Core.AEAD.ChaCha20Poly1305: aeadOpenDetached :: Key -> Nonce -> ByteString -> ByteString -> ByteString -> Maybe ByteString
+ Crypto.Saltine.Core.AEAD.ChaCha20Poly1305: data Key
+ Crypto.Saltine.Core.AEAD.ChaCha20Poly1305: data Nonce
+ Crypto.Saltine.Core.AEAD.ChaCha20Poly1305: newKey :: IO Key
+ Crypto.Saltine.Core.AEAD.ChaCha20Poly1305: newNonce :: IO Nonce
+ Crypto.Saltine.Core.AEAD.ChaCha20Poly1305IETF: aead :: Key -> Nonce -> ByteString -> ByteString -> ByteString
+ Crypto.Saltine.Core.AEAD.ChaCha20Poly1305IETF: aeadDetached :: Key -> Nonce -> ByteString -> ByteString -> (ByteString, ByteString)
+ Crypto.Saltine.Core.AEAD.ChaCha20Poly1305IETF: aeadOpen :: Key -> Nonce -> ByteString -> ByteString -> Maybe ByteString
+ Crypto.Saltine.Core.AEAD.ChaCha20Poly1305IETF: aeadOpenDetached :: Key -> Nonce -> ByteString -> ByteString -> ByteString -> Maybe ByteString
+ Crypto.Saltine.Core.AEAD.ChaCha20Poly1305IETF: data Key
+ Crypto.Saltine.Core.AEAD.ChaCha20Poly1305IETF: data Nonce
+ Crypto.Saltine.Core.AEAD.ChaCha20Poly1305IETF: newKey :: IO Key
+ Crypto.Saltine.Core.AEAD.ChaCha20Poly1305IETF: newNonce :: IO Nonce
+ Crypto.Saltine.Core.AEAD.XChaCha20Poly1305: aead :: Key -> Nonce -> ByteString -> ByteString -> ByteString
+ Crypto.Saltine.Core.AEAD.XChaCha20Poly1305: aeadDetached :: Key -> Nonce -> ByteString -> ByteString -> (ByteString, ByteString)
+ Crypto.Saltine.Core.AEAD.XChaCha20Poly1305: aeadOpen :: Key -> Nonce -> ByteString -> ByteString -> Maybe ByteString
+ Crypto.Saltine.Core.AEAD.XChaCha20Poly1305: aeadOpenDetached :: Key -> Nonce -> ByteString -> ByteString -> ByteString -> Maybe ByteString
+ Crypto.Saltine.Core.AEAD.XChaCha20Poly1305: data Key
+ Crypto.Saltine.Core.AEAD.XChaCha20Poly1305: data Nonce
+ Crypto.Saltine.Core.AEAD.XChaCha20Poly1305: newKey :: IO Key
+ Crypto.Saltine.Core.AEAD.XChaCha20Poly1305: newNonce :: IO Nonce
+ Crypto.Saltine.Core.Box: Keypair :: SecretKey -> PublicKey -> Keypair
+ Crypto.Saltine.Core.Box: [publicKey] :: Keypair -> PublicKey
+ Crypto.Saltine.Core.Box: [secretKey] :: Keypair -> SecretKey
+ Crypto.Saltine.Core.Box: data Keypair
+ Crypto.Saltine.Core.Password: Policy :: Opslimit -> Memlimit -> Algorithm -> Policy
+ Crypto.Saltine.Core.Password: [algPolicy] :: Policy -> Algorithm
+ Crypto.Saltine.Core.Password: [memPolicy] :: Policy -> Memlimit
+ Crypto.Saltine.Core.Password: [opsPolicy] :: Policy -> Opslimit
+ Crypto.Saltine.Core.Password: data Algorithm
+ Crypto.Saltine.Core.Password: data Memlimit
+ Crypto.Saltine.Core.Password: data Opslimit
+ Crypto.Saltine.Core.Password: data Policy
+ Crypto.Saltine.Core.Password: data Salt
+ Crypto.Saltine.Core.Password: defaultAlgorithm :: Algorithm
+ Crypto.Saltine.Core.Password: getMemlimit :: Memlimit -> Int
+ Crypto.Saltine.Core.Password: getOpslimit :: Opslimit -> Int
+ Crypto.Saltine.Core.Password: interactivePolicy :: Policy
+ Crypto.Saltine.Core.Password: maxMemlimit :: Algorithm -> Memlimit
+ Crypto.Saltine.Core.Password: maxOpslimit :: Algorithm -> Opslimit
+ Crypto.Saltine.Core.Password: memlimit :: Algorithm -> Int -> Maybe Memlimit
+ Crypto.Saltine.Core.Password: memlimitInteractive :: Algorithm -> Memlimit
+ Crypto.Saltine.Core.Password: memlimitModerate :: Algorithm -> Memlimit
+ Crypto.Saltine.Core.Password: memlimitSensitive :: Algorithm -> Memlimit
+ Crypto.Saltine.Core.Password: minMemlimit :: Algorithm -> Memlimit
+ Crypto.Saltine.Core.Password: minOpslimit :: Algorithm -> Opslimit
+ Crypto.Saltine.Core.Password: moderatePolicy :: Policy
+ Crypto.Saltine.Core.Password: needsRehash :: Opslimit -> Memlimit -> PasswordHash -> Maybe Bool
+ Crypto.Saltine.Core.Password: newSalt :: IO Salt
+ Crypto.Saltine.Core.Password: opslimit :: Algorithm -> Int -> Maybe Opslimit
+ Crypto.Saltine.Core.Password: opslimitInteractive :: Algorithm -> Opslimit
+ Crypto.Saltine.Core.Password: opslimitModerate :: Algorithm -> Opslimit
+ Crypto.Saltine.Core.Password: opslimitSensitive :: Algorithm -> Opslimit
+ Crypto.Saltine.Core.Password: pwhash :: Text -> Int -> Salt -> Policy -> Maybe ByteString
+ Crypto.Saltine.Core.Password: pwhashStr :: Text -> Policy -> IO (Maybe PasswordHash)
+ Crypto.Saltine.Core.Password: pwhashStrVerify :: PasswordHash -> Text -> Bool
+ Crypto.Saltine.Core.Password: sensitivePolicy :: Policy
+ Crypto.Saltine.Core.SecretBox: data Authenticator
+ Crypto.Saltine.Core.Sign: Keypair :: SecretKey -> PublicKey -> Keypair
+ Crypto.Saltine.Core.Sign: [publicKey] :: Keypair -> PublicKey
+ Crypto.Saltine.Core.Sign: [secretKey] :: Keypair -> SecretKey
+ Crypto.Saltine.Core.Sign: data Keypair
+ Crypto.Saltine.Core.Sign: data Signature
+ Crypto.Saltine.Core.Utils: bin2hex :: ByteString -> String
+ Crypto.Saltine.Internal.AEAD.AES256GCM: Key :: ByteString -> Key
+ Crypto.Saltine.Internal.AEAD.AES256GCM: Nonce :: ByteString -> Nonce
+ Crypto.Saltine.Internal.AEAD.AES256GCM: [unKey] :: Key -> ByteString
+ Crypto.Saltine.Internal.AEAD.AES256GCM: [unNonce] :: Nonce -> ByteString
+ Crypto.Saltine.Internal.AEAD.AES256GCM: aead_aes256gcm_abytes :: Int
+ Crypto.Saltine.Internal.AEAD.AES256GCM: aead_aes256gcm_keybytes :: Int
+ Crypto.Saltine.Internal.AEAD.AES256GCM: aead_aes256gcm_npubbytes :: Int
+ Crypto.Saltine.Internal.AEAD.AES256GCM: c_aead :: Ptr CChar -> Ptr CULLong -> Ptr CChar -> CULLong -> Ptr CChar -> CULLong -> Ptr CChar -> Ptr CChar -> Ptr CChar -> IO CInt
+ Crypto.Saltine.Internal.AEAD.AES256GCM: c_aead_aes256gcm_is_available :: IO CInt
+ Crypto.Saltine.Internal.AEAD.AES256GCM: c_aead_detached :: Ptr CChar -> Ptr CChar -> Ptr CULLong -> Ptr CChar -> CULLong -> Ptr CChar -> CULLong -> Ptr CChar -> Ptr CChar -> Ptr CChar -> IO CInt
+ Crypto.Saltine.Internal.AEAD.AES256GCM: c_aead_open :: Ptr CChar -> Ptr CULLong -> Ptr CChar -> Ptr CChar -> CULLong -> Ptr CChar -> CULLong -> Ptr CChar -> Ptr CChar -> IO CInt
+ Crypto.Saltine.Internal.AEAD.AES256GCM: c_aead_open_detached :: Ptr CChar -> Ptr CChar -> Ptr CChar -> CULLong -> Ptr CChar -> Ptr CChar -> CULLong -> Ptr CChar -> Ptr CChar -> IO CInt
+ Crypto.Saltine.Internal.AEAD.AES256GCM: instance Control.DeepSeq.NFData Crypto.Saltine.Internal.AEAD.AES256GCM.Key
+ Crypto.Saltine.Internal.AEAD.AES256GCM: instance Control.DeepSeq.NFData Crypto.Saltine.Internal.AEAD.AES256GCM.Nonce
+ Crypto.Saltine.Internal.AEAD.AES256GCM: instance Crypto.Saltine.Class.IsEncoding Crypto.Saltine.Internal.AEAD.AES256GCM.Key
+ Crypto.Saltine.Internal.AEAD.AES256GCM: instance Crypto.Saltine.Class.IsEncoding Crypto.Saltine.Internal.AEAD.AES256GCM.Nonce
+ Crypto.Saltine.Internal.AEAD.AES256GCM: instance Crypto.Saltine.Class.IsNonce Crypto.Saltine.Internal.AEAD.AES256GCM.Nonce
+ Crypto.Saltine.Internal.AEAD.AES256GCM: instance Data.Data.Data Crypto.Saltine.Internal.AEAD.AES256GCM.Key
+ Crypto.Saltine.Internal.AEAD.AES256GCM: instance Data.Data.Data Crypto.Saltine.Internal.AEAD.AES256GCM.Nonce
+ Crypto.Saltine.Internal.AEAD.AES256GCM: instance Data.Hashable.Class.Hashable Crypto.Saltine.Internal.AEAD.AES256GCM.Key
+ Crypto.Saltine.Internal.AEAD.AES256GCM: instance Data.Hashable.Class.Hashable Crypto.Saltine.Internal.AEAD.AES256GCM.Nonce
+ Crypto.Saltine.Internal.AEAD.AES256GCM: instance GHC.Classes.Eq Crypto.Saltine.Internal.AEAD.AES256GCM.Key
+ Crypto.Saltine.Internal.AEAD.AES256GCM: instance GHC.Classes.Eq Crypto.Saltine.Internal.AEAD.AES256GCM.Nonce
+ Crypto.Saltine.Internal.AEAD.AES256GCM: instance GHC.Classes.Ord Crypto.Saltine.Internal.AEAD.AES256GCM.Key
+ Crypto.Saltine.Internal.AEAD.AES256GCM: instance GHC.Classes.Ord Crypto.Saltine.Internal.AEAD.AES256GCM.Nonce
+ Crypto.Saltine.Internal.AEAD.AES256GCM: instance GHC.Generics.Generic Crypto.Saltine.Internal.AEAD.AES256GCM.Key
+ Crypto.Saltine.Internal.AEAD.AES256GCM: instance GHC.Generics.Generic Crypto.Saltine.Internal.AEAD.AES256GCM.Nonce
+ Crypto.Saltine.Internal.AEAD.AES256GCM: instance GHC.Show.Show Crypto.Saltine.Internal.AEAD.AES256GCM.Key
+ Crypto.Saltine.Internal.AEAD.AES256GCM: instance GHC.Show.Show Crypto.Saltine.Internal.AEAD.AES256GCM.Nonce
+ Crypto.Saltine.Internal.AEAD.AES256GCM: newtype Key
+ Crypto.Saltine.Internal.AEAD.AES256GCM: newtype Nonce
+ Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305: Key :: ByteString -> Key
+ Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305: Nonce :: ByteString -> Nonce
+ Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305: [unKey] :: Key -> ByteString
+ Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305: [unNonce] :: Nonce -> ByteString
+ Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305: aead_chacha20poly1305_abytes :: Int
+ Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305: aead_chacha20poly1305_keybytes :: Int
+ Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305: aead_chacha20poly1305_npubbytes :: Int
+ Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305: c_aead :: Ptr CChar -> Ptr CULLong -> Ptr CChar -> CULLong -> Ptr CChar -> CULLong -> Ptr CChar -> Ptr CChar -> Ptr CChar -> IO CInt
+ Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305: c_aead_detached :: Ptr CChar -> Ptr CChar -> Ptr CULLong -> Ptr CChar -> CULLong -> Ptr CChar -> CULLong -> Ptr CChar -> Ptr CChar -> Ptr CChar -> IO CInt
+ Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305: c_aead_open :: Ptr CChar -> Ptr CULLong -> Ptr CChar -> Ptr CChar -> CULLong -> Ptr CChar -> CULLong -> Ptr CChar -> Ptr CChar -> IO CInt
+ Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305: c_aead_open_detached :: Ptr CChar -> Ptr CChar -> Ptr CChar -> CULLong -> Ptr CChar -> Ptr CChar -> CULLong -> Ptr CChar -> Ptr CChar -> IO CInt
+ Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305: instance Control.DeepSeq.NFData Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305.Key
+ Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305: instance Control.DeepSeq.NFData Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305.Nonce
+ Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305: instance Crypto.Saltine.Class.IsEncoding Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305.Key
+ Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305: instance Crypto.Saltine.Class.IsEncoding Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305.Nonce
+ Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305: instance Crypto.Saltine.Class.IsNonce Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305.Nonce
+ Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305: instance Data.Data.Data Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305.Key
+ Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305: instance Data.Data.Data Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305.Nonce
+ Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305: instance Data.Hashable.Class.Hashable Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305.Key
+ Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305: instance Data.Hashable.Class.Hashable Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305.Nonce
+ Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305: instance GHC.Classes.Eq Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305.Key
+ Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305: instance GHC.Classes.Eq Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305.Nonce
+ Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305: instance GHC.Classes.Ord Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305.Key
+ Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305: instance GHC.Classes.Ord Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305.Nonce
+ Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305: instance GHC.Generics.Generic Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305.Key
+ Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305: instance GHC.Generics.Generic Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305.Nonce
+ Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305: instance GHC.Show.Show Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305.Key
+ Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305: instance GHC.Show.Show Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305.Nonce
+ Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305: newtype Key
+ Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305: newtype Nonce
+ Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305IETF: Key :: ByteString -> Key
+ Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305IETF: Nonce :: ByteString -> Nonce
+ Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305IETF: [unKey] :: Key -> ByteString
+ Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305IETF: [unNonce] :: Nonce -> ByteString
+ Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305IETF: aead_chacha20poly1305_ietf_abytes :: Int
+ Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305IETF: aead_chacha20poly1305_ietf_keybytes :: Int
+ Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305IETF: aead_chacha20poly1305_ietf_npubbytes :: Int
+ Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305IETF: c_aead :: Ptr CChar -> Ptr CULLong -> Ptr CChar -> CULLong -> Ptr CChar -> CULLong -> Ptr CChar -> Ptr CChar -> Ptr CChar -> IO CInt
+ Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305IETF: c_aead_detached :: Ptr CChar -> Ptr CChar -> Ptr CULLong -> Ptr CChar -> CULLong -> Ptr CChar -> CULLong -> Ptr CChar -> Ptr CChar -> Ptr CChar -> IO CInt
+ Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305IETF: c_aead_open :: Ptr CChar -> Ptr CULLong -> Ptr CChar -> Ptr CChar -> CULLong -> Ptr CChar -> CULLong -> Ptr CChar -> Ptr CChar -> IO CInt
+ Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305IETF: c_aead_open_detached :: Ptr CChar -> Ptr CChar -> Ptr CChar -> CULLong -> Ptr CChar -> Ptr CChar -> CULLong -> Ptr CChar -> Ptr CChar -> IO CInt
+ Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305IETF: instance Control.DeepSeq.NFData Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305IETF.Key
+ Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305IETF: instance Control.DeepSeq.NFData Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305IETF.Nonce
+ Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305IETF: instance Crypto.Saltine.Class.IsEncoding Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305IETF.Key
+ Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305IETF: instance Crypto.Saltine.Class.IsEncoding Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305IETF.Nonce
+ Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305IETF: instance Crypto.Saltine.Class.IsNonce Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305IETF.Nonce
+ Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305IETF: instance Data.Data.Data Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305IETF.Key
+ Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305IETF: instance Data.Data.Data Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305IETF.Nonce
+ Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305IETF: instance Data.Hashable.Class.Hashable Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305IETF.Key
+ Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305IETF: instance Data.Hashable.Class.Hashable Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305IETF.Nonce
+ Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305IETF: instance GHC.Classes.Eq Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305IETF.Key
+ Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305IETF: instance GHC.Classes.Eq Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305IETF.Nonce
+ Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305IETF: instance GHC.Classes.Ord Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305IETF.Key
+ Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305IETF: instance GHC.Classes.Ord Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305IETF.Nonce
+ Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305IETF: instance GHC.Generics.Generic Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305IETF.Key
+ Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305IETF: instance GHC.Generics.Generic Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305IETF.Nonce
+ Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305IETF: instance GHC.Show.Show Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305IETF.Key
+ Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305IETF: instance GHC.Show.Show Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305IETF.Nonce
+ Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305IETF: newtype Key
+ Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305IETF: newtype Nonce
+ Crypto.Saltine.Internal.AEAD.XChaCha20Poly1305: Key :: ByteString -> Key
+ Crypto.Saltine.Internal.AEAD.XChaCha20Poly1305: Nonce :: ByteString -> Nonce
+ Crypto.Saltine.Internal.AEAD.XChaCha20Poly1305: [unKey] :: Key -> ByteString
+ Crypto.Saltine.Internal.AEAD.XChaCha20Poly1305: [unNonce] :: Nonce -> ByteString
+ Crypto.Saltine.Internal.AEAD.XChaCha20Poly1305: aead_xchacha20poly1305_ietf_abytes :: Int
+ Crypto.Saltine.Internal.AEAD.XChaCha20Poly1305: aead_xchacha20poly1305_ietf_keybytes :: Int
+ Crypto.Saltine.Internal.AEAD.XChaCha20Poly1305: aead_xchacha20poly1305_ietf_npubbytes :: Int
+ Crypto.Saltine.Internal.AEAD.XChaCha20Poly1305: c_aead :: Ptr CChar -> Ptr CULLong -> Ptr CChar -> CULLong -> Ptr CChar -> CULLong -> Ptr CChar -> Ptr CChar -> Ptr CChar -> IO CInt
+ Crypto.Saltine.Internal.AEAD.XChaCha20Poly1305: c_aead_detached :: Ptr CChar -> Ptr CChar -> Ptr CULLong -> Ptr CChar -> CULLong -> Ptr CChar -> CULLong -> Ptr CChar -> Ptr CChar -> Ptr CChar -> IO CInt
+ Crypto.Saltine.Internal.AEAD.XChaCha20Poly1305: c_aead_open :: Ptr CChar -> Ptr CULLong -> Ptr CChar -> Ptr CChar -> CULLong -> Ptr CChar -> CULLong -> Ptr CChar -> Ptr CChar -> IO CInt
+ Crypto.Saltine.Internal.AEAD.XChaCha20Poly1305: c_aead_open_detached :: Ptr CChar -> Ptr CChar -> Ptr CChar -> CULLong -> Ptr CChar -> Ptr CChar -> CULLong -> Ptr CChar -> Ptr CChar -> IO CInt
+ Crypto.Saltine.Internal.AEAD.XChaCha20Poly1305: instance Control.DeepSeq.NFData Crypto.Saltine.Internal.AEAD.XChaCha20Poly1305.Key
+ Crypto.Saltine.Internal.AEAD.XChaCha20Poly1305: instance Control.DeepSeq.NFData Crypto.Saltine.Internal.AEAD.XChaCha20Poly1305.Nonce
+ Crypto.Saltine.Internal.AEAD.XChaCha20Poly1305: instance Crypto.Saltine.Class.IsEncoding Crypto.Saltine.Internal.AEAD.XChaCha20Poly1305.Key
+ Crypto.Saltine.Internal.AEAD.XChaCha20Poly1305: instance Crypto.Saltine.Class.IsEncoding Crypto.Saltine.Internal.AEAD.XChaCha20Poly1305.Nonce
+ Crypto.Saltine.Internal.AEAD.XChaCha20Poly1305: instance Crypto.Saltine.Class.IsNonce Crypto.Saltine.Internal.AEAD.XChaCha20Poly1305.Nonce
+ Crypto.Saltine.Internal.AEAD.XChaCha20Poly1305: instance Data.Data.Data Crypto.Saltine.Internal.AEAD.XChaCha20Poly1305.Key
+ Crypto.Saltine.Internal.AEAD.XChaCha20Poly1305: instance Data.Data.Data Crypto.Saltine.Internal.AEAD.XChaCha20Poly1305.Nonce
+ Crypto.Saltine.Internal.AEAD.XChaCha20Poly1305: instance Data.Hashable.Class.Hashable Crypto.Saltine.Internal.AEAD.XChaCha20Poly1305.Key
+ Crypto.Saltine.Internal.AEAD.XChaCha20Poly1305: instance Data.Hashable.Class.Hashable Crypto.Saltine.Internal.AEAD.XChaCha20Poly1305.Nonce
+ Crypto.Saltine.Internal.AEAD.XChaCha20Poly1305: instance GHC.Classes.Eq Crypto.Saltine.Internal.AEAD.XChaCha20Poly1305.Key
+ Crypto.Saltine.Internal.AEAD.XChaCha20Poly1305: instance GHC.Classes.Eq Crypto.Saltine.Internal.AEAD.XChaCha20Poly1305.Nonce
+ Crypto.Saltine.Internal.AEAD.XChaCha20Poly1305: instance GHC.Classes.Ord Crypto.Saltine.Internal.AEAD.XChaCha20Poly1305.Key
+ Crypto.Saltine.Internal.AEAD.XChaCha20Poly1305: instance GHC.Classes.Ord Crypto.Saltine.Internal.AEAD.XChaCha20Poly1305.Nonce
+ Crypto.Saltine.Internal.AEAD.XChaCha20Poly1305: instance GHC.Generics.Generic Crypto.Saltine.Internal.AEAD.XChaCha20Poly1305.Key
+ Crypto.Saltine.Internal.AEAD.XChaCha20Poly1305: instance GHC.Generics.Generic Crypto.Saltine.Internal.AEAD.XChaCha20Poly1305.Nonce
+ Crypto.Saltine.Internal.AEAD.XChaCha20Poly1305: instance GHC.Show.Show Crypto.Saltine.Internal.AEAD.XChaCha20Poly1305.Key
+ Crypto.Saltine.Internal.AEAD.XChaCha20Poly1305: instance GHC.Show.Show Crypto.Saltine.Internal.AEAD.XChaCha20Poly1305.Nonce
+ Crypto.Saltine.Internal.AEAD.XChaCha20Poly1305: newtype Key
+ Crypto.Saltine.Internal.AEAD.XChaCha20Poly1305: newtype Nonce
+ Crypto.Saltine.Internal.Auth: Au :: ByteString -> Authenticator
+ Crypto.Saltine.Internal.Auth: Key :: ByteString -> Key
+ Crypto.Saltine.Internal.Auth: [unAu] :: Authenticator -> ByteString
+ Crypto.Saltine.Internal.Auth: [unKey] :: Key -> ByteString
+ Crypto.Saltine.Internal.Auth: auth_bytes :: Int
+ Crypto.Saltine.Internal.Auth: auth_keybytes :: Int
+ Crypto.Saltine.Internal.Auth: c_auth :: Ptr CChar -> Ptr CChar -> CULLong -> Ptr CChar -> IO CInt
+ Crypto.Saltine.Internal.Auth: c_auth_verify :: Ptr CChar -> Ptr CChar -> CULLong -> Ptr CChar -> CInt
+ Crypto.Saltine.Internal.Auth: instance Control.DeepSeq.NFData Crypto.Saltine.Internal.Auth.Authenticator
+ Crypto.Saltine.Internal.Auth: instance Control.DeepSeq.NFData Crypto.Saltine.Internal.Auth.Key
+ Crypto.Saltine.Internal.Auth: instance Crypto.Saltine.Class.IsEncoding Crypto.Saltine.Internal.Auth.Authenticator
+ Crypto.Saltine.Internal.Auth: instance Crypto.Saltine.Class.IsEncoding Crypto.Saltine.Internal.Auth.Key
+ Crypto.Saltine.Internal.Auth: instance Data.Data.Data Crypto.Saltine.Internal.Auth.Authenticator
+ Crypto.Saltine.Internal.Auth: instance Data.Data.Data Crypto.Saltine.Internal.Auth.Key
+ Crypto.Saltine.Internal.Auth: instance Data.Hashable.Class.Hashable Crypto.Saltine.Internal.Auth.Authenticator
+ Crypto.Saltine.Internal.Auth: instance Data.Hashable.Class.Hashable Crypto.Saltine.Internal.Auth.Key
+ Crypto.Saltine.Internal.Auth: instance GHC.Classes.Eq Crypto.Saltine.Internal.Auth.Authenticator
+ Crypto.Saltine.Internal.Auth: instance GHC.Classes.Eq Crypto.Saltine.Internal.Auth.Key
+ Crypto.Saltine.Internal.Auth: instance GHC.Classes.Ord Crypto.Saltine.Internal.Auth.Authenticator
+ Crypto.Saltine.Internal.Auth: instance GHC.Classes.Ord Crypto.Saltine.Internal.Auth.Key
+ Crypto.Saltine.Internal.Auth: instance GHC.Generics.Generic Crypto.Saltine.Internal.Auth.Authenticator
+ Crypto.Saltine.Internal.Auth: instance GHC.Generics.Generic Crypto.Saltine.Internal.Auth.Key
+ Crypto.Saltine.Internal.Auth: instance GHC.Show.Show Crypto.Saltine.Internal.Auth.Authenticator
+ Crypto.Saltine.Internal.Auth: instance GHC.Show.Show Crypto.Saltine.Internal.Auth.Key
+ Crypto.Saltine.Internal.Auth: newtype Authenticator
+ Crypto.Saltine.Internal.Auth: newtype Key
+ Crypto.Saltine.Internal.Box: CK :: ByteString -> CombinedKey
+ Crypto.Saltine.Internal.Box: Keypair :: SecretKey -> PublicKey -> Keypair
+ Crypto.Saltine.Internal.Box: Nonce :: ByteString -> Nonce
+ Crypto.Saltine.Internal.Box: PK :: ByteString -> PublicKey
+ Crypto.Saltine.Internal.Box: SK :: ByteString -> SecretKey
+ Crypto.Saltine.Internal.Box: [publicKey] :: Keypair -> PublicKey
+ Crypto.Saltine.Internal.Box: [secretKey] :: Keypair -> SecretKey
+ Crypto.Saltine.Internal.Box: [unCK] :: CombinedKey -> ByteString
+ Crypto.Saltine.Internal.Box: [unNonce] :: Nonce -> ByteString
+ Crypto.Saltine.Internal.Box: [unPK] :: PublicKey -> ByteString
+ Crypto.Saltine.Internal.Box: [unSK] :: SecretKey -> ByteString
+ Crypto.Saltine.Internal.Box: box_beforenmbytes :: Int
+ Crypto.Saltine.Internal.Box: box_boxzerobytes :: Int
+ Crypto.Saltine.Internal.Box: box_macbytes :: Int
+ Crypto.Saltine.Internal.Box: box_noncebytes :: Int
+ Crypto.Saltine.Internal.Box: box_publickeybytes :: Int
+ Crypto.Saltine.Internal.Box: box_sealbytes :: Int
+ Crypto.Saltine.Internal.Box: box_secretkeybytes :: Int
+ Crypto.Saltine.Internal.Box: box_zerobytes :: Int
+ Crypto.Saltine.Internal.Box: c_box_beforenm :: Ptr CChar -> Ptr CChar -> Ptr CChar -> IO CInt
+ Crypto.Saltine.Internal.Box: c_box_easy :: Ptr CChar -> Ptr CChar -> CULLong -> Ptr CChar -> Ptr CChar -> Ptr CChar -> IO CInt
+ Crypto.Saltine.Internal.Box: c_box_easy_afternm :: Ptr CChar -> Ptr CChar -> CULLong -> Ptr CChar -> Ptr CChar -> IO CInt
+ Crypto.Saltine.Internal.Box: c_box_keypair :: Ptr CChar -> Ptr CChar -> IO CInt
+ Crypto.Saltine.Internal.Box: c_box_open_easy :: Ptr CChar -> Ptr CChar -> CULLong -> Ptr CChar -> Ptr CChar -> Ptr CChar -> IO CInt
+ Crypto.Saltine.Internal.Box: c_box_open_easy_afternm :: Ptr CChar -> Ptr CChar -> CULLong -> Ptr CChar -> Ptr CChar -> IO CInt
+ Crypto.Saltine.Internal.Box: c_box_seal :: Ptr CChar -> Ptr CChar -> CULLong -> Ptr CChar -> IO CInt
+ Crypto.Saltine.Internal.Box: c_box_seal_open :: Ptr CChar -> Ptr CChar -> CULLong -> Ptr CChar -> Ptr CChar -> IO CInt
+ Crypto.Saltine.Internal.Box: data Keypair
+ Crypto.Saltine.Internal.Box: instance Control.DeepSeq.NFData Crypto.Saltine.Internal.Box.CombinedKey
+ Crypto.Saltine.Internal.Box: instance Control.DeepSeq.NFData Crypto.Saltine.Internal.Box.Keypair
+ Crypto.Saltine.Internal.Box: instance Control.DeepSeq.NFData Crypto.Saltine.Internal.Box.Nonce
+ Crypto.Saltine.Internal.Box: instance Control.DeepSeq.NFData Crypto.Saltine.Internal.Box.PublicKey
+ Crypto.Saltine.Internal.Box: instance Control.DeepSeq.NFData Crypto.Saltine.Internal.Box.SecretKey
+ Crypto.Saltine.Internal.Box: instance Crypto.Saltine.Class.IsEncoding Crypto.Saltine.Internal.Box.CombinedKey
+ Crypto.Saltine.Internal.Box: instance Crypto.Saltine.Class.IsEncoding Crypto.Saltine.Internal.Box.Nonce
+ Crypto.Saltine.Internal.Box: instance Crypto.Saltine.Class.IsEncoding Crypto.Saltine.Internal.Box.PublicKey
+ Crypto.Saltine.Internal.Box: instance Crypto.Saltine.Class.IsEncoding Crypto.Saltine.Internal.Box.SecretKey
+ Crypto.Saltine.Internal.Box: instance Crypto.Saltine.Class.IsNonce Crypto.Saltine.Internal.Box.Nonce
+ Crypto.Saltine.Internal.Box: instance Data.Data.Data Crypto.Saltine.Internal.Box.CombinedKey
+ Crypto.Saltine.Internal.Box: instance Data.Data.Data Crypto.Saltine.Internal.Box.Keypair
+ Crypto.Saltine.Internal.Box: instance Data.Data.Data Crypto.Saltine.Internal.Box.Nonce
+ Crypto.Saltine.Internal.Box: instance Data.Data.Data Crypto.Saltine.Internal.Box.PublicKey
+ Crypto.Saltine.Internal.Box: instance Data.Data.Data Crypto.Saltine.Internal.Box.SecretKey
+ Crypto.Saltine.Internal.Box: instance Data.Hashable.Class.Hashable Crypto.Saltine.Internal.Box.CombinedKey
+ Crypto.Saltine.Internal.Box: instance Data.Hashable.Class.Hashable Crypto.Saltine.Internal.Box.Keypair
+ Crypto.Saltine.Internal.Box: instance Data.Hashable.Class.Hashable Crypto.Saltine.Internal.Box.Nonce
+ Crypto.Saltine.Internal.Box: instance Data.Hashable.Class.Hashable Crypto.Saltine.Internal.Box.PublicKey
+ Crypto.Saltine.Internal.Box: instance Data.Hashable.Class.Hashable Crypto.Saltine.Internal.Box.SecretKey
+ Crypto.Saltine.Internal.Box: instance GHC.Classes.Eq Crypto.Saltine.Internal.Box.CombinedKey
+ Crypto.Saltine.Internal.Box: instance GHC.Classes.Eq Crypto.Saltine.Internal.Box.Keypair
+ Crypto.Saltine.Internal.Box: instance GHC.Classes.Eq Crypto.Saltine.Internal.Box.Nonce
+ Crypto.Saltine.Internal.Box: instance GHC.Classes.Eq Crypto.Saltine.Internal.Box.PublicKey
+ Crypto.Saltine.Internal.Box: instance GHC.Classes.Eq Crypto.Saltine.Internal.Box.SecretKey
+ Crypto.Saltine.Internal.Box: instance GHC.Classes.Ord Crypto.Saltine.Internal.Box.CombinedKey
+ Crypto.Saltine.Internal.Box: instance GHC.Classes.Ord Crypto.Saltine.Internal.Box.Keypair
+ Crypto.Saltine.Internal.Box: instance GHC.Classes.Ord Crypto.Saltine.Internal.Box.Nonce
+ Crypto.Saltine.Internal.Box: instance GHC.Classes.Ord Crypto.Saltine.Internal.Box.PublicKey
+ Crypto.Saltine.Internal.Box: instance GHC.Classes.Ord Crypto.Saltine.Internal.Box.SecretKey
+ Crypto.Saltine.Internal.Box: instance GHC.Generics.Generic Crypto.Saltine.Internal.Box.CombinedKey
+ Crypto.Saltine.Internal.Box: instance GHC.Generics.Generic Crypto.Saltine.Internal.Box.Keypair
+ Crypto.Saltine.Internal.Box: instance GHC.Generics.Generic Crypto.Saltine.Internal.Box.Nonce
+ Crypto.Saltine.Internal.Box: instance GHC.Generics.Generic Crypto.Saltine.Internal.Box.PublicKey
+ Crypto.Saltine.Internal.Box: instance GHC.Generics.Generic Crypto.Saltine.Internal.Box.SecretKey
+ Crypto.Saltine.Internal.Box: instance GHC.Show.Show Crypto.Saltine.Internal.Box.CombinedKey
+ Crypto.Saltine.Internal.Box: instance GHC.Show.Show Crypto.Saltine.Internal.Box.Nonce
+ Crypto.Saltine.Internal.Box: instance GHC.Show.Show Crypto.Saltine.Internal.Box.PublicKey
+ Crypto.Saltine.Internal.Box: instance GHC.Show.Show Crypto.Saltine.Internal.Box.SecretKey
+ Crypto.Saltine.Internal.Box: newtype CombinedKey
+ Crypto.Saltine.Internal.Box: newtype Nonce
+ Crypto.Saltine.Internal.Box: newtype PublicKey
+ Crypto.Saltine.Internal.Box: newtype SecretKey
+ Crypto.Saltine.Internal.Hash: GhK :: ByteString -> GenerichashKey
+ Crypto.Saltine.Internal.Hash: GhOL :: Int -> GenerichashOutLen
+ Crypto.Saltine.Internal.Hash: ShK :: ByteString -> ShorthashKey
+ Crypto.Saltine.Internal.Hash: [unGhK] :: GenerichashKey -> ByteString
+ Crypto.Saltine.Internal.Hash: [unGhOL] :: GenerichashOutLen -> Int
+ Crypto.Saltine.Internal.Hash: [unShK] :: ShorthashKey -> ByteString
+ Crypto.Saltine.Internal.Hash: c_generichash :: Ptr CChar -> CULLong -> Ptr CChar -> CULLong -> Ptr CChar -> CULLong -> IO CInt
+ Crypto.Saltine.Internal.Hash: c_hash :: Ptr CChar -> Ptr CChar -> CULLong -> IO CInt
+ Crypto.Saltine.Internal.Hash: c_shorthash :: Ptr CChar -> Ptr CChar -> CULLong -> Ptr CChar -> IO CInt
+ Crypto.Saltine.Internal.Hash: generichash_bytes_max :: Int
+ Crypto.Saltine.Internal.Hash: generichash_keybytes_max :: Int
+ Crypto.Saltine.Internal.Hash: hash_bytes :: Int
+ Crypto.Saltine.Internal.Hash: instance Control.DeepSeq.NFData Crypto.Saltine.Internal.Hash.GenerichashKey
+ Crypto.Saltine.Internal.Hash: instance Control.DeepSeq.NFData Crypto.Saltine.Internal.Hash.GenerichashOutLen
+ Crypto.Saltine.Internal.Hash: instance Control.DeepSeq.NFData Crypto.Saltine.Internal.Hash.ShorthashKey
+ Crypto.Saltine.Internal.Hash: instance Crypto.Saltine.Class.IsEncoding Crypto.Saltine.Internal.Hash.GenerichashKey
+ Crypto.Saltine.Internal.Hash: instance Crypto.Saltine.Class.IsEncoding Crypto.Saltine.Internal.Hash.ShorthashKey
+ Crypto.Saltine.Internal.Hash: instance Data.Data.Data Crypto.Saltine.Internal.Hash.GenerichashKey
+ Crypto.Saltine.Internal.Hash: instance Data.Data.Data Crypto.Saltine.Internal.Hash.GenerichashOutLen
+ Crypto.Saltine.Internal.Hash: instance Data.Data.Data Crypto.Saltine.Internal.Hash.ShorthashKey
+ Crypto.Saltine.Internal.Hash: instance Data.Hashable.Class.Hashable Crypto.Saltine.Internal.Hash.GenerichashKey
+ Crypto.Saltine.Internal.Hash: instance Data.Hashable.Class.Hashable Crypto.Saltine.Internal.Hash.GenerichashOutLen
+ Crypto.Saltine.Internal.Hash: instance Data.Hashable.Class.Hashable Crypto.Saltine.Internal.Hash.ShorthashKey
+ Crypto.Saltine.Internal.Hash: instance GHC.Classes.Eq Crypto.Saltine.Internal.Hash.GenerichashKey
+ Crypto.Saltine.Internal.Hash: instance GHC.Classes.Eq Crypto.Saltine.Internal.Hash.GenerichashOutLen
+ Crypto.Saltine.Internal.Hash: instance GHC.Classes.Eq Crypto.Saltine.Internal.Hash.ShorthashKey
+ Crypto.Saltine.Internal.Hash: instance GHC.Classes.Ord Crypto.Saltine.Internal.Hash.GenerichashKey
+ Crypto.Saltine.Internal.Hash: instance GHC.Classes.Ord Crypto.Saltine.Internal.Hash.GenerichashOutLen
+ Crypto.Saltine.Internal.Hash: instance GHC.Classes.Ord Crypto.Saltine.Internal.Hash.ShorthashKey
+ Crypto.Saltine.Internal.Hash: instance GHC.Generics.Generic Crypto.Saltine.Internal.Hash.GenerichashKey
+ Crypto.Saltine.Internal.Hash: instance GHC.Generics.Generic Crypto.Saltine.Internal.Hash.GenerichashOutLen
+ Crypto.Saltine.Internal.Hash: instance GHC.Generics.Generic Crypto.Saltine.Internal.Hash.ShorthashKey
+ Crypto.Saltine.Internal.Hash: instance GHC.Show.Show Crypto.Saltine.Internal.Hash.GenerichashKey
+ Crypto.Saltine.Internal.Hash: instance GHC.Show.Show Crypto.Saltine.Internal.Hash.ShorthashKey
+ Crypto.Saltine.Internal.Hash: newtype GenerichashKey
+ Crypto.Saltine.Internal.Hash: newtype GenerichashOutLen
+ Crypto.Saltine.Internal.Hash: newtype ShorthashKey
+ Crypto.Saltine.Internal.Hash: nullShKey :: ShorthashKey
+ Crypto.Saltine.Internal.Hash: shorthash :: ShorthashKey -> ByteString -> ByteString
+ Crypto.Saltine.Internal.Hash: shorthash_bytes :: Int
+ Crypto.Saltine.Internal.Hash: shorthash_keybytes :: Int
+ Crypto.Saltine.Internal.OneTimeAuth: Au :: ByteString -> Authenticator
+ Crypto.Saltine.Internal.OneTimeAuth: Key :: ByteString -> Key
+ Crypto.Saltine.Internal.OneTimeAuth: [unAu] :: Authenticator -> ByteString
+ Crypto.Saltine.Internal.OneTimeAuth: [unKey] :: Key -> ByteString
+ Crypto.Saltine.Internal.OneTimeAuth: c_onetimeauth :: Ptr CChar -> Ptr CChar -> CULLong -> Ptr CChar -> IO CInt
+ Crypto.Saltine.Internal.OneTimeAuth: c_onetimeauth_verify :: Ptr CChar -> Ptr CChar -> CULLong -> Ptr CChar -> CInt
+ Crypto.Saltine.Internal.OneTimeAuth: instance Control.DeepSeq.NFData Crypto.Saltine.Internal.OneTimeAuth.Authenticator
+ Crypto.Saltine.Internal.OneTimeAuth: instance Control.DeepSeq.NFData Crypto.Saltine.Internal.OneTimeAuth.Key
+ Crypto.Saltine.Internal.OneTimeAuth: instance Crypto.Saltine.Class.IsEncoding Crypto.Saltine.Internal.OneTimeAuth.Authenticator
+ Crypto.Saltine.Internal.OneTimeAuth: instance Crypto.Saltine.Class.IsEncoding Crypto.Saltine.Internal.OneTimeAuth.Key
+ Crypto.Saltine.Internal.OneTimeAuth: instance Data.Data.Data Crypto.Saltine.Internal.OneTimeAuth.Authenticator
+ Crypto.Saltine.Internal.OneTimeAuth: instance Data.Data.Data Crypto.Saltine.Internal.OneTimeAuth.Key
+ Crypto.Saltine.Internal.OneTimeAuth: instance Data.Hashable.Class.Hashable Crypto.Saltine.Internal.OneTimeAuth.Authenticator
+ Crypto.Saltine.Internal.OneTimeAuth: instance Data.Hashable.Class.Hashable Crypto.Saltine.Internal.OneTimeAuth.Key
+ Crypto.Saltine.Internal.OneTimeAuth: instance GHC.Classes.Eq Crypto.Saltine.Internal.OneTimeAuth.Authenticator
+ Crypto.Saltine.Internal.OneTimeAuth: instance GHC.Classes.Eq Crypto.Saltine.Internal.OneTimeAuth.Key
+ Crypto.Saltine.Internal.OneTimeAuth: instance GHC.Classes.Ord Crypto.Saltine.Internal.OneTimeAuth.Authenticator
+ Crypto.Saltine.Internal.OneTimeAuth: instance GHC.Classes.Ord Crypto.Saltine.Internal.OneTimeAuth.Key
+ Crypto.Saltine.Internal.OneTimeAuth: instance GHC.Generics.Generic Crypto.Saltine.Internal.OneTimeAuth.Authenticator
+ Crypto.Saltine.Internal.OneTimeAuth: instance GHC.Generics.Generic Crypto.Saltine.Internal.OneTimeAuth.Key
+ Crypto.Saltine.Internal.OneTimeAuth: instance GHC.Show.Show Crypto.Saltine.Internal.OneTimeAuth.Authenticator
+ Crypto.Saltine.Internal.OneTimeAuth: instance GHC.Show.Show Crypto.Saltine.Internal.OneTimeAuth.Key
+ Crypto.Saltine.Internal.OneTimeAuth: newtype Authenticator
+ Crypto.Saltine.Internal.OneTimeAuth: newtype Key
+ Crypto.Saltine.Internal.OneTimeAuth: onetimeauth_bytes :: Int
+ Crypto.Saltine.Internal.OneTimeAuth: onetimeauth_keybytes :: Int
+ Crypto.Saltine.Internal.Password: Argon2i13 :: Algorithm
+ Crypto.Saltine.Internal.Password: Argon2id13 :: Algorithm
+ Crypto.Saltine.Internal.Password: DefaultAlgorithm :: Algorithm
+ Crypto.Saltine.Internal.Password: Memlimit :: Int -> Memlimit
+ Crypto.Saltine.Internal.Password: Opslimit :: Int -> Opslimit
+ Crypto.Saltine.Internal.Password: PasswordHash :: Text -> PasswordHash
+ Crypto.Saltine.Internal.Password: Policy :: Opslimit -> Memlimit -> Algorithm -> Policy
+ Crypto.Saltine.Internal.Password: Salt :: ByteString -> Salt
+ Crypto.Saltine.Internal.Password: [algPolicy] :: Policy -> Algorithm
+ Crypto.Saltine.Internal.Password: [getMemlimit] :: Memlimit -> Int
+ Crypto.Saltine.Internal.Password: [getOpslimit] :: Opslimit -> Int
+ Crypto.Saltine.Internal.Password: [memPolicy] :: Policy -> Memlimit
+ Crypto.Saltine.Internal.Password: [opsPolicy] :: Policy -> Opslimit
+ Crypto.Saltine.Internal.Password: [unPasswordHash] :: PasswordHash -> Text
+ Crypto.Saltine.Internal.Password: [unSalt] :: Salt -> ByteString
+ Crypto.Saltine.Internal.Password: algorithm :: Algorithm -> CInt
+ Crypto.Saltine.Internal.Password: c_pwhash :: Ptr CChar -> CULLong -> Ptr CChar -> CULLong -> Ptr CChar -> CULLong -> CSize -> CInt -> IO CInt
+ Crypto.Saltine.Internal.Password: c_pwhash_str :: Ptr CChar -> Ptr CChar -> CULLong -> CULLong -> CSize -> IO CInt
+ Crypto.Saltine.Internal.Password: c_pwhash_str_needs_rehash :: Ptr CChar -> CULLong -> CSize -> IO CInt
+ Crypto.Saltine.Internal.Password: c_pwhash_str_verify :: Ptr CChar -> Ptr CChar -> CULLong -> IO CInt
+ Crypto.Saltine.Internal.Password: data Algorithm
+ Crypto.Saltine.Internal.Password: data Policy
+ Crypto.Saltine.Internal.Password: instance Control.DeepSeq.NFData Crypto.Saltine.Internal.Password.Memlimit
+ Crypto.Saltine.Internal.Password: instance Control.DeepSeq.NFData Crypto.Saltine.Internal.Password.Opslimit
+ Crypto.Saltine.Internal.Password: instance Control.DeepSeq.NFData Crypto.Saltine.Internal.Password.PasswordHash
+ Crypto.Saltine.Internal.Password: instance Control.DeepSeq.NFData Crypto.Saltine.Internal.Password.Salt
+ Crypto.Saltine.Internal.Password: instance Crypto.Saltine.Class.IsEncoding Crypto.Saltine.Internal.Password.Salt
+ Crypto.Saltine.Internal.Password: instance Data.Data.Data Crypto.Saltine.Internal.Password.Algorithm
+ Crypto.Saltine.Internal.Password: instance Data.Data.Data Crypto.Saltine.Internal.Password.Memlimit
+ Crypto.Saltine.Internal.Password: instance Data.Data.Data Crypto.Saltine.Internal.Password.Opslimit
+ Crypto.Saltine.Internal.Password: instance Data.Data.Data Crypto.Saltine.Internal.Password.PasswordHash
+ Crypto.Saltine.Internal.Password: instance Data.Data.Data Crypto.Saltine.Internal.Password.Policy
+ Crypto.Saltine.Internal.Password: instance Data.Data.Data Crypto.Saltine.Internal.Password.Salt
+ Crypto.Saltine.Internal.Password: instance Data.Hashable.Class.Hashable Crypto.Saltine.Internal.Password.Algorithm
+ Crypto.Saltine.Internal.Password: instance Data.Hashable.Class.Hashable Crypto.Saltine.Internal.Password.Memlimit
+ Crypto.Saltine.Internal.Password: instance Data.Hashable.Class.Hashable Crypto.Saltine.Internal.Password.Opslimit
+ Crypto.Saltine.Internal.Password: instance Data.Hashable.Class.Hashable Crypto.Saltine.Internal.Password.PasswordHash
+ Crypto.Saltine.Internal.Password: instance Data.Hashable.Class.Hashable Crypto.Saltine.Internal.Password.Policy
+ Crypto.Saltine.Internal.Password: instance Data.Hashable.Class.Hashable Crypto.Saltine.Internal.Password.Salt
+ Crypto.Saltine.Internal.Password: instance GHC.Classes.Eq Crypto.Saltine.Internal.Password.Algorithm
+ Crypto.Saltine.Internal.Password: instance GHC.Classes.Eq Crypto.Saltine.Internal.Password.Memlimit
+ Crypto.Saltine.Internal.Password: instance GHC.Classes.Eq Crypto.Saltine.Internal.Password.Opslimit
+ Crypto.Saltine.Internal.Password: instance GHC.Classes.Eq Crypto.Saltine.Internal.Password.PasswordHash
+ Crypto.Saltine.Internal.Password: instance GHC.Classes.Eq Crypto.Saltine.Internal.Password.Policy
+ Crypto.Saltine.Internal.Password: instance GHC.Classes.Eq Crypto.Saltine.Internal.Password.Salt
+ Crypto.Saltine.Internal.Password: instance GHC.Classes.Ord Crypto.Saltine.Internal.Password.Algorithm
+ Crypto.Saltine.Internal.Password: instance GHC.Classes.Ord Crypto.Saltine.Internal.Password.Memlimit
+ Crypto.Saltine.Internal.Password: instance GHC.Classes.Ord Crypto.Saltine.Internal.Password.Opslimit
+ Crypto.Saltine.Internal.Password: instance GHC.Classes.Ord Crypto.Saltine.Internal.Password.PasswordHash
+ Crypto.Saltine.Internal.Password: instance GHC.Classes.Ord Crypto.Saltine.Internal.Password.Policy
+ Crypto.Saltine.Internal.Password: instance GHC.Classes.Ord Crypto.Saltine.Internal.Password.Salt
+ Crypto.Saltine.Internal.Password: instance GHC.Enum.Bounded Crypto.Saltine.Internal.Password.Algorithm
+ Crypto.Saltine.Internal.Password: instance GHC.Enum.Enum Crypto.Saltine.Internal.Password.Algorithm
+ Crypto.Saltine.Internal.Password: instance GHC.Generics.Generic Crypto.Saltine.Internal.Password.Algorithm
+ Crypto.Saltine.Internal.Password: instance GHC.Generics.Generic Crypto.Saltine.Internal.Password.Memlimit
+ Crypto.Saltine.Internal.Password: instance GHC.Generics.Generic Crypto.Saltine.Internal.Password.Opslimit
+ Crypto.Saltine.Internal.Password: instance GHC.Generics.Generic Crypto.Saltine.Internal.Password.PasswordHash
+ Crypto.Saltine.Internal.Password: instance GHC.Generics.Generic Crypto.Saltine.Internal.Password.Policy
+ Crypto.Saltine.Internal.Password: instance GHC.Generics.Generic Crypto.Saltine.Internal.Password.Salt
+ Crypto.Saltine.Internal.Password: instance GHC.Show.Show Crypto.Saltine.Internal.Password.Algorithm
+ Crypto.Saltine.Internal.Password: instance GHC.Show.Show Crypto.Saltine.Internal.Password.Memlimit
+ Crypto.Saltine.Internal.Password: instance GHC.Show.Show Crypto.Saltine.Internal.Password.Opslimit
+ Crypto.Saltine.Internal.Password: instance GHC.Show.Show Crypto.Saltine.Internal.Password.PasswordHash
+ Crypto.Saltine.Internal.Password: instance GHC.Show.Show Crypto.Saltine.Internal.Password.Policy
+ Crypto.Saltine.Internal.Password: instance GHC.Show.Show Crypto.Saltine.Internal.Password.Salt
+ Crypto.Saltine.Internal.Password: newtype Memlimit
+ Crypto.Saltine.Internal.Password: newtype Opslimit
+ Crypto.Saltine.Internal.Password: newtype PasswordHash
+ Crypto.Saltine.Internal.Password: newtype Salt
+ Crypto.Saltine.Internal.Password: pwhash_alg_argon2i13 :: Int
+ Crypto.Saltine.Internal.Password: pwhash_alg_argon2id13 :: Int
+ Crypto.Saltine.Internal.Password: pwhash_alg_default :: Int
+ Crypto.Saltine.Internal.Password: pwhash_argon2i_bytes_max :: Int
+ Crypto.Saltine.Internal.Password: pwhash_argon2i_bytes_min :: Int
+ Crypto.Saltine.Internal.Password: pwhash_argon2i_memlimit_interactive :: Int
+ Crypto.Saltine.Internal.Password: pwhash_argon2i_memlimit_max :: Int
+ Crypto.Saltine.Internal.Password: pwhash_argon2i_memlimit_min :: Int
+ Crypto.Saltine.Internal.Password: pwhash_argon2i_memlimit_moderate :: Int
+ Crypto.Saltine.Internal.Password: pwhash_argon2i_memlimit_sensitive :: Int
+ Crypto.Saltine.Internal.Password: pwhash_argon2i_opslimit_interactive :: Int
+ Crypto.Saltine.Internal.Password: pwhash_argon2i_opslimit_max :: Int
+ Crypto.Saltine.Internal.Password: pwhash_argon2i_opslimit_min :: Int
+ Crypto.Saltine.Internal.Password: pwhash_argon2i_opslimit_moderate :: Int
+ Crypto.Saltine.Internal.Password: pwhash_argon2i_opslimit_sensitive :: Int
+ Crypto.Saltine.Internal.Password: pwhash_argon2i_passwd_max :: Int
+ Crypto.Saltine.Internal.Password: pwhash_argon2i_passwd_min :: Int
+ Crypto.Saltine.Internal.Password: pwhash_argon2i_saltbytes :: Int
+ Crypto.Saltine.Internal.Password: pwhash_argon2i_strbytes :: Int
+ Crypto.Saltine.Internal.Password: pwhash_argon2i_strprefix :: Int
+ Crypto.Saltine.Internal.Password: pwhash_argon2id_bytes_max :: Int
+ Crypto.Saltine.Internal.Password: pwhash_argon2id_bytes_min :: Int
+ Crypto.Saltine.Internal.Password: pwhash_argon2id_memlimit_interactive :: Int
+ Crypto.Saltine.Internal.Password: pwhash_argon2id_memlimit_max :: Int
+ Crypto.Saltine.Internal.Password: pwhash_argon2id_memlimit_min :: Int
+ Crypto.Saltine.Internal.Password: pwhash_argon2id_memlimit_moderate :: Int
+ Crypto.Saltine.Internal.Password: pwhash_argon2id_memlimit_sensitive :: Int
+ Crypto.Saltine.Internal.Password: pwhash_argon2id_opslimit_interactive :: Int
+ Crypto.Saltine.Internal.Password: pwhash_argon2id_opslimit_max :: Int
+ Crypto.Saltine.Internal.Password: pwhash_argon2id_opslimit_min :: Int
+ Crypto.Saltine.Internal.Password: pwhash_argon2id_opslimit_moderate :: Int
+ Crypto.Saltine.Internal.Password: pwhash_argon2id_opslimit_sensitive :: Int
+ Crypto.Saltine.Internal.Password: pwhash_argon2id_passwd_max :: Int
+ Crypto.Saltine.Internal.Password: pwhash_argon2id_passwd_min :: Int
+ Crypto.Saltine.Internal.Password: pwhash_argon2id_saltbytes :: Int
+ Crypto.Saltine.Internal.Password: pwhash_argon2id_strbytes :: Int
+ Crypto.Saltine.Internal.Password: pwhash_argon2id_strprefix :: Int
+ Crypto.Saltine.Internal.Password: pwhash_bytes_max :: Int
+ Crypto.Saltine.Internal.Password: pwhash_bytes_min :: Int
+ Crypto.Saltine.Internal.Password: pwhash_memlimit_interactive :: Int
+ Crypto.Saltine.Internal.Password: pwhash_memlimit_max :: Int
+ Crypto.Saltine.Internal.Password: pwhash_memlimit_min :: Int
+ Crypto.Saltine.Internal.Password: pwhash_memlimit_moderate :: Int
+ Crypto.Saltine.Internal.Password: pwhash_memlimit_sensitive :: Int
+ Crypto.Saltine.Internal.Password: pwhash_opslimit_interactive :: Int
+ Crypto.Saltine.Internal.Password: pwhash_opslimit_max :: Int
+ Crypto.Saltine.Internal.Password: pwhash_opslimit_min :: Int
+ Crypto.Saltine.Internal.Password: pwhash_opslimit_moderate :: Int
+ Crypto.Saltine.Internal.Password: pwhash_opslimit_sensitive :: Int
+ Crypto.Saltine.Internal.Password: pwhash_passwd_max :: Int
+ Crypto.Saltine.Internal.Password: pwhash_passwd_min :: Int
+ Crypto.Saltine.Internal.Password: pwhash_saltbytes :: Int
+ Crypto.Saltine.Internal.Password: pwhash_strbytes :: Int
+ Crypto.Saltine.Internal.Password: pwhash_strprefix :: Int
+ Crypto.Saltine.Internal.ScalarMult: GE :: ByteString -> GroupElement
+ Crypto.Saltine.Internal.ScalarMult: Sc :: ByteString -> Scalar
+ Crypto.Saltine.Internal.ScalarMult: [unGE] :: GroupElement -> ByteString
+ Crypto.Saltine.Internal.ScalarMult: [unSc] :: Scalar -> ByteString
+ Crypto.Saltine.Internal.ScalarMult: c_scalarmult :: Ptr CChar -> Ptr CChar -> Ptr CChar -> IO CInt
+ Crypto.Saltine.Internal.ScalarMult: c_scalarmult_base :: Ptr CChar -> Ptr CChar -> IO CInt
+ Crypto.Saltine.Internal.ScalarMult: instance Control.DeepSeq.NFData Crypto.Saltine.Internal.ScalarMult.GroupElement
+ Crypto.Saltine.Internal.ScalarMult: instance Control.DeepSeq.NFData Crypto.Saltine.Internal.ScalarMult.Scalar
+ Crypto.Saltine.Internal.ScalarMult: instance Crypto.Saltine.Class.IsEncoding Crypto.Saltine.Internal.ScalarMult.GroupElement
+ Crypto.Saltine.Internal.ScalarMult: instance Crypto.Saltine.Class.IsEncoding Crypto.Saltine.Internal.ScalarMult.Scalar
+ Crypto.Saltine.Internal.ScalarMult: instance Data.Data.Data Crypto.Saltine.Internal.ScalarMult.GroupElement
+ Crypto.Saltine.Internal.ScalarMult: instance Data.Data.Data Crypto.Saltine.Internal.ScalarMult.Scalar
+ Crypto.Saltine.Internal.ScalarMult: instance Data.Hashable.Class.Hashable Crypto.Saltine.Internal.ScalarMult.GroupElement
+ Crypto.Saltine.Internal.ScalarMult: instance Data.Hashable.Class.Hashable Crypto.Saltine.Internal.ScalarMult.Scalar
+ Crypto.Saltine.Internal.ScalarMult: instance GHC.Classes.Eq Crypto.Saltine.Internal.ScalarMult.GroupElement
+ Crypto.Saltine.Internal.ScalarMult: instance GHC.Classes.Eq Crypto.Saltine.Internal.ScalarMult.Scalar
+ Crypto.Saltine.Internal.ScalarMult: instance GHC.Classes.Ord Crypto.Saltine.Internal.ScalarMult.GroupElement
+ Crypto.Saltine.Internal.ScalarMult: instance GHC.Classes.Ord Crypto.Saltine.Internal.ScalarMult.Scalar
+ Crypto.Saltine.Internal.ScalarMult: instance GHC.Generics.Generic Crypto.Saltine.Internal.ScalarMult.GroupElement
+ Crypto.Saltine.Internal.ScalarMult: instance GHC.Generics.Generic Crypto.Saltine.Internal.ScalarMult.Scalar
+ Crypto.Saltine.Internal.ScalarMult: instance GHC.Show.Show Crypto.Saltine.Internal.ScalarMult.GroupElement
+ Crypto.Saltine.Internal.ScalarMult: instance GHC.Show.Show Crypto.Saltine.Internal.ScalarMult.Scalar
+ Crypto.Saltine.Internal.ScalarMult: newtype GroupElement
+ Crypto.Saltine.Internal.ScalarMult: newtype Scalar
+ Crypto.Saltine.Internal.ScalarMult: scalarmult_bytes :: Int
+ Crypto.Saltine.Internal.ScalarMult: scalarmult_scalarbytes :: Int
+ Crypto.Saltine.Internal.SecretBox: Au :: ByteString -> Authenticator
+ Crypto.Saltine.Internal.SecretBox: Key :: ByteString -> Key
+ Crypto.Saltine.Internal.SecretBox: Nonce :: ByteString -> Nonce
+ Crypto.Saltine.Internal.SecretBox: [unAu] :: Authenticator -> ByteString
+ Crypto.Saltine.Internal.SecretBox: [unKey] :: Key -> ByteString
+ Crypto.Saltine.Internal.SecretBox: [unNonce] :: Nonce -> ByteString
+ Crypto.Saltine.Internal.SecretBox: c_secretbox :: Ptr CChar -> Ptr CChar -> CULLong -> Ptr CChar -> Ptr CChar -> IO CInt
+ Crypto.Saltine.Internal.SecretBox: c_secretbox_detached :: Ptr CChar -> Ptr CChar -> Ptr CChar -> CULLong -> Ptr CChar -> Ptr CChar -> IO CInt
+ Crypto.Saltine.Internal.SecretBox: c_secretbox_open :: Ptr CChar -> Ptr CChar -> CULLong -> Ptr CChar -> Ptr CChar -> IO CInt
+ Crypto.Saltine.Internal.SecretBox: c_secretbox_open_detached :: Ptr CChar -> Ptr CChar -> Ptr CChar -> CULLong -> Ptr CChar -> Ptr CChar -> IO CInt
+ Crypto.Saltine.Internal.SecretBox: instance Control.DeepSeq.NFData Crypto.Saltine.Internal.SecretBox.Authenticator
+ Crypto.Saltine.Internal.SecretBox: instance Control.DeepSeq.NFData Crypto.Saltine.Internal.SecretBox.Key
+ Crypto.Saltine.Internal.SecretBox: instance Control.DeepSeq.NFData Crypto.Saltine.Internal.SecretBox.Nonce
+ Crypto.Saltine.Internal.SecretBox: instance Crypto.Saltine.Class.IsEncoding Crypto.Saltine.Internal.SecretBox.Authenticator
+ Crypto.Saltine.Internal.SecretBox: instance Crypto.Saltine.Class.IsEncoding Crypto.Saltine.Internal.SecretBox.Key
+ Crypto.Saltine.Internal.SecretBox: instance Crypto.Saltine.Class.IsEncoding Crypto.Saltine.Internal.SecretBox.Nonce
+ Crypto.Saltine.Internal.SecretBox: instance Crypto.Saltine.Class.IsNonce Crypto.Saltine.Internal.SecretBox.Nonce
+ Crypto.Saltine.Internal.SecretBox: instance Data.Data.Data Crypto.Saltine.Internal.SecretBox.Authenticator
+ Crypto.Saltine.Internal.SecretBox: instance Data.Data.Data Crypto.Saltine.Internal.SecretBox.Key
+ Crypto.Saltine.Internal.SecretBox: instance Data.Data.Data Crypto.Saltine.Internal.SecretBox.Nonce
+ Crypto.Saltine.Internal.SecretBox: instance Data.Hashable.Class.Hashable Crypto.Saltine.Internal.SecretBox.Authenticator
+ Crypto.Saltine.Internal.SecretBox: instance Data.Hashable.Class.Hashable Crypto.Saltine.Internal.SecretBox.Key
+ Crypto.Saltine.Internal.SecretBox: instance Data.Hashable.Class.Hashable Crypto.Saltine.Internal.SecretBox.Nonce
+ Crypto.Saltine.Internal.SecretBox: instance GHC.Classes.Eq Crypto.Saltine.Internal.SecretBox.Authenticator
+ Crypto.Saltine.Internal.SecretBox: instance GHC.Classes.Eq Crypto.Saltine.Internal.SecretBox.Key
+ Crypto.Saltine.Internal.SecretBox: instance GHC.Classes.Eq Crypto.Saltine.Internal.SecretBox.Nonce
+ Crypto.Saltine.Internal.SecretBox: instance GHC.Classes.Ord Crypto.Saltine.Internal.SecretBox.Authenticator
+ Crypto.Saltine.Internal.SecretBox: instance GHC.Classes.Ord Crypto.Saltine.Internal.SecretBox.Key
+ Crypto.Saltine.Internal.SecretBox: instance GHC.Classes.Ord Crypto.Saltine.Internal.SecretBox.Nonce
+ Crypto.Saltine.Internal.SecretBox: instance GHC.Generics.Generic Crypto.Saltine.Internal.SecretBox.Authenticator
+ Crypto.Saltine.Internal.SecretBox: instance GHC.Generics.Generic Crypto.Saltine.Internal.SecretBox.Key
+ Crypto.Saltine.Internal.SecretBox: instance GHC.Generics.Generic Crypto.Saltine.Internal.SecretBox.Nonce
+ Crypto.Saltine.Internal.SecretBox: instance GHC.Show.Show Crypto.Saltine.Internal.SecretBox.Authenticator
+ Crypto.Saltine.Internal.SecretBox: instance GHC.Show.Show Crypto.Saltine.Internal.SecretBox.Key
+ Crypto.Saltine.Internal.SecretBox: instance GHC.Show.Show Crypto.Saltine.Internal.SecretBox.Nonce
+ Crypto.Saltine.Internal.SecretBox: newtype Authenticator
+ Crypto.Saltine.Internal.SecretBox: newtype Key
+ Crypto.Saltine.Internal.SecretBox: newtype Nonce
+ Crypto.Saltine.Internal.SecretBox: secretbox_boxzerobytes :: Int
+ Crypto.Saltine.Internal.SecretBox: secretbox_keybytes :: Int
+ Crypto.Saltine.Internal.SecretBox: secretbox_macbytes :: Int
+ Crypto.Saltine.Internal.SecretBox: secretbox_noncebytes :: Int
+ Crypto.Saltine.Internal.SecretBox: secretbox_zerobytes :: Int
+ Crypto.Saltine.Internal.Sign: Keypair :: SecretKey -> PublicKey -> Keypair
+ Crypto.Saltine.Internal.Sign: PK :: ByteString -> PublicKey
+ Crypto.Saltine.Internal.Sign: SK :: ByteString -> SecretKey
+ Crypto.Saltine.Internal.Sign: Signature :: ByteString -> Signature
+ Crypto.Saltine.Internal.Sign: [publicKey] :: Keypair -> PublicKey
+ Crypto.Saltine.Internal.Sign: [secretKey] :: Keypair -> SecretKey
+ Crypto.Saltine.Internal.Sign: [unPK] :: PublicKey -> ByteString
+ Crypto.Saltine.Internal.Sign: [unSK] :: SecretKey -> ByteString
+ Crypto.Saltine.Internal.Sign: [unSignature] :: Signature -> ByteString
+ Crypto.Saltine.Internal.Sign: c_sign :: Ptr CChar -> Ptr CULLong -> Ptr CChar -> CULLong -> Ptr CChar -> IO CInt
+ Crypto.Saltine.Internal.Sign: c_sign_detached :: Ptr CChar -> Ptr CULLong -> Ptr CChar -> CULLong -> Ptr CChar -> IO CInt
+ Crypto.Saltine.Internal.Sign: c_sign_keypair :: Ptr CChar -> Ptr CChar -> IO CInt
+ Crypto.Saltine.Internal.Sign: c_sign_open :: Ptr CChar -> Ptr CULLong -> Ptr CChar -> CULLong -> Ptr CChar -> IO CInt
+ Crypto.Saltine.Internal.Sign: c_sign_verify_detached :: Ptr CChar -> Ptr CChar -> CULLong -> Ptr CChar -> IO CInt
+ Crypto.Saltine.Internal.Sign: data Keypair
+ Crypto.Saltine.Internal.Sign: instance Control.DeepSeq.NFData Crypto.Saltine.Internal.Sign.Keypair
+ Crypto.Saltine.Internal.Sign: instance Control.DeepSeq.NFData Crypto.Saltine.Internal.Sign.PublicKey
+ Crypto.Saltine.Internal.Sign: instance Control.DeepSeq.NFData Crypto.Saltine.Internal.Sign.SecretKey
+ Crypto.Saltine.Internal.Sign: instance Control.DeepSeq.NFData Crypto.Saltine.Internal.Sign.Signature
+ Crypto.Saltine.Internal.Sign: instance Crypto.Saltine.Class.IsEncoding Crypto.Saltine.Internal.Sign.PublicKey
+ Crypto.Saltine.Internal.Sign: instance Crypto.Saltine.Class.IsEncoding Crypto.Saltine.Internal.Sign.SecretKey
+ Crypto.Saltine.Internal.Sign: instance Crypto.Saltine.Class.IsEncoding Crypto.Saltine.Internal.Sign.Signature
+ Crypto.Saltine.Internal.Sign: instance Data.Data.Data Crypto.Saltine.Internal.Sign.Keypair
+ Crypto.Saltine.Internal.Sign: instance Data.Data.Data Crypto.Saltine.Internal.Sign.PublicKey
+ Crypto.Saltine.Internal.Sign: instance Data.Data.Data Crypto.Saltine.Internal.Sign.SecretKey
+ Crypto.Saltine.Internal.Sign: instance Data.Data.Data Crypto.Saltine.Internal.Sign.Signature
+ Crypto.Saltine.Internal.Sign: instance Data.Hashable.Class.Hashable Crypto.Saltine.Internal.Sign.Keypair
+ Crypto.Saltine.Internal.Sign: instance Data.Hashable.Class.Hashable Crypto.Saltine.Internal.Sign.PublicKey
+ Crypto.Saltine.Internal.Sign: instance Data.Hashable.Class.Hashable Crypto.Saltine.Internal.Sign.SecretKey
+ Crypto.Saltine.Internal.Sign: instance Data.Hashable.Class.Hashable Crypto.Saltine.Internal.Sign.Signature
+ Crypto.Saltine.Internal.Sign: instance GHC.Classes.Eq Crypto.Saltine.Internal.Sign.Keypair
+ Crypto.Saltine.Internal.Sign: instance GHC.Classes.Eq Crypto.Saltine.Internal.Sign.PublicKey
+ Crypto.Saltine.Internal.Sign: instance GHC.Classes.Eq Crypto.Saltine.Internal.Sign.SecretKey
+ Crypto.Saltine.Internal.Sign: instance GHC.Classes.Eq Crypto.Saltine.Internal.Sign.Signature
+ Crypto.Saltine.Internal.Sign: instance GHC.Classes.Ord Crypto.Saltine.Internal.Sign.Keypair
+ Crypto.Saltine.Internal.Sign: instance GHC.Classes.Ord Crypto.Saltine.Internal.Sign.PublicKey
+ Crypto.Saltine.Internal.Sign: instance GHC.Classes.Ord Crypto.Saltine.Internal.Sign.SecretKey
+ Crypto.Saltine.Internal.Sign: instance GHC.Classes.Ord Crypto.Saltine.Internal.Sign.Signature
+ Crypto.Saltine.Internal.Sign: instance GHC.Generics.Generic Crypto.Saltine.Internal.Sign.Keypair
+ Crypto.Saltine.Internal.Sign: instance GHC.Generics.Generic Crypto.Saltine.Internal.Sign.PublicKey
+ Crypto.Saltine.Internal.Sign: instance GHC.Generics.Generic Crypto.Saltine.Internal.Sign.SecretKey
+ Crypto.Saltine.Internal.Sign: instance GHC.Generics.Generic Crypto.Saltine.Internal.Sign.Signature
+ Crypto.Saltine.Internal.Sign: instance GHC.Show.Show Crypto.Saltine.Internal.Sign.PublicKey
+ Crypto.Saltine.Internal.Sign: instance GHC.Show.Show Crypto.Saltine.Internal.Sign.SecretKey
+ Crypto.Saltine.Internal.Sign: instance GHC.Show.Show Crypto.Saltine.Internal.Sign.Signature
+ Crypto.Saltine.Internal.Sign: newtype PublicKey
+ Crypto.Saltine.Internal.Sign: newtype SecretKey
+ Crypto.Saltine.Internal.Sign: newtype Signature
+ Crypto.Saltine.Internal.Sign: sign_bytes :: Int
+ Crypto.Saltine.Internal.Sign: sign_publickeybytes :: Int
+ Crypto.Saltine.Internal.Sign: sign_secretkeybytes :: Int
+ Crypto.Saltine.Internal.Stream: Key :: ByteString -> Key
+ Crypto.Saltine.Internal.Stream: Nonce :: ByteString -> Nonce
+ Crypto.Saltine.Internal.Stream: [unKey] :: Key -> ByteString
+ Crypto.Saltine.Internal.Stream: [unNonce] :: Nonce -> ByteString
+ Crypto.Saltine.Internal.Stream: c_stream :: Ptr CChar -> CULLong -> Ptr CChar -> Ptr CChar -> IO CInt
+ Crypto.Saltine.Internal.Stream: c_stream_xor :: Ptr CChar -> Ptr CChar -> CULLong -> Ptr CChar -> Ptr CChar -> IO CInt
+ Crypto.Saltine.Internal.Stream: instance Control.DeepSeq.NFData Crypto.Saltine.Internal.Stream.Key
+ Crypto.Saltine.Internal.Stream: instance Control.DeepSeq.NFData Crypto.Saltine.Internal.Stream.Nonce
+ Crypto.Saltine.Internal.Stream: instance Crypto.Saltine.Class.IsEncoding Crypto.Saltine.Internal.Stream.Key
+ Crypto.Saltine.Internal.Stream: instance Crypto.Saltine.Class.IsEncoding Crypto.Saltine.Internal.Stream.Nonce
+ Crypto.Saltine.Internal.Stream: instance Crypto.Saltine.Class.IsNonce Crypto.Saltine.Internal.Stream.Nonce
+ Crypto.Saltine.Internal.Stream: instance Data.Data.Data Crypto.Saltine.Internal.Stream.Key
+ Crypto.Saltine.Internal.Stream: instance Data.Data.Data Crypto.Saltine.Internal.Stream.Nonce
+ Crypto.Saltine.Internal.Stream: instance Data.Hashable.Class.Hashable Crypto.Saltine.Internal.Stream.Key
+ Crypto.Saltine.Internal.Stream: instance Data.Hashable.Class.Hashable Crypto.Saltine.Internal.Stream.Nonce
+ Crypto.Saltine.Internal.Stream: instance GHC.Classes.Eq Crypto.Saltine.Internal.Stream.Key
+ Crypto.Saltine.Internal.Stream: instance GHC.Classes.Eq Crypto.Saltine.Internal.Stream.Nonce
+ Crypto.Saltine.Internal.Stream: instance GHC.Classes.Ord Crypto.Saltine.Internal.Stream.Key
+ Crypto.Saltine.Internal.Stream: instance GHC.Classes.Ord Crypto.Saltine.Internal.Stream.Nonce
+ Crypto.Saltine.Internal.Stream: instance GHC.Generics.Generic Crypto.Saltine.Internal.Stream.Key
+ Crypto.Saltine.Internal.Stream: instance GHC.Generics.Generic Crypto.Saltine.Internal.Stream.Nonce
+ Crypto.Saltine.Internal.Stream: instance GHC.Show.Show Crypto.Saltine.Internal.Stream.Key
+ Crypto.Saltine.Internal.Stream: instance GHC.Show.Show Crypto.Saltine.Internal.Stream.Nonce
+ Crypto.Saltine.Internal.Stream: newtype Key
+ Crypto.Saltine.Internal.Stream: newtype Nonce
+ Crypto.Saltine.Internal.Stream: stream_keybytes :: Int
+ Crypto.Saltine.Internal.Stream: stream_noncebytes :: Int
+ Crypto.Saltine.Internal.Util: (!&&!) :: Bool -> Bool -> Bool
+ Crypto.Saltine.Internal.Util: (!||!) :: Bool -> Bool -> Bool
+ Crypto.Saltine.Internal.Util: allocaBytes :: Int -> (Ptr a -> IO b) -> IO b
+ Crypto.Saltine.Internal.Util: bin2hex :: ByteString -> String
+ Crypto.Saltine.Internal.Util: buildUnsafeByteString :: Int -> (Ptr CChar -> IO b) -> (b, ByteString)
+ Crypto.Saltine.Internal.Util: buildUnsafeByteString' :: Int -> (Ptr CChar -> IO b) -> IO (b, ByteString)
+ Crypto.Saltine.Internal.Util: buildUnsafeScrubbedByteString :: Int -> (Ptr CChar -> IO b) -> (b, ByteString)
+ Crypto.Saltine.Internal.Util: buildUnsafeScrubbedByteString' :: Int -> (Ptr CChar -> IO b) -> IO (b, ByteString)
+ Crypto.Saltine.Internal.Util: buildUnsafeVariableByteString :: Int -> (Ptr CChar -> IO b) -> (b, ByteString)
+ Crypto.Saltine.Internal.Util: buildUnsafeVariableByteString' :: Int -> (Ptr CChar -> IO b) -> IO (b, ByteString)
+ Crypto.Saltine.Internal.Util: c_randombytes_buf :: Ptr CChar -> CInt -> IO ()
+ Crypto.Saltine.Internal.Util: c_sodium_bin2hex :: Ptr CChar -> CInt -> Ptr CChar -> CInt -> IO (Ptr CChar)
+ Crypto.Saltine.Internal.Util: c_sodium_free :: Ptr Word8 -> IO ()
+ Crypto.Saltine.Internal.Util: c_sodium_malloc :: CSize -> IO (Ptr a)
+ Crypto.Saltine.Internal.Util: c_sodium_memcmp :: Ptr CChar -> Ptr CChar -> CInt -> IO CInt
+ Crypto.Saltine.Internal.Util: compare :: ByteString -> ByteString -> Bool
+ Crypto.Saltine.Internal.Util: constByteStrings :: [ByteString] -> ([CStringLen] -> IO b) -> IO b
+ Crypto.Saltine.Internal.Util: cycleSucc :: (Bounded a, Enum a, Eq a) => a -> (Bool, a)
+ Crypto.Saltine.Internal.Util: handleErrno :: CInt -> a -> Either String a
+ Crypto.Saltine.Internal.Util: hush :: Either s a -> Maybe a
+ Crypto.Saltine.Internal.Util: nudgeBS :: ByteString -> ByteString
+ Crypto.Saltine.Internal.Util: orbit :: Eq a => (a -> a) -> a -> [a]
+ Crypto.Saltine.Internal.Util: pad :: Int -> ByteString -> ByteString
+ Crypto.Saltine.Internal.Util: randomByteString :: Int -> IO ByteString
+ Crypto.Saltine.Internal.Util: safeSubtract :: (Ord a, Num a) => a -> a -> Maybe a
+ Crypto.Saltine.Internal.Util: uncurry3 :: (a -> b -> c -> d) -> (a, b, c) -> d
+ Crypto.Saltine.Internal.Util: uncurry5 :: (a -> b -> c -> d -> e -> f) -> (a, b, c, d, e) -> f
+ Crypto.Saltine.Internal.Util: unpad :: Int -> ByteString -> ByteString
+ Crypto.Saltine.Internal.Util: unsafeDidSucceed :: IO CInt -> Bool
+ Crypto.Saltine.Internal.Util: withCString :: String -> (CString -> IO a) -> IO a
+ Crypto.Saltine.Internal.Util: withCStringLens :: [String] -> ([CStringLen] -> IO a) -> IO a
+ Crypto.Saltine.Internal.Util: withCStrings :: [String] -> ([CString] -> IO a) -> IO a
- Crypto.Saltine.Core.SecretBox: secretboxDetached :: Key -> Nonce -> ByteString -> (ByteString, ByteString)
+ Crypto.Saltine.Core.SecretBox: secretboxDetached :: Key -> Nonce -> ByteString -> (Authenticator, ByteString)
- Crypto.Saltine.Core.SecretBox: secretboxOpenDetached :: Key -> Nonce -> ByteString -> ByteString -> Maybe ByteString
+ Crypto.Saltine.Core.SecretBox: secretboxOpenDetached :: Key -> Nonce -> Authenticator -> ByteString -> Maybe ByteString
- Crypto.Saltine.Core.Sign: signDetached :: SecretKey -> ByteString -> ByteString
+ Crypto.Saltine.Core.Sign: signDetached :: SecretKey -> ByteString -> Signature
- Crypto.Saltine.Core.Sign: signVerifyDetached :: PublicKey -> ByteString -> ByteString -> Bool
+ Crypto.Saltine.Core.Sign: signVerifyDetached :: PublicKey -> Signature -> ByteString -> Bool

Files

CHANGELOG.md view
@@ -4,6 +4,23 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)  ## [Unreleased]+### Added+### Changed++## [0.2.0.0] - 2021-05-27+### Added+- All AEAD variants are now in saltine+- Key comparisons now use sodium_memcmp to prevent timing attacks+- Liberal use of Internal modules+- Benchmarks added+- Export Key/Nonce/… constructors from Internal module+- New password hashing module+- Show instances for most (all?) relevant data types+- Signature types for detached functions++### Changed+- newtype accessor functions added, keypairs are separate data types now instead+of tuples  ## [0.1.1.1] - 2021-01-15 ### Changed
README.md view
@@ -1,4 +1,4 @@-# Saltine 0.1.1.1 [![Build Status](https://travis-ci.org/tel/saltine.png?branch=master)](https://travis-ci.org/tel/saltine)[![Hackage version](https://img.shields.io/hackage/v/saltine.svg?colorB=4FB900)](https://hackage.haskell.org/package/saltine)+# Saltine 0.2.0.0 [![Hackage version](https://img.shields.io/hackage/v/saltine.svg?colorB=4FB900)](https://hackage.haskell.org/package/saltine)  A Haskell binding for @jedisct1's portable binding for djb's NaCl. **This is an early release.** Please try it out, but don't just@@ -61,7 +61,7 @@ in `C:\Program Files\Haskell Platform\*\mingw`. Then just add saltine  to your cabal file and watch it go. -Tested with [`libsodium-1.0.13`](https://download.libsodium.org/libsodium/releases/).+Tested with [`libsodium-1.0.18`](https://download.libsodium.org/libsodium/releases/).  Inspired by @thoughtpolice's [`salt`](http://github.com/thoughtpolice/salt) library. `salt` also
+ bench/AES256GCMBench.hs view
@@ -0,0 +1,68 @@+module AES256GCMBench (benchAes256GCM, aes256GCMEnv) where++import Criterion.Main++import Control.Monad+import Control.DeepSeq+import Control.Exception+import Data.ByteString as BS++import Crypto.Saltine.Core.AEAD.AES256GCM as G++import BenchUtils++aes256GCMEnv :: IO Key+aes256GCMEnv = newKey++benchAes256GCM :: Key -> Benchmark+benchAes256GCM k = do+  let encrypt :: ByteString -> ByteString -> IO ByteString+      encrypt msg aad = newNonce >>= \n -> pure $ G.aead k n msg aad++      decrypt :: ByteString -> ByteString -> IO (Maybe ByteString)+      decrypt msg aad = do+        n <- newNonce+        let ciphertext = G.aead k n msg aad+        return $ G.aeadOpen k n ciphertext aad++      encryptDetached msg aad = newNonce >>= \n -> pure $ G.aeadDetached k n msg aad+      decryptDetached msg aad = do+        n <- newNonce+        let (t,c) = G.aeadDetached k n msg aad+        pure $ G.aeadOpenDetached k n t c aad++  bgroup "AES256GCM"+    [ bench "newKey" $ nfIO newKey+    , bgroup "aead"+      [ bench "128 B + 128 B" $ nfIO $ encrypt bs128 bs128+      , bench "128 B + 5 MB"  $ nfIO $ encrypt bs128 mb5+      , bench "1 MB + 128 B"  $ nfIO $ encrypt mb1   bs128+      , bench "1 MB + 5 B"    $ nfIO $ encrypt mb1   mb5+      , bench "5 MB + 128 B"  $ nfIO $ encrypt mb5   bs128+      , bench "5 MB + 5 MB"   $ nfIO $ encrypt mb5   mb5+      ]+    , bgroup "aead + open"+      [ bench "128 B + 128 B" $ nfIO $ decrypt bs128 bs128+      , bench "128 B + 5 MB"  $ nfIO $ decrypt bs128 mb5+      , bench "1 MB + 128 B"  $ nfIO $ decrypt mb1   bs128+      , bench "1 MB + 5 B"    $ nfIO $ decrypt mb1   mb5+      , bench "5 MB + 128 B"  $ nfIO $ decrypt mb5   bs128+      , bench "5 MB + 5 MB"   $ nfIO $ decrypt mb5   mb5+      ]+    , bgroup "aeadDetached"+      [ bench "128 B + 128 B" $ nfIO $ encryptDetached bs128 bs128+      , bench "128 B + 5 MB"  $ nfIO $ encryptDetached bs128 mb5+      , bench "1 MB + 128 B"  $ nfIO $ encryptDetached mb1   bs128+      , bench "1 MB + 5 B"    $ nfIO $ encryptDetached mb1   mb5+      , bench "5 MB + 128 B"  $ nfIO $ encryptDetached mb5   bs128+      , bench "5 MB + 5 MB"   $ nfIO $ encryptDetached mb5   mb5+      ]+    , bgroup "aeadDetached + openDetached"+      [ bench "128 B + 128 B" $ nfIO $ decryptDetached bs128 bs128+      , bench "128 B + 5 MB"  $ nfIO $ decryptDetached bs128 mb5+      , bench "1 MB + 128 B"  $ nfIO $ decryptDetached mb1   bs128+      , bench "1 MB + 5 B"    $ nfIO $ decryptDetached mb1   mb5+      , bench "5 MB + 128 B"  $ nfIO $ decryptDetached mb5   bs128+      , bench "5 MB + 5 MB"   $ nfIO $ decryptDetached mb5   mb5+      ]+    ]
+ bench/AuthBench.hs view
@@ -0,0 +1,37 @@+module AuthBench (benchAuth, authEnv) where++import Criterion.Main++import Control.Monad+import Control.DeepSeq+import Control.Exception+import Data.ByteString as BS++import Crypto.Saltine.Core.Auth++import BenchUtils+++authEnv :: IO Key+authEnv = newKey++benchAuth :: Key -> Benchmark+benchAuth k = do+  let authVerify :: ByteString -> Bool+      authVerify message = do+        let authenticator = auth k message+        verify k authenticator message++  bgroup "Auth"+    [ bench "newKey" $ nfIO newKey+    , bgroup "auth"+      [ bench "128 B" $ nf (auth k) bs128+      , bench "1 MB"  $ nf (auth k) mb1+      , bench "5 MB"  $ nf (auth k) mb5+      ]+    , bgroup "auth+verify"+      [ bench "128 B" $ nf authVerify bs128+      , bench "1 MB"  $ nf authVerify mb1+      , bench "5 MB"  $ nf authVerify mb5+      ]+    ]
+ bench/BenchUtils.hs view
@@ -0,0 +1,15 @@+module BenchUtils where++import Data.ByteString (ByteString)+import qualified Data.ByteString as BS++import Data.Text as T++bs128, kb2, mb1, mb5 :: ByteString+bs128 = BS.replicate 128     0+kb2   = BS.replicate 2000    0+mb1   = BS.replicate 1000000 0+mb5   = BS.replicate 5000000 0++s128  = T.replicate 128  (T.pack "0")+s2000 = T.replicate 2000 (T.pack "0")
+ bench/BoxBench.hs view
@@ -0,0 +1,45 @@+module BoxBench (benchBox, boxEnv) where++import Criterion.Main++import Control.Monad+import Control.DeepSeq+import Control.Exception+import Data.ByteString as BS++import Crypto.Saltine.Core.Box++import BenchUtils+++boxEnv :: IO (Keypair, Keypair)+boxEnv = do+  alice <- newKeypair+  bob   <- newKeypair+  return (alice, bob)+++benchBox :: (Keypair, Keypair) -> Benchmark+benchBox (alice, bob) = do+  let encrypt :: ByteString -> IO ByteString+      encrypt b = newNonce >>= \n -> pure $ box (publicKey bob) (secretKey alice) n b++      decrypt :: ByteString -> IO (Maybe ByteString)+      decrypt message = do+        n <- newNonce+        let ciphertext = box (publicKey alice) (secretKey bob) n message+        return $ boxOpen (publicKey bob) (secretKey alice) n ciphertext++  bgroup "Box"+    [ bench "newKeypair" $ nfIO newKeypair+    , bgroup "encrypt"+      [ bench "128 B" $ nfIO $ encrypt bs128+      , bench "1 MB"  $ nfIO $ encrypt mb1+      , bench "5 MB"  $ nfIO $ encrypt mb5+      ]+    , bgroup "encrypt+decrypt"+      [ bench "128 B" $ nfIO $ decrypt bs128+      , bench "1 MB"  $ nfIO $ decrypt mb1+      , bench "5 MB"  $ nfIO $ decrypt mb5+      ]+    ]
+ bench/ChaCha20Poly1305Bench.hs view
@@ -0,0 +1,68 @@+module ChaCha20Poly1305Bench (benchChaCha20Poly1305, chaCha20Poly1305Env) where++import Criterion.Main++import Control.Monad+import Control.DeepSeq+import Control.Exception+import Data.ByteString as BS++import Crypto.Saltine.Core.AEAD.ChaCha20Poly1305 as C++import BenchUtils++chaCha20Poly1305Env :: IO Key+chaCha20Poly1305Env = newKey++benchChaCha20Poly1305 :: Key -> Benchmark+benchChaCha20Poly1305 k = do+  let encrypt :: ByteString -> ByteString -> IO ByteString+      encrypt msg aad = newNonce >>= \n -> pure $ C.aead k n msg aad++      decrypt :: ByteString -> ByteString -> IO (Maybe ByteString)+      decrypt msg aad = do+        n <- newNonce+        let ciphertext = C.aead k n msg aad+        return $ C.aeadOpen k n ciphertext aad++      encryptDetached msg aad = newNonce >>= \n -> pure $ C.aeadDetached k n msg aad+      decryptDetached msg aad = do+        n <- newNonce+        let (t,c) = C.aeadDetached k n msg aad+        pure $ C.aeadOpenDetached k n t c aad++  bgroup "ChaCha20Poly1305"+    [ bench "newKey" $ nfIO newKey+    , bgroup "aead"+      [ bench "128 B + 128 B" $ nfIO $ encrypt bs128 bs128+      , bench "128 B + 5 MB"  $ nfIO $ encrypt bs128 mb5+      , bench "1 MB + 128 B"  $ nfIO $ encrypt mb1   bs128+      , bench "1 MB + 5 B"    $ nfIO $ encrypt mb1   mb5+      , bench "5 MB + 128 B"  $ nfIO $ encrypt mb5   bs128+      , bench "5 MB + 5 MB"   $ nfIO $ encrypt mb5   mb5+      ]+    , bgroup "aead + open"+      [ bench "128 B + 128 B" $ nfIO $ decrypt bs128 bs128+      , bench "128 B + 5 MB"  $ nfIO $ decrypt bs128 mb5+      , bench "1 MB + 128 B"  $ nfIO $ decrypt mb1   bs128+      , bench "1 MB + 5 B"    $ nfIO $ decrypt mb1   mb5+      , bench "5 MB + 128 B"  $ nfIO $ decrypt mb5   bs128+      , bench "5 MB + 5 MB"   $ nfIO $ decrypt mb5   mb5+      ]+    , bgroup "aeadDetached"+      [ bench "128 B + 128 B" $ nfIO $ encryptDetached bs128 bs128+      , bench "128 B + 5 MB"  $ nfIO $ encryptDetached bs128 mb5+      , bench "1 MB + 128 B"  $ nfIO $ encryptDetached mb1   bs128+      , bench "1 MB + 5 B"    $ nfIO $ encryptDetached mb1   mb5+      , bench "5 MB + 128 B"  $ nfIO $ encryptDetached mb5   bs128+      , bench "5 MB + 5 MB"   $ nfIO $ encryptDetached mb5   mb5+      ]+    , bgroup "aeadDetached + openDetached"+      [ bench "128 B + 128 B" $ nfIO $ decryptDetached bs128 bs128+      , bench "128 B + 5 MB"  $ nfIO $ decryptDetached bs128 mb5+      , bench "1 MB + 128 B"  $ nfIO $ decryptDetached mb1   bs128+      , bench "1 MB + 5 B"    $ nfIO $ decryptDetached mb1   mb5+      , bench "5 MB + 128 B"  $ nfIO $ decryptDetached mb5   bs128+      , bench "5 MB + 5 MB"   $ nfIO $ decryptDetached mb5   mb5+      ]+    ]
+ bench/ChaCha20Poly1305IETFBench.hs view
@@ -0,0 +1,68 @@+module ChaCha20Poly1305IETFBench (benchChaCha20Poly1305IETF, chaCha20Poly1305IETFEnv) where++import Criterion.Main++import Control.Monad+import Control.DeepSeq+import Control.Exception+import Data.ByteString as BS++import Crypto.Saltine.Core.AEAD.ChaCha20Poly1305IETF as C++import BenchUtils++chaCha20Poly1305IETFEnv :: IO Key+chaCha20Poly1305IETFEnv = newKey++benchChaCha20Poly1305IETF :: Key -> Benchmark+benchChaCha20Poly1305IETF k = do+  let encrypt :: ByteString -> ByteString -> IO ByteString+      encrypt msg aad = newNonce >>= \n -> pure $ C.aead k n msg aad++      decrypt :: ByteString -> ByteString -> IO (Maybe ByteString)+      decrypt msg aad = do+        n <- newNonce+        let ciphertext = C.aead k n msg aad+        return $ C.aeadOpen k n ciphertext aad++      encryptDetached msg aad = newNonce >>= \n -> pure $ C.aeadDetached k n msg aad+      decryptDetached msg aad = do+        n <- newNonce+        let (t,c) = C.aeadDetached k n msg aad+        pure $ C.aeadOpenDetached k n t c aad++  bgroup "ChaCha20Poly1305IETF"+    [ bench "newKey" $ nfIO newKey+    , bgroup "aead"+      [ bench "128 B + 128 B" $ nfIO $ encrypt bs128 bs128+      , bench "128 B + 5 MB"  $ nfIO $ encrypt bs128 mb5+      , bench "1 MB + 128 B"  $ nfIO $ encrypt mb1   bs128+      , bench "1 MB + 5 B"    $ nfIO $ encrypt mb1   mb5+      , bench "5 MB + 128 B"  $ nfIO $ encrypt mb5   bs128+      , bench "5 MB + 5 MB"   $ nfIO $ encrypt mb5   mb5+      ]+    , bgroup "aead + open"+      [ bench "128 B + 128 B" $ nfIO $ decrypt bs128 bs128+      , bench "128 B + 5 MB"  $ nfIO $ decrypt bs128 mb5+      , bench "1 MB + 128 B"  $ nfIO $ decrypt mb1   bs128+      , bench "1 MB + 5 B"    $ nfIO $ decrypt mb1   mb5+      , bench "5 MB + 128 B"  $ nfIO $ decrypt mb5   bs128+      , bench "5 MB + 5 MB"   $ nfIO $ decrypt mb5   mb5+      ]+    , bgroup "aeadDetached"+      [ bench "128 B + 128 B" $ nfIO $ encryptDetached bs128 bs128+      , bench "128 B + 5 MB"  $ nfIO $ encryptDetached bs128 mb5+      , bench "1 MB + 128 B"  $ nfIO $ encryptDetached mb1   bs128+      , bench "1 MB + 5 B"    $ nfIO $ encryptDetached mb1   mb5+      , bench "5 MB + 128 B"  $ nfIO $ encryptDetached mb5   bs128+      , bench "5 MB + 5 MB"   $ nfIO $ encryptDetached mb5   mb5+      ]+    , bgroup "aeadDetached + openDetached"+      [ bench "128 B + 128 B" $ nfIO $ decryptDetached bs128 bs128+      , bench "128 B + 5 MB"  $ nfIO $ decryptDetached bs128 mb5+      , bench "1 MB + 128 B"  $ nfIO $ decryptDetached mb1   bs128+      , bench "1 MB + 5 B"    $ nfIO $ decryptDetached mb1   mb5+      , bench "5 MB + 128 B"  $ nfIO $ decryptDetached mb5   bs128+      , bench "5 MB + 5 MB"   $ nfIO $ decryptDetached mb5   mb5+      ]+    ]
+ bench/ConstantTimeBench.hs view
@@ -0,0 +1,29 @@+module ConstantTimeBench (benchComparison) where++import Criterion.Main++import Control.Monad+import Control.DeepSeq+import Control.Exception+import Data.ByteString              as BS++import Crypto.Saltine.Core.Auth     as A+import Crypto.Saltine.Class+import Crypto.Saltine.Internal.Util as U++import BenchUtils++benchComparison :: Benchmark+benchComparison =+  bgroup "ConstantTime"+    [ bench "Compare two \"keys\" using ByteString comparison" $ nfIO $ do+        k1 <- randomByteString (2^20)+        k2 <- randomByteString (2^20)++        pure $ k1 == k2+    , bench "Compare two keys using constant-time comparison" $ nfIO $ do+        k1 <- randomByteString (2^20)+        k2 <- randomByteString (2^20)++        pure $ U.compare k1 k2+    ]
+ bench/HashBench.hs view
@@ -0,0 +1,40 @@+module HashBench (benchHash, hashEnv) where++import Criterion++import Control.Monad++import Crypto.Saltine.Core.Hash+import Crypto.Saltine.Core.Utils++import BenchUtils+import Data.Maybe (fromJust)++hashEnv :: IO (ShorthashKey, GenerichashKey, GenerichashOutLen)+hashEnv = do+    shk <- newShorthashKey+    ghk <- fromJust <$> newGenerichashKey 48+    let ghol = fromJust (generichashOutLen 48)++    pure (shk,ghk,ghol)++benchHash :: (ShorthashKey, GenerichashKey, GenerichashOutLen) -> Benchmark+benchHash (shk,ghk,ghol) =+  bgroup "Hash"+    [ bgroup "hash"+      [ bench "128 B" $ nf hash bs128+      , bench "1 MB"  $ nf hash mb1+      , bench "5 MB"  $ nf hash mb5+      ]+    , bgroup "shortHash"+      [ bench "128 B" $ nf (shorthash shk) bs128+      , bench "2 KB"  $ nf (shorthash shk) kb2+      , bench "1 MB"  $ nf (shorthash shk) mb1+      ]+    , bgroup "genericHash"+      [ bench "128 B" $ nf (generichash ghk bs128) ghol+      , bench "2 KB"  $ nf (generichash ghk kb2  ) ghol+      , bench "1 MB"  $ nf (generichash ghk mb1  ) ghol+      , bench "5 MB"  $ nf (generichash ghk mb5  ) ghol+      ]+    ]
+ bench/Main.hs view
@@ -0,0 +1,79 @@+import Criterion.Main++import Control.Monad+import Control.DeepSeq+import Control.Exception++import AuthBench+import OneTimeAuthBench+import BoxBench+import SecretBoxBench+import ConstantTimeBench+import HashBench+import RandomBench+import ScalarMultBench+import SignBench+import StreamBench+import PasswordBench+import AES256GCMBench+import ChaCha20Poly1305Bench+import ChaCha20Poly1305IETFBench+import XChaCha20Poly1305Bench++main :: IO ()+main = do+  authKeyToEval <- authEnv+  authKey <- evaluate $ force authKeyToEval++  oneTimeAuthKeyToEval <- oneTimeAuthEnv+  oneTimeAuthKey <- evaluate $ force oneTimeAuthKeyToEval++  boxToEval <- boxEnv+  boxKeys <- evaluate $ force boxToEval++  secretboxKeyToEval <- secretboxEnv+  secretboxKey <- evaluate $ force secretboxKeyToEval++  scmlToEval <- scalarMultEnv+  scml <- evaluate $ force scmlToEval++  signToEval <- signEnv+  signKey <- evaluate $ force signToEval++  streamKeyToEval <- streamEnv+  streamKey <- evaluate $ force streamKeyToEval++  passwordSaltToEval <- passwordEnv+  passwordSalt <- evaluate $ force passwordSaltToEval++  hashKeysToEval <- hashEnv+  hashKeys <- evaluate $ force hashKeysToEval++  aes256GCMKeyToEval <- aes256GCMEnv+  aes256GCMKey <- evaluate $ force aes256GCMKeyToEval++  chaCha20Poly1305KeyToEval <- chaCha20Poly1305Env+  chaCha20Poly1305Key <- evaluate $ force chaCha20Poly1305KeyToEval++  chaCha20Poly1305IETFKeyToEval <- chaCha20Poly1305IETFEnv+  chaCha20Poly1305IETFKey <- evaluate $ force chaCha20Poly1305IETFKeyToEval++  xChaCha20Poly1305KeyToEval <- xChaCha20Poly1305Env+  xChaCha20Poly1305Key <- evaluate $ force xChaCha20Poly1305KeyToEval++  defaultMain [+      benchAuth authKey+    , benchOneTimeAuth oneTimeAuthKey+    , benchBox boxKeys+    , benchSecretbox secretboxKey+    , benchHash hashKeys+    , benchScalarMult scml+    , benchSign signKey+    , benchStream streamKey+    , benchPassword passwordSalt+    , benchComparison+    , benchAes256GCM aes256GCMKey+    , benchChaCha20Poly1305 chaCha20Poly1305Key+    , benchChaCha20Poly1305IETF chaCha20Poly1305IETFKey+    , benchXChaCha20Poly1305 xChaCha20Poly1305Key+    ]
+ bench/OneTimeAuthBench.hs view
@@ -0,0 +1,37 @@+module OneTimeAuthBench (benchOneTimeAuth, oneTimeAuthEnv) where++import Criterion.Main++import Control.Monad+import Control.DeepSeq+import Control.Exception+import Data.ByteString as BS++import Crypto.Saltine.Core.OneTimeAuth++import BenchUtils+++oneTimeAuthEnv :: IO Key+oneTimeAuthEnv = newKey++benchOneTimeAuth :: Key -> Benchmark+benchOneTimeAuth k = do+  let authVerify :: ByteString -> Bool+      authVerify message = do+        let authenticator = auth k message+        verify k authenticator message++  bgroup "OneTimeAuth"+    [ bench "newKey" $ nfIO newKey+    , bgroup "auth"+      [ bench "128 B" $ nf (auth k) bs128+      , bench "1 MB"  $ nf (auth k) mb1+      , bench "5 MB"  $ nf (auth k) mb5+      ]+    , bgroup "auth+verify"+      [ bench "128 B" $ nf authVerify bs128+      , bench "1 MB"  $ nf authVerify mb1+      , bench "5 MB"  $ nf authVerify mb5+      ]+    ]
+ bench/PasswordBench.hs view
@@ -0,0 +1,87 @@+module PasswordBench (benchPassword, passwordEnv) where++import Criterion.Main++import Control.Monad+import Control.DeepSeq+import Control.Exception+import Data.ByteString as BS+import Data.Maybe      (fromJust)+import Data.Text       (Text)++import Crypto.Saltine.Core.Password as P++import BenchUtils++passwordEnv :: IO Salt+passwordEnv = newSalt++benchPassword :: Salt -> Benchmark+benchPassword s = do+  let hashAndVerify :: Text -> Policy ->  IO Bool+      hashAndVerify p pol = do+          h <- pwhashStr p pol+          pure $ pwhashStrVerify (fromJust h) p++      hashAndRehash :: Text -> Policy -> IO (Maybe Bool)+      hashAndRehash p pol = do+          h <- pwhashStr p pol+          pure $ needsRehash (opsPolicy pol) (memPolicy pol) (fromJust h)++  bgroup "Password"+    [ bench "newSalt" $ nfIO newSalt+    , bgroup "hash + verify"+      [ bgroup "interactive"+        [ bench "128 B" $ nfIO $ hashAndVerify s128  interactivePolicy+        , bench "2 KB"  $ nfIO $ hashAndVerify s2000 interactivePolicy+        ]+      , bgroup "moderate"+        [ bench "128 B" $ nfIO $ hashAndVerify s128  moderatePolicy+        , bench "2 KB"  $ nfIO $ hashAndVerify s2000 moderatePolicy+        ]+      , bgroup "sensitive"+        [ bench "128 B" $ nfIO $ hashAndVerify s128  sensitivePolicy+        , bench "2 KB"  $ nfIO $ hashAndVerify s2000 sensitivePolicy+        ]+      ]+    , bgroup "needsRehash"+      [ bgroup "interactive"+        [ bench "128 B" $ nfIO $ hashAndRehash s128  interactivePolicy+        , bench "2 KB"  $ nfIO $ hashAndRehash s2000 interactivePolicy+        ]+      , bgroup "moderate"+        [ bench "128 B" $ nfIO $ hashAndRehash s128  moderatePolicy+        , bench "2 KB"  $ nfIO $ hashAndRehash s2000 moderatePolicy+        ]+      , bgroup "sensitive"+        [ bench "128 B" $ nfIO $ hashAndRehash s128  sensitivePolicy+        , bench "2 KB"  $ nfIO $ hashAndRehash s2000 sensitivePolicy+        ]+      ]+    , bgroup "pwhash"+      [ bgroup "interactive"+        [ bench "128 B + 256"  $ nf (pwhash s128 (2^8 ) s) interactivePolicy+        , bench "128 B + 512"  $ nf (pwhash s128 (2^9 ) s) interactivePolicy+        , bench "128 B + 1024" $ nf (pwhash s128 (2^10) s) interactivePolicy+        , bench "128 B + 2048" $ nf (pwhash s128 (2^11) s) interactivePolicy+        , bench "128 B + 4096" $ nf (pwhash s128 (2^12) s) interactivePolicy+        , bench "128 B + 8192" $ nf (pwhash s128 (2^13) s) interactivePolicy+        ]+      , bgroup "moderate"+        [ bench "128 B + 256"  $ nf (pwhash s128 (2^8 ) s) moderatePolicy+        , bench "128 B + 512"  $ nf (pwhash s128 (2^9 ) s) moderatePolicy+        , bench "128 B + 1024" $ nf (pwhash s128 (2^10) s) moderatePolicy+        , bench "128 B + 2048" $ nf (pwhash s128 (2^11) s) moderatePolicy+        , bench "128 B + 4096" $ nf (pwhash s128 (2^12) s) moderatePolicy+        , bench "128 B + 8192" $ nf (pwhash s128 (2^13) s) moderatePolicy+        ]+      , bgroup "sensitive"+        [ bench "128 B + 256"  $ nf (pwhash s128 (2^8 ) s) sensitivePolicy+        , bench "128 B + 512"  $ nf (pwhash s128 (2^9 ) s) sensitivePolicy+        , bench "128 B + 1024" $ nf (pwhash s128 (2^10) s) sensitivePolicy+        , bench "128 B + 2048" $ nf (pwhash s128 (2^11) s) sensitivePolicy+        , bench "128 B + 4096" $ nf (pwhash s128 (2^12) s) sensitivePolicy+        , bench "128 B + 8192" $ nf (pwhash s128 (2^13) s) sensitivePolicy+        ]+      ]+    ]
+ bench/RandomBench.hs view
@@ -0,0 +1,21 @@+module RandomBench (benchRandom) where++import Criterion++import Data.ByteString (ByteString)+import Crypto.Saltine.Core.Utils++benchRandom = bgroup "random"+  [ bench "32 B"   $ nfIO (randomByteString 32          :: IO ByteString)+  , bench "128 B"  $ nfIO (randomByteString 128         :: IO ByteString)+  , bench "512 B"  $ nfIO (randomByteString 512         :: IO ByteString)+  , bench "2 KB"   $ nfIO (randomByteString 2000        :: IO ByteString)+  , bench "8 KB"   $ nfIO (randomByteString 8000        :: IO ByteString)+  , bench "32 KB"  $ nfIO (randomByteString 32000       :: IO ByteString)+  , bench "128 KB" $ nfIO (randomByteString 128000      :: IO ByteString)+  , bench "512 KB" $ nfIO (randomByteString 512000      :: IO ByteString)+  , bench "2 MB"   $ nfIO (randomByteString 2000000     :: IO ByteString)+  , bench "8 MB"   $ nfIO (randomByteString 8000000     :: IO ByteString)+  , bench "32 MB"  $ nfIO (randomByteString 32000000    :: IO ByteString)+  , bench "128 MB" $ nfIO (randomByteString 128000000   :: IO ByteString)+  ]
+ bench/ScalarMultBench.hs view
@@ -0,0 +1,35 @@+module ScalarMultBench (benchScalarMult, scalarMultEnv) where++import Criterion.Main++import Control.Monad+import Control.DeepSeq+import Control.Exception+import Data.ByteString as BS++import Data.Maybe (fromJust)++import Crypto.Saltine.Class+import Crypto.Saltine.Core.ScalarMult as S+import Crypto.Saltine.Internal.ScalarMult as Bytes+import Crypto.Saltine.Internal.Util++import BenchUtils++scalarMultEnv :: IO (GroupElement, Scalar)+scalarMultEnv = do+    bsge <- randomByteString Bytes.scalarmult_bytes+    bssc <- randomByteString Bytes.scalarmult_scalarbytes++    let ge = fromJust $ decode bsge+    let sc = fromJust $ decode bssc++    pure (ge,sc)+++benchScalarMult :: (GroupElement, Scalar) -> Benchmark+benchScalarMult (ge,sc) =+  bgroup "ScalarMult"+    [ bench "mult"     $ nf (S.mult    sc) ge+    , bench "multBase" $ nf S.multBase sc+    ]
+ bench/SecretBoxBench.hs view
@@ -0,0 +1,57 @@+module SecretBoxBench (benchSecretbox, secretboxEnv) where++import Criterion.Main++import Control.Monad+import Control.DeepSeq+import Control.Exception+import Data.ByteString as BS++import Crypto.Saltine.Core.SecretBox++import BenchUtils+++secretboxEnv :: IO Key+secretboxEnv = newKey++benchSecretbox :: Key -> Benchmark+benchSecretbox k = do+  let encrypt :: ByteString -> IO ByteString+      encrypt msg = newNonce >>= \n -> pure $ secretbox k n msg++      decrypt :: ByteString -> IO (Maybe ByteString)+      decrypt msg = do+        n <- newNonce+        let ciphertext = secretbox k n msg+        return $ secretboxOpen k n ciphertext++      encryptDetached msg = newNonce >>= \n -> pure $ secretboxDetached k n msg+      decryptDetached msg = do+          n <- newNonce+          let (t,c) = secretboxDetached k n msg+          pure $ secretboxOpenDetached k n t c++  bgroup "Box"+    [ bench "newKey" $ nfIO newKey+    , bgroup "encrypt"+      [ bench "128 B" $ nfIO $ encrypt bs128+      , bench "1 MB"  $ nfIO $ encrypt mb1+      , bench "5 MB"  $ nfIO $ encrypt mb5+      ]+    , bgroup "encrypt+decrypt"+      [ bench "128 B" $ nfIO $ decrypt bs128+      , bench "1 MB"  $ nfIO $ decrypt mb1+      , bench "5 MB"  $ nfIO $ decrypt mb5+      ]+    , bgroup "encryptDetached"+      [ bench "128 B" $ nfIO $ encryptDetached bs128+      , bench "1 MB"  $ nfIO $ encryptDetached mb1+      , bench "5 MB"  $ nfIO $ encryptDetached mb5+      ]+    , bgroup "encryptDetached+decryptDetached"+      [ bench "128 B" $ nfIO $ decryptDetached bs128+      , bench "1 MB"  $ nfIO $ decryptDetached mb1+      , bench "5 MB"  $ nfIO $ decryptDetached mb5+      ]+    ]
+ bench/SignBench.hs view
@@ -0,0 +1,53 @@+module SignBench (benchSign, signEnv) where++import Criterion.Main++import Control.Monad+import Control.DeepSeq+import Control.Exception+import Data.ByteString as BS++import Crypto.Saltine.Core.Sign as S++import BenchUtils++signEnv :: IO Keypair+signEnv = newKeypair++benchSign :: Keypair -> Benchmark+benchSign alice = do+  let sign :: ByteString -> ByteString+      sign = S.sign (secretKey alice)++      verify :: ByteString -> Bool+      verify message =+        let signed = sign message+        in case S.signOpen (publicKey alice) signed of+          Nothing -> False+          Just ms -> True++      signDetached               = S.signDetached       (secretKey alice)+      signVerifyDetached message = S.signVerifyDetached (publicKey alice) (signDetached message)+  bgroup "Sign"+    [ bench "newKeypair" $ nfIO newKeypair+    , bgroup "sign"+      [ bench "128 B" $ nf sign bs128+      , bench "1 MB"  $ nf sign mb1+      , bench "5 MB"  $ nf sign mb5+      ]+    , bgroup "sign+verify"+      [ bench "128 B" $ nf verify bs128+      , bench "1 MB"  $ nf verify mb1+      , bench "5 MB"  $ nf verify mb5+      ]+    , bgroup "signDetached"+      [ bench "128 B" $ nf signDetached bs128+      , bench "1 MB"  $ nf signDetached mb1+      , bench "5 MB"  $ nf signDetached mb5+      ]+    , bgroup "signDetached+verifyDetached"+      [ bench "128 B" $ nf signVerifyDetached bs128+      , bench "1 MB"  $ nf signVerifyDetached mb1+      , bench "5 MB"  $ nf signVerifyDetached mb5+      ]+    ]
+ bench/StreamBench.hs view
@@ -0,0 +1,37 @@+module StreamBench (benchStream, streamEnv) where++import Criterion.Main++import Control.Monad+import Control.DeepSeq+import Control.Exception+import Data.ByteString as BS++import Crypto.Saltine.Core.Stream as S++import BenchUtils++streamEnv :: IO Key+streamEnv = newKey++benchStream :: Key -> Benchmark+benchStream k = do+  let stream :: Int -> IO ByteString+      stream i = newNonce >>= \n -> pure $ S.stream k n i++      xor :: ByteString -> IO ByteString+      xor m = newNonce >>= \n -> pure $ S.xor k n m++  bgroup "Stream"+    [ bench "newKey" $ nfIO newKey+    , bgroup "stream"+      [ bench "128 B" $ nfIO $ stream (2^7)+      , bench "1 MB"  $ nfIO $ stream (2^20)+      , bench "16 MB" $ nfIO $ stream (2^24)+      ]+    , bgroup "xor"+      [ bench "128 B" $ nfIO $ xor bs128+      , bench "1 MB"  $ nfIO $ xor mb1+      , bench "5 MB"  $ nfIO $ xor mb5+      ]+    ]
+ bench/XChaCha20Poly1305Bench.hs view
@@ -0,0 +1,68 @@+module XChaCha20Poly1305Bench (benchXChaCha20Poly1305, xChaCha20Poly1305Env) where++import Criterion.Main++import Control.Monad+import Control.DeepSeq+import Control.Exception+import Data.ByteString as BS++import Crypto.Saltine.Core.AEAD.XChaCha20Poly1305 as C++import BenchUtils++xChaCha20Poly1305Env :: IO Key+xChaCha20Poly1305Env = newKey++benchXChaCha20Poly1305 :: Key -> Benchmark+benchXChaCha20Poly1305 k = do+  let encrypt :: ByteString -> ByteString -> IO ByteString+      encrypt msg aad = newNonce >>= \n -> pure $ C.aead k n msg aad++      decrypt :: ByteString -> ByteString -> IO (Maybe ByteString)+      decrypt msg aad = do+        n <- newNonce+        let ciphertext = C.aead k n msg aad+        return $ C.aeadOpen k n ciphertext aad++      encryptDetached msg aad = newNonce >>= \n -> pure $ C.aeadDetached k n msg aad+      decryptDetached msg aad = do+        n <- newNonce+        let (t,c) = C.aeadDetached k n msg aad+        pure $ C.aeadOpenDetached k n t c aad++  bgroup "XChaCha20Poly1305"+    [ bench "newKey" $ nfIO newKey+    , bgroup "aead"+      [ bench "128 B + 128 B" $ nfIO $ encrypt bs128 bs128+      , bench "128 B + 5 MB"  $ nfIO $ encrypt bs128 mb5+      , bench "1 MB + 128 B"  $ nfIO $ encrypt mb1   bs128+      , bench "1 MB + 5 B"    $ nfIO $ encrypt mb1   mb5+      , bench "5 MB + 128 B"  $ nfIO $ encrypt mb5   bs128+      , bench "5 MB + 5 MB"   $ nfIO $ encrypt mb5   mb5+      ]+    , bgroup "aead + open"+      [ bench "128 B + 128 B" $ nfIO $ decrypt bs128 bs128+      , bench "128 B + 5 MB"  $ nfIO $ decrypt bs128 mb5+      , bench "1 MB + 128 B"  $ nfIO $ decrypt mb1   bs128+      , bench "1 MB + 5 B"    $ nfIO $ decrypt mb1   mb5+      , bench "5 MB + 128 B"  $ nfIO $ decrypt mb5   bs128+      , bench "5 MB + 5 MB"   $ nfIO $ decrypt mb5   mb5+      ]+    , bgroup "aeadDetached"+      [ bench "128 B + 128 B" $ nfIO $ encryptDetached bs128 bs128+      , bench "128 B + 5 MB"  $ nfIO $ encryptDetached bs128 mb5+      , bench "1 MB + 128 B"  $ nfIO $ encryptDetached mb1   bs128+      , bench "1 MB + 5 B"    $ nfIO $ encryptDetached mb1   mb5+      , bench "5 MB + 128 B"  $ nfIO $ encryptDetached mb5   bs128+      , bench "5 MB + 5 MB"   $ nfIO $ encryptDetached mb5   mb5+      ]+    , bgroup "aeadDetached + openDetached"+      [ bench "128 B + 128 B" $ nfIO $ decryptDetached bs128 bs128+      , bench "128 B + 5 MB"  $ nfIO $ decryptDetached bs128 mb5+      , bench "1 MB + 128 B"  $ nfIO $ decryptDetached mb1   bs128+      , bench "1 MB + 5 B"    $ nfIO $ decryptDetached mb1   mb5+      , bench "5 MB + 128 B"  $ nfIO $ decryptDetached mb5   bs128+      , bench "5 MB + 5 MB"   $ nfIO $ decryptDetached mb5   mb5+      ]+    ]
saltine.cabal view
@@ -1,5 +1,7 @@+cabal-version: 2.0+ name:                saltine-version:             0.1.1.1+version:             0.2.0.0 synopsis:            Cryptography that's easy to digest (NaCl/libsodium bindings). description: @@ -30,8 +32,7 @@ copyright:           Copyright (c) Joseph Abrahamson 2013 category:            Cryptography build-type:          Simple-cabal-version:       >=1.10-tested-with:         GHC==7.8.4, GHC==7.10.3, GHC==8.0.2, GHC==8.2.2, GHC==8.4.3, GHC==8.6.5, GHC==8.8.3+tested-with:         GHC==8.0.2, GHC==8.2.2, GHC==8.4.4, GHC==8.6.5, GHC==8.8.4, GHC==8.10.4, GHC==9.0.1  source-repository head   type: git@@ -41,9 +42,13 @@   hs-source-dirs:     src   exposed-modules:                   Crypto.Saltine-                  Crypto.Saltine.Internal.ByteSizes+                  Crypto.Saltine.Class                   Crypto.Saltine.Core.SecretBox                   Crypto.Saltine.Core.AEAD+                  Crypto.Saltine.Core.AEAD.AES256GCM+                  Crypto.Saltine.Core.AEAD.ChaCha20Poly1305+                  Crypto.Saltine.Core.AEAD.ChaCha20Poly1305IETF+                  Crypto.Saltine.Core.AEAD.XChaCha20Poly1305                   Crypto.Saltine.Core.Box                   Crypto.Saltine.Core.Stream                   Crypto.Saltine.Core.Auth@@ -51,24 +56,40 @@                   Crypto.Saltine.Core.Sign                   Crypto.Saltine.Core.Hash                   Crypto.Saltine.Core.ScalarMult+                  Crypto.Saltine.Core.Password                   Crypto.Saltine.Core.Utils-                  Crypto.Saltine.Class-  other-modules:+                  Crypto.Saltine.Internal.AEAD.AES256GCM+                  Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305+                  Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305IETF+                  Crypto.Saltine.Internal.AEAD.XChaCha20Poly1305+                  Crypto.Saltine.Internal.Auth+                  Crypto.Saltine.Internal.Box+                  Crypto.Saltine.Internal.ByteSizes+                  Crypto.Saltine.Internal.Hash+                  Crypto.Saltine.Internal.OneTimeAuth+                  Crypto.Saltine.Internal.Password+                  Crypto.Saltine.Internal.ScalarMult+                  Crypto.Saltine.Internal.SecretBox+                  Crypto.Saltine.Internal.Sign+                  Crypto.Saltine.Internal.Stream                   Crypto.Saltine.Internal.Util+  other-modules:    if os(windows)     extra-libraries: sodium   else-    pkgconfig-depends: libsodium >= 1.0.13+    pkgconfig-depends: libsodium >= 1.0.18    cc-options:         -Wall   ghc-options:        -Wall -funbox-strict-fields   default-language:   Haskell2010   build-depends:-                base >= 4.5 && < 5-              , bytestring >= 0.10.8 && < 0.11-              , profunctors >= 5.3 && < 5.7+                base        >= 4.5    && < 5+              , bytestring  >= 0.10.8 && < 0.11+              , deepseq    ^>= 1.4+              , profunctors >= 5.3    && < 5.7               , hashable+              , text       ^>= 1.2  test-suite tests   type:    exitcode-stdio-1.0@@ -78,13 +99,18 @@                 BoxProperties                 HashProperties                 OneTimeAuthProperties+                PasswordProperties                 ScalarMultProperties                 SecretBoxProperties                 SealedBoxProperties                 SignProperties                 StreamProperties-                AEADProperties+                AEAD.AES256GCMProperties+                AEAD.ChaCha20Poly1305IETFProperties+                AEAD.ChaCha20Poly1305Properties+                AEAD.XChaCha20Poly1305Properties                 Util+                UtilProperties   ghc-options: -Wall -threaded -rtsopts   hs-source-dirs: tests   default-language: Haskell2010@@ -92,7 +118,42 @@                 base >= 4.7 && < 5               , saltine               , bytestring+              , text               , QuickCheck               , test-framework-quickcheck2               , test-framework               , semigroups++benchmark benchmarks+  type: exitcode-stdio-1.0+  main-is: Main.hs+  hs-source-dirs:+      bench+  ghc-options: -rtsopts -threaded -with-rtsopts=-N -O2+  extra-libraries:+      sodium+  build-depends:+      base+    , bytestring+    , text+    , criterion+    , deepseq+    , saltine+  other-modules:+      AuthBench+      OneTimeAuthBench+      ConstantTimeBench+      BoxBench+      SecretBoxBench+      HashBench+      RandomBench+      PasswordBench+      ScalarMultBench+      SignBench+      StreamBench+      BenchUtils+      AES256GCMBench+      ChaCha20Poly1305Bench+      ChaCha20Poly1305IETFBench+      XChaCha20Poly1305Bench+  default-language: Haskell2010
src/Crypto/Saltine/Class.hs view
@@ -1,3 +1,5 @@+-- {-# LANGUAGE FlexibleInstances #-}+ -- | -- Module      : Crypto.Saltine.Class -- Copyright   : (c) Joseph Abrahamson 2013@@ -13,9 +15,8 @@   IsNonce (..)   ) where -import           Control.Applicative-import           Data.Profunctor-import           Data.ByteString     (ByteString)+import Data.Profunctor+import Data.ByteString (ByteString)  -- | Class for all keys and nonces in Saltine which have a -- representation as ByteString. 'encoded' is a 'Prism' of
src/Crypto/Saltine/Core/AEAD.hs view
@@ -1,11 +1,10 @@-{-# LANGUAGE DeriveDataTypeable, GeneralizedNewtypeDeriving, DeriveGeneric #-}- -- | -- Module      : Crypto.Saltine.Core.AEAD -- Copyright   : (c) Thomas DuBuisson 2017+--               (c) Max Amanshauser 2021 -- License     : MIT ----- Maintainer  : me@jspha.com+-- Maintainer  : max@lambdalifting.org -- Stability   : experimental -- Portability : non-portable --@@ -30,232 +29,19 @@ -- Note that the length is not hidden. Note also that it is the -- caller's responsibility to ensure the uniqueness of nonces—for -- example, by using nonce 1 for the first message, nonce 2 for the--- second message, etc. Nonces are long enough that randomly generated--- nonces have negligible risk of collision.+-- second message, etc. With XChaCha20Poly1305 nonces are long enough+-- that you can also generate nonces randomly as they have negligible+-- risk of collision.+--+-- The keysize is identical for all the *ChaCha20Poly1305* variants,+-- but the nonce length differs. Since libsodium keeps separate definitions,+-- we do the same.+--+-- This module reexports the XChaCha20Poly1305 variant, which is the+-- recommended one.  module Crypto.Saltine.Core.AEAD (-  Key, Nonce,-  aead, aeadOpen,-  aeadDetached, aeadOpenDetached,-  newKey, newNonce+  module X   ) where -import           Crypto.Saltine.Class-import           Crypto.Saltine.Internal.Util-import qualified Crypto.Saltine.Internal.ByteSizes as Bytes--import           Control.Applicative-import           Foreign.C-import           Foreign.Ptr-import qualified Data.ByteString                   as S-import           Data.ByteString                     (ByteString)-import           Data.Hashable (Hashable)-import           Data.Data (Data, Typeable)-import           GHC.Generics (Generic)---- $types---- | An opaque 'secretbox' cryptographic key.-newtype Key = Key ByteString deriving (Eq, Ord, Hashable, Data, Typeable, Generic)--instance IsEncoding Key where-  decode v = if S.length v == Bytes.secretBoxKey-           then Just (Key v)-           else Nothing-  {-# INLINE decode #-}-  encode (Key v) = v-  {-# INLINE encode #-}---- | An opaque 'secretbox' nonce.-newtype Nonce = Nonce ByteString deriving (Eq, Ord, Hashable, Data, Typeable, Generic)--instance IsEncoding Nonce where-  decode v = if S.length v == Bytes.secretBoxNonce-           then Just (Nonce v)-           else Nothing-  {-# INLINE decode #-}-  encode (Nonce v) = v-  {-# INLINE encode #-}--instance IsNonce Nonce where-  zero            = Nonce (S.replicate Bytes.secretBoxNonce 0)-  nudge (Nonce n) = Nonce (nudgeBS n)---- | Creates a random key of the correct size for 'secretbox'.-newKey :: IO Key-newKey = Key <$> randomByteString Bytes.secretBoxKey---- | Creates a random nonce of the correct size for 'secretbox'.-newNonce :: IO Nonce-newNonce = Nonce <$> randomByteString Bytes.secretBoxNonce----- | Encrypts a message. It is infeasible for an attacker to decrypt--- the message so long as the 'Nonce' is never repeated.-aead :: Key -> Nonce-          -> ByteString-          -- ^ Message-          -> ByteString-          -- ^ AAD-          -> ByteString-          -- ^ Ciphertext-aead (Key key) (Nonce nonce) msg aad =-  snd . buildUnsafeByteString clen $ \pc ->-    constByteStrings [key, msg, aad, nonce] $ \-      [(pk, _), (pm, _), (pa, _), (pn, _)] ->-          c_aead pc nullPtr pm (fromIntegral mlen) pa (fromIntegral alen) nullPtr pn pk-  where mlen    = S.length msg-        alen    = S.length aad-        clen    = mlen + Bytes.aead_xchacha20poly1305_ietf_ABYTES---- | Decrypts a message. Returns 'Nothing' if the keys and message do--- not match.-aeadOpen :: Key -> Nonce -         -> ByteString-         -- ^ Ciphertext-         -> ByteString-         -- ^ AAD-         -> Maybe ByteString-         -- ^ Message-aeadOpen (Key key) (Nonce nonce) cipher aad = do-  let clen   = S.length cipher-      alen   = S.length aad-  mlen <- clen `safeSubtract` Bytes.aead_xchacha20poly1305_ietf_ABYTES-  let (err, vec) = buildUnsafeByteString mlen $ \pm ->-        constByteStrings [key, cipher, aad, nonce] $ \-          [(pk, _), (pc, _), (pa, _), (pn, _)] ->-            c_aead_open pm nullPtr nullPtr pc (fromIntegral clen) pa (fromIntegral alen) pn pk-  hush . handleErrno err $ vec---- | Encrypts a message. It is infeasible for an attacker to decrypt--- the message so long as the 'Nonce' is never repeated.-aeadDetached :: Key -> Nonce-          -> ByteString-          -- ^ Message-          -> ByteString-          -- ^ AAD-          -> (ByteString,ByteString)-          -- ^ Tag, Ciphertext-aeadDetached (Key key) (Nonce nonce) msg aad =-  buildUnsafeByteString clen $ \pc ->-   fmap snd . buildUnsafeByteString' tlen $ \pt ->-    constByteStrings [key, msg, aad, nonce] $ \-      [(pk, _), (pm, _), (pa, _), (pn, _)] ->-          c_aead_detached pc pt nullPtr pm (fromIntegral mlen) pa (fromIntegral alen) nullPtr pn pk-  where mlen    = S.length msg-        alen    = S.length aad-        clen    = mlen-        tlen    = Bytes.aead_xchacha20poly1305_ietf_ABYTES---- | Decrypts a message. Returns 'Nothing' if the keys and message do--- not match.-aeadOpenDetached :: Key -> Nonce-         -> ByteString-         -- ^ Tag-         -> ByteString-         -- ^ Ciphertext-         -> ByteString-         -- ^ AAD-         -> Maybe ByteString-         -- ^ Message-aeadOpenDetached (Key key) (Nonce nonce) tag cipher aad-    | S.length tag /= tlen = Nothing-    | otherwise =-  let (err, vec) = buildUnsafeByteString len $ \pm ->-        constByteStrings [key, tag, cipher, aad, nonce] $ \-          [(pk, _), (pt, _), (pc, _), (pa, _), (pn, _)] ->-            c_aead_open_detached pm nullPtr pc (fromIntegral len) pt pa (fromIntegral alen) pn pk-  in hush . handleErrno err $ vec-  where len    = S.length cipher-        alen   = S.length aad-        tlen   = Bytes.aead_xchacha20poly1305_ietf_ABYTES---- | The aead C API uses C strings. Always returns 0.-foreign import ccall "crypto_aead_xchacha20poly1305_ietf_encrypt"-  c_aead :: Ptr CChar-              -- ^ Cipher output buffer-              -> Ptr CULLong-              -- ^ Cipher output bytes used-              -> Ptr CChar-              -- ^ Constant message input buffer-              -> CULLong-              -- ^ Length of message input buffer-              -> Ptr CChar-              -- ^ Constant aad input buffer-              -> CULLong-              -- ^ Length of aad input buffer-              -> Ptr CChar-              -- ^ Unused 'nsec' value (must be NULL)-              -> Ptr CChar-              -- ^ Constant nonce buffer-              -> Ptr CChar-              -- ^ Constant key buffer-              -> IO CInt---- | The aead open C API uses C strings. Returns 0 if successful.-foreign import ccall "crypto_aead_xchacha20poly1305_ietf_decrypt"-  c_aead_open :: Ptr CChar-              -- ^ Message output buffer-              -> Ptr CULLong-              -- ^ Message output bytes used-              -> Ptr CChar-              -- ^ Unused 'nsec' value (must be NULL)-              -> Ptr CChar-              -- ^ Constant ciphertext input buffer-              -> CULLong-              -- ^ Length of ciphertext input buffer-              -> Ptr CChar-              -- ^ Constant aad input buffer-              -> CULLong-              -- ^ Length of aad input buffer-              -> Ptr CChar-              -- ^ Constant nonce buffer-              -> Ptr CChar-              -- ^ Constant key buffer-              -> IO CInt---- | The aead C API uses C strings. Always returns 0.-foreign import ccall "crypto_aead_xchacha20poly1305_ietf_encrypt_detached"-  c_aead_detached :: Ptr CChar-              -- ^ Cipher output buffer-              -> Ptr CChar-              -- ^ Tag output buffer-              -> Ptr CULLong-              -- ^ Tag bytes used-              -> Ptr CChar-              -- ^ Constant message input buffer-              -> CULLong-              -- ^ Length of message input buffer-              -> Ptr CChar-              -- ^ Constant aad input buffer-              -> CULLong-              -- ^ Length of aad input buffer-              -> Ptr CChar-              -- ^ Unused 'nsec' value (must be NULL)-              -> Ptr CChar-              -- ^ Constant nonce buffer-              -> Ptr CChar-              -- ^ Constant key buffer-              -> IO CInt---- | The aead open C API uses C strings. Returns 0 if successful.-foreign import ccall "crypto_aead_xchacha20poly1305_ietf_decrypt_detached"-  c_aead_open_detached :: Ptr CChar-              -- ^ Message output buffer-              -> Ptr CChar-              -- ^ Unused 'nsec' value (must be NULL)-              -> Ptr CChar-              -- ^ Constant ciphertext input buffer-              -> CULLong-              -- ^ Length of ciphertext input buffer-              -> Ptr CChar-              -- ^ Constant tag input buffer-              -> Ptr CChar-              -- ^ Constant aad input buffer-              -> CULLong-              -- ^ Length of aad input buffer-              -> Ptr CChar-              -- ^ Constant nonce buffer-              -> Ptr CChar-              -- ^ Constant key buffer-              -> IO CInt+import Crypto.Saltine.Core.AEAD.XChaCha20Poly1305 as X
+ src/Crypto/Saltine/Core/AEAD/AES256GCM.hs view
@@ -0,0 +1,149 @@+-- |+-- Module      : Crypto.Saltine.Core.AEAD.AES256GCM+-- Copyright   : (c) Thomas DuBuisson 2017+--               (c) Max Amanshauser 2021+-- License     : MIT+--+-- Maintainer  : max@lambdalifting.org+-- Stability   : experimental+-- Portability : non-portable+--+-- Secret-key authenticated encryption with additional data (AEAD):+-- "Crypto.Saltine.Core.AEAD.AES256GCM"+--+-- Using this module is not recommended. Don't use unless you have to.+-- Keep in mind its limitations: https://doc.libsodium.org/secret-key_cryptography/aead+--+-- Unless you know for certain the CPU your program will run on supports+-- Intel SSSE3, AES-NI and CLMUL, you should run @aead_aes256gcm_available@+-- first and only proceed if the result is True.+--+-- Generating nonces for the functions in this module randomly+-- is not recommended, due to the risk of generating collisions.++module Crypto.Saltine.Core.AEAD.AES256GCM (+  Key, Nonce,+  aead_aes256gcm_available,+  aead, aeadOpen,+  aeadDetached, aeadOpenDetached,+  newKey, newNonce+  ) where++import Crypto.Saltine.Internal.AEAD.AES256GCM+            ( c_aead_aes256gcm_is_available+            , c_aead+            , c_aead_open+            , c_aead_detached+            , c_aead_open_detached+            , Key(..)+            , Nonce(..)+            )+import Crypto.Saltine.Internal.Util as U+import Data.ByteString              (ByteString)+import Foreign.Ptr+import System.IO.Unsafe             (unsafePerformIO)++import qualified Crypto.Saltine.Internal.AEAD.AES256GCM as Bytes+import qualified Data.ByteString                        as S++-- | Creates a random 'AES256GCM' key+newKey :: IO Key+newKey = Key <$> randomByteString Bytes.aead_aes256gcm_keybytes++-- | Creates a random 'AES256GCM' nonce+newNonce :: IO Nonce+newNonce = Nonce <$> randomByteString Bytes.aead_aes256gcm_npubbytes+++{-# NOINLINE aead_aes256gcm_available #-}+aead_aes256gcm_available :: Bool+aead_aes256gcm_available =+    unsafePerformIO c_aead_aes256gcm_is_available == 1++-- | Encrypts a message. It is infeasible for an attacker to decrypt+-- the message so long as the 'Nonce' is never repeated.+aead+    :: Key+    -> Nonce+    -> ByteString+    -- ^ Message+    -> ByteString+    -- ^ AAD+    -> ByteString+    -- ^ Ciphertext+aead (Key key) (Nonce nonce) msg aad =+  snd . buildUnsafeByteString clen $ \pc ->+    constByteStrings [key, msg, aad, nonce] $ \+      [(pk, _), (pm, _), (pa, _), (pn, _)] ->+          c_aead pc nullPtr pm (fromIntegral mlen) pa (fromIntegral alen) nullPtr pn pk+  where mlen    = S.length msg+        alen    = S.length aad+        clen    = mlen + Bytes.aead_aes256gcm_abytes++-- | Decrypts a message. Returns 'Nothing' if the keys and message do+-- not match.+aeadOpen+    :: Key+    -> Nonce+    -> ByteString+    -- ^ Ciphertext+    -> ByteString+    -- ^ AAD+    -> Maybe ByteString+    -- ^ Message+aeadOpen (Key key) (Nonce nonce) cipher aad = do+  let clen   = S.length cipher+      alen   = S.length aad+  mlen <- clen `safeSubtract` Bytes.aead_aes256gcm_abytes+  let (err, vec) = buildUnsafeByteString mlen $ \pm ->+        constByteStrings [key, cipher, aad, nonce] $ \+          [(pk, _), (pc, _), (pa, _), (pn, _)] ->+            c_aead_open pm nullPtr nullPtr pc (fromIntegral clen) pa (fromIntegral alen) pn pk+  hush . handleErrno err $ vec++-- | Encrypts a message. It is infeasible for an attacker to decrypt+-- the message so long as the 'Nonce' is never repeated.+aeadDetached+    :: Key+    -> Nonce+    -> ByteString+    -- ^ Message+    -> ByteString+    -- ^ AAD+    -> (ByteString,ByteString)+    -- ^ Tag, Ciphertext+aeadDetached (Key key) (Nonce nonce) msg aad =+  buildUnsafeByteString clen $ \pc ->+   fmap snd . buildUnsafeByteString' tlen $ \pt ->+    constByteStrings [key, msg, aad, nonce] $ \+      [(pk, _), (pm, _), (pa, _), (pn, _)] ->+          c_aead_detached pc pt nullPtr pm (fromIntegral mlen) pa (fromIntegral alen) nullPtr pn pk+  where mlen    = S.length msg+        alen    = S.length aad+        clen    = mlen+        tlen    = Bytes.aead_aes256gcm_abytes++-- | Decrypts a message. Returns 'Nothing' if the keys and message do+-- not match.+aeadOpenDetached+    :: Key+    -> Nonce+    -> ByteString+    -- ^ Tag+    -> ByteString+    -- ^ Ciphertext+    -> ByteString+    -- ^ AAD+    -> Maybe ByteString+    -- ^ Message+aeadOpenDetached (Key key) (Nonce nonce) tag cipher aad+    | S.length tag /= tlen = Nothing+    | otherwise =+  let (err, vec) = buildUnsafeByteString len $ \pm ->+        constByteStrings [key, tag, cipher, aad, nonce] $ \+          [(pk, _), (pt, _), (pc, _), (pa, _), (pn, _)] ->+            c_aead_open_detached pm nullPtr pc (fromIntegral len) pt pa (fromIntegral alen) pn pk+  in hush . handleErrno err $ vec+  where len    = S.length cipher+        alen   = S.length aad+        tlen   = Bytes.aead_aes256gcm_abytes
+ src/Crypto/Saltine/Core/AEAD/ChaCha20Poly1305.hs view
@@ -0,0 +1,134 @@+-- |+-- Module      : Crypto.Saltine.Core.AEAD.ChaCha20Poly1305+-- Copyright   : (c) Thomas DuBuisson 2017+--               (c) Max Amanshauser 2021+-- License     : MIT+--+-- Maintainer  : max@lambdalifting.org+-- Stability   : experimental+-- Portability : non-portable+--+-- Secret-key authenticated encryption with additional data (AEAD):+-- "Crypto.Saltine.Core.AEAD.ChaCha20Poly1305"+--+-- Generating nonces for the functions in this module randomly+-- is not recommended, due to the risk of generating collisions.++module Crypto.Saltine.Core.AEAD.ChaCha20Poly1305 (+  Key, Nonce,+  aead, aeadOpen,+  aeadDetached, aeadOpenDetached,+  newKey, newNonce+  ) where++import Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305+            ( c_aead+            , c_aead_open+            , c_aead_detached+            , c_aead_open_detached+            , Key(..)+            , Nonce(..)+            )+import Crypto.Saltine.Internal.Util as U+import Data.ByteString              (ByteString)+import Foreign.Ptr++import qualified Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305  as Bytes+import qualified Data.ByteString                                as S++-- | Creates a random 'ChaCha20Poly1305' key+newKey :: IO Key+newKey = Key <$> randomByteString Bytes.aead_chacha20poly1305_keybytes++-- | Creates a random 'ChaCha20Poly1305' nonce+newNonce :: IO Nonce+newNonce = Nonce <$> randomByteString Bytes.aead_chacha20poly1305_npubbytes+++-- | Encrypts a message. It is infeasible for an attacker to decrypt+-- the message so long as the 'Nonce' is never repeated.+aead+    :: Key+    -> Nonce+    -> ByteString+    -- ^ Message+    -> ByteString+    -- ^ AAD+    -> ByteString+    -- ^ Ciphertext+aead (Key key) (Nonce nonce) msg aad =+  snd . buildUnsafeByteString clen $ \pc ->+    constByteStrings [key, msg, aad, nonce] $ \+      [(pk, _), (pm, _), (pa, _), (pn, _)] ->+          c_aead pc nullPtr pm (fromIntegral mlen) pa (fromIntegral alen) nullPtr pn pk+  where mlen    = S.length msg+        alen    = S.length aad+        clen    = mlen + Bytes.aead_chacha20poly1305_abytes++-- | Decrypts a message. Returns 'Nothing' if the keys and message do+-- not match.+aeadOpen+    :: Key+    -> Nonce+    -> ByteString+    -- ^ Ciphertext+    -> ByteString+    -- ^ AAD+    -> Maybe ByteString+    -- ^ Message+aeadOpen (Key key) (Nonce nonce) cipher aad = do+  let clen   = S.length cipher+      alen   = S.length aad+  mlen <- clen `safeSubtract` Bytes.aead_chacha20poly1305_abytes+  let (err, vec) = buildUnsafeByteString mlen $ \pm ->+        constByteStrings [key, cipher, aad, nonce] $ \+          [(pk, _), (pc, _), (pa, _), (pn, _)] ->+            c_aead_open pm nullPtr nullPtr pc (fromIntegral clen) pa (fromIntegral alen) pn pk+  hush . handleErrno err $ vec++-- | Encrypts a message. It is infeasible for an attacker to decrypt+-- the message so long as the 'Nonce' is never repeated.+aeadDetached+    :: Key+    -> Nonce+    -> ByteString+    -- ^ Message+    -> ByteString+    -- ^ AAD+    -> (ByteString,ByteString)+    -- ^ Tag, Ciphertext+aeadDetached (Key key) (Nonce nonce) msg aad =+  buildUnsafeByteString clen $ \pc ->+   fmap snd . buildUnsafeByteString' tlen $ \pt ->+    constByteStrings [key, msg, aad, nonce] $ \+      [(pk, _), (pm, _), (pa, _), (pn, _)] ->+          c_aead_detached pc pt nullPtr pm (fromIntegral mlen) pa (fromIntegral alen) nullPtr pn pk+  where mlen    = S.length msg+        alen    = S.length aad+        clen    = mlen+        tlen    = Bytes.aead_chacha20poly1305_abytes++-- | Decrypts a message. Returns 'Nothing' if the keys and message do+-- not match.+aeadOpenDetached+    :: Key+    -> Nonce+    -> ByteString+    -- ^ Tag+    -> ByteString+    -- ^ Ciphertext+    -> ByteString+    -- ^ AAD+    -> Maybe ByteString+    -- ^ Message+aeadOpenDetached (Key key) (Nonce nonce) tag cipher aad+    | S.length tag /= tlen = Nothing+    | otherwise =+  let (err, vec) = buildUnsafeByteString len $ \pm ->+        constByteStrings [key, tag, cipher, aad, nonce] $ \+          [(pk, _), (pt, _), (pc, _), (pa, _), (pn, _)] ->+            c_aead_open_detached pm nullPtr pc (fromIntegral len) pt pa (fromIntegral alen) pn pk+  in hush . handleErrno err $ vec+  where len    = S.length cipher+        alen   = S.length aad+        tlen   = Bytes.aead_chacha20poly1305_abytes
+ src/Crypto/Saltine/Core/AEAD/ChaCha20Poly1305IETF.hs view
@@ -0,0 +1,134 @@+-- |+-- Module      : Crypto.Saltine.Core.AEAD.ChaCha20Poly1305IETF+-- Copyright   : (c) Thomas DuBuisson 2017+--               (c) Max Amanshauser 2021+-- License     : MIT+--+-- Maintainer  : max@lambdalifting.org+-- Stability   : experimental+-- Portability : non-portable+--+-- Secret-key authenticated encryption with additional data (AEAD):+-- "Crypto.Saltine.Core.AEAD.ChaCha20Poly1305IETF"+--+-- Generating nonces for the functions in this module randomly+-- is not recommended, due to the risk of generating collisions.++module Crypto.Saltine.Core.AEAD.ChaCha20Poly1305IETF (+  Key, Nonce,+  aead, aeadOpen,+  aeadDetached, aeadOpenDetached,+  newKey, newNonce+  ) where++import Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305IETF+        ( c_aead+        , c_aead_open+        , c_aead_detached+        , c_aead_open_detached+        , Key(..)+        , Nonce(..)+        )+import Crypto.Saltine.Internal.Util as U+import Data.ByteString              (ByteString)+import Foreign.Ptr++import qualified Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305IETF  as Bytes+import qualified Data.ByteString                                    as S++-- | Creates a random 'ChaCha20Poly1305IETF' key+newKey :: IO Key+newKey = Key <$> randomByteString Bytes.aead_chacha20poly1305_ietf_keybytes++-- | Creates a random 'ChaCha20Poly1305IETF' nonce+newNonce :: IO Nonce+newNonce = Nonce <$> randomByteString Bytes.aead_chacha20poly1305_ietf_npubbytes+++-- | Encrypts a message. It is infeasible for an attacker to decrypt+-- the message so long as the 'Nonce' is never repeated.+aead+    :: Key+    -> Nonce+    -> ByteString+    -- ^ Message+    -> ByteString+    -- ^ AAD+    -> ByteString+    -- ^ Ciphertext+aead (Key key) (Nonce nonce) msg aad =+  snd . buildUnsafeByteString clen $ \pc ->+    constByteStrings [key, msg, aad, nonce] $ \+      [(pk, _), (pm, _), (pa, _), (pn, _)] ->+          c_aead pc nullPtr pm (fromIntegral mlen) pa (fromIntegral alen) nullPtr pn pk+  where mlen    = S.length msg+        alen    = S.length aad+        clen    = mlen + Bytes.aead_chacha20poly1305_ietf_abytes++-- | Decrypts a message. Returns 'Nothing' if the keys and message do+-- not match.+aeadOpen+    :: Key+    -> Nonce+    -> ByteString+    -- ^ Ciphertext+    -> ByteString+    -- ^ AAD+    -> Maybe ByteString+    -- ^ Message+aeadOpen (Key key) (Nonce nonce) cipher aad = do+  let clen   = S.length cipher+      alen   = S.length aad+  mlen <- clen `safeSubtract` Bytes.aead_chacha20poly1305_ietf_abytes+  let (err, vec) = buildUnsafeByteString mlen $ \pm ->+        constByteStrings [key, cipher, aad, nonce] $ \+          [(pk, _), (pc, _), (pa, _), (pn, _)] ->+            c_aead_open pm nullPtr nullPtr pc (fromIntegral clen) pa (fromIntegral alen) pn pk+  hush . handleErrno err $ vec++-- | Encrypts a message. It is infeasible for an attacker to decrypt+-- the message so long as the 'Nonce' is never repeated.+aeadDetached+    :: Key+    -> Nonce+    -> ByteString+    -- ^ Message+    -> ByteString+    -- ^ AAD+    -> (ByteString,ByteString)+    -- ^ Tag, Ciphertext+aeadDetached (Key key) (Nonce nonce) msg aad =+  buildUnsafeByteString clen $ \pc ->+   fmap snd . buildUnsafeByteString' tlen $ \pt ->+    constByteStrings [key, msg, aad, nonce] $ \+      [(pk, _), (pm, _), (pa, _), (pn, _)] ->+          c_aead_detached pc pt nullPtr pm (fromIntegral mlen) pa (fromIntegral alen) nullPtr pn pk+  where mlen    = S.length msg+        alen    = S.length aad+        clen    = mlen+        tlen    = Bytes.aead_chacha20poly1305_ietf_abytes++-- | Decrypts a message. Returns 'Nothing' if the keys and message do+-- not match.+aeadOpenDetached+    :: Key+    -> Nonce+    -> ByteString+    -- ^ Tag+    -> ByteString+    -- ^ Ciphertext+    -> ByteString+    -- ^ AAD+    -> Maybe ByteString+    -- ^ Message+aeadOpenDetached (Key key) (Nonce nonce) tag cipher aad+    | S.length tag /= tlen = Nothing+    | otherwise =+  let (err, vec) = buildUnsafeByteString len $ \pm ->+        constByteStrings [key, tag, cipher, aad, nonce] $ \+          [(pk, _), (pt, _), (pc, _), (pa, _), (pn, _)] ->+            c_aead_open_detached pm nullPtr pc (fromIntegral len) pt pa (fromIntegral alen) pn pk+  in hush . handleErrno err $ vec+  where len    = S.length cipher+        alen   = S.length aad+        tlen   = Bytes.aead_chacha20poly1305_ietf_abytes
+ src/Crypto/Saltine/Core/AEAD/XChaCha20Poly1305.hs view
@@ -0,0 +1,134 @@+-- |+-- Module      : Crypto.Saltine.Core.AEAD.XChaCha20Poly1305+-- Copyright   : (c) Thomas DuBuisson 2017+-- License     : MIT+--+-- Maintainer  : max@lambdalifting.org+-- Stability   : experimental+-- Portability : non-portable+--+-- Secret-key authenticated encryption with additional data (AEAD):+-- "Crypto.Saltine.Core.AEAD.XChaCha20Poly1305"+--+-- Nonces are long enough that randomly generated+-- nonces have negligible risk of collision.++module Crypto.Saltine.Core.AEAD.XChaCha20Poly1305 (+  Key, Nonce,+  aead, aeadOpen,+  aeadDetached, aeadOpenDetached,+  newKey, newNonce+  ) where++import Crypto.Saltine.Internal.AEAD.XChaCha20Poly1305+            ( c_aead+            , c_aead_open+            , c_aead_detached+            , c_aead_open_detached+            , Key(..)+            , Nonce(..)+            )+import Crypto.Saltine.Internal.Util as U+import Data.ByteString              (ByteString)+import Foreign.Ptr++import qualified Crypto.Saltine.Internal.AEAD.XChaCha20Poly1305 as Bytes+import qualified Data.ByteString                                as S+++-- | Creates a random 'XChaCha20Poly1305' key+newKey :: IO Key+newKey = Key <$> randomByteString Bytes.aead_xchacha20poly1305_ietf_keybytes++-- | Creates a random 'XChaCha20Poly1305' nonce+newNonce :: IO Nonce+newNonce = Nonce <$> randomByteString Bytes.aead_xchacha20poly1305_ietf_npubbytes+++-- | Encrypts a message. It is infeasible for an attacker to decrypt+-- the message so long as the 'Nonce' is never repeated.+aead+    :: Key+    -> Nonce+    -> ByteString+    -- ^ Message+    -> ByteString+    -- ^ AAD+    -> ByteString+    -- ^ Ciphertext+aead (Key key) (Nonce nonce) msg aad =+  snd . buildUnsafeByteString clen $ \pc ->+    constByteStrings [key, msg, aad, nonce] $ \+      [(pk, _), (pm, _), (pa, _), (pn, _)] ->+          c_aead pc nullPtr pm (fromIntegral mlen) pa (fromIntegral alen) nullPtr pn pk+  where mlen    = S.length msg+        alen    = S.length aad+        clen    = mlen + Bytes.aead_xchacha20poly1305_ietf_abytes++-- | Decrypts a message. Returns 'Nothing' if the keys and message do+-- not match.+aeadOpen+    :: Key+    -> Nonce+    -> ByteString+    -- ^ Ciphertext+    -> ByteString+    -- ^ AAD+    -> Maybe ByteString+    -- ^ Message+aeadOpen (Key key) (Nonce nonce) cipher aad = do+  let clen   = S.length cipher+      alen   = S.length aad+  mlen <- clen `safeSubtract` Bytes.aead_xchacha20poly1305_ietf_abytes+  let (err, vec) = buildUnsafeByteString mlen $ \pm ->+        constByteStrings [key, cipher, aad, nonce] $ \+          [(pk, _), (pc, _), (pa, _), (pn, _)] ->+            c_aead_open pm nullPtr nullPtr pc (fromIntegral clen) pa (fromIntegral alen) pn pk+  hush . handleErrno err $ vec++-- | Encrypts a message. It is infeasible for an attacker to decrypt+-- the message so long as the 'Nonce' is never repeated.+aeadDetached+    :: Key+    -> Nonce+    -> ByteString+    -- ^ Message+    -> ByteString+    -- ^ AAD+    -> (ByteString,ByteString)+    -- ^ Tag, Ciphertext+aeadDetached (Key key) (Nonce nonce) msg aad =+  buildUnsafeByteString clen $ \pc ->+   fmap snd . buildUnsafeByteString' tlen $ \pt ->+    constByteStrings [key, msg, aad, nonce] $ \+      [(pk, _), (pm, _), (pa, _), (pn, _)] ->+          c_aead_detached pc pt nullPtr pm (fromIntegral mlen) pa (fromIntegral alen) nullPtr pn pk+  where mlen    = S.length msg+        alen    = S.length aad+        clen    = mlen+        tlen    = Bytes.aead_xchacha20poly1305_ietf_abytes++-- | Decrypts a message. Returns 'Nothing' if the keys and message do+-- not match.+aeadOpenDetached+    :: Key+    -> Nonce+    -> ByteString+    -- ^ Tag+    -> ByteString+    -- ^ Ciphertext+    -> ByteString+    -- ^ AAD+    -> Maybe ByteString+    -- ^ Message+aeadOpenDetached (Key key) (Nonce nonce) tag cipher aad+    | S.length tag /= tlen = Nothing+    | otherwise =+  let (err, vec) = buildUnsafeByteString len $ \pm ->+        constByteStrings [key, tag, cipher, aad, nonce] $ \+          [(pk, _), (pt, _), (pc, _), (pa, _), (pn, _)] ->+            c_aead_open_detached pm nullPtr pc (fromIntegral len) pt pa (fromIntegral alen) pn pk+  in hush . handleErrno err $ vec+  where len    = S.length cipher+        alen   = S.length aad+        tlen   = Bytes.aead_xchacha20poly1305_ietf_abytes
src/Crypto/Saltine/Core/Auth.hs view
@@ -1,5 +1,3 @@-{-# LANGUAGE DeriveDataTypeable, GeneralizedNewtypeDeriving, DeriveGeneric #-}- -- | -- Module      : Crypto.Saltine.Core.Auth -- Copyright   : (c) Joseph Abrahamson 2013@@ -13,7 +11,7 @@ -- "Crypto.Saltine.Core.Auth" -- -- The 'auth' function authenticates a message 'ByteString' using a--- secret key The function returns an authenticator. The 'verify'+-- secret key. The function returns an authenticator. The 'verify' -- function checks if it's passed a correct authenticator of a message -- under the given secret key. --@@ -45,46 +43,20 @@   auth, verify   ) where -import           Crypto.Saltine.Class-import           Crypto.Saltine.Internal.Util-import qualified Crypto.Saltine.Internal.ByteSizes as Bytes--import           Control.Applicative-import           Foreign.C-import           Foreign.Ptr-import qualified Data.ByteString                   as S-import           Data.ByteString                     (ByteString)-import           Data.Hashable (Hashable)-import           Data.Data (Data, Typeable)-import           GHC.Generics (Generic)---- $types---- | An opaque 'auth' cryptographic key.-newtype Key           = Key ByteString deriving (Eq, Ord, Hashable, Data, Typeable, Generic)---- | An opaque 'auth' authenticator.-newtype Authenticator = Au ByteString  deriving (Eq, Ord, Hashable, Data, Typeable, Generic)--instance IsEncoding Key where-  decode v = if S.length v == Bytes.authKey-           then Just (Key v)-           else Nothing-  {-# INLINE decode #-}-  encode (Key v) = v-  {-# INLINE encode #-}+import Crypto.Saltine.Internal.Auth+            ( c_auth+            , c_auth_verify+            , Key(..)+            , Authenticator(..)+            )+import Crypto.Saltine.Internal.Util as U+import Data.ByteString              (ByteString) -instance IsEncoding Authenticator where-  decode v = if S.length v == Bytes.auth-           then Just (Au v)-           else Nothing-  {-# INLINE decode #-}-  encode (Au v) = v-  {-# INLINE encode #-}+import qualified Crypto.Saltine.Internal.Auth as Bytes  -- | Creates a random key of the correct size for 'auth' and 'verify'. newKey :: IO Key-newKey = Key <$> randomByteString Bytes.authKey+newKey = Key <$> randomByteString Bytes.auth_keybytes  -- | Computes an keyed authenticator 'ByteString' from a message. It -- is infeasible to forge these authenticators without the key, even@@ -95,7 +67,7 @@      -- ^ Message      -> Authenticator auth (Key key) msg =-  Au . snd . buildUnsafeByteString Bytes.auth $ \pa ->+  Au . snd . buildUnsafeByteString Bytes.auth_bytes $ \pa ->     constByteStrings [key, msg] $ \[(pk, _), (pm, mlen)] ->     c_auth pa pm (fromIntegral mlen) pk @@ -110,29 +82,3 @@ verify (Key key) (Au a) msg =   unsafeDidSucceed $ constByteStrings [key, msg, a] $ \[(pk, _), (pm, mlen), (pa, _)] ->     return $ c_auth_verify pa pm (fromIntegral mlen) pk--foreign import ccall "crypto_auth"-  c_auth :: Ptr CChar-         -- ^ Authenticator output buffer-         -> Ptr CChar-         -- ^ Constant message buffer-         -> CULLong-         -- ^ Length of message buffer-         -> Ptr CChar-         -- ^ Constant key buffer-         -> IO CInt-         -- ^ Always 0---- | We don't even include this in the IO monad since all of the--- buffers are constant.-foreign import ccall "crypto_auth_verify"-  c_auth_verify :: Ptr CChar-                -- ^ Constant authenticator buffer-                -> Ptr CChar-                -- ^ Constant message buffer-                -> CULLong-                -- ^ Length of message buffer-                -> Ptr CChar-                -- ^ Constant key buffer-                -> CInt-                -- ^ Success if 0, failure if -1
src/Crypto/Saltine/Core/Box.hs view
@@ -1,5 +1,3 @@-{-# LANGUAGE DeriveDataTypeable, GeneralizedNewtypeDeriving, DeriveGeneric #-}- -- | -- Module      : Crypto.Saltine.Core.Box -- Copyright   : (c) Joseph Abrahamson 2013@@ -80,99 +78,52 @@ -- -- This is version 2010.08.30 of the box.html web page. module Crypto.Saltine.Core.Box (-  SecretKey, PublicKey, Keypair, CombinedKey, Nonce,+  SecretKey, PublicKey, Keypair(..), CombinedKey, Nonce,   newKeypair, beforeNM, newNonce,   box, boxOpen,   boxAfterNM, boxOpenAfterNM,   boxSeal, boxSealOpen   ) where -import           Crypto.Saltine.Class-import           Crypto.Saltine.Internal.Util-import qualified Crypto.Saltine.Internal.ByteSizes as Bytes--import           Control.Applicative-import           Foreign.C-import           Foreign.Ptr-import qualified Data.ByteString                   as S-import           Data.ByteString (ByteString)-import           Data.Hashable (Hashable)-import           Data.Data (Data, Typeable)-import           GHC.Generics (Generic)----- $types---- | An opaque 'box' cryptographic secret key.-newtype SecretKey = SK ByteString deriving (Eq, Ord, Hashable, Data, Typeable, Generic)--instance IsEncoding SecretKey where-  decode v = if S.length v == Bytes.boxSK-           then Just (SK v)-           else Nothing-  {-# INLINE decode #-}-  encode (SK v) = v-  {-# INLINE encode #-}---- | An opaque 'box' cryptographic public key.-newtype PublicKey = PK ByteString deriving (Eq, Ord, Hashable, Data, Typeable, Generic)--instance IsEncoding PublicKey where-  decode v = if S.length v == Bytes.boxPK-           then Just (PK v)-           else Nothing-  {-# INLINE decode #-}-  encode (PK v) = v-  {-# INLINE encode #-}---- | A convenience type for keypairs-type Keypair = (SecretKey, PublicKey)---- | An opaque 'boxAfterNM' cryptographic combined key.-newtype CombinedKey = CK ByteString deriving (Eq, Ord, Hashable, Data, Typeable, Generic)--instance IsEncoding CombinedKey where-  decode v = if S.length v == Bytes.boxBeforeNM-           then Just (CK v)-           else Nothing-  {-# INLINE decode #-}-  encode (CK v) = v-  {-# INLINE encode #-}---- | An opaque 'box' nonce.-newtype Nonce = Nonce ByteString deriving (Eq, Ord, Hashable, Data, Typeable, Generic)--instance IsEncoding Nonce where-  decode v = if S.length v == Bytes.boxNonce-           then Just (Nonce v)-           else Nothing-  {-# INLINE decode #-}-  encode (Nonce v) = v-  {-# INLINE encode #-}+import Crypto.Saltine.Internal.Box+            ( c_box_keypair+            , c_box_easy+            , c_box_open_easy+            , c_box_beforenm+            , c_box_easy_afternm+            , c_box_open_easy_afternm+            , c_box_seal, c_box_seal_open+            , SecretKey(..)+            , PublicKey(..)+            , Keypair(..)+            , CombinedKey(..)+            , Nonce(..)+            )+import Crypto.Saltine.Internal.Util as U+import Data.ByteString              (ByteString) -instance IsNonce Nonce where-  zero            = Nonce (S.replicate Bytes.boxNonce 0)-  nudge (Nonce n) = Nonce (nudgeBS n)+import qualified Crypto.Saltine.Internal.Box as Bytes+import qualified Data.ByteString             as S  -- | Randomly generates a secret key and a corresponding public key. newKeypair :: IO Keypair newKeypair = do   -- This is a little bizarre and a likely source of errors.   -- _err ought to always be 0.-  ((_err, sk), pk) <- buildUnsafeByteString' Bytes.boxPK $ \pkbuf ->-    buildUnsafeByteString' Bytes.boxSK $ \skbuf ->+  ((_err, sk), pk) <- buildUnsafeByteString' Bytes.box_publickeybytes $ \pkbuf ->+    buildUnsafeByteString' Bytes.box_secretkeybytes $ \skbuf ->       c_box_keypair pkbuf skbuf-  return (SK sk, PK pk)+  return $ Keypair (SK sk) (PK pk)  -- | Randomly generates a nonce for usage with 'box' and 'boxOpen'. newNonce :: IO Nonce-newNonce = Nonce <$> randomByteString Bytes.boxNonce+newNonce = Nonce <$> randomByteString Bytes.box_noncebytes  -- | Build a 'CombinedKey' for sending from 'SecretKey' to -- 'PublicKey'. This is a precomputation step which can accelerate -- later encryption calls. beforeNM :: SecretKey -> PublicKey -> CombinedKey-beforeNM (SK sk) (PK pk) = CK $ snd $ buildUnsafeByteString Bytes.boxBeforeNM $ \ckbuf ->+beforeNM (SK sk) (PK pk) = CK $ snd $ buildUnsafeByteString Bytes.box_beforenmbytes $ \ckbuf ->   constByteStrings [pk, sk] $ \[(ppk, _), (psk, _)] ->     c_box_beforenm ckbuf ppk psk @@ -193,7 +144,7 @@       [(ppk, _), (psk, _), (pm, _), (pn, _)] ->         c_box_easy pc pm (fromIntegral msgLen) pn ppk psk   where-    bufSize = S.length msg + Bytes.boxMac+    bufSize = S.length msg + Bytes.box_macbytes     msgLen  = S.length msg  -- | Decrypts a message sent from the owner of the public key. They@@ -206,14 +157,13 @@         -- ^ Message boxOpen (PK pk) (SK sk) (Nonce nonce) cipher = do   let msgLen = S.length cipher-  bufSize <- msgLen `safeSubtract` Bytes.boxMac+  bufSize <- msgLen `safeSubtract` Bytes.box_macbytes   let (err, vec) = buildUnsafeByteString bufSize $ \pm ->         constByteStrings [pk, sk, cipher, nonce] $ \           [(ppk, _), (psk, _), (pc, _), (pn, _)] ->             c_box_open_easy pm pc (fromIntegral msgLen) pn ppk psk   hush . handleErrno err $ vec -      -- | 'box' using a 'CombinedKey' and thus faster. boxAfterNM :: CombinedKey@@ -228,7 +178,7 @@       [(pck, _), (pm, _), (pn, _)] ->         c_box_easy_afternm pc pm (fromIntegral msgLen) pn pck   where-    bufSize = S.length msg + Bytes.boxMac+    bufSize = S.length msg + Bytes.box_macbytes     msgLen  = S.length msg  -- | 'boxOpen' using a 'CombinedKey' and is thus faster.@@ -240,25 +190,25 @@                -- ^ Message boxOpenAfterNM (CK ck) (Nonce nonce) cipher = do   let msgLen = S.length cipher-  bufSize <- msgLen `safeSubtract` Bytes.boxMac+  bufSize <- msgLen `safeSubtract` Bytes.box_macbytes   let (err, vec) = buildUnsafeByteString bufSize $ \pm ->         constByteStrings [ck, cipher, nonce] $ \           [(pck, _), (pc, _), (pn, _)] ->             c_box_open_easy_afternm pm pc (fromIntegral msgLen) pn pck   hush . handleErrno err $ vec -     - -- | Encrypts a message for sending to the owner of the public -- key. The message is unauthenticated, but permits integrity checking.+-- This function is non-deterministic, it uses newly created ephemeral keys internally,+-- and thus in IO. boxSeal :: PublicKey -> ByteString -> IO ByteString boxSeal (PK pk) msg = fmap snd . buildUnsafeByteString' bufSize $ \pc ->     constByteStrings [pk, msg] $ \       [(ppk, _), (pm, _)] ->         c_box_seal pc pm (fromIntegral msgLen) ppk   where-    bufSize = S.length msg + Bytes.sealedBox+    bufSize = S.length msg + Bytes.box_sealbytes     msgLen  = S.length msg  -- | Decrypts a sealed box message. The message must have been@@ -273,122 +223,9 @@             -- ^ Message boxSealOpen (PK pk) (SK sk) cipher = do   let msgLen = S.length cipher-  bufSize <- msgLen `safeSubtract` Bytes.sealedBox+  bufSize <- msgLen `safeSubtract` Bytes.box_sealbytes   let (err, vec) = buildUnsafeByteString bufSize $ \pm ->         constByteStrings [pk, sk, cipher] $ \           [(ppk, _), (psk, _), (pc, _)] ->           c_box_seal_open pm pc (fromIntegral msgLen) ppk psk   hush . handleErrno err $ vec---- | Should always return a 0.-foreign import ccall "crypto_box_keypair"-  c_box_keypair :: Ptr CChar-                -- ^ Public key-                -> Ptr CChar-                -- ^ Secret key-                -> IO CInt-                -- ^ Always 0---- | The secretbox C API uses C strings.-foreign import ccall "crypto_box_easy"-  c_box_easy :: Ptr CChar-             -- ^ Cipher output buffer-             -> Ptr CChar-             -- ^ Constant message input buffer-             -> CULLong-             -- ^ Length of message input buffer-             -> Ptr CChar-             -- ^ Constant nonce buffer-             -> Ptr CChar-             -- ^ Constant public key buffer-             -> Ptr CChar-             -- ^ Constant secret key buffer-             -> IO CInt-             -- ^ Always 0---- | The secretbox C API uses C strings.-foreign import ccall "crypto_box_open_easy"-  c_box_open_easy :: Ptr CChar-                  -- ^ Message output buffer-                  -> Ptr CChar-                  -- ^ Constant ciphertext input buffer-                  -> CULLong-                  -- ^ Length of message input buffer-                  -> Ptr CChar-                  -- ^ Constant nonce buffer-                  -> Ptr CChar-                  -- ^ Constant public key buffer-                  -> Ptr CChar-                  -- ^ Constant secret key buffer-                  -> IO CInt-                  -- ^ 0 for success, -1 for failure to verify---- | Single target key precompilation.-foreign import ccall "crypto_box_beforenm"-  c_box_beforenm :: Ptr CChar-                 -- ^ Combined key output buffer-                 -> Ptr CChar-                 -- ^ Constant public key buffer-                 -> Ptr CChar-                 -- ^ Constant secret key buffer-                 -> IO CInt-                 -- ^ Always 0---- | Precompiled key crypto box. Uses C strings.-foreign import ccall "crypto_box_easy_afternm"-  c_box_easy_afternm :: Ptr CChar-                     -- ^ Cipher output buffer-                     -> Ptr CChar-                     -- ^ Constant message input buffer-                     -> CULLong-                     -- ^ Length of message input buffer (incl. 0s)-                     -> Ptr CChar-                     -- ^ Constant nonce buffer-                     -> Ptr CChar-                     -- ^ Constant combined key buffer-                     -> IO CInt-                     -- ^ Always 0---- | The secretbox C API uses C strings.-foreign import ccall "crypto_box_open_easy_afternm"-  c_box_open_easy_afternm :: Ptr CChar-                          -- ^ Message output buffer-                          -> Ptr CChar-                          -- ^ Constant ciphertext input buffer-                          -> CULLong-                          -- ^ Length of message input buffer (incl. 0s)-                          -> Ptr CChar-                          -- ^ Constant nonce buffer-                          -> Ptr CChar-                          -- ^ Constant combined key buffer-                          -> IO CInt-                          -- ^ 0 for success, -1 for failure to verify----- | The sealedbox C API uses C strings.-foreign import ccall "crypto_box_seal"-  c_box_seal :: Ptr CChar-             -- ^ Cipher output buffer-             -> Ptr CChar-             -- ^ Constant message input buffer-             -> CULLong-             -- ^ Length of message input buffer-             -> Ptr CChar-             -- ^ Constant public key buffer-             -> IO CInt-             -- ^ Always 0---- | The sealedbox C API uses C strings.-foreign import ccall "crypto_box_seal_open"-  c_box_seal_open :: Ptr CChar-                  -- ^ Message output buffer-                  -> Ptr CChar-                  -- ^ Constant ciphertext input buffer-                  -> CULLong-                  -- ^ Length of message input buffer-                  -> Ptr CChar-                  -- ^ Constant public key buffer-                  -> Ptr CChar-                  -- ^ Constant secret key buffer-                  -> IO CInt-                  -- ^ 0 for success, -1 for failure to decrypt
src/Crypto/Saltine/Core/Hash.hs view
@@ -1,5 +1,3 @@-{-# LANGUAGE DeriveDataTypeable, GeneralizedNewtypeDeriving, DeriveGeneric #-}-  -- | -- Module      : Crypto.Saltine.Core.Hash -- Copyright   : (c) Joseph Abrahamson 2013@@ -52,18 +50,19 @@   generichashOutLen, generichash   ) where -import           Crypto.Saltine.Class-import           Crypto.Saltine.Internal.Util-import qualified Crypto.Saltine.Internal.ByteSizes as Bytes+import Crypto.Saltine.Internal.Hash+            ( c_hash+            , c_generichash+            , shorthash+            , ShorthashKey(..)+            , GenerichashKey(..)+            , GenerichashOutLen(..)+            )+import Crypto.Saltine.Internal.Util as U+import Data.ByteString              (ByteString) -import           Control.Applicative-import           Foreign.C-import           Foreign.Ptr-import qualified Data.ByteString as S-import           Data.ByteString (ByteString)-import           Data.Hashable (Hashable)-import           Data.Data (Data, Typeable)-import           GHC.Generics (Generic)+import qualified Crypto.Saltine.Internal.Hash as Bytes+import qualified Data.ByteString              as S  -- | Computes a cryptographically collision-resistant hash making -- @hash m == hash m' ==> m == m'@ highly likely even when under@@ -72,56 +71,22 @@      -- ^ Message      -> ByteString      -- ^ Hash-hash m = snd . buildUnsafeByteString Bytes.hash $ \ph ->+hash m = snd . buildUnsafeByteString Bytes.hash_bytes $ \ph ->   constByteStrings [m] $ \[(pm, _)] -> c_hash ph pm (fromIntegral $ S.length m) --- | An opaque 'shorthash' cryptographic secret key.-newtype ShorthashKey = ShK ByteString deriving (Eq, Ord, Hashable, Data, Typeable, Generic)--instance IsEncoding ShorthashKey where-  decode v = if S.length v == Bytes.shorthashKey-           then Just (ShK v)-           else Nothing-  {-# INLINE decode #-}-  encode (ShK v) = v-  {-# INLINE encode #-}- -- | Randomly generates a new key for 'shorthash'. newShorthashKey :: IO ShorthashKey-newShorthashKey = ShK <$> randomByteString Bytes.shorthashKey---- | Computes a very short, fast keyed hash.-shorthash :: ShorthashKey-          -> ByteString-          -- ^ Message-          -> ByteString-          -- ^ Hash-shorthash (ShK k) m = snd . buildUnsafeByteString Bytes.shorthash $ \ph ->-  constByteStrings [k, m] $ \[(pk, _), (pm, _)] ->-    c_shorthash ph pm (fromIntegral $ S.length m) pk---- | An opaque 'generichash' cryptographic secret key.-newtype GenerichashKey = GhK ByteString deriving (Eq, Ord, Hashable, Data, Typeable, Generic)--instance IsEncoding GenerichashKey where-  decode v = if S.length v <= Bytes.generichashKeyLenMax-             then Just (GhK v)-             else Nothing-  {-# INLINE decode #-}-  encode (GhK v) = v-  {-# INLINE encode #-}+newShorthashKey = ShK <$> randomByteString Bytes.shorthash_keybytes  -- | Randomly generates a new key for 'generichash' of the given length. newGenerichashKey :: Int -> IO (Maybe GenerichashKey)-newGenerichashKey n = if n >= 0 && n <= Bytes.generichashKeyLenMax+newGenerichashKey n = if n >= 0 && n <= Bytes.generichash_keybytes_max                       then Just . GhK <$> randomByteString n                       else return Nothing -newtype GenerichashOutLen = GhOL Int deriving (Eq, Ord, Hashable, Data, Typeable, Generic)- -- | Create a validated Generichash output length generichashOutLen :: Int -> Maybe GenerichashOutLen-generichashOutLen n = if n > 0 && n <= Bytes.generichashOutLenMax+generichashOutLen n = if n > 0 && n <= Bytes.generichash_bytes_max                       then Just $ GhOL $ fromIntegral n                       else Nothing @@ -136,41 +101,3 @@ generichash (GhK k) m (GhOL outLen) = snd . buildUnsafeByteString outLen $ \ph ->   constByteStrings [k, m] $ \[(pk, _), (pm, _)] ->     c_generichash ph (fromIntegral outLen) pm (fromIntegral $ S.length m) pk (fromIntegral $ S.length k)--foreign import ccall "crypto_hash"-  c_hash :: Ptr CChar-         -- ^ Output hash buffer-         -> Ptr CChar-         -- ^ Constant message buffer-         -> CULLong-         -- ^ Constant message buffer length-         -> IO CInt-         -- ^ Always 0--foreign import ccall "crypto_shorthash"-  c_shorthash :: Ptr CChar-              -- ^ Output hash buffer-              -> Ptr CChar-              -- ^ Constant message buffer-              -> CULLong-              -- ^ Message buffer length-              -> Ptr CChar-              -- ^ Constant Key buffer-              -> IO CInt-              -- ^ Always 0--foreign import ccall "crypto_generichash"-  c_generichash :: Ptr CChar-                -- ^ Output hash buffer-                -> CULLong-                -- ^ Output hash length-                -> Ptr CChar-                -- ^ Constant message buffer-                -> CULLong-                -- ^ Message buffer length-                -> Ptr CChar-                -- ^ Constant Key buffer-                -> CULLong-                -- ^ Key buffer length-                -> IO CInt-                -- ^ Always 0
src/Crypto/Saltine/Core/OneTimeAuth.hs view
@@ -1,5 +1,3 @@-{-# LANGUAGE DeriveDataTypeable, GeneralizedNewtypeDeriving, DeriveGeneric #-}- -- | -- Module      : Crypto.Saltine.Core.OneTimeAuth -- Copyright   : (c) Joseph Abrahamson 2013@@ -41,46 +39,21 @@   auth, verify   ) where -import           Crypto.Saltine.Class-import           Crypto.Saltine.Internal.Util-import qualified Crypto.Saltine.Internal.ByteSizes as Bytes+import Crypto.Saltine.Internal.OneTimeAuth+            ( c_onetimeauth+            , c_onetimeauth_verify+            , Key(..)+            , Authenticator(..)+            )+import Crypto.Saltine.Internal.Util as U+import Data.ByteString              (ByteString) -import           Control.Applicative-import           Foreign.C-import           Foreign.Ptr+import qualified Crypto.Saltine.Internal.OneTimeAuth as Bytes import qualified Data.ByteString                   as S-import           Data.ByteString                     (ByteString)-import           Data.Hashable (Hashable)-import           Data.Data (Data, Typeable)-import           GHC.Generics (Generic) --- $types---- | An opaque 'auth' cryptographic key.-newtype Key           = Key ByteString deriving (Eq, Ord, Hashable, Data, Typeable, Generic)---- | An opaque 'auth' authenticator.-newtype Authenticator = Au ByteString  deriving (Eq, Ord, Hashable, Data, Typeable, Generic)--instance IsEncoding Key where-  decode v = if S.length v == Bytes.onetimeKey-           then Just (Key v)-           else Nothing-  {-# INLINE decode #-}-  encode (Key v) = v-  {-# INLINE encode #-}--instance IsEncoding Authenticator where-  decode v = if S.length v == Bytes.onetime-           then Just (Au v)-           else Nothing-  {-# INLINE decode #-}-  encode (Au v) = v-  {-# INLINE encode #-}- -- | Creates a random key of the correct size for 'auth' and 'verify'. newKey :: IO Key-newKey = Key <$> randomByteString Bytes.onetimeKey+newKey = Key <$> randomByteString Bytes.onetimeauth_keybytes  -- | Builds a keyed 'Authenticator' for a message. This -- 'Authenticator' is /impossible/ to forge so long as the 'Key' is@@ -90,7 +63,7 @@      -- ^ Message      -> Authenticator auth (Key key) msg =-  Au . snd . buildUnsafeByteString Bytes.onetime $ \pa ->+  Au . snd . buildUnsafeByteString Bytes.onetimeauth_bytes $ \pa ->     constByteStrings [key, msg] $ \[(pk, _), (pm, _)] ->       c_onetimeauth pa pm (fromIntegral $ S.length msg) pk @@ -105,29 +78,3 @@   unsafeDidSucceed $ constByteStrings [key, msg, a] $ \     [(pk, _), (pm, _), (pa, _)] ->       return $ c_onetimeauth_verify pa pm (fromIntegral $ S.length msg) pk--foreign import ccall "crypto_onetimeauth"-  c_onetimeauth :: Ptr CChar-                -- ^ Authenticator output buffer-                -> Ptr CChar-                -- ^ Constant message buffer-                -> CULLong-                -- ^ Length of message buffer-                -> Ptr CChar-                -- ^ Constant key buffer-                -> IO CInt-                -- ^ Always 0---- | We don't even include this in the IO monad since all of the--- buffers are constant.-foreign import ccall "crypto_onetimeauth_verify"-  c_onetimeauth_verify :: Ptr CChar-                       -- ^ Constant authenticator buffer-                       -> Ptr CChar-                       -- ^ Constant message buffer-                       -> CULLong-                       -- ^ Length of message buffer-                       -> Ptr CChar-                       -- ^ Constant key buffer-                       -> CInt-                       -- ^ Success if 0, failure if -1
+ src/Crypto/Saltine/Core/Password.hs view
@@ -0,0 +1,247 @@+-- |+-- Module      : Crypto.Saltine.Core.Password+-- Description : Argon2 password hash+-- Copyright   : (c) Promethea Raschke 2018+--                   Max Amanshauser 2021+-- License     : MIT+-- Maintainer  : max@lambdalifting.org+-- Stability   : experimental+-- Portability : non-portable+--+-- Password hashing and key derivation+--+-- When in doubt, just use one of [ interactivePolicy, moderatePolicy, sensitivePolicy ],+-- but this module also allows you to fine-tune parameters for specific circumstances.+--+-- This module uses the @Text@ type for passwords, because this seems to be the only+-- reasonable way to get consistent encodings across locales and architectures, short of+-- letting users mess around with ByteStrings themselves.++module Crypto.Saltine.Core.Password+  ( Salt+  , newSalt++  , needsRehash++  , pwhashStr+  , pwhashStrVerify+  , pwhash++  , Policy(..)+  , interactivePolicy+  , moderatePolicy+  , sensitivePolicy++  , Opslimit+  , opslimit+  , getOpslimit++  , minOpslimit+  , maxOpslimit++  , opslimitInteractive+  , opslimitModerate+  , opslimitSensitive++  , Memlimit+  , memlimit+  , getMemlimit++  , minMemlimit+  , maxMemlimit++  , memlimitInteractive+  , memlimitModerate+  , memlimitSensitive++  , Algorithm+  , defaultAlgorithm+  ) where++import Crypto.Saltine.Internal.Util+import Crypto.Saltine.Internal.Password as I+import Data.ByteString (ByteString)+import Data.Text       (Text)+import Foreign.C+import System.IO.Unsafe++import qualified Crypto.Saltine.Internal.Password as Bytes+import qualified Data.Text as T+import qualified Data.Text.Encoding as TE+++newSalt :: IO Salt+newSalt = Salt <$> randomByteString Bytes.pwhash_saltbytes++-- | Hashes a password according to the policy+-- This function is non-deterministic and hence in IO.+-- Since this function may cause a huge amount of memory to be allocated, it will return+-- Nothing if the allocation failed and on any other error.+pwhashStr :: Text -> Policy -> IO (Maybe PasswordHash)+pwhashStr pw policy = do+  let (ops, mem, _alg) = unpackPolicy policy++  -- Hash is always ASCII, so no decoding needed+  fmap (fmap (PasswordHash . T.pack)) $ allocaBytes pwhash_strbytes $ \pp ->+    constByteStrings [TE.encodeUtf8 pw] $ \ [(ppw, ppwlen)] -> do+          ret <- c_pwhash_str pp ppw (fromIntegral ppwlen) (fromIntegral ops) (fromIntegral mem)++          case ret of+              0 -> Just <$> peekCAString pp+              _ -> pure Nothing++-- | Verifies that a certain password hash was constructed from the supplied password+pwhashStrVerify :: PasswordHash -> Text -> Bool+pwhashStrVerify (PasswordHash h) pw = unsafePerformIO $+  constByteStrings [TE.encodeUtf8 $ T.snoc h '\NUL', TE.encodeUtf8 pw] $ \[(ph, _), (ppw, ppwlen)] -> do+    res <- c_pwhash_str_verify ph ppw (fromIntegral ppwlen)+    pure (res == 0)++-- | Indicates whether a password needs to be rehashed, because the opslimit/memlimit parameters+-- used to hash the password are inconsistent with the supplied values.+-- Returns Nothing if the hash appears to be invalid.+-- Internally this function will always use the current DefaultAlgorithm and hence will give+-- undefined results if a different algorithm was used to hash the password.+needsRehash :: Opslimit -> Memlimit -> PasswordHash -> Maybe Bool+needsRehash (Opslimit ops) (Memlimit mem) (PasswordHash h) =+    unsafePerformIO $+        constByteStrings [TE.encodeUtf8 $ T.snoc h '\NUL'] $ \[(ph,_)] -> do+            res <- c_pwhash_str_needs_rehash ph (fromIntegral ops) (fromIntegral mem)+            pure $  if res == -1+                    then Nothing+                    else Just (res == 1)++-- | Derives a key of the specified length from a password using a salt according to the provided policy.+-- Since this function may cause a huge amount of memory to be allocated, it will return+-- Nothing if the allocation failed and on any other error.+pwhash :: Text -> Int -> Salt -> Policy -> Maybe ByteString+pwhash pw len (Salt salt) policy = do+  let (ops, mem, alg) = unpackPolicy policy++  let (e, hashed) =+        buildUnsafeByteString len $ \hbuf ->+          constByteStrings [TE.encodeUtf8 pw, salt] $ \[(ppw,ppwlen), (psalt,_)] ->+              c_pwhash+                    hbuf (fromIntegral len)+                    ppw (fromIntegral ppwlen)+                    psalt+                    (fromIntegral ops)+                    (fromIntegral mem)+                    (fromIntegral $ fromEnum alg)++  if e == -1+  then Nothing+  else Just hashed+++-- | Smart constructor for opslimit+opslimit :: Algorithm -> Int -> Maybe Opslimit+opslimit alg x+  | Opslimit x < minOpslimit alg = Nothing+  | Opslimit x > maxOpslimit alg = Nothing+  | otherwise = Just (Opslimit x)++opslimitInteractive :: Algorithm -> Opslimit+opslimitInteractive DefaultAlgorithm = Opslimit (fromIntegral Bytes.pwhash_opslimit_interactive)+opslimitInteractive Argon2i13        = Opslimit (fromIntegral Bytes.pwhash_argon2i_opslimit_interactive)+opslimitInteractive Argon2id13       = Opslimit (fromIntegral Bytes.pwhash_argon2id_opslimit_interactive)++opslimitModerate :: Algorithm -> Opslimit+opslimitModerate DefaultAlgorithm   = Opslimit (fromIntegral Bytes.pwhash_opslimit_moderate)+opslimitModerate Argon2i13          = Opslimit (fromIntegral Bytes.pwhash_argon2i_opslimit_moderate)+opslimitModerate Argon2id13         = Opslimit (fromIntegral Bytes.pwhash_argon2id_opslimit_moderate)++opslimitSensitive :: Algorithm -> Opslimit+opslimitSensitive DefaultAlgorithm  = Opslimit (fromIntegral Bytes.pwhash_opslimit_sensitive)+opslimitSensitive Argon2i13         = Opslimit (fromIntegral Bytes.pwhash_argon2i_opslimit_sensitive)+opslimitSensitive Argon2id13        = Opslimit (fromIntegral Bytes.pwhash_argon2id_opslimit_sensitive)+++-- | Smart constructor for memlimit+memlimit :: Algorithm -> Int -> Maybe Memlimit+memlimit alg x+  | Memlimit x < minMemlimit alg  = Nothing+  | Memlimit x > maxMemlimit alg= Nothing+  | otherwise = Just (Memlimit x)++memlimitInteractive :: Algorithm -> Memlimit+memlimitInteractive DefaultAlgorithm = Memlimit (fromIntegral Bytes.pwhash_memlimit_interactive)+memlimitInteractive Argon2i13        = Memlimit (fromIntegral Bytes.pwhash_argon2i_memlimit_interactive)+memlimitInteractive Argon2id13       = Memlimit (fromIntegral Bytes.pwhash_argon2id_memlimit_interactive)++memlimitModerate :: Algorithm -> Memlimit+memlimitModerate DefaultAlgorithm   = Memlimit (fromIntegral Bytes.pwhash_memlimit_moderate)+memlimitModerate Argon2i13          = Memlimit (fromIntegral Bytes.pwhash_argon2i_memlimit_moderate)+memlimitModerate Argon2id13         = Memlimit (fromIntegral Bytes.pwhash_argon2id_memlimit_moderate)++memlimitSensitive :: Algorithm -> Memlimit+memlimitSensitive DefaultAlgorithm  = Memlimit (fromIntegral Bytes.pwhash_memlimit_sensitive)+memlimitSensitive Argon2i13         = Memlimit (fromIntegral Bytes.pwhash_argon2i_memlimit_sensitive)+memlimitSensitive Argon2id13        = Memlimit (fromIntegral Bytes.pwhash_argon2id_memlimit_sensitive)++defaultAlgorithm :: Algorithm+defaultAlgorithm = DefaultAlgorithm+++-- | Get raw C types from a policy, suitable for passing to FFI functions+unpackPolicy :: Policy -> (CULLong, CSize, CInt)+unpackPolicy (Policy ops mem alg) =+  ( fromIntegral (getOpslimit ops)+  , fromIntegral (getMemlimit mem)+  , algorithm alg+  )+++{-+Fast policy suitable for low-powered devices++Takes approximately 0.1 seconds on a typical desktop computer+and requires 64 MiB of dedicated RAM+-}+interactivePolicy :: Policy+interactivePolicy = Policy (opslimitInteractive defaultAlgorithm)+                           (memlimitInteractive defaultAlgorithm)+                           defaultAlgorithm++{-|+Moderate policy with a balance of speed and security++Takes approximately 1 second on a typical desktop computer+and requires 256 MiB of dedicated RAM+-}+moderatePolicy :: Policy+moderatePolicy = Policy (opslimitModerate defaultAlgorithm)+                        (memlimitModerate defaultAlgorithm)+                        defaultAlgorithm++{-|+High-security policy designed to make attacking the password extremely expensive++Takes several seconds on a typical desktop computer+and requires 1024 MiB of dedicated RAM+-}+sensitivePolicy :: Policy+sensitivePolicy = Policy (opslimitSensitive defaultAlgorithm)+                         (memlimitSensitive defaultAlgorithm)+                         defaultAlgorithm+++minOpslimit :: Algorithm -> Opslimit+minOpslimit DefaultAlgorithm = Opslimit $ fromIntegral Bytes.pwhash_opslimit_min+minOpslimit Argon2i13        = Opslimit $ fromIntegral Bytes.pwhash_argon2i_opslimit_min+minOpslimit Argon2id13       = Opslimit $ fromIntegral Bytes.pwhash_argon2id_opslimit_min++maxOpslimit :: Algorithm -> Opslimit+maxOpslimit DefaultAlgorithm = Opslimit $ fromIntegral Bytes.pwhash_opslimit_max+maxOpslimit Argon2i13        = Opslimit $ fromIntegral Bytes.pwhash_argon2i_opslimit_max+maxOpslimit Argon2id13       = Opslimit $ fromIntegral Bytes.pwhash_argon2id_opslimit_max++minMemlimit :: Algorithm -> Memlimit+minMemlimit DefaultAlgorithm = Memlimit $ fromIntegral Bytes.pwhash_memlimit_min+minMemlimit Argon2i13        = Memlimit $ fromIntegral Bytes.pwhash_argon2i_memlimit_min+minMemlimit Argon2id13       = Memlimit $ fromIntegral Bytes.pwhash_argon2id_memlimit_min++maxMemlimit :: Algorithm -> Memlimit+maxMemlimit DefaultAlgorithm = Memlimit $ fromIntegral Bytes.pwhash_memlimit_max+maxMemlimit Argon2i13        = Memlimit $ fromIntegral Bytes.pwhash_argon2i_memlimit_max+maxMemlimit Argon2id13       = Memlimit $ fromIntegral Bytes.pwhash_argon2id_memlimit_max
src/Crypto/Saltine/Core/ScalarMult.hs view
@@ -57,66 +57,23 @@   mult, multBase   ) where -import           Crypto.Saltine.Class-import           Crypto.Saltine.Internal.Util-import qualified Crypto.Saltine.Internal.ByteSizes as Bytes+import Crypto.Saltine.Internal.Util+import Crypto.Saltine.Internal.ScalarMult+            ( c_scalarmult+            , c_scalarmult_base+            , GroupElement(..)+            , Scalar(..)+            ) -import           Foreign.C-import           Foreign.Ptr-import qualified Data.ByteString                   as S-import           Data.ByteString                     (ByteString)-import           Data.Hashable (Hashable)-import           Data.Data (Data, Typeable)-import           GHC.Generics (Generic)+import qualified Crypto.Saltine.Internal.ScalarMult as Bytes --- $types --- | A group element.-newtype GroupElement = GE ByteString deriving (Eq, Ord, Hashable, Data, Typeable, Generic)---- | A scalar integer.-newtype Scalar       = Sc ByteString deriving (Eq, Ord, Hashable, Data, Typeable, Generic)--instance IsEncoding GroupElement where-  decode v = if S.length v == Bytes.mult-           then Just (GE v)-           else Nothing-  {-# INLINE decode #-}-  encode (GE v) = v-  {-# INLINE encode #-}--instance IsEncoding Scalar where-  decode v = if S.length v == Bytes.multScalar-           then Just (Sc v)-           else Nothing-  {-# INLINE decode #-}-  encode (Sc v) = v-  {-# INLINE encode #-}- mult :: Scalar -> GroupElement -> GroupElement-mult (Sc n) (GE p) = GE . snd . buildUnsafeByteString Bytes.mult $ \pq ->+mult (Sc n) (GE p) = GE . snd . buildUnsafeByteString Bytes.scalarmult_bytes $ \pq ->   constByteStrings [n, p] $ \[(pn, _), (pp, _)] ->     c_scalarmult pq pn pp  multBase :: Scalar -> GroupElement-multBase (Sc n) = GE . snd . buildUnsafeByteString Bytes.mult $ \pq ->+multBase (Sc n) = GE . snd . buildUnsafeByteString Bytes.scalarmult_bytes $ \pq ->   constByteStrings [n] $ \[(pn, _)] ->     c_scalarmult_base pq pn--foreign import ccall "crypto_scalarmult"-  c_scalarmult :: Ptr CChar-               -- ^ Output group element buffer-               -> Ptr CChar-               -- ^ Input integer buffer-               -> Ptr CChar-               -- ^ Input group element buffer-               -> IO CInt-               -- ^ Always 0--foreign import ccall "crypto_scalarmult_base"-  c_scalarmult_base :: Ptr CChar-                    -- ^ Output group element buffer-                    -> Ptr CChar-                    -- ^ Input integer buffer-                    -> IO CInt-                    -- ^ Always 0
src/Crypto/Saltine/Core/SecretBox.hs view
@@ -1,11 +1,9 @@-{-# LANGUAGE DeriveDataTypeable, GeneralizedNewtypeDeriving, DeriveGeneric #-}- -- | -- Module      : Crypto.Saltine.Core.SecretBox -- Copyright   : (c) Joseph Abrahamson 2013 -- License     : MIT ----- Maintainer  : me@jspha.com+-- Maintainer  : max@lambdalifting.org -- Stability   : experimental -- Portability : non-portable --@@ -40,123 +38,105 @@ -- -- This is version 2010.08.30 of the secretbox.html web page. module Crypto.Saltine.Core.SecretBox (-  Key, Nonce,+  Key, Nonce, Authenticator,   secretbox, secretboxOpen,   secretboxDetached, secretboxOpenDetached,   newKey, newNonce   ) where -import           Crypto.Saltine.Class-import           Crypto.Saltine.Internal.Util-import qualified Crypto.Saltine.Internal.ByteSizes as Bytes+import Crypto.Saltine.Internal.SecretBox+            ( c_secretbox+            , c_secretbox_detached+            , c_secretbox_open+            , c_secretbox_open_detached+            , Key(..)+            , Nonce(..)+            , Authenticator(..)+            )+import Crypto.Saltine.Internal.Util as U+import Data.ByteString              (ByteString) -import           Control.Applicative-import           Foreign.C-import           Foreign.Ptr+import qualified Crypto.Saltine.Internal.SecretBox as Bytes import qualified Data.ByteString                   as S-import           Data.ByteString                     (ByteString)-import           Data.Hashable (Hashable)-import           Data.Data (Data, Typeable)-import           GHC.Generics (Generic) --- $types---- | An opaque 'secretbox' cryptographic key.-newtype Key = Key ByteString deriving (Eq, Ord, Hashable, Data, Typeable, Generic)--instance IsEncoding Key where-  decode v = if S.length v == Bytes.secretBoxKey-           then Just (Key v)-           else Nothing-  {-# INLINE decode #-}-  encode (Key v) = v-  {-# INLINE encode #-}---- | An opaque 'secretbox' nonce.-newtype Nonce = Nonce ByteString deriving (Eq, Ord, Hashable, Data, Typeable, Generic)--instance IsEncoding Nonce where-  decode v = if S.length v == Bytes.secretBoxNonce-           then Just (Nonce v)-           else Nothing-  {-# INLINE decode #-}-  encode (Nonce v) = v-  {-# INLINE encode #-}--instance IsNonce Nonce where-  zero            = Nonce (S.replicate Bytes.secretBoxNonce 0)-  nudge (Nonce n) = Nonce (nudgeBS n)- -- | Creates a random key of the correct size for 'secretbox'. newKey :: IO Key-newKey = Key <$> randomByteString Bytes.secretBoxKey+newKey = Key <$> randomByteString Bytes.secretbox_keybytes  -- | Creates a random nonce of the correct size for 'secretbox'. newNonce :: IO Nonce-newNonce = Nonce <$> randomByteString Bytes.secretBoxNonce+newNonce = Nonce <$> randomByteString Bytes.secretbox_noncebytes  -- | Encrypts a message. It is infeasible for an attacker to decrypt -- the message so long as the 'Nonce' is never repeated.-secretbox :: Key -> Nonce-          -> ByteString-          -- ^ Message-          -> ByteString-          -- ^ Ciphertext+secretbox+    :: Key+    -> Nonce+    -> ByteString+    -- ^ Message+    -> ByteString+    -- ^ Ciphertext secretbox (Key key) (Nonce nonce) msg =   unpad' . snd . buildUnsafeByteString len $ \pc ->     constByteStrings [key, pad' msg, nonce] $ \       [(pk, _), (pm, _), (pn, _)] ->         c_secretbox pc pm (fromIntegral len) pn pk-  where len    = S.length msg + Bytes.secretBoxZero-        pad'   = pad Bytes.secretBoxZero-        unpad' = unpad Bytes.secretBoxBoxZero+  where len    = S.length msg + Bytes.secretbox_zerobytes+        pad'   = pad Bytes.secretbox_zerobytes+        unpad' = unpad Bytes.secretbox_boxzerobytes  -- | Encrypts a message. In contrast with 'secretbox', the result is not -- serialized as one element and instead provided as an authentication tag and -- ciphertext.-secretboxDetached :: Key -> Nonce-          -> ByteString-          -- ^ Message-          -> (ByteString,ByteString)-          -- ^ (Authentication Tag, Ciphertext)+secretboxDetached+    :: Key+    -> Nonce+    -> ByteString+    -- ^ Message+    -> (Authenticator,ByteString)+    -- ^ (Authentication Tag, Ciphertext) secretboxDetached (Key key) (Nonce nonce) msg =   buildUnsafeByteString ctLen $ \pc ->-   fmap snd . buildUnsafeByteString' tagLen $ \ptag ->-    constByteStrings [key, msg, nonce] $ \-      [(pk, _), (pmsg, _), (pn, _)] ->-        c_secretbox_detached pc ptag pmsg (fromIntegral ptLen) pn pk+    fmap (Au . snd) . buildUnsafeByteString' tagLen $ \ptag ->+      constByteStrings [key, msg, nonce] $ \+        [(pk, _), (pmsg, _), (pn, _)] ->+          c_secretbox_detached pc ptag pmsg (fromIntegral ptLen) pn pk   where ctLen  = ptLen         ptLen  = S.length msg-        tagLen = Bytes.secretBoxMac+        tagLen = Bytes.secretbox_macbytes  -- | Decrypts a message. Returns 'Nothing' if the keys and message do -- not match.-secretboxOpen :: Key -> Nonce -                 -> ByteString-                 -- ^ Ciphertext-                 -> Maybe ByteString-                 -- ^ Message+secretboxOpen+    :: Key+    -> Nonce+    -> ByteString+    -- ^ Ciphertext+    -> Maybe ByteString+    -- ^ Message secretboxOpen (Key key) (Nonce nonce) cipher =   let (err, vec) = buildUnsafeByteString len $ \pm ->         constByteStrings [key, pad' cipher, nonce] $ \           [(pk, _), (pc, _), (pn, _)] ->             c_secretbox_open pm pc (fromIntegral len) pn pk   in hush . handleErrno err $ unpad' vec-  where len    = S.length cipher + Bytes.secretBoxBoxZero-        pad'   = pad Bytes.secretBoxBoxZero-        unpad' = unpad Bytes.secretBoxZero+  where len    = S.length cipher + Bytes.secretbox_boxzerobytes+        pad'   = pad Bytes.secretbox_boxzerobytes+        unpad' = unpad Bytes.secretbox_zerobytes  -- | Decrypts a message. Returns 'Nothing' if the keys and message do -- not match.-secretboxOpenDetached :: Key -> Nonce-                 -> ByteString-                 -- ^ Auth Tag-                 -> ByteString-                 -- ^ Ciphertext-                 -> Maybe ByteString-                 -- ^ Message-secretboxOpenDetached (Key key) (Nonce nonce) tag cipher-    | S.length tag /= Bytes.secretBoxMac = Nothing+secretboxOpenDetached+    :: Key+    -> Nonce+    -> Authenticator+    -- ^ Auth Tag+    -> ByteString+    -- ^ Ciphertext+    -> Maybe ByteString+    -- ^ Message+secretboxOpenDetached (Key key) (Nonce nonce) (Au tag) cipher+    | S.length tag /= Bytes.secretbox_macbytes = Nothing     | otherwise =   let (err, vec) = buildUnsafeByteString len $ \pm ->         constByteStrings [key, cipher, tag, nonce] $ \@@ -164,67 +144,3 @@             c_secretbox_open_detached pm pc pt (fromIntegral len) pn pk   in hush . handleErrno err $ vec   where len    = S.length cipher---- | The secretbox C API uses 0-padded C strings. Always returns 0.-foreign import ccall "crypto_secretbox"-  c_secretbox :: Ptr CChar-              -- ^ Cipher 0-padded output buffer-              -> Ptr CChar-              -- ^ Constant 0-padded message input buffer-              -> CULLong-              -- ^ Length of message input buffer (incl. 0s)-              -> Ptr CChar-              -- ^ Constant nonce buffer-              -> Ptr CChar-              -- ^ Constant key buffer-              -> IO CInt---- | The secretbox_detached C API uses C strings. Always returns 0.-foreign import ccall "crypto_secretbox_detached"-  c_secretbox_detached-              :: Ptr CChar-              -- ^ Ciphertext output buffer-              -> Ptr CChar-              -- ^ Authentication tag output buffer-              -> Ptr CChar-              -- ^ Constant message input buffer-              -> CULLong-              -- ^ Length of message input buffer (incl. 0s)-              -> Ptr CChar-              -- ^ Constant nonce buffer-              -> Ptr CChar-              -- ^ Constant key buffer-              -> IO CInt---- | The secretbox C API uses 0-padded C strings. Returns 0 if--- successful or -1 if verification failed.-foreign import ccall "crypto_secretbox_open"-  c_secretbox_open :: Ptr CChar-                   -- ^ Message 0-padded output buffer-                   -> Ptr CChar-                   -- ^ Constant 0-padded message input buffer-                   -> CULLong-                   -- ^ Length of message input buffer (incl. 0s)-                   -> Ptr CChar-                   -- ^ Constant nonce buffer-                   -> Ptr CChar-                   -- ^ Constant key buffer-                   -> IO CInt---- | The secretbox C API uses C strings. Returns 0 if--- successful or -1 if verification failed.-foreign import ccall "crypto_secretbox_open_detached"-  c_secretbox_open_detached-                   :: Ptr CChar-                   -- ^ Message output buffer-                   -> Ptr CChar-                   -- ^ Constant ciphertext input buffer-                   -> Ptr CChar-                   -- ^ Constant auth tag input buffer-                   -> CULLong-                   -- ^ Length of ciphertext input buffer-                   -> Ptr CChar-                   -- ^ Constant nonce buffer-                   -> Ptr CChar-                   -- ^ Constant key buffer-                   -> IO CInt
src/Crypto/Saltine/Core/Sign.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE DeriveDataTypeable, GeneralizedNewtypeDeriving, DeriveGeneric #-}  -- | -- Module      : Crypto.Saltine.Core.Sign@@ -28,54 +27,31 @@ -- This is current information as of 2013 June 6.  module Crypto.Saltine.Core.Sign (-  SecretKey, PublicKey, Keypair,+  SecretKey, PublicKey, Keypair(..), Signature,   newKeypair,   sign, signOpen,   signDetached, signVerifyDetached   ) where -import           Crypto.Saltine.Class-import           Crypto.Saltine.Internal.Util-import qualified Crypto.Saltine.Internal.ByteSizes as Bytes--import           Foreign.C-import           Foreign.Ptr-import           Foreign.Marshal.Alloc-import           Foreign.Storable-import           System.IO.Unsafe-import qualified Data.ByteString                   as S-import           Data.ByteString                     (ByteString)-import           Data.Data (Data, Typeable)-import           Data.Hashable (Hashable)-import           GHC.Generics (Generic)----- $types---- | An opaque 'box' cryptographic secret key.-newtype SecretKey = SK ByteString deriving (Eq, Ord, Hashable, Data, Typeable, Generic)--instance IsEncoding SecretKey where-  decode v = if S.length v == Bytes.signSK-           then Just (SK v)-           else Nothing-  {-# INLINE decode #-}-  encode (SK v) = v-  {-# INLINE encode #-}---- | An opaque 'box' cryptographic public key.-newtype PublicKey = PK ByteString deriving (Eq, Ord, Data, Typeable, Hashable, Generic)--instance IsEncoding PublicKey where-  decode v = if S.length v == Bytes.signPK-           then Just (PK v)-           else Nothing-  {-# INLINE decode #-}-  encode (PK v) = v-  {-# INLINE encode #-}+import Crypto.Saltine.Internal.Sign+            ( c_sign_keypair+            , c_sign+            , c_sign_open+            , c_sign_detached+            , c_sign_verify_detached+            , SecretKey(..)+            , PublicKey(..)+            , Keypair(..)+            , Signature(..)+            )+import Crypto.Saltine.Internal.Util as U+import Data.ByteString              (ByteString)+import Foreign.Marshal.Alloc+import Foreign.Storable+import System.IO.Unsafe --- | A convenience type for keypairs-type Keypair = (SecretKey, PublicKey)+import qualified Crypto.Saltine.Internal.Sign as Bytes+import qualified Data.ByteString              as S  -- | Creates a random key of the correct size for 'sign' and -- 'signOpen' of form @(secretKey, publicKey)@.@@ -83,10 +59,10 @@ newKeypair = do   -- This is a little bizarre and a likely source of errors.   -- _err ought to always be 0.-  ((_err, sk), pk) <- buildUnsafeByteString' Bytes.signPK $ \pkbuf ->-    buildUnsafeByteString' Bytes.signSK $ \skbuf ->+  ((_err, sk), pk) <- buildUnsafeByteString' Bytes.sign_publickeybytes $ \pkbuf ->+    buildUnsafeByteString' Bytes.sign_secretkeybytes $ \skbuf ->       c_sign_keypair pkbuf skbuf-  return (SK sk, PK pk)+  return $ Keypair (SK sk) (PK pk)  -- | Augments a message with a signature forming a \"signed -- message\".@@ -97,7 +73,7 @@      -- ^ Signed message sign (SK k) m = unsafePerformIO $   alloca $ \psmlen -> do-    (_err, sm) <- buildUnsafeByteString' (len + Bytes.sign) $ \psmbuf ->+    (_err, sm) <- buildUnsafeByteString' (len + Bytes.sign_bytes) $ \psmbuf ->       constByteStrings [k, m] $ \[(pk, _), (pm, _)] ->         c_sign psmbuf psmlen pm (fromIntegral len) pk     smlen <- peek psmlen@@ -127,87 +103,29 @@ signDetached :: SecretKey              -> ByteString              -- ^ Message-             -> ByteString+             -> Signature              -- ^ Signature signDetached (SK k) m = unsafePerformIO $     alloca $ \psmlen -> do-        (_err, sm) <- buildUnsafeByteString' Bytes.sign $ \sigbuf ->+        (_err, sm) <- buildUnsafeByteString' Bytes.sign_bytes $ \sigbuf ->             constByteStrings [k, m] $ \[(pk, _), (pm, _)] ->                 c_sign_detached sigbuf psmlen pm (fromIntegral len) pk         smlen <- peek psmlen-        return $ S.take (fromIntegral smlen) sm+        return $ Signature $ S.take (fromIntegral smlen) sm   where len = S.length m  -- | Returns @True@ if the signature is valid for the given public key and -- message. signVerifyDetached :: PublicKey-                   -> ByteString+                   -> Signature                    -- ^ Signature                    -> ByteString-                   -- ^ Message+                   -- ^ Message (not signed)                    -> Bool-signVerifyDetached (PK k) sig sm = unsafePerformIO $+signVerifyDetached (PK k) (Signature sig) sm = unsafePerformIO $     constByteStrings [k, sig, sm] $ \[(pk, _), (psig, _), (psm, _)] -> do         res <- c_sign_verify_detached psig psm (fromIntegral len) pk         return (res == 0)   where len = S.length sm  -foreign import ccall "crypto_sign_keypair"-  c_sign_keypair :: Ptr CChar-                 -- ^ Public key output buffer-                 -> Ptr CChar-                 -- ^ Secret key output buffer-                 -> IO CInt-                 -- ^ Always 0--foreign import ccall "crypto_sign"-  c_sign :: Ptr CChar-         -- ^ Signed message output buffer-         -> Ptr CULLong-         -- ^ Length of signed message-         -> Ptr CChar-         -- ^ Constant message buffer-         -> CULLong-         -- ^ Length of message input buffer-         -> Ptr CChar-         -- ^ Constant secret key buffer-         -> IO CInt-         -- ^ Always 0--foreign import ccall "crypto_sign_open"-  c_sign_open :: Ptr CChar-              -- ^ Message output buffer-              -> Ptr CULLong-              -- ^ Length of message-              -> Ptr CChar-              -- ^ Constant signed message buffer-              -> CULLong-              -- ^ Length of signed message buffer-              -> Ptr CChar-              -- ^ Public key buffer-              -> IO CInt-              -- ^ 0 if signature is verifiable, -1 otherwise--foreign import ccall "crypto_sign_detached"-    c_sign_detached :: Ptr CChar-                    -- ^ Signature output buffer-                    -> Ptr CULLong-                    -- ^ Length of the signature-                    -> Ptr CChar-                    -- ^ Constant message buffer-                    -> CULLong-                    -- ^ Length of message buffer-                    -> Ptr CChar-                    -- ^ Constant secret key buffer-                    -> IO CInt-foreign import ccall "crypto_sign_verify_detached"-    c_sign_verify_detached :: Ptr CChar-                           -- ^ Signature buffer-                           -> Ptr CChar-                           -- ^ Constant signed message buffer-                           -> CULLong-                           -- ^ Length of signed message buffer-                           -> Ptr CChar-                           -- ^ Public key buffer-                           -> IO CInt
src/Crypto/Saltine/Core/Stream.hs view
@@ -1,5 +1,3 @@-{-# LANGUAGE DeriveDataTypeable, GeneralizedNewtypeDeriving, DeriveGeneric #-}- -- | -- Module      : Crypto.Saltine.Core.Stream -- Copyright   : (c) Joseph Abrahamson 2013@@ -55,55 +53,25 @@   stream, xor   ) where -import           Crypto.Saltine.Class-import           Crypto.Saltine.Internal.Util-import qualified Crypto.Saltine.Internal.ByteSizes as Bytes--import           Control.Applicative-import           Foreign.C-import           Foreign.Ptr-import qualified Data.ByteString as S-import           Data.ByteString (ByteString)-import           Data.Hashable (Hashable)-import           Data.Data (Data, Typeable)-import           GHC.Generics (Generic)---- $types---- | An opaque 'stream' cryptographic key.-newtype Key = Key ByteString deriving (Eq, Ord, Hashable, Data, Typeable, Generic)--instance IsEncoding Key where-  decode v = if S.length v == Bytes.streamKey-           then Just (Key v)-           else Nothing-  {-# INLINE decode #-}-  encode (Key v) = v-  {-# INLINE encode #-}---- | An opaque 'stream' nonce.-newtype Nonce = Nonce ByteString deriving (Eq, Ord, Hashable, Data, Typeable, Generic)--instance IsNonce Nonce where-  zero = Nonce (S.replicate Bytes.streamNonce 0)-  nudge (Nonce n) = Nonce (nudgeBS n)+import Crypto.Saltine.Internal.Stream ( c_stream+                                      , c_stream_xor+                                      , Key(..)+                                      , Nonce(..)+                                      )+import Crypto.Saltine.Internal.Util   as U+import Data.ByteString                (ByteString) -instance IsEncoding Nonce where-  decode v = if S.length v == Bytes.streamNonce-           then Just (Nonce v)-           else Nothing-  {-# INLINE decode #-}-  encode (Nonce v) = v-  {-# INLINE encode #-}+import qualified Crypto.Saltine.Internal.Stream as Bytes+import qualified Data.ByteString                as S  -- | Creates a random key of the correct size for 'stream' and 'xor'. newKey :: IO Key-newKey = Key <$> randomByteString Bytes.streamKey+newKey = Key <$> randomByteString Bytes.stream_keybytes  -- | Creates a random nonce of the correct size for 'stream' and -- 'xor'. newNonce :: IO Nonce-newNonce = Nonce <$> randomByteString Bytes.streamNonce+newNonce = Nonce <$> randomByteString Bytes.stream_noncebytes  -- | Generates a cryptographic random stream indexed by the 'Key' and -- 'Nonce'. These streams are indistinguishable from random noise so@@ -133,29 +101,3 @@     constByteStrings [key, nonce, msg] $ \[(pk, _), (pn, _), (pm, _)] ->     c_stream_xor pc pm (fromIntegral len) pn pk   where len = S.length msg--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
src/Crypto/Saltine/Core/Utils.hs view
@@ -1,5 +1,6 @@ module Crypto.Saltine.Core.Utils-    (Crypto.Saltine.Internal.Util.randomByteString+    ( Crypto.Saltine.Internal.Util.randomByteString+    , Crypto.Saltine.Internal.Util.bin2hex     ) where  import qualified Crypto.Saltine.Internal.Util
+ src/Crypto/Saltine/Internal/AEAD/AES256GCM.hs view
@@ -0,0 +1,188 @@+{-# LANGUAGE DeriveDataTypeable, GeneralizedNewtypeDeriving, DeriveGeneric, ForeignFunctionInterface #-}+-- |+-- Module      : Crypto.Saltine.Internal.AEAD.AES256GCM+-- Copyright   : (c) Max Amanshauser 2021+-- License     : MIT+--+-- Maintainer  : max@lambdalifting.org+-- Stability   : experimental+-- Portability : non-portable+--+module Crypto.Saltine.Internal.AEAD.AES256GCM (+    aead_aes256gcm_keybytes+  , aead_aes256gcm_npubbytes+  , aead_aes256gcm_abytes+  , c_aead_aes256gcm_is_available+  , c_aead+  , c_aead_open+  , c_aead_detached+  , c_aead_open_detached+  , Key(..)+  , Nonce(..)+) where++import Control.DeepSeq+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 GHC.Generics                 (Generic)+import Foreign.C+import Foreign.Ptr++import qualified Data.ByteString as S++-- | An opaque 'AES256GCM' 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 = "AEAD.AES256GCM.Key {hashesTo = \"" <> (bin2hex . shorthash nullShKey $ encode k) <> "}\""++instance IsEncoding Key where+  decode v = if S.length v == aead_aes256gcm_keybytes+           then Just (Key v)+           else Nothing+  {-# INLINE decode #-}+  encode (Key v) = v+  {-# INLINE encode #-}++-- | An opaque 'AES256GCM' nonce.+newtype Nonce = Nonce { unNonce :: ByteString } deriving (Eq, Ord, Hashable, Data, Typeable, Generic, NFData)+instance Show Nonce where+    show k = "AEAD.AES256GCM.Nonce " <> bin2hex (encode k)++instance IsEncoding Nonce where+  decode v = if S.length v == aead_aes256gcm_npubbytes+           then Just (Nonce v)+           else Nothing+  {-# INLINE decode #-}+  encode (Nonce v) = v+  {-# INLINE encode #-}++instance IsNonce Nonce where+  zero            = Nonce (S.replicate aead_aes256gcm_npubbytes 0)+  nudge (Nonce n) = Nonce (nudgeBS n)+++aead_aes256gcm_keybytes, aead_aes256gcm_abytes, aead_aes256gcm_npubbytes :: Int++-- | Size of an AES256 key+aead_aes256gcm_keybytes  = fromIntegral c_crypto_aead_aes256gcm_keybytes+-- | Size of an AES256 nonce+aead_aes256gcm_npubbytes = fromIntegral c_crypto_aead_aes256gcm_npubbytes+-- | Size of an AES256 authentication tag+aead_aes256gcm_abytes    = fromIntegral c_crypto_aead_aes256gcm_abytes+++-- src/libsodium/crypto_aead/aes256gcm/sodium/aead_aes256gcm.c+-- src/libsodium/include/sodium/crypto_aead_aes256gcm.h+foreign import ccall "crypto_aead_aes256gcm_keybytes"+    c_crypto_aead_aes256gcm_keybytes :: CSize+foreign import ccall "crypto_aead_aes256gcm_npubbytes"+    c_crypto_aead_aes256gcm_npubbytes:: CSize+foreign import ccall "crypto_aead_aes256gcm_abytes"+    c_crypto_aead_aes256gcm_abytes :: CSize+++foreign import ccall "crypto_aead_aes256gcm_is_available"+  c_aead_aes256gcm_is_available+    :: IO CInt++-- | The aead C API uses C strings. Always returns 0.+foreign import ccall "crypto_aead_aes256gcm_encrypt"+  c_aead+    :: Ptr CChar+    -- ^ Cipher output buffer+    -> Ptr CULLong+    -- ^ Cipher output bytes used+    -> Ptr CChar+    -- ^ Constant message input buffer+    -> CULLong+    -- ^ Length of message input buffer+    -> Ptr CChar+    -- ^ Constant aad input buffer+    -> CULLong+    -- ^ Length of aad input buffer+    -> Ptr CChar+    -- ^ Unused 'nsec' value (must be NULL)+    -> Ptr CChar+    -- ^ Constant nonce buffer+    -> Ptr CChar+    -- ^ Constant key buffer+    -> IO CInt++-- | The aead open C API uses C strings. Returns 0 if successful.+foreign import ccall "crypto_aead_aes256gcm_decrypt"+  c_aead_open+    :: Ptr CChar+    -- ^ Message output buffer+    -> Ptr CULLong+    -- ^ Message output bytes used+    -> Ptr CChar+    -- ^ Unused 'nsec' value (must be NULL)+    -> Ptr CChar+    -- ^ Constant ciphertext input buffer+    -> CULLong+    -- ^ Length of ciphertext input buffer+    -> Ptr CChar+    -- ^ Constant aad input buffer+    -> CULLong+    -- ^ Length of aad input buffer+    -> Ptr CChar+    -- ^ Constant nonce buffer+    -> Ptr CChar+    -- ^ Constant key buffer+    -> IO CInt++-- | The aead C API uses C strings. Always returns 0.+foreign import ccall "crypto_aead_aes256gcm_encrypt_detached"+  c_aead_detached+    :: Ptr CChar+    -- ^ Cipher output buffer+    -> Ptr CChar+    -- ^ Tag output buffer+    -> Ptr CULLong+    -- ^ Tag bytes used+    -> Ptr CChar+    -- ^ Constant message input buffer+    -> CULLong+    -- ^ Length of message input buffer+    -> Ptr CChar+    -- ^ Constant aad input buffer+    -> CULLong+    -- ^ Length of aad input buffer+    -> Ptr CChar+    -- ^ Unused 'nsec' value (must be NULL)+    -> Ptr CChar+    -- ^ Constant nonce buffer+    -> Ptr CChar+    -- ^ Constant key buffer+    -> IO CInt++-- | The aead open C API uses C strings. Returns 0 if successful.+foreign import ccall "crypto_aead_aes256gcm_decrypt_detached"+  c_aead_open_detached+    :: Ptr CChar+    -- ^ Message output buffer+    -> Ptr CChar+    -- ^ Unused 'nsec' value (must be NULL)+    -> Ptr CChar+    -- ^ Constant ciphertext input buffer+    -> CULLong+    -- ^ Length of ciphertext input buffer+    -> Ptr CChar+    -- ^ Constant tag input buffer+    -> Ptr CChar+    -- ^ Constant aad input buffer+    -> CULLong+    -- ^ Length of aad input buffer+    -> Ptr CChar+    -- ^ Constant nonce buffer+    -> Ptr CChar+    -- ^ Constant key buffer+    -> IO CInt
+ src/Crypto/Saltine/Internal/AEAD/ChaCha20Poly1305.hs view
@@ -0,0 +1,184 @@+{-# LANGUAGE DeriveDataTypeable, GeneralizedNewtypeDeriving, DeriveGeneric, ForeignFunctionInterface #-}+-- |+-- Module      : Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305+-- Copyright   : (c) Max Amanshauser 2021+-- License     : MIT+--+-- Maintainer  : max@lambdalifting.org+-- Stability   : experimental+-- Portability : non-portable+--+module Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305 (+    aead_chacha20poly1305_keybytes+  , aead_chacha20poly1305_npubbytes+  , aead_chacha20poly1305_abytes+  , c_aead+  , c_aead_open+  , c_aead_detached+  , c_aead_open_detached+  , Key(..)+  , Nonce(..)+) where++import Control.DeepSeq+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 'ChaCha20Poly1305' 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 = "AEAD.ChaCha20Poly1305.Key {hashesTo = \"" <> (bin2hex . shorthash nullShKey $ encode k) <> "}\""++instance IsEncoding Key where+  decode v = if S.length v == aead_chacha20poly1305_keybytes+           then Just (Key v)+           else Nothing+  {-# INLINE decode #-}+  encode (Key v) = v+  {-# INLINE encode #-}++-- | An opaque 'ChaCha20Poly1305' nonce.+newtype Nonce = Nonce { unNonce :: ByteString } deriving (Eq, Ord, Hashable, Data, Typeable, Generic, NFData)+instance Show Nonce where+    show k = "AEAD.ChaCha20Poly1305.Nonce " <> bin2hex (encode k)++instance IsEncoding Nonce where+  decode v = if S.length v == aead_chacha20poly1305_npubbytes+           then Just (Nonce v)+           else Nothing+  {-# INLINE decode #-}+  encode (Nonce v) = v+  {-# INLINE encode #-}++instance IsNonce Nonce where+  zero            = Nonce (S.replicate aead_chacha20poly1305_npubbytes 0)+  nudge (Nonce n) = Nonce (nudgeBS n)+++aead_chacha20poly1305_keybytes, aead_chacha20poly1305_abytes, aead_chacha20poly1305_npubbytes :: Int++-- | Size of a ChaCha20-Poly1305 key+aead_chacha20poly1305_keybytes  = fromIntegral c_crypto_aead_chacha20poly1305_keybytes+-- | Size of a ChaCha20-Poly1305 nonce+aead_chacha20poly1305_npubbytes = fromIntegral c_crypto_aead_chacha20poly1305_npubbytes+-- | Size of a ChaCha20-Poly1305 authentication tag+aead_chacha20poly1305_abytes    = fromIntegral c_crypto_aead_chacha20poly1305_abytes+++-- src/libsodium/crypto_aead/xchacha20poly1305/sodium/aead_xchacha20poly1305.c+-- src/libsodium/include/sodium/crypto_aead_xchacha20poly1305.h+foreign import ccall "crypto_aead_chacha20poly1305_keybytes"+    c_crypto_aead_chacha20poly1305_keybytes :: CSize+foreign import ccall "crypto_aead_chacha20poly1305_npubbytes"+    c_crypto_aead_chacha20poly1305_npubbytes:: CSize+foreign import ccall "crypto_aead_chacha20poly1305_abytes"+    c_crypto_aead_chacha20poly1305_abytes :: CSize+++-- | The aead C API uses C strings. Always returns 0.+foreign import ccall "crypto_aead_chacha20poly1305_encrypt"+  c_aead+    :: Ptr CChar+    -- ^ Cipher output buffer+    -> Ptr CULLong+    -- ^ Cipher output bytes used+    -> Ptr CChar+    -- ^ Constant message input buffer+    -> CULLong+    -- ^ Length of message input buffer+    -> Ptr CChar+    -- ^ Constant aad input buffer+    -> CULLong+    -- ^ Length of aad input buffer+    -> Ptr CChar+    -- ^ Unused 'nsec' value (must be NULL)+    -> Ptr CChar+    -- ^ Constant nonce buffer+    -> Ptr CChar+    -- ^ Constant key buffer+    -> IO CInt++-- | The aead open C API uses C strings. Returns 0 if successful.+foreign import ccall "crypto_aead_chacha20poly1305_decrypt"+  c_aead_open+    :: Ptr CChar+    -- ^ Message output buffer+    -> Ptr CULLong+    -- ^ Message output bytes used+    -> Ptr CChar+    -- ^ Unused 'nsec' value (must be NULL)+    -> Ptr CChar+    -- ^ Constant ciphertext input buffer+    -> CULLong+    -- ^ Length of ciphertext input buffer+    -> Ptr CChar+    -- ^ Constant aad input buffer+    -> CULLong+    -- ^ Length of aad input buffer+    -> Ptr CChar+    -- ^ Constant nonce buffer+    -> Ptr CChar+    -- ^ Constant key buffer+    -> IO CInt++-- | The aead C API uses C strings. Always returns 0.+foreign import ccall "crypto_aead_chacha20poly1305_encrypt_detached"+  c_aead_detached+    :: Ptr CChar+    -- ^ Cipher output buffer+    -> Ptr CChar+    -- ^ Tag output buffer+    -> Ptr CULLong+    -- ^ Tag bytes used+    -> Ptr CChar+    -- ^ Constant message input buffer+    -> CULLong+    -- ^ Length of message input buffer+    -> Ptr CChar+    -- ^ Constant aad input buffer+    -> CULLong+    -- ^ Length of aad input buffer+    -> Ptr CChar+    -- ^ Unused 'nsec' value (must be NULL)+    -> Ptr CChar+    -- ^ Constant nonce buffer+    -> Ptr CChar+    -- ^ Constant key buffer+    -> IO CInt++-- | The aead open C API uses C strings. Returns 0 if successful.+foreign import ccall "crypto_aead_chacha20poly1305_decrypt_detached"+  c_aead_open_detached+    :: Ptr CChar+    -- ^ Message output buffer+    -> Ptr CChar+    -- ^ Unused 'nsec' value (must be NULL)+    -> Ptr CChar+    -- ^ Constant ciphertext input buffer+    -> CULLong+    -- ^ Length of ciphertext input buffer+    -> Ptr CChar+    -- ^ Constant tag input buffer+    -> Ptr CChar+    -- ^ Constant aad input buffer+    -> CULLong+    -- ^ Length of aad input buffer+    -> Ptr CChar+    -- ^ Constant nonce buffer+    -> Ptr CChar+    -- ^ Constant key buffer+    -> IO CInt
+ src/Crypto/Saltine/Internal/AEAD/ChaCha20Poly1305IETF.hs view
@@ -0,0 +1,183 @@+{-# LANGUAGE DeriveDataTypeable, GeneralizedNewtypeDeriving, DeriveGeneric, ForeignFunctionInterface #-}+-- |+-- Module      : Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305IETF+-- Copyright   : (c) Max Amanshauser 2021+-- License     : MIT+--+-- Maintainer  : max@lambdalifting.org+-- Stability   : experimental+-- Portability : non-portable+--+module Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305IETF (+    aead_chacha20poly1305_ietf_keybytes+  , aead_chacha20poly1305_ietf_npubbytes+  , aead_chacha20poly1305_ietf_abytes+  , c_aead+  , c_aead_open+  , c_aead_detached+  , c_aead_open_detached+  , Key(..)+  , Nonce(..)+) where++import Control.DeepSeq+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 'ChaCha20Poly1305IETF' 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 = "AEAD.ChaCha20Poly1305IETF.Key {hashesTo = \"" <> (bin2hex . shorthash nullShKey $ encode k) <> "}\""++instance IsEncoding Key where+  decode v = if S.length v == aead_chacha20poly1305_ietf_keybytes+           then Just (Key v)+           else Nothing+  {-# INLINE decode #-}+  encode (Key v) = v+  {-# INLINE encode #-}++-- | An opaque 'ChaCha20Poly1305IETF' nonce.+newtype Nonce = Nonce { unNonce :: ByteString } deriving (Eq, Ord, Hashable, Data, Typeable, Generic, NFData)+instance Show Nonce where+    show k = "AEAD.ChaCha20Poly1305IETF.Nonce " <> bin2hex (encode k)++instance IsEncoding Nonce where+  decode v = if S.length v == aead_chacha20poly1305_ietf_npubbytes+           then Just (Nonce v)+           else Nothing+  {-# INLINE decode #-}+  encode (Nonce v) = v+  {-# INLINE encode #-}++instance IsNonce Nonce where+  zero            = Nonce (S.replicate aead_chacha20poly1305_ietf_npubbytes 0)+  nudge (Nonce n) = Nonce (nudgeBS n)++aead_chacha20poly1305_ietf_keybytes, aead_chacha20poly1305_ietf_abytes, aead_chacha20poly1305_ietf_npubbytes :: Int++-- | Size of a ChaCha20-Poly1305-IETF key+aead_chacha20poly1305_ietf_keybytes  = fromIntegral c_crypto_aead_chacha20poly1305_ietf_keybytes+-- | Size of a ChaCha20-Poly1305-IETF nonce+aead_chacha20poly1305_ietf_npubbytes = fromIntegral c_crypto_aead_chacha20poly1305_ietf_npubbytes+-- | Size of a ChaCha20-Poly1305-IETF authentication tag+aead_chacha20poly1305_ietf_abytes    = fromIntegral c_crypto_aead_chacha20poly1305_ietf_abytes+++-- src/libsodium/crypto_aead/chacha20poly1305/sodium/aead_chacha20poly1305.c+-- src/libsodium/include/sodium/crypto_aead_chacha20poly1305.h+foreign import ccall "crypto_aead_chacha20poly1305_ietf_keybytes"+    c_crypto_aead_chacha20poly1305_ietf_keybytes :: CSize+foreign import ccall "crypto_aead_chacha20poly1305_ietf_npubbytes"+    c_crypto_aead_chacha20poly1305_ietf_npubbytes:: CSize+foreign import ccall "crypto_aead_chacha20poly1305_ietf_abytes"+    c_crypto_aead_chacha20poly1305_ietf_abytes :: CSize+++-- | The aead C API uses C strings. Always returns 0.+foreign import ccall "crypto_aead_chacha20poly1305_ietf_encrypt"+  c_aead+    :: Ptr CChar+    -- ^ Cipher output buffer+    -> Ptr CULLong+    -- ^ Cipher output bytes used+    -> Ptr CChar+    -- ^ Constant message input buffer+    -> CULLong+    -- ^ Length of message input buffer+    -> Ptr CChar+    -- ^ Constant aad input buffer+    -> CULLong+    -- ^ Length of aad input buffer+    -> Ptr CChar+    -- ^ Unused 'nsec' value (must be NULL)+    -> Ptr CChar+    -- ^ Constant nonce buffer+    -> Ptr CChar+    -- ^ Constant key buffer+    -> IO CInt++-- | The aead open C API uses C strings. Returns 0 if successful.+foreign import ccall "crypto_aead_chacha20poly1305_ietf_decrypt"+  c_aead_open+    :: Ptr CChar+    -- ^ Message output buffer+    -> Ptr CULLong+    -- ^ Message output bytes used+    -> Ptr CChar+    -- ^ Unused 'nsec' value (must be NULL)+    -> Ptr CChar+    -- ^ Constant ciphertext input buffer+    -> CULLong+    -- ^ Length of ciphertext input buffer+    -> Ptr CChar+    -- ^ Constant aad input buffer+    -> CULLong+    -- ^ Length of aad input buffer+    -> Ptr CChar+    -- ^ Constant nonce buffer+    -> Ptr CChar+    -- ^ Constant key buffer+    -> IO CInt++-- | The aead C API uses C strings. Always returns 0.+foreign import ccall "crypto_aead_chacha20poly1305_ietf_encrypt_detached"+  c_aead_detached+    :: Ptr CChar+    -- ^ Cipher output buffer+    -> Ptr CChar+    -- ^ Tag output buffer+    -> Ptr CULLong+    -- ^ Tag bytes used+    -> Ptr CChar+    -- ^ Constant message input buffer+    -> CULLong+    -- ^ Length of message input buffer+    -> Ptr CChar+    -- ^ Constant aad input buffer+    -> CULLong+    -- ^ Length of aad input buffer+    -> Ptr CChar+    -- ^ Unused 'nsec' value (must be NULL)+    -> Ptr CChar+    -- ^ Constant nonce buffer+    -> Ptr CChar+    -- ^ Constant key buffer+    -> IO CInt++-- | The aead open C API uses C strings. Returns 0 if successful.+foreign import ccall "crypto_aead_chacha20poly1305_ietf_decrypt_detached"+  c_aead_open_detached+    :: Ptr CChar+    -- ^ Message output buffer+    -> Ptr CChar+    -- ^ Unused 'nsec' value (must be NULL)+    -> Ptr CChar+    -- ^ Constant ciphertext input buffer+    -> CULLong+    -- ^ Length of ciphertext input buffer+    -> Ptr CChar+    -- ^ Constant tag input buffer+    -> Ptr CChar+    -- ^ Constant aad input buffer+    -> CULLong+    -- ^ Length of aad input buffer+    -> Ptr CChar+    -- ^ Constant nonce buffer+    -> Ptr CChar+    -- ^ Constant key buffer+    -> IO CInt
+ src/Crypto/Saltine/Internal/AEAD/XChaCha20Poly1305.hs view
@@ -0,0 +1,183 @@+{-# LANGUAGE DeriveDataTypeable, GeneralizedNewtypeDeriving, DeriveGeneric, ForeignFunctionInterface #-}+-- |+-- Module      : Crypto.Saltine.Internal.AEAD.XChaCha20Poly1305+-- Copyright   : (c) Max Amanshauser 2021+-- License     : MIT+--+-- Maintainer  : max@lambdalifting.org+-- Stability   : experimental+-- Portability : non-portable+--+module Crypto.Saltine.Internal.AEAD.XChaCha20Poly1305 (+    aead_xchacha20poly1305_ietf_keybytes+  , aead_xchacha20poly1305_ietf_npubbytes+  , aead_xchacha20poly1305_ietf_abytes+  , c_aead+  , c_aead_open+  , c_aead_detached+  , c_aead_open_detached+  , Key(..)+  , Nonce(..)+) where++import Control.DeepSeq+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 'XChaCha20Poly1305' 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 = "AEAD.XChaCha20Poly1305.Key {hashesTo = \"" <> (bin2hex . shorthash nullShKey $ encode k) <> "}\""++instance IsEncoding Key where+  decode v = if S.length v == aead_xchacha20poly1305_ietf_keybytes+           then Just (Key v)+           else Nothing+  {-# INLINE decode #-}+  encode (Key v) = v+  {-# INLINE encode #-}++-- | An opaque 'XChaCha20Poly1305' nonce.+newtype Nonce = Nonce { unNonce :: ByteString } deriving (Eq, Ord, Hashable, Data, Typeable, Generic, NFData)+instance Show Nonce where+    show k = "AEAD.XChaCha20Poly1305.Nonce " <> bin2hex (encode k)++instance IsEncoding Nonce where+  decode v = if S.length v == aead_xchacha20poly1305_ietf_npubbytes+           then Just (Nonce v)+           else Nothing+  {-# INLINE decode #-}+  encode (Nonce v) = v+  {-# INLINE encode #-}++instance IsNonce Nonce where+  zero            = Nonce (S.replicate aead_xchacha20poly1305_ietf_npubbytes 0)+  nudge (Nonce n) = Nonce (nudgeBS n)+++aead_xchacha20poly1305_ietf_keybytes, aead_xchacha20poly1305_ietf_abytes, aead_xchacha20poly1305_ietf_npubbytes :: Int++-- | Size of a XChaCha20-Poly1305 key+aead_xchacha20poly1305_ietf_keybytes  = fromIntegral c_crypto_aead_xchacha20poly1305_ietf_keybytes+-- | Size of a XChaCha20-Poly1305 nonce+aead_xchacha20poly1305_ietf_npubbytes = fromIntegral c_crypto_aead_xchacha20poly1305_ietf_npubbytes+-- | Size of a XChaCha20-Poly1305 authentication tag+aead_xchacha20poly1305_ietf_abytes    = fromIntegral c_crypto_aead_xchacha20poly1305_ietf_abytes+++-- src/libsodium/crypto_aead/xchacha20poly1305/sodium/aead_xchacha20poly1305.c+-- src/libsodium/include/sodium/crypto_aead_xchacha20poly1305.h+foreign import ccall "crypto_aead_xchacha20poly1305_ietf_keybytes"+    c_crypto_aead_xchacha20poly1305_ietf_keybytes :: CSize+foreign import ccall "crypto_aead_xchacha20poly1305_ietf_npubbytes"+    c_crypto_aead_xchacha20poly1305_ietf_npubbytes:: CSize+foreign import ccall "crypto_aead_xchacha20poly1305_ietf_abytes"+    c_crypto_aead_xchacha20poly1305_ietf_abytes :: CSize+++-- | The aead C API uses C strings. Always returns 0.+foreign import ccall "crypto_aead_xchacha20poly1305_ietf_encrypt"+  c_aead+    :: Ptr CChar+    -- ^ Cipher output buffer+    -> Ptr CULLong+    -- ^ Cipher output bytes used+    -> Ptr CChar+    -- ^ Constant message input buffer+    -> CULLong+    -- ^ Length of message input buffer+    -> Ptr CChar+    -- ^ Constant aad input buffer+    -> CULLong+    -- ^ Length of aad input buffer+    -> Ptr CChar+    -- ^ Unused 'nsec' value (must be NULL)+    -> Ptr CChar+    -- ^ Constant nonce buffer+    -> Ptr CChar+    -- ^ Constant key buffer+    -> IO CInt++-- | The aead open C API uses C strings. Returns 0 if successful.+foreign import ccall "crypto_aead_xchacha20poly1305_ietf_decrypt"+  c_aead_open+    :: Ptr CChar+    -- ^ Message output buffer+    -> Ptr CULLong+    -- ^ Message output bytes used+    -> Ptr CChar+    -- ^ Unused 'nsec' value (must be NULL)+    -> Ptr CChar+    -- ^ Constant ciphertext input buffer+    -> CULLong+    -- ^ Length of ciphertext input buffer+    -> Ptr CChar+    -- ^ Constant aad input buffer+    -> CULLong+    -- ^ Length of aad input buffer+    -> Ptr CChar+    -- ^ Constant nonce buffer+    -> Ptr CChar+    -- ^ Constant key buffer+    -> IO CInt++-- | The aead C API uses C strings. Always returns 0.+foreign import ccall "crypto_aead_xchacha20poly1305_ietf_encrypt_detached"+  c_aead_detached+    :: Ptr CChar+    -- ^ Cipher output buffer+    -> Ptr CChar+    -- ^ Tag output buffer+    -> Ptr CULLong+    -- ^ Tag bytes used+    -> Ptr CChar+    -- ^ Constant message input buffer+    -> CULLong+    -- ^ Length of message input buffer+    -> Ptr CChar+    -- ^ Constant aad input buffer+    -> CULLong+    -- ^ Length of aad input buffer+    -> Ptr CChar+    -- ^ Unused 'nsec' value (must be NULL)+    -> Ptr CChar+    -- ^ Constant nonce buffer+    -> Ptr CChar+    -- ^ Constant key buffer+    -> IO CInt++-- | The aead open C API uses C strings. Returns 0 if successful.+foreign import ccall "crypto_aead_xchacha20poly1305_ietf_decrypt_detached"+  c_aead_open_detached+    :: Ptr CChar+    -- ^ Message output buffer+    -> Ptr CChar+    -- ^ Unused 'nsec' value (must be NULL)+    -> Ptr CChar+    -- ^ Constant ciphertext input buffer+    -> CULLong+    -- ^ Length of ciphertext input buffer+    -> Ptr CChar+    -- ^ Constant tag input buffer+    -> Ptr CChar+    -- ^ Constant aad input buffer+    -> CULLong+    -- ^ Length of aad input buffer+    -> Ptr CChar+    -- ^ Constant nonce buffer+    -> Ptr CChar+    -- ^ Constant key buffer+    -> IO CInt
+ src/Crypto/Saltine/Internal/Auth.hs view
@@ -0,0 +1,103 @@+{-# LANGUAGE DeriveDataTypeable, GeneralizedNewtypeDeriving, DeriveGeneric, ForeignFunctionInterface #-}+-- |+-- Module      : Crypto.Saltine.Internal.Auth+-- Copyright   : (c) Max Amanshauser 2021+-- License     : MIT+--+-- Maintainer  : max@lambdalifting.org+-- Stability   : experimental+-- Portability : non-portable+--+module Crypto.Saltine.Internal.Auth (+    auth_bytes+  , auth_keybytes+  , c_auth+  , c_auth_verify+  , Key(..)+  , Authenticator(..)+) where+++import Control.DeepSeq+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 GHC.Generics                 (Generic)+import Foreign.C+import Foreign.Ptr++import qualified Data.ByteString as S++-- | An opaque 'auth' 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 = "Auth.Key {hashesTo = \"" <> (bin2hex . shorthash nullShKey $ encode k) <> "}\""++instance IsEncoding Key where+  decode v = if S.length v == auth_keybytes+           then Just (Key v)+           else Nothing+  {-# INLINE decode #-}+  encode (Key v) = v+  {-# INLINE encode #-}++-- | An opaque 'auth' authenticator.+newtype Authenticator = Au { unAu :: ByteString } deriving (Eq, Ord, Hashable, Data, Typeable, Generic, NFData)+instance Show Authenticator where+    show k = "Auth.Authenticator " <> bin2hex (encode k)++instance IsEncoding Authenticator where+  decode v = if S.length v == auth_bytes+           then Just (Au v)+           else Nothing+  {-# INLINE decode #-}+  encode (Au v) = v+  {-# INLINE encode #-}+++auth_bytes, auth_keybytes :: Int++-- Authentication+-- | Size of a @crypto_auth@ authenticator.+auth_bytes    = fromIntegral c_crypto_auth_bytes+-- | Size of a @crypto_auth@ authenticator key.+auth_keybytes = fromIntegral c_crypto_auth_keybytes++-- src/libsodium/crypto_auth/crypto_auth.c+foreign import ccall "crypto_auth_bytes"+  c_crypto_auth_bytes :: CSize+foreign import ccall "crypto_auth_keybytes"+  c_crypto_auth_keybytes :: CSize++foreign import ccall "crypto_auth"+  c_auth :: Ptr CChar+         -- ^ Authenticator output buffer+         -> Ptr CChar+         -- ^ Constant message buffer+         -> CULLong+         -- ^ Length of message buffer+         -> Ptr CChar+         -- ^ Constant key buffer+         -> IO CInt+         -- ^ Always 0++-- | We don't even include this in the IO monad since all of the+-- buffers are constant.+foreign import ccall "crypto_auth_verify"+  c_auth_verify :: Ptr CChar+                -- ^ Constant authenticator buffer+                -> Ptr CChar+                -- ^ Constant message buffer+                -> CULLong+                -- ^ Length of message buffer+                -> Ptr CChar+                -- ^ Constant key buffer+                -> CInt+                -- ^ Success if 0, failure if -1
+ src/Crypto/Saltine/Internal/Box.hs view
@@ -0,0 +1,282 @@+{-# LANGUAGE DeriveDataTypeable, GeneralizedNewtypeDeriving, DeriveGeneric, ForeignFunctionInterface #-}+-- |+-- Module      : Crypto.Saltine.Internal.Box+-- Copyright   : (c) Max Amanshauser 2021+-- License     : MIT+--+-- Maintainer  : max@lambdalifting.org+-- Stability   : experimental+-- Portability : non-portable+--+module Crypto.Saltine.Internal.Box (+    box_publickeybytes+  , box_secretkeybytes+  , box_noncebytes+  , box_zerobytes+  , box_boxzerobytes+  , box_macbytes+  , box_beforenmbytes+  , box_sealbytes+  , c_box_keypair+  , c_box_easy+  , c_box_open_easy+  , c_box_beforenm+  , c_box_easy_afternm+  , c_box_open_easy_afternm+  , c_box_seal+  , c_box_seal_open+  , SecretKey(..)+  , PublicKey(..)+  , Keypair(..)+  , CombinedKey(..)+  , 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 'box' cryptographic secret key.+newtype SecretKey = SK { unSK :: ByteString } deriving (Ord, Hashable, Data, Typeable, Generic, NFData)+instance Eq SecretKey where+    SK a == SK b = U.compare a b+instance Show SecretKey where+    show k = "Box.SecretKey {hashesTo = \"" <> (bin2hex . shorthash nullShKey $ encode k) <> "}\""++instance IsEncoding SecretKey where+  decode v = if S.length v == box_secretkeybytes+           then Just (SK v)+           else Nothing+  {-# INLINE decode #-}+  encode (SK v) = v+  {-# INLINE encode #-}++-- | An opaque 'box' cryptographic public key.+newtype PublicKey = PK { unPK :: ByteString } deriving (Ord, Hashable, Data, Typeable, Generic, NFData)+instance Eq PublicKey where+    PK a == PK b = U.compare a b+instance Show PublicKey where+    show k = "Box.PublicKey {hashesTo = \"" <> (bin2hex . shorthash nullShKey $ encode k) <> "}\""++instance IsEncoding PublicKey where+  decode v = if S.length v == box_publickeybytes+           then Just (PK v)+           else Nothing+  {-# INLINE decode #-}+  encode (PK v) = v+  {-# INLINE encode #-}++-- | A convenience type for keypairs+data Keypair = Keypair {+    secretKey :: SecretKey+  , publicKey :: PublicKey+} deriving (Ord, Data, Typeable, Generic)++instance Eq Keypair where+    kp1 == kp2 = U.compare (encode $ secretKey kp1) (encode $ secretKey kp2)+            !&&! U.compare (encode $ publicKey kp1) (encode $ publicKey kp2)++instance Hashable Keypair+instance NFData   Keypair++-- | An opaque 'boxAfterNM' cryptographic combined key.+newtype CombinedKey = CK { unCK :: ByteString } deriving (Ord, Hashable, Data, Typeable, Generic, NFData)+instance Eq CombinedKey where+    CK a == CK b = U.compare a b+instance Show CombinedKey where+    show k = "Box.CombinedKey {hashesTo = \"" <> (bin2hex . shorthash nullShKey $ encode k) <> "}\""++instance IsEncoding CombinedKey where+  decode v = if S.length v == box_beforenmbytes+           then Just (CK v)+           else Nothing+  {-# INLINE decode #-}+  encode (CK v) = v+  {-# INLINE encode #-}++-- | An opaque 'box' nonce.+newtype Nonce = Nonce { unNonce :: ByteString } deriving (Eq, Ord, Hashable, Data, Typeable, Generic, NFData)+instance Show Nonce where+    show k = "Box.Nonce " <> bin2hex (encode k)++instance IsEncoding Nonce where+  decode v = if S.length v == box_noncebytes+           then Just (Nonce v)+           else Nothing+  {-# INLINE decode #-}+  encode (Nonce v) = v+  {-# INLINE encode #-}++instance IsNonce Nonce where+  zero            = Nonce (S.replicate box_noncebytes 0)+  nudge (Nonce n) = Nonce (nudgeBS n)+++box_publickeybytes, box_secretkeybytes, box_noncebytes, box_zerobytes, box_boxzerobytes :: Int+box_macbytes, box_beforenmbytes, box_sealbytes :: Int++-- Box+-- | Size of a @crypto_box@ public key+box_publickeybytes  = fromIntegral c_crypto_box_publickeybytes+-- | Size of a @crypto_box@ secret key+box_secretkeybytes  = fromIntegral c_crypto_box_secretkeybytes+-- | Size of a @crypto_box@ nonce+box_noncebytes      = fromIntegral c_crypto_box_noncebytes+-- | Size of 0-padding prepended to messages before using @crypto_box@+-- or after using @crypto_box_open@+box_zerobytes       = fromIntegral c_crypto_box_zerobytes+-- | Size of 0-padding prepended to ciphertext before using+-- @crypto_box_open@ or after using @crypto_box@.+box_boxzerobytes    = fromIntegral c_crypto_box_boxzerobytes+box_macbytes        = fromIntegral c_crypto_box_macbytes+-- | Size of a @crypto_box_beforenm@-generated combined key+box_beforenmbytes   = fromIntegral c_crypto_box_beforenmbytes++-- SealedBox+-- | Amount by which ciphertext is longer than plaintext+-- in sealed boxes+box_sealbytes       = fromIntegral c_crypto_box_sealbytes++-- src/libsodium/crypto_box/crypto_box.c+foreign import ccall "crypto_box_publickeybytes"+  c_crypto_box_publickeybytes :: CSize+foreign import ccall "crypto_box_secretkeybytes"+  c_crypto_box_secretkeybytes :: CSize+foreign import ccall "crypto_box_beforenmbytes"+  c_crypto_box_beforenmbytes :: CSize+foreign import ccall "crypto_box_noncebytes"+  c_crypto_box_noncebytes :: CSize+foreign import ccall "crypto_box_zerobytes"+  c_crypto_box_zerobytes :: CSize+foreign import ccall "crypto_box_boxzerobytes"+  c_crypto_box_boxzerobytes :: CSize+foreign import ccall "crypto_box_macbytes"+  c_crypto_box_macbytes :: CSize++-- src/libsodium/crypto_box_seal.c+foreign import ccall "crypto_box_sealbytes"+  c_crypto_box_sealbytes :: CSize++-- | Should always return a 0.+foreign import ccall "crypto_box_keypair"+  c_box_keypair :: Ptr CChar+                -- ^ Public key+                -> Ptr CChar+                -- ^ Secret key+                -> IO CInt+                -- ^ Always 0++-- | The secretbox C API uses C strings.+foreign import ccall "crypto_box_easy"+  c_box_easy :: Ptr CChar+             -- ^ Cipher output buffer+             -> Ptr CChar+             -- ^ Constant message input buffer+             -> CULLong+             -- ^ Length of message input buffer+             -> Ptr CChar+             -- ^ Constant nonce buffer+             -> Ptr CChar+             -- ^ Constant public key buffer+             -> Ptr CChar+             -- ^ Constant secret key buffer+             -> IO CInt+             -- ^ Always 0++-- | The secretbox C API uses C strings.+foreign import ccall "crypto_box_open_easy"+  c_box_open_easy :: Ptr CChar+                  -- ^ Message output buffer+                  -> Ptr CChar+                  -- ^ Constant ciphertext input buffer+                  -> CULLong+                  -- ^ Length of message input buffer+                  -> Ptr CChar+                  -- ^ Constant nonce buffer+                  -> Ptr CChar+                  -- ^ Constant public key buffer+                  -> Ptr CChar+                  -- ^ Constant secret key buffer+                  -> IO CInt+                  -- ^ 0 for success, -1 for failure to verify++-- | Single target key precompilation.+foreign import ccall "crypto_box_beforenm"+  c_box_beforenm :: Ptr CChar+                 -- ^ Combined key output buffer+                 -> Ptr CChar+                 -- ^ Constant public key buffer+                 -> Ptr CChar+                 -- ^ Constant secret key buffer+                 -> IO CInt+                 -- ^ Always 0++-- | Precompiled key crypto box. Uses C strings.+foreign import ccall "crypto_box_easy_afternm"+  c_box_easy_afternm :: Ptr CChar+                     -- ^ Cipher output buffer+                     -> Ptr CChar+                     -- ^ Constant message input buffer+                     -> CULLong+                     -- ^ Length of message input buffer (incl. 0s)+                     -> Ptr CChar+                     -- ^ Constant nonce buffer+                     -> Ptr CChar+                     -- ^ Constant combined key buffer+                     -> IO CInt+                     -- ^ Always 0++-- | The secretbox C API uses C strings.+foreign import ccall "crypto_box_open_easy_afternm"+  c_box_open_easy_afternm :: Ptr CChar+                          -- ^ Message output buffer+                          -> Ptr CChar+                          -- ^ Constant ciphertext input buffer+                          -> CULLong+                          -- ^ Length of message input buffer (incl. 0s)+                          -> Ptr CChar+                          -- ^ Constant nonce buffer+                          -> Ptr CChar+                          -- ^ Constant combined key buffer+                          -> IO CInt+                          -- ^ 0 for success, -1 for failure to verify+++-- | The sealedbox C API uses C strings.+foreign import ccall "crypto_box_seal"+  c_box_seal :: Ptr CChar+             -- ^ Cipher output buffer+             -> Ptr CChar+             -- ^ Constant message input buffer+             -> CULLong+             -- ^ Length of message input buffer+             -> Ptr CChar+             -- ^ Constant public key buffer+             -> IO CInt+             -- ^ Always 0++-- | The sealedbox C API uses C strings.+foreign import ccall "crypto_box_seal_open"+  c_box_seal_open :: Ptr CChar+                  -- ^ Message output buffer+                  -> Ptr CChar+                  -- ^ Constant ciphertext input buffer+                  -> CULLong+                  -- ^ Length of message input buffer+                  -> Ptr CChar+                  -- ^ Constant public key buffer+                  -> Ptr CChar+                  -- ^ Constant secret key buffer+                  -> IO CInt+                  -- ^ 0 for success, -1 for failure to decrypt
src/Crypto/Saltine/Internal/ByteSizes.hs view
@@ -1,277 +1,16 @@-{-# LANGUAGE ForeignFunctionInterface #-} -- |--- Module      : Crypto.Saltine.Core.ScalarMult+-- Module      : Crypto.Saltine.Internal.ByteSizes -- Copyright   : (c) Joseph Abrahamson 2013+--               (c) Max Amanshauser 2021 -- License     : MIT ----- Maintainer  : me@jspha.com+-- Maintainer  : max@lambdalifting.org -- Stability   : experimental -- Portability : non-portable ----- Various sizes------ While technically these sizes are hidden behind opaque newtype--- wrappers, they can be useful for computation and sizing and are--- thus exposed.------ As of @libsodium-4.1@ some of these sizes are not exported and thus--- are hardcoded here. This limitation should be removed in later--- versions of @libsodium@. module Crypto.Saltine.Internal.ByteSizes (--  auth,-  authKey,-  boxPK,-  boxSK,-  boxNonce,-  boxZero,-  boxBoxZero,-  boxMac,-  boxBeforeNM,-  sealedBox,-  onetime,-  onetimeKey,-  mult,-  multScalar,-  secretBoxKey,-  secretBoxNonce,-  secretBoxMac,-  secretBoxZero,-  secretBoxBoxZero,-  aead_xchacha20poly1305_ietf_ABYTES,-  sign,-  signPK,-  signSK,-  streamKey,-  streamNonce,-  hash,-  shorthash,-  shorthashKey,-  generichashOutLenMax,-  generichashKeyLenMax   ) where -import Foreign.C---- Constants for--auth, authKey :: Int-boxPK, boxSK, boxNonce, boxZero, boxBoxZero :: Int-boxMac, boxBeforeNM, sealedBox :: Int-onetime, onetimeKey :: Int-mult, multScalar :: Int-secretBoxKey, secretBoxNonce, secretBoxMac, secretBoxZero, secretBoxBoxZero :: Int-sign, signPK, signSK :: Int-streamKey, streamNonce :: Int-hash, shorthash, shorthashKey :: Int-generichashOutLenMax, generichashKeyLenMax :: Int---- Authentication--- | Size of a @crypto_auth@ authenticator.-auth    = fromIntegral c_crypto_auth_bytes--- | Size of a @crypto_auth@ authenticator key.-authKey = fromIntegral c_crypto_auth_keybytes---- Box--- | Size of a @crypto_box@ public key-boxPK       = fromIntegral c_crypto_box_publickeybytes--- | Size of a @crypto_box@ secret key-boxSK       = fromIntegral c_crypto_box_secretkeybytes--- | Size of a @crypto_box@ nonce-boxNonce    = fromIntegral c_crypto_box_noncebytes--- | Size of 0-padding prepended to messages before using @crypto_box@--- or after using @crypto_box_open@-boxZero     = fromIntegral c_crypto_box_zerobytes--- | Size of 0-padding prepended to ciphertext before using--- @crypto_box_open@ or after using @crypto_box@.-boxBoxZero  = fromIntegral c_crypto_box_boxzerobytes-boxMac      = fromIntegral c_crypto_box_macbytes--- | Size of a @crypto_box_beforenm@-generated combined key-boxBeforeNM =-  fromIntegral c_crypto_box_beforenmbytes---- SealedBox--- | Amount by which ciphertext is longer than plaintext--- in sealed boxes-sealedBox = fromIntegral c_crypto_box_sealbytes---- OneTimeAuth--- | Size of a @crypto_onetimeauth@ authenticator.-onetime    = fromIntegral c_crypto_onetimeauth_bytes--- | Size of a @crypto_onetimeauth@ authenticator key.-onetimeKey = fromIntegral c_crypto_onetimeauth_keybytes---- ScalarMult--- | Size of a group element string representation for--- @crypto_scalarmult@.-mult = fromIntegral c_crypto_scalarmult_bytes--- | Size of a integer string representation for @crypto_scalarmult@.-multScalar = fromIntegral c_crypto_scalarmult_scalarbytes---- SecretBox--- | Size of a @crypto_secretbox@ secret key-secretBoxKey     = fromIntegral c_crypto_secretbox_keybytes--- | Size of a @crypto_secretbox@ nonce-secretBoxNonce   = fromIntegral c_crypto_secretbox_noncebytes--- | Size of a @crypto_secretbox@ mac-secretBoxMac     = fromIntegral c_crypto_secretbox_macbytes--- | Size of 0-padding prepended to messages before using--- @crypto_secretbox@ or after using @crypto_secretbox_open@-secretBoxZero    = fromIntegral c_crypto_secretbox_zerobytes--- | Size of 0-padding prepended to ciphertext before using--- @crypto_secretbox_open@ or after using @crypto_secretbox@-secretBoxBoxZero = fromIntegral c_crypto_secretbox_boxzerobytes--aead_xchacha20poly1305_ietf_ABYTES :: Int-aead_xchacha20poly1305_ietf_ABYTES = fromIntegral c_crypto_aead_xchacha20poly1305_ietf_ABYTES ---- Signatures--- | The maximum size of a signature prepended to a message to form a--- signed message.-sign   = fromIntegral c_crypto_sign_bytes--- | The size of a public key for signing verification-signPK = fromIntegral c_crypto_sign_publickeybytes--- | The size of a secret key for signing-signSK = fromIntegral c_crypto_sign_secretkeybytes---- Streams--- | The size of a key for the cryptographic stream generation-streamKey   = fromIntegral c_crypto_stream_keybytes--- | The size of a nonce for the cryptographic stream generation-streamNonce = fromIntegral c_crypto_stream_noncebytes---- Hashes--- | The size of a hash resulting from--- 'Crypto.Saltine.Internal.Hash.hash'.-hash         = fromIntegral c_crypto_hash_bytes--- | The size of a keyed hash resulting from--- 'Crypto.Saltine.Internal.Hash.shorthash'.-shorthash    = fromIntegral c_crypto_shorthash_bytes--- | The size of a hashing key for the keyed hash function--- 'Crypto.Saltine.Internal.Hash.shorthash'.-shorthashKey = fromIntegral c_crypto_shorthash_keybytes--- | The maximum output size of the generic hash function--- 'Crypto.Saltine.Core.Hash.generichash'-generichashOutLenMax = fromIntegral c_crypto_generichash_bytes_max--- | The maximum key size of the generic hash function--- 'Crypto.Saltine.Core.Hash.generichash'-generichashKeyLenMax = fromIntegral c_crypto_generichash_keybytes_max---- src/libsodium/crypto_auth/crypto_auth.c-foreign import ccall "crypto_auth_bytes"-  c_crypto_auth_bytes :: CSize-foreign import ccall "crypto_auth_keybytes"-  c_crypto_auth_keybytes :: CSize---- src/libsodium/crypto_box/crypto_box.c-foreign import ccall "crypto_box_publickeybytes"-  c_crypto_box_publickeybytes :: CSize-foreign import ccall "crypto_box_secretkeybytes"-  c_crypto_box_secretkeybytes :: CSize-foreign import ccall "crypto_box_beforenmbytes"-  c_crypto_box_beforenmbytes :: CSize-foreign import ccall "crypto_box_noncebytes"-  c_crypto_box_noncebytes :: CSize-foreign import ccall "crypto_box_zerobytes"-  c_crypto_box_zerobytes :: CSize-foreign import ccall "crypto_box_boxzerobytes"-  c_crypto_box_boxzerobytes :: CSize-foreign import ccall "crypto_box_macbytes"-  c_crypto_box_macbytes :: CSize---- src/libsodium/crypto_box_seal.c-foreign import ccall "crypto_box_sealbytes"-  c_crypto_box_sealbytes :: CSize---- src/libsodium/crypto_onetimeauth/crypto_onetimeauth.c-foreign import ccall "crypto_onetimeauth_bytes"-  c_crypto_onetimeauth_bytes :: CSize-foreign import ccall "crypto_onetimeauth_keybytes"-  c_crypto_onetimeauth_keybytes :: CSize---- src/libsodium/crypto_scalarmult/crypto_scalarmult.c-foreign import ccall "crypto_scalarmult_bytes"-  c_crypto_scalarmult_bytes :: CSize-foreign import ccall "crypto_scalarmult_scalarbytes"-  c_crypto_scalarmult_scalarbytes :: CSize---- src/libsodium/crypto_secretbox/crypto_secretbox.c-foreign import ccall "crypto_secretbox_keybytes"-  c_crypto_secretbox_keybytes :: CSize-foreign import ccall "crypto_secretbox_noncebytes"-  c_crypto_secretbox_noncebytes :: CSize-foreign import ccall "crypto_secretbox_macbytes"-  c_crypto_secretbox_macbytes :: CSize-foreign import ccall "crypto_secretbox_zerobytes"-  c_crypto_secretbox_zerobytes :: CSize-foreign import ccall "crypto_secretbox_boxzerobytes"-  c_crypto_secretbox_boxzerobytes :: CSize---- src/libsodium/crypto_sign/crypto_sign.c-foreign import ccall "crypto_sign_bytes"-  c_crypto_sign_bytes :: CSize-foreign import ccall "crypto_sign_publickeybytes"-  c_crypto_sign_publickeybytes :: CSize-foreign import ccall "crypto_sign_secretkeybytes"-  c_crypto_sign_secretkeybytes :: CSize---- src/libsodium/crypto_generichash/crypto_generichash.c-foreign import ccall "crypto_generichash_bytes_max"-  c_crypto_generichash_bytes_max :: CSize-foreign import ccall "crypto_generichash_keybytes_max"-  c_crypto_generichash_keybytes_max :: CSize---- HARDCODED--- ------------- | The size of a @crypto_aead_tag@.------ HARDCODED to be @crypto_aead_xchacha20poly1305_ietf_ABYTES@ for now until Sodium--- exports the C constant (is a macro).-c_crypto_aead_xchacha20poly1305_ietf_ABYTES :: CSize-c_crypto_aead_xchacha20poly1305_ietf_ABYTES = 16---- | The size of a @crypto_stream@ or @crypto_stream_xor@--- key. HARDCODED to be @crypto_stream_xsalsa20@ for now until Sodium--- exports the C constant.-c_crypto_stream_keybytes :: CSize-c_crypto_stream_keybytes = 32---- | The size of a @crypto_stream@ or @crypto_stream_xor@--- nonce. HARDCODED to be @crypto_stream_xsalsa20@ for now until--- Sodium exports the C constant.-c_crypto_stream_noncebytes :: CSize-c_crypto_stream_noncebytes = 24---- | The size of a @crypto_hash@ output hash. HARDCODED to be--- @crypto_hash_sha512@ for now until Sodium exports the C constant.-c_crypto_hash_bytes :: CSize-c_crypto_hash_bytes = 64---- | The size of a @crypto_shorthash@ output hash. HARDCODED to be--- @crypto_shorthash_siphash24@ for now until Sodium exports the C--- constant.-c_crypto_shorthash_bytes :: CSize-c_crypto_shorthash_bytes = 8---- | The size of a @crypto_shorthash@ key. HARDCODED to be--- @crypto_shorthash_siphash24@ for now until Sodium exports the C--- constant.-c_crypto_shorthash_keybytes :: CSize-c_crypto_shorthash_keybytes = 16----- src/libsodium/crypto_stream/crypto_stream.c--- foreign import ccall "crypto_stream_keybytes"---   c_crypto_stream_keybytes :: CSize--- foreign import ccall "crypto_stream_noncebytes"---   c_crypto_stream_noncebytes :: CSize---- src/libsodium/crypto_shorthash/crypto_shorthash.c--- foreign import ccall "crypto_shorthash_bytes"---   c_crypto_shorthash_bytes :: CSize--- foreign import ccall "crypto_shorthash_keybytes"---   c_crypto_shorthash_keybytes :: CSize  -- Others -- ------
+ src/Crypto/Saltine/Internal/Hash.hs view
@@ -0,0 +1,162 @@+{-# LANGUAGE DeriveDataTypeable, GeneralizedNewtypeDeriving, DeriveGeneric, ForeignFunctionInterface #-}+-- |+-- Module      : Crypto.Saltine.Internal.Hash+-- Copyright   : (c) Max Amanshauser 2021+-- License     : MIT+--+-- Maintainer  : max@lambdalifting.org+-- Stability   : experimental+-- Portability : non-portable+--+module Crypto.Saltine.Internal.Hash (+    hash_bytes+  , shorthash_bytes+  , shorthash_keybytes+  , generichash_bytes_max+  , generichash_keybytes_max+  , c_hash+  , c_shorthash+  , c_generichash+  , nullShKey+  , shorthash+  , ShorthashKey(..)+  , GenerichashKey(..)+  , GenerichashOutLen(..)+) where++import Control.DeepSeq+import Crypto.Saltine.Class+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+import qualified Data.ByteString.Char8 as S8++-- | An opaque 'shorthash' cryptographic secret key.+newtype ShorthashKey = ShK { unShK :: ByteString } deriving (Ord, Hashable, Data, Typeable, Generic, NFData)+instance Eq ShorthashKey where+    ShK a == ShK b = U.compare a b+instance Show ShorthashKey where+    show k = "Hash.ShorthashKey {hashesTo = \"" <> (bin2hex . shorthash nullShKey $ encode k) <> "}\""++-- | Used for our `Show` instances+nullShKey :: ShorthashKey+nullShKey = ShK (S8.replicate shorthash_keybytes '\NUL')++-- | Computes a very short, fast keyed hash.+-- This function is defined here to break circulat module imports+shorthash :: ShorthashKey+          -> ByteString+          -- ^ Message+          -> ByteString+          -- ^ Hash+shorthash (ShK k) m = snd . buildUnsafeByteString shorthash_bytes $ \ph ->+  constByteStrings [k, m] $ \[(pk, _), (pm, _)] ->+    c_shorthash ph pm (fromIntegral $ S.length m) pk++instance IsEncoding ShorthashKey where+  decode v = if S.length v == shorthash_keybytes+           then Just (ShK v)+           else Nothing+  {-# INLINE decode #-}+  encode (ShK v) = v+  {-# INLINE encode #-}++-- | An opaque 'generichash' cryptographic secret key.+newtype GenerichashKey = GhK { unGhK :: ByteString } deriving (Ord, Hashable, Data, Typeable, Generic, NFData)+instance Eq GenerichashKey where+    GhK a == GhK b = U.compare a b+instance Show GenerichashKey where+    show k = "Hash.GenerichashKey {hashesTo = \"" <> (bin2hex . shorthash nullShKey $ encode k) <> "}\""++instance IsEncoding GenerichashKey where+  decode v = if S.length v <= generichash_keybytes_max+             then Just (GhK v)+             else Nothing+  {-# INLINE decode #-}+  encode (GhK v) = v+  {-# INLINE encode #-}++newtype GenerichashOutLen = GhOL { unGhOL :: Int } deriving (Eq, Ord, Hashable, Data, Typeable, Generic, NFData)++hash_bytes, shorthash_bytes, shorthash_keybytes, generichash_bytes_max, generichash_keybytes_max :: Int++-- Hashes+-- | The size of a hash resulting from+-- 'Crypto.Saltine.Internal.Hash.hash'.+hash_bytes         = fromIntegral c_crypto_hash_bytes+-- | The size of a keyed hash resulting from+-- 'Crypto.Saltine.Internal.Hash.shorthash'.+shorthash_bytes    = fromIntegral c_crypto_shorthash_bytes+-- | The size of a hashing key for the keyed hash function+-- 'Crypto.Saltine.Internal.Hash.shorthash'.+shorthash_keybytes = fromIntegral c_crypto_shorthash_keybytes+-- | The maximum output size of the generic hash function+-- 'Crypto.Saltine.Core.Hash.generichash'+generichash_bytes_max = fromIntegral c_crypto_generichash_bytes_max+-- | The maximum key size of the generic hash function+-- 'Crypto.Saltine.Core.Hash.generichash'+generichash_keybytes_max = fromIntegral c_crypto_generichash_keybytes_max++-- src/libsodium/crypto_generichash/crypto_generichash.c+foreign import ccall "crypto_generichash_bytes_max"+  c_crypto_generichash_bytes_max :: CSize+foreign import ccall "crypto_generichash_keybytes_max"+  c_crypto_generichash_keybytes_max :: CSize++-- src/libsodium/crypto_hash/crypto_hash.c+-- src/libsodium/include/sodium/crypto_hash.h+foreign import ccall "crypto_hash_bytes"+  c_crypto_hash_bytes :: CSize++-- src/libsodium/crypto_shorthash/crypto_shorthash.c+-- src/libsodium/include/sodium/crypto_shorthash.h+foreign import ccall "crypto_shorthash_bytes"+  c_crypto_shorthash_bytes :: CSize+foreign import ccall "crypto_shorthash_keybytes"+  c_crypto_shorthash_keybytes :: CSize+++foreign import ccall "crypto_hash"+  c_hash :: Ptr CChar+         -- ^ Output hash buffer+         -> Ptr CChar+         -- ^ Constant message buffer+         -> CULLong+         -- ^ Constant message buffer length+         -> IO CInt+         -- ^ Always 0++foreign import ccall "crypto_shorthash"+  c_shorthash :: Ptr CChar+              -- ^ Output hash buffer+              -> Ptr CChar+              -- ^ Constant message buffer+              -> CULLong+              -- ^ Message buffer length+              -> Ptr CChar+              -- ^ Constant Key buffer+              -> IO CInt+              -- ^ Always 0++foreign import ccall "crypto_generichash"+  c_generichash :: Ptr CChar+                -- ^ Output hash buffer+                -> CULLong+                -- ^ Output hash length+                -> Ptr CChar+                -- ^ Constant message buffer+                -> CULLong+                -- ^ Message buffer length+                -> Ptr CChar+                -- ^ Constant Key buffer+                -> CULLong+                -- ^ Key buffer length+                -> IO CInt+                -- ^ Always 0
+ src/Crypto/Saltine/Internal/OneTimeAuth.hs view
@@ -0,0 +1,104 @@+{-# LANGUAGE DeriveDataTypeable, GeneralizedNewtypeDeriving, DeriveGeneric, ForeignFunctionInterface #-}+-- |+-- Module      : Crypto.Saltine.Internal.OneTimeAuth+-- Copyright   : (c) Max Amanshauser 2021+-- License     : MIT+--+-- Maintainer  : max@lambdalifting.org+-- Stability   : experimental+-- Portability : non-portable+--+module Crypto.Saltine.Internal.OneTimeAuth (+    onetimeauth_bytes+  , onetimeauth_keybytes+  , c_onetimeauth+  , c_onetimeauth_verify+  , Key(..)+  , Authenticator(..)+) where+++import Control.DeepSeq+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 'auth' 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 = "OneTimeAuth.Key {hashesTo = \"" <> (bin2hex . shorthash nullShKey $ encode k) <> "}\""++instance IsEncoding Key where+  decode v = if S.length v == onetimeauth_keybytes+           then Just (Key v)+           else Nothing+  {-# INLINE decode #-}+  encode (Key v) = v+  {-# INLINE encode #-}++-- | An opaque 'auth' authenticator.+newtype Authenticator = Au { unAu :: ByteString } deriving (Eq, Ord, Hashable, Data, Typeable, Generic, NFData)+instance Show Authenticator where+    show k = "OneTimeAuth.Authenticator " <> bin2hex (encode k)++instance IsEncoding Authenticator where+  decode v = if S.length v == onetimeauth_bytes+           then Just (Au v)+           else Nothing+  {-# INLINE decode #-}+  encode (Au v) = v+  {-# INLINE encode #-}+++onetimeauth_bytes, onetimeauth_keybytes :: Int++-- OneTimeAuth+-- | Size of a @crypto_onetimeauth@ authenticator.+onetimeauth_bytes    = fromIntegral c_crypto_onetimeauth_bytes+-- | Size of a @crypto_onetimeauth@ authenticator key.+onetimeauth_keybytes = fromIntegral c_crypto_onetimeauth_keybytes++-- src/libsodium/crypto_onetimeauth/crypto_onetimeauth.c+foreign import ccall "crypto_onetimeauth_bytes"+  c_crypto_onetimeauth_bytes :: CSize+foreign import ccall "crypto_onetimeauth_keybytes"+  c_crypto_onetimeauth_keybytes :: CSize+++foreign import ccall "crypto_onetimeauth"+  c_onetimeauth :: Ptr CChar+                -- ^ Authenticator output buffer+                -> Ptr CChar+                -- ^ Constant message buffer+                -> CULLong+                -- ^ Length of message buffer+                -> Ptr CChar+                -- ^ Constant key buffer+                -> IO CInt+                -- ^ Always 0++-- | We don't even include this in the IO monad since all of the+-- buffers are constant.+foreign import ccall "crypto_onetimeauth_verify"+  c_onetimeauth_verify :: Ptr CChar+                       -- ^ Constant authenticator buffer+                       -> Ptr CChar+                       -- ^ Constant message buffer+                       -> CULLong+                       -- ^ Length of message buffer+                       -> Ptr CChar+                       -- ^ Constant key buffer+                       -> CInt+                       -- ^ Success if 0, failure if -1
+ src/Crypto/Saltine/Internal/Password.hs view
@@ -0,0 +1,567 @@+{-# LANGUAGE DeriveDataTypeable, GeneralizedNewtypeDeriving, DeriveGeneric, ForeignFunctionInterface #-}++-- |+-- Module      : Crypto.Saltine.Internal.Password+-- Copyright   : (c) Promethea Raschke 2018+--                   Max Amanshauser 2021+-- License     : MIT+-- Maintainer  : max@lambdalifting.org+-- Stability   : experimental+-- Portability : non-portable++module Crypto.Saltine.Internal.Password+  ( c_pwhash+  , c_pwhash_str+  , c_pwhash_str_verify+  , c_pwhash_str_needs_rehash++  , pwhash_alg_argon2i13+  , pwhash_alg_argon2id13+  , pwhash_alg_default+  , algorithm++  -- Default algorithm constants+  , pwhash_bytes_max+  , pwhash_bytes_min++  , pwhash_memlimit_interactive+  , pwhash_memlimit_moderate+  , pwhash_memlimit_sensitive+  , pwhash_memlimit_min+  , pwhash_memlimit_max++  , pwhash_opslimit_interactive+  , pwhash_opslimit_moderate+  , pwhash_opslimit_sensitive+  , pwhash_opslimit_min+  , pwhash_opslimit_max++  , pwhash_passwd_min+  , pwhash_passwd_max+  , pwhash_saltbytes+  , pwhash_strbytes+  , pwhash_strprefix++  -- Argon2i algorithm constants+  , pwhash_argon2i_bytes_max+  , pwhash_argon2i_bytes_min++  , pwhash_argon2i_memlimit_interactive+  , pwhash_argon2i_memlimit_moderate+  , pwhash_argon2i_memlimit_sensitive+  , pwhash_argon2i_memlimit_min+  , pwhash_argon2i_memlimit_max++  , pwhash_argon2i_opslimit_interactive+  , pwhash_argon2i_opslimit_moderate+  , pwhash_argon2i_opslimit_sensitive+  , pwhash_argon2i_opslimit_min+  , pwhash_argon2i_opslimit_max++  , pwhash_argon2i_passwd_min+  , pwhash_argon2i_passwd_max+  , pwhash_argon2i_saltbytes+  , pwhash_argon2i_strbytes+  , pwhash_argon2i_strprefix++  -- Argon2id algorithm constants+  , pwhash_argon2id_bytes_max+  , pwhash_argon2id_bytes_min++  , pwhash_argon2id_memlimit_interactive+  , pwhash_argon2id_memlimit_moderate+  , pwhash_argon2id_memlimit_sensitive+  , pwhash_argon2id_memlimit_min+  , pwhash_argon2id_memlimit_max++  , pwhash_argon2id_opslimit_interactive+  , pwhash_argon2id_opslimit_moderate+  , pwhash_argon2id_opslimit_sensitive+  , pwhash_argon2id_opslimit_min+  , pwhash_argon2id_opslimit_max++  , pwhash_argon2id_passwd_min+  , pwhash_argon2id_passwd_max+  , pwhash_argon2id_saltbytes+  , pwhash_argon2id_strbytes+  , pwhash_argon2id_strprefix++  , Salt(..)+  , PasswordHash(..)+  , Opslimit(..)+  , Memlimit(..)+  , Policy(..)+  , Algorithm(..)+  ) where++import Control.DeepSeq+import Crypto.Saltine.Class+import Crypto.Saltine.Internal.Util as U+import Data.ByteString              (ByteString)+import Data.Data                    (Data, Typeable)+import Data.Hashable                (Hashable)+import Data.Monoid+import Data.Text                    (Text)+import GHC.Generics                 (Generic)+import Foreign.C+import Foreign.Ptr++import qualified Data.ByteString    as S+import qualified Data.Text.Encoding as DTE+++-- | Salt for deriving keys from passwords+newtype Salt = Salt { unSalt :: ByteString } deriving (Ord, Data, Hashable, Typeable, Generic, NFData)+instance Eq Salt where+    Salt a == Salt b = U.compare a b+instance Show Salt where+    show k = "Password.Salt " <> bin2hex (encode k)++instance IsEncoding Salt where+  decode v = if S.length v == pwhash_saltbytes+           then Just (Salt v)+           else Nothing+  {-# INLINE decode #-}+  encode (Salt v) = v+  {-# INLINE encode #-}++-- | Verification string for stored passwords+-- This hash contains only printable characters, hence we can just derive Show.+newtype PasswordHash = PasswordHash { unPasswordHash :: Text } deriving (Ord, Data, Hashable, Typeable, Generic, Show, NFData)+-- Constant time Eq instance, just in case.+instance Eq PasswordHash where+    PasswordHash a == PasswordHash b = U.compare (DTE.encodeUtf8 a) (DTE.encodeUtf8 b)++-- | Wrapper type for the operations used by password hashing+newtype Opslimit = Opslimit { getOpslimit :: Int } deriving (Eq, Ord, Data, Hashable, Typeable, Generic, Show, NFData)++-- | Wrapper type for the memory used by password hashing+newtype Memlimit = Memlimit { getMemlimit :: Int } deriving (Eq, Ord, Data, Hashable, Typeable, Generic, Show, NFData)++-- | Wrapper for opslimit, memlimit and algorithm+data Policy = Policy+  { opsPolicy :: Opslimit+  , memPolicy :: Memlimit+  , algPolicy :: Algorithm+  } deriving (Eq, Ord, Data, Typeable, Generic, Show)+instance Hashable Policy++-- | Algorithms known to Libsodium, as an enum datatype+data Algorithm+  = DefaultAlgorithm+  | Argon2i13+  | Argon2id13+  deriving (Eq, Enum, Ord, Show, Generic, Data, Typeable, Bounded)+instance Hashable Algorithm++algorithm :: Algorithm -> CInt+algorithm DefaultAlgorithm = fromIntegral pwhash_alg_default+algorithm Argon2i13        = fromIntegral pwhash_alg_argon2i13+algorithm Argon2id13       = fromIntegral pwhash_alg_argon2id13++-- | Lets libsodium pick a hashing algorithm+pwhash_alg_default :: Int+pwhash_alg_default = fromIntegral c_crypto_pwhash_alg_default+-- | version 1.3 of the Argon2i algorithm+pwhash_alg_argon2i13 :: Int+pwhash_alg_argon2i13 = fromIntegral c_crypto_pwhash_alg_argon2i13+-- | version 1.3 of the Argon2id algorithm+pwhash_alg_argon2id13 :: Int+pwhash_alg_argon2id13 = fromIntegral c_crypto_pwhash_alg_argon2id13++-- | Constants for the default algorithm+-- | Minimum output length for key derivation (16 (128 bits)).+pwhash_bytes_min :: Int+pwhash_bytes_min = fromIntegral c_crypto_pwhash_bytes_min+-- | Maximum output length for key derivation.+pwhash_bytes_max :: Int+pwhash_bytes_max = fromIntegral c_crypto_pwhash_bytes_max++-- | Minimum allowed memory limit for password hashing+pwhash_memlimit_min :: Int+pwhash_memlimit_min = fromIntegral c_crypto_pwhash_memlimit_min+-- | Maximum allowed memory limit for password hashing+pwhash_memlimit_max :: Int+pwhash_memlimit_max = fromIntegral c_crypto_pwhash_memlimit_max+-- | Constant for currently 64MB memory+pwhash_memlimit_interactive :: Int+pwhash_memlimit_interactive = fromIntegral c_crypto_pwhash_memlimit_interactive+-- | Constant for currently 256MB memory+pwhash_memlimit_moderate :: Int+pwhash_memlimit_moderate = fromIntegral c_crypto_pwhash_memlimit_moderate+-- | Constant for currently 1024MB memory+pwhash_memlimit_sensitive :: Int+pwhash_memlimit_sensitive = fromIntegral c_crypto_pwhash_memlimit_sensitive++-- | Minimum allowed number of computations for password hashing+pwhash_opslimit_min :: Int+pwhash_opslimit_min = fromIntegral c_crypto_pwhash_opslimit_min+-- | Maximum allowed number of computations for password hashing+pwhash_opslimit_max :: Int+pwhash_opslimit_max = fromIntegral c_crypto_pwhash_opslimit_max++-- | Constant for relatively fast hashing+pwhash_opslimit_interactive :: Int+pwhash_opslimit_interactive = fromIntegral c_crypto_pwhash_opslimit_interactive+-- | Constant for moderately fast hashing+pwhash_opslimit_moderate :: Int+pwhash_opslimit_moderate = fromIntegral c_crypto_pwhash_opslimit_moderate+-- | Constant for relatively slow hashing+pwhash_opslimit_sensitive :: Int+pwhash_opslimit_sensitive = fromIntegral c_crypto_pwhash_opslimit_sensitive++-- | Minimum number of characters in password for key derivation+pwhash_passwd_min :: Int+pwhash_passwd_min = fromIntegral c_crypto_pwhash_passwd_min+-- | Maximum number of characters in password for key derivation+pwhash_passwd_max :: Int+pwhash_passwd_max = fromIntegral c_crypto_pwhash_passwd_max++-- | Size of salt+pwhash_saltbytes :: Int+pwhash_saltbytes = fromIntegral c_crypto_pwhash_saltbytes+-- | (Maximum) size of password hashing output+pwhash_strbytes :: Int+pwhash_strbytes = fromIntegral c_crypto_pwhash_strbytes+-- string that hashes with this algorithm are prefixed with+pwhash_strprefix :: Int+pwhash_strprefix = fromIntegral c_crypto_pwhash_strprefix+++-- | Constants for Argon2ID+-- | Minimum output length for key derivation (= 16 (128 bits)).+pwhash_argon2id_bytes_min :: Int+pwhash_argon2id_bytes_min = fromIntegral c_crypto_pwhash_argon2id_bytes_min+-- | Maximum output length for key derivation.+pwhash_argon2id_bytes_max :: Int+pwhash_argon2id_bytes_max = fromIntegral c_crypto_pwhash_argon2id_bytes_max++-- | Minimum allowed memory limit for password hashing+pwhash_argon2id_memlimit_min :: Int+pwhash_argon2id_memlimit_min = fromIntegral c_crypto_pwhash_argon2id_memlimit_min+-- | Maximum allowed memory limit for password hashing+pwhash_argon2id_memlimit_max :: Int+pwhash_argon2id_memlimit_max = fromIntegral c_crypto_pwhash_argon2id_memlimit_max+-- | Constant for currently 64MB memory+pwhash_argon2id_memlimit_interactive :: Int+pwhash_argon2id_memlimit_interactive = fromIntegral c_crypto_pwhash_argon2id_memlimit_interactive+-- | Constant for currently 256MB memory+pwhash_argon2id_memlimit_moderate :: Int+pwhash_argon2id_memlimit_moderate = fromIntegral c_crypto_pwhash_argon2id_memlimit_moderate+-- | Constant for currently 1024MB memory+pwhash_argon2id_memlimit_sensitive :: Int+pwhash_argon2id_memlimit_sensitive = fromIntegral c_crypto_pwhash_argon2id_memlimit_sensitive++-- | Minimum allowed number of computations for password hashing+pwhash_argon2id_opslimit_min :: Int+pwhash_argon2id_opslimit_min = fromIntegral c_crypto_pwhash_argon2id_opslimit_min+-- | Maximum allowed number of computations for password hashing+pwhash_argon2id_opslimit_max :: Int+pwhash_argon2id_opslimit_max = fromIntegral c_crypto_pwhash_argon2id_opslimit_max++-- | Constant for relatively fast hashing+pwhash_argon2id_opslimit_interactive :: Int+pwhash_argon2id_opslimit_interactive = fromIntegral c_crypto_pwhash_argon2id_opslimit_interactive+-- | Constant for moderately fast hashing+pwhash_argon2id_opslimit_moderate :: Int+pwhash_argon2id_opslimit_moderate = fromIntegral c_crypto_pwhash_argon2id_opslimit_moderate+-- | Constant for relatively slow hashing+pwhash_argon2id_opslimit_sensitive :: Int+pwhash_argon2id_opslimit_sensitive = fromIntegral c_crypto_pwhash_argon2id_opslimit_sensitive++-- | Minimum number of characters in password for key derivation+pwhash_argon2id_passwd_min :: Int+pwhash_argon2id_passwd_min = fromIntegral c_crypto_pwhash_argon2id_passwd_min+-- | Maximum number of characters in password for key derivation+pwhash_argon2id_passwd_max :: Int+pwhash_argon2id_passwd_max = fromIntegral c_crypto_pwhash_argon2id_passwd_max++-- | Size of salt+pwhash_argon2id_saltbytes :: Int+pwhash_argon2id_saltbytes = fromIntegral c_crypto_pwhash_argon2id_saltbytes+-- | (Maximum) size of password hashing output+pwhash_argon2id_strbytes :: Int+pwhash_argon2id_strbytes = fromIntegral c_crypto_pwhash_argon2id_strbytes+-- string that hashes with this algorithm are prefixed with+pwhash_argon2id_strprefix :: Int+pwhash_argon2id_strprefix = fromIntegral c_crypto_pwhash_argon2id_strprefix++-- | Constants for ARGON2I+-- | Minimum output length for key derivation (= 16 (128 bits)).+pwhash_argon2i_bytes_min :: Int+pwhash_argon2i_bytes_min = fromIntegral c_crypto_pwhash_argon2i_bytes_min+-- | Maximum output length for key derivation.+pwhash_argon2i_bytes_max :: Int+pwhash_argon2i_bytes_max = fromIntegral c_crypto_pwhash_argon2i_bytes_max++-- | Minimum allowed memory limit for password hashing+pwhash_argon2i_memlimit_min :: Int+pwhash_argon2i_memlimit_min = fromIntegral c_crypto_pwhash_argon2i_memlimit_min+-- | Maximum allowed memory limit for password hashing+pwhash_argon2i_memlimit_max :: Int+pwhash_argon2i_memlimit_max = fromIntegral c_crypto_pwhash_argon2i_memlimit_max+-- | Constant for currently 64MB memory+pwhash_argon2i_memlimit_interactive :: Int+pwhash_argon2i_memlimit_interactive = fromIntegral c_crypto_pwhash_argon2i_memlimit_interactive+-- | Constant for currently 256MB memory+pwhash_argon2i_memlimit_moderate :: Int+pwhash_argon2i_memlimit_moderate = fromIntegral c_crypto_pwhash_argon2i_memlimit_moderate+-- | Constant for currently 1024MB memory+pwhash_argon2i_memlimit_sensitive :: Int+pwhash_argon2i_memlimit_sensitive = fromIntegral c_crypto_pwhash_argon2i_memlimit_sensitive++-- | Minimum allowed number of computations for password hashing+pwhash_argon2i_opslimit_min :: Int+pwhash_argon2i_opslimit_min = fromIntegral c_crypto_pwhash_argon2i_opslimit_min+-- | Maximum allowed number of computations for password hashing+pwhash_argon2i_opslimit_max :: Int+pwhash_argon2i_opslimit_max = fromIntegral c_crypto_pwhash_argon2i_opslimit_max++-- | Constant for relatively fast hashing+pwhash_argon2i_opslimit_interactive :: Int+pwhash_argon2i_opslimit_interactive = fromIntegral c_crypto_pwhash_argon2i_opslimit_interactive+-- | Constant for moderately fast hashing+pwhash_argon2i_opslimit_moderate :: Int+pwhash_argon2i_opslimit_moderate = fromIntegral c_crypto_pwhash_argon2i_opslimit_moderate+-- | Constant for relatively slow hashing+pwhash_argon2i_opslimit_sensitive :: Int+pwhash_argon2i_opslimit_sensitive = fromIntegral c_crypto_pwhash_argon2i_opslimit_sensitive++-- | Minimum number of characters in password for key derivation+pwhash_argon2i_passwd_min :: Int+pwhash_argon2i_passwd_min = fromIntegral c_crypto_pwhash_argon2i_passwd_min+-- | Maximum number of characters in password for key derivation+pwhash_argon2i_passwd_max :: Int+pwhash_argon2i_passwd_max = fromIntegral c_crypto_pwhash_argon2i_passwd_max++-- | Size of salt+pwhash_argon2i_saltbytes :: Int+pwhash_argon2i_saltbytes = fromIntegral c_crypto_pwhash_argon2i_saltbytes+-- | (Maximum) size of password hashing output+pwhash_argon2i_strbytes :: Int+pwhash_argon2i_strbytes = fromIntegral c_crypto_pwhash_argon2i_strbytes+-- string that hashes with this algorithm are prefixed with+pwhash_argon2i_strprefix :: Int+pwhash_argon2i_strprefix = fromIntegral c_crypto_pwhash_argon2i_strprefix++++foreign import ccall "crypto_pwhash"+  c_pwhash+        :: Ptr CChar+        -- ^ Derived key output buffer+        -> CULLong+        -- ^ Derived key length+        -> Ptr CChar+        -- ^ Password input buffer+        -> CULLong+        -- ^ Password length+        -> Ptr CChar+        -- ^ Salt input buffer+        -> CULLong+        -- ^ Operation limit+        -> CSize+        -- ^ Memory usage limit+        -> CInt+        -- ^ Algorithm+        -> IO CInt++foreign import ccall "crypto_pwhash_str"+  c_pwhash_str+        :: Ptr CChar+        -- ^ Hashed password output buffer+        -> Ptr CChar+        -- ^ Password input buffer+        -> CULLong+        -- ^ Password length+        -> CULLong+        -- ^ Operation limit+        -> CSize+        -- ^ Memory usage limit+        -> IO CInt++foreign import ccall "crypto_pwhash_str_verify"+  c_pwhash_str_verify+        :: Ptr CChar+        -- ^ Hashed password input buffer+        -> Ptr CChar+        -- ^ Password input buffer+        -> CULLong+        -- ^ Password length+        -> IO CInt++foreign import ccall "crypto_pwhash_str_needs_rehash"+  c_pwhash_str_needs_rehash+        :: Ptr CChar+        -- ^ Hashed password input buffer+        -> CULLong+        -- ^ Operation limit+        -> CSize+        -- ^ Memory usage limit+        -> IO CInt++foreign import ccall "crypto_pwhash_alg_argon2id13"+  c_crypto_pwhash_alg_argon2id13 :: CSize++foreign import ccall "crypto_pwhash_alg_argon2i13"+  c_crypto_pwhash_alg_argon2i13 :: CSize++foreign import ccall "crypto_pwhash_alg_default"+  c_crypto_pwhash_alg_default :: CSize++-- Constants for the default algorithm+foreign import ccall "crypto_pwhash_bytes_min"+  c_crypto_pwhash_bytes_min :: CSize++foreign import ccall "crypto_pwhash_bytes_max"+  c_crypto_pwhash_bytes_max :: CSize++foreign import ccall "crypto_pwhash_memlimit_min"+  c_crypto_pwhash_memlimit_min :: CSize++foreign import ccall "crypto_pwhash_memlimit_max"+  c_crypto_pwhash_memlimit_max :: CSize++foreign import ccall "crypto_pwhash_memlimit_interactive"+  c_crypto_pwhash_memlimit_interactive :: CSize++foreign import ccall "crypto_pwhash_memlimit_moderate"+  c_crypto_pwhash_memlimit_moderate :: CSize++foreign import ccall "crypto_pwhash_memlimit_sensitive"+  c_crypto_pwhash_memlimit_sensitive :: CSize++foreign import ccall "crypto_pwhash_opslimit_min"+  c_crypto_pwhash_opslimit_min :: CSize++foreign import ccall "crypto_pwhash_opslimit_max"+  c_crypto_pwhash_opslimit_max :: CSize++foreign import ccall "crypto_pwhash_opslimit_interactive"+  c_crypto_pwhash_opslimit_interactive :: CSize++foreign import ccall "crypto_pwhash_opslimit_moderate"+  c_crypto_pwhash_opslimit_moderate :: CSize++foreign import ccall "crypto_pwhash_opslimit_sensitive"+  c_crypto_pwhash_opslimit_sensitive :: CSize++foreign import ccall "crypto_pwhash_passwd_min"+  c_crypto_pwhash_passwd_min :: CSize++foreign import ccall "crypto_pwhash_passwd_max"+  c_crypto_pwhash_passwd_max :: CSize++foreign import ccall "crypto_pwhash_saltbytes"+  c_crypto_pwhash_saltbytes :: CSize++foreign import ccall "crypto_pwhash_strbytes"+  c_crypto_pwhash_strbytes :: CSize++foreign import ccall "crypto_pwhash_strprefix"+  c_crypto_pwhash_strprefix :: CSize++-- Constants for ARGON2ID (currently default)+foreign import ccall "crypto_pwhash_argon2id_bytes_min"+  c_crypto_pwhash_argon2id_bytes_min :: CSize++foreign import ccall "crypto_pwhash_argon2id_bytes_max"+  c_crypto_pwhash_argon2id_bytes_max :: CSize++foreign import ccall "crypto_pwhash_argon2id_memlimit_min"+  c_crypto_pwhash_argon2id_memlimit_min :: CSize++foreign import ccall "crypto_pwhash_argon2id_memlimit_max"+  c_crypto_pwhash_argon2id_memlimit_max :: CSize++foreign import ccall "crypto_pwhash_argon2id_memlimit_interactive"+  c_crypto_pwhash_argon2id_memlimit_interactive :: CSize++foreign import ccall "crypto_pwhash_argon2id_memlimit_moderate"+  c_crypto_pwhash_argon2id_memlimit_moderate :: CSize++foreign import ccall "crypto_pwhash_argon2id_memlimit_sensitive"+  c_crypto_pwhash_argon2id_memlimit_sensitive :: CSize++foreign import ccall "crypto_pwhash_argon2id_opslimit_min"+  c_crypto_pwhash_argon2id_opslimit_min :: CSize++foreign import ccall "crypto_pwhash_argon2id_opslimit_max"+  c_crypto_pwhash_argon2id_opslimit_max :: CSize++foreign import ccall "crypto_pwhash_argon2id_opslimit_interactive"+  c_crypto_pwhash_argon2id_opslimit_interactive :: CSize++foreign import ccall "crypto_pwhash_argon2id_opslimit_moderate"+  c_crypto_pwhash_argon2id_opslimit_moderate :: CSize++foreign import ccall "crypto_pwhash_argon2id_opslimit_sensitive"+  c_crypto_pwhash_argon2id_opslimit_sensitive :: CSize++foreign import ccall "crypto_pwhash_argon2id_passwd_min"+  c_crypto_pwhash_argon2id_passwd_min :: CSize++foreign import ccall "crypto_pwhash_argon2id_passwd_max"+  c_crypto_pwhash_argon2id_passwd_max :: CSize++foreign import ccall "crypto_pwhash_argon2id_saltbytes"+  c_crypto_pwhash_argon2id_saltbytes :: CSize++foreign import ccall "crypto_pwhash_argon2id_strbytes"+  c_crypto_pwhash_argon2id_strbytes :: CSize++foreign import ccall "crypto_pwhash_argon2id_strprefix"+  c_crypto_pwhash_argon2id_strprefix :: CSize+++-- Constants for ARGON2I+foreign import ccall "crypto_pwhash_argon2i_bytes_min"+  c_crypto_pwhash_argon2i_bytes_min :: CSize++foreign import ccall "crypto_pwhash_argon2i_bytes_max"+  c_crypto_pwhash_argon2i_bytes_max :: CSize++foreign import ccall "crypto_pwhash_argon2i_memlimit_min"+  c_crypto_pwhash_argon2i_memlimit_min :: CSize++foreign import ccall "crypto_pwhash_argon2i_memlimit_max"+  c_crypto_pwhash_argon2i_memlimit_max :: CSize++foreign import ccall "crypto_pwhash_argon2i_memlimit_interactive"+  c_crypto_pwhash_argon2i_memlimit_interactive :: CSize++foreign import ccall "crypto_pwhash_argon2i_memlimit_moderate"+  c_crypto_pwhash_argon2i_memlimit_moderate :: CSize++foreign import ccall "crypto_pwhash_argon2i_memlimit_sensitive"+  c_crypto_pwhash_argon2i_memlimit_sensitive :: CSize++foreign import ccall "crypto_pwhash_argon2i_opslimit_min"+  c_crypto_pwhash_argon2i_opslimit_min :: CSize++foreign import ccall "crypto_pwhash_argon2i_opslimit_max"+  c_crypto_pwhash_argon2i_opslimit_max :: CSize++foreign import ccall "crypto_pwhash_argon2i_opslimit_interactive"+  c_crypto_pwhash_argon2i_opslimit_interactive :: CSize++foreign import ccall "crypto_pwhash_argon2i_opslimit_moderate"+  c_crypto_pwhash_argon2i_opslimit_moderate :: CSize++foreign import ccall "crypto_pwhash_argon2i_opslimit_sensitive"+  c_crypto_pwhash_argon2i_opslimit_sensitive :: CSize++foreign import ccall "crypto_pwhash_argon2i_passwd_min"+  c_crypto_pwhash_argon2i_passwd_min :: CSize++foreign import ccall "crypto_pwhash_argon2i_passwd_max"+  c_crypto_pwhash_argon2i_passwd_max :: CSize++foreign import ccall "crypto_pwhash_argon2i_saltbytes"+  c_crypto_pwhash_argon2i_saltbytes :: CSize++foreign import ccall "crypto_pwhash_argon2i_strbytes"+  c_crypto_pwhash_argon2i_strbytes :: CSize++foreign import ccall "crypto_pwhash_argon2i_strprefix"+  c_crypto_pwhash_argon2i_strprefix :: CSize
+ src/Crypto/Saltine/Internal/ScalarMult.hs view
@@ -0,0 +1,91 @@+{-# LANGUAGE DeriveDataTypeable, GeneralizedNewtypeDeriving, DeriveGeneric, ForeignFunctionInterface #-}+-- |+-- Module      : Crypto.Saltine.Internal.ScalarMult+-- Copyright   : (c) Max Amanshauser 2021+-- License     : MIT+--+-- Maintainer  : max@lambdalifting.org+-- Stability   : experimental+-- Portability : non-portable+--+module Crypto.Saltine.Internal.ScalarMult (+    scalarmult_bytes+  , scalarmult_scalarbytes+  , c_scalarmult+  , c_scalarmult_base+  , GroupElement(..)+  , Scalar(..)+) where++import Control.DeepSeq+import Crypto.Saltine.Class+import Crypto.Saltine.Internal.Util as U+import Data.ByteString              (ByteString)+import Data.Data                    (Data, Typeable)+import Data.Hashable                (Hashable)+import Foreign.C+import Foreign.Ptr+import GHC.Generics                 (Generic)++import qualified Data.ByteString as S+++-- | A group element.+newtype GroupElement = GE { unGE :: ByteString } deriving (Eq, Ord, Hashable, Data, Typeable, Generic, NFData)+instance Show GroupElement where+    show = bin2hex . encode++instance IsEncoding GroupElement where+  decode v = if S.length v == scalarmult_bytes+           then Just (GE v)+           else Nothing+  {-# INLINE decode #-}+  encode (GE v) = v+  {-# INLINE encode #-}++-- | A scalar integer.+newtype Scalar       = Sc { unSc :: ByteString } deriving (Eq, Ord, Hashable, Data, Typeable, Generic, NFData)+instance Show Scalar where+    show = bin2hex . encode++instance IsEncoding Scalar where+  decode v = if S.length v == scalarmult_scalarbytes+           then Just (Sc v)+           else Nothing+  {-# INLINE decode #-}+  encode (Sc v) = v+  {-# INLINE encode #-}+++scalarmult_bytes, scalarmult_scalarbytes :: Int++-- ScalarMult+-- | Size of a group element string representation for+-- @crypto_scalarmult@.+scalarmult_bytes = fromIntegral c_crypto_scalarmult_bytes+-- | Size of a integer string representation for @crypto_scalarmult@.+scalarmult_scalarbytes = fromIntegral c_crypto_scalarmult_scalarbytes++-- src/libsodium/crypto_scalarmult/crypto_scalarmult.c+foreign import ccall "crypto_scalarmult_bytes"+  c_crypto_scalarmult_bytes :: CSize+foreign import ccall "crypto_scalarmult_scalarbytes"+  c_crypto_scalarmult_scalarbytes :: CSize++foreign import ccall "crypto_scalarmult"+  c_scalarmult :: Ptr CChar+               -- ^ Output group element buffer+               -> Ptr CChar+               -- ^ Input integer buffer+               -> Ptr CChar+               -- ^ Input group element buffer+               -> IO CInt+               -- ^ Always 0++foreign import ccall "crypto_scalarmult_base"+  c_scalarmult_base :: Ptr CChar+                    -- ^ Output group element buffer+                    -> Ptr CChar+                    -- ^ Input integer buffer+                    -> IO CInt+                    -- ^ Always 0
+ src/Crypto/Saltine/Internal/SecretBox.hs view
@@ -0,0 +1,179 @@+{-# LANGUAGE DeriveDataTypeable, GeneralizedNewtypeDeriving, DeriveGeneric, ForeignFunctionInterface #-}+-- |+-- Module      : Crypto.Saltine.Internal.SecretBox+-- Copyright   : (c) Max Amanshauser 2021+-- License     : MIT+--+-- Maintainer  : max@lambdalifting.org+-- Stability   : experimental+-- Portability : non-portable+--+module Crypto.Saltine.Internal.SecretBox (+  secretbox_keybytes,+  secretbox_noncebytes,+  secretbox_macbytes,+  secretbox_zerobytes,+  secretbox_boxzerobytes,+  c_secretbox,+  c_secretbox_detached,+  c_secretbox_open,+  c_secretbox_open_detached,+  Key(..),+  Nonce(..),+  Authenticator(..)+) 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++secretbox_keybytes, secretbox_noncebytes, secretbox_macbytes, secretbox_zerobytes, secretbox_boxzerobytes :: Int++-- | An opaque 'secretbox' 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 = "SecretBox.Key {hashesTo = \"" <> (bin2hex . shorthash nullShKey $ encode k) <> "}\""++instance IsEncoding Key where+  decode v = if S.length v == secretbox_keybytes+           then Just (Key v)+           else Nothing+  {-# INLINE decode #-}+  encode (Key v) = v+  {-# INLINE encode #-}++-- | An opaque 'secretbox' nonce.+newtype Nonce = Nonce { unNonce :: ByteString } deriving (Eq, Ord, Hashable, Data, Typeable, Generic, NFData)+instance Show Nonce where+    show k = "SecretBox.Nonce " <> bin2hex (encode k)++instance IsEncoding Nonce where+  decode v = if S.length v == secretbox_noncebytes+           then Just (Nonce v)+           else Nothing+  {-# INLINE decode #-}+  encode (Nonce v) = v+  {-# INLINE encode #-}++instance IsNonce Nonce where+  zero            = Nonce (S.replicate secretbox_noncebytes 0)+  nudge (Nonce n) = Nonce (nudgeBS n)+++-- | An Authenticator for a Message+newtype Authenticator = Au { unAu :: ByteString } deriving (Eq, Ord, Data, Typeable, Hashable, Generic, NFData)+instance Show Authenticator where+    show k = "Sign.Authenticator " <> bin2hex (encode k)++instance IsEncoding Authenticator where+  decode v = if S.length v == secretbox_macbytes+           then Just (Au v)+           else Nothing+  {-# INLINE decode #-}+  encode (Au v) = v+  {-# INLINE encode #-}+++-- | Size of a @crypto_secretbox@ secret key+secretbox_keybytes     = fromIntegral c_crypto_secretbox_keybytes+-- | Size of a @crypto_secretbox@ nonce+secretbox_noncebytes   = fromIntegral c_crypto_secretbox_noncebytes+-- | Size of a @crypto_secretbox@ mac+secretbox_macbytes     = fromIntegral c_crypto_secretbox_macbytes+-- | Size of 0-padding prepended to messages before using+-- @crypto_secretbox@ or after using @crypto_secretbox_open@+secretbox_zerobytes    = fromIntegral c_crypto_secretbox_zerobytes+-- | Size of 0-padding prepended to ciphertext before using+-- @crypto_secretbox_open@ or after using @crypto_secretbox@+secretbox_boxzerobytes = fromIntegral c_crypto_secretbox_boxzerobytes++-- src/libsodium/crypto_secretbox/crypto_secretbox.c+foreign import ccall "crypto_secretbox_keybytes"+  c_crypto_secretbox_keybytes :: CSize+foreign import ccall "crypto_secretbox_noncebytes"+  c_crypto_secretbox_noncebytes :: CSize+foreign import ccall "crypto_secretbox_macbytes"+  c_crypto_secretbox_macbytes :: CSize+foreign import ccall "crypto_secretbox_zerobytes"+  c_crypto_secretbox_zerobytes :: CSize+foreign import ccall "crypto_secretbox_boxzerobytes"+  c_crypto_secretbox_boxzerobytes :: CSize++-- | The secretbox C API uses 0-padded C strings. Always returns 0.+foreign import ccall "crypto_secretbox"+  c_secretbox+    :: Ptr CChar+    -- ^ Cipher 0-padded output buffer+    -> Ptr CChar+    -- ^ Constant 0-padded message input buffer+    -> CULLong+    -- ^ Length of message input buffer (incl. 0s)+    -> Ptr CChar+    -- ^ Constant nonce buffer+    -> Ptr CChar+    -- ^ Constant key buffer+    -> IO CInt++-- | The secretbox_detached C API uses C strings. Always returns 0.+foreign import ccall "crypto_secretbox_detached"+  c_secretbox_detached+    :: Ptr CChar+    -- ^ Ciphertext output buffer+    -> Ptr CChar+    -- ^ Authentication tag output buffer+    -> Ptr CChar+    -- ^ Constant message input buffer+    -> CULLong+    -- ^ Length of message input buffer (incl. 0s)+    -> Ptr CChar+    -- ^ Constant nonce buffer+    -> Ptr CChar+    -- ^ Constant key buffer+    -> IO CInt++-- | The secretbox C API uses 0-padded C strings. Returns 0 if+-- successful or -1 if verification failed.+foreign import ccall "crypto_secretbox_open"+  c_secretbox_open+    :: Ptr CChar+    -- ^ Message 0-padded output buffer+    -> Ptr CChar+    -- ^ Constant 0-padded message input buffer+    -> CULLong+    -- ^ Length of message input buffer (incl. 0s)+    -> Ptr CChar+    -- ^ Constant nonce buffer+    -> Ptr CChar+    -- ^ Constant key buffer+    -> IO CInt++-- | The secretbox C API uses C strings. Returns 0 if+-- successful or -1 if verification failed.+foreign import ccall "crypto_secretbox_open_detached"+  c_secretbox_open_detached+    :: Ptr CChar+    -- ^ Message output buffer+    -> Ptr CChar+    -- ^ Constant ciphertext input buffer+    -> Ptr CChar+    -- ^ Constant auth tag input buffer+    -> CULLong+    -- ^ Length of ciphertext input buffer+    -> Ptr CChar+    -- ^ Constant nonce buffer+    -> Ptr CChar+    -- ^ Constant key buffer+    -> IO CInt
+ src/Crypto/Saltine/Internal/Sign.hs view
@@ -0,0 +1,179 @@+{-# LANGUAGE DeriveDataTypeable, GeneralizedNewtypeDeriving, DeriveGeneric, ForeignFunctionInterface #-}+-- |+-- Module      : Crypto.Saltine.Internal.Sign+-- Copyright   : (c) Max Amanshauser 2021+-- License     : MIT+--+-- Maintainer  : max@lambdalifting.org+-- Stability   : experimental+-- Portability : non-portable+--+module Crypto.Saltine.Internal.Sign (+    sign_bytes+  , sign_publickeybytes+  , sign_secretkeybytes+  , c_sign_keypair+  , c_sign+  , c_sign_open+  , c_sign_detached+  , c_sign_verify_detached+  , SecretKey(..)+  , PublicKey(..)+  , Keypair(..)+  , Signature(..)+) 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 'box' cryptographic secret key.+newtype SecretKey = SK { unSK :: ByteString } deriving (Ord, Hashable, Data, Typeable, Generic, NFData)+instance Eq SecretKey where+    SK a == SK b = U.compare a b+instance Show SecretKey where+    show k = "Sign.SecretKey {hashesTo = \"" <> (bin2hex . shorthash nullShKey $ encode k) <> "}\""++instance IsEncoding SecretKey where+  decode v = if S.length v == sign_secretkeybytes+           then Just (SK v)+           else Nothing+  {-# INLINE decode #-}+  encode (SK v) = v+  {-# INLINE encode #-}++-- | An opaque 'box' cryptographic public key.+newtype PublicKey = PK { unPK :: ByteString } deriving (Ord, Data, Typeable, Hashable, Generic, NFData)+instance Eq PublicKey where+    PK a == PK b = U.compare a b+instance Show PublicKey where+    show k = "Sign.PublicKey {hashesTo = \"" <> (bin2hex . shorthash nullShKey $ encode k) <> "}\""++instance IsEncoding PublicKey where+  decode v = if S.length v == sign_publickeybytes+           then Just (PK v)+           else Nothing+  {-# INLINE decode #-}+  encode (PK v) = v+  {-# INLINE encode #-}++-- | A convenience type for keypairs+data Keypair = Keypair {+    secretKey :: SecretKey+  , publicKey :: PublicKey+} deriving (Ord, Data, Typeable, Generic)++instance Eq Keypair where+    kp1 == kp2 = U.compare (encode $ secretKey kp1) (encode $ secretKey kp2)+            !&&! U.compare (encode $ publicKey kp1) (encode $ publicKey kp2)++instance Hashable Keypair+instance NFData   Keypair+++-- | A signature for a Message+newtype Signature = Signature { unSignature :: ByteString } deriving (Ord, Data, Typeable, Hashable, Generic, NFData)+instance Eq Signature where+    Signature a == Signature b = U.compare a b+instance Show Signature where+    show k = "Sign.Signature " <> bin2hex (encode k)++-- | Actual signatures may be shorter, but not when generated with saltine.+instance IsEncoding Signature where+  decode v = if S.length v == sign_bytes+           then Just (Signature v)+           else Nothing+  {-# INLINE decode #-}+  encode (Signature s) = s+  {-# INLINE encode #-}++sign_bytes, sign_publickeybytes, sign_secretkeybytes :: Int++-- Signatures+-- | The maximum size of a signature prepended to a message to form a+-- signed message.+sign_bytes          = fromIntegral c_crypto_sign_bytes+-- | The size of a public key for signing verification+sign_publickeybytes = fromIntegral c_crypto_sign_publickeybytes+-- | The size of a secret key for signing+sign_secretkeybytes = fromIntegral c_crypto_sign_secretkeybytes++-- src/libsodium/crypto_sign/crypto_sign.c+foreign import ccall "crypto_sign_bytes"+  c_crypto_sign_bytes :: CSize+foreign import ccall "crypto_sign_publickeybytes"+  c_crypto_sign_publickeybytes :: CSize+foreign import ccall "crypto_sign_secretkeybytes"+  c_crypto_sign_secretkeybytes :: CSize+++foreign import ccall "crypto_sign_keypair"+  c_sign_keypair :: Ptr CChar+                 -- ^ Public key output buffer+                 -> Ptr CChar+                 -- ^ Secret key output buffer+                 -> IO CInt+                 -- ^ Always 0++foreign import ccall "crypto_sign"+  c_sign :: Ptr CChar+         -- ^ Signed message output buffer+         -> Ptr CULLong+         -- ^ Length of signed message+         -> Ptr CChar+         -- ^ Constant message buffer+         -> CULLong+         -- ^ Length of message input buffer+         -> Ptr CChar+         -- ^ Constant secret key buffer+         -> IO CInt+         -- ^ Always 0++foreign import ccall "crypto_sign_open"+  c_sign_open :: Ptr CChar+              -- ^ Message output buffer+              -> Ptr CULLong+              -- ^ Length of message+              -> Ptr CChar+              -- ^ Constant signed message buffer+              -> CULLong+              -- ^ Length of signed message buffer+              -> Ptr CChar+              -- ^ Public key buffer+              -> IO CInt+              -- ^ 0 if signature is verifiable, -1 otherwise++foreign import ccall "crypto_sign_detached"+    c_sign_detached :: Ptr CChar+                    -- ^ Signature output buffer+                    -> Ptr CULLong+                    -- ^ Length of the signature+                    -> Ptr CChar+                    -- ^ Constant message buffer+                    -> CULLong+                    -- ^ Length of message buffer+                    -> Ptr CChar+                    -- ^ Constant secret key buffer+                    -> IO CInt+foreign import ccall "crypto_sign_verify_detached"+    c_sign_verify_detached :: Ptr CChar+                           -- ^ Signature buffer+                           -> Ptr CChar+                           -- ^ Constant signed message buffer+                           -> CULLong+                           -- ^ Length of signed message buffer+                           -> Ptr CChar+                           -- ^ Public key buffer+                           -> IO CInt
+ src/Crypto/Saltine/Internal/Stream.hs view
@@ -0,0 +1,107 @@+{-# 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
src/Crypto/Saltine/Internal/Util.hs view
@@ -1,16 +1,24 @@-module Crypto.Saltine.Internal.Util where+{-# LANGUAGE BangPatterns #-} -import           Foreign.C-import           Foreign.Marshal.Alloc    (mallocBytes)-import           Foreign.Ptr-import           System.IO.Unsafe+module Crypto.Saltine.Internal.Util (+    module Crypto.Saltine.Internal.Util+  , withCString+  , allocaBytes+)+where -import           Control.Applicative-import qualified Data.ByteString        as S-import           Data.ByteString          (ByteString)-import           Data.ByteString.Unsafe-import           Data.Monoid+import Data.ByteString          (ByteString)+import Data.ByteString.Unsafe+import Data.Monoid+import Foreign.C+import Foreign.Marshal.Alloc    (mallocBytes, allocaBytes)+import Foreign.Ptr+import GHC.Word                 (Word8)+import System.IO.Unsafe +import qualified Data.ByteString       as S+import qualified Data.ByteString.Char8 as S8+ -- | Returns @Nothing@ if the subtraction would result in an -- underflow or a negative number. safeSubtract :: (Ord a, Num a) => a -> a -> Maybe a@@ -63,6 +71,12 @@   where go 0 = True         go _ = False +withCStrings :: [String] -> ([CString] -> IO a) -> IO a+withCStrings = foldr (\v kk -> \k -> (withCString v) (\a -> kk (\as -> k (a:as)))) ($ [])++withCStringLens :: [String] -> ([CStringLen] -> IO a) -> IO a+withCStringLens = foldr (\v kk -> \k -> (withCStringLen v) (\a -> kk (\as -> k (a:as)))) ($ [])+ -- | Convenience function for accessing constant C strings constByteStrings :: [ByteString] -> ([CStringLen] -> IO b) -> IO b constByteStrings =@@ -77,6 +91,18 @@   out <- unsafeUseAsCString bs k   return (out, bs) ++-- | Sometimes we have to deal with variable-length strings+buildUnsafeVariableByteString' :: Int -> (Ptr CChar -> IO b) -> IO (b, ByteString)+buildUnsafeVariableByteString' n k = do+  ph  <- mallocBytes n+  out <- k ph+  bs  <- unsafePackMallocCString ph+  return (out, bs)++buildUnsafeVariableByteString :: Int -> (Ptr CChar -> IO b) -> (b, ByteString)+buildUnsafeVariableByteString n = unsafePerformIO . buildUnsafeVariableByteString' n+ -- | Extremely unsafe function, use with utmost care! Builds a new -- ByteString using a ccall which is given access to the raw underlying -- pointer. Overwrites are UNCHECKED and 'unsafePerformIO' is used so@@ -96,3 +122,67 @@  foreign import ccall "randombytes_buf"   c_randombytes_buf :: Ptr CChar -> CInt -> IO ()++-- | Constant time memory comparison+foreign import ccall unsafe "sodium_memcmp"+  c_sodium_memcmp+    :: Ptr CChar -- a+    -> Ptr CChar -- b+    -> CInt   -- Length+    -> IO CInt++foreign import ccall unsafe "sodium_malloc"+  c_sodium_malloc+    :: CSize -> IO (Ptr a)++foreign import ccall unsafe "sodium_free"+  c_sodium_free+    :: Ptr Word8 -> IO ()++-- | Not sure yet what to use this for+buildUnsafeScrubbedByteString' :: Int -> (Ptr CChar -> IO b) -> IO (b,ByteString)+buildUnsafeScrubbedByteString' n k = do+    p <- c_sodium_malloc (fromIntegral n)++    bs <- unsafePackCStringFinalizer p n (c_sodium_free p)+    out <- unsafeUseAsCString bs k+    pure (out,bs)++-- | Not sure yet what to use this for+buildUnsafeScrubbedByteString :: Int -> (Ptr CChar -> IO b) -> (b,ByteString)+buildUnsafeScrubbedByteString n = unsafePerformIO . buildUnsafeScrubbedByteString' n++-- | Constant-time comparison+compare :: ByteString -> ByteString -> Bool+compare a b =+    (S.length a == S.length b) && unsafePerformIO (constByteStrings [a, b] $ \+        [(bsa, _), (bsb,_)] ->+            (== 0) <$> c_sodium_memcmp bsa bsb (fromIntegral $ S.length a))++-- | bin2hex conversion for showing various binary types+foreign import ccall unsafe "sodium_bin2hex"+  c_sodium_bin2hex+    :: Ptr CChar            -- Target zone+    -> CInt                 -- Max. length of target string (must be min. bin_len * 2 + 1)+    -> Ptr CChar            -- Source+    -> CInt                 -- Source length+    -> IO (Ptr CChar)++bin2hex :: ByteString -> String+bin2hex bs = let tlen = S.length bs * 2 + 1 in+    S8.unpack . S8.init . snd . buildUnsafeByteString tlen $ \t ->+        constByteStrings [bs] $ \+            [(pbs, _)] ->+                c_sodium_bin2hex t (fromIntegral tlen) pbs (fromIntegral $ S.length bs)++uncurry3 :: (a -> b -> c -> d) -> ((a, b, c) -> d)+uncurry3 f ~(a,b,c) = f a b c++uncurry5 :: (a -> b -> c -> d -> e -> f) -> ((a, b, c, d, e) -> f)+uncurry5 f ~(a,b,c,d,e) = f a b c d e++(!&&!) :: Bool -> Bool -> Bool+(!&&!) !a !b = a && b++(!||!) :: Bool -> Bool -> Bool+(!||!) !a !b = a || b
+ tests/AEAD/AES256GCMProperties.hs view
@@ -0,0 +1,125 @@+{-# LANGUAGE OverloadedStrings #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}++module AEAD.AES256GCMProperties (+  testAEADAES+  ) where++import           Util+import           Crypto.Saltine.Core.AEAD.AES256GCM+import           Crypto.Saltine.Class (decode)+import           Crypto.Saltine.Internal.AEAD.AES256GCM as Bytes++import qualified Data.ByteString                      as S+import           Data.Maybe (fromJust)+import           Test.Framework.Providers.QuickCheck2+import           Test.Framework+import           Test.QuickCheck (Property, (==>))+import           Test.QuickCheck.Arbitrary++instance Arbitrary Nonce where+    arbitrary =+        do bs <- S.pack <$> vector Bytes.aead_aes256gcm_npubbytes+           pure $ fromJust (decode bs)++instance Arbitrary Key where+    arbitrary =+        do bs <- S.pack <$> vector Bytes.aead_aes256gcm_keybytes+           pure $ fromJust (decode bs)++-- | Ciphertext can be decrypted+rightInverseProp :: Key -> Nonce -> Message -> Message -> Bool+rightInverseProp k n (Message bs) (Message aad) =+  Just bs == aeadOpen k n (aead k n bs aad) aad++-- | Detached ciphertext/tag can be decrypted+rightInverseDetachedProp :: Key -> Nonce -> Message -> Message -> Bool+rightInverseDetachedProp k n (Message bs) (Message aad) =+  let (tag,ct) = aeadDetached k n bs aad+  in Just bs == aeadOpenDetached k n tag ct aad++-- | Ciphertext cannot be decrypted if the ciphertext is perturbed+rightInverseFailureProp :: Key -> Nonce -> Message -> Message -> Perturb -> Property+rightInverseFailureProp k n (Message bs) (Message aad) p =+  S.length bs /= 0 ==>+   let ct = aead k n bs aad+       fakeCT = perturb ct p+   in fakeCT /= ct ==> Nothing == aeadOpen k n fakeCT aad++-- | Ciphertext cannot be decrypted if the aad is perturbed+rightInverseAADFailureProp :: Key -> Nonce -> Message -> Message -> Message -> Property+rightInverseAADFailureProp k n (Message bs) (Message aad) (Message aad2) =+  aad /= aad2 ==> Nothing == aeadOpen k n (aead k n bs aad) aad2++-- | Ciphertext cannot be decrypted if the tag is perturbed+rightInverseTagFailureProp :: Key -> Nonce -> Message -> Message -> Message -> Property+rightInverseTagFailureProp k n (Message bs) (Message aad) (Message newTag) =+   let (tag,ct) = aeadDetached k n bs aad+   in newTag /= tag ==> Nothing == aeadOpenDetached k n newTag ct aad++-- | Ciphertext cannot be decrypted if the ciphertext is perturbed+rightInverseFailureDetachedProp :: Key -> Nonce -> Message -> Message -> Perturb -> Property+rightInverseFailureDetachedProp k n (Message bs) (Message aad) p@(Perturb pBytes) =+  let (tag,ct) = aeadDetached k n bs aad+  in S.length bs > length pBytes ==>+        Nothing == aeadOpenDetached k n tag (perturb ct p) aad++-- | Ciphertext cannot be decrypted with a different key+cannotDecryptKeyProp :: Key -> Key -> Nonce -> Message -> Message -> Property+cannotDecryptKeyProp k1 k2 n (Message bs) (Message aad) =+  let ct = aead k1 n bs aad+  in k1 /= k2 ==> Nothing == aeadOpen k2 n ct aad++-- | Ciphertext cannot be decrypted with a different key+cannotDecryptKeyDetachedProp :: Key -> Key -> Nonce -> Message -> Message -> Property+cannotDecryptKeyDetachedProp k1 k2 n (Message bs) (Message aad) =+  let (tag,ct) = aeadDetached k1 n bs aad+  in k1 /= k2 ==> Nothing == aeadOpenDetached k2 n tag ct aad++-- | Ciphertext cannot be decrypted with a different nonce+cannotDecryptNonceProp :: Key -> Nonce -> Nonce -> Message -> Message -> Property+cannotDecryptNonceProp k n1 n2 (Message bs) (Message aad) =+  n1 /= n2 ==> Nothing == aeadOpen k n2 (aead k n1 bs aad) aad++-- | Ciphertext cannot be decrypted with a different nonce+cannotDecryptNonceDetachedProp :: Key -> Nonce -> Nonce -> Message -> Message -> Property+cannotDecryptNonceDetachedProp k n1 n2 (Message bs) (Message aad) =+  let (tag,ct) = aeadDetached k n1 bs aad+  in n1 /= n2 ==> Nothing == aeadOpenDetached k n2 tag ct aad++testAEADAES :: Test+testAEADAES = buildTest $++  return $ testGroup "...Internal.AEAD.AES256GCM" $ if not aead_aes256gcm_available then [] else [+    testProperty "Can decrypt ciphertext" rightInverseProp,++    testProperty "Can decrypt ciphertext (detached)" rightInverseDetachedProp,++    testGroup "Cannot decrypt ciphertext when..." [++      testProperty "... ciphertext is perturbed"+      $ rightInverseFailureProp,++      testProperty "... AAD is perturbed"+      $ rightInverseAADFailureProp,++      testProperty "... ciphertext is perturbed (detached)"+      $ rightInverseFailureDetachedProp,++      testProperty "... tag is perturbed (detached)"+      $ rightInverseTagFailureProp,++      testProperty "... using the wrong key"+      $ cannotDecryptKeyProp,++      testProperty "... using the wrong key (detached)"+      $ cannotDecryptKeyDetachedProp,++      testProperty "... using the wrong nonce"+      $ cannotDecryptNonceProp,++      testProperty "... using the wrong nonce (detached"+      $ cannotDecryptNonceDetachedProp++      ]+    ]
+ tests/AEAD/ChaCha20Poly1305IETFProperties.hs view
@@ -0,0 +1,128 @@+{-# LANGUAGE OverloadedStrings #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}++module AEAD.ChaCha20Poly1305IETFProperties (+  testAEADIETF+  ) where++import           Util+import           Crypto.Saltine.Core.AEAD.ChaCha20Poly1305IETF+import           Crypto.Saltine.Class (decode)+import           Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305IETF as Bytes++import qualified Data.ByteString                      as S+import           Data.Maybe (fromJust)+import           Test.Framework.Providers.QuickCheck2+import           Test.Framework+import           Test.QuickCheck (Property, (==>))+import           Test.QuickCheck.Arbitrary++instance Arbitrary Nonce where+    arbitrary =+        do bs <- S.pack <$> vector Bytes.aead_chacha20poly1305_ietf_npubbytes+           pure $ fromJust (decode bs)++instance Arbitrary Key where+    arbitrary =+        do bs <- S.pack <$> vector Bytes.aead_chacha20poly1305_ietf_keybytes+           pure $ fromJust (decode bs)++-- | Ciphertext can be decrypted+rightInverseProp :: Key -> Nonce -> Message -> Message -> Bool+rightInverseProp k n (Message bs) (Message aad) =+  Just bs == aeadOpen k n (aead k n bs aad) aad++-- | Detached ciphertext/tag can be decrypted+rightInverseDetachedProp :: Key -> Nonce -> Message -> Message -> Bool+rightInverseDetachedProp k n (Message bs) (Message aad) =+  let (tag,ct) = aeadDetached k n bs aad+  in Just bs == aeadOpenDetached k n tag ct aad++-- | Ciphertext cannot be decrypted if the ciphertext is perturbed+rightInverseFailureProp :: Key -> Nonce -> Message -> Message -> Perturb -> Property+rightInverseFailureProp k n (Message bs) (Message aad) p =+  S.length bs /= 0 ==>+   let ct = aead k n bs aad+       fakeCT = perturb ct p+   in fakeCT /= ct ==> Nothing == aeadOpen k n fakeCT aad++-- | Ciphertext cannot be decrypted if the aad is perturbed+rightInverseAADFailureProp :: Key -> Nonce -> Message -> Message -> Message -> Property+rightInverseAADFailureProp k n (Message bs) (Message aad) (Message aad2) =+  aad /= aad2 ==> Nothing == aeadOpen k n (aead k n bs aad) aad2++-- | Ciphertext cannot be decrypted if the tag is perturbed+rightInverseTagFailureProp :: Key -> Nonce -> Message -> Message -> Message -> Property+rightInverseTagFailureProp k n (Message bs) (Message aad) (Message newTag) =+   let (tag,ct) = aeadDetached k n bs aad+   in newTag /= tag ==> Nothing == aeadOpenDetached k n newTag ct aad++-- | Ciphertext cannot be decrypted if the ciphertext is perturbed+rightInverseFailureDetachedProp :: Key -> Nonce -> Message -> Message -> Perturb -> Property+rightInverseFailureDetachedProp k n (Message bs) (Message aad) p@(Perturb pBytes) =+  let (tag,ct) = aeadDetached k n bs aad+  in S.length bs > length pBytes ==>+        Nothing == aeadOpenDetached k n tag (perturb ct p) aad++-- | Ciphertext cannot be decrypted with a different key+cannotDecryptKeyProp :: Key -> Key -> Nonce -> Message -> Message -> Property+cannotDecryptKeyProp k1 k2 n (Message bs) (Message aad) =+  let ct = aead k1 n bs aad+  in k1 /= k2 ==> Nothing == aeadOpen k2 n ct aad++-- | Ciphertext cannot be decrypted with a different key+cannotDecryptKeyDetachedProp :: Key -> Key -> Nonce -> Message -> Message -> Property+cannotDecryptKeyDetachedProp k1 k2 n (Message bs) (Message aad) =+  let (tag,ct) = aeadDetached k1 n bs aad+  in k1 /= k2 ==> Nothing == aeadOpenDetached k2 n tag ct aad++-- | Ciphertext cannot be decrypted with a different nonce+cannotDecryptNonceProp :: Key -> Nonce -> Nonce -> Message -> Message -> Property+cannotDecryptNonceProp k n1 n2 (Message bs) (Message aad) =+  n1 /= n2 ==> Nothing == aeadOpen k n2 (aead k n1 bs aad) aad++-- | Ciphertext cannot be decrypted with a different nonce+cannotDecryptNonceDetachedProp :: Key -> Nonce -> Nonce -> Message -> Message -> Property+cannotDecryptNonceDetachedProp k n1 n2 (Message bs) (Message aad) =+  let (tag,ct) = aeadDetached k n1 bs aad+  in n1 /= n2 ==> Nothing == aeadOpenDetached k n2 tag ct aad++testAEADIETF :: Test+testAEADIETF = buildTest $ do++  return $ testGroup "...Internal.AEAD.ChaCha20Poly1305IETF" [++    testProperty "Can decrypt ciphertext"+    $ rightInverseProp,++    testProperty "Can decrypt ciphertext (detached)"+    $ rightInverseDetachedProp,++    testGroup "Cannot decrypt ciphertext when..." [++      testProperty "... ciphertext is perturbed"+      $ rightInverseFailureProp,++      testProperty "... AAD is perturbed"+      $ rightInverseAADFailureProp,++      testProperty "... ciphertext is perturbed (detached)"+      $ rightInverseFailureDetachedProp,++      testProperty "... tag is perturbed (detached)"+      $ rightInverseTagFailureProp,++      testProperty "... using the wrong key"+      $ cannotDecryptKeyProp,++      testProperty "... using the wrong key (detached)"+      $ cannotDecryptKeyDetachedProp,++      testProperty "... using the wrong nonce"+      $ cannotDecryptNonceProp,++      testProperty "... using the wrong nonce (detached"+      $ cannotDecryptNonceDetachedProp++      ]+    ]
+ tests/AEAD/ChaCha20Poly1305Properties.hs view
@@ -0,0 +1,128 @@+{-# LANGUAGE OverloadedStrings #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}++module AEAD.ChaCha20Poly1305Properties (+  testAEADChaCha20+  ) where++import           Util+import           Crypto.Saltine.Core.AEAD.ChaCha20Poly1305IETF+import           Crypto.Saltine.Class (decode)+import           Crypto.Saltine.Internal.AEAD.ChaCha20Poly1305IETF as Bytes++import qualified Data.ByteString                      as S+import           Data.Maybe (fromJust)+import           Test.Framework.Providers.QuickCheck2+import           Test.Framework+import           Test.QuickCheck (Property, (==>))+import           Test.QuickCheck.Arbitrary++instance Arbitrary Nonce where+    arbitrary =+        do bs <- S.pack <$> vector Bytes.aead_chacha20poly1305_ietf_npubbytes+           pure $ fromJust (decode bs)++instance Arbitrary Key where+    arbitrary =+        do bs <- S.pack <$> vector Bytes.aead_chacha20poly1305_ietf_keybytes+           pure $ fromJust (decode bs)++-- | Ciphertext can be decrypted+rightInverseProp :: Key -> Nonce -> Message -> Message -> Bool+rightInverseProp k n (Message bs) (Message aad) =+  Just bs == aeadOpen k n (aead k n bs aad) aad++-- | Detached ciphertext/tag can be decrypted+rightInverseDetachedProp :: Key -> Nonce -> Message -> Message -> Bool+rightInverseDetachedProp k n (Message bs) (Message aad) =+  let (tag,ct) = aeadDetached k n bs aad+  in Just bs == aeadOpenDetached k n tag ct aad++-- | Ciphertext cannot be decrypted if the ciphertext is perturbed+rightInverseFailureProp :: Key -> Nonce -> Message -> Message -> Perturb -> Property+rightInverseFailureProp k n (Message bs) (Message aad) p =+  S.length bs /= 0 ==>+   let ct = aead k n bs aad+       fakeCT = perturb ct p+   in fakeCT /= ct ==> Nothing == aeadOpen k n fakeCT aad++-- | Ciphertext cannot be decrypted if the aad is perturbed+rightInverseAADFailureProp :: Key -> Nonce -> Message -> Message -> Message -> Property+rightInverseAADFailureProp k n (Message bs) (Message aad) (Message aad2) =+  aad /= aad2 ==> Nothing == aeadOpen k n (aead k n bs aad) aad2++-- | Ciphertext cannot be decrypted if the tag is perturbed+rightInverseTagFailureProp :: Key -> Nonce -> Message -> Message -> Message -> Property+rightInverseTagFailureProp k n (Message bs) (Message aad) (Message newTag) =+   let (tag,ct) = aeadDetached k n bs aad+   in newTag /= tag ==> Nothing == aeadOpenDetached k n newTag ct aad++-- | Ciphertext cannot be decrypted if the ciphertext is perturbed+rightInverseFailureDetachedProp :: Key -> Nonce -> Message -> Message -> Perturb -> Property+rightInverseFailureDetachedProp k n (Message bs) (Message aad) p@(Perturb pBytes) =+  let (tag,ct) = aeadDetached k n bs aad+  in S.length bs > length pBytes ==>+        Nothing == aeadOpenDetached k n tag (perturb ct p) aad++-- | Ciphertext cannot be decrypted with a different key+cannotDecryptKeyProp :: Key -> Key -> Nonce -> Message -> Message -> Property+cannotDecryptKeyProp k1 k2 n (Message bs) (Message aad) =+  let ct = aead k1 n bs aad+  in k1 /= k2 ==> Nothing == aeadOpen k2 n ct aad++-- | Ciphertext cannot be decrypted with a different key+cannotDecryptKeyDetachedProp :: Key -> Key -> Nonce -> Message -> Message -> Property+cannotDecryptKeyDetachedProp k1 k2 n (Message bs) (Message aad) =+  let (tag,ct) = aeadDetached k1 n bs aad+  in k1 /= k2 ==> Nothing == aeadOpenDetached k2 n tag ct aad++-- | Ciphertext cannot be decrypted with a different nonce+cannotDecryptNonceProp :: Key -> Nonce -> Nonce -> Message -> Message -> Property+cannotDecryptNonceProp k n1 n2 (Message bs) (Message aad) =+  n1 /= n2 ==> Nothing == aeadOpen k n2 (aead k n1 bs aad) aad++-- | Ciphertext cannot be decrypted with a different nonce+cannotDecryptNonceDetachedProp :: Key -> Nonce -> Nonce -> Message -> Message -> Property+cannotDecryptNonceDetachedProp k n1 n2 (Message bs) (Message aad) =+  let (tag,ct) = aeadDetached k n1 bs aad+  in n1 /= n2 ==> Nothing == aeadOpenDetached k n2 tag ct aad++testAEADChaCha20 :: Test+testAEADChaCha20 = buildTest $ do++  return $ testGroup "...Internal.AEAD.ChaCha20Poly1305" [++    testProperty "Can decrypt ciphertext"+    $ rightInverseProp,++    testProperty "Can decrypt ciphertext (detached)"+    $ rightInverseDetachedProp,++    testGroup "Cannot decrypt ciphertext when..." [++      testProperty "... ciphertext is perturbed"+      $ rightInverseFailureProp,++      testProperty "... AAD is perturbed"+      $ rightInverseAADFailureProp,++      testProperty "... ciphertext is perturbed (detached)"+      $ rightInverseFailureDetachedProp,++      testProperty "... tag is perturbed (detached)"+      $ rightInverseTagFailureProp,++      testProperty "... using the wrong key"+      $ cannotDecryptKeyProp,++      testProperty "... using the wrong key (detached)"+      $ cannotDecryptKeyDetachedProp,++      testProperty "... using the wrong nonce"+      $ cannotDecryptNonceProp,++      testProperty "... using the wrong nonce (detached"+      $ cannotDecryptNonceDetachedProp++      ]+    ]
+ tests/AEAD/XChaCha20Poly1305Properties.hs view
@@ -0,0 +1,128 @@+{-# LANGUAGE OverloadedStrings #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}++module AEAD.XChaCha20Poly1305Properties (+  testAEADXChaCha20+  ) where++import           Util+import           Crypto.Saltine.Core.AEAD.XChaCha20Poly1305+import           Crypto.Saltine.Class (decode)+import           Crypto.Saltine.Internal.AEAD.XChaCha20Poly1305 as Bytes++import qualified Data.ByteString                      as S+import           Data.Maybe (fromJust)+import           Test.Framework.Providers.QuickCheck2+import           Test.Framework+import           Test.QuickCheck (Property, (==>))+import           Test.QuickCheck.Arbitrary++instance Arbitrary Nonce where+    arbitrary =+        do bs <- S.pack <$> vector Bytes.aead_xchacha20poly1305_ietf_npubbytes+           pure $ fromJust (decode bs)++instance Arbitrary Key where+    arbitrary =+        do bs <- S.pack <$> vector Bytes.aead_xchacha20poly1305_ietf_keybytes+           pure $ fromJust (decode bs)++-- | Ciphertext can be decrypted+rightInverseProp :: Key -> Nonce -> Message -> Message -> Bool+rightInverseProp k n (Message bs) (Message aad) =+  Just bs == aeadOpen k n (aead k n bs aad) aad++-- | Detached ciphertext/tag can be decrypted+rightInverseDetachedProp :: Key -> Nonce -> Message -> Message -> Bool+rightInverseDetachedProp k n (Message bs) (Message aad) =+  let (tag,ct) = aeadDetached k n bs aad+  in Just bs == aeadOpenDetached k n tag ct aad++-- | Ciphertext cannot be decrypted if the ciphertext is perturbed+rightInverseFailureProp :: Key -> Nonce -> Message -> Message -> Perturb -> Property+rightInverseFailureProp k n (Message bs) (Message aad) p =+  S.length bs /= 0 ==>+   let ct = aead k n bs aad+       fakeCT = perturb ct p+   in fakeCT /= ct ==> Nothing == aeadOpen k n fakeCT aad++-- | Ciphertext cannot be decrypted if the aad is perturbed+rightInverseAADFailureProp :: Key -> Nonce -> Message -> Message -> Message -> Property+rightInverseAADFailureProp k n (Message bs) (Message aad) (Message aad2) =+  aad /= aad2 ==> Nothing == aeadOpen k n (aead k n bs aad) aad2++-- | Ciphertext cannot be decrypted if the tag is perturbed+rightInverseTagFailureProp :: Key -> Nonce -> Message -> Message -> Message -> Property+rightInverseTagFailureProp k n (Message bs) (Message aad) (Message newTag) =+   let (tag,ct) = aeadDetached k n bs aad+   in newTag /= tag ==> Nothing == aeadOpenDetached k n newTag ct aad++-- | Ciphertext cannot be decrypted if the ciphertext is perturbed+rightInverseFailureDetachedProp :: Key -> Nonce -> Message -> Message -> Perturb -> Property+rightInverseFailureDetachedProp k n (Message bs) (Message aad) p@(Perturb pBytes) =+  let (tag,ct) = aeadDetached k n bs aad+  in S.length bs > length pBytes ==>+        Nothing == aeadOpenDetached k n tag (perturb ct p) aad++-- | Ciphertext cannot be decrypted with a different key+cannotDecryptKeyProp :: Key -> Key -> Nonce -> Message -> Message -> Property+cannotDecryptKeyProp k1 k2 n (Message bs) (Message aad) =+  let ct = aead k1 n bs aad+  in k1 /= k2 ==> Nothing == aeadOpen k2 n ct aad++-- | Ciphertext cannot be decrypted with a different key+cannotDecryptKeyDetachedProp :: Key -> Key -> Nonce -> Message -> Message -> Property+cannotDecryptKeyDetachedProp k1 k2 n (Message bs) (Message aad) =+  let (tag,ct) = aeadDetached k1 n bs aad+  in k1 /= k2 ==> Nothing == aeadOpenDetached k2 n tag ct aad++-- | Ciphertext cannot be decrypted with a different nonce+cannotDecryptNonceProp :: Key -> Nonce -> Nonce -> Message -> Message -> Property+cannotDecryptNonceProp k n1 n2 (Message bs) (Message aad) =+  n1 /= n2 ==> Nothing == aeadOpen k n2 (aead k n1 bs aad) aad++-- | Ciphertext cannot be decrypted with a different nonce+cannotDecryptNonceDetachedProp :: Key -> Nonce -> Nonce -> Message -> Message -> Property+cannotDecryptNonceDetachedProp k n1 n2 (Message bs) (Message aad) =+  let (tag,ct) = aeadDetached k n1 bs aad+  in n1 /= n2 ==> Nothing == aeadOpenDetached k n2 tag ct aad++testAEADXChaCha20 :: Test+testAEADXChaCha20 = buildTest $ do++  return $ testGroup "...Internal.AEAD.XChaCha20Poly1305" [++    testProperty "Can decrypt ciphertext"+    $ rightInverseProp,++    testProperty "Can decrypt ciphertext (detached)"+    $ rightInverseDetachedProp,++    testGroup "Cannot decrypt ciphertext when..." [++      testProperty "... ciphertext is perturbed"+      $ rightInverseFailureProp,++      testProperty "... AAD is perturbed"+      $ rightInverseAADFailureProp,++      testProperty "... ciphertext is perturbed (detached)"+      $ rightInverseFailureDetachedProp,++      testProperty "... tag is perturbed (detached)"+      $ rightInverseTagFailureProp,++      testProperty "... using the wrong key"+      $ cannotDecryptKeyProp,++      testProperty "... using the wrong key (detached)"+      $ cannotDecryptKeyDetachedProp,++      testProperty "... using the wrong nonce"+      $ cannotDecryptNonceProp,++      testProperty "... using the wrong nonce (detached"+      $ cannotDecryptNonceDetachedProp++      ]+    ]
− tests/AEADProperties.hs
@@ -1,134 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}--module AEADProperties (-  testAEAD-  ) where--import           Util-import           Crypto.Saltine.Core.AEAD-import           Crypto.Saltine.Class (decode,encode)-import           Crypto.Saltine.Internal.ByteSizes as Bytes--import           Control.Applicative-import qualified Data.ByteString                      as S-import           Data.Maybe (fromJust)-import           Test.Framework.Providers.QuickCheck2-import           Test.Framework-import           Test.QuickCheck (Property, (==>))-import           Test.QuickCheck.Arbitrary--instance Arbitrary Nonce where-    arbitrary =-        do bs <- S.pack <$> vector Bytes.secretBoxNonce-           pure $ fromJust (decode bs)--instance Arbitrary Key where-    arbitrary =-        do bs <- S.pack <$> vector Bytes.secretBoxKey-           pure $ fromJust (decode bs)--instance Show Key where-    show = show . encode-instance Show Nonce where-    show = show . encode---- | Ciphertext can be decrypted-rightInverseProp :: Key -> Nonce -> Message -> Message -> Bool-rightInverseProp k n (Message bs) (Message aad) =-  Just bs == aeadOpen k n (aead k n bs aad) aad---- | Detached ciphertext/tag can be decrypted-rightInverseDetachedProp :: Key -> Nonce -> Message -> Message -> Bool-rightInverseDetachedProp k n (Message bs) (Message aad) =-  let (tag,ct) = aeadDetached k n bs aad-  in Just bs == aeadOpenDetached k n tag ct aad---- | Ciphertext cannot be decrypted if the ciphertext is perturbed-rightInverseFailureProp :: Key -> Nonce -> Message -> Message -> Perturb -> Property-rightInverseFailureProp k n (Message bs) (Message aad) p =-  S.length bs /= 0 ==>-   let ct = aead k n bs aad-       fakeCT = perturb ct p-   in fakeCT /= ct ==> Nothing == aeadOpen k n fakeCT aad---- | Ciphertext cannot be decrypted if the aad is perturbed-rightInverseAADFailureProp :: Key -> Nonce -> Message -> Message -> Message -> Property-rightInverseAADFailureProp k n (Message bs) (Message aad) (Message aad2) =-  aad /= aad2 ==> Nothing == aeadOpen k n (aead k n bs aad) aad2---- | Ciphertext cannot be decrypted if the tag is perturbed-rightInverseTagFailureProp :: Key -> Nonce -> Message -> Message -> Message -> Property-rightInverseTagFailureProp k n (Message bs) (Message aad) (Message newTag) =-   let (tag,ct) = aeadDetached k n bs aad-   in newTag /= tag ==> Nothing == aeadOpenDetached k n newTag ct aad---- | Ciphertext cannot be decrypted if the ciphertext is perturbed-rightInverseFailureDetachedProp :: Key -> Nonce -> Message -> Message -> Perturb -> Property-rightInverseFailureDetachedProp k n (Message bs) (Message aad) p@(Perturb pBytes) =-  let (tag,ct) = aeadDetached k n bs aad-  in S.length bs > length pBytes ==>-        Nothing == aeadOpenDetached k n tag (perturb ct p) aad---- | Ciphertext cannot be decrypted with a different key-cannotDecryptKeyProp :: Key -> Key -> Nonce -> Message -> Message -> Property-cannotDecryptKeyProp k1 k2 n (Message bs) (Message aad) =-  let ct = aead k1 n bs aad-  in k1 /= k2 ==> Nothing == aeadOpen k2 n ct aad---- | Ciphertext cannot be decrypted with a different key-cannotDecryptKeyDetachedProp :: Key -> Key -> Nonce -> Message -> Message -> Property-cannotDecryptKeyDetachedProp k1 k2 n (Message bs) (Message aad) =-  let (tag,ct) = aeadDetached k1 n bs aad-  in k1 /= k2 ==> Nothing == aeadOpenDetached k2 n tag ct aad---- | Ciphertext cannot be decrypted with a different nonce-cannotDecryptNonceProp :: Key -> Nonce -> Nonce -> Message -> Message -> Property-cannotDecryptNonceProp k n1 n2 (Message bs) (Message aad) =-  n1 /= n2 ==> Nothing == aeadOpen k n2 (aead k n1 bs aad) aad---- | Ciphertext cannot be decrypted with a different nonce-cannotDecryptNonceDetachedProp :: Key -> Nonce -> Nonce -> Message -> Message -> Property-cannotDecryptNonceDetachedProp k n1 n2 (Message bs) (Message aad) =-  let (tag,ct) = aeadDetached k n1 bs aad-  in n1 /= n2 ==> Nothing == aeadOpenDetached k n2 tag ct aad--testAEAD :: Test-testAEAD = buildTest $ do--  return $ testGroup "...Internal.AEAD" [--    testProperty "Can decrypt ciphertext"-    $ rightInverseProp,--    testProperty "Can decrypt ciphertext (detached)"-    $ rightInverseDetachedProp,--    testGroup "Cannot decrypt ciphertext when..." [--      testProperty "... ciphertext is perturbed"-      $ rightInverseFailureProp,--      testProperty "... AAD is perturbed"-      $ rightInverseAADFailureProp,--      testProperty "... ciphertext is perturbed (detached)"-      $ rightInverseFailureDetachedProp,--      testProperty "... tag is perturbed (detached)"-      $ rightInverseTagFailureProp,--      testProperty "... using the wrong key"-      $ cannotDecryptKeyProp,--      testProperty "... using the wrong key (detached)"-      $ cannotDecryptKeyDetachedProp,--      testProperty "... using the wrong nonce"-      $ cannotDecryptNonceProp,--      testProperty "... using the wrong nonce (detached"-      $ cannotDecryptNonceDetachedProp--      ]-    ]
tests/BoxProperties.hs view
@@ -5,49 +5,47 @@   testBox   ) where -import           Util-import           Crypto.Saltine.Core.Box-import qualified Data.ByteString                      as S-import           Data.Monoid--import           Test.Framework.Providers.QuickCheck2-import           Test.Framework-import           Test.QuickCheck.Property-import           Test.QuickCheck.Monadic+import Crypto.Saltine.Core.Box+import Data.Monoid+import Test.Framework.Providers.QuickCheck2+import Test.Framework+import Test.QuickCheck.Property+import Test.QuickCheck.Monadic+import Util  -- | Ciphertext can be decrypted rightInverseProp :: Keypair -> Keypair -> Nonce -> Message -> Bool-rightInverseProp (sk1, pk1) (sk2, pk2) n (Message bs) =+rightInverseProp (Keypair sk1 pk1) (Keypair sk2 pk2) n (Message bs) =   Just bs == boxOpen pk1 sk2 n (box pk2 sk1 n bs)  -- | Cannot decrypt without the corrent secret key rightInverseFailureProp1 :: Keypair -> Keypair -> Nonce -> Message -> Perturb -> Bool-rightInverseFailureProp1 (sk1, pk1) (sk2, pk2) n (Message bs) p =+rightInverseFailureProp1 (Keypair sk1 pk1) (Keypair sk2 pk2) n (Message bs) p =   Nothing == boxOpen pk1 (perturb sk2 ([0] <> p)) n (box pk2 sk1 n bs)  -- | Cannot decrypt when not sent to you rightInverseFailureProp2 :: Keypair -> Keypair -> Nonce -> Message -> Perturb -> Bool-rightInverseFailureProp2 (sk1, pk1) (sk2, pk2) n (Message bs) p =+rightInverseFailureProp2 (Keypair sk1 pk1) (Keypair sk2 pk2) n (Message bs) p =   Nothing == boxOpen pk1 sk2 n (box (perturb pk2 p) sk1 n bs)  -- | Ciphertext cannot be decrypted (verification failure) if the -- ciphertext is perturbed rightInverseFailureProp3 :: Keypair -> Keypair -> Nonce -> Message -> Perturb -> Bool-rightInverseFailureProp3 (sk1, pk1) (sk2, pk2) n (Message bs) p =+rightInverseFailureProp3 (Keypair sk1 pk1) (Keypair sk2 pk2) n (Message bs) p =   Nothing == boxOpen pk1 sk2 n (perturb (box pk2 sk1 n bs) p)  -- | Ciphertext cannot be decrypted with a different nonce cannotDecryptNonceProp   :: Keypair -> Keypair -> Nonce -> Nonce -> Message -> Bool-cannotDecryptNonceProp (sk1, pk1) (sk2, pk2) n1 n2 (Message bs) =+cannotDecryptNonceProp (Keypair sk1 pk1) (Keypair sk2 pk2) n1 n2 (Message bs) =   Nothing == boxOpen pk1 sk2 n2 (box pk2 sk1 n1 bs)  -- | BeforeNM creates identical secret keys when called in an -- anti-symmetric fashion. beforeNMCreateSecretKeyProp :: Test.QuickCheck.Property.Property beforeNMCreateSecretKeyProp = monadicIO . (assert =<<) . run $ do-  (sk1, pk1) <- newKeypair-  (sk2, pk2) <- newKeypair+  Keypair sk1 pk1 <- newKeypair+  Keypair sk2 pk2 <- newKeypair   let ck_1for2 = beforeNM sk1 pk2       ck_2for1 = beforeNM sk2 pk1   return (ck_1for2 == ck_2for1)@@ -66,8 +64,8 @@  testBox :: Test testBox = buildTest $ do-  (sk1, pk1) <- newKeypair-  (sk2, pk2) <- newKeypair+  kp1@(Keypair sk1 pk1) <- newKeypair+  kp2@(Keypair sk2 pk2) <- newKeypair   let ck_1for2 = beforeNM sk1 pk2       ck_2for1 = beforeNM sk2 pk1   n1 <- newNonce@@ -78,7 +76,7 @@     testGroup "Can decrypt ciphertext using..." [         testProperty "... public key/secret key"-       $ rightInverseProp (sk1, pk1) (sk2, pk2) n1 ,+       $ rightInverseProp kp1 kp2 n1 ,         testProperty "... combined key"        $ rightInverseAfterNMProp ck_1for2 ck_2for1 n1@@ -88,16 +86,16 @@     testGroup "Fail to verify ciphertext when..." [        testProperty "... not using proper secret key"-      $ rightInverseFailureProp1 (sk1, pk1) (sk2, pk2) n1,+      $ rightInverseFailureProp1 kp1 kp2 n1,        testProperty "... not actually sent to you"-      $ rightInverseFailureProp2 (sk1, pk1) (sk2, pk2) n1,+      $ rightInverseFailureProp2 kp1 kp2 n1,        testProperty "... ciphertext has been perturbed"-      $ rightInverseFailureProp3 (sk1, pk1) (sk2, pk2) n1,+      $ rightInverseFailureProp3 kp1 kp2 n1,        testProperty "... using the wrong nonce"-      $ cannotDecryptNonceProp (sk1, pk1) (sk2, pk2) n1 n2,+      $ cannotDecryptNonceProp kp1 kp2 n1 n2,        testProperty "... using the wrong combined key"       $ rightInverseFailureAfterNMProp1 ck_1for2 ck_2for1 n1
tests/Main.hs view
@@ -3,7 +3,10 @@ module Main where  import SecretBoxProperties   (testSecretBox)-import AEADProperties        (testAEAD)+import AEAD.ChaCha20Poly1305Properties      (testAEADChaCha20)+import AEAD.ChaCha20Poly1305IETFProperties  (testAEADIETF)+import AEAD.XChaCha20Poly1305Properties     (testAEADXChaCha20)+import AEAD.AES256GCMProperties             (testAEADAES) import BoxProperties         (testBox) import SealedBoxProperties   (testSealedBox) import StreamProperties      (testStream)@@ -12,9 +15,10 @@ import SignProperties        (testSign) import HashProperties        (testHash) import ScalarMultProperties  (testScalarMult)+import PasswordProperties    (testPassword)+import UtilProperties        (testUtils) import Crypto.Saltine -import Data.Monoid import Test.Framework  runOpts :: RunnerOptions@@ -29,14 +33,19 @@ main = do   sodiumInit   flip defaultMainWithOpts runOpts [+        testUtils,         testBox,         testSealedBox,         testSecretBox,-        testAEAD,+        testAEADChaCha20,+        testAEADIETF,+        testAEADXChaCha20,+        testAEADAES,         testStream,         testAuth,         testOneTimeAuth,         testSign,         testHash,-        testScalarMult+        testScalarMult,+        testPassword         ]
+ tests/PasswordProperties.hs view
@@ -0,0 +1,97 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE OverloadedLists #-}++module PasswordProperties (+  testPassword+) where++import Crypto.Saltine.Core.Password+import Crypto.Saltine.Internal.Util+import Data.Maybe                             (isJust, isNothing, fromJust)+import Data.Monoid+import Data.Text                              (Text)+import Test.Framework.Providers.QuickCheck2+import Test.Framework+import Test.QuickCheck++import qualified Crypto.Saltine.Internal.Password as I+import qualified Data.Text                        as T++instance Arbitrary Text where+    arbitrary = T.pack <$> arbitrary++instance Arbitrary Algorithm where+    arbitrary = elements $ enumFromTo minBound maxBound++-- | Sadly using the actual maximum limit is just way too slow+instance Arbitrary Memlimit where+    arbitrary = I.Memlimit <$> chooseInt ( max I.pwhash_argon2i_memlimit_min I.pwhash_argon2id_memlimit_min+                                         , max I.pwhash_argon2i_memlimit_min I.pwhash_argon2id_memlimit_min * 4+                                         )++instance Arbitrary Opslimit where+    arbitrary = I.Opslimit <$> chooseInt ( max I.pwhash_argon2i_opslimit_min I.pwhash_argon2id_opslimit_min+                                         , max I.pwhash_argon2i_opslimit_min I.pwhash_argon2id_opslimit_min * 4+                                         )++instance Arbitrary Policy where+    arbitrary = applyArbitrary3 Policy++rightInverseProp :: Text -> Policy -> IO Bool+rightInverseProp pw pol = do+    h <- pwhashStr pw pol+    pure $ pwhashStrVerify (fromJust h) pw++rightInverseFailureProp1 :: Text -> Policy -> Text -> IO Bool+rightInverseFailureProp1 pw pol per =+    let npw = T.reverse pw <> T.pack "0" <> per+    in do+        h <- pwhashStr pw pol+        pure . not $ pwhashStrVerify (fromJust h) npw++rightProp :: Text -> Policy -> IO Bool+rightProp pw pol = do+    h <- pwhashStr pw pol+    pure $ Just False == needsRehash (opsPolicy pol) (memPolicy pol) (fromJust h)++rightFailureProp :: Text -> Opslimit -> Opslimit -> Memlimit -> Memlimit -> IO Bool+rightFailureProp pw ops1 ops2 mem1 mem2 = do+    h <- pwhashStr pw (Policy ops1 mem1 defaultAlgorithm)+    pure $ Just True == needsRehash ops2 mem2 (fromJust h)+            || ops1 == ops2++rightFailureProp2 :: Text -> Opslimit -> Memlimit -> Bool+rightFailureProp2 invhash ops mem =+    isNothing $ needsRehash ops mem (I.PasswordHash invhash)++rightProp2 :: Salt -> Text -> Policy -> Gen Bool+rightProp2 salt pw pol = do+    i <- chooseInt (I.pwhash_bytes_min, 1024)++    pure $ isJust $ pwhash pw i salt pol+++testPassword :: Test+testPassword = buildTest $ do+  salt <- newSalt++  return $ testGroup "... Password" [++    testProperty "Can hash passwords and verify them..."+        $ ioProperty . uncurry rightInverseProp,++    testProperty "Hashed passwords cannot be verified with the wrong password..."+        $ ioProperty . uncurry3 rightInverseFailureProp1,++    testProperty "Hashed passwords do not need to be rehashed with the same policy..."+        $ ioProperty . uncurry rightProp,++    testProperty "Hashed passwords do need to be rehashed with a different policy..."+        $ ioProperty . uncurry5 rightFailureProp,++    testProperty "needsRehash detects invalid hashes..."+        rightFailureProp2,++    testProperty "Deriving a key from a password..."+        (rightProp2 salt)+    ]
tests/SealedBoxProperties.hs view
@@ -5,69 +5,67 @@   testSealedBox ) where -import           Util-import           Crypto.Saltine.Core.Box-import           Data.Monoid--import qualified Data.ByteString                      as S-import           Test.Framework.Providers.QuickCheck2-import           Test.Framework-import           Test.QuickCheck.Property               (ioProperty)+import Crypto.Saltine.Core.Box+import Data.Monoid+import Test.Framework.Providers.QuickCheck2+import Test.Framework+import Test.QuickCheck.Property               (ioProperty)+import Util  -- | Ciphertext can be decrypted rightInverseProp :: Keypair -> Message -> IO Bool-rightInverseProp (sk1, pk1) (Message bs) = do+rightInverseProp (Keypair sk1 pk1) (Message bs) = do   enc <- boxSeal pk1 bs   return (Just bs == boxSealOpen pk1 sk1 enc)  -- | Cannot decrypt without the correct secret key rightInverseFailureProp1 :: Keypair -> Message -> Perturb -> IO Bool-rightInverseFailureProp1 (sk1, pk1) (Message bs) p = do+rightInverseFailureProp1 (Keypair sk1 pk1) (Message bs) p = do   enc <- boxSeal pk1 bs   return (Nothing == boxSealOpen pk1 (perturb sk1 ([0] <> p)) enc)  -- | Cannot decrypt without the correct public key rightInverseFailureProp2 :: Keypair -> Message -> Perturb -> IO Bool-rightInverseFailureProp2 (sk1, pk1) (Message bs) p = do+rightInverseFailureProp2 (Keypair sk1 pk1) (Message bs) p = do   enc <- boxSeal pk1 bs   return (Nothing == boxSealOpen (perturb pk1 p) sk1 enc)  -- | Cannot decrypt when not sent to you rightInverseFailureProp3 :: Keypair -> Message -> Perturb -> IO Bool-rightInverseFailureProp3 (sk1, pk1) (Message bs) p = do+rightInverseFailureProp3 (Keypair sk1 pk1) (Message bs) p = do   enc <- boxSeal (perturb pk1 p) bs   return (Nothing == boxSealOpen pk1 sk1 enc)  -- | Ciphertext cannot be decrypted (verification failure) if the -- ciphertext is perturbed rightInverseFailureProp4 :: Keypair -> Message -> Perturb -> IO Bool-rightInverseFailureProp4 (sk1, pk1) (Message bs) p = do+rightInverseFailureProp4 (Keypair sk1 pk1) (Message bs) p = do   enc <- boxSeal pk1 bs   return (Nothing == boxSealOpen pk1 sk1 (perturb enc p))  testSealedBox :: Test testSealedBox = buildTest $ do -  (sk1, pk1) <- newKeypair+  kp <- newKeypair    return $ testGroup "... SealedBox" [      testGroup "Can decrypt ciphertext using..." [        testProperty "... public key/secret key"-       $ ioProperty . rightInverseProp (sk1, pk1)+       $ ioProperty . rightInverseProp kp        ],      testGroup "Fail to verify ciphertext when..." [       testProperty "... not using proper secret key"-      $ ioProperty . uncurry (rightInverseFailureProp1 (sk1, pk1)),+      $ ioProperty . uncurry (rightInverseFailureProp1 kp),        testProperty "... not using proper public key"-      $ ioProperty . uncurry (rightInverseFailureProp2 (sk1, pk1)),+      $ ioProperty . uncurry (rightInverseFailureProp2 kp),        testProperty "... not actually sent to you"-      $ ioProperty . uncurry (rightInverseFailureProp3 (sk1, pk1)),+      $ ioProperty . uncurry (rightInverseFailureProp3 kp),        testProperty "... ciphertext has been perturbed"-      $ ioProperty . uncurry ( rightInverseFailureProp4 (sk1, pk1) )+      $ ioProperty . uncurry (rightInverseFailureProp4 kp)       ]     ]
tests/SecretBoxProperties.hs view
@@ -8,9 +8,8 @@ import           Util import           Crypto.Saltine.Core.SecretBox import           Crypto.Saltine.Class-import           Crypto.Saltine.Internal.ByteSizes as Bytes+import           Crypto.Saltine.Internal.SecretBox as Internal -import           Control.Applicative import qualified Data.ByteString                      as S import           Data.Maybe (fromJust) import           Test.Framework.Providers.QuickCheck2@@ -20,17 +19,13 @@  instance Arbitrary Nonce where     arbitrary =-        do bs <- S.pack <$> vector Bytes.secretBoxNonce+        do bs <- S.pack <$> vector Internal.secretbox_noncebytes            pure $ fromJust  (decode bs)  instance Arbitrary Key where     arbitrary =-        do bs <- S.pack <$> vector Bytes.secretBoxKey+        do bs <- S.pack <$> vector Internal.secretbox_keybytes            pure $ fromJust (decode bs)-instance Show Key where-    show = show . encode-instance Show Nonce where-    show = show . encode  -- | Ciphertext can be decrypted rightInverseProp :: Key -> Nonce -> Message -> Bool@@ -51,8 +46,9 @@  -- | Ciphertext cannot be decrypted if the tag is perturbed rightInverseTagFailureProp :: Key -> Nonce -> Message -> Message -> Property-rightInverseTagFailureProp k n (Message bs) (Message fakeTag) =+rightInverseTagFailureProp k n (Message bs) (Message fakeTagBs) =   let (realTag, ct) = secretboxDetached k n bs+      fakeTag       = Internal.Au fakeTagBs   in realTag /= fakeTag ==> Nothing == secretboxOpenDetached k n fakeTag ct  -- | Ciphertext cannot be decrypted if the ciphertext is perturbed
tests/SignProperties.hs view
@@ -6,6 +6,7 @@  import           Util import           Crypto.Saltine.Core.Sign+import           Crypto.Saltine.Internal.Sign  import qualified Data.ByteString                      as S import           Test.Framework.Providers.QuickCheck2@@ -14,8 +15,11 @@  testSign :: Test testSign = buildTest $ do-  (sk1,  pk1) <- newKeypair-  (_sk2, pk2) <- newKeypair+  kp1 <- newKeypair+  let sk1 = secretKey kp1+  let pk1 = publicKey kp1+  kp2 <- newKeypair+  let pk2 = publicKey kp2    return $ testGroup "...Internal.Sign" [ @@ -34,6 +38,6 @@      testProperty "Rejects message with mismatched key w/ detached signature"     $ \(Message bs) -> not (S.null bs) ==>-                         not (signVerifyDetached pk2 (sign sk1 bs) bs)+                         not (signVerifyDetached pk2 (signDetached sk1 bs) bs)      ]
tests/Util.hs view
@@ -5,13 +5,12 @@  import           Crypto.Saltine.Class -import           Control.Applicative import           Control.Monad           (replicateM) import qualified Data.ByteString       as S import           Data.Monoid+import           Data.Semigroup          (Semigroup) import           Data.Word (Word8) import           Data.Bits (xor)-import           Data.Semigroup (Semigroup) import           Test.QuickCheck import           GHC.Exts (IsList(..)) @@ -45,7 +44,7 @@             then pure (Perturb (1:bs))             else pure (Perturb bs) -newtype ByteString32 = ByteString32 S.ByteString deriving (Show)+newtype ByteString32 = ByteString32 S.ByteString deriving (Eq,Show)  instance Arbitrary ByteString32 where   arbitrary = ByteString32 . S.pack <$> replicateM 32 arbitrary
+ tests/UtilProperties.hs view
@@ -0,0 +1,28 @@+{-# LANGUAGE OverloadedStrings #-}++module UtilProperties (+  testUtils+  ) where++import Test.Framework.Providers.QuickCheck2+import Test.Framework+import Test.QuickCheck+import Util++import qualified Crypto.Saltine.Internal.Util as U++-- | Testing the comparison of keys+keyEquality :: ByteString32 -> Property+keyEquality k@(ByteString32 bs1) = k === k .&. U.compare bs1 bs1++keyInequality :: ByteString32 -> ByteString32 -> Property+keyInequality k1@(ByteString32 bs1) k2@(ByteString32 bs2) =+    k1 /= k2 ==> not $ U.compare bs1 bs2+++testUtils :: Test+testUtils = buildTest $ do+  return $ testGroup "...Utils" [+    testProperty "ByteString equality"      keyEquality,+    testProperty "ByteString inequality"    keyInequality+    ]