cacophony 0.1.0.0 → 0.2.0
raw patch · 17 files changed
+316/−46 lines, 17 files
Files
- cacophony.cabal +7/−4
- changelog.md +11/−0
- src/Crypto/Noise/Cipher.hs +1/−1
- src/Crypto/Noise/Cipher/ChaChaPoly1305.hs +2/−3
- src/Crypto/Noise/Curve.hs +1/−1
- src/Crypto/Noise/Curve/Curve25519.hs +2/−3
- src/Crypto/Noise/Descriptors.hs +106/−3
- src/Crypto/Noise/Handshake.hs +3/−1
- src/Crypto/Noise/Hash.hs +1/−1
- src/Crypto/Noise/Hash/SHA256.hs +4/−5
- src/Crypto/Noise/Internal/CipherState.hs +1/−1
- src/Crypto/Noise/Internal/HandshakeState.hs +3/−3
- src/Crypto/Noise/Internal/SymmetricHandshakeState.hs +1/−1
- src/Crypto/Noise/Types.hs +30/−3
- tests/Handshake.hs +132/−4
- tests/Instances.hs +10/−9
- tests/SymmetricHandshakeState.hs +1/−3
cacophony.cabal view
@@ -1,20 +1,24 @@ name: cacophony-version: 0.1.0.0+version: 0.2.0 synopsis: A library implementing the Noise protocol. license: PublicDomain license-file: LICENSE author: John Galt-maintainer: centromere@users.noreply.github.com-homepage: https://github.com/centromere/cacophony/wiki+maintainer: jgalt@centromere.net+homepage: https://github.com/centromere/cacophony bug-reports: https://github.com/centromere/cacophony/issues category: Cryptography build-type: Simple cabal-version: >=1.10 tested-with: GHC == 7.10.1, GHC == 7.10.2+description:+ This library implements the <https://github.com/trevp/noise/blob/master/noise.md Noise>+ protocol. extra-source-files: .travis.yml README.md+ changelog.md LICENSE source-repository head@@ -77,7 +81,6 @@ base >= 4.8 && < 4.9, bytestring, cacophony,- memory, mtl, QuickCheck, tasty,
+ changelog.md view
@@ -0,0 +1,11 @@+# 0.2.0++* Added support for one-way handshakes++* Fixed Noise_IX++* Added helper functions for ScrubbedBytes / ByteString conversion++# 0.1.0.0++* First version.
src/Crypto/Noise/Cipher.hs view
@@ -2,7 +2,7 @@ ---------------------------------------------------------------- -- | -- Module : Crypto.Noise.Cipher--- Maintainer : John Galt <centromere@users.noreply.github.com>+-- Maintainer : John Galt <jgalt@centromere.net> -- Stability : experimental -- Portability : POSIX
src/Crypto/Noise/Cipher/ChaChaPoly1305.hs view
@@ -2,7 +2,7 @@ ---------------------------------------------------------------- -- | -- Module : Crypto.Noise.Cipher.ChaChaPoly1305--- Maintainer : John Galt <centromere@users.noreply.github.com>+-- Maintainer : John Galt <jgalt@centromere.net> -- Stability : experimental -- Portability : POSIX @@ -15,7 +15,6 @@ import qualified Crypto.Cipher.ChaChaPoly1305 as CCP import qualified Crypto.MAC.Poly1305 as P import qualified Data.ByteArray as B (take, drop, length)-import Data.ByteString (ByteString) import qualified Data.ByteString as BS (replicate) import Crypto.Noise.Cipher@@ -29,7 +28,7 @@ newtype SymmetricKey ChaChaPoly1305 = SKCCP1305 ScrubbedBytes newtype Nonce ChaChaPoly1305 = NCCP1305 CCP.Nonce - cipherName _ = convert ("ChaChaPoly" :: ByteString)+ cipherName _ = bsToSB' "ChaChaPoly" cipherEncrypt = encrypt cipherDecrypt = decrypt cipherZeroNonce = zeroNonce
src/Crypto/Noise/Curve.hs view
@@ -2,7 +2,7 @@ ---------------------------------------------------------------- -- | -- Module : Crypto.Noise.Curve--- Maintainer : John Galt <centromere@users.noreply.github.com>+-- Maintainer : John Galt <jgalt@centromere.net> -- Stability : experimental -- Portability : POSIX
src/Crypto/Noise/Curve/Curve25519.hs view
@@ -2,7 +2,7 @@ ---------------------------------------------------------------- -- | -- Module : Crypto.Noise.Curve.Curve25519--- Maintainer : John Galt <centromere@users.noreply.github.com>+-- Maintainer : John Galt <jgalt@centromere.net> -- Stability : experimental -- Portability : POSIX @@ -13,7 +13,6 @@ import Crypto.Random.Entropy import qualified Crypto.PubKey.Curve25519 as C-import Data.ByteString (ByteString) import Crypto.Noise.Curve import Crypto.Noise.Types@@ -25,7 +24,7 @@ newtype PublicKey Curve25519 = PK25519 C.PublicKey newtype SecretKey Curve25519 = SK25519 C.SecretKey - curveName _ = convert ("25519" :: ByteString)+ curveName _ = bsToSB' "25519" curveLength _ = 32 curveGenKey = genKey curveDH = dh
src/Crypto/Noise/Descriptors.hs view
@@ -1,7 +1,7 @@ ---------------------------------------------------------------- -- | -- Module : Crypto.Noise.Descriptors--- Maintainer : John Galt <centromere@users.noreply.github.com>+-- Maintainer : John Galt <jgalt@centromere.net> -- Stability : experimental -- Portability : POSIX --@@ -134,7 +134,22 @@ noiseIXI1, noiseIXR1, noiseIXR2,- noiseIXI2+ noiseIXI2,+ -- * Noise_N+ noiseNI0,+ noiseNR0,+ noiseNI1,+ noiseNR1,+ -- * Noise_K+ noiseKI0,+ noiseKR0,+ noiseKI1,+ noiseKR1,+ -- * Noise_X+ noiseXI0,+ noiseXR0,+ noiseXI1,+ noiseXR1 ) where import Control.Monad ((>=>))@@ -819,7 +834,7 @@ noiseIXI1 = do s <- tokenWS e <- tokenWE- return $ e `append` s+ return $ s `append` e noiseIXR1 :: (Cipher c, Curve d, Hash h) => ByteString@@ -845,4 +860,92 @@ tokenDHSE rest' <- tokenRS rest tokenDHES+ return rest'++--------------------------------------------------------------------------------+-- Noise_N++noiseNI0 :: (Cipher c, Curve d, Hash h)+ => Descriptor c d h ()+noiseNI0 = tokenPreRS++noiseNR0 :: (Cipher c, Curve d, Hash h)+ => Descriptor c d h ()+noiseNR0 = tokenPreLS++noiseNI1 :: (Cipher c, Curve d, Hash h)+ => DescriptorIO c d h ByteString+noiseNI1 = do+ e <- tokenWE+ tokenDHES+ return e++noiseNR1 :: (Cipher c, Curve d, Hash h)+ => ByteString+ -> Descriptor c d h ByteString+noiseNR1 buf = do+ rest <- tokenRE buf+ tokenDHSE+ return rest++--------------------------------------------------------------------------------+-- Noise_K++noiseKI0 :: (Cipher c, Curve d, Hash h)+ => Descriptor c d h ()+noiseKI0 = do+ tokenPreRS+ tokenPreLS++noiseKR0 :: (Cipher c, Curve d, Hash h)+ => Descriptor c d h ()+noiseKR0 = do+ tokenPreLS+ tokenPreRS++noiseKI1 :: (Cipher c, Curve d, Hash h)+ => DescriptorIO c d h ByteString+noiseKI1 = do+ e <- tokenWE+ tokenDHES+ tokenDHSS+ return e++noiseKR1 :: (Cipher c, Curve d, Hash h)+ => ByteString+ -> Descriptor c d h ByteString+noiseKR1 buf = do+ rest <- tokenRE buf+ tokenDHSE+ tokenDHSS+ return rest++--------------------------------------------------------------------------------+-- Noise_X++noiseXI0 :: (Cipher c, Curve d, Hash h)+ => Descriptor c d h ()+noiseXI0 = tokenPreRS++noiseXR0 :: (Cipher c, Curve d, Hash h)+ => Descriptor c d h ()+noiseXR0 = tokenPreLS++noiseXI1 :: (Cipher c, Curve d, Hash h)+ => DescriptorIO c d h ByteString+noiseXI1 = do+ e <- tokenWE+ tokenDHES+ s <- tokenWS+ tokenDHSS+ return $ e `append` s++noiseXR1 :: (Cipher c, Curve d, Hash h)+ => ByteString+ -> Descriptor c d h ByteString+noiseXR1 buf = do+ rest <- tokenRE buf+ tokenDHSE+ rest' <- tokenRS rest+ tokenDHSS return rest'
src/Crypto/Noise/Handshake.hs view
@@ -1,7 +1,7 @@ ---------------------------------------------------------------- -- | -- Module : Crypto.Noise.Handshake--- Maintainer : John Galt <centromere@users.noreply.github.com>+-- Maintainer : John Galt <jgalt@centromere.net> -- Stability : experimental -- Portability : POSIX --@@ -12,6 +12,7 @@ HandshakeState, Descriptor, DescriptorIO,+ CipherState, -- * Functions getRemoteStaticKey, handshakeState,@@ -24,3 +25,4 @@ ) where import Crypto.Noise.Internal.HandshakeState+import Crypto.Noise.Internal.CipherState
src/Crypto/Noise/Hash.hs view
@@ -2,7 +2,7 @@ ---------------------------------------------------------------- -- | -- Module : Crypto.Noise.Hash--- Maintainer : John Galt <centromere@users.noreply.github.com>+-- Maintainer : John Galt <jgalt@centromere.net> -- Stability : experimental -- Portability : POSIX
src/Crypto/Noise/Hash/SHA256.hs view
@@ -2,7 +2,7 @@ ---------------------------------------------------------------- -- | -- Module : Crypto.Noise.Hash.SHA256--- Maintainer : John Galt <centromere@users.noreply.github.com>+-- Maintainer : John Galt <jgalt@centromere.net> -- Stability : experimental -- Portability : POSIX @@ -13,7 +13,6 @@ import qualified Crypto.Hash as H import qualified Crypto.MAC.HMAC as M-import Data.ByteString (ByteString) import Crypto.Noise.Hash import Crypto.Noise.Types@@ -25,7 +24,7 @@ newtype ChainingKey SHA256 = HCKSHA256 ScrubbedBytes newtype Digest SHA256 = HDSHA256 (H.Digest H.SHA256) - hashName _ = convert ("SHA256" :: ByteString)+ hashName _ = bsToSB' "SHA256" hashLength _ = 32 hash = hash' hashHKDF = hkdf@@ -39,8 +38,8 @@ hkdf :: ChainingKey SHA256 -> ScrubbedBytes -> (ChainingKey SHA256, ScrubbedBytes) hkdf (HCKSHA256 ck) d = (HCKSHA256 ck', sk) where- x01 = convert ("\x01" :: ByteString) :: ScrubbedBytes- x02 = convert ("\x02" :: ByteString) :: ScrubbedBytes+ x01 = bsToSB' "\x01"+ x02 = bsToSB' "\x02" hmac1 = M.hmac ck d :: M.HMAC H.SHA256 temp = convert . M.hmacGetDigest $ hmac1 :: ScrubbedBytes
src/Crypto/Noise/Internal/CipherState.hs view
@@ -2,7 +2,7 @@ ---------------------------------------------------------------- -- | -- Module : Crypto.Noise.Internal.CipherState--- Maintainer : John Galt <centromere@users.noreply.github.com>+-- Maintainer : John Galt <jgalt@centromere.net> -- Stability : experimental -- Portability : POSIX
src/Crypto/Noise/Internal/HandshakeState.hs view
@@ -4,7 +4,7 @@ ---------------------------------------------------------------- -- | -- Module : Crypto.Noise.Internal.HandshakeState--- Maintainer : John Galt <centromere@users.noreply.github.com>+-- Maintainer : John Galt <jgalt@centromere.net> -- Stability : experimental -- Portability : POSIX @@ -308,7 +308,7 @@ encryptPayload pt cs = ((convert . cipherTextToBytes) ct, cs') where (ct, cs') = encryptAndIncrement ad pt cs- ad = AssocData $ convert ("" :: ByteString)+ ad = AssocData . bsToSB' $ "" -- | Decrypts a payload. The returned 'CipherState' must be used for all -- subsequent calls.@@ -321,4 +321,4 @@ decryptPayload ct cs = (pt, cs') where (pt, cs') = decryptAndIncrement ad ((cipherBytesToText . convert) ct) cs- ad = AssocData $ convert ("" :: ByteString)+ ad = AssocData . bsToSB' $ ""
src/Crypto/Noise/Internal/SymmetricHandshakeState.hs view
@@ -2,7 +2,7 @@ ---------------------------------------------------------------- -- | -- Module : Crypto.Noise.Internal.SymmetricHandshakeState--- Maintainer : John Galt <centromere@users.noreply.github.com>+-- Maintainer : John Galt <jgalt@centromere.net> -- Stability : experimental -- Portability : POSIX
src/Crypto/Noise/Types.hs view
@@ -1,7 +1,7 @@ ---------------------------------------------------------------- -- | -- Module : Crypto.Noise.Types--- Maintainer : John Galt <centromere@users.noreply.github.com>+-- Maintainer : John Galt <jgalt@centromere.net> -- Stability : experimental -- Portability : POSIX @@ -10,7 +10,34 @@ ScrubbedBytes, -- * Functions convert,- append+ append,+ concatSB,+ bsToSB,+ bsToSB',+ sbToBS,+ sbToBS',+ sbEq ) where -import Data.ByteArray (ScrubbedBytes, convert, append)+import Data.ByteArray (ScrubbedBytes, concat, convert, append, eq)+import qualified Data.ByteString as BS (ByteString)+import qualified Data.ByteString.Lazy as BL (ByteString, toStrict, fromStrict)+import Prelude hiding (concat)++concatSB :: [ScrubbedBytes] -> ScrubbedBytes+concatSB = concat++bsToSB :: BL.ByteString -> ScrubbedBytes+bsToSB = convert . BL.toStrict++bsToSB' :: BS.ByteString -> ScrubbedBytes+bsToSB' = convert++sbToBS :: ScrubbedBytes -> BL.ByteString+sbToBS = BL.fromStrict . convert++sbToBS' :: ScrubbedBytes -> BS.ByteString+sbToBS' = convert++sbEq :: ScrubbedBytes -> ScrubbedBytes -> Bool+sbEq = eq
tests/Handshake.hs view
@@ -17,18 +17,17 @@ import Crypto.Noise.Types import Data.ByteString (ByteString)-import qualified Data.ByteArray as BA (concat) sampleHSPT :: Plaintext-sampleHSPT = Plaintext $ convert ("cacophony" :: ByteString)+sampleHSPT = Plaintext . bsToSB' $ "cacophony" makeHSN :: ByteString -> ScrubbedBytes-makeHSN hs = BA.concat [convert hs, u, a, u, b, u, c]+makeHSN hs = concatSB [convert hs, u, a, u, b, u, c] where a = curveName (Proxy :: Proxy Curve25519) b = cipherName (Proxy :: Proxy ChaChaPoly1305) c = hashName (Proxy :: Proxy SHA256)- u = convert ("_" :: ByteString)+ u = bsToSB' "_" -------------------------------------------------------------------------------- -- Noise_NN@@ -765,6 +764,131 @@ encrypt cs p = fst $ encryptPayload p cs decrypt cs ct = fst $ decryptPayload ct cs +--------------------------------------------------------------------------------+-- Noise_N++hsnN :: ScrubbedBytes+hsnN = makeHSN "Noise_N"++doN :: Plaintext -> Property+doN pt = ioProperty $ do+ bobStaticKey@(_, bobStaticPK) <- curveGenKey :: IO (KeyPair Curve25519)++ let aliceN = handshakeState+ hsnN+ Nothing+ Nothing+ (Just bobStaticPK)+ Nothing+ (Just noiseNI0) :: HandshakeState ChaChaPoly1305 Curve25519 SHA256++ bobN = handshakeState+ hsnN+ (Just bobStaticKey)+ Nothing+ Nothing+ Nothing+ (Just noiseNR0) :: HandshakeState ChaChaPoly1305 Curve25519 SHA256++ (aliceToBob1, csAlice1, csAlice2) <- writeHandshakeMsgFinal aliceN noiseNI1 sampleHSPT+ let (hsptFromBob1, csBob1, csBob2) = readHandshakeMsgFinal bobN aliceToBob1 noiseNR1++ return $ conjoin+ [ (decrypt csBob1 . encrypt csAlice1) pt === pt+ , (decrypt csBob2 . encrypt csAlice2) pt === pt+ , (decrypt csAlice1 . encrypt csBob1) pt === pt+ , (decrypt csAlice2 . encrypt csBob2) pt === pt+ , hsptFromBob1 === sampleHSPT+ ]++ where+ encrypt cs p = fst $ encryptPayload p cs+ decrypt cs ct = fst $ decryptPayload ct cs++--------------------------------------------------------------------------------+-- Noise_K++hsnK :: ScrubbedBytes+hsnK = makeHSN "Noise_K"++doK :: Plaintext -> Property+doK pt = ioProperty $ do+ aliceStaticKey@(_, aliceStaticPK) <- curveGenKey :: IO (KeyPair Curve25519)+ bobStaticKey@(_, bobStaticPK) <- curveGenKey :: IO (KeyPair Curve25519)++ let aliceK = handshakeState+ hsnK+ (Just aliceStaticKey)+ Nothing+ (Just bobStaticPK)+ Nothing+ (Just noiseKI0) :: HandshakeState ChaChaPoly1305 Curve25519 SHA256++ bobK = handshakeState+ hsnK+ (Just bobStaticKey)+ Nothing+ (Just aliceStaticPK)+ Nothing+ (Just noiseKR0) :: HandshakeState ChaChaPoly1305 Curve25519 SHA256++ (aliceToBob1, csAlice1, csAlice2) <- writeHandshakeMsgFinal aliceK noiseKI1 sampleHSPT+ let (hsptFromBob1, csBob1, csBob2) = readHandshakeMsgFinal bobK aliceToBob1 noiseKR1++ return $ conjoin+ [ (decrypt csBob1 . encrypt csAlice1) pt === pt+ , (decrypt csBob2 . encrypt csAlice2) pt === pt+ , (decrypt csAlice1 . encrypt csBob1) pt === pt+ , (decrypt csAlice2 . encrypt csBob2) pt === pt+ , hsptFromBob1 === sampleHSPT+ ]++ where+ encrypt cs p = fst $ encryptPayload p cs+ decrypt cs ct = fst $ decryptPayload ct cs++--------------------------------------------------------------------------------+-- Noise_X++hsnX :: ScrubbedBytes+hsnX = makeHSN "Noise_X"++doX :: Plaintext -> Property+doX pt = ioProperty $ do+ aliceStaticKey <- curveGenKey :: IO (KeyPair Curve25519)+ bobStaticKey@(_, bobStaticPK) <- curveGenKey :: IO (KeyPair Curve25519)++ let aliceX = handshakeState+ hsnX+ (Just aliceStaticKey)+ Nothing+ (Just bobStaticPK)+ Nothing+ (Just noiseXI0) :: HandshakeState ChaChaPoly1305 Curve25519 SHA256++ bobX = handshakeState+ hsnX+ (Just bobStaticKey)+ Nothing+ Nothing+ Nothing+ (Just noiseXR0) :: HandshakeState ChaChaPoly1305 Curve25519 SHA256++ (aliceToBob1, csAlice1, csAlice2) <- writeHandshakeMsgFinal aliceX noiseXI1 sampleHSPT+ let (hsptFromBob1, csBob1, csBob2) = readHandshakeMsgFinal bobX aliceToBob1 noiseXR1++ return $ conjoin+ [ (decrypt csBob1 . encrypt csAlice1) pt === pt+ , (decrypt csBob2 . encrypt csAlice2) pt === pt+ , (decrypt csAlice1 . encrypt csBob1) pt === pt+ , (decrypt csAlice2 . encrypt csBob2) pt === pt+ , hsptFromBob1 === sampleHSPT+ ]++ where+ encrypt cs p = fst $ encryptPayload p cs+ decrypt cs ct = fst $ decryptPayload ct cs+ tests :: TestTree tests = testGroup "Handshakes" [ testProperty "Noise_NN" $ property doNN@@ -782,4 +906,8 @@ , testProperty "Noise_XE" $ property doXE , testProperty "Noise_IE" $ property doIE , testProperty "Noise_XX" $ property doXX+ , testProperty "Noise_IX" $ property doIX+ , testProperty "Noise_N" $ property doN+ , testProperty "Noise_K" $ property doK+ , testProperty "Noise_X" $ property doX ]
tests/Instances.hs view
@@ -2,22 +2,23 @@ {-# OPTIONS_GHC -fno-warn-orphans #-} module Instances where -import Control.Monad (liftM, replicateM)-import qualified Data.ByteArray as BA-import qualified Data.ByteString as BS+import Control.Monad (liftM, replicateM)+import Data.ByteString (pack) import Test.QuickCheck import Crypto.Noise.Cipher import Crypto.Noise.Internal.CipherState+import Crypto.Noise.Types (ScrubbedBytes, bsToSB', sbEq,+ sbToBS') instance Eq Plaintext where- (Plaintext pt1) == (Plaintext pt2) = pt1 `BA.eq` pt2+ (Plaintext pt1) == (Plaintext pt2) = pt1 `sbEq` pt2 instance Show Plaintext where- show (Plaintext pt) = show (BA.convert pt :: BS.ByteString)+ show (Plaintext pt) = show . sbToBS' $ pt instance Show AssocData where- show (AssocData ad) = show (BA.convert ad :: BS.ByteString)+ show (AssocData ad) = show . sbToBS' $ ad instance Show (SymmetricKey a) where show _ = "<symmetric key>"@@ -27,8 +28,8 @@ deriving instance Show (CipherState a) -instance Arbitrary BA.ScrubbedBytes where- arbitrary = BA.convert `liftM` BS.pack <$> arbitrary+instance Arbitrary ScrubbedBytes where+ arbitrary = bsToSB' `liftM` pack <$> arbitrary instance Arbitrary Plaintext where arbitrary = Plaintext `liftM` arbitrary@@ -38,5 +39,5 @@ instance Cipher c => Arbitrary (CipherState c) where arbitrary = do- a <- (BA.convert . BS.pack) <$> replicateM 32 arbitrary+ a <- (bsToSB' . pack) <$> replicateM 32 arbitrary return $ CipherState (cipherBytesToSym a) cipherZeroNonce
tests/SymmetricHandshakeState.hs view
@@ -6,8 +6,6 @@ import Control.Monad.State (runState, state) -import Data.ByteString (ByteString)- import Crypto.Noise.Cipher import Crypto.Noise.Cipher.ChaChaPoly1305 import Crypto.Noise.Hash.SHA256@@ -15,7 +13,7 @@ import Crypto.Noise.Types shs :: SymmetricHandshakeState ChaChaPoly1305 SHA256-shs = symmetricHandshake $ convert ("handshake name" :: ByteString)+shs = symmetricHandshake $ bsToSB' "handshake name" roundTripProp :: Plaintext -> Property roundTripProp pt = (decrypt . encrypt) pt === pt