View difference between Paste ID: DyQFEAWa and NdDiPzvB
SHOW: | | - or go back to the newest paste.
1
-------------------------------------------------------------------------------
2
-- SHA-1 secure hash computation, and HMAC-SHA1 signature computation,
3
-- in pure Lua (tested on Lua 5.1)
4
-- License: GPL
5
--
6
-- Usage:
7
--   local hash_as_hex   = sha1(message)            -- returns a hex string
8
--   local hash_as_data  = sha1_binary(message)     -- returns raw bytes
9
--
10
-- Pass sha1() a string, and it returns a hash as a 40-character hex string.
11
--
12
-- The "_binary" version does the same, but returns the 20-byte string of raw
13
-- data that the 40-byte hex string represents.
14
--
15
-------------------------------------------------------------------------------
16
-- based on Zet's implementation (which I found too big)
17
-- > http://cube3d.de/uploads/Main/sha1.txt
18
-- > > based on Jeffrey Friedl's implementation (which I found a bit too slow)
19
-- > > jfriedl@yahoo.com
20
-- > > http://regex.info/blog/
21
-- > > Version 1 [May 28, 2009]
22
-- Algorithm: http://www.itl.nist.gov/fipspubs/fip180-1.htm
23
24
-------------------------------------------------------------------------------
25
-------------------------------------------------------------------------------
26
27
-- set this to false if you don't want to build several 64k sized tables when
28
-- loading this file (takes a while but grants a boost of factor 13)
29
local cfg_caching = false
30
31
-- local storing of global functions (minor speedup)
32
local floor,modf = math.floor,math.modf
33
local char,format,rep = string.char,string.format,string.rep
34
35
-- merge 4 bytes to an 32 bit word
36
local function bytes_to_w32 (a,b,c,d) return a*0x1000000+b*0x10000+c*0x100+d end
37
-- split a 32 bit word into four 8 bit numbers
38
local function w32_to_bytes (i)
39
	return floor(i/0x1000000)%0x100,floor(i/0x10000)%0x100,floor(i/0x100)%0x100,i%0x100
40
end
41
42
-- shift the bits of a 32 bit word. Don't use negative values for "bits"
43
local function w32_rot (bits,a)
44
	local b2 = 2^(32-bits)
45
	local a,b = modf(a/b2)
46
	return a+b*b2*(2^(bits))
47
end
48
49
-- caching function for functions that accept 2 arguments, both of values between
50
-- 0 and 255. The function to be cached is passed, all values are calculated
51
-- during loading and a function is returned that returns the cached values (only)
52
local function cache2arg (fn)
53
	if not cfg_caching then return fn end
54
	local lut = {}
55
	for i=0,0xffff do
56
		local a,b = floor(i/0x100),i%0x100
57
		lut[i] = fn(a,b)
58
	end
59
	return function (a,b)
60
		return lut[a*0x100+b]
61
	end
62
end
63
64
-- splits an 8-bit number into 8 bits, returning all 8 bits as booleans
65
local function byte_to_bits (b)
66
	local b = function (n)
67
		local b = floor(b/n)
68
		return b%2==1
69
	end
70
	return b(1),b(2),b(4),b(8),b(16),b(32),b(64),b(128)
71
end
72
73
-- builds an 8bit number from 8 booleans
74
local function bits_to_byte (a,b,c,d,e,f,g,h)
75
	local function n(b,x) return b and x or 0 end
76
	return n(a,1)+n(b,2)+n(c,4)+n(d,8)+n(e,16)+n(f,32)+n(g,64)+n(h,128)
77
end
78
79
-- debug function for visualizing bits in a string
80
local function bits_to_string (a,b,c,d,e,f,g,h)
81
	local function x(b) return b and "1" or "0" end
82
	return ("%s%s%s%s %s%s%s%s"):format(x(a),x(b),x(c),x(d),x(e),x(f),x(g),x(h))
83
end
84
85
-- debug function for converting a 8-bit number as bit string
86
local function byte_to_bit_string (b)
87
	return bits_to_string(byte_to_bits(b))
88
end
89
90
-- debug function for converting a 32 bit number as bit string
91
local function w32_to_bit_string(a)
92
	if type(a) == "string" then return a end
93
	local aa,ab,ac,ad = w32_to_bytes(a)
94
	local s = byte_to_bit_string
95
	return ("%s %s %s %s"):format(s(aa):reverse(),s(ab):reverse(),s(ac):reverse(),s(ad):reverse()):reverse()
96
end
97
98
-- bitwise "and" function for 2 8bit number
99
local band = cache2arg (function(a,b)
100
	local A,B,C,D,E,F,G,H = byte_to_bits(b)
101
	local a,b,c,d,e,f,g,h = byte_to_bits(a)
102
	return bits_to_byte(
103
		A and a, B and b, C and c, D and d,
104
		E and e, F and f, G and g, H and h)
105
end)
106
107
-- bitwise "or" function for 2 8bit numbers
108
local bor = cache2arg(function(a,b)
109
	local A,B,C,D,E,F,G,H = byte_to_bits(b)
110
	local a,b,c,d,e,f,g,h = byte_to_bits(a)
111
	return bits_to_byte(
112
		A or a, B or b, C or c, D or d,
113
		E or e, F or f, G or g, H or h)
114
end)
115
116
-- bitwise "xor" function for 2 8bit numbers
117
local bxor = cache2arg(function(a,b)
118
	local A,B,C,D,E,F,G,H = byte_to_bits(b)
119
	local a,b,c,d,e,f,g,h = byte_to_bits(a)
120
	return bits_to_byte(
121
		A ~= a, B ~= b, C ~= c, D ~= d,
122
		E ~= e, F ~= f, G ~= g, H ~= h)
123
end)
124
125
-- bitwise complement for one 8bit number
126
local function bnot (x)
127
	return 255-(x % 256)
128
end
129
130
-- creates a function to combine to 32bit numbers using an 8bit combination function
131
local function w32_comb(fn)
132
	return function (a,b)
133
		local aa,ab,ac,ad = w32_to_bytes(a)
134
		local ba,bb,bc,bd = w32_to_bytes(b)
135
		return bytes_to_w32(fn(aa,ba),fn(ab,bb),fn(ac,bc),fn(ad,bd))
136
	end
137
end
138
139
-- create functions for and, xor and or, all for 2 32bit numbers
140
local w32_and = w32_comb(band)
141
local w32_xor = w32_comb(bxor)
142
local w32_or = w32_comb(bor)
143
144
-- xor function that may receive a variable number of arguments
145
local function w32_xor_n (a,...)
146
	local aa,ab,ac,ad = w32_to_bytes(a)
147
	for i=1,select('#',...) do
148
		local ba,bb,bc,bd = w32_to_bytes(select(i,...))
149
		aa,ab,ac,ad = bxor(aa,ba),bxor(ab,bb),bxor(ac,bc),bxor(ad,bd)
150
	end
151
	return bytes_to_w32(aa,ab,ac,ad)
152
end
153
154
-- combining 3 32bit numbers through binary "or" operation
155
local function w32_or3 (a,b,c)
156
	local aa,ab,ac,ad = w32_to_bytes(a)
157
	local ba,bb,bc,bd = w32_to_bytes(b)
158
	local ca,cb,cc,cd = w32_to_bytes(c)
159
	return bytes_to_w32(
160
		bor(aa,bor(ba,ca)), bor(ab,bor(bb,cb)), bor(ac,bor(bc,cc)), bor(ad,bor(bd,cd))
161
	)
162
end
163
164
-- binary complement for 32bit numbers
165
local function w32_not (a)
166
	return 4294967295-(a % 4294967296)
167
end
168
169
-- adding 2 32bit numbers, cutting off the remainder on 33th bit
170
local function w32_add (a,b) return (a+b) % 4294967296 end
171
172
-- adding n 32bit numbers, cutting off the remainder (again)
173
local function w32_add_n (a,...)
174
	for i=1,select('#',...) do
175
		a = (a+select(i,...)) % 4294967296
176
	end
177
	return a
178
end
179
-- converting the number to a hexadecimal string
180
local function w32_to_hexstring (w) return format("%08x",w) end
181
182
-- calculating the SHA1 for some text
183
function sha1(msg)
184
	local H0,H1,H2,H3,H4 = 0x67452301,0xEFCDAB89,0x98BADCFE,0x10325476,0xC3D2E1F0
185
	local msg_len_in_bits = #msg * 8
186
187
	local first_append = char(0x80) -- append a '1' bit plus seven '0' bits
188
189
	local non_zero_message_bytes = #msg +1 +8 -- the +1 is the appended bit 1, the +8 are for the final appended length
190
	local current_mod = non_zero_message_bytes % 64
191
	local second_append = current_mod>0 and rep(char(0), 64 - current_mod) or ""
192
193
	-- now to append the length as a 64-bit number.
194
	local B1, R1 = modf(msg_len_in_bits  / 0x01000000)
195
	local B2, R2 = modf( 0x01000000 * R1 / 0x00010000)
196
	local B3, R3 = modf( 0x00010000 * R2 / 0x00000100)
197
	local B4	  =	0x00000100 * R3
198
199
	local L64 = char( 0) .. char( 0) .. char( 0) .. char( 0) -- high 32 bits
200
				.. char(B1) .. char(B2) .. char(B3) .. char(B4) --  low 32 bits
201
202
	msg = msg .. first_append .. second_append .. L64
203
204
	assert(#msg % 64 == 0)
205
206
	local chunks = #msg / 64
207
208
	local W = { }
209
	local start, A, B, C, D, E, f, K, TEMP
210
	local chunk = 0
211
212
	while chunk < chunks do
213
		--
214
		-- break chunk up into W[0] through W[15]
215
		--
216
		start,chunk = chunk * 64 + 1,chunk + 1
217
218
		for t = 0, 15 do
219
			W[t] = bytes_to_w32(msg:byte(start, start + 3))
220
			start = start + 4
221
		end
222
223
		--
224
		-- build W[16] through W[79]
225
		--
226
		for t = 16, 79 do
227
			-- For t = 16 to 79 let Wt = S1(Wt-3 XOR Wt-8 XOR Wt-14 XOR Wt-16).
228
			W[t] = w32_rot(1, w32_xor_n(W[t-3], W[t-8], W[t-14], W[t-16]))
229
		end
230
231
		A,B,C,D,E = H0,H1,H2,H3,H4
232
233
		for t = 0, 79 do
234
			if t <= 19 then
235
				-- (B AND C) OR ((NOT B) AND D)
236
				f = w32_or(w32_and(B, C), w32_and(w32_not(B), D))
237
				K = 0x5A827999
238
			elseif t <= 39 then
239
				-- B XOR C XOR D
240
				f = w32_xor_n(B, C, D)
241
				K = 0x6ED9EBA1
242
			elseif t <= 59 then
243
				-- (B AND C) OR (B AND D) OR (C AND D
244
				f = w32_or3(w32_and(B, C), w32_and(B, D), w32_and(C, D))
245
				K = 0x8F1BBCDC
246
			else
247
				-- B XOR C XOR D
248
				f = w32_xor_n(B, C, D)
249
				K = 0xCA62C1D6
250
			end
251
252
			-- TEMP = S5(A) + ft(B,C,D) + E + Wt + Kt;
253
			A,B,C,D,E = w32_add_n(w32_rot(5, A), f, E, W[t], K),
254
				A, w32_rot(30, B), C, D
255
		end
256
		-- Let H0 = H0 + A, H1 = H1 + B, H2 = H2 + C, H3 = H3 + D, H4 = H4 + E.
257
		H0,H1,H2,H3,H4 = w32_add(H0, A),w32_add(H1, B),w32_add(H2, C),w32_add(H3, D),w32_add(H4, E)
258
	end
259
	local f = w32_to_hexstring
260
	return f(H0) .. f(H1) .. f(H2) .. f(H3) .. f(H4)
261
end
262
263
local function hex_to_binary(hex)
264
	return hex:gsub('..', function(hexval)
265
		return string.char(tonumber(hexval, 16))
266
	end)
267
end
268
269
function sha1_binary(msg)
270
	return hex_to_binary(sha1(msg))
271
end
272
273
local xor_with_0x5c = {}
274
local xor_with_0x36 = {}
275
-- building the lookuptables ahead of time (instead of littering the source code
276
-- with precalculated values)
277
for i=0,0xff do
278
	xor_with_0x5c[char(i)] = char(bxor(i,0x5c))
279
	xor_with_0x36[char(i)] = char(bxor(i,0x36))
280
end
281
282
-- String Randomizer API --
283
local chars = {}
284
for loop = 0, 255 do
285
   chars[loop+1] = string.char(loop)
286
end
287
local string = table.concat(chars)
288
289
local built = {['.'] = chars}
290
291
local addLookup = function(charSet)
292
   local substitute = string.gsub(string, '[^'..charSet..']', '')
293
   local lookup = {}
294
   for loop = 1, string.len(substitute) do
295
       lookup[loop] = string.sub(substitute, loop, loop)
296
   end
297
   built[charSet] = lookup
298
299
   return lookup
300
end
301
302
function random(length, charSet)
303
   -- length (number)
304
   -- charSet (string, optional); e.g. %l%d for lower case letters and digits
305
306
   local charSet = charSet or '.'
307
308
   if charSet == '' then
309
      return ''
310
   else
311
      local result = {}
312
      local lookup = built[charSet] or addLookup(charSet)
313
      local range = table.getn(lookup)
314
315
      for loop = 1,length do
316
         result[loop] = lookup[math.random(1, range)]
317
      end
318
319
      return table.concat(result)
320
   end
321
end
322
323
function randomULN(length)
324
   return random(length, "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM0123456789")
325
end
326
327
-- Hashing API --
328
function hashPassword(password)
329
   local salt = string.sub(sha1(randomULN(20)), 1, 12)
330
   local hash = sha1(salt .. password)
331
   local saltPos = string.len(password)
332
   if saltPos > string.len(hash) then
333
      saltPos = string.len(hash)
334
   end
335
   return string.sub(hash, 1, saltPos) .. salt .. string.sub(hash, saltPos + 1, string.len(hash))
336
end
337
338
function checkPassword(input, correct)
339
   local saltPos = string.len(correct)
340
   if saltPos > string.len(input) - 12 then
341
      saltPos = string.len(input) - 12
342
   end
343
   local salt = string.sub(input, saltPos + 1, saltPos + 12)
344
   local password = sha1(salt .. correct)
345
   return (password == (string.sub(input, 1, saltPos) .. string.sub(input, saltPos + 13, string.len(input))))
346
end
347
348
-- crypt.checkPassword(crypt.hashPassword("password"), "password")