{-# LANGUAGE OverloadedStrings #-} module ExpensiveHash where import Types import Serialization import Cost 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 CreationOp) B.ByteString deriving (Show) data Salt t = Salt t expensiveHash :: Encodable t => Tunables -> Salt t -> Password -> ExpensiveHash expensiveHash tunables (Salt s) (Password password) = case expensiveHashTunable tunables of UseArgon2 opts cost -> ExpensiveHash cost $ Argon2.hash opts password (toByteString s) benchmarkExpensiveHash :: Tunables -> IO (Benchmark (Cost CreationOp)) benchmarkExpensiveHash tunables = do start <- getCurrentTime let ExpensiveHash expected b = expensiveHash tunables (Salt (KeyIdent gpgKey (Name ("benchmark" :: B.ByteString)))) (Password ("himom" :: B.ByteString)) end <- b `deepseq` getCurrentTime let diff = floor $ end `diffUTCTime` start let actual = CPUCost $ Seconds diff return $ Benchmark { expectedBenchmark = expected , actualBenchmark = actual }