packages feed

longshot 0.1.0.2 → 0.1.0.3

raw patch · 9 files changed

+167/−107 lines, 9 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- Crypto.Longshot: byteChars :: String -> [ByteString]
- Crypto.Longshot: bytePrefixes :: Int -> String -> [ByteString]
- Crypto.Longshot: defChars :: String
- Crypto.Longshot: defNumBind :: Int
- Crypto.Longshot: defNumPrefix :: Int
- Crypto.Longshot: defSearchLength :: Int
- Crypto.Longshot: image :: String -> ByteString
- Crypto.Longshot: limitSearchLength :: Int
- Crypto.Longshot: toKey :: ByteString -> String
+ Crypto.Longshot.Const: defChars :: String
+ Crypto.Longshot.Const: defNumPrefix :: Int
+ Crypto.Longshot.Const: defSearchLength :: Int
+ Crypto.Longshot.Const: limitSearchLength :: Int
+ Crypto.Longshot.Const: maxNumBind :: Int
+ Crypto.Longshot.Internal: (<%>) :: (NFData a, NFData b) => (a -> b) -> [a] -> [b]
+ Crypto.Longshot.Internal: bruteforcePar :: Int -> [ByteString] -> ByteString -> Hasher -> ByteString -> Maybe String
+ Crypto.Longshot.Internal: byteChars :: String -> [ByteString]
+ Crypto.Longshot.Internal: bytePrefixes :: Int -> String -> [ByteString]
+ Crypto.Longshot.Internal: image :: String -> ByteString

Files

ChangeLog.md view
@@ -7,3 +7,7 @@  ## 0.1.0.2 * Fixed Hackage metadata++## 0.1.0.3+* Up to 10% performance improvement+* Additional explanations on the arguments of the core function
README.md view
@@ -52,7 +52,10 @@ ```  ## How to build-```bash+```shell+## Install 'stack' if not any+$ brew install stack+ $ git clone https://github.com/thyeem/longshot.git  $ make build @@ -65,7 +68,7 @@ ```  ## Quick start-```bash+```shell ## Refer to the following usage: ## Note that the order of arguments and options matter. $ ./longshot -h@@ -96,7 +99,7 @@ See below for more interesting detailed examples.  ## More examples-```bash+```shell ## Generate a example image using Blake2b hash algorithm ## Blake2b-hashed sofia (my first daughter!) $ ./longshot image -a blake2b sofia
app/Main.hs view
@@ -1,13 +1,13 @@ {-# LANGUAGE QuasiQuotes #-} module Main where -import           Control.Monad-import           System.Environment+import           Control.Monad                  ( when )+import           System.Environment             ( getArgs ) import           System.Console.Docopt import qualified Data.ByteString.Char8         as C import qualified Data.ByteString.Base16        as H import           Crypto.Longshot.Internal-import           Crypto.Longshot.Hasher+import           Crypto.Longshot.Hasher         ( getHasher )  patterns :: Docopt patterns = [docopt|
longshot.cabal view
@@ -4,10 +4,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: 4cf3d32f97b4605f2bd729574881eb5df14e31adef0431f928343ea04e268c38+-- hash: 950eaac57e913aaa5d3f38ed066cb8aefb07851a8072f2686280220fd76aa711  name:           longshot-version:        0.1.0.2+version:        0.1.0.3 synopsis:       Fast Brute-force search using parallelism description:    Longshot enables to search for preimages from a given hash value                 using a brute-force method based on parallelism.@@ -41,6 +41,7 @@ library   exposed-modules:       Crypto.Longshot+      Crypto.Longshot.Const       Crypto.Longshot.Hasher       Crypto.Longshot.Internal       Crypto.Longshot.TH
src/Crypto/Longshot.hs view
@@ -5,56 +5,21 @@ -- Stability   : experimental -- Portability : unknown ----- How big is the search space? The space consists of two axes.------ * X-axis: Number of characters available--- * Y-axis: Search length of preimage to find------ Note that it's proportional to @(X ^ Y)@ rather than @(X * Y)@------ The values below are defined by default.------ When not provided as options in CUI, the following values are used.+-- Fast Brute-force search using parallelism ---module Crypto.Longshot where--import           Control.Monad-import qualified Data.ByteString.Char8         as C-import qualified Data.ByteString.Base16        as H---- | Characters available in a preimage-defChars :: String-defChars = "0123456789"---- | Search length of preimage-defSearchLength :: Int-defSearchLength = 8---- | Limit search length of preimage-limitSearchLength :: Int-limitSearchLength = 20---- | Value related to the number of sparks-defNumPrefix :: Int-defNumPrefix = 3---- | Number of actions in TH bruteforceN-defNumBind :: Int-defNumBind = limitSearchLength - defNumPrefix------------------------------------------------------------------------- | Image bytestring: target hash value to find-image :: String -> C.ByteString-image = fst . H.decode . C.pack---- | Bytestring usable for preimage-byteChars :: String -> [C.ByteString]-byteChars chars = C.pack . (: []) <$> chars---- | Combination of prefixes possible: size of (length of chars) ^ (numPrefix)-bytePrefixes :: Int -> String -> [C.ByteString]-bytePrefixes numPrefix chars = C.pack <$> replicateM numPrefix chars+-- Longshot enables to search for preimages from a given hash value+-- using a brute-force method based on parallelism.+-- +module Crypto.Longshot+  ( module Crypto.Longshot+  , module Crypto.Longshot.Const+  , module Crypto.Longshot.Internal+  , module Crypto.Longshot.TH+  , module Crypto.Longshot.Hasher+  )+where --- | Convert preimage found into key string-toKey :: C.ByteString -> String-toKey = C.unpack+import           Crypto.Longshot.Const+import           Crypto.Longshot.Internal+import           Crypto.Longshot.TH+import           Crypto.Longshot.Hasher
+ src/Crypto/Longshot/Const.hs view
@@ -0,0 +1,39 @@+-- |+-- Module      : Crypto.Longshot.Const+-- License     : MIT+-- Maintainer  : Francis Lim <thyeem@gmail.com>+-- Stability   : experimental+-- Portability : unknown+--+-- How big is the search space? The space consists of two axes.+--+-- * @X-axis@: Number of characters available+-- * @Y-axis@: Search length of preimage to find+--+-- Note that it's proportional to @(X ^ Y)@ rather than @(X * Y)@+--+-- The values below are defined by default.+--+-- When not provided as options in CUI, the following values are used.+--+module Crypto.Longshot.Const where++-- | Default characters available in a preimage+defChars :: String+defChars = "0123456789"++-- | Default search length of preimage+defSearchLength :: Int+defSearchLength = 8++-- | Limit search length of preimage+limitSearchLength :: Int+limitSearchLength = 20++-- | Default value related to the number of sparks+defNumPrefix :: Int+defNumPrefix = 3++-- | Maximum number of actions in bruteforceN+maxNumBind :: Int+maxNumBind = limitSearchLength - defNumPrefix
src/Crypto/Longshot/Hasher.hs view
@@ -11,22 +11,21 @@   ) where -import           GHC.TypeLits-import           Numeric.Natural+import           GHC.TypeLits                   ( Nat )+import           Data.ByteString                ( ByteString ) import qualified Data.ByteArray                as B-import qualified Data.ByteString.Char8         as C import qualified Crypto.Hash                   as X import qualified Crypto.Hash.SHA256            as S-import qualified Crypto.Hash.BLAKE2.BLAKE2s    as B2s-import qualified Crypto.Hash.BLAKE2.BLAKE2b    as B2b-import qualified BLAKE3                        as B3+import qualified Crypto.Hash.BLAKE2.BLAKE2s    as Blake2s+import qualified Crypto.Hash.BLAKE2.BLAKE2b    as Blake2b+import qualified BLAKE3                        as Blake3  -- | Type for hash functions available-type Hasher = C.ByteString -> C.ByteString+type Hasher = ByteString -> ByteString -type Blake3_256 = C.ByteString -> B3.Digest (32 :: Nat)-type Blake3_384 = C.ByteString -> B3.Digest (48 :: Nat)-type Blake3_512 = C.ByteString -> B3.Digest (64 :: Nat)+type Blake3_256 = ByteString -> Blake3.Digest (32 :: Nat)+type Blake3_384 = ByteString -> Blake3.Digest (48 :: Nat)+type Blake3_512 = ByteString -> Blake3.Digest (64 :: Nat)  -- | Select hasher by defined name getHasher :: String -> Hasher@@ -39,13 +38,13 @@   "sha3_256"    -> B.convert . X.hashWith X.SHA3_256   "sha3_384"    -> B.convert . X.hashWith X.SHA3_384   "sha3_512"    -> B.convert . X.hashWith X.SHA3_512-  "blake2s_256" -> B2s.hash 32 mempty-  "blake2b_256" -> B2b.hash 32 mempty-  "blake2b_384" -> B2b.hash 48 mempty-  "blake2b_512" -> B2b.hash 64 mempty-  "blake3_256"  -> B.convert . (B3.hash . (: []) :: Blake3_256)-  "blake3_384"  -> B.convert . (B3.hash . (: []) :: Blake3_384)-  "blake3_512"  -> B.convert . (B3.hash . (: []) :: Blake3_512)+  "blake2s_256" -> Blake2s.hash 32 mempty+  "blake2b_256" -> Blake2b.hash 32 mempty+  "blake2b_384" -> Blake2b.hash 48 mempty+  "blake2b_512" -> Blake2b.hash 64 mempty+  "blake3_256"  -> B.convert . (Blake3.hash . (: []) :: Blake3_256)+  "blake3_384"  -> B.convert . (Blake3.hash . (: []) :: Blake3_384)+  "blake3_512"  -> B.convert . (Blake3.hash . (: []) :: Blake3_512)   "keccak_256"  -> B.convert . X.hashWith X.Keccak_256   "keccak_384"  -> B.convert . X.hashWith X.Keccak_384   "keccak_512"  -> B.convert . X.hashWith X.Keccak_512
src/Crypto/Longshot/Internal.hs view
@@ -8,23 +8,59 @@ module Crypto.Longshot.Internal   ( bruteforce   , bruteforceDeep+  , bruteforcePar+  , (<%>)+  , image+  , byteChars+  , bytePrefixes   ) where -import           Control.Applicative-import           Control.DeepSeq-import           Control.Parallel-import           Data.Foldable+import           Control.Monad                  ( replicateM )+import           Control.Applicative            ( (<|>)+                                                , empty+                                                )+import           Control.Parallel               ( par+                                                , pseq+                                                )+import           Control.DeepSeq                ( NFData+                                                , force+                                                )+import           Data.Foldable                  ( foldl' )+import           Data.ByteString                ( ByteString ) import qualified Data.ByteString.Char8         as C-import           Language.Haskell.TH-import           Crypto.Longshot-import           Crypto.Longshot.TH+import qualified Data.ByteString.Base16        as H import           Crypto.Longshot.Hasher+import           Crypto.Longshot.TH+import           Crypto.Longshot.Const --- Declaration of bruteforceN: generating code by splicing+-- | Each bruteforceN declaration: generating code through splicing.+-- Number of functions declared == 'maxNumBind'+-- $( funcGenerator )  -- | Brute-force search only for a given exact length+--+-- @+-- ------------------------------------------------------------------------------+--     size | Preimage length to search+-- ------------------------------------------------------------------------------+--    chars | Given character set like "0123456789"+-- ------------------------------------------------------------------------------+--      hex | Given hex-string like "17da1ae431f965d839ec8eb93087fb2b"+-- ------------------------------------------------------------------------------+--   hasher | Hash functions in 'Hasher' module. Get it using 'getHasher'+-- ------------------------------------------------------------------------------+--  numBind | Number of bound variables defined by search length and prefix size+-- ------------------------------------------------------------------------------+--   runPar | A partially applied function for parallel execution+-- ------------------------------------------------------------------------------+-- prefixes | All possible combinations of given prefix characters.+--          | The search space is equally partioned based on these prefixes.+--          | length of prefixes == number of sparks+-- ------------------------------------------------------------------------------+-- @+-- bruteforce :: Int -> String -> String -> Hasher -> Maybe String bruteforce size chars hex hasher = found  where@@ -36,27 +72,43 @@   prefixes = bytePrefixes numPrefix chars  -- | Pick up an appropriate search function+--+-- Returns a partial application corresponding to the given numBind+-- bruteforcePar-  :: Int-  -> [C.ByteString]-  -> C.ByteString-  -> Hasher-  -> C.ByteString-  -> Maybe String-bruteforcePar n-  | n `elem` [0 .. defNumBind] = $( funcList ) !! n+  :: Int -> [ByteString] -> ByteString -> Hasher -> ByteString -> Maybe String+bruteforcePar numBind+  | numBind `elem` [0 .. maxNumBind] = $( funcList ) !! numBind   | otherwise = errorWithoutStackTrace "Not available search length"  -- | Deep Brute-force search including less than a given search size+--+-- See the 'bruteforce' function for the arguments used+-- bruteforceDeep :: Int -> String -> String -> Hasher -> Maybe String-bruteforceDeep size x y z = foldl' (<|>) empty found+bruteforceDeep size chars hex hasher = foldl' (<|>) empty found  where-  found = deep x y z <%> [1 .. size]+  found = deep chars hex hasher <%> [1 .. size]   deep a b c d = bruteforce d a b c  -- | Parallel map using deepseq, par and pseq+--+-- Type of any argument in this map should be instance of 'NFData'.+-- (<%>) :: (NFData a, NFData b) => (a -> b) -> [a] -> [b] f <%> []       = [] f <%> (x : xs) = y `par` ys `pseq` (y : ys) where   y  = force $ f x   ys = f <%> xs++-- | Image bytestring: target hash value to find+image :: String -> ByteString+image = fst . H.decode . C.pack++-- | Bytestring usable for preimage+byteChars :: String -> [ByteString]+byteChars chars = C.pack . (: []) <$> chars++-- | Combination of prefixes possible: size of @(length of chars) ^ (numPrefix)@+bytePrefixes :: Int -> String -> [ByteString]+bytePrefixes numPrefix chars = C.pack <$> replicateM numPrefix chars
src/Crypto/Longshot/TH.hs view
@@ -7,31 +7,28 @@ -- module Crypto.Longshot.TH where -import           Control.Monad-import           Data.Foldable+import           Control.Monad                  ( replicateM )+import           Data.Foldable                  ( foldl' )+import           Data.ByteString.Char8          ( unpack ) import           Language.Haskell.TH-import           Crypto.Longshot+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 ) <>-                 $( foldl' (\a b -> [| $a <> $b |])-                    [| mempty |]-                    (varE <$> names)-                  )-              |]-  let cond  = condE [| $( appE hasher bytes ) == $(hex) |]-                    [| Just (toKey $( bytes )) |]+  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 = forM [0 .. defNumBind] funcG where +funcGenerator = mapM funcG [0 .. maxNumBind] where   funcG numBind = do     let name = mkName $ "bruteforce" <> show numBind     chars <- newName "chars"@@ -46,4 +43,4 @@  -- | Get list of functions to run in parallel for search funcList :: Q Exp-funcList = listE (varE . mkName . ("bruteforce" <>) . show <$> [0 .. defNumBind])+funcList = listE (varE . mkName . ("bruteforce" <>) . show <$> [0 .. maxNumBind])