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 +17/−0
- README.md +2/−2
- bench/AES256GCMBench.hs +68/−0
- bench/AuthBench.hs +37/−0
- bench/BenchUtils.hs +15/−0
- bench/BoxBench.hs +45/−0
- bench/ChaCha20Poly1305Bench.hs +68/−0
- bench/ChaCha20Poly1305IETFBench.hs +68/−0
- bench/ConstantTimeBench.hs +29/−0
- bench/HashBench.hs +40/−0
- bench/Main.hs +79/−0
- bench/OneTimeAuthBench.hs +37/−0
- bench/PasswordBench.hs +87/−0
- bench/RandomBench.hs +21/−0
- bench/ScalarMultBench.hs +35/−0
- bench/SecretBoxBench.hs +57/−0
- bench/SignBench.hs +53/−0
- bench/StreamBench.hs +37/−0
- bench/XChaCha20Poly1305Bench.hs +68/−0
- saltine.cabal +72/−11
- src/Crypto/Saltine/Class.hs +4/−3
- src/Crypto/Saltine/Core/AEAD.hs +14/−228
- src/Crypto/Saltine/Core/AEAD/AES256GCM.hs +149/−0
- src/Crypto/Saltine/Core/AEAD/ChaCha20Poly1305.hs +134/−0
- src/Crypto/Saltine/Core/AEAD/ChaCha20Poly1305IETF.hs +134/−0
- src/Crypto/Saltine/Core/AEAD/XChaCha20Poly1305.hs +134/−0
- src/Crypto/Saltine/Core/Auth.hs +12/−66
- src/Crypto/Saltine/Core/Box.hs +32/−195
- src/Crypto/Saltine/Core/Hash.hs +16/−89
- src/Crypto/Saltine/Core/OneTimeAuth.hs +11/−64
- src/Crypto/Saltine/Core/Password.hs +247/−0
- src/Crypto/Saltine/Core/ScalarMult.hs +10/−53
- src/Crypto/Saltine/Core/SecretBox.hs +59/−143
- src/Crypto/Saltine/Core/Sign.hs +29/−111
- src/Crypto/Saltine/Core/Stream.hs +11/−69
- src/Crypto/Saltine/Core/Utils.hs +2/−1
- src/Crypto/Saltine/Internal/AEAD/AES256GCM.hs +188/−0
- src/Crypto/Saltine/Internal/AEAD/ChaCha20Poly1305.hs +184/−0
- src/Crypto/Saltine/Internal/AEAD/ChaCha20Poly1305IETF.hs +183/−0
- src/Crypto/Saltine/Internal/AEAD/XChaCha20Poly1305.hs +183/−0
- src/Crypto/Saltine/Internal/Auth.hs +103/−0
- src/Crypto/Saltine/Internal/Box.hs +282/−0
- src/Crypto/Saltine/Internal/ByteSizes.hs +3/−264
- src/Crypto/Saltine/Internal/Hash.hs +162/−0
- src/Crypto/Saltine/Internal/OneTimeAuth.hs +104/−0
- src/Crypto/Saltine/Internal/Password.hs +567/−0
- src/Crypto/Saltine/Internal/ScalarMult.hs +91/−0
- src/Crypto/Saltine/Internal/SecretBox.hs +179/−0
- src/Crypto/Saltine/Internal/Sign.hs +179/−0
- src/Crypto/Saltine/Internal/Stream.hs +107/−0
- src/Crypto/Saltine/Internal/Util.hs +100/−10
- tests/AEAD/AES256GCMProperties.hs +125/−0
- tests/AEAD/ChaCha20Poly1305IETFProperties.hs +128/−0
- tests/AEAD/ChaCha20Poly1305Properties.hs +128/−0
- tests/AEAD/XChaCha20Poly1305Properties.hs +128/−0
- tests/AEADProperties.hs +0/−134
- tests/BoxProperties.hs +21/−23
- tests/Main.hs +13/−4
- tests/PasswordProperties.hs +97/−0
- tests/SealedBoxProperties.hs +17/−19
- tests/SecretBoxProperties.hs +5/−9
- tests/SignProperties.hs +7/−3
- tests/Util.hs +2/−3
- tests/UtilProperties.hs +28/−0
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 [](https://travis-ci.org/tel/saltine)[](https://hackage.haskell.org/package/saltine)+# Saltine 0.2.0.0 [](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+ ]