module Data.Codec.Blizz.CDHash where
import Data.Bits
import Data.Word
import qualified Data.Vector as V
import Data.Vector (Vector, (//))
import Text.Printf
import Numeric.Taint.Word32
import Data.Digest.XSHA1.Extend
import Data.Digest.XSHA1.Compress
import Data.Digest.XSHA1
data Sniff = Sniff
{ snClientTok :: Word32
, snServerTok :: Word32
, snProduct :: Word32
, snPublic :: Word32
} deriving (Eq,Ord,Show)
hash :: Sniff -> N
-> Vector N
hash s priv = V.fromList $
fmap N [snClientTok s, snServerTok s, snProduct s, snPublic s, 0]
++priv:(take 10 . repeat $ N 0)
sniff1, sniff2 :: Sniff
result1,result2 :: (N,N,N,N,N)
sniff1 = Sniff 0x98c7130e 0xe96733c6 6 0x00010203
result1 = (N 0xdf75610a, N 0x831300a6, N 0x81c8617f, N 0x9fd22f92, N 0x543ddabc)
sniff2 = Sniff 0x98c7130e 0xe96733c6 10 0x00030201
result2 = (N 0xc6625bbd, N 0x6d91ec5c, N 0xb2736fe9, N 0xc89f19f5, N 0x9621a2c6)
view :: Vector N -> IO ()
view xs = V.mapM_ (putStrLn . pprint) xs
classify :: Vector N -> String
classify = fmap f . V.toList where
f (N n) = 'X'
f U = '?'
f (X LShift (N 1) _) = '#'
group _ = error "Unexpected pattern."
space :: Sniff -> [Vector N]
space s = map (extend . hash s . N) [0..31]
setPriv :: N -> Vector N -> Vector N
setPriv p = (// [(5,p)])
test = finalize $ foldl (iter buff) consts [0..79] where
buff = setPriv U $ head (space sniff1)
alpha xs = foldl (iter xs) consts [0..4]
beta xs result = foldl (reti xs) (unfinalize result) (reverse [6..79])
getUnk result xs = let
(X Add n U,_,_,_,_) = iter (setPriv U xs) (alpha xs) 5
(b,_,_,_,_) = beta xs result
in
b n
guessedUnknowns sniff res = map (getUnk res) (space sniff)
unhash :: Sniff -> (N,N,N,N,N) -> IO ()
unhash sniff res
= mapM_ (printf "%x\n")
. map (\(_,N x)->x)
. filter (\(a,b)->a==(b.&.31))
. zip (map N [0..31])
$ guessedUnknowns sniff res
printReg (N a, N b, N c, N d, N e) = printf "%x %x %x %x %x\n" a b c d e
hfoldl f z0 xs = (z,reverse h) where
(z,h) = hfoldl' f (z0,[z0]) xs
hfoldl' f a [] = a
hfoldl' f (a,h) (b:bs) =
let a' = f a b
in hfoldl' f (a',a':h) bs