-- | -- Module : Crypto.Longshot.TH -- License : MIT -- Maintainer : Francis Lim -- Stability : experimental -- Portability : unknown -- module Crypto.Longshot.TH where import Control.Monad ( replicateM ) import Data.Foldable ( foldl' ) import Data.ByteString.Char8 ( unpack ) import Language.Haskell.TH import Crypto.Longshot.Const -- | Brute-force with N-search-length using TH bruteforceN :: Int -> Q Exp -> Q Exp -> Q Exp -> Q Exp -> Q Exp bruteforceN numBind chars hex hasher prefix = do names <- replicateM numBind (newName "names") let pats = varP <$> names let bytes = prefix : (varE <$> names) let preimage = [| $( foldl' (\a b -> [| $a <> $b |]) [| mempty |] bytes ) |] let cond = condE [| $( appE hasher preimage ) == $( hex ) |] [| Just (unpack $( preimage )) |] [| Nothing |] let stmts = ((`bindS` chars) <$> pats) <> [noBindS cond] [| foldl' (<|>) empty $( compE stmts ) |] -- | Declare functions to run in parallel for search funcGenerator :: Q [Dec] funcGenerator = mapM funcG [0 .. maxNumBind] where funcG numBind = do let name = mkName $ "bruteforce" <> show numBind chars <- newName "chars" hex <- newName "hex" hasher <- newName "hasher" prefix <- newName "prefix" funD name [ clause [varP chars, varP hex, varP hasher, varP prefix] (normalB (bruteforceN numBind (varE chars) (varE hex) (varE hasher) (varE prefix))) [] ] -- | Get list of functions to run in parallel for search funcList :: Q Exp funcList = listE (varE . mkName . ("bruteforce" <>) . show <$> [0 .. maxNumBind])