summaryrefslogtreecommitdiffhomepage
path: root/Hash.hs
blob: 9b5fa80fb847259ba8f6910980c2915d2d246aae (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
{-# LANGUAGE FlexibleInstances, OverloadedStrings #-}

module Hash where

import Types

import qualified Data.ByteString as B
import qualified Data.ByteString.Char8 as C8
import qualified Crypto.Hash as H

class Hashable a where
	hash :: a -> Hash

instance Hashable B.ByteString where
	-- Encodes the SHA256 using base16 format
	hash = Hash SHA256 . Val . C8.pack . show . sha256

instance Hashable Val where
	hash (Val v) = hash v

instance Hashable Hash where
	hash = id

sha256 :: B.ByteString -> H.Digest H.SHA256
sha256 = H.hash

-- | A value tagged with a ByteString describing the type of value.
-- This is hashed by hashing the concacenation of the hash of the
-- bytestring and the hash of the value. This way, items of different types
-- but with the same internal content will hash differently. For example,
-- a Seen "foo" and a Entered "foo" should not hash the same.
data Tagged a = Tagged B.ByteString a

instance Hashable a => Hashable (Tagged a) where
	hash (Tagged b a) = hash [hash b, hash a]

instance Hashable a => Hashable (Activity a) where
	hash (Activity a (Just p) s) = hash $ Tagged "Activity"
		[hash a, hash p, hash s]
	hash (Activity a Nothing s) = hash $ Tagged "Activity"
		[hash a, hash (), hash s]

instance Hashable a => Hashable (Proto a) where
	hash (Proto a) = hash $ Tagged "Proto" a
	hash (Rejected a) = hash $ Tagged "Rejected" (hash a)

instance Hashable Entered where
	hash v = hash $ Tagged "Entered"
		[hash (enteredData v), hash (echoData v)]

instance Hashable Seen where
	hash v = hash $ Tagged "Seen" [hash (seenData v)]

instance Hashable Signature where
	hash (Signature s) = hash $ Tagged "Signature" s

-- | Hash a list of hashes by hashing the concacenation of the hashes.
instance Hashable [Hash] where
	hash = hash . B.concat . map (val . hashValue)

-- | Hash empty string for ()
instance Hashable () where
	hash () = hash (mempty :: B.ByteString)