cacophony-0.9.0: tests/vectors/Generate.hs
{-# LANGUAGE OverloadedStrings, GADTs #-}
module Generate where
import Control.Concurrent.Async (mapConcurrently)
import Control.Lens ((^.))
import Data.Aeson (encode)
import Data.ByteArray (ScrubbedBytes, convert)
import Data.ByteString (ByteString)
import qualified Data.ByteString.Base16 as B16
import Data.ByteString.Lazy (writeFile)
import Data.Maybe (fromJust)
import Data.Monoid ((<>))
import Prelude hiding (writeFile)
import Crypto.Noise
import Crypto.Noise.Cipher
import Crypto.Noise.DH
import Crypto.Noise.Hash
import Crypto.Noise.Internal.Handshake
import Crypto.Noise.Internal.NoiseState
import Handshakes
import Types
import VectorFile
hexToPlaintext :: ByteString
-> ScrubbedBytes
hexToPlaintext = convert . fst . B16.decode
hexToPair :: DH d
=> ByteString
-> KeyPair d
hexToPair = fromJust . dhBytesToPair . convert . fst . B16.decode
initiatorEphemeral :: DH d
=> DHType d
-> KeyPair d
initiatorEphemeral DTCurve25519 = hexToPair "893e28b9dc6ca8d611ab664754b8ceb7bac5117349a4439a6b0569da977c464a"
initiatorEphemeral DTCurve448 = hexToPair "7fd26c8b8a0d5c98c85ff9ca1d7bc66d78578b9f2c4c170850748b27992767e6ea6cc9992a561c9d19dfc342e260c280ef4f3f9b8f879d4e"
responderEphemeral :: DH d
=> DHType d
-> KeyPair d
responderEphemeral DTCurve25519 = hexToPair "bbdb4cdbd309f1a1f2e1456967fe288cadd6f712d65dc7b7793d5e63da6b375b"
responderEphemeral DTCurve448 = hexToPair "3facf7503ebee252465689f1d4e3b1dd219639ef9de4ffd6049d6d71a0f62126840febb99042421ce12af6626d98d9170260390fbc8399a5"
initiatorStatic :: DH d
=> DHType d
-> KeyPair d
initiatorStatic DTCurve25519 = hexToPair "e61ef9919cde45dd5f82166404bd08e38bceb5dfdfded0a34c8df7ed542214d1"
initiatorStatic DTCurve448 = hexToPair "34d564c4be963d1b2a89fcfe83e6a72b5e3f5e3127f9f596ffc7575e418dfc1f4e827cfc10c9fed38e92ad56ddf8f08571430df2e76d5411"
responderStatic :: DH d
=> DHType d
-> KeyPair d
responderStatic DTCurve25519 = hexToPair "4a3acbfdb163dec651dfa3194dece676d437029c62a408b4c5ea9114246e4893"
responderStatic DTCurve448 = hexToPair "a9b45971180882a79b89a3399544a425ef8136d278efa443ed67d3ff9d36e883bc330c6295bbf6ed73ff6fd10cbed767ad05ce03ebd27c7c"
mkKeys :: DH d
=> Plaintext
-> Maybe ScrubbedBytes
-> Bool
-> DHType d
-> HandshakeKeys d
mkKeys pro psk i d =
HandshakeKeys { hkPrologue = pro
, hkPSK = psk
, hkLocalStatic = if i then initiatorStatic d else responderStatic d
, hkLocalEphemeral = if i then initiatorEphemeral d else responderEphemeral d
, hkRemoteStatic = if i then (snd . responderStatic) d else (snd . initiatorStatic) d
}
genMessages :: (Cipher c, DH d, Hash h)
=> Bool
-> NoiseState c d h
-> NoiseState c d h
-> [ScrubbedBytes]
-> [(ScrubbedBytes, ByteString)]
genMessages swap = go []
where
go acc _ _ [] = acc
go acc sendingState receivingState (payload : rest) =
let writeResult = writeMessage sendingState payload
(ct, sendingState') = either (error "write failed") id writeResult
(_, receivingState') = either (error "read failed")
id
$ readMessage receivingState ct in
if swap
then go (acc <> [(payload, ct)]) receivingState' sendingState' rest
else go (acc <> [(payload, ct)]) sendingState' receivingState' rest
genVector :: [ScrubbedBytes]
-> HandshakeType
-> Maybe ScrubbedBytes
-> SomeCipherType
-> SomeDHType
-> SomeHashType
-> IO Vector
genVector payloads pat psk cType@(WrapCipherType c) dType@(WrapDHType d) hType@(WrapHashType h) = do
let ihk = mkKeys "John Galt" psk True d
rhk = mkKeys "John Galt" psk False d
ins = mkNoiseState ihk pat InitiatorRole c h
rns = mkNoiseState rhk pat ResponderRole c h
swap = not (pat == NoiseN || pat == NoiseK || pat == NoiseX)
name = maybe "Noise_" (const "NoisePSK_") psk <>
show pat <>
"_" <>
show d <>
"_" <>
show c <>
"_" <>
show h
allMsgs = (\(payload, ct) -> Message (Just payload) ct)
<$> genMessages swap ins rns payloads
return
Vector { vName = name
, vPattern = pat
, vCipher = cType
, vDH = dType
, vHash = hType
, vFail = False
, viPrologue = hkPrologue ihk
, viPSK = hkPSK ihk
, viStatic = dhSecToBytes . fst <$> ins ^. nsHandshakeState . hsOpts . hoLocalStatic
, viSemiEphemeral = Nothing
, viEphemeral = dhSecToBytes . fst <$> ins ^. nsHandshakeState . hsOpts . hoLocalEphemeral
, virStatic = dhPubToBytes <$> ins ^. nsHandshakeState . hsOpts . hoRemoteStatic
, virSemiEphemeral = Nothing
, vrPrologue = hkPrologue rhk
, vrPSK = hkPSK rhk
, vrStatic = dhSecToBytes . fst <$> rns ^. nsHandshakeState . hsOpts . hoLocalStatic
, vrSemiEphemeral = Nothing
, vrEphemeral = dhSecToBytes . fst <$> rns ^. nsHandshakeState . hsOpts . hoLocalEphemeral
, vrrStatic = dhPubToBytes <$> rns ^. nsHandshakeState . hsOpts . hoRemoteStatic
, vrrSemiEphemeral = Nothing
, vMessages = allMsgs
}
genVectorFile :: FilePath
-> IO ()
genVectorFile f = do
let payloads = ["Ludwig von Mises", "Murray Rothbard", "F. A. Hayek", "Carl Menger", "Jean-Baptiste Say", "Eugen Böhm von Bawerk"]
patterns = [NoiseNN, NoiseKN, NoiseNK, NoiseKK, NoiseNX, NoiseKX, NoiseXN, NoiseIN, NoiseXK, NoiseIK, NoiseXX, NoiseIX, NoiseN, NoiseK, NoiseX]
psks = [Nothing, Just "This is my Austrian perspective!"]
ciphers = [WrapCipherType CTChaChaPoly1305, WrapCipherType CTAESGCM]
dhs = [WrapDHType DTCurve25519, WrapDHType DTCurve448]
hashes = [WrapHashType HTSHA256, WrapHashType HTSHA512, WrapHashType HTBLAKE2s, WrapHashType HTBLAKE2b]
vectors = [genVector payloads p psk c d h | p <- patterns, psk <- psks, c <- ciphers, d <- dhs, h <- hashes]
vs <- mapConcurrently id vectors
writeFile f . encode . VectorFile $ vs