• API
• FAQ
• Tools
• Archive
SHARE
TWEET  # ChaCha20-Lua Anavrins   Dec 24th, 2015 (edited) 393 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
1. -- Chacha20 cipher in ComputerCraft
2. -- By Anavrins
3. -- For help and details, you can PM me on the CC forums
4. -- You may use this code in your projects without asking me, as long as credit is given and this header is kept intact
5. -- http://www.computercraft.info/forums2/index.php?/user/12870-anavrins
6. -- http://pastebin.com/GPzf9JSa
7. -- Last update: June 30, 2019
8.
9. local mod32 = 2^32
10. local bor = bit32.bor
11. local bxor = bit32.bxor
12. local band = bit32.band
13. local blshift = bit32.lshift
14. local brshift = bit32.arshift
15.
16. local tau = {("expand 16-byte k"):byte(1,-1)}
17. local sigma = {("expand 32-byte k"):byte(1,-1)}
18. local null32 = {("A"):rep(32):byte(1,-1)}
19. local null12 = {("A"):rep(12):byte(1,-1)}
20.
21. local function rotl(n, b)
22.     local s = n/(2^(32-b))
23.     local f = s%1
24.     return (s-f) + f*mod32
25. end
26.
27. local function quarterRound(s, a, b, c, d)
28.     s[a] = (s[a]+s[b])%mod32; s[d] = rotl(bxor(s[d], s[a]), 16)
29.     s[c] = (s[c]+s[d])%mod32; s[b] = rotl(bxor(s[b], s[c]), 12)
30.     s[a] = (s[a]+s[b])%mod32; s[d] = rotl(bxor(s[d], s[a]), 8)
31.     s[c] = (s[c]+s[d])%mod32; s[b] = rotl(bxor(s[b], s[c]), 7)
32.     return s
33. end
34.
35. local function hashBlock(state, rnd)
36.     local s = {unpack(state)}
37.     for i = 1, rnd do
38.         local r = i%2==1
39.         s = r and quarterRound(s, 1, 5,  9, 13) or quarterRound(s, 1, 6, 11, 16)
40.         s = r and quarterRound(s, 2, 6, 10, 14) or quarterRound(s, 2, 7, 12, 13)
41.         s = r and quarterRound(s, 3, 7, 11, 15) or quarterRound(s, 3, 8,  9, 14)
42.         s = r and quarterRound(s, 4, 8, 12, 16) or quarterRound(s, 4, 5, 10, 15)
43.     end
44.     for i = 1, 16 do s[i] = (s[i]+state[i])%mod32 end
45.     return s
46. end
47.
48. local function LE_toInt(bs, i)
49.     return (bs[i+1] or 0)+
50.     blshift((bs[i+2] or 0), 8)+
51.     blshift((bs[i+3] or 0), 16)+
52.     blshift((bs[i+4] or 0), 24)
53. end
54.
55. local function initState(key, nonce, counter)
56.     local isKey256 = #key == 32
57.     local const = isKey256 and sigma or tau
58.     local state = {}
59.
60.     state[ 1] = LE_toInt(const, 0)
61.     state[ 2] = LE_toInt(const, 4)
62.     state[ 3] = LE_toInt(const, 8)
63.     state[ 4] = LE_toInt(const, 12)
64.
65.     state[ 5] = LE_toInt(key, 0)
66.     state[ 6] = LE_toInt(key, 4)
67.     state[ 7] = LE_toInt(key, 8)
68.     state[ 8] = LE_toInt(key, 12)
69.     state[ 9] = LE_toInt(key, isKey256 and 16 or 0)
70.     state = LE_toInt(key, isKey256 and 20 or 4)
71.     state = LE_toInt(key, isKey256 and 24 or 8)
72.     state = LE_toInt(key, isKey256 and 28 or 12)
73.
74.     state = counter
75.     state = LE_toInt(nonce, 0)
76.     state = LE_toInt(nonce, 4)
77.     state = LE_toInt(nonce, 8)
78.
79.     return state
80. end
81.
82. local function serialize(state)
83.     local r = {}
84.     for i = 1, 16 do
85.         r[#r+1] = band(state[i], 0xFF)
86.         r[#r+1] = band(brshift(state[i], 8), 0xFF)
87.         r[#r+1] = band(brshift(state[i], 16), 0xFF)
88.         r[#r+1] = band(brshift(state[i], 24), 0xFF)
89.     end
90.     return r
91. end
92.
93. local mt = {
94.     __tostring = function(a) return string.char(unpack(a)) end,
95.     __index = {
96.         toHex = function(self) return ("%02x"):rep(#self):format(unpack(self)) end,
97.         isEqual = function(self, t)
98.             if type(t) ~= "table" then return false end
99.             if #self ~= #t then return false end
100.             local ret = 0
101.             for i = 1, #self do
102.                 ret = bor(ret, bxor(self[i], t[i]))
103.             end
104.             return ret == 0
105.         end
106.     }
107. }
108.
109. local function crypt(data, key, nonce, cntr, round)
110.     assert(type(key) == "table", "ChaCha20: Invalid key format ("..type(key).."), must be table")
111.     assert(type(nonce) == "table", "ChaCha20: Invalid nonce format ("..type(nonce).."), must be table")
112.     assert(#key == 16 or #key == 32, "ChaCha20: Invalid key length ("..#key.."), must be 16 or 32")
113.     assert(#nonce == 12, "ChaCha20: Invalid nonce length ("..#nonce.."), must be 12")
114.
115.     local data = type(data) == "table" and {unpack(data)} or {tostring(data):byte(1,-1)}
116.     cntr = tonumber(cntr) or 1
117.     round = tonumber(round) or 20
118.
119.     local out = {}
120.     local state = initState(key, nonce, cntr)
121.     local blockAmt = math.floor(#data/64)
122.     for i = 0, blockAmt do
123.         local ks = serialize(hashBlock(state, round))
124.         state = (state+1) % mod32
125.
126.         local block = {}
127.         for j = 1, 64 do
128.             block[j] = data[((i)*64)+j]
129.         end
130.         for j = 1, #block do
131.             out[#out+1] = bxor(block[j], ks[j])
132.         end
133.
134.         if i % 1000 == 0 then
135.             os.queueEvent("")
136.             os.pullEvent("")
137.         end
138.     end
139.     return setmetatable(out, mt)
140. end
141.
142. local function genNonce(len)
143.     local nonce = {}
144.     for i = 1, len do
145.         nonce[i] = math.random(0, 0xFF)
146.     end
147.     return setmetatable(nonce, mt)
148. end
149.
150. local obj = {}
151. local mtrng = {['__index'] = obj}
152. local function newRNG(seed)
153.   local objVars = {}
154.   objVars.seed = seed
155.   objVars.cnt = 0
156.   objVars.block = {}
157.   return setmetatable(objVars, mtrng)
158. end
159.
160. -- Specify how many bytes to return
161. -- 1 Byte is 8 bits, returns int between 0 and 255
162. -- 2 Bytes is 16 bits, returns int up to 65535
163. -- 4 Bytes is 32 bits, returns int up to 4294967295
164. -- Max of 6 Bytes is 48 bits, returns int up to 281474976710655
165. function obj:nextInt(byte)
166.   if not byte or byte < 1 or byte > 6 then error("Can only return 1-6 bytes", 2) end
167.   local output = 0
168.   for i = 0, byte-1 do
169.     if #self.block == 0 then
170.       self.cnt = self.cnt + 1
171.       self.block = crypt(null32, self.seed, null12, self.cnt)
172.     end
173.     local newByte = table.remove(self.block)
174.     output = output + (newByte * (2^(8*i)))
175.   end
176.   return output
177. end
178.
179. return {
180.     crypt = crypt,
181.     genNonce = genNonce,
182.     newRNG = newRNG
183. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy.

Top