sha256.lua

by hugeblank
520 days ago
COPY
1
-- SHA-256
2
-- By KillaVanilla
3
-- Made require-able by hugeblank
4

5
k = {
6
   0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
7
   0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
8
   0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
9
   0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
10
   0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
11
   0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
12
   0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
13
   0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
14
}
15

16
local function generateShiftBitmask(bits)
17
	local bitmask = 0
18
	for i=1, bits do
19
		bit.bor(bitmask, 0x8000000)
20
		bit.brshift(bitmask, 1)
21
	end
22
	return bitmask
23
end
24

25
local function rrotate(input, shiftAmount)
26
	if input > (2^32) then
27
		input = input % (2^32)
28
	end
29
	return bit.bor( bit.brshift(input, shiftAmount), bit.blshift(input, 32-shiftAmount) )
30
end
31

32
local function Preprocessing(message)
33
	local len = #message*8
34
	local bits = #message*8
35
	table.insert(message, 1)
36
	while true do
37
		if bits % 512 == 448 then
38
			break
39
		else
40
			table.insert(message, 0)
41
			bits = #message*8
42
		end
43
	end
44
	table.insert(message, len)
45
	return message
46
end
47

48
local function breakMsg(message)
49
	local chunks = {}
50
	local chunk = 1
51
	for word=1, #message, 16 do
52
		chunks[chunk] = {}
53
		table.insert(chunks[chunk], message[word] or 0)
54
		table.insert(chunks[chunk], message[word+1] or 0)
55
		table.insert(chunks[chunk], message[word+2] or 0)
56
		table.insert(chunks[chunk], message[word+3] or 0)
57
		table.insert(chunks[chunk], message[word+4] or 0)
58
		table.insert(chunks[chunk], message[word+5] or 0)
59
		table.insert(chunks[chunk], message[word+6] or 0)
60
		table.insert(chunks[chunk], message[word+7] or 0)
61
		table.insert(chunks[chunk], message[word+8] or 0)
62
		table.insert(chunks[chunk], message[word+9] or 0)
63
		table.insert(chunks[chunk], message[word+10] or 0)
64
		table.insert(chunks[chunk], message[word+11] or 0)
65
		table.insert(chunks[chunk], message[word+12] or 0)
66
		table.insert(chunks[chunk], message[word+13] or 0)
67
		table.insert(chunks[chunk], message[word+14] or 0)
68
		table.insert(chunks[chunk], message[word+15] or 0)
69
		chunk = chunk+1
70
	end
71
	return chunks
72
end
73

74
local function digestChunk(chunk, hash)
75
	for i=17, 64 do
76
		local s0 = bit.bxor( bit.brshift(chunk[i-15], 3), bit.bxor( rrotate(chunk[i-15], 7), rrotate(chunk[i-15], 18) ) )
77
		local s1 = bit.bxor( bit.brshift(chunk[i-2], 10), bit.bxor( rrotate(chunk[i-2], 17), rrotate(chunk[i-2], 19) ) )
78
		chunk[i] = (chunk[i-16] + s0 + chunk[i-7] + s1) % (2^32)
79
	end
80

81
	local a = hash[1]
82
	local b = hash[2]
83
	local c = hash[3]
84
	local d = hash[4]
85
	local e = hash[5]
86
	local f = hash[6]
87
	local g = hash[7]
88
	local h = hash[8]
89
	
90
	for i=1, 64 do
91
		local S1 = bit.bxor(rrotate(e, 6), bit.bxor(rrotate(e,11),rrotate(e,25)))
92
		local ch = bit.bxor( bit.band(e, f), bit.band(bit.bnot(e), g) )
93
		local t1 = h + S1 + ch + k[i] + chunk[i]
94
		--d = d+h
95
		S0 = bit.bxor(rrotate(a,2), bit.bxor( rrotate(a,13), rrotate(a,22) ))
96
		local maj = bit.bxor( bit.band( a, bit.bxor(b, c) ), bit.band(b, c) )
97
		local t2 = S0 + maj
98
		
99
		h = g
100
		g = f
101
		f = e
102
		e = d + t1
103
		d = c
104
		c = b
105
		b = a
106
		a = t1 + t2
107
		
108
		a = a % (2^32)
109
		b = b % (2^32)
110
		c = c % (2^32)
111
		d = d % (2^32)
112
		e = e % (2^32)
113
		f = f % (2^32)
114
		g = g % (2^32)
115
		h = h % (2^32)
116
		
117
	end
118
		
119
	hash[1] = (hash[1] + a) % (2^32)
120
	hash[2] = (hash[2] + b) % (2^32)
121
	hash[3] = (hash[3] + c) % (2^32)
122
	hash[4] = (hash[4] + d) % (2^32)
123
	hash[5] = (hash[5] + e) % (2^32)
124
	hash[6] = (hash[6] + f) % (2^32)
125
	hash[7] = (hash[7] + g) % (2^32)
126
	hash[8] = (hash[8] + h) % (2^32)
127
	
128
	return hash
129
end
130

131
local function digest(msg)
132
	msg = Preprocessing(msg)
133
	local hash = {0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19}
134
	local chunks = breakMsg(msg)
135
	for i=1, #chunks do
136
		hash = digestChunk(chunks[i], hash)
137
	end
138
	return hash
139
end
140

141
local function digestStr(input)
142
	-- transform the input into a table of ints:
143
	local output = {}
144
	local outputStr = ""
145
	for i=1, #input do
146
		output[i] = string.byte(input, i, i)
147
	end
148
	output = digest(output)
149
	for i=1, #output do
150
		outputStr = outputStr..string.format("%X", output[i])
151
	end
152
	return outputStr, output
153
end
154

155
local function hashToBytes(hash)
156
	local bytes = {}
157
	for i=1, 8 do
158
		table.insert(bytes, bit.band(bit.brshift(bit.band(hash[i], 0xFF000000), 24), 0xFF))
159
		table.insert(bytes, bit.band(bit.brshift(bit.band(hash[i], 0xFF0000), 16), 0xFF))
160
		table.insert(bytes, bit.band(bit.brshift(bit.band(hash[i], 0xFF00), 8), 0xFF))
161
		table.insert(bytes, bit.band(hash[i], 0xFF))
162
	end
163
	return bytes
164
end
165

166
local function hmac(input, key)
167
	-- HMAC(H,K,m) = H( (K <xor> opad) .. H((K <xor> ipad) .. m))
168
	-- Where:
169
	-- H - cryptographic hash function. In this case, H is SHA-256.
170
	-- K - The secret key.
171
	--	if length(K) > 256 bits or 32 bytes, then K = H(K)
172
	--  if length(K) < 256 bits or 32 bytes, then pad K to the right with zeroes. (i.e pad(K) = K .. repeat(0, 32 - byte_length(K)))
173
	-- m - The message to be authenticated.
174
	-- .. - byte concentration
175
	-- <xor> eXclusive OR.
176
	-- opad - Outer Padding, equal to repeat(0x5C, 32).
177
	-- ipad - Inner Padding, equal to repeat(0x36, 32).
178
	if #key > 32 then
179
		local keyDigest = digest(key)
180
		key = keyDigest
181
	elseif #key < 32 then
182
		for i=#key, 32 do
183
			key[i] = 0
184
		end
185
	end
186
	local opad = {}
187
	local ipad = {}
188
	for i=1, 32 do
189
		opad[i] = bit.bxor(0x5C, key[i] or 0)
190
		ipad[i] = bit.bxor(0x36, key[i] or 0)
191
	end
192
	local padded_key = {}
193
	for i=1, #input do
194
		ipad[32+i] = input[i]
195
	end
196
	local ipadHash = hashToBytes(digest(ipad))
197
	ipad = ipadHash
198
	for i=1, 32 do
199
		padded_key[i] = opad[i]
200
		padded_key[32+i] = ipad[i]
201
	end
202
	return digest(padded_key)
203
end
204

205
return {
206
    digest = digest,
207
    digestStr = digestStr,
208
    hmac = hmac,
209
}