blakesum-demo (empty) → 0.5
raw patch · 4 files changed
+289/−0 lines, 4 filesdep +basedep +blakesumdep +bytestringsetup-changed
Dependencies added: base, blakesum, bytestring, haskell98, text, vector
Files
- LICENSE +26/−0
- Main.hs +222/−0
- Setup.hs +2/−0
- blakesum-demo.cabal +39/−0
+ LICENSE view
@@ -0,0 +1,26 @@+Copyright (c) 2011, Kevin Cantu <me@kevincantu.org>+All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions+are met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above+ copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials provided+ with the distribution.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Main.hs view
@@ -0,0 +1,222 @@+-- |+-- Module : Main+-- Copyright : (c) 2011 Kevin Cantu+--+-- License : BSD-style+-- Maintainer : Kevin Cantu <me@kevincantu.org>+-- Stability : experimental+--+-- A demo program providing a command line `blakesum` utility which behaves +-- much like the sha512sum or shasum software available for various platforms+module Main (main) where++import Data.Digest.BLAKE+import qualified Data.ByteString.Lazy as B+import System+--import System.IO+import IO+import System.Console.GetOpt+import qualified Data.Text.Lazy as T+import qualified Data.Text.Lazy.Encoding as E+import Data.Word+++-- command line options+data Options = Options { help :: Bool+ , check :: Bool+ , algorithm :: Integer+ , salt_ :: B.ByteString+ }+++-- command line defaults+defaultOpts :: Options+defaultOpts = Options { help = False+ , check = False+ , algorithm = 512+ , salt_ = B.take 32 $ B.repeat 0+ }+++-- command line description+-- this format is kinda bone headed:+-- [Option short [long] (property setter-function hint) description]+options :: [ OptDescr (Options -> IO Options) ]+options = [ Option "a" ["algorithm"] + (ReqArg+ (\arg opt -> let alg = read arg :: Integer+ in+ if elem alg [256,512,224,384]+ then return opt { algorithm = alg }+ else error "please choose a working algorithm size")+ "BITS")+ "256, 512, 224, 384 (default: 512)"++ , Option "c" ["check"] + (NoArg $ \opt -> return opt { check = True })+ "check saved hashes"++ , Option "s" ["salt"] + (ReqArg+ (\arg opt -> let s = (read ("[" ++ arg ++ "]")) :: [Word8]+ in + if (length $ filter (<0) s) > 0+ then error "please specify a salt of positive numbers"+ else return opt { salt_ = B.pack s })+ "SALT")+ "one positive uint per byte, salt: \"0,0,...0,0\""++ , Option "h" ["help"] + (NoArg $ \_ -> do+ prg <- getProgName+ hPutStrLn stderr $ usageInfo prg options+ exitWith ExitSuccess)+ "display this help and exit"++ , Option "v" ["version"] + (NoArg $ \_ -> do+ me <- getProgName+ hPutStrLn stderr $ me ++ " version 0.5"+ exitWith ExitSuccess)+ "display version and exit"+ ]+++-- apply a function (which uses the path) to a list of files and/or stdin+fileMapWithPath :: ( FilePath -> B.ByteString -> IO () ) -> [FilePath] -> IO ()+fileMapWithPath f paths = + let + -- apply f to stdin+ stdinF :: IO ()+ stdinF = B.getContents >>= f "-"++ -- apply f to a file (or stdin, when "-")+ fileF :: FilePath -> IO ()+ fileF "-" = stdinF+ fileF path = (B.readFile path >>= f path) `catch` (\e -> hPutStrLn stderr (show e))+ in+ case paths of+ [] -> stdinF+ _ -> mapM_ fileF paths+++-- apply a function to a list of files and/or stdin+fileMap :: ( B.ByteString -> IO () ) -> [FilePath] -> IO ()+fileMap f paths = fileMapWithPath (\_ -> f) paths++++-- compute a hash, return text+getHash256 :: B.ByteString -> B.ByteString -> T.Text+getHash256 salt message = textDigest $ blake256 salt message+getHash224 :: B.ByteString -> B.ByteString -> T.Text+getHash224 salt message = textDigest $ blake224 salt message+getHash512 :: B.ByteString -> B.ByteString -> T.Text+getHash512 salt message = textDigest $ blake512 salt message+getHash384 :: B.ByteString -> B.ByteString -> T.Text+getHash384 salt message = textDigest $ blake384 salt message+++-- print out the BLAKE hash followed by the file name+printHash :: (B.ByteString -> B.ByteString -> T.Text)+ -> B.ByteString+ -> String+ -> B.ByteString+ -> IO ()++printHash getHash salt path message = + do+ hash <- return $ getHash salt message+ B.putStrLn $ E.encodeUtf8 $ T.concat [hash, T.pack " *", T.pack path]+++-- check one hash line (i.e., aas98d4a654...5756 *README.txt)+checkHash :: (B.ByteString -> B.ByteString -> T.Text)+ -> B.ByteString+ -> T.Text+ -> IO ()++checkHash getHash salt line = + let+ [savedHash, path] = T.splitOn (T.pack " *") line+ printStatus status = B.putStrLn $ E.encodeUtf8 $ T.append path $ T.pack $ ": " ++ status+ in+ (do+ message <- B.readFile (T.unpack path)++ printStatus $ if savedHash == getHash salt message+ then "OK"+ else "FAILED"++ ) `catch` (\e -> hPutStrLn stderr (show e) + >> printStatus "FAILED open or read")+++-- print hashes of given files+printHashes :: Num a => a -> B.ByteString -> [FilePath] -> IO ()+printHashes alg salt paths =+ let+ printHash' =+ case alg of + 256 -> printHash getHash256+ 224 -> printHash getHash224+ 512 -> printHash getHash512+ 384 -> printHash getHash384+ _ -> error "unavailable algorithm size"+ in+ fileMapWithPath (printHash' salt) paths+++-- check hashes within given files+checkHashes :: Num a => a -> B.ByteString -> [FilePath] -> IO ()+checkHashes alg salt paths =+ let+ -- check message (file) of hashes+ checkHashesInMessage f salt' = mapM_ (checkHash f salt') +++ checkHashes' =+ case alg of+ 256 -> checkHashesInMessage getHash256+ 224 -> checkHashesInMessage getHash224+ 512 -> checkHashesInMessage getHash512+ 384 -> checkHashesInMessage getHash384+ _ -> error "unavailable algorithm size"+ in+ fileMap ((checkHashes' salt) . T.lines . E.decodeUtf8) paths+++main :: IO ()+main = + do + args <- getArgs++ -- call getOpt with the option description+ -- ignoring errors+ let (actions, nonOptions, _) = getOpt Permute options args++ -- process the defaults with those actions+ -- returns command line properties+ opts <- foldl (>>=) (return defaultOpts) actions+ + -- assign the results+ -- via destructuring assignment+ let Options { check = check'+ , algorithm = algorithm'+ , salt_ = salt'+ } = opts++ let salt'' = case algorithm' of+ 256 | B.length salt' == 16 -> salt'+ 512 | B.length salt' == 32 -> salt'+ _ -> error "salt should be 32 (default) or 16 bytes"++ -- are we in check mode?+ let run = if check'+ then checkHashes -- verify hashes listed in given files+ else printHashes -- output hashes of given files++ -- either check or print hashes+ run algorithm' salt'' nonOptions++
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ blakesum-demo.cabal view
@@ -0,0 +1,39 @@+name: blakesum-demo+version: 0.5+synopsis: The BLAKE SHA-3 candidate hashes, in Haskell+description: + .+ This provides an executable which relies on the `blakesum` library, `Data.Digest.BLAKE`.+ .+ Usage:+ blakesum [--algorithm=BITS] [--check] [--salt=SALT] FILE(S)+ .+ Contributions and optimizations are welcome!+ .+category: Cryptography+stability: experimental+license: BSD3+license-file: LICENSE+author: Kevin Cantu <me@kevincantu.org>+maintainer: Kevin Cantu <me@kevincantu.org>+copyright: (c) 2011 Kevin Cantu+homepage: https://github.com/killerswan/Haskell-BLAKE+bug-reports: https://github.com/killerswan/Haskell-BLAKE/issues+build-type: Simple+cabal-version: >=1.8++source-repository head+ type: git+ location: https://github.com/killerswan/Haskell-BLAKE++executable blakesum+ main-is: Main.hs+ hs-source-dirs: .+ build-depends: base >= 4 && < 5,+ blakesum >= 0 && < 1,+ bytestring >= 0 && < 1,+ haskell98 >= 1 && < 2,+ text >= 0 && < 1,+ vector >= 0 && < 1++