httpserver-b64decode.lua 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. #!/usr/local/bin/lua
  2. -- httpserver-b64decode.lua
  3. -- Part of nodemcu-httpserver, contains b64 decoding used for HTTP Basic Authentication.
  4. -- Modified to use an exponentiation by multiplication method for only applicable for unsigned integers.
  5. -- Based on http://lua-users.org/wiki/BaseSixtyFour by Alex Kloss
  6. -- compatible with lua 5.1
  7. -- http://www.it-rfc.de
  8. -- Author: Marcos Kirsch
  9. local function uipow(a, b)
  10. local ret = 1
  11. if b >= 0 then
  12. for i = 1, b do
  13. ret = ret * a
  14. end
  15. end
  16. return ret
  17. end
  18. -- bitshift functions (<<, >> equivalent)
  19. -- shift left
  20. local function lsh(value,shift)
  21. return (value*(uipow(2, shift))) % 256
  22. end
  23. -- shift right
  24. local function rsh(value,shift)
  25. -- Lua builds with no floating point don't define math.
  26. if math then return math.floor(value/uipow(2, shift)) % 256 end
  27. return (value/uipow(2, shift)) % 256
  28. end
  29. -- return single bit (for OR)
  30. local function bit(x,b)
  31. return (x % uipow(2, b) - x % uipow(2, (b-1)) > 0)
  32. end
  33. -- logic OR for number values
  34. local function lor(x,y)
  35. local result = 0
  36. for p=1,8 do result = result + (((bit(x,p) or bit(y,p)) == true) and uipow(2, (p-1)) or 0) end
  37. return result
  38. end
  39. -- Character decoding table
  40. local function toBase64Byte(char)
  41. local ascii = string.byte(char, 1)
  42. if ascii >= string.byte('A', 1) and ascii <= string.byte('Z', 1) then return ascii - string.byte('A', 1)
  43. elseif ascii >= string.byte('a', 1) and ascii <= string.byte('z', 1) then return ascii - string.byte('a', 1) + 26
  44. elseif ascii >= string.byte('0', 1) and ascii <= string.byte('9', 1) then return ascii + 4
  45. elseif ascii == string.byte('-', 1) then return 62
  46. elseif ascii == string.byte('_', 1) then return 63
  47. elseif ascii == string.byte('=', 1) then return nil
  48. else return nil, "ERROR! Char is invalid for Base64 encoding: "..char end
  49. end
  50. -- decode base64 input to string
  51. return function(data)
  52. local chars = {}
  53. local result=""
  54. for dpos=0,string.len(data)-1,4 do
  55. for char=1,4 do chars[char] = toBase64Byte((string.sub(data,(dpos+char),(dpos+char)) or "=")) end
  56. result = string.format(
  57. '%s%s%s%s',
  58. result,
  59. string.char(lor(lsh(chars[1],2), rsh(chars[2],4))),
  60. (chars[3] ~= nil) and string.char(lor(lsh(chars[2],4),
  61. rsh(chars[3],2))) or "",
  62. (chars[4] ~= nil) and string.char(lor(lsh(chars[3],6) % 192,
  63. (chars[4]))) or ""
  64. )
  65. end
  66. return result
  67. end