Advertisement
ComputerMan123

AES Encryption by Anavrins

Nov 22nd, 2016
102
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.47 KB | None | 0 0
  1. -- Chacha20 cipher in ComputerCraft
  2. -- By Anavrins
  3. -- For help and details, you can PM me on the CC forums
  4. -- http://www.computercraft.info/forums2/index.php?/user/12870-anavrins
  5. -- You may use this code in your projects without asking me, as long as credit is given and this header is kept intact
  6.  
  7. local bxor = bit32.bxor
  8. local band = bit32.band
  9. local blshift = bit32.lshift
  10. local brshift = bit32.arshift
  11.  
  12. local mod = 2^32
  13. local tau = {("expand 16-byte k"):byte(1,-1)}
  14. local sigma = {("expand 32-byte k"):byte(1,-1)}
  15.  
  16. local function rotl(n, b)
  17. local s = n/(2^(32-b))
  18. local f = s%1
  19. return (s-f) + f*mod
  20. end
  21.  
  22. local function quarterRound(s, a, b, c, d)
  23. s[a] = (s[a]+s[b])%mod; s[d] = rotl(bxor(s[d], s[a]), 16)
  24. s[c] = (s[c]+s[d])%mod; s[b] = rotl(bxor(s[b], s[c]), 12)
  25. s[a] = (s[a]+s[b])%mod; s[d] = rotl(bxor(s[d], s[a]), 8)
  26. s[c] = (s[c]+s[d])%mod; s[b] = rotl(bxor(s[b], s[c]), 7)
  27. return s
  28. end
  29.  
  30. local function hashBlock(state, rnd)
  31. local s = {unpack(state)}
  32. local r = true
  33. for i = 1, rnd do
  34. s = r and quarterRound(s, 1, 5, 9, 13) or quarterRound(s, 1, 6, 11, 16)
  35. s = r and quarterRound(s, 2, 6, 10, 14) or quarterRound(s, 2, 7, 12, 13)
  36. s = r and quarterRound(s, 3, 7, 11, 15) or quarterRound(s, 3, 8, 9, 14)
  37. s = r and quarterRound(s, 4, 8, 12, 16) or quarterRound(s, 4, 5, 10, 15)
  38. r = not r
  39. end
  40. for i = 1, 16 do
  41. s[i] = (s[i]+state[i])%mod
  42. end
  43. return s
  44. end
  45.  
  46. local function LE_toInt(bs, i)
  47. return (bs[i+1] or 0)+
  48. blshift((bs[i+2] or 0), 8)+
  49. blshift((bs[i+3] or 0), 16)+
  50. blshift((bs[i+4] or 0), 24)
  51. end
  52.  
  53. local function initState(key, nonce, counter)
  54. local isKey256 = #key == 32
  55. local const = isKey256 and sigma or tau
  56. local state = {}
  57.  
  58. state[ 1] = LE_toInt(const, 0)
  59. state[ 2] = LE_toInt(const, 4)
  60. state[ 3] = LE_toInt(const, 8)
  61. state[ 4] = LE_toInt(const, 12)
  62.  
  63. state[ 5] = LE_toInt(key, 0)
  64. state[ 6] = LE_toInt(key, 4)
  65. state[ 7] = LE_toInt(key, 8)
  66. state[ 8] = LE_toInt(key, 12)
  67. state[ 9] = LE_toInt(key, isKey256 and 16 or 0)
  68. state[10] = LE_toInt(key, isKey256 and 20 or 4)
  69. state[11] = LE_toInt(key, isKey256 and 24 or 8)
  70. state[12] = LE_toInt(key, isKey256 and 28 or 12)
  71.  
  72. state[13] = counter
  73. state[14] = LE_toInt(nonce, 0)
  74. state[15] = LE_toInt(nonce, 4)
  75. state[16] = LE_toInt(nonce, 8)
  76.  
  77. return state
  78. end
  79.  
  80. local function serialize(state)
  81. local r = {}
  82. for i = 1, 16 do
  83. r[#r+1] = band(state[i], 0xFF)
  84. r[#r+1] = band(brshift(band(state[i], 0xFF00), 8), 0xFF)
  85. r[#r+1] = band(brshift(band(state[i], 0xFF0000), 16), 0xFF)
  86. r[#r+1] = band(brshift(band(state[i], 0xFF000000), 24), 0xFF)
  87. end
  88. return r
  89. end
  90.  
  91. local mt = {
  92. __tostring = function(a) return string.char(unpack(a)) end,
  93. __index = {
  94. toHex = function(self, s) return ("%02x"):rep(#self):format(unpack(self)) end,
  95. isEqual = function(self, t)
  96. if type(t) ~= "table" then return false end
  97. if #self ~= #t then return false end
  98. local ret = 0
  99. for i = 1, #self do
  100. ret = bit32.bor(ret, bxor(self[i], t[i]))
  101. end
  102. return ret == 0
  103. end
  104. }
  105. }
  106.  
  107. local function crypt(data, key, nonce, cntr, round)
  108. assert(type(key) == "table", "ChaCha20: Invalid key format ("..type(key).."), must be table")
  109. assert(type(nonce) == "table", "ChaCha20: Invalid nonce format ("..type(nonce).."), must be table")
  110. assert(#key == 16 or #key == 32, "ChaCha20: Invalid key length ("..#key.."), must be 16 or 32")
  111. assert(#nonce == 12, "ChaCha20: Invalid nonce length ("..#nonce.."), must be 12")
  112.  
  113. local data = type(data) == "table" and {unpack(data)} or {tostring(data):byte(1,-1)}
  114. cntr = tonumber(cntr) or 1
  115. round = tonumber(round) or 20
  116.  
  117. local out = {}
  118. local state = initState(key, nonce, cntr)
  119. local blockAmt = math.floor(#data/64)
  120. for i = 0, blockAmt do
  121. local ks = serialize(hashBlock(state, round))
  122. state[13] = (state[13]+1) % mod
  123.  
  124. local block = {}
  125. for j = 1, 64 do
  126. block[j] = data[((i)*64)+j]
  127. end
  128. for j = 1, #block do
  129. out[#out+1] = bxor(block[j], ks[j])
  130. end
  131.  
  132. if i % 1000 == 0 then
  133. os.queueEvent("")
  134. os.pullEvent("")
  135. end
  136. end
  137. return setmetatable(out, mt)
  138. end
  139.  
  140. local function generateNonce(size)
  141. local n = {}
  142. for i = 1, size do n[i] = math.random(0, 0xFF) end
  143. return setmetatable(n, mt)
  144. end
  145.  
  146. local function encrypt(key,ptext)
  147. local nonce = generateNonce(12)
  148. return {nonce, crypt(ptext, key, nonce)}
  149. end
  150.  
  151. local function decrypt(key,data)
  152. return tostring(crypt(data[2], key, data[1]))
  153. end
  154. return {['generateNonce'] = generateNonce,['encrypt'] = encrypt,['decrypt'] = decrypt}
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement