module Data.Digest.XSHA1.Compress where
import qualified Data.Vector as V
import Data.Vector (Vector, (!))
import Data.Bits
import qualified Test.QuickCheck as Q
import Numeric.Taint.Word32
type Regs = (N,N,N,N,N)
consts :: Regs
consts = (N 0x67452301, N 0xefcdab89, N 0x98badcfe, N 0x10325476, N 0xc3d2e1f0)
f :: Int -> N -> N -> N -> N
f r b c d | r<20 = b .&. c .|. complement b .&. d
| r<40 = b `xor` c `xor` d
| r<60 = b .&. c .|. c .&. d .|. d .&. b
| r<80 = b `xor` c `xor` d
k :: Int -> N
k r | r<20 = N 0x5a827999
| r<40 = N 0x6ed9eba1
| r<60 = N 0x8f1bbcdc
| r<80 = N 0xca62c1d6
iter :: Vector N -> Regs -> Int -> Regs
iter xs (a,b,c,d,e) r = (t, a, rotate b 30, c, d) where
t = e + f r b c d + (xs!r) + (k r) + rotate a 5
reti :: Vector N -> Regs -> Int -> Regs
reti xs (a',b',c',d',e') r = (a,b,c,d,e) where
e = a' f r b c d (xs!r) k r rotate a 5
a = b'
b = rotate c' (30)
c = d'
d = e'
finalize :: Regs -> Regs
finalize (a,b,c,d,e) =
let (aa,bb,cc,dd,ee) = consts
in (a+aa,b+bb,c+cc,d+dd,e+ee)
unfinalize :: Regs -> Regs
unfinalize (a,b,c,d,e) =
let (aa,bb,cc,dd,ee) = consts
in (aaa,bbb,ccc,ddd,eee)
instance Q.Arbitrary N where
arbitrary = do
int <- Q.choose (0, 0xFFFFFFFF) :: Q.Gen Int
return . N . read . show $ int
test = Q.quickCheck (\t-> do
r <- Q.choose (0, 79)
xs <- V.fromList `fmap` Q.vector 80 :: Q.Gen (Vector N)
return $ (reti xs (iter xs t r) r) == t)