packages feed

cacophony 0.7.0 → 0.8.0

raw patch · 13 files changed

+139/−97 lines, 13 filesdep +exceptionsdep +safe-exceptionsPVP ok

version bump matches the API change (PVP)

Dependencies added: exceptions, safe-exceptions

API changes (from Hackage documentation)

+ Crypto.Noise.HandshakePatterns: noiseXXfallback :: HandshakePattern
+ Crypto.Noise.Internal.Types: instance GHC.Exception.Exception Crypto.Noise.Internal.Types.NoiseException
- Crypto.Noise: hoLocalEphemeral :: forall d_atHx. Lens' (HandshakeOpts d_atHx) (Maybe (KeyPair d_atHx))
+ Crypto.Noise: hoLocalEphemeral :: forall d_atOc. Lens' (HandshakeOpts d_atOc) (Maybe (KeyPair d_atOc))
- Crypto.Noise: hoLocalSemiEphemeral :: forall d_atHx. Lens' (HandshakeOpts d_atHx) (Maybe (KeyPair d_atHx))
+ Crypto.Noise: hoLocalSemiEphemeral :: forall d_atOc. Lens' (HandshakeOpts d_atOc) (Maybe (KeyPair d_atOc))
- Crypto.Noise: hoLocalStatic :: forall d_atHx. Lens' (HandshakeOpts d_atHx) (Maybe (KeyPair d_atHx))
+ Crypto.Noise: hoLocalStatic :: forall d_atOc. Lens' (HandshakeOpts d_atOc) (Maybe (KeyPair d_atOc))
- Crypto.Noise: hoPattern :: forall d_atHx. Lens' (HandshakeOpts d_atHx) HandshakePattern
+ Crypto.Noise: hoPattern :: forall d_atOc. Lens' (HandshakeOpts d_atOc) HandshakePattern
- Crypto.Noise: hoPreSharedKey :: forall d_atHx. Lens' (HandshakeOpts d_atHx) (Maybe Plaintext)
+ Crypto.Noise: hoPreSharedKey :: forall d_atOc. Lens' (HandshakeOpts d_atOc) (Maybe Plaintext)
- Crypto.Noise: hoPrologue :: forall d_atHx. Lens' (HandshakeOpts d_atHx) Plaintext
+ Crypto.Noise: hoPrologue :: forall d_atOc. Lens' (HandshakeOpts d_atOc) Plaintext
- Crypto.Noise: hoRemoteEphemeral :: forall d_atHx. Lens' (HandshakeOpts d_atHx) (Maybe (PublicKey d_atHx))
+ Crypto.Noise: hoRemoteEphemeral :: forall d_atOc. Lens' (HandshakeOpts d_atOc) (Maybe (PublicKey d_atOc))
- Crypto.Noise: hoRemoteSemiEphemeral :: forall d_atHx. Lens' (HandshakeOpts d_atHx) (Maybe (PublicKey d_atHx))
+ Crypto.Noise: hoRemoteSemiEphemeral :: forall d_atOc. Lens' (HandshakeOpts d_atOc) (Maybe (PublicKey d_atOc))
- Crypto.Noise: hoRemoteStatic :: forall d_atHx. Lens' (HandshakeOpts d_atHx) (Maybe (PublicKey d_atHx))
+ Crypto.Noise: hoRemoteStatic :: forall d_atOc. Lens' (HandshakeOpts d_atOc) (Maybe (PublicKey d_atOc))
- Crypto.Noise: hoRole :: forall d_atHx. Lens' (HandshakeOpts d_atHx) HandshakeRole
+ Crypto.Noise: hoRole :: forall d_atOc. Lens' (HandshakeOpts d_atOc) HandshakeRole
- Crypto.Noise: readMessage :: (Cipher c, Hash h) => NoiseState c d h -> ByteString -> Either NoiseException (ScrubbedBytes, NoiseState c d h)
+ Crypto.Noise: readMessage :: (MonadThrow m, Cipher c, Hash h) => NoiseState c d h -> ByteString -> m (ScrubbedBytes, NoiseState c d h)
- Crypto.Noise: writeMessage :: (Cipher c, Hash h) => NoiseState c d h -> ScrubbedBytes -> Either NoiseException (ByteString, NoiseState c d h)
+ Crypto.Noise: writeMessage :: (MonadThrow m, Cipher c, Hash h) => NoiseState c d h -> ScrubbedBytes -> m (ByteString, NoiseState c d h)

Files

.travis.yml view
@@ -57,7 +57,6 @@       rm -rf $HOME/.cabsnap;       mkdir -p $HOME/.ghc $HOME/.cabal/lib $HOME/.cabal/share $HOME/.cabal/bin;       cabal install --only-dependencies --enable-tests --enable-benchmarks -fbuild-examples cacophony.cabal;-      if [ "$GHCVER" = "7.10.1" ]; then cabal install Cabal-1.22.4.0; fi;     fi    # snapshot package-db on cache miss
cacophony.cabal view
@@ -1,5 +1,5 @@ name:          cacophony-version:       0.7.0+version:       0.8.0 synopsis:      A library implementing the Noise protocol. license:       PublicDomain license-file:  LICENSE@@ -57,11 +57,13 @@     bytestring,     cryptonite >=0.16,     deepseq,+    exceptions >=0.8.3,     free,     lens,     memory,     monad-coroutine,     mtl,+    safe-exceptions,     transformers   hs-source-dirs:   src   default-language: Haskell2010
changelog.md view
@@ -1,3 +1,16 @@+# 0.8.0++* Exceptions are now provided by the safe-exceptions package+  (breaking API change)++* Added Noise\_XXfallback pattern++* Minor improvements to handshake pattern definition++* Updated non-standard handshake patterns to conform with rev 30++* Fixed bug which caused echo-server to read wrong public key+ # 0.7.0  * Major API overhaul and refactoring
examples/echo-server/Main.hs view
@@ -52,7 +52,7 @@ processOptions (Options{..}, [port, pskFile]) = do   local25519 <- processPrivateKey "server_key_25519"   local448 <- processPrivateKey "server_key_448"-  remote25519 <- readPublicKey "client_key_448.pub"+  remote25519 <- readPublicKey "client_key_25519.pub"   remote448 <- readPublicKey "client_key_448.pub"   psk <- readPSK pskFile 
src/Crypto/Noise.hs view
@@ -37,6 +37,7 @@   ) where  import Control.Arrow+import Control.Exception.Safe import Control.Lens import Data.ByteString (ByteString) import Data.Maybe      (isJust)@@ -58,18 +59,18 @@ -- --   To prevent catastrophic key re-use, this function may only be used to --   secure 2^64 post-handshake messages.-writeMessage :: (Cipher c, Hash h)+writeMessage :: (MonadThrow m, Cipher c, Hash h)              => NoiseState c d h              -> ScrubbedBytes-             -> Either NoiseException (ByteString, NoiseState c d h)-writeMessage ns msg = right toByteString $-  maybe (runHandshake msg ns)-        (right (ctToBytes *** updateState) . encryptAndIncrement "" msg)-        (ns ^. nsSendingCipherState)+             -> m (ByteString, NoiseState c d h)+writeMessage ns msg = maybe+  (first convertArr <$> runHandshake msg ns)+  (\cs -> (ctToBytes *** updateState) <$> encryptAndIncrement "" msg cs)+  (ns ^. nsSendingCipherState)   where-    ctToBytes    = arr cipherTextToBytes+    convertArr   = arr convert+    ctToBytes    = convertArr . arr cipherTextToBytes     updateState  = arr $ \cs -> ns & nsSendingCipherState .~ Just cs-    toByteString = first (arr convert)  -- | Reads a Noise message and returns the embedded payload. If the --   handshake fails, a 'HandshakeError' will be returned. After the handshake@@ -77,15 +78,16 @@ -- --   To prevent catastrophic key re-use, this function may only be used to --   receive 2^64 post-handshake messages.-readMessage :: (Cipher c, Hash h)+readMessage :: (MonadThrow m, Cipher c, Hash h)             => NoiseState c d h             -> ByteString-            -> Either NoiseException (ScrubbedBytes, NoiseState c d h)-readMessage ns ct =-  maybe (runHandshake (convert ct) ns)-        ((right . second) updateState . (decryptAndIncrement "" . cipherBytesToText . convert) ct)-        (ns ^. nsReceivingCipherState)+            -> m (ScrubbedBytes, NoiseState c d h)+readMessage ns ct = maybe+  (runHandshake (convert ct) ns)+  (\cs -> second updateState <$> decryptAndIncrement "" ct' cs)+  (ns ^. nsReceivingCipherState)   where+    ct'         = cipherBytesToText . convert $ ct     updateState = arr $ \cs -> ns & nsReceivingCipherState .~ Just cs  -- | For handshake patterns where the remote party's static key is
src/Crypto/Noise/HandshakePatterns.hs view
@@ -33,6 +33,7 @@   , noiseN   , noiseK   , noiseX+  , noiseXXfallback   ) where  import Crypto.Noise.Internal.HandshakePattern@@ -113,8 +114,8 @@ noiseNE :: HandshakePattern noiseNE = HandshakePattern "NE" $ do   preResponder $ do-    s     e+    s    initiator $ do     e@@ -138,8 +139,8 @@   preInitiator s    preResponder $ do-    s     e+    s    initiator $ do     e@@ -266,8 +267,8 @@ noiseXE :: HandshakePattern noiseXE = HandshakePattern "XE" $ do   preResponder $ do-    s     e+    s    initiator $ do     e@@ -292,8 +293,8 @@ noiseIE :: HandshakePattern noiseIE = HandshakePattern "IE" $ do   preResponder $ do-    s     e+    s    initiator $ do     e@@ -382,3 +383,22 @@     dhes     s     dhss++-- | @Noise_XXfallback(s, rs, re):+--  <- e+--  ...+--  -> e, dhee, s, dhse+--  <- s, dhse+noiseXXfallback :: HandshakePattern+noiseXXfallback = HandshakePattern "XXfallback" $ do+  preResponder e++  initiator $ do+    e+    dhee+    s+    dhse++  responder $ do+    s+    dhse
src/Crypto/Noise/Internal/CipherState.hs view
@@ -9,6 +9,7 @@  module Crypto.Noise.Internal.CipherState where +import Control.Exception.Safe import Control.Lens  import Crypto.Noise.Cipher@@ -22,28 +23,30 @@  $(makeLenses ''CipherState) -encryptAndIncrement :: Cipher c+encryptAndIncrement :: (MonadThrow m, Cipher c)                     => AssocData                     -> Plaintext                     -> CipherState c-                    -> Either NoiseException (Ciphertext c, CipherState c)-encryptAndIncrement ad plaintext cs | allow     = Right (ct, newState)-                                    | otherwise = Left $ MessageLimitReached "encryptAndIncrement"+                    -> m (Ciphertext c, CipherState c)+encryptAndIncrement ad plaintext cs+  | allow     = return (ct, newState)+  | otherwise = throwM $ MessageLimitReached "encryptAndIncrement"   where     ct       = cipherEncrypt (cs ^. csk) (cs ^. csn) ad plaintext     newState = cs & csn %~ cipherIncNonce     allow    = cs ^. csCount < 2 ^ (64 :: Integer) -decryptAndIncrement :: Cipher c+decryptAndIncrement :: (MonadThrow m, Cipher c)                     => AssocData                     -> Ciphertext c                     -> CipherState c-                    -> Either NoiseException (Plaintext, CipherState c)-decryptAndIncrement ad ct cs | allow     =-  maybe (Left $ DecryptionError "decryptAndIncrement")-        (\x -> Right (x, newState))-        pt-                             | otherwise = Left $ MessageLimitReached "decryptAndIncrement"+                    -> m (Plaintext, CipherState c)+decryptAndIncrement ad ct cs+  | allow     =+    maybe (throwM (DecryptionError "decryptAndIncrement"))+          (\x -> return (x, newState))+          pt+  | otherwise = throwM $ MessageLimitReached "decryptAndIncrement"   where     pt       = cipherDecrypt (cs ^. csk) (cs ^. csn) ad ct     newState = maybe cs (const (cs & csn %~ cipherIncNonce)) pt
src/Crypto/Noise/Internal/Handshake.hs view
@@ -14,7 +14,7 @@ import Control.Lens import Control.Monad.Coroutine import Control.Monad.Coroutine.SuspensionFunctors-import Control.Monad.Except (MonadError(..), Except)+import Control.Monad.Catch.Pure import Control.Monad.State  (MonadState(..), StateT) import Control.Monad.Trans.Class (MonadTrans(lift)) @@ -22,7 +22,6 @@ import Crypto.Noise.DH import Crypto.Noise.Internal.HandshakePattern import Crypto.Noise.Internal.SymmetricState-import Crypto.Noise.Internal.Types import Data.ByteArray.Extend  -- | Represents the side of the conversation upon which a party resides.@@ -54,17 +53,16 @@ $(makeLenses ''HandshakeState)  newtype Handshake c d h r =-  Handshake { runHandshake' :: Coroutine (Request ScrubbedBytes ScrubbedBytes) (StateT (HandshakeState c d h) (Except NoiseException)) r+  Handshake { runHandshake' :: Coroutine (Request ScrubbedBytes ScrubbedBytes) (StateT (HandshakeState c d h) Catch) r             } deriving ( Functor                        , Applicative                        , Monad-                       , MonadError NoiseException+                       , MonadThrow                        , MonadState (HandshakeState c d h)                        ) -instance (Functor f, MonadError e m) => MonadError e (Coroutine f m) where-  throwError = lift . throwError-  catchError m _ = m+instance (Functor f, MonadThrow m) => MonadThrow (Coroutine f m) where+  throwM = lift . throwM  instance (Functor f, MonadState s m) => MonadState s (Coroutine f m) where   get = lift get
src/Crypto/Noise/Internal/HandshakePattern.hs view
@@ -10,7 +10,7 @@ module Crypto.Noise.Internal.HandshakePattern where  import Control.Lens-import Control.Monad.Trans.Free.Church+import Control.Monad.Free.Church import Control.Monad.Free.TH import Data.ByteString (ByteString) @@ -26,10 +26,10 @@ $(makeFree ''TokenF)  data HandshakePatternF next-  = PreInitiator (FT TokenF Identity ()) next-  | PreResponder (FT TokenF Identity ()) next-  | Initiator (FT TokenF Identity ()) next-  | Responder (FT TokenF Identity ()) next+  = PreInitiator (F TokenF ()) next+  | PreResponder (F TokenF ()) next+  | Initiator (F TokenF ()) next+  | Responder (F TokenF ()) next   deriving Functor  $(makeFree ''HandshakePatternF)@@ -38,7 +38,7 @@ --   Free Monad. data HandshakePattern =   HandshakePattern { _hpName    :: ByteString-                   , _hpActions :: FT HandshakePatternF Identity ()+                   , _hpActions :: F HandshakePatternF ()                    }  $(makeLenses ''HandshakePattern)
src/Crypto/Noise/Internal/NoiseState.hs view
@@ -9,11 +9,11 @@  module Crypto.Noise.Internal.NoiseState where +import Control.Monad.Catch.Pure import Control.Monad.Coroutine import Control.Monad.Coroutine.SuspensionFunctors-import Control.Monad.Except (MonadError(..), runExcept) import Control.Monad.State  (MonadState(..), runStateT, get, put)-import Control.Monad.Trans.Free.Church+import Control.Monad.Free.Church import Control.Lens import Data.ByteString      (ByteString) import Data.Maybe           (isJust)@@ -93,15 +93,16 @@     ss'  = mixHash (ho ^. hoPrologue) ss     ss'' = maybe ss' (`mixPSK` ss') $ ho ^. hoPreSharedKey -runHandshake :: (Cipher c, Hash h)+runHandshake :: (MonadThrow m, Cipher c, Hash h)              => ScrubbedBytes              -> NoiseState c d h-             -> Either NoiseException (ScrubbedBytes, NoiseState c d h)-runHandshake msg ns = runExcept $ do+             -> m (ScrubbedBytes, NoiseState c d h)+runHandshake msg ns = reThrow . runCatch $ do   ((res, ns''), hs') <- runStateT st $ ns ^. nsHandshakeState   return (res, ns'' & nsHandshakeState .~ hs')    where+    reThrow = either throwM return     st = do       x <- resume . runHandshake' . (ns ^. nsHandshakeSuspension) $ msg       case x of@@ -130,8 +131,8 @@    where     hs        = handshakeState ho :: HandshakeState c d h-    coroutine = iterM evalPattern $ hoistFT (return . runIdentity) (ho ^. hoPattern . hpActions)-    (suspension, hs'') = case runExcept (runStateT (resume (runHandshake' coroutine)) hs) of+    coroutine = iterM evalPattern $ ho ^. hoPattern . hpActions+    (suspension, hs'') = case runCatch (runStateT (resume (runHandshake' coroutine)) hs) of             Left err -> error $ "handshake pattern interpreter threw exception: " <> show err             Right result -> case result of               (Left (Request _ resp), hs') -> (Handshake . resp, hs')@@ -139,7 +140,7 @@  processPatternOp :: (Cipher c, DH d, Hash h)                  => HandshakeRole-                 -> FT TokenF Identity ()+                 -> F TokenF ()                  -> Handshake c d h ()                  -> Handshake c d h () processPatternOp opRole t next = do@@ -149,19 +150,19 @@    if opRole == hs' ^. hsOpts . hoRole then do     put $ hs' & hsMsgBuffer .~ mempty-    iterM (evalMsgToken opRole) $ hoistFT (return . runIdentity) t+    iterM (evalMsgToken opRole) t      hs'' <- get      let enc = encryptAndHash (convert input) $ hs'' ^. hsSymmetricState -    (ep, ss) <- either throwError return enc+    (ep, ss) <- either throwM return enc      put $ hs'' & hsMsgBuffer      %~ (flip mappend . convert) ep                & hsSymmetricState .~ ss   else do     put $ hs' & hsMsgBuffer .~ input-    iterM (evalMsgToken opRole) $ hoistFT (return . runIdentity) t+    iterM (evalMsgToken opRole) t      hs'' <- get @@ -169,7 +170,7 @@         dec       = decryptAndHash (cipherBytesToText (convert remaining))                     $ hs'' ^. hsSymmetricState -    (dp, ss) <- either (const . throwError . HandshakeError $ "handshake payload failed to decrypt") return dec+    (dp, ss) <- either (const . throwM . HandshakeError $ "handshake payload failed to decrypt") return dec      put $ hs'' & hsMsgBuffer      .~ convert dp                & hsSymmetricState .~ ss@@ -180,11 +181,11 @@             => HandshakePatternF (Handshake c d h ())             -> Handshake c d h () evalPattern (PreInitiator t next) = do-  iterM (evalPreMsgToken InitiatorRole) $ hoistFT (return . runIdentity) t+  iterM (evalPreMsgToken InitiatorRole) t   next  evalPattern (PreResponder t next) = do-  iterM (evalPreMsgToken ResponderRole) $ hoistFT (return . runIdentity) t+  iterM (evalPreMsgToken ResponderRole) t   next  evalPattern (Initiator t next) = processPatternOp InitiatorRole t next@@ -215,7 +216,7 @@         ss''      = if ss ^. ssHasPSK then mixKey reBytes ss' else ss'         theirKey  = dhBytesToPub reBytes -    theirKey' <- maybe (throwError . HandshakeError $ "invalid remote ephemeral key") return theirKey+    theirKey' <- maybe (throwM . HandshakeError $ "invalid remote ephemeral key") return theirKey      put $ hs & hsOpts . hoRemoteEphemeral .~ Just theirKey'              & hsSymmetricState           .~ ss''@@ -231,13 +232,13 @@     let ss  = hs ^. hsSymmetricState         enc = encryptAndHash (convert pk) ss -    (ct, ss') <- either throwError return enc+    (ct, ss') <- either throwM return enc      put $ hs & hsSymmetricState .~ ss'              & hsMsgBuffer      %~ (flip mappend . convert) ct   else     if isJust (hs ^. hsOpts ^. hoRemoteStatic)-      then throwError . InvalidHandshakeOptions $ "unable to overwrite remote static key"+      then throwM . InvalidHandshakeOptions $ "unable to overwrite remote static key"       else do         let hasKey    = hs ^. hsSymmetricState . ssHasKey             len       = dhLength (Proxy :: Proxy d)@@ -248,8 +249,8 @@             ss        = hs ^. hsSymmetricState             dec       = decryptAndHash ct ss -        (pt, ss')     <- either (const . throwError . HandshakeError $ "failed to decrypt remote static key") return dec-        theirKey'     <- maybe (throwError . HandshakeError $ "invalid remote static key provided") return $ dhBytesToPub pt+        (pt, ss')     <- either (const . throwM . HandshakeError $ "failed to decrypt remote static key") return dec+        theirKey'     <- maybe (throwM . HandshakeError $ "invalid remote static key provided") return $ dhBytesToPub pt          put $ hs & hsOpts . hoRemoteStatic .~ Just theirKey'                  & hsSymmetricState        .~ ss'@@ -354,36 +355,36 @@  getLocalStatic :: HandshakeState c d h                -> Handshake c d h (KeyPair d)-getLocalStatic hs = maybe (throwError (InvalidHandshakeOptions "local static key not set"))+getLocalStatic hs = maybe (throwM (InvalidHandshakeOptions "local static key not set"))                           return                           (hs ^. hsOpts ^. hoLocalStatic)  getLocalSemiEphemeral :: HandshakeState c d h                       -> Handshake c d h (KeyPair d)-getLocalSemiEphemeral hs = maybe (throwError (InvalidHandshakeOptions "local semi-ephemeral key not set"))+getLocalSemiEphemeral hs = maybe (throwM (InvalidHandshakeOptions "local semi-ephemeral key not set"))                                  return                                  (hs ^. hsOpts ^. hoLocalSemiEphemeral)  getLocalEphemeral :: HandshakeState c d h                   -> Handshake c d h (KeyPair d)-getLocalEphemeral hs = maybe (throwError (InvalidHandshakeOptions "local ephemeral key not set"))+getLocalEphemeral hs = maybe (throwM (InvalidHandshakeOptions "local ephemeral key not set"))                              return                              (hs ^. hsOpts ^. hoLocalEphemeral)  getRemoteStatic :: HandshakeState c d h                 -> Handshake c d h (PublicKey d)-getRemoteStatic hs = maybe (throwError (InvalidHandshakeOptions "remote static key not set"))+getRemoteStatic hs = maybe (throwM (InvalidHandshakeOptions "remote static key not set"))                            return                            (hs ^. hsOpts ^. hoRemoteStatic)  getRemoteSemiEphemeral :: HandshakeState c d h                        -> Handshake c d h (PublicKey d)-getRemoteSemiEphemeral hs = maybe (throwError (InvalidHandshakeOptions "remote semi-ephemeral key not set"))+getRemoteSemiEphemeral hs = maybe (throwM (InvalidHandshakeOptions "remote semi-ephemeral key not set"))                                   return                                   (hs ^. hsOpts ^. hoRemoteSemiEphemeral)  getRemoteEphemeral :: HandshakeState c d h                    -> Handshake c d h (PublicKey d)-getRemoteEphemeral hs = maybe (throwError (InvalidHandshakeOptions "remote ephemeral key not set"))+getRemoteEphemeral hs = maybe (throwM (InvalidHandshakeOptions "remote ephemeral key not set"))                               return                               (hs ^. hsOpts ^. hoRemoteEphemeral)
src/Crypto/Noise/Internal/SymmetricState.hs view
@@ -9,6 +9,8 @@  module Crypto.Noise.Internal.SymmetricState where +import Control.Arrow+import Control.Exception.Safe import Control.Lens import Data.ByteString (empty) import Data.Proxy@@ -17,7 +19,6 @@ import Crypto.Noise.Cipher import Crypto.Noise.Hash import Crypto.Noise.Internal.CipherState-import Crypto.Noise.Internal.Types import Data.ByteArray.Extend  data SymmetricState c h =@@ -71,29 +72,29 @@         -> SymmetricState c h mixHash d ss = ss & ssh %~ Right . hash . (`mappend` d) . sshBytes -encryptAndHash :: (Cipher c, Hash h)+encryptAndHash :: (MonadThrow m, Cipher c, Hash h)                => Plaintext                -> SymmetricState c h-               -> Either NoiseException (ScrubbedBytes, SymmetricState c h)+               -> m (ScrubbedBytes, SymmetricState c h) encryptAndHash pt ss-  | ss ^. ssHasKey = either Left (\(ct, cs') -> Right (cipherTextToBytes ct, kss ct cs')) enc-  | otherwise      = Right (pt, nkss)+  | ss ^. ssHasKey = mix . first toBytes <$> enc+  | otherwise      = return (pt, mixHash pt ss)   where-    enc       = encryptAndIncrement (sshBytes (ss ^. ssh)) pt (ss ^. ssCipher)-    kss ct cs = mixHash (cipherTextToBytes ct) ss & ssCipher .~ cs-    nkss      = mixHash pt ss+    enc          = encryptAndIncrement (sshBytes (ss ^. ssh)) pt (ss ^. ssCipher)+    mix (cb, cs) = (cb, mixHash cb ss & ssCipher .~ cs)+    toBytes      = arr cipherTextToBytes -decryptAndHash :: (Cipher c, Hash h)+decryptAndHash :: (MonadThrow m, Cipher c, Hash h)                => Ciphertext c                -> SymmetricState c h-               -> Either NoiseException (Plaintext, SymmetricState c h)+               -> m (Plaintext, SymmetricState c h) decryptAndHash ct ss-  | ss ^. ssHasKey = either Left (\(pt, cs') -> Right (pt, kss cs')) dec-  | otherwise      = Right (cipherTextToBytes ct, nkss)+  | ss ^. ssHasKey = second kss <$> dec+  | otherwise      = return (ct', mixHash ct' ss)   where-    dec    = decryptAndIncrement (sshBytes (ss ^. ssh)) ct (ss ^. ssCipher)-    kss cs = mixHash (cipherTextToBytes ct) ss & ssCipher .~ cs-    nkss   = mixHash (cipherTextToBytes ct) ss+    dec  = decryptAndIncrement (sshBytes (ss ^. ssh)) ct (ss ^. ssCipher)+    kss  = arr $ \cs -> mixHash ct' ss & ssCipher .~ cs+    ct'  = cipherTextToBytes ct  split :: (Cipher c, Hash h)       => SymmetricState c h
src/Crypto/Noise/Internal/Types.hs view
@@ -7,6 +7,8 @@  module Crypto.Noise.Internal.Types where +import Control.Exception.Safe+ -- | Represents the various exceptions which can be thrown. -- --   * 'InvalidHandshakeOptions' occurs when a key that is needed is missing, or@@ -31,3 +33,5 @@                     | HandshakeError String                     | MessageLimitReached String                     deriving Show++instance Exception NoiseException
tests/vectors/Verify.hs view
@@ -3,6 +3,7 @@  import Control.Arrow import Control.Concurrent.Async (mapConcurrently)+import Control.Exception        (SomeException) import Control.Monad.State import Data.Aeson               (decode) import Data.ByteString          (ByteString)@@ -67,21 +68,19 @@               => NoiseState c d h               -> NoiseState c d h               -> Message-              -> (Either NoiseException (ByteString, ByteString, NoiseState c d h),-                  Either NoiseException (ByteString, ByteString, NoiseState c d h))+              -> (Either SomeException (ByteString, ByteString, NoiseState c d h),+                  Either SomeException (ByteString, ByteString, NoiseState c d h)) verifyMessage sendingState receivingState Message{..} = (sendResult, recvResult)   where-    payload        = fromMaybe "" mPayload-    writeMsg       = writeMessage sendingState payload-    readMsg        = readMessage receivingState mCiphertext-    convertPayload = either Left (\(p, s) -> Right (convert p, convert payload, s))-    convertCt      = either Left (\(p, s) -> Right (p, mCiphertext , s))-    sendResult     = convertCt writeMsg-    recvResult     = convertPayload readMsg+    payload            = fromMaybe "" mPayload+    convertSend (p, s) = (p, mCiphertext, s)+    convertRecv (c, s) = (convert c, convert payload, s)+    sendResult         = convertSend <$> writeMessage sendingState payload+    recvResult         = convertRecv <$> readMessage receivingState mCiphertext  verifyVector :: Vector-             -> [(Either NoiseException (ByteString, ByteString),-                  Either NoiseException (ByteString, ByteString))]+             -> [(Either SomeException (ByteString, ByteString),+                  Either SomeException (ByteString, ByteString))] verifyVector v@Vector{..} =   case (vCipher, vDH, vHash) of     (WrapCipherType c, WrapDHType d, WrapHashType h) ->@@ -112,7 +111,7 @@  printFailure :: Int              -> Bool-             -> Either NoiseException (ByteString, ByteString)+             -> Either SomeException (ByteString, ByteString)              -> IO () printFailure i payload mr =   case mr of