Skip to content

Commit aa54d30

Browse files
committed
Replace sha256.lua with sha1.lua (no need for 5.2 bit32)
Fixes #6, version bump
1 parent 93b6163 commit aa54d30

File tree

6 files changed

+337
-246
lines changed

6 files changed

+337
-246
lines changed

cat_osc.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"src/license_blurb.lua",
55
"<version>",
66
"lib/helpers.lua",
7-
"lib/sha256.lua",
7+
"lib/sha1.lua",
88
"src/options.lua",
99
"src/thumbnailer_shared.lua",
1010
"src/patched_osc.lua"
@@ -15,4 +15,4 @@
1515

1616
"header_prefix" : "--[ ",
1717
"header_suffix" : " ]--"
18-
}
18+
}

lib/sha1.lua

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

0 commit comments

Comments
 (0)