summaryrefslogtreecommitdiffhomepage
path: root/ExpensiveHash.hs
diff options
context:
space:
mode:
authorJoey Hess <joeyh@joeyh.name>2016-08-16 12:57:19 -0400
committerJoey Hess <joeyh@joeyh.name>2016-08-16 13:04:07 -0400
commit3b4a775d536b2b2956269a59f886487efe29ed51 (patch)
treebbd8fd580afad11f822b2929061b034abf376c50 /ExpensiveHash.hs
parentd7696832e183cc3e98d094b35ee4392d0c8d3df5 (diff)
downloadkeysafe-3b4a775d536b2b2956269a59f886487efe29ed51.tar.gz
switch to random salt byte to make decryption expensive
Diffstat (limited to 'ExpensiveHash.hs')
-rw-r--r--ExpensiveHash.hs46
1 files changed, 30 insertions, 16 deletions
diff --git a/ExpensiveHash.hs b/ExpensiveHash.hs
index 226fac7..3d832fb 100644
--- a/ExpensiveHash.hs
+++ b/ExpensiveHash.hs
@@ -17,6 +17,7 @@ import qualified Crypto.Argon2 as Argon2
import Raaz.Core.Encode
import Data.Time.Clock
import Control.DeepSeq
+import Control.Monad
import Data.Monoid
-- | A hash that is expensive to calculate.
@@ -29,32 +30,45 @@ data ExpensiveHash = ExpensiveHash (Cost CreationOp) T.Text
data Salt t = Salt t
--- | Would rather use haskell argon2 library, but it doesn't build
--- from source, and is buggy. https://github.com/ocharles/argon2/issues/3
-expensiveHash :: Encodable t => Tunables -> Salt t -> B.ByteString -> ExpensiveHash
-expensiveHash tunables (Salt s) b =
- case expensiveHashTunable tunables of
- UseArgon2 opts cost -> ExpensiveHash cost $
- -- Using hashEncoded here and not hash,
- -- because of this bug:
- -- https://github.com/ocharles/argon2/issues/3
- Argon2.hashEncoded opts b argonsalt
+expensiveHash :: Encodable t => ExpensiveHashTunable -> Salt t -> B.ByteString -> ExpensiveHash
+expensiveHash (UseArgon2 cost opts) (Salt s) b = ExpensiveHash cost $
+ -- Using hashEncoded here and not hash,
+ -- because of this bug:
+ -- https://github.com/ocharles/argon2/issues/3
+ Argon2.hashEncoded opts b argonsalt
where
-- argon salt cannot be shorter than 8 bytes, so pad with spaces.
argonsalt =
let sb = toByteString s
in sb <> B.replicate (8 - B.length sb ) 32
-benchmarkExpensiveHash :: Tunables -> IO (Benchmark (Cost CreationOp))
-benchmarkExpensiveHash tunables = do
+benchmarkExpensiveHash :: Int -> ExpensiveHashTunable -> Cost op -> IO (Benchmark (Cost op))
+benchmarkExpensiveHash rounds tunables expected = do
start <- getCurrentTime
- let ExpensiveHash expected t = expensiveHash tunables
- (Salt (KeyId gpgKey ("benchmark" :: B.ByteString)))
- ("himom" :: B.ByteString)
- end <- t `deepseq` getCurrentTime
+ forM_ [1..rounds] $ \_ -> do
+ let ExpensiveHash _ t = expensiveHash tunables
+ (Salt (KeyId gpgKey ("benchmark" :: B.ByteString)))
+ ("himom" :: B.ByteString)
+ t `deepseq` return ()
+ end <- getCurrentTime
let diff = floor $ end `diffUTCTime` start
let actual = CPUCost $ Seconds diff
return $ Benchmark
{ expectedBenchmark = expected
, actualBenchmark = actual
}
+
+benchmarkTunables :: Tunables -> IO ()
+benchmarkTunables tunables = do
+ putStrLn "Note that expected times are for 1 core machine."
+ putStrLn "If this machine has 2 cores, the actual times should be half the expected times."
+ putStrLn "Benchmarking 16 rounds of key generation hash..."
+ print =<< benchmarkExpensiveHash 16
+ (keyEncryptionKeyHash $ keyEncryptionKeyTunable tunables)
+ (mapCost (`div` 16) $ randomSaltBytesBruteForceCost $ keyEncryptionKeyTunable tunables)
+ putStrLn "Benchmarking 1 round of name generation hash..."
+ print =<< benchmarkExpensiveHash 1
+ (nameGenerationHash $ nameGenerationTunable tunables)
+ (getexpected $ nameGenerationHash $ nameGenerationTunable tunables)
+ where
+ getexpected (UseArgon2 cost _) = cost