Added HMAC utility module
[prosody.git] / util / hmac.lua
1 local hashes = require "util.hashes"
2 local xor = require "bit".bxor
3
4 module "hmac"
5
6 local function arraystr(array)
7     t = {}
8     for i = 1,table.getn(array) do
9         table.insert(t, string.char(array[i]))
10     end
11
12     return table.concat(t)
13 end
14
15 --[[
16 key
17     the key to use in the hash
18 message
19     the message to hash
20 hash
21     the hash function
22 blocksize
23     the blocksize for the hash function in bytes
24 hex
25   return raw hash or hexadecimal string
26 --]]
27 function hmac(key, message, hash, blocksize, hex)
28     local opad = {}
29     local ipad = {}
30     
31     for i = 1,blocksize do
32         opad[i] = 0x5c
33         ipad[i] = 0x36
34     end
35
36     if #key > blocksize then
37         key = hash(key)
38     end
39
40     for i = 1,#key do
41         ipad[i] = xor(ipad[i],key:sub(i,i):byte())
42         opad[i] = xor(opad[i],key:sub(i,i):byte())
43     end
44
45     opad = arraystr(opad)
46     ipad = arraystr(ipad)
47
48     if hex then
49         return hash(opad..hash(ipad..message), true)
50     else
51         return hash(opad..hash(ipad..message))
52     end
53 end
54
55 function md5(key, message, hex)
56     return hmac(key, message, hashes.md5, 64, hex)
57 end
58
59 function sha1(key, message, hex)
60     return hmac(key, message, hashes.sha1, 64, hex)
61 end
62
63 function sha256(key, message, hex)
64     return hmac(key, message, hashes.sha256, 64, hex)
65 end
66
67 return _M