saltine 0.0.0.4 → 0.0.0.5
raw patch · 22 files changed
+660/−602 lines, 22 filesdep −vectornew-uploaderPVP: minor bump suggested
API additions: PVP suggests at least a minor version bump
Dependencies removed: vector
API changes (from Hackage documentation)
+ Crypto.Saltine.Core.Box: boxSeal :: PublicKey -> ByteString -> IO ByteString
+ Crypto.Saltine.Core.Box: boxSealOpen :: PublicKey -> SecretKey -> ByteString -> Maybe ByteString
+ Crypto.Saltine.Internal.ByteSizes: sealedBox :: Int
Files
- saltine.cabal +33/−34
- src/Crypto/Saltine.hs +4/−7
- src/Crypto/Saltine/Class.hs +7/−8
- src/Crypto/Saltine/Core/Auth.hs +51/−52
- src/Crypto/Saltine/Core/Box.hs +188/−116
- src/Crypto/Saltine/Core/Hash.hs +41/−42
- src/Crypto/Saltine/Core/OneTimeAuth.hs +50/−51
- src/Crypto/Saltine/Core/ScalarMult.hs +36/−36
- src/Crypto/Saltine/Core/SecretBox.hs +47/−48
- src/Crypto/Saltine/Core/Sign.hs +59/−59
- src/Crypto/Saltine/Core/Stream.hs +46/−47
- src/Crypto/Saltine/Internal/ByteSizes.hs +18/−8
- src/Crypto/Saltine/Internal/Util.hs +18/−16
- tests/AuthProperties.hs +1/−2
- tests/BoxProperties.hs +17/−23
- tests/Main.hs +8/−6
- tests/OneTimeAuthProperties.hs +0/−0
- tests/ScalarMultProperties.hs +8/−10
- tests/SecretBoxProperties.hs +6/−8
- tests/SignProperties.hs +7/−9
- tests/StreamProperties.hs +7/−11
- tests/Util.hs +8/−9
saltine.cabal view
@@ -1,10 +1,10 @@ name: saltine-version: 0.0.0.4+version: 0.0.0.5 synopsis: Cryptography that's easy to digest (NaCl/libsodium bindings). description: /NaCl/ (pronounced \"salt\") is a new easy-to-use high-speed software- library for network communica tion, encryption, decryption,+ library for network communication, encryption, decryption, signatures, etc. NaCl's goal is to provide all of the core operations needed to build higher-level cryptographic tools. .@@ -21,13 +21,13 @@ license: MIT license-file: LICENSE author: Joseph Abrahamson-maintainer: Joseph Abrahamson <me@jspha.com>+maintainer: Max Amanshauser <max@lambdalifting.org> bug-reports: http://github.com/tel/saltine/issues copyright: Copyright (c) Joseph Abrahamson 2013 category: Cryptography build-type: Simple cabal-version: >=1.10-tested-with: GHC==7.6.3, GHC==7.8.4, GHC==7.10.1+tested-with: GHC==7.8.4, GHC==7.10.3, GHC==8.0.2 source-repository head type: git@@ -36,48 +36,47 @@ library hs-source-dirs: src exposed-modules:- Crypto.Saltine- Crypto.Saltine.Internal.ByteSizes- Crypto.Saltine.Core.SecretBox- Crypto.Saltine.Core.Box- Crypto.Saltine.Core.Stream- Crypto.Saltine.Core.Auth- Crypto.Saltine.Core.OneTimeAuth- Crypto.Saltine.Core.Sign- Crypto.Saltine.Core.Hash- Crypto.Saltine.Core.ScalarMult- Crypto.Saltine.Class+ Crypto.Saltine+ Crypto.Saltine.Internal.ByteSizes+ Crypto.Saltine.Core.SecretBox+ Crypto.Saltine.Core.Box+ Crypto.Saltine.Core.Stream+ Crypto.Saltine.Core.Auth+ Crypto.Saltine.Core.OneTimeAuth+ Crypto.Saltine.Core.Sign+ Crypto.Saltine.Core.Hash+ Crypto.Saltine.Core.ScalarMult+ Crypto.Saltine.Class other-modules:- Crypto.Saltine.Internal.Util+ Crypto.Saltine.Internal.Util extra-libraries: sodium cc-options: -Wall ghc-options: -Wall -funbox-strict-fields default-language: Haskell2010 build-depends:- base >= 4.5 && < 5,- bytestring,- profunctors+ base >= 4.5 && < 5+ , bytestring+ , profunctors test-suite tests type: exitcode-stdio-1.0 main-is: Main.hs other-modules:- AuthProperties- BoxProperties- OneTimeAuthProperties- ScalarMultProperties- SecretBoxProperties- SignProperties- StreamProperties- Util+ AuthProperties+ BoxProperties+ OneTimeAuthProperties+ ScalarMultProperties+ SecretBoxProperties+ SignProperties+ StreamProperties+ Util ghc-options: -Wall -threaded -O0 -rtsopts hs-source-dirs: tests default-language: Haskell2010 build-depends:- base >= 4.5 && < 5,- saltine,- bytestring,- vector,- QuickCheck,- test-framework-quickcheck2,- test-framework+ base >= 4.5 && < 5+ , saltine+ , bytestring+ , QuickCheck+ , test-framework-quickcheck2+ , test-framework
src/Crypto/Saltine.hs view
@@ -1,6 +1,5 @@ {-# LANGUAGE ForeignFunctionInterface #-}-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeFamilies #-} module Crypto.Saltine ( optimize,@@ -10,11 +9,9 @@ import Foreign.C import Crypto.Saltine.Core.SecretBox --- | Runs Sodiums's optimizer. This has no semantic effect, but both--- may boost the speed of Sodium after running it. It is recommended--- in production environments. It is, however, NOT thread-safe so no--- other Sodium functions should be called until it successfully--- returns.+-- | Runs Sodiums's initialization routine. This should be called before+-- using any other function. It is thread-safe since libsodium 1.0.11,+-- but not before. optimize :: IO () optimize = do err <- c_sodiumInit
src/Crypto/Saltine/Class.hs view
@@ -2,25 +2,24 @@ -- Module : Crypto.Saltine.Class -- Copyright : (c) Joseph Abrahamson 2013 -- License : MIT--- +-- -- Maintainer : me@jspha.com -- Stability : experimental -- Portability : non-portable--- +-- -- Saltine type classes module Crypto.Saltine.Class ( IsEncoding (..), IsNonce (..) ) where -import Data.Profunctor-import qualified Data.ByteString as S-import Data.ByteString (ByteString)-import Control.Applicative+import Control.Applicative+import Data.Profunctor+import Data.ByteString (ByteString) -- | Class for all keys and nonces in Saltine which have a--- representation as 'V.Vector' of 'Word8'. 'encoded' is a 'Prism' of--- type @Prism' (V.Vector Word8) a@ compatible with "Control.Lens" and+-- representation as ByteString. 'encoded' is a 'Prism' of+-- type @Prism' ByteString a@ compatible with "Control.Lens" and -- is automatically deduced. class IsEncoding a where encode :: a -> ByteString
src/Crypto/Saltine/Core/Auth.hs view
@@ -2,19 +2,19 @@ -- Module : Crypto.Saltine.Core.Auth -- Copyright : (c) Joseph Abrahamson 2013 -- License : MIT--- +-- -- Maintainer : me@jspha.com -- Stability : experimental -- Portability : non-portable--- --- Secret-key message authentication: +--+-- Secret-key message authentication: -- "Crypto.Saltine.Core.Auth"--- +-- -- The 'auth' function authenticates a message 'ByteString' using a -- 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.--- +-- -- The 'auth' function, viewed as a function of the message for a -- uniform random key, is designed to meet the standard notion of -- unforgeability. This means that an attacker cannot find@@ -25,17 +25,17 @@ -- cipher block chaining message authentication code,\" Journal of -- Computer and System Sciences 61 (2000), 362–399; -- <http://www-cse.ucsd.edu/~mihir/papers/cbc.html>.--- +-- -- Saltine does not make any promises regarding \"strong\" -- unforgeability; perhaps one valid authenticator can be converted -- into another valid authenticator for the same message. NaCl also -- does not make any promises regarding \"truncated unforgeability.\"--- +-- -- "Crypto.Saltine.Core.Auth" is currently an implementation of -- HMAC-SHA-512-256, i.e., the first 256 bits of -- HMAC-SHA-512. HMAC-SHA-512-256 is conjectured to meet the standard -- notion of unforgeability.--- +-- -- This is version 2010.08.30 of the auth.html web page. module Crypto.Saltine.Core.Auth ( Key, Authenticator,@@ -43,37 +43,36 @@ auth, verify ) where -import Crypto.Saltine.Class-import Crypto.Saltine.Internal.Util+import Crypto.Saltine.Class+import Crypto.Saltine.Internal.Util import qualified Crypto.Saltine.Internal.ByteSizes as Bytes -import Foreign.C-import Foreign.Ptr-import qualified Data.ByteString as S-import Data.ByteString (ByteString)--import Control.Applicative+import Control.Applicative+import Foreign.C+import Foreign.Ptr+import qualified Data.ByteString as S+import Data.ByteString (ByteString) -- $types -- | An opaque 'auth' cryptographic key.-newtype Key = Key ByteString deriving (Eq, Ord)+newtype Key = Key ByteString deriving (Eq, Ord) -- | An opaque 'auth' authenticator.-newtype Authenticator = Au ByteString deriving (Eq, Ord)+newtype Authenticator = Au ByteString deriving (Eq, Ord) instance IsEncoding Key where- decode v = case S.length v == Bytes.authKey of- True -> Just (Key v)- False -> Nothing+ decode v = if S.length v == Bytes.authKey+ then Just (Key v)+ else Nothing {-# INLINE decode #-} encode (Key v) = v {-# INLINE encode #-} instance IsEncoding Authenticator where- decode v = case S.length v == Bytes.auth of- True -> Just (Au v)- False -> Nothing+ decode v = if S.length v == Bytes.auth+ then Just (Au v)+ else Nothing {-# INLINE decode #-} encode (Au v) = v {-# INLINE encode #-}@@ -86,10 +85,10 @@ -- is infeasible to forge these authenticators without the key, even -- if an attacker observes many authenticators and messages and has -- the ability to influence the messages sent.-auth :: Key - -> ByteString- -- ^ Message- -> Authenticator+auth :: Key+ -> ByteString+ -- ^ Message+ -> Authenticator auth (Key key) msg = Au . snd . buildUnsafeCVector Bytes.auth $ \pa -> constVectors [key, msg] $ \[(pk, _), (pm, mlen)] ->@@ -98,37 +97,37 @@ -- | Checks to see if an authenticator is a correct proof that a -- message was signed by some key. verify :: Key- -> Authenticator- -> ByteString- -- ^ Message- -> Bool- -- ^ Is this message authentic?+ -> Authenticator+ -> ByteString+ -- ^ Message+ -> Bool+ -- ^ Is this message authentic? verify (Key key) (Au a) msg = unsafeDidSucceed $ constVectors [key, msg, a] $ \[(pk, _), (pm, mlen), (pa, _)] ->- return $ c_auth_verify pa pm (fromIntegral mlen) pk+ 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+ -- ^ 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+ -- ^ 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
@@ -2,28 +2,32 @@ -- Module : Crypto.Saltine.Core.Box -- Copyright : (c) Joseph Abrahamson 2013 -- License : MIT--- +-- -- Maintainer : me@jspha.com -- Stability : experimental -- Portability : non-portable--- --- Public-key authenticated encryption:+--+-- Public-key cryptography abstraction: -- "Crypto.Saltine.Core.Box"--- --- The 'box' function encrypts and authenticates a message+--+-- This module consists of functions dealing with two public-key+-- cryptography concepts in libsodium.+--+-- The first one is an authenticated encryption scheme. In this+-- scheme, the 'box' function encrypts and authenticates a message -- 'ByteString' using the sender's secret key, the receiver's public -- key, and a nonce. The 'boxOpen' function verifies and decrypts a -- ciphertext 'ByteString' using the receiver's secret key, the -- sender's public key, and a nonce. If the ciphertext fails -- verification, 'boxOpen' returns 'Nothing'.--- --- The "Crypto.Saltine.Core.Box" module is designed to meet the+--+-- The set of box functions is designed to meet the -- standard notions of privacy and third-party unforgeability for a -- public-key authenticated-encryption scheme using nonces. For formal -- definitions see, e.g., Jee Hea An, "Authenticated encryption in the -- public-key setting: security notions and analyses," -- <http://eprint.iacr.org/2001/079>.--- +-- -- Distinct messages between the same @{sender, receiver}@ set are -- required to have distinct nonces. For example, the -- lexicographically smaller public key can use nonce 1 for its first@@ -33,13 +37,22 @@ -- nonce 4 for its second message, nonce 6 for its third message, -- etc. Nonces are long enough that randomly generated nonces have -- negligible risk of collision.--- +-- -- There is no harm in having the same nonce for different messages if -- the @{sender, receiver}@ sets are different. This is true even if -- the sets overlap. For example, a sender can use the same nonce for -- two different messages if the messages are sent to two different -- public keys.--- +--+-- The second concept is sealed boxes, which provide encryption and+-- preservation of integrity, but not authentication. Technically,+-- the sender of a message generates a keypair, uses the regular+-- box mechanism, attaches the public key to the message and then+-- immediately destroys the private key. This is useful, e.g. when+-- the receiver cannot know the sender's public key in advance and+-- hence cannot use the regular box functions, or when you want to+-- send messages anonymously.+-- -- The "Crypto.Saltine.Core.Box" module is not meant to provide -- non-repudiation. On the contrary: the crypto_box function -- guarantees repudiability. A receiver can freely modify a boxed@@ -50,37 +63,38 @@ -- <http://groups.google.com/group/sci.crypt/msg/ec5c18b23b11d82c>, -- crypto_box uses "public-key authenticators" rather than "public-key -- signatures."--- +-- -- Users who want public verifiability (or receiver-assisted public -- verifiability) should instead use signatures (or -- signcryption). Signatures are documented in the -- "Crypto.Saltine.Core.Sign" module.--- +-- -- "Crypto.Saltine.Core.Box" is @curve25519xsalsa20poly1305@, a -- particular combination of Curve25519, Salsa20, and Poly1305 -- specified in "Cryptography in NaCl" -- (<http://nacl.cr.yp.to/valid.html>). This function is conjectured -- to meet the standard notions of privacy and third-party -- unforgeability.--- +-- -- This is version 2010.08.30 of the box.html web page. module Crypto.Saltine.Core.Box ( SecretKey, PublicKey, Keypair, CombinedKey, Nonce, newKeypair, beforeNM, newNonce, box, boxOpen,- boxAfterNM, boxOpenAfterNM + boxAfterNM, boxOpenAfterNM,+ boxSeal, boxSealOpen ) where -import Crypto.Saltine.Class-import Crypto.Saltine.Internal.Util+import Crypto.Saltine.Class+import Crypto.Saltine.Internal.Util import qualified Crypto.Saltine.Internal.ByteSizes as Bytes -import Foreign.C-import Foreign.Ptr-import qualified Data.ByteString as S+import Control.Applicative+import Foreign.C+import Foreign.Ptr+import qualified Data.ByteString as S import Data.ByteString (ByteString) -import Control.Applicative -- $types @@ -88,9 +102,9 @@ newtype SecretKey = SK ByteString deriving (Eq, Ord) instance IsEncoding SecretKey where- decode v = case S.length v == Bytes.boxSK of- True -> Just (SK v)- False -> Nothing+ decode v = if S.length v == Bytes.boxSK+ then Just (SK v)+ else Nothing {-# INLINE decode #-} encode (SK v) = v {-# INLINE encode #-}@@ -99,9 +113,9 @@ newtype PublicKey = PK ByteString deriving (Eq, Ord) instance IsEncoding PublicKey where- decode v = case S.length v == Bytes.boxPK of- True -> Just (PK v)- False -> Nothing+ decode v = if S.length v == Bytes.boxPK+ then Just (PK v)+ else Nothing {-# INLINE decode #-} encode (PK v) = v {-# INLINE encode #-}@@ -113,9 +127,9 @@ newtype CombinedKey = CK ByteString deriving (Eq, Ord) instance IsEncoding CombinedKey where- decode v = case S.length v == Bytes.boxBeforeNM of- True -> Just (CK v)- False -> Nothing+ decode v = if S.length v == Bytes.boxBeforeNM+ then Just (CK v)+ else Nothing {-# INLINE decode #-} encode (CK v) = v {-# INLINE encode #-}@@ -124,15 +138,15 @@ newtype Nonce = Nonce ByteString deriving (Eq, Ord) instance IsEncoding Nonce where- decode v = case S.length v == Bytes.boxNonce of- True -> Just (Nonce v)- False -> Nothing+ decode v = if S.length v == Bytes.boxNonce+ then Just (Nonce v)+ else Nothing {-# INLINE decode #-} encode (Nonce v) = v {-# INLINE encode #-} instance IsNonce Nonce where- zero = Nonce (S.replicate Bytes.boxNonce 0)+ zero = Nonce (S.replicate Bytes.boxNonce 0) nudge (Nonce n) = Nonce (nudgeBS n) -- | Randomly generates a secret key and a corresponding public key.@@ -142,7 +156,7 @@ -- _err ought to always be 0. ((_err, sk), pk) <- buildUnsafeCVector' Bytes.boxPK $ \pkbuf -> buildUnsafeCVector' Bytes.boxSK $ \skbuf ->- c_box_keypair pkbuf skbuf+ c_box_keypair pkbuf skbuf return (SK sk, PK pk) -- | Randomly generates a nonce for usage with 'box' and 'boxOpen'.@@ -155,39 +169,39 @@ beforeNM :: SecretKey -> PublicKey -> CombinedKey beforeNM (SK sk) (PK pk) = CK $ snd $ buildUnsafeCVector Bytes.boxBeforeNM $ \ckbuf -> constVectors [pk, sk] $ \[(ppk, _), (psk, _)] ->- c_box_beforenm ckbuf ppk psk+ c_box_beforenm ckbuf ppk psk -- | Encrypts a message for sending to the owner of the public -- key. They must have your public key in order to decrypt the -- message. It is infeasible for an attacker to decrypt the message so -- long as the 'Nonce' is not repeated. box :: PublicKey -> SecretKey -> Nonce- -> ByteString- -- ^ Message- -> ByteString- -- ^ Ciphertext+ -> ByteString+ -- ^ Message+ -> ByteString+ -- ^ Ciphertext box (PK pk) (SK sk) (Nonce nonce) msg = unpad' . snd . buildUnsafeCVector len $ \pc -> constVectors [pk, sk, pad' msg, nonce] $ \ [(ppk, _), (psk, _), (pm, _), (pn, _)] ->- c_box pc pm (fromIntegral len) pn ppk psk+ c_box pc pm (fromIntegral len) pn ppk psk where len = S.length msg + Bytes.boxZero pad' = pad Bytes.boxZero unpad' = unpad Bytes.boxBoxZero -- | Decrypts a message sent from the owner of the public key. They--- must have encrypted it using your secret key. Returns 'Nothing' if+-- must have encrypted it using your public key. Returns 'Nothing' if -- the keys and message do not match. boxOpen :: PublicKey -> SecretKey -> Nonce- -> ByteString- -- ^ Ciphertext- -> Maybe ByteString- -- ^ Message+ -> ByteString+ -- ^ Ciphertext+ -> Maybe ByteString+ -- ^ Message boxOpen (PK pk) (SK sk) (Nonce nonce) cipher = let (err, vec) = buildUnsafeCVector len $ \pm -> constVectors [pk, sk, pad' cipher, nonce] $ \ [(ppk, _), (psk, _), (pc, _), (pn, _)] ->- c_box_open pm pc (fromIntegral len) pn ppk psk+ c_box_open pm pc (fromIntegral len) pn ppk psk in hush . handleErrno err $ unpad' vec where len = S.length cipher + Bytes.boxBoxZero pad' = pad Bytes.boxBoxZero@@ -195,116 +209,174 @@ -- | 'box' using a 'CombinedKey' and is thus faster. boxAfterNM :: CombinedKey -> Nonce- -> ByteString- -- ^ Message- -> ByteString- -- ^ Ciphertext+ -> ByteString+ -- ^ Message+ -> ByteString+ -- ^ Ciphertext boxAfterNM (CK ck) (Nonce nonce) msg = unpad' . snd . buildUnsafeCVector len $ \pc -> constVectors [ck, pad' msg, nonce] $ \ [(pck, _), (pm, _), (pn, _)] ->- c_box_afternm pc pm (fromIntegral len) pn pck+ c_box_afternm pc pm (fromIntegral len) pn pck where len = S.length msg + Bytes.boxZero pad' = pad Bytes.boxZero unpad' = unpad Bytes.boxBoxZero -- | 'boxOpen' using a 'CombinedKey' and is thus faster. boxOpenAfterNM :: CombinedKey -> Nonce- -> ByteString- -- ^ Ciphertext- -> Maybe ByteString- -- ^ Message+ -> ByteString+ -- ^ Ciphertext+ -> Maybe ByteString+ -- ^ Message boxOpenAfterNM (CK ck) (Nonce nonce) cipher = let (err, vec) = buildUnsafeCVector len $ \pm -> constVectors [ck, pad' cipher, nonce] $ \ [(pck, _), (pc, _), (pn, _)] ->- c_box_open_afternm pm pc (fromIntegral len) pn pck+ c_box_open_afternm pm pc (fromIntegral len) pn pck in hush . handleErrno err $ unpad' vec where len = S.length cipher + Bytes.boxBoxZero pad' = pad Bytes.boxBoxZero unpad' = unpad Bytes.boxZero +-- | Encrypts a message for sending to the owner of the public+-- key. The message is unauthenticated, but permits integrity checking.+boxSeal :: PublicKey -> ByteString -> IO ByteString+boxSeal (PK pk) msg = fmap snd . buildUnsafeCVector' strlen $ \pc ->+ constVectors [pk, msg] $ \+ [(ppk, _), (pm, _)] ->+ c_box_seal pc pm (fromIntegral len) ppk+ where strlen = S.length msg + Bytes.sealedBox+ len = S.length msg++-- | Decrypts a sealed box message. The message must have been+-- encrypted using the receiver's public key.+-- Returns 'Nothing' if keys and message do not match or integrity+-- is violated.+boxSealOpen :: PublicKey -> SecretKey+ -> ByteString+ -- ^ Ciphertext+ -> Maybe ByteString+ -- ^ Message+boxSealOpen (PK pk) (SK sk) cipher =+ let (err, vec) = buildUnsafeCVector strlen $ \pm ->+ constVectors [pk, sk, cipher] $ \+ [(ppk, _), (psk, _), (pc, _)] ->+ c_box_seal_open pm pc (fromIntegral len) ppk psk+ in hush . handleErrno err $ vec+ where strlen = S.length cipher - Bytes.sealedBox+ len = S.length cipher++ -- | 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+ -- ^ Public key+ -> Ptr CChar+ -- ^ Secret key+ -> IO CInt+ -- ^ Always 0 -- | The secretbox C API uses 0-padded C strings. foreign import ccall "crypto_box" c_box :: 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 public key buffer- -> Ptr CChar- -- ^ Constant secret key buffer- -> IO CInt- -- ^ Always 0+ -- ^ 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 public key buffer+ -> Ptr CChar+ -- ^ Constant secret key buffer+ -> IO CInt+ -- ^ Always 0 -- | The secretbox C API uses 0-padded C strings. foreign import ccall "crypto_box_open" c_box_open :: Ptr CChar- -- ^ Message 0-padded output buffer- -> Ptr CChar- -- ^ Constant 0-padded ciphertext input buffer- -> CULLong- -- ^ Length of message input buffer (incl. 0s)- -> 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+ -- ^ Message 0-padded output buffer+ -> Ptr CChar+ -- ^ Constant 0-padded ciphertext input buffer+ -> CULLong+ -- ^ Length of message input buffer (incl. 0s)+ -> 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+ -- ^ 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 0-padded C strings. foreign import ccall "crypto_box_afternm" c_box_afternm :: 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 combined key buffer- -> IO CInt- -- ^ Always 0+ -- ^ 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 combined key buffer+ -> IO CInt+ -- ^ Always 0 -- | The secretbox C API uses 0-padded C strings. foreign import ccall "crypto_box_open_afternm" c_box_open_afternm :: Ptr CChar- -- ^ Message 0-padded output buffer- -> Ptr CChar- -- ^ Constant 0-padded 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+ -- ^ Message 0-padded output buffer+ -> Ptr CChar+ -- ^ Constant 0-padded 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
@@ -2,19 +2,19 @@ -- Module : Crypto.Saltine.Core.Hash -- Copyright : (c) Joseph Abrahamson 2013 -- License : MIT--- +-- -- Maintainer : me@jspha.com -- Stability : experimental -- Portability : non-portable--- +-- -- Hashing: "Crypto.Saltine.Core.Hash"--- +-- -- The 'hash' function hashes a message 'ByteString' and returns a -- hash. Hashes are always of length 'Bytes.hash'. The 'shorthash' -- function hashes a message 'ByteString' with respect to a secret key -- and returns a very short hash. Short hashes are always of length -- 'Bytes.shorthash'.--- +-- -- The 'hash' function is designed to be usable as a strong component -- of DSA, RSA-PSS, key derivation, hash-based message-authentication -- codes, hash-based ciphers, and various other common@@ -23,21 +23,21 @@ -- security of the applications against generic attacks. In -- particular, the 'hash' function is designed to make finding -- collisions difficult.--- +-- -- 'hash' is currently an implementation of SHA-512. 'shorthash' is -- currently an implementation of SipHash-2-4 -- (<https://131002.net/siphash/>).--- +-- -- There has been considerable degradation of public confidence in the -- security conjectures for many hash functions, including -- SHA-512. However, for the moment, there do not appear to be -- alternatives that inspire satisfactory levels of confidence. One -- can hope that NIST's SHA-3 competition will improve the situation.--- +-- -- Sodium includes an implementation of the Blake2 hash -- (<https://blake2.net/>) but since this is not standard NaCl nor was -- Blake2 selected to be SHA-3 the library doesn't bind it.--- +-- -- This is version 2010.08.30 of the hash.html web page. Information -- about SipHash has been added. module Crypto.Saltine.Core.Hash (@@ -46,24 +46,23 @@ shorthash, newShorthashKey ) where -import Crypto.Saltine.Class-import Crypto.Saltine.Internal.Util+import Crypto.Saltine.Class+import Crypto.Saltine.Internal.Util import qualified Crypto.Saltine.Internal.ByteSizes as Bytes -import Foreign.C-import Foreign.Ptr+import Control.Applicative+import Foreign.C+import Foreign.Ptr import qualified Data.ByteString as S import Data.ByteString (ByteString) -import Control.Applicative- -- | Computes a cryptographically collision-resistant hash making -- @hash m == hash m' ==> m == m'@ highly likely even when under -- attack. hash :: ByteString- -- ^ Message- -> ByteString- -- ^ Hash+ -- ^ Message+ -> ByteString+ -- ^ Hash hash m = snd . buildUnsafeCVector Bytes.hash $ \ph -> constVectors [m] $ \[(pm, _)] -> c_hash ph pm (fromIntegral $ S.length m) @@ -71,9 +70,9 @@ newtype ShorthashKey = ShK ByteString deriving (Eq, Ord) instance IsEncoding ShorthashKey where- decode v = case S.length v == Bytes.shorthashKey of- True -> Just (ShK v)- False -> Nothing+ decode v = if S.length v == Bytes.shorthashKey+ then Just (ShK v)+ else Nothing {-# INLINE decode #-} encode (ShK v) = v {-# INLINE encode #-}@@ -84,32 +83,32 @@ -- | Computes a very short, fast keyed hash. shorthash :: ShorthashKey- -> ByteString- -- ^ Message- -> ByteString- -- ^ Hash+ -> ByteString+ -- ^ Message+ -> ByteString+ -- ^ Hash shorthash (ShK k) m = snd . buildUnsafeCVector Bytes.shorthash $ \ph -> constVectors [k, m] $ \[(pk, _), (pm, _)] ->- c_shorthash ph pm (fromIntegral $ S.length m) pk- + c_shorthash ph pm (fromIntegral $ S.length m) pk+ 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+ -- ^ 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+ -- ^ Output hash buffer+ -> Ptr CChar+ -- ^ Constant message buffer+ -> CULLong+ -- ^ Message buffer length+ -> Ptr CChar+ -- ^ Constant Key buffer+ -> IO CInt+ -- ^ Always 0
src/Crypto/Saltine/Core/OneTimeAuth.hs view
@@ -2,36 +2,36 @@ -- Module : Crypto.Saltine.Core.OneTimeAuth -- Copyright : (c) Joseph Abrahamson 2013 -- License : MIT--- +-- -- Maintainer : me@jspha.com -- Stability : experimental -- Portability : non-portable--- +-- -- Secret-key single-message authentication: -- "Crypto.Saltine.Core.OneTimeAuth"--- +-- -- The 'auth' function authenticates a message 'ByteString' using a -- 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.--- +-- -- The 'auth' function, viewed as a function of the message for a -- uniform random key, is designed to meet the standard notion of -- unforgeability after a single message. After the sender -- authenticates one message, an attacker cannot find authenticators -- for any other messages.--- +-- -- The sender must not use 'auth' to authenticate more than one -- message under the same key. Authenticators for two messages under -- the same key should be expected to reveal enough information to -- allow forgeries of authenticators on other messages.--- +-- -- "Crypto.Saltine.Core.OneTimeAuth" is -- @crypto_onetimeauth_poly1305@, an authenticator specified in -- "Cryptography in NaCl" (<http://nacl.cr.yp.to/valid.html>), Section -- 9. This authenticator is proven to meet the standard notion of -- unforgeability after a single message.--- +-- -- This is version 2010.08.30 of the onetimeauth.html web page. module Crypto.Saltine.Core.OneTimeAuth ( Key, Authenticator,@@ -39,37 +39,36 @@ auth, verify ) where -import Crypto.Saltine.Class-import Crypto.Saltine.Internal.Util+import Crypto.Saltine.Class+import Crypto.Saltine.Internal.Util import qualified Crypto.Saltine.Internal.ByteSizes as Bytes -import Foreign.C-import Foreign.Ptr-import qualified Data.ByteString as S-import Data.ByteString (ByteString)--import Control.Applicative+import Control.Applicative+import Foreign.C+import Foreign.Ptr+import qualified Data.ByteString as S+import Data.ByteString (ByteString) -- $types -- | An opaque 'auth' cryptographic key.-newtype Key = Key ByteString deriving (Eq, Ord)+newtype Key = Key ByteString deriving (Eq, Ord) -- | An opaque 'auth' authenticator.-newtype Authenticator = Au ByteString deriving (Eq, Ord)+newtype Authenticator = Au ByteString deriving (Eq, Ord) instance IsEncoding Key where- decode v = case S.length v == Bytes.onetimeKey of- True -> Just (Key v)- False -> Nothing+ 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 = case S.length v == Bytes.onetime of- True -> Just (Au v)- False -> Nothing+ decode v = if S.length v == Bytes.onetime+ then Just (Au v)+ else Nothing {-# INLINE decode #-} encode (Au v) = v {-# INLINE encode #-}@@ -82,48 +81,48 @@ -- 'Authenticator' is /impossible/ to forge so long as the 'Key' is -- never used twice. auth :: Key- -> ByteString- -- ^ Message- -> Authenticator+ -> ByteString+ -- ^ Message+ -> Authenticator auth (Key key) msg = Au . snd . buildUnsafeCVector Bytes.onetime $ \pa -> constVectors [key, msg] $ \[(pk, _), (pm, _)] ->- c_onetimeauth pa pm (fromIntegral $ S.length msg) pk+ c_onetimeauth pa pm (fromIntegral $ S.length msg) pk -- | Verifies that an 'Authenticator' matches a given message and key. verify :: Key- -> Authenticator- -> ByteString- -- ^ Message- -> Bool- -- ^ Is this message authentic?+ -> Authenticator+ -> ByteString+ -- ^ Message+ -> Bool+ -- ^ Is this message authentic? verify (Key key) (Au a) msg = unsafeDidSucceed $ constVectors [key, msg, a] $ \ [(pk, _), (pm, _), (pa, _)] ->- return $ c_onetimeauth_verify pa pm (fromIntegral $ S.length msg) pk+ 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+ -- ^ 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+ -- ^ 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/ScalarMult.hs view
@@ -2,31 +2,31 @@ -- Module : Crypto.Saltine.Core.ScalarMult -- Copyright : (c) Joseph Abrahamson 2013 -- License : MIT--- +-- -- Maintainer : me@jspha.com -- Stability : experimental -- Portability : non-portable--- +-- -- Scalar multiplication: "Crypto.Saltine.Core.ScalarMult"--- +-- -- The 'mult' function multiplies a group element by an integer of -- length 'Bytes.multScalar'. It returns the resulting group element -- of length 'Bytes.mult'. The 'multBase' function multiplies a -- standard group element by an integer of length -- 'Bytes.multScalar'. It returns the resulting group element of -- length 'Bytes.mult'.--- +-- -- The correspondence between strings and group elements depends on -- the primitive implemented by 'mult'. The correspondence is not -- necessarily injective in either direction, but it is compatible -- with scalar multiplication in the group. The correspondence does -- not necessarily include all group elements, but it does include all -- strings; i.e., every string represents at least one group element.--- +-- -- The correspondence between strings and integers also depends on the -- primitive implemented by 'mult'. Every string represents at least -- one integer.--- +-- -- 'mult' is designed to be strong as a component of various -- well-known \"hashed Diffie–Hellman\" applications. In particular, -- it is designed to make the \"computational Diffie–Hellman\" problem@@ -36,33 +36,33 @@ -- order, then it is annihilated by all represented scalars. This -- feature allows protocols to avoid validating membership in the -- subgroup generated by the standard base.--- +-- -- NaCl does not make any promises regarding the \"decisional -- Diffie–Hellman\" problem (DDH), the \"static Diffie–Hellman\" -- problem (SDH), etc. Users are responsible for hashing group -- elements.--- +-- -- 'mult' is the function @crypto_scalarmult_curve25519@ specified in -- \"Cryptography in NaCl\", Sections 2, 3, and 4 -- (<http://nacl.cr.yp.to/valid.html>). This function is conjectured -- to be strong. For background see Bernstein, \"Curve25519: new -- Diffie-Hellman speed records,\" Lecture Notes in Computer Science -- 3958 (2006), 207–228, <http://cr.yp.to/papers.html#curve25519>.--- +-- -- This is version 2010.08.30 of the scalarmult.html web page. module Crypto.Saltine.Core.ScalarMult ( Scalar, GroupElement, mult, multBase ) where -import Crypto.Saltine.Class-import Crypto.Saltine.Internal.Util+import Crypto.Saltine.Class+import Crypto.Saltine.Internal.Util import qualified Crypto.Saltine.Internal.ByteSizes as Bytes -import Foreign.C-import Foreign.Ptr-import qualified Data.ByteString as S-import Data.ByteString (ByteString)+import Foreign.C+import Foreign.Ptr+import qualified Data.ByteString as S+import Data.ByteString (ByteString) -- $types @@ -70,20 +70,20 @@ newtype GroupElement = GE ByteString deriving (Eq) -- | A scalar integer.-newtype Scalar = Sc ByteString deriving (Eq)+newtype Scalar = Sc ByteString deriving (Eq) instance IsEncoding GroupElement where- decode v = case S.length v == Bytes.mult of- True -> Just (GE v)- False -> Nothing+ 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 = case S.length v == Bytes.multScalar of- True -> Just (Sc v)- False -> Nothing+ decode v = if S.length v == Bytes.multScalar+ then Just (Sc v)+ else Nothing {-# INLINE decode #-} encode (Sc v) = v {-# INLINE encode #-}@@ -91,27 +91,27 @@ mult :: Scalar -> GroupElement -> GroupElement mult (Sc n) (GE p) = GE . snd . buildUnsafeCVector Bytes.mult $ \pq -> constVectors [n, p] $ \[(pn, _), (pp, _)] ->- c_scalarmult pq pn pp+ c_scalarmult pq pn pp multBase :: Scalar -> GroupElement multBase (Sc n) = GE . snd . buildUnsafeCVector Bytes.mult $ \pq -> constVectors [n] $ \[(pn, _)] ->- c_scalarmult_base pq 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+ -- ^ 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+ -- ^ Output group element buffer+ -> Ptr CChar+ -- ^ Input integer buffer+ -> IO CInt+ -- ^ Always 0
src/Crypto/Saltine/Core/SecretBox.hs view
@@ -2,20 +2,20 @@ -- Module : Crypto.Saltine.Core.SecretBox -- Copyright : (c) Joseph Abrahamson 2013 -- License : MIT--- +-- -- Maintainer : me@jspha.com -- Stability : experimental -- Portability : non-portable--- +-- -- Secret-key authenticated encryption: -- "Crypto.Saltine.Core.SecretBox"--- +-- -- The 'secretbox' function encrypts and authenticates a message -- 'ByteString' using a secret key and a nonce. The 'secretboxOpen' -- function verifies and decrypts a ciphertext 'ByteString' using a -- secret key and a nonce. If the ciphertext fails validation, -- 'secretboxOpen' returns 'Nothing'.--- +-- -- The "Crypto.Saltine.Core.SecretBox" module is designed to meet -- the standard notions of privacy and authenticity for a secret-key -- authenticated-encryption scheme using nonces. For formal@@ -23,19 +23,19 @@ -- encryption: relations among notions and analysis of the generic -- composition paradigm," Lecture Notes in Computer Science 1976 -- (2000), 531–545, <http://www-cse.ucsd.edu/~mihir/papers/oem.html>.--- +-- -- 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.--- +-- -- "Crypto.Saltine.Core.SecretBox" is -- @crypto_secretbox_xsalsa20poly1305@, a particular combination of -- Salsa20 and Poly1305 specified in \"Cryptography in NaCl\" -- (<http://nacl.cr.yp.to/valid.html>). This function is conjectured -- to meet the standard notions of privacy and authenticity.--- +-- -- This is version 2010.08.30 of the secretbox.html web page. module Crypto.Saltine.Core.SecretBox ( Key, Nonce,@@ -43,16 +43,15 @@ newKey, newNonce ) where -import Crypto.Saltine.Class-import Crypto.Saltine.Internal.Util+import Crypto.Saltine.Class+import Crypto.Saltine.Internal.Util import qualified Crypto.Saltine.Internal.ByteSizes as Bytes -import Foreign.C-import Foreign.Ptr-import qualified Data.ByteString as S-import Data.ByteString (ByteString)--import Control.Applicative+import Control.Applicative+import Foreign.C+import Foreign.Ptr+import qualified Data.ByteString as S+import Data.ByteString (ByteString) -- $types @@ -60,9 +59,9 @@ newtype Key = Key ByteString deriving (Eq, Ord) instance IsEncoding Key where- decode v = case S.length v == Bytes.secretBoxKey of- True -> Just (Key v)- False -> Nothing+ decode v = if S.length v == Bytes.secretBoxKey+ then Just (Key v)+ else Nothing {-# INLINE decode #-} encode (Key v) = v {-# INLINE encode #-}@@ -71,15 +70,15 @@ newtype Nonce = Nonce ByteString deriving (Eq, Ord) instance IsEncoding Nonce where- decode v = case S.length v == Bytes.secretBoxNonce of- True -> Just (Nonce v)- False -> Nothing+ 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)+ zero = Nonce (S.replicate Bytes.secretBoxNonce 0) nudge (Nonce n) = Nonce (nudgeBS n) -- | Creates a random key of the correct size for 'secretbox'.@@ -93,15 +92,15 @@ -- | 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+ -> ByteString+ -- ^ Message+ -> ByteString+ -- ^ Ciphertext secretbox (Key key) (Nonce nonce) msg = unpad' . snd . buildUnsafeCVector len $ \pc -> constVectors [key, pad' msg, nonce] $ \ [(pk, _), (pm, _), (pn, _)] ->- c_secretbox pc pm (fromIntegral len) pn pk+ c_secretbox pc pm (fromIntegral len) pn pk where len = S.length msg + Bytes.secretBoxZero pad' = pad Bytes.secretBoxZero unpad' = unpad Bytes.secretBoxBoxZero@@ -117,7 +116,7 @@ let (err, vec) = buildUnsafeCVector len $ \pm -> constVectors [key, pad' cipher, nonce] $ \ [(pk, _), (pc, _), (pn, _)] ->- c_secretbox_open pm pc (fromIntegral len) pn pk+ 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@@ -126,28 +125,28 @@ -- | 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+ -- ^ 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 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+ -- ^ 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
src/Crypto/Saltine/Core/Sign.hs view
@@ -2,20 +2,20 @@ -- Module : Crypto.Saltine.Core.Sign -- Copyright : (c) Joseph Abrahamson 2013 -- License : MIT--- +-- -- Maintainer : me@jspha.com -- Stability : experimental -- Portability : non-portable--- +-- -- Signatures: "Crypto.Saltine.Core.Sign"--- +-- -- The 'newKeypair' function randomly generates a secret key and a -- corresponding public key. The 'sign' function signs a message -- 'ByteString' using the signer's secret key and returns the -- resulting signed message. The 'signOpen' function verifies the -- signature in a signed message using the signer's public key then -- returns the message without its signature.--- +-- -- "Crypto.Saltine.Core.Sign" is an EdDSA signature using -- elliptic-curve Curve25519 (see: <http://ed25519.cr.yp.to/>). See -- also, \"Daniel J. Bernstein, Niels Duif, Tanja Lange, Peter@@ -31,17 +31,17 @@ sign, signOpen ) where -import Crypto.Saltine.Class-import Crypto.Saltine.Internal.Util+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 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) -- $types @@ -49,9 +49,9 @@ newtype SecretKey = SK ByteString deriving (Eq, Ord) instance IsEncoding SecretKey where- decode v = case S.length v == Bytes.signSK of- True -> Just (SK v)- False -> Nothing+ decode v = if S.length v == Bytes.signSK+ then Just (SK v)+ else Nothing {-# INLINE decode #-} encode (SK v) = v {-# INLINE encode #-}@@ -60,9 +60,9 @@ newtype PublicKey = PK ByteString deriving (Eq, Ord) instance IsEncoding PublicKey where- decode v = case S.length v == Bytes.signPK of- True -> Just (PK v)- False -> Nothing+ decode v = if S.length v == Bytes.signPK+ then Just (PK v)+ else Nothing {-# INLINE decode #-} encode (PK v) = v {-# INLINE encode #-}@@ -78,21 +78,21 @@ -- _err ought to always be 0. ((_err, sk), pk) <- buildUnsafeCVector' Bytes.signPK $ \pkbuf -> buildUnsafeCVector' Bytes.signSK $ \skbuf ->- c_sign_keypair pkbuf skbuf+ c_sign_keypair pkbuf skbuf return (SK sk, PK pk) -- | Augments a message with a signature forming a \"signed -- message\". sign :: SecretKey- -> ByteString- -- ^ Message- -> ByteString- -- ^ Signed message-sign (SK k) m = unsafePerformIO $ + -> ByteString+ -- ^ Message+ -> ByteString+ -- ^ Signed message+sign (SK k) m = unsafePerformIO $ alloca $ \psmlen -> do (_err, sm) <- buildUnsafeCVector' (len + Bytes.sign) $ \psmbuf -> constVectors [k, m] $ \[(pk, _), (pm, _)] ->- c_sign psmbuf psmlen pm (fromIntegral len) pk+ c_sign psmbuf psmlen pm (fromIntegral len) pk smlen <- peek psmlen return $ S.take (fromIntegral smlen) sm where len = S.length m@@ -101,54 +101,54 @@ -- iff the signature was generated using the 'SecretKey' corresponding -- to the given 'PublicKey'. Returns 'Nothing' otherwise. signOpen :: PublicKey- -> ByteString- -- ^ Signed message- -> Maybe ByteString- -- ^ Maybe the restored message+ -> ByteString+ -- ^ Signed message+ -> Maybe ByteString+ -- ^ Maybe the restored message signOpen (PK k) sm = unsafePerformIO $ alloca $ \pmlen -> do (err, m) <- buildUnsafeCVector' smlen $ \pmbuf -> constVectors [k, sm] $ \[(pk, _), (psm, _)] ->- c_sign_open pmbuf pmlen psm (fromIntegral smlen) pk+ c_sign_open pmbuf pmlen psm (fromIntegral smlen) pk mlen <- peek pmlen case err of 0 -> return $ Just $ S.take (fromIntegral mlen) m- _ -> return $ Nothing+ _ -> return Nothing where smlen = 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+ -- ^ 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+ -- ^ 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+ -- ^ 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
src/Crypto/Saltine/Core/Stream.hs view
@@ -2,21 +2,21 @@ -- Module : Crypto.Saltine.Core.Stream -- Copyright : (c) Joseph Abrahamson 2013 -- License : MIT--- +-- -- Maintainer : me@jspha.com -- Stability : experimental -- Portability : non-portable--- +-- -- Secret-key encryption: -- "Crypto.Saltine.Core.Stream"--- +-- -- The 'stream' function produces a sized stream 'ByteString' as a -- function of a secret key and a nonce. The 'xor' function encrypts a -- message 'ByteString' using a secret key and a nonce. The 'xor' -- function guarantees that the ciphertext has the same length as the -- plaintext, and is the @plaintext `xor` stream k n@. Consequently -- 'xor' can also be used to decrypt.--- +-- -- The 'stream' function, viewed as a function of the nonce for a -- uniform random key, is designed to meet the standard notion of -- unpredictability (\"PRF\"). For a formal definition see, e.g.,@@ -29,22 +29,22 @@ -- 'xor' with /a different nonce for each message/, the ciphertexts -- are indistinguishable from uniform random strings of the same -- length.--- +-- -- 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.--- +-- -- Saltine does not make any promises regarding the resistance of -- crypto_stream to \"related-key attacks.\" It is the caller's -- responsibility to use proper key-derivation functions.--- +-- -- "Crypto.Saltine.Core.Stream" is @crypto_stream_xsalsa20@, a -- particular cipher specified in \"Cryptography in NaCl\" -- (<http://nacl.cr.yp.to/valid.html>), Section 7. This cipher is -- conjectured to meet the standard notion of unpredictability.--- +-- -- This is version 2010.08.30 of the stream.html web page. module Crypto.Saltine.Core.Stream (@@ -53,26 +53,25 @@ stream, xor ) where -import Crypto.Saltine.Class-import Crypto.Saltine.Internal.Util+import Crypto.Saltine.Class+import Crypto.Saltine.Internal.Util import qualified Crypto.Saltine.Internal.ByteSizes as Bytes -import Foreign.C-import Foreign.Ptr+import Control.Applicative+import Foreign.C+import Foreign.Ptr import qualified Data.ByteString as S import Data.ByteString (ByteString) -import Control.Applicative- -- $types -- | An opaque 'stream' cryptographic key. newtype Key = Key ByteString deriving (Eq, Ord) instance IsEncoding Key where- decode v = case S.length v == Bytes.streamKey of- True -> Just (Key v)- False -> Nothing+ decode v = if S.length v == Bytes.streamKey+ then Just (Key v)+ else Nothing {-# INLINE decode #-} encode (Key v) = v {-# INLINE encode #-}@@ -85,9 +84,9 @@ nudge (Nonce n) = Nonce (nudgeBS n) instance IsEncoding Nonce where- decode v = case S.length v == Bytes.streamNonce of- True -> Just (Nonce v)- False -> Nothing+ decode v = if S.length v == Bytes.streamNonce+ then Just (Nonce v)+ else Nothing {-# INLINE decode #-} encode (Nonce v) = v {-# INLINE encode #-}@@ -105,8 +104,8 @@ -- 'Nonce'. These streams are indistinguishable from random noise so -- long as the 'Nonce' is not used more than once. stream :: Key -> Nonce -> Int- -> ByteString- -- ^ Cryptographic stream+ -> ByteString+ -- ^ Cryptographic stream stream (Key key) (Nonce nonce) n = snd . buildUnsafeCVector n $ \ps -> constVectors [key, nonce] $ \[(pk, _), (pn, _)] ->@@ -119,11 +118,11 @@ -- for encryption and decryption, it is /possible for an attacker to/ -- /manipulate the message in transit without detection/. USE AT YOUR -- OWN RISK.-xor :: Key -> Nonce - -> ByteString- -- ^ Message- -> ByteString- -- ^ Ciphertext+xor :: Key -> Nonce+ -> ByteString+ -- ^ Message+ -> ByteString+ -- ^ Ciphertext xor (Key key) (Nonce nonce) msg = snd . buildUnsafeCVector len $ \pc -> constVectors [key, nonce, msg] $ \[(pk, _), (pn, _), (pm, _)] ->@@ -132,26 +131,26 @@ 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+ -- ^ 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+ -- ^ 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/ByteSizes.hs view
@@ -3,17 +3,17 @@ -- Module : Crypto.Saltine.Core.ScalarMult -- Copyright : (c) Joseph Abrahamson 2013 -- License : MIT--- +-- -- Maintainer : me@jspha.com -- 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@.@@ -28,6 +28,7 @@ boxBoxZero, boxMac, boxBeforeNM,+ sealedBox, onetime, onetimeKey, mult,@@ -44,7 +45,6 @@ hash, shorthash, shorthashKey- ) where import Foreign.C@@ -52,7 +52,8 @@ -- Constants for auth, authKey :: Int-boxPK, boxSK, boxNonce, boxZero, boxBoxZero, boxMac, boxBeforeNM :: Int+boxPK, boxSK, boxNonce, boxZero, boxBoxZero :: Int+boxMac, boxBeforeNM, sealedBox :: Int onetime, onetimeKey :: Int mult, multScalar :: Int secretBoxKey, secretBoxNonce, secretBoxZero, secretBoxBoxZero :: Int@@ -64,7 +65,7 @@ -- Authentication -- | Size of a @crypto_auth@ authenticator. auth = fromIntegral c_crypto_auth_bytes--- | Size of a @crypto_auth@ authenticator key. +-- | Size of a @crypto_auth@ authenticator key. authKey = fromIntegral c_crypto_auth_keybytes -- Box@@ -85,6 +86,11 @@ 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@@ -157,7 +163,11 @@ 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
src/Crypto/Saltine/Internal/Util.hs view
@@ -1,13 +1,14 @@ module Crypto.Saltine.Internal.Util where -import Foreign.C-import Foreign.Ptr-import System.IO.Unsafe+import Foreign.C+import Foreign.Ptr+import System.IO.Unsafe -import Data.Monoid-import qualified Data.ByteString as S-import Data.ByteString (ByteString)-import Data.ByteString.Unsafe+import Control.Applicative+import qualified Data.ByteString as S+import Data.ByteString (ByteString)+import Data.ByteString.Unsafe+import Data.Monoid -- | @snd . cycleSucc@ computes the 'succ' of a 'Bounded', 'Eq' 'Enum' -- with wraparound. The @fst . cycleSuc@ is whether the wraparound@@ -20,16 +21,17 @@ -- it. nudgeBS :: ByteString -> ByteString nudgeBS i = fst $ S.unfoldrN (S.length i) go (True, i) where- go (toSucc, bs) =- do (hd, tl) <- S.uncons bs- let (top, hd') = cycleSucc hd- if toSucc- then return (hd', (top, tl))- else return (hd, (top && toSucc, tl))+ go (toSucc, bs) = do+ (hd, tl) <- S.uncons bs+ let (top, hd') = cycleSucc hd + if toSucc+ then return (hd', (top, tl))+ else return (hd, (top && toSucc, tl))+ -- | Computes the orbit of a endomorphism... in a very brute force -- manner. Exists just for the below property.--- +-- -- prop> length . orbit nudgeBS . S.pack . replicate 0 == (256^) orbit :: Eq a => (a -> a) -> a -> [a] orbit f a0 = orbit' (f a0) where@@ -66,7 +68,7 @@ buildUnsafeCVector' :: Int -> (Ptr CChar -> IO b) -> IO (b, ByteString) buildUnsafeCVector' n k = do let bs = S.replicate n 0- out <- unsafeUseAsCString bs k+ out <- unsafeUseAsCString bs k return (out, bs) -- | Extremely unsafe function, use with utmost care! Builds a new@@ -80,7 +82,7 @@ -- @/dev/urandom@. randomVector :: Int -> IO ByteString randomVector n =- fmap snd $ buildUnsafeCVector' n (`c_randombytes_buf` fromIntegral n)+ snd <$> buildUnsafeCVector' n (`c_randombytes_buf` fromIntegral n) -- | To prevent a dependency on package 'errors' hush :: Either s a -> Maybe a
tests/AuthProperties.hs view
@@ -5,7 +5,6 @@ ) where import Util- import Crypto.Saltine.Core.Auth import Test.Framework.Providers.QuickCheck2@@ -17,6 +16,6 @@ return $ testGroup "...Internal.Auth" [ testProperty "Authenticates message"- $ \(Message bs) -> verify k (auth k bs) bs == True+ $ \(Message bs) -> verify k (auth k bs) bs == True ]
tests/BoxProperties.hs view
@@ -4,17 +4,14 @@ testBox ) where -import Util--import Crypto.Saltine.Core.Box--import qualified Data.ByteString as S--import Test.Framework.Providers.QuickCheck2-import Test.Framework+import Util+import Crypto.Saltine.Core.Box+import qualified Data.ByteString as S -import Test.QuickCheck.Property-import Test.QuickCheck.Monadic+import Test.Framework.Providers.QuickCheck2+import Test.Framework+import Test.QuickCheck.Property+import Test.QuickCheck.Monadic -- | Ciphertext can be decrypted rightInverseProp :: Keypair -> Keypair -> Nonce -> Message -> Bool@@ -67,7 +64,6 @@ testBox :: Test testBox = buildTest $ do- (sk1, pk1) <- newKeypair (sk2, pk2) <- newKeypair let ck_1for2 = beforeNM sk1 pk2@@ -78,39 +74,37 @@ return $ testGroup "...Internal.Box" [ testGroup "Can decrypt ciphertext using..." [- + testProperty "... public key/secret key" $ rightInverseProp (sk1, pk1) (sk2, pk2) n1 ,- + testProperty "... combined key" $ rightInverseAfterNMProp ck_1for2 ck_2for1 n1- + ], testGroup "Fail to verify ciphertext when..." [- + testProperty "... not using proper secret key" $ rightInverseFailureProp1 (sk1, pk1) (sk2, pk2) n1,- + testProperty "... not actually sent to you" $ rightInverseFailureProp2 (sk1, pk1) (sk2, pk2) n1,- + testProperty "... ciphertext has been perturbed" $ rightInverseFailureProp3 (sk1, pk1) (sk2, pk2) n1,- + testProperty "... using the wrong nonce" $ cannotDecryptNonceProp (sk1, pk1) (sk2, pk2) n1 n2,- + testProperty "... using the wrong combined key" $ rightInverseFailureAfterNMProp1 ck_1for2 ck_2for1 n1- + ], testGroup "(properties)" [ testProperty "beforeNM is anti-symmetric" beforeNMCreateSecretKeyProp- + ] ]- -
tests/Main.hs view
@@ -2,19 +2,21 @@ module Main where -import SecretBoxProperties (testSecretBox)-import BoxProperties (testBox)-import StreamProperties (testStream)-import AuthProperties (testAuth)+import SecretBoxProperties (testSecretBox)+import BoxProperties (testBox)+import SealedBoxProperties (testSealedBox)+import StreamProperties (testStream)+import AuthProperties (testAuth) import OneTimeAuthProperties (testOneTimeAuth)-import SignProperties (testSign)-import ScalarMultProperties (testScalarMult)+import SignProperties (testSign)+import ScalarMultProperties (testScalarMult) import Test.Framework main :: IO () main = defaultMain [ testBox,+ testSealedBox, testSecretBox, testStream, testAuth,
tests/OneTimeAuthProperties.hs view
tests/ScalarMultProperties.hs view
@@ -4,16 +4,14 @@ testScalarMult ) where -import Util--import Crypto.Saltine.Class-import Crypto.Saltine.Core.ScalarMult--import qualified Data.ByteString as S-import Data.Maybe (fromJust)+import Util+import Crypto.Saltine.Class+import Crypto.Saltine.Core.ScalarMult -import Test.Framework.Providers.QuickCheck2-import Test.Framework+import qualified Data.ByteString as S+import Data.Maybe (fromJust)+import Test.Framework.Providers.QuickCheck2+import Test.Framework -- Test vectors extracted from "Cryptography in NaCl", -- http://cr.yp.to/highspeed/naclcrypto-20090310.pdf@@ -47,7 +45,7 @@ ,0x76,0xf0,0x9b,0x3c,0x1e,0x16,0x17,0x42] testScalarMult :: Test-testScalarMult = buildTest $ do+testScalarMult = buildTest $ return $ testGroup "...Internal.ScalarMult" [ testProperty "mult a (multBase a) /= multBase a"
tests/SecretBoxProperties.hs view
@@ -4,14 +4,12 @@ testSecretBox ) where -import Util--import Crypto.Saltine.Core.SecretBox--import qualified Data.ByteString as S+import Util+import Crypto.Saltine.Core.SecretBox -import Test.Framework.Providers.QuickCheck2-import Test.Framework+import qualified Data.ByteString as S+import Test.Framework.Providers.QuickCheck2+import Test.Framework -- | Ciphertext can be decrypted rightInverseProp :: Key -> Nonce -> Message -> Bool@@ -55,6 +53,6 @@ testProperty "... using the wrong nonce" $ cannotDecryptNonceProp k1 n1 n2- + ] ]
tests/SignProperties.hs view
@@ -4,15 +4,13 @@ testSign ) where -import Util--import Crypto.Saltine.Core.Sign--import qualified Data.ByteString as S+import Util+import Crypto.Saltine.Core.Sign -import Test.Framework.Providers.QuickCheck2-import Test.Framework-import Test.QuickCheck+import qualified Data.ByteString as S+import Test.Framework.Providers.QuickCheck2+import Test.Framework+import Test.QuickCheck testSign :: Test testSign = buildTest $ do@@ -28,6 +26,6 @@ $ \(Message bs) -> S.length (sign sk1 bs) >= S.length bs, testProperty "Rejects message with mismatched key"- $ \(Message bs) -> (not $ S.null bs) ==> signOpen pk2 (sign sk1 bs) == Nothing+ $ \(Message bs) -> not (S.null bs) ==> signOpen pk2 (sign sk1 bs) == Nothing ]
tests/StreamProperties.hs view
@@ -4,15 +4,13 @@ testStream ) where -import Util--import Crypto.Saltine.Core.Stream--import qualified Data.ByteString as S+import Util+import Crypto.Saltine.Core.Stream -import Test.Framework.Providers.QuickCheck2-import Test.Framework-import Test.QuickCheck+import qualified Data.ByteString as S+import Test.Framework.Providers.QuickCheck2+import Test.Framework+import Test.QuickCheck testStream :: Test testStream = buildTest $ do@@ -30,7 +28,5 @@ testProperty "xor is involutive" $ \(Message bs) -> xor k n (xor k n bs) == bs- + ]- -
tests/Util.hs view
@@ -1,19 +1,18 @@ module Util where -import Test.QuickCheck--import Crypto.Saltine.Class+import Crypto.Saltine.Class -import qualified Data.ByteString as S+import Control.Applicative+import Control.Monad (replicateM)+import qualified Data.ByteString as S import qualified Data.ByteString.Char8 as S8-import Control.Monad (replicateM)+import Data.Maybe (fromMaybe)+import Test.QuickCheck -import Control.Applicative perturb :: IsEncoding a => a -> a-perturb a = case decode (S.reverse (encode a)) of- Just x -> x- Nothing -> error "Util.perturb"+perturb a = fromMaybe (error "Util.perturb")+ (decode (S.reverse (encode a))) newtype ByteString32 = ByteString32 S.ByteString deriving (Show)