packages feed

Lazy-Pbkdf2 1.0.2 → 2.1.0

raw patch · 3 files changed

+58/−24 lines, 3 filesdep +cryptonitedep +memorydep −SHAPVP ok

version bump matches the API change (PVP)

Dependencies added: cryptonite, memory

Dependencies removed: SHA

API changes (from Hackage documentation)

- Crypto.Pbkdf2: hmacSha512Pbkdf2 :: ByteString -> ByteString -> Integer -> ByteString
+ Crypto.Pbkdf2: pbkdf2_iterative :: (ByteString -> ByteString -> ByteString) -> ByteString -> ByteString -> Integer -> ByteString

Files

Crypto/Pbkdf2.hs view
@@ -1,12 +1,12 @@-module Crypto.Pbkdf2 (pbkdf2, hmacSha512Pbkdf2) where+module Crypto.Pbkdf2 (pbkdf2, pbkdf2_iterative) where -import Data.Digest.Pure.SHA (hmacSha512, bytestringDigest) import Data.Bits (shiftR)-import Data.ByteString.Lazy as B-import Data.Binary as Bin import Data.Bits(xor) -octetsBE :: Word32 -> [Word8]+import qualified Data.ByteString.Lazy as B+import qualified Data.Binary as Bin++octetsBE :: Bin.Word32 -> [Bin.Word8] octetsBE w =      [ fromIntegral (w `shiftR` 24)     , fromIntegral (w `shiftR` 16)@@ -18,17 +18,55 @@   | B.length x == B.length y = B.pack $ B.zipWith xor x y   | otherwise = error "xor bytestrings are not of equal length" -pbkdf2 :: (ByteString -> ByteString -> ByteString)+-- | This is a non standard variation of PBKDF2 which recursively uses the+-- last generated value to improve the salt. In difference to pbkdf2 the+-- salt can not be precalculated for every iteration (with a simple append+-- of 4 bytes), but has to be calculated for every single iteration. This+-- also creates a function where you cannot jump in the stream without+-- calculating everything before it.  Compared to the standard this+-- function only changes the salt for the initial PBKDF2 value of each+-- iteration to include a salt iterated from earlier parts of the PBKDF2+-- stream. This can be verified by removing the i from (hash' $ B.concat+-- [i, salt, B.pack $ octetsBE c]).+--+-- The added salt for the first iteration will be "", and all following+-- will be calculated as (PRF output input), where output is the output of+-- the previous block and input is the added salt for the previous block.+-- Notice that the output from the previous block is put in the password+-- filed of the PRF.+pbkdf2_iterative :: (B.ByteString -> B.ByteString -> B.ByteString)+                     -- ^ @PRF@, the PRF function to be used for the+                     -- iterative PBKDF2. The first argument is secret, the+                     -- second argument is not.+                 -> B.ByteString -- ^ @Password@, the secret to use in the PBKDF2 computations.+                 -> B.ByteString -- ^ @Salt@, the not neccesarily secret data to use in the PBKDF2 computations.+                 -> Integer -- ^ @c@, number of iterations for the the PBKDF2 computations.+                 -> B.ByteString -- ^ @DK@, the output data in the format of an unlimited lazy ByteString.+pbkdf2_iterative prf password salt iterations = B.concat $ pbkdf2' (B.pack []) 1+  where+    hash' = prf password+    pbkdf2' :: B.ByteString -> Bin.Word32 -> [B.ByteString]+    pbkdf2' i c = let prev = (pbkdf2'' (hash' $ B.concat [i, salt, B.pack $ octetsBE c])) in prev:(pbkdf2' (prf prev i) (c + 1))+    pbkdf2'' hash = pbkdf2''' hash hash 1+    pbkdf2''' prev_hash prev_result i+      | i == iterations = prev_result+      | i > iterations = error "Count must be at least 1"+      | otherwise = pbkdf2''' current_hash result (i + 1)+        where+          current_hash = (hash' prev_hash)+          result = xorByteStrings current_hash prev_result++pbkdf2 :: (B.ByteString -> B.ByteString -> B.ByteString)            -- ^ @PRF@, the PRF function to be used for PBKDF2. The first            -- argument is secret, the second argument is not.-       -> ByteString -- ^ @Password@, the secret to use in the PBKDF2 computations.-       -> ByteString -- ^ @Salt@, the not neccesarily secret data to use in the PBKDF2 computations.+       -> B.ByteString -- ^ @Password@, the secret to use in the PBKDF2 computations.+       -> B.ByteString -- ^ @Salt@, the not neccesarily secret data to use in the PBKDF2 computations.        -> Integer -- ^ @c@, number of iterations for the the PBKDF2 computations.-       -> ByteString -- ^ @DK@, the output data in the format of an unlimited lazy ByteString.+       -> B.ByteString -- ^ @DK@, the output data in the format of an unlimited lazy ByteString. pbkdf2 prf password salt iterations = B.concat $ pbkdf2' 1 True   where     hash' = prf password-    pbkdf2' :: Word32 -> Bool -> [ByteString]+    pbkdf2' :: Bin.Word32 -> Bool -> [B.ByteString]     pbkdf2' 1 False = error "Hashing algorithm looped, stopping to maintain security of data" -- Paranoia, but that's useful when doing crypto     pbkdf2' i _ = (pbkdf2'' (hash' $ B.concat [salt, B.pack $ octetsBE i])):(pbkdf2' (i + 1) False)     pbkdf2'' hash = pbkdf2''' hash hash 1@@ -39,12 +77,3 @@         where           current_hash = (hash' prev_hash)           result = xorByteStrings current_hash prev_result---- |Example of the pbkdf2 function using SHA512. See `pbkdf2` for usage.-hmacSha512Pbkdf2 :: ByteString -- ^ @Password@-                 -> ByteString -- ^ @Salt@-                 -> Integer -- ^ @c@-                 -> ByteString -- ^ @DK@-hmacSha512Pbkdf2 = pbkdf2 hash-  where-    hash password salt = bytestringDigest $ hmacSha512 password salt
Lazy-Pbkdf2.cabal view
@@ -1,5 +1,5 @@ Name:           Lazy-Pbkdf2-Version:        1.0.2+Version:        2.1.0 Author:         Marcus Ofenhed <marcus@conditionraise.se> Maintainer:     Marcus Ofenhed <marcus@conditionraise.se> License:        MIT@@ -15,7 +15,6 @@   Exposed-Modules:   Crypto.Pbkdf2   Default-Language:  Haskell2010   Build-Depends:     base>= 4 && <5,-                     SHA,                      bytestring,                      binary                    @@ -25,10 +24,11 @@   Main-Is:           Pbkdf2-test.hs   Default-Language:  Haskell2010   Build-Depends:     base>= 4 && <5,-                     SHA,+                     cryptonite,                      bytestring,                      base16-bytestring,-                     binary+                     binary,+                     memory  Source-Repository head   Type:       git
Pbkdf2-test.hs view
@@ -1,10 +1,14 @@ import Data.ByteString.Lazy.Char8 as C8-import Crypto.Pbkdf2 (hmacSha512Pbkdf2)+import qualified Data.ByteString.Lazy as BS+import Crypto.Pbkdf2 (pbkdf2) import Data.Binary as B+import Data.ByteArray as BA import Data.ByteString.Base16.Lazy as B16 import Data.Int (Int64) import System.IO (hSetBuffering, stdout, BufferMode (NoBuffering) ) import System.Exit (exitFailure, exitSuccess)+import Crypto.MAC.HMAC (initialize, update, finalize, Context(), hmacGetDigest)+import Crypto.Hash.Algorithms (SHA512)  -- Inofficial test suite fetched from http://stackoverflow.com/a/19898265 test_vectors :: [(ByteString, ByteString, Integer, Int64, ByteString)]@@ -84,6 +88,7 @@   where     generated = B16.encode $ C8.take len $ hmacSha512Pbkdf2 pass salt iter     (pass, salt, iter, len, result) = test+    hmacSha512Pbkdf2 = pbkdf2 (\key d -> let h = (initialize $ C8.toStrict key :: Context SHA512) ; h' = update h $ C8.toStrict d in BS.pack $ BA.unpack $ hmacGetDigest $ finalize h')  countIf :: (a -> Bool) -> [a] -> Int countIf cond = Prelude.length . Prelude.filter cond