Advertisement
superzilla

Pure Lua SHA-1 and HMAC-SHA1

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