diff options
author | Joey Hess <joeyh@joeyh.name> | 2016-08-06 17:35:10 -0400 |
---|---|---|
committer | Joey Hess <joeyh@joeyh.name> | 2016-08-06 17:35:10 -0400 |
commit | 7192abc5d53aa5a6ee609ed30bd05f1575e67b65 (patch) | |
tree | 2f1d17f27b483a8deec001a12a55696b0eea5978 /ExpensiveHash.hs | |
parent | fbd0bb3a2b2541e897708fb441ab1c8a2b5ab78e (diff) | |
download | keysafe-7192abc5d53aa5a6ee609ed30bd05f1575e67b65.tar.gz |
some basic data types and expensive hashing
Diffstat (limited to 'ExpensiveHash.hs')
-rw-r--r-- | ExpensiveHash.hs | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/ExpensiveHash.hs b/ExpensiveHash.hs new file mode 100644 index 0000000..8bfe004 --- /dev/null +++ b/ExpensiveHash.hs @@ -0,0 +1,54 @@ +{-# LANGUAGE OverloadedStrings #-} + +module ExpensiveHash where + +import Types +import qualified Data.ByteString as B +import Raaz.Core.Encode +import qualified Crypto.Argon2 as Argon2 +import Data.Time.Clock +import Control.DeepSeq + +-- | A hash that is expensive to calculate. +-- +-- This is a lynchpin of keysafe's security, because using this hash +-- as an encryption key forces brute force attackers to generate +-- hashes over and over again, taking a very long time. +data ExpensiveHash = ExpensiveHash Cost B.ByteString + deriving (Show) + +data Salt t = Salt t + +expensiveHash :: Encodable t => RunMode -> Salt t -> Password -> ExpensiveHash +expensiveHash runmode (Salt s) (Password password) = + ExpensiveHash cost $ Argon2.hash o password (toByteString s) + where + HashParams o cost = hashParams runmode + +data HashParams = HashParams Argon2.HashOptions Cost + +hashParams :: RunMode -> HashParams +hashParams SecureMode = HashParams o cost + where + -- argon2 is GPU and ASIC resistent, so it uses CPU time. + -- The selected HashOptions were benchmarked at 661 seconds CPU time + -- on a 2 core Intel(R) Core(TM) i5-4210Y CPU @ 1.50GHz. + cost = CPUCost (Seconds 600) + o = Argon2.HashOptions + { Argon2.hashIterations = 10000 + , Argon2.hashMemory = 131072 -- 128 mebibtyes per thread + , Argon2.hashParallelism = 4 -- 4 threads + , Argon2.hashVariant = Argon2.Argon2i + } +hashParams TestingMode = + HashParams Argon2.defaultHashOptions $ CPUCost (Seconds 0) + +benchmarkExpensiveHash :: IO (Benchmark Cost) +benchmarkExpensiveHash = do + start <- getCurrentTime + let ExpensiveHash expected b = expensiveHash SecureMode + (Salt (KeyIdent gpgKey (Name ("benchmark" :: B.ByteString)))) + (Password ("himom" :: B.ByteString)) + end <- b `deepseq` getCurrentTime + let actual = (CPUCost $ Seconds $ end `diffUTCTime` start) + return $ Benchmark { expectedBenchmark = expected, actualBenchmark = actual } |