cryptopals

Matasano's cryptopals challenges (cryptopals.com).
git clone git://git.jtobin.io/cryptopals.git
Log | Files | Refs | README | LICENSE

DetectSingleByteXor.hs (1553B)


      1 {-# LANGUAGE OverloadedStrings #-}
      2 {-# LANGUAGE RecordWildCards #-}
      3 
      4 module Main where
      5 
      6 import qualified Cryptopals.Util as CU
      7 import qualified Data.ByteString.Base16 as B16
      8 import qualified Data.ByteString.Char8 as B8
      9 import qualified Data.Foldable as F
     10 import Data.Function (on)
     11 import qualified Data.List as L
     12 import qualified Data.Text.IO as TIO
     13 import qualified Data.Text.Encoding as TE
     14 import qualified Options.Applicative as O
     15 import qualified System.Exit as SE
     16 import qualified System.IO as SIO
     17 
     18 data Args = Args { argsFil :: SIO.FilePath }
     19 
     20 ops :: O.Parser Args
     21 ops = Args <$> O.argument O.str (O.metavar "FILE")
     22 
     23 detect :: Args -> IO ()
     24 detect Args {..} = do
     25   let err = TIO.hPutStrLn SIO.stderr
     26       out = TIO.hPutStrLn SIO.stdout
     27 
     28   contents <- B8.readFile argsFil
     29 
     30   let ls = B8.lines contents
     31       es = traverse B16.decodeBase16 ls
     32 
     33   case es of
     34     Left e -> do
     35       err $ "cryptopals: " <> e
     36       SE.exitFailure
     37 
     38     Right bs -> do
     39       let fs = concatMap (\s -> [(head . CU.often $ s, s)]) bs -- XX hack
     40           sorted = L.sortBy (flip compare `on`  (snd . fst)) fs
     41           most   = take 3 sorted
     42 
     43       err "cryptopals: suspect inputs"
     44       F.for_ most $ \((_, _), s) -> do
     45         err $ "cryptopals: " <> (TE.decodeUtf8 . B16.encodeBase16' $ s)
     46         out . TE.decodeUtf8 . B16.encodeBase16' $ s
     47 
     48 main :: IO ()
     49 main = do
     50   let pars = O.info (O.helper <*> ops) $
     51            O.fullDesc
     52         <> O.progDesc "produce byte frequencies"
     53         <> O.header "detect-single-byte-xor"
     54 
     55   args <- O.execParser pars
     56 
     57   detect args
     58