blob: bf8e1661361dca04d43b005094735c560da514a5 (
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
|
{- Copyright 2017 Joey Hess <id@joeyh.name>
-
- Licensed under the GNU AGPL version 3 or higher.
-}
{-# 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 SHA512 using base16 format
hash = Hash SHA512 . Val . C8.pack . show . sha512
instance Hashable Val where
hash (Val v) = hash v
instance Hashable Hash where
hash = id
sha512 :: B.ByteString -> H.Digest H.SHA512
sha512 = 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 mps mpe mt s) = hash $ Tagged "Activity"
[hash a, hash mps, hash mpe, hash mt, hash s]
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 ControlAction where
hash (EnteredRejected h1 h2) = hash $ Tagged "EnteredRejected"
[hash h1, hash h2]
hash (SessionKey pk) = hash $ Tagged "SessionKey" pk
hash (SessionKeyAccepted pk) = hash $ Tagged "SessionKeyAccepted" pk
hash (SessionKeyRejected pk) = hash $ Tagged "SessionKeyRejected" pk
hash (ChatMessage u m) = hash $ Tagged "ChatMessage" [hash u, hash m]
instance Hashable Signature where
hash (Ed25519Signature s) = hash $ Tagged "Ed25519Signature" s
hash (OtherSignature s) = hash $ Tagged "OtherSignature" s
instance Hashable PublicKey where
hash (PublicKey v) = hash $ Tagged "PublicKey" v
instance Hashable GpgSig where
hash (GpgSig v) = hash $ Tagged "GpgSig" v
instance Hashable a => Hashable (PerhapsSigned a) where
hash (GpgSigned a sig) = hash $ Tagged "GpgSigned" [hash a, hash sig]
hash (UnSigned a) = hash $ Tagged "UnSigned" a
instance Hashable ElapsedTime where
hash (ElapsedTime n) = hash $ Tagged "ElapsedTime" $ C8.pack $ show n
-- | 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 Nothing
instance Hashable v => Hashable (Maybe v) where
hash Nothing = hash ()
hash (Just v) = hash v
instance Hashable () where
hash () = hash (mempty :: B.ByteString)
|