PBKDF2 (empty) → 0.1
raw patch · 4 files changed
+146/−0 lines, 4 filesdep +Cryptodep +basedep +binarysetup-changed
Dependencies added: Crypto, base, binary, bytestring, haskell98
Files
- Crypto/PBKDF2.hs +98/−0
- PBKDF2.cabal +18/−0
- Setup.hs +3/−0
- bsd3.txt +27/−0
+ Crypto/PBKDF2.hs view
@@ -0,0 +1,98 @@+{- | Implementation of Password Based Key Derivation Function, from RSA labs. ++See PKCS # 5 / RFC 2898 from rsa labs: and haskell cafe discussion on why password hashing is a good idea for web apps and a suggestion that this be implemented: ++> http://www.ietf.org/rfc/rfc2898.txt +> http://groups.google.com/group/fa.haskell/browse_thread/thread/66c7aeeb6e47764a/b15d9d74d68c002c+-}+module Crypto.PBKDF2 (pbkdf2, pbkdf2') where++import qualified Data.ByteString.Char8 as B+import qualified Data.ByteString.Lazy as L+import GHC.Word+import Control.Monad (foldM)+import Random+import Data.Digest.SHA512 (hash)+import Data.Word +import Data.Bits+import Data.Binary++newtype Password = Password [Word8]+newtype Salt = Salt [Word8]+newtype HashedPass = HashedPass [Word8]+ deriving Show+++t = pbkdf2 ( Password . toWord8s $ "meh" ) ( Salt . toWord8s $ "moo" )++{- | A reasonable default for rsa pbkdf2. ++> pbkdf2 = pbkdf2' (prfSHA512,64) 5000 64++SHA512 outputs 64 bytes. At least 1000 iters is suggested by PKCS#5 (rsa link above). I chose 5000 because this takes my computer a little over a second to compute a simple key derivation (see t test function in source)++Dklen of 64 seemed reasonable to me: if this is being stored in a database, doesn't take too much space.++Computational barriers can be raised by increasing number of iters+-} +--sha512 generates 64-element octet lists, so set hlen to 64. +-- not sure if this is correct. does hlen refer to length in bytes or bits?+pbkdf2 :: Password -> Salt -> HashedPass+pbkdf2 = pbkdf2' (prfSHA512,64) 5000 64+++{- | Password Based Key Derivation Function, from RSA labs.++> pbkdf2' (prf,hlen) cIters dklen (Password pass) (Salt salt) ++prf: pseudo random function++hlen: length of prf output++cIters: Number of iterations of prf++dklen: Length of the derived key (hashed password)+-}+pbkdf2' :: ( ([Word8] -> [Word8] -> [Word8]),Integer) -> Integer -> Integer -> Password -> Salt -> HashedPass+pbkdf2' (prf,hlen) cIters dklen (Password pass) (Salt salt) + | dklen > ( (2^32-1) * hlen) = error $ "pbkdf2, (dklen,hlen) : " ++ (show (dklen,hlen))+ | otherwise = + let --l,r :: Int+ l = ceiling $ (fromIntegral dklen) / (fromIntegral hlen )+ r = dklen - ( (l-1) * hlen)+ ustream :: [Word8] -> [Word8] -> [[Word8]]+ ustream p s = let x = prf p s+ in x : ustream p x + --us :: Integer -> [[Word8]]+ us i = take (fromIntegral cIters) $ ustream pass ( salt `myor` ((intToFourWord8s i) ))+ --f :: [Word8] -> [Word8] -> Integer -> Integer -> [Word8]+ f pass salt cIters i = foldr1 myxor $ us i+ ts :: [[Word8]]+ ts = map (f pass salt cIters) ( [1..l] )+ in HashedPass . take (fromIntegral dklen) . concat $ ts++-- The spec says+-- Here, INT (i) is a four-octet encoding of the integer i, most significant octet first.+-- I'm reading from the right... is this the right thing?+toWord8s x = L.unpack . encode $ x++--intToFourWord8s :: Integer -> [Word8]+intToFourWord8s i = let w8s = toWord8s $ i+ in drop (length w8s -4) w8s++myxor :: [Word8] -> [Word8] -> [Word8]+myxor = zipWith xor ++myor :: [Word8] -> [Word8] -> [Word8]+myor = zipWith (.|.)++{- > prfSHA512 hlen seed pass ...++hlen is the length of the pseudo random output. (not really, fix me)++output is always 64 bytes long+-}+prfSHA512 :: [Word8] -> [Word8] -> [Word8]+prfSHA512 seed pass = hash $ seed ++ pass++t2 = prfSHA512 (toWord8s "asdf") (toWord8s "jkl; asdfjl; asjdfnkl;ajsdfl;jk;sn")
+ PBKDF2.cabal view
@@ -0,0 +1,18 @@+Name: PBKDF2+Version: 0.1+License: BSD3+License-file: bsd3.txt+Description: Implementation of Password-Based Key Derivation Function, aka pbkdf2, from RSA labs.+ http://tools.ietf.org/html/rfc2898#section-5.2+ I'll deprecate this if it's adopted into the Crypto package.+ +Synopsis: Make password-based security schemes more secure.+Maintainer: Thomas Hartman <thomashartman1 at gmail>+Author: Thomas Hartman +Stability: Beta+Copyright: Copyright (c) 2008 Thomas Hartman+Exposed-Modules: Crypto.PBKDF2+Build-Depends: base, bytestring, Crypto, haskell98, binary+Category: Crypto+Build-type: Simple+
+ Setup.hs view
@@ -0,0 +1,3 @@+#!/usr/bin/env runhaskell+import Distribution.Simple+main = defaultMain
+ bsd3.txt view
@@ -0,0 +1,27 @@+Copyright (c) Benedikt Schmidt, Eelco Lempsink 2008++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions+are met:+1. Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.+2. 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.+3. Neither the name of the author nor the names of his contributors+ may be used to endorse or promote products derived from this software+ without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 AUTHORS 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.