File: Blake2.hs

package info (click to toggle)
haskell-crypton 1.0.4-3
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 3,548 kB
  • sloc: haskell: 26,764; ansic: 22,294; makefile: 6
file content (242 lines) | stat: -rw-r--r-- 8,471 bytes parent folder | download
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE ForeignFunctionInterface #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}

-- |
-- Module      : Crypto.Hash.Blake2
-- License     : BSD-style
-- Maintainer  : Nicolas Di Prima <nicolas@primetype.co.uk>
-- Stability   : experimental
-- Portability : unknown
--
-- Module containing the binding functions to work with the
-- Blake2
--
-- Implementation based from [RFC7693](https://tools.ietf.org/html/rfc7693)
--
-- Please consider the following when chosing a hash:
--
--      Algorithm     | Target | Collision | Digest Size |
--         Identifier |  Arch  |  Security |   in bytes  |
--     ---------------+--------+-----------+-------------+
--      id-blake2b160 | 64-bit |   2**80   |         20  |
--      id-blake2b256 | 64-bit |   2**128  |         32  |
--      id-blake2b384 | 64-bit |   2**192  |         48  |
--      id-blake2b512 | 64-bit |   2**256  |         64  |
--     ---------------+--------+-----------+-------------+
--      id-blake2s128 | 32-bit |   2**64   |         16  |
--      id-blake2s160 | 32-bit |   2**80   |         20  |
--      id-blake2s224 | 32-bit |   2**112  |         28  |
--      id-blake2s256 | 32-bit |   2**128  |         32  |
--     ---------------+--------+-----------+-------------+
module Crypto.Hash.Blake2 (
    HashBlake2 (..),
    Blake2s (..),
    Blake2sp (..),
    Blake2b (..),
    Blake2bp (..),
) where

import Crypto.Hash.Types
import Crypto.Internal.Nat
import Data.Data
import Data.Word (Word32, Word8)
import Foreign.Ptr (Ptr)
import GHC.TypeLits (KnownNat, Nat)

-- | Typeclass for the Blake2 family of digest functions.
class HashAlgorithm a => HashBlake2 a where
    -- | Init Blake2 algorithm with the specified key of the specified length.
    -- The key length is specified in bytes.
    blake2InternalKeyedInit :: Ptr (Context a) -> Ptr Word8 -> Word32 -> IO ()

-- | Fast and secure alternative to SHA1 and HMAC-SHA1
--
-- It is espacially known to target 32bits architectures.
--
-- Known supported digest sizes:
--
-- * Blake2s 160
-- * Blake2s 224
-- * Blake2s 256
data Blake2s (bitlen :: Nat) = Blake2s
    deriving (Show, Data)

instance
    ( IsDivisibleBy8 bitlen
    , KnownNat bitlen
    , IsAtLeast bitlen 8
    , IsAtMost bitlen 256
    )
    => HashAlgorithm (Blake2s bitlen)
    where
    type HashBlockSize (Blake2s bitlen) = 64
    type HashDigestSize (Blake2s bitlen) = Div8 bitlen
    type HashInternalContextSize (Blake2s bitlen) = 136
    hashBlockSize _ = 64
    hashDigestSize _ = byteLen (Proxy :: Proxy bitlen)
    hashInternalContextSize _ = 136
    hashInternalInit p = c_blake2s_init p (integralNatVal (Proxy :: Proxy bitlen))
    hashInternalUpdate = c_blake2s_update
    hashInternalFinalize p = c_blake2s_finalize p (integralNatVal (Proxy :: Proxy bitlen))

instance
    ( IsDivisibleBy8 bitlen
    , KnownNat bitlen
    , IsAtLeast bitlen 8
    , IsAtMost bitlen 256
    )
    => HashBlake2 (Blake2s bitlen)
    where
    blake2InternalKeyedInit p = c_blake2s_init_key p outLen
      where
        outLen = integralNatVal (Proxy :: Proxy bitlen)

foreign import ccall unsafe "crypton_blake2s_init"
    c_blake2s_init :: Ptr (Context a) -> Word32 -> IO ()
foreign import ccall unsafe "crypton_blake2s_init_key"
    c_blake2s_init_key :: Ptr (Context a) -> Word32 -> Ptr Word8 -> Word32 -> IO ()
foreign import ccall "crypton_blake2s_update"
    c_blake2s_update :: Ptr (Context a) -> Ptr Word8 -> Word32 -> IO ()
foreign import ccall unsafe "crypton_blake2s_finalize"
    c_blake2s_finalize :: Ptr (Context a) -> Word32 -> Ptr (Digest a) -> IO ()

-- | Fast cryptographic hash.
--
-- It is especially known to target 64bits architectures.
--
-- Known supported digest sizes:
--
-- * Blake2b 160
-- * Blake2b 224
-- * Blake2b 256
-- * Blake2b 384
-- * Blake2b 512
data Blake2b (bitlen :: Nat) = Blake2b
    deriving (Show, Data)

instance
    ( IsDivisibleBy8 bitlen
    , KnownNat bitlen
    , IsAtLeast bitlen 8
    , IsAtMost bitlen 512
    )
    => HashAlgorithm (Blake2b bitlen)
    where
    type HashBlockSize (Blake2b bitlen) = 128
    type HashDigestSize (Blake2b bitlen) = Div8 bitlen
    type HashInternalContextSize (Blake2b bitlen) = 248
    hashBlockSize _ = 128
    hashDigestSize _ = byteLen (Proxy :: Proxy bitlen)
    hashInternalContextSize _ = 248
    hashInternalInit p = c_blake2b_init p (integralNatVal (Proxy :: Proxy bitlen))
    hashInternalUpdate = c_blake2b_update
    hashInternalFinalize p = c_blake2b_finalize p (integralNatVal (Proxy :: Proxy bitlen))

instance
    ( IsDivisibleBy8 bitlen
    , KnownNat bitlen
    , IsAtLeast bitlen 8
    , IsAtMost bitlen 512
    )
    => HashBlake2 (Blake2b bitlen)
    where
    blake2InternalKeyedInit p = c_blake2b_init_key p outLen
      where
        outLen = integralNatVal (Proxy :: Proxy bitlen)

foreign import ccall unsafe "crypton_blake2b_init"
    c_blake2b_init :: Ptr (Context a) -> Word32 -> IO ()
foreign import ccall unsafe "crypton_blake2b_init_key"
    c_blake2b_init_key :: Ptr (Context a) -> Word32 -> Ptr Word8 -> Word32 -> IO ()
foreign import ccall "crypton_blake2b_update"
    c_blake2b_update :: Ptr (Context a) -> Ptr Word8 -> Word32 -> IO ()
foreign import ccall unsafe "crypton_blake2b_finalize"
    c_blake2b_finalize :: Ptr (Context a) -> Word32 -> Ptr (Digest a) -> IO ()

data Blake2sp (bitlen :: Nat) = Blake2sp
    deriving (Show, Data)

instance
    ( IsDivisibleBy8 bitlen
    , KnownNat bitlen
    , IsAtLeast bitlen 8
    , IsAtMost bitlen 256
    )
    => HashAlgorithm (Blake2sp bitlen)
    where
    type HashBlockSize (Blake2sp bitlen) = 64
    type HashDigestSize (Blake2sp bitlen) = Div8 bitlen
    type HashInternalContextSize (Blake2sp bitlen) = 2185
    hashBlockSize _ = 64
    hashDigestSize _ = byteLen (Proxy :: Proxy bitlen)
    hashInternalContextSize _ = 2185
    hashInternalInit p = c_blake2sp_init p (integralNatVal (Proxy :: Proxy bitlen))
    hashInternalUpdate = c_blake2sp_update
    hashInternalFinalize p = c_blake2sp_finalize p (integralNatVal (Proxy :: Proxy bitlen))

instance
    ( IsDivisibleBy8 bitlen
    , KnownNat bitlen
    , IsAtLeast bitlen 8
    , IsAtMost bitlen 256
    )
    => HashBlake2 (Blake2sp bitlen)
    where
    blake2InternalKeyedInit p = c_blake2sp_init_key p outLen
      where
        outLen = integralNatVal (Proxy :: Proxy bitlen)

foreign import ccall unsafe "crypton_blake2sp_init"
    c_blake2sp_init :: Ptr (Context a) -> Word32 -> IO ()
foreign import ccall unsafe "crypton_blake2sp_init_key"
    c_blake2sp_init_key :: Ptr (Context a) -> Word32 -> Ptr Word8 -> Word32 -> IO ()
foreign import ccall "crypton_blake2sp_update"
    c_blake2sp_update :: Ptr (Context a) -> Ptr Word8 -> Word32 -> IO ()
foreign import ccall unsafe "crypton_blake2sp_finalize"
    c_blake2sp_finalize :: Ptr (Context a) -> Word32 -> Ptr (Digest a) -> IO ()

data Blake2bp (bitlen :: Nat) = Blake2bp
    deriving (Show, Data)

instance
    ( IsDivisibleBy8 bitlen
    , KnownNat bitlen
    , IsAtLeast bitlen 8
    , IsAtMost bitlen 512
    )
    => HashAlgorithm (Blake2bp bitlen)
    where
    type HashBlockSize (Blake2bp bitlen) = 128
    type HashDigestSize (Blake2bp bitlen) = Div8 bitlen
    type HashInternalContextSize (Blake2bp bitlen) = 2325
    hashBlockSize _ = 128
    hashDigestSize _ = byteLen (Proxy :: Proxy bitlen)
    hashInternalContextSize _ = 2325
    hashInternalInit p = c_blake2bp_init p (integralNatVal (Proxy :: Proxy bitlen))
    hashInternalUpdate = c_blake2bp_update
    hashInternalFinalize p = c_blake2bp_finalize p (integralNatVal (Proxy :: Proxy bitlen))

instance
    ( IsDivisibleBy8 bitlen
    , KnownNat bitlen
    , IsAtLeast bitlen 8
    , IsAtMost bitlen 512
    )
    => HashBlake2 (Blake2bp bitlen)
    where
    blake2InternalKeyedInit p = c_blake2bp_init_key p outLen
      where
        outLen = integralNatVal (Proxy :: Proxy bitlen)

foreign import ccall unsafe "crypton_blake2bp_init"
    c_blake2bp_init :: Ptr (Context a) -> Word32 -> IO ()
foreign import ccall unsafe "crypton_blake2bp_init_key"
    c_blake2bp_init_key :: Ptr (Context a) -> Word32 -> Ptr Word8 -> Word32 -> IO ()
foreign import ccall "crypton_blake2bp_update"
    c_blake2bp_update :: Ptr (Context a) -> Ptr Word8 -> Word32 -> IO ()
foreign import ccall unsafe "crypton_blake2bp_finalize"
    c_blake2bp_finalize :: Ptr (Context a) -> Word32 -> Ptr (Digest a) -> IO ()