util/sha1.lua

1
-------------------------------------------------
2
---      *** SHA-1 algorithm for Lua ***      ---
3
-------------------------------------------------
4
--- Author:  Martin Huesser                   ---
5
--- Date:    2008-06-16                       ---
6
--- License: You may use this code in your    ---
7
---          projects as long as this header  ---
8
---          stays intact.                    ---
9
-------------------------------------------------
10
 
11
local strlen  = string.len
12
local strchar = string.char
13
local strbyte = string.byte
14
local strsub  = string.sub
15
local floor   = math.floor
16
local bit     = bit32 or require "prosody.util.bit"
17
local bnot    = bit.bnot
18
local band    = bit.band
19
local bor     = bit.bor
20
local bxor    = bit.bxor
21
local shl     = bit.lshift
22
local shr     = bit.rshift
23
local h0, h1, h2, h3, h4
24
 
25
-------------------------------------------------
26
 
27
local function LeftRotate(val, nr)
28
	return shl(val, nr) + shr(val, 32 - nr)
29
end
30
 
31
-------------------------------------------------
32
 
33
local function ToHex(num)
34
	local i, d
35
	local str = ""
36
	for i = 1, 8 do
37
		d = band(num, 15)
38
		if (d < 10) then
39
			str = strchar(d + 48) .. str
40
		else
41
			str = strchar(d + 87) .. str
42
		end
43
		num = floor(num / 16)
44
	end
45
	return str
46
end
47
 
48
-------------------------------------------------
49
 
50
local function PreProcess(str)
51
	local bitlen, i
52
	local str2 = ""
53
	bitlen = strlen(str) * 8
54
	str = str .. strchar(128)
55
	i = 56 - band(strlen(str), 63)
56
	if (i < 0) then
57
		i = i + 64
58
	end
59
	for i = 1, i do
60
		str = str .. strchar(0)
61
	end
62
	for i = 1, 8 do
63
		str2 = strchar(band(bitlen, 255)) .. str2
64
		bitlen = floor(bitlen / 256)
65
	end
66
	return str .. str2
67
end
68
 
69
-------------------------------------------------
70
 
71
local function MainLoop(str)
72
	local a, b, c, d, e, f, k, t
73
	local i, j
74
	local w = {}
75
	while (str ~= "") do
76
		for i = 0, 15 do
77
			w[i] = 0
78
			for j = 1, 4 do
79
				w[i] = w[i] * 256 + strbyte(str, i * 4 + j)
80
			end
81
		end
82
		for i = 16, 79 do
83
			w[i] = LeftRotate(bxor(bxor(w[i - 3], w[i - 8]), bxor(w[i - 14], w[i - 16])), 1)
84
		end
85
		a = h0
86
		b = h1
87
		c = h2
88
		d = h3
89
		e = h4
90
		for i = 0, 79 do
91
			if (i < 20) then
92
				f = bor(band(b, c), band(bnot(b), d))
93
				k = 1518500249
94
			elseif (i < 40) then
95
				f = bxor(bxor(b, c), d)
96
				k = 1859775393
97
			elseif (i < 60) then
98
				f = bor(bor(band(b, c), band(b, d)), band(c, d))
99
				k = 2400959708
100
			else
101
				f = bxor(bxor(b, c), d)
102
				k = 3395469782
103
			end
104
			t = LeftRotate(a, 5) + f + e + k + w[i]	
105
			e = d
106
			d = c
107
			c = LeftRotate(b, 30)
108
			b = a
109
			a = t
110
		end
111
		h0 = band(h0 + a, 4294967295)
112
		h1 = band(h1 + b, 4294967295)
113
		h2 = band(h2 + c, 4294967295)
114
		h3 = band(h3 + d, 4294967295)
115
		h4 = band(h4 + e, 4294967295)
116
		str = strsub(str, 65)
117
	end
118
end
119
 
120
-------------------------------------------------
121
 
122
local function sha1(str, hexres)
123
	str = PreProcess(str)
124
	h0  = 1732584193
125
	h1  = 4023233417
126
	h2  = 2562383102
127
	h3  = 0271733878
128
	h4  = 3285377520
129
	MainLoop(str)
130
	local hex = ToHex(h0)..ToHex(h1)..ToHex(h2)
131
	            ..ToHex(h3)..ToHex(h4);
132
	if hexres then
133
		return  hex;
134
	else
135
		return (hex:gsub("..", function (byte)
136
			return string.char(tonumber(byte, 16));
137
		end));
138
	end
139
end
140
 
141
return {
142
	sha1 = sha1;
143
};
144
 
145
-------------------------------------------------
146
-------------------------------------------------
147
-------------------------------------------------