├── LICENSE ├── README.md ├── cryptoNet.lua ├── door.png └── doorExample.md /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 SiliconSloth 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CryptoNet 2 | 3 | CryptoNet is a secure and simple-to-use encrypted networking framework 4 | and login system for ComputerCraft computers. Here's an example: 5 | 6 | ##### Client: 7 | ```lua 8 | local cryptoNet = require("cryptoNet") 9 | -- cryptoNet.setLoggingEnabled(false) 10 | 11 | -- Runs when the event loop starts 12 | function onStart() 13 | -- Connect to the server 14 | local socket = cryptoNet.connect("DemoServer") 15 | -- Send an encrypted message 16 | cryptoNet.send(socket, "Hello server!") 17 | end 18 | 19 | -- Runs every time an event occurs 20 | function onEvent(event) 21 | -- Received a message from the server 22 | if event[1] == "encrypted_message" then 23 | print("Server said: "..event[2]) 24 | end 25 | end 26 | 27 | -- Let CryptoNet handle messages in the background 28 | cryptoNet.startEventLoop(onStart, onEvent) 29 | ``` 30 | 31 | ##### Server: 32 | ```lua 33 | local cryptoNet = require("cryptoNet") 34 | -- cryptoNet.setLoggingEnabled(false) 35 | 36 | -- Runs when the event loop starts 37 | function onStart() 38 | -- Start the server 39 | cryptoNet.host("DemoServer") 40 | end 41 | 42 | -- Runs every time an event occurs 43 | function onEvent(event) 44 | -- When a client opens a connection 45 | if event[1] == "connection_opened" then 46 | -- The socket used to send messages to the client 47 | local socket = event[2] 48 | -- Send some encypted messages back to the client 49 | cryptoNet.send(socket, "Welcome to the server!") 50 | cryptoNet.send(socket, "Please wait while I show off CryptoNet...") 51 | -- Each call to onEvent is run in a different thread, so you can use 52 | -- blocking calls like sleep() and pullEvent() without freezing the whole server 53 | os.sleep(5) 54 | cryptoNet.send(socket, "Done!") 55 | -- Received a message from the client 56 | elseif event[1] == "encrypted_message" then 57 | print("Client says: "..event[2]) 58 | -- Even works with non-CryptoNet events! 59 | elseif event[1] == "redstone" then 60 | print("Something redstoney happened!") 61 | end 62 | end 63 | 64 | -- Let CryptoNet handle messages in the background 65 | cryptoNet.startEventLoop(onStart, onEvent) 66 | ``` 67 | 68 | ### Login System 69 | 70 | Here's how you use the login system: 71 | 72 | ##### Client: 73 | ```lua 74 | local cryptoNet = require("cryptoNet") 75 | -- cryptoNet.setLoggingEnabled(false) 76 | 77 | function onStart() 78 | -- Connect to the server 79 | local socket = cryptoNet.connect("LoginDemoServer") 80 | -- Log in with a username and password 81 | cryptoNet.login(socket, "Bobby", "mypass123") 82 | end 83 | 84 | function onEvent(event) 85 | -- Logged in successfully 86 | if event[1] == "login" then 87 | -- The username logged in 88 | local username = event[2] 89 | -- The socket that was logged in 90 | local socket = event[3] 91 | print("Logged in as "..username) 92 | cryptoNet.send(socket, "Hello server!") 93 | -- Login failed (wrong username or password) 94 | elseif event[1] == "login_failed" then 95 | print("Didn't manage to log in. :(") 96 | elseif event[1] == "encrypted_message" then 97 | print("Server said: "..event[2]) 98 | end 99 | end 100 | 101 | cryptoNet.startEventLoop(onStart, onEvent) 102 | ``` 103 | 104 | ##### Server: 105 | ```lua 106 | local cryptoNet = require("cryptoNet") 107 | -- cryptoNet.setLoggingEnabled(false) 108 | 109 | function onStart() 110 | -- Start the server 111 | cryptoNet.host("LoginDemoServer") 112 | end 113 | 114 | function onEvent(event) 115 | -- When a client logs in 116 | if event[1] == "login" then 117 | local username = event[2] 118 | -- The socket of the client that just logged in 119 | local socket = event[3] 120 | -- The logged-in username is also stored in the socket 121 | print(socket.username.." just logged in.") 122 | -- Received a message from the client 123 | elseif event[1] == "encrypted_message" then 124 | local socket = event[3] 125 | -- Check the username to see if the client is logged in 126 | if socket.username ~= nil then 127 | print(socket.username.." says: "..event[2]) 128 | else 129 | cryptoNet.send(socket, "Sorry, I only talk to logged in users.") 130 | end 131 | end 132 | end 133 | 134 | cryptoNet.startEventLoop(onStart, onEvent) 135 | ``` 136 | 137 | ##### Adding users to the server: 138 | ```lua 139 | -- This can just be run in the interactive Lua prompt 140 | local cryptoNet = require("cryptoNet") 141 | -- Start the server to add users to 142 | cryptoNet.host("LoginDemoServer") 143 | -- Add a user with a password 144 | cryptoNet.addUser("Bobby", "mypass123") 145 | -- Close the server once we are done with it 146 | cryptoNet.closeAll() 147 | ``` 148 | 149 | CryptoNet hashes passwords before sending them across the network, and before storing them. 150 | This makes CryptoNet's login system much more secure than your average password door! 151 | 152 | For an example of a secure password door made with CryptoNet, see the [door example](doorExample.md). 153 | 154 | **Note: While CryptoNet aims to be much more secure than standard Rednet, 155 | I am not a security expert and cannot guarantee its effectiveness. 156 | Do not use passwords used with other real life services with CryptoNet.** 157 | 158 | ## How CryptoNet works (and why you shouldn't use Rednet) 159 | TL;DR Rednet has no way to prevent attackers from reading your messages, 160 | or pretending to be another user. For more information about how CryptoNet works internally 161 | and why it exists, check out [How CryptoNet Works](https://github.com/SiliconSloth/CryptoNet/wiki/How-CryptoNet-Works). 162 | 163 | ## Documentation 164 | - [Clients and Servers](https://github.com/SiliconSloth/CryptoNet/wiki/Clients-and-Servers) 165 | - [Messages and Events](https://github.com/SiliconSloth/CryptoNet/wiki/Messages-and-Events) 166 | - [Login System](https://github.com/SiliconSloth/CryptoNet/wiki/Login-System) 167 | - [Certificate Signing](https://github.com/SiliconSloth/CryptoNet/wiki/Certificate-Signing) 168 | - [Settings](https://github.com/SiliconSloth/CryptoNet/wiki/Settings) 169 | 170 | ## Acknowledgements 171 | CryptoNet contains several third-party libraries that allow it to function. 172 | Thanks to the creators of all these libraries for making CryptoNet possible! 173 | - [SHA-256, HMAC and PBKDF2 functions in ComputerCraft by Anavrins](https://pastebin.com/6UV4qfNF) 174 | - [Simple RSA Library by 1lann](https://gist.github.com/1lann/6604c8d3d8e5fdad0832) 175 | - [RSA Key Generator by 1lann](https://gist.github.com/1lann/c9d4d2e7c1f825cad36b) 176 | - [Mersenne Twister RNG and ISAAC algorithm by KillaVanilla](http://www.computercraft.info/forums2/index.php?/topic/12163-cryptographically-secure-random-number-generator/) 177 | - [AES implementation by KillaVanilla](http://www.computercraft.info/forums2/index.php?/topic/18930-aes-encryption/) 178 | - [Simple thread API by immibis](http://www.computercraft.info/forums2/index.php?/topic/3479-basic-background-thread-api/) 179 | -------------------------------------------------------------------------------- /cryptoNet.lua: -------------------------------------------------------------------------------- 1 | -- CryptoNet Networking Framework by SiliconSloth 2 | -- Licensed under the MIT license. 3 | -- 4 | -- Copyright (c) 2019 SiliconSloth 5 | -- 6 | -- Permission is hereby granted, free of charge, to any person obtaining a copy 7 | -- of this software and associated documentation files (the "Software"), to deal 8 | -- in the Software without restriction, including without limitation the rights 9 | -- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | -- copies of the Software, and to permit persons to whom the Software is 11 | -- furnished to do so, subject to the following conditions: 12 | -- 13 | -- The above copyright notice and this permission notice shall be included in all 14 | -- copies or substantial portions of the Software. 15 | -- 16 | -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | -- SOFTWARE. 23 | 24 | 25 | -- CryptoNet is a simple and secure framework for encrypted networking 26 | -- between ComputerCraft computers, intended to be used as an alternative to Rednet. 27 | -- For more information, see CryptoNet's GitHub repo at https://github.com/SiliconSloth/CryptoNet 28 | 29 | -- Line numbers: 30 | -- 49 Third Party 31 | -- 54 - SHA-256, HMAC and PBKDF2 functions in ComputerCraft by Anavrins 32 | -- 288 - Simple RSA Library by 1lann 33 | -- 1256 - RSA Key Generator by 1lann 34 | -- 1468 - Mersenne Twister RNG and ISAAC algorithm by KillaVanilla 35 | -- 1725 - AES implementation by KillaVanilla 36 | -- 2692 - Simple thread API by immibis 37 | -- 2772 CryptoNet 38 | -- 2801 - Accessors 39 | -- 2848 - Validity Checks 40 | -- 2953 - Helpers 41 | -- 3277 - Send Functions 42 | -- 3353 - Login System 43 | -- 3905 - Core Networking 44 | -- 4974 - Event Loop 45 | -- 5082 - Certificate Authority 46 | -- 5251 - Module Export 47 | 48 | 49 | ------- THIRD PARTY ------- 50 | -- The following code was written by third parties and modified by me (SiliconSloth) 51 | -- to integrate it into CryptoNet. (I shoved everything into tables.) 52 | 53 | 54 | -- SHA-256, HMAC and PBKDF2 functions in ComputerCraft 55 | -- By Anavrins 56 | -- For help and details, you can PM me on the CC forums 57 | -- You may use this code in your projects without asking me, as long as credit is given and this header is kept intact 58 | -- http://www.computercraft.info/forums2/index.php?/user/12870-anavrins 59 | -- http://pastebin.com/6UV4qfNF 60 | -- Last update: October 10, 2017 61 | 62 | -- Usage 63 | ---- Data format 64 | ------ Almost all arguments passed in these functions can take both a string or a special table containing a byte array. 65 | ------ This byte array format is simply a table containing a list of each character's byte values. 66 | ------ The phrase "hello world" will become {104,101,108,108,111, 32,119,111,114,108,100}. 67 | ------ Any strings can be converted into it with {str:byte(1,-1)}, and back into string with string.char(unpack(arr)) 68 | ------ 69 | ------ The data returned by all functions are also in this byte array format. 70 | ------ They are paired with a metatable containing metamethods like 71 | ------ :toHex() to convert into the traditional hexadecimal representation. 72 | ------ :isEqual(arr) to compare the hash with another byte array "arr" in constant time. 73 | ------ __tostring to convert into a raw string (Might crash window api on old CC versions). 74 | ------ This output can also be fed into my base64 function (TEtna4tX) to get a shorter hash representation. 75 | 76 | ---- digest(data) 77 | ------ The digest function is the core of this API, it simply hashes your data with the SHA256 algorithm, period. 78 | ------ It's the function everybody is familiar with, and most likely what you're looking for. 79 | ------ This function is mainly used for file integrity, however it is not suited for password storage by itself, use PBKDF2 instead. 80 | 81 | ---- hmac(data, key) 82 | ------ The HMAC function is used for message authentication, it's primary use is in networking apis 83 | ------ to authenticate an encrypted message and ensuring that the data was not tempered with. 84 | ------ The key may be a string or a byte array, with a size between 0 and 32 bytes (256-bits), having a key larger than 32 bytes will not increase security. 85 | ------ This function *may* be used for password storage, if you choose to do so, you must pass the password as the key argument, and the salt as the data argument. 86 | 87 | ---- PBKDF2(pass, salt, iter, dklen) 88 | ------ Password-based key derivation function, returns a "dklen" bytes long array for use in various networking protocol to generate secure cryptographic keys. 89 | ------ This is the preferred choice for password storage, it uses individual argument for password and salt, do not concatenate beforehand. 90 | ------ This algorithm is designed to inherently slow down hashing by repeating the process many times to slow down cracking attempts. 91 | ------ You can adjust the number of "iter" to control the speed of the algorithm, higher "iter" means slower hashing, as well as slower to crack. 92 | ------ DO NOT TOUCH "dklen" if you're using it for passwords, simply pass nil or nothing at all (defaults to 32). 93 | ------ Passing a dklen higher than 32 will multiply the number of iterations with no additional security whatsoever. 94 | 95 | sha256 = {} 96 | 97 | sha256.mod32 = 2^32 98 | sha256.band = bit32 and bit32.band or bit.band 99 | sha256.bnot = bit32 and bit32.bnot or bit.bnot 100 | sha256.bxor = bit32 and bit32.bxor or bit.bxor 101 | sha256.blshift = bit32 and bit32.lshift or bit.blshift 102 | sha256.upack = unpack 103 | 104 | sha256.rrotate = function (n, b) 105 | local s = n/(2^b) 106 | local f = s%1 107 | return (s-f) + f*sha256.mod32 108 | end 109 | sha256.brshift = function (int, by) -- Thanks bit32 for bad rshift 110 | local s = int / (2^by) 111 | return s - s%1 112 | end 113 | 114 | sha256.H = { 115 | 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 116 | 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19, 117 | } 118 | 119 | sha256.K = { 120 | 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 121 | 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 122 | 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 123 | 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 124 | 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 125 | 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 126 | 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 127 | 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2, 128 | } 129 | 130 | sha256.counter = function (incr) 131 | local t1, t2 = 0, 0 132 | if 0xFFFFFFFF - t1 < incr then 133 | t2 = t2 + 1 134 | t1 = incr - (0xFFFFFFFF - t1) - 1 135 | else t1 = t1 + incr 136 | end 137 | return t2, t1 138 | end 139 | 140 | sha256.BE_toInt = function (bs, i) 141 | return sha256.blshift((bs[i] or 0), 24) + sha256.blshift((bs[i+1] or 0), 16) + sha256.blshift((bs[i+2] or 0), 8) + (bs[i+3] or 0) 142 | end 143 | 144 | sha256.preprocess = function (data) 145 | local len = #data 146 | local proc = {} 147 | data[#data+1] = 0x80 148 | while #data%64~=56 do data[#data+1] = 0 end 149 | local blocks = math.ceil(#data/64) 150 | for i = 1, blocks do 151 | proc[i] = {} 152 | for j = 1, 16 do 153 | proc[i][j] = sha256.BE_toInt(data, 1+((i-1)*64)+((j-1)*4)) 154 | end 155 | end 156 | proc[blocks][15], proc[blocks][16] = sha256.counter(len*8) 157 | return proc 158 | end 159 | 160 | sha256.digestblock = function (w, C) 161 | for j = 17, 64 do 162 | local v = w[j-15] 163 | local s0 = sha256.bxor(sha256.bxor(sha256.rrotate(w[j-15], 7), sha256.rrotate(w[j-15], 18)), sha256.brshift(w[j-15], 3)) 164 | local s1 = sha256.bxor(sha256.bxor(sha256.rrotate(w[j-2], 17), sha256.rrotate(w[j-2], 19)), sha256.brshift(w[j-2], 10)) 165 | w[j] = (w[j-16] + s0 + w[j-7] + s1)%sha256.mod32 166 | end 167 | local a, b, c, d, e, f, g, h = sha256.upack(C) 168 | for j = 1, 64 do 169 | local S1 = sha256.bxor(sha256.bxor(sha256.rrotate(e, 6), sha256.rrotate(e, 11)), sha256.rrotate(e, 25)) 170 | local ch = sha256.bxor(sha256.band(e, f), sha256.band(sha256.bnot(e), g)) 171 | local temp1 = (h + S1 + ch + sha256.K[j] + w[j])%sha256.mod32 172 | local S0 = sha256.bxor(sha256.bxor(sha256.rrotate(a, 2), sha256.rrotate(a, 13)), sha256.rrotate(a, 22)) 173 | local maj = sha256.bxor(sha256.bxor(sha256.band(a, b), sha256.band(a, c)), sha256.band(b, c)) 174 | local temp2 = (S0 + maj)%sha256.mod32 175 | h, g, f, e, d, c, b, a = g, f, e, (d+temp1)%sha256.mod32, c, b, a, (temp1+temp2)%sha256.mod32 176 | end 177 | C[1] = (C[1] + a)%sha256.mod32 178 | C[2] = (C[2] + b)%sha256.mod32 179 | C[3] = (C[3] + c)%sha256.mod32 180 | C[4] = (C[4] + d)%sha256.mod32 181 | C[5] = (C[5] + e)%sha256.mod32 182 | C[6] = (C[6] + f)%sha256.mod32 183 | C[7] = (C[7] + g)%sha256.mod32 184 | C[8] = (C[8] + h)%sha256.mod32 185 | return C 186 | end 187 | 188 | sha256.mt = { 189 | __tostring = function(a) return string.char(unpack(a)) end, 190 | __index = { 191 | toHex = function(self, s) return ("%02x"):rep(#self):format(unpack(self)) end, 192 | isEqual = function(self, t) 193 | if type(t) ~= "table" then return false end 194 | if #self ~= #t then return false end 195 | local ret = 0 196 | for i = 1, #self do 197 | ret = bit32.bor(ret, sha256.bxor(self[i], t[i])) 198 | end 199 | return ret == 0 200 | end 201 | } 202 | } 203 | 204 | sha256.toBytes = function (t, n) 205 | local b = {} 206 | for i = 1, n do 207 | b[(i-1)*4+1] = sha256.band(sha256.brshift(t[i], 24), 0xFF) 208 | b[(i-1)*4+2] = sha256.band(sha256.brshift(t[i], 16), 0xFF) 209 | b[(i-1)*4+3] = sha256.band(sha256.brshift(t[i], 8), 0xFF) 210 | b[(i-1)*4+4] = sha256.band(t[i], 0xFF) 211 | end 212 | return setmetatable(b, sha256.mt) 213 | end 214 | 215 | sha256.digest = function (data) 216 | data = data or "" 217 | data = type(data) == "string" and {data:byte(1,-1)} or data 218 | 219 | data = sha256.preprocess(data) 220 | local C = {sha256.upack(sha256.H)} 221 | for i = 1, #data do C = sha256.digestblock(data[i], C) end 222 | return sha256.toBytes(C, 8) 223 | end 224 | 225 | sha256.hmac = function (data, key) 226 | local data = type(data) == "table" and {sha256.upack(data)} or {tostring(data):byte(1,-1)} 227 | local key = type(key) == "table" and {sha256.upack(key)} or {tostring(key):byte(1,-1)} 228 | 229 | local blocksize = 64 230 | 231 | key = #key > blocksize and sha256.digest(key) or key 232 | 233 | local ipad = {} 234 | local opad = {} 235 | local padded_key = {} 236 | 237 | for i = 1, blocksize do 238 | ipad[i] = sha256.bxor(0x36, key[i] or 0) 239 | opad[i] = sha256.bxor(0x5C, key[i] or 0) 240 | end 241 | 242 | for i = 1, #data do 243 | ipad[blocksize+i] = data[i] 244 | end 245 | 246 | ipad = sha256.digest(ipad) 247 | 248 | for i = 1, blocksize do 249 | padded_key[i] = opad[i] 250 | padded_key[blocksize+i] = ipad[i] 251 | end 252 | 253 | return sha256.digest(padded_key) 254 | end 255 | 256 | sha256.pbkdf2 = function (pass, salt, iter, dklen) 257 | local salt = type(salt) == "table" and salt or {tostring(salt):byte(1,-1)} 258 | local hashlen = 32 259 | local dklen = dklen or 32 260 | local block = 1 261 | local out = {} 262 | 263 | while dklen > 0 do 264 | local ikey = {} 265 | local isalt = {sha256.upack(salt)} 266 | local clen = dklen > hashlen and hashlen or dklen 267 | 268 | isalt[#isalt+1] = sha256.band(sha256.brshift(block, 24), 0xFF) 269 | isalt[#isalt+1] = sha256.band(sha256.brshift(block, 16), 0xFF) 270 | isalt[#isalt+1] = sha256.band(sha256.brshift(block, 8), 0xFF) 271 | isalt[#isalt+1] = sha256.band(block, 0xFF) 272 | 273 | for j = 1, iter do 274 | isalt = sha256.hmac(isalt, pass) 275 | for k = 1, clen do ikey[k] = sha256.bxor(isalt[k], ikey[k] or 0) end 276 | if j % 200 == 0 then os.queueEvent("PBKDF2", j) coroutine.yield("PBKDF2") end 277 | end 278 | dklen = dklen - clen 279 | block = block+1 280 | for k = 1, clen do out[#out+1] = ikey[k] end 281 | end 282 | 283 | return setmetatable(out, sha256.mt) 284 | end 285 | 286 | 287 | -- 288 | -- Licenses for Simple RSA Library by 1lann 289 | -- 290 | -- This RSA library should not be used for real-life purposes. 291 | -- It is here to demonstrate a pure Lua implementation of RSA 292 | -- for educational purposes. This RSA library is in no way 293 | -- secure and does not endorse use of this library for any 294 | -- actual security purposes. 295 | -- 296 | -- Copyright (c) 2015 Jason Chu (1lann) 297 | -- 298 | -- Permission to use, copy, modify, and distribute this software for any 299 | -- purpose with or without fee is hereby granted, provided that the above 300 | -- copyright notice and this permission notice appear in all copies. 301 | -- 302 | -- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 303 | -- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 304 | -- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 305 | -- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 306 | -- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 307 | -- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 308 | -- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 309 | -- 310 | 311 | -- 312 | -- Big Integer Library, copyright as follows. 313 | -- 314 | -- Copyright (c) 2010 Ted Unangst 315 | -- 316 | -- Permission to use, copy, modify, and distribute this software for any 317 | -- purpose with or without fee is hereby granted, provided that the above 318 | -- copyright notice and this permission notice appear in all copies. 319 | -- 320 | -- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 321 | -- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 322 | -- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 323 | -- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 324 | -- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 325 | -- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 326 | -- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 327 | -- 328 | 329 | -- 330 | -- Lua version ported/copied from the C version of the Big Integer Library, copyright as follows. 331 | -- 332 | -- Copyright (c) 2000 by Jef Poskanzer . 333 | -- All rights reserved. 334 | -- 335 | -- Redistribution and use in source and binary forms, with or without 336 | -- modification, are permitted provided that the following conditions 337 | -- are met: 338 | -- 1. Redistributions of source code must retain the above copyright 339 | -- notice, this list of conditions and the following disclaimer. 340 | -- 2. Redistributions in binary form must reproduce the above copyright 341 | -- notice, this list of conditions and the following disclaimer in the 342 | -- documentation and/or other materials provided with the distribution. 343 | -- 344 | -- THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 345 | -- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 346 | -- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 347 | -- ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 348 | -- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 349 | -- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 350 | -- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 351 | -- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 352 | -- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 353 | -- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 354 | -- SUCH DAMAGE. 355 | -- 356 | 357 | 358 | -- 359 | -- RSA Encryption/Decryption Library 360 | -- By 1lann 361 | -- 362 | -- Refer to license: http://pastebin.com/9gWSyqQt 363 | -- 364 | 365 | rsaCrypt = {} 366 | 367 | -- 368 | -- Start of third-party libraries/helpers 369 | -- 370 | 371 | -- two functions to help make Lua act more like C 372 | rsaCrypt.fl = function (x) 373 | if x < 0 then 374 | return math.ceil(x) + 0 -- make -0 go away 375 | else 376 | return math.floor(x) 377 | end 378 | end 379 | 380 | rsaCrypt.cmod = function (a, b) 381 | local x = a % b 382 | if a < 0 and x > 0 then 383 | x = x - b 384 | end 385 | return x 386 | end 387 | 388 | 389 | rsaCrypt.radix = 2^24 -- maybe up to 2^26 is safe? 390 | rsaCrypt.radix_sqrt = rsaCrypt.fl(math.sqrt(rsaCrypt.radix)) 391 | 392 | rsaCrypt.alloc = function () 393 | local bi = {} 394 | setmetatable(bi, rsaCrypt.bigintmt) 395 | bi.comps = {} 396 | bi.sign = 1; 397 | return bi 398 | end 399 | 400 | rsaCrypt.clone = function (a) 401 | local bi = rsaCrypt.alloc() 402 | bi.sign = a.sign 403 | local c = bi.comps 404 | local ac = a.comps 405 | for i = 1, #ac do 406 | c[i] = ac[i] 407 | end 408 | return bi 409 | end 410 | 411 | rsaCrypt.normalize = function (bi, notrunc) 412 | local c = bi.comps 413 | local v 414 | -- borrow for negative components 415 | for i = 1, #c - 1 do 416 | v = c[i] 417 | if v < 0 then 418 | c[i+1] = c[i+1] + rsaCrypt.fl(v / rsaCrypt.radix) - 1 419 | v = rsaCrypt.cmod(v, rsaCrypt.radix) 420 | if v ~= 0 then 421 | c[i] = v + rsaCrypt.radix 422 | else 423 | c[i] = v 424 | c[i+1] = c[i+1] + 1 425 | end 426 | end 427 | end 428 | -- is top component negative? 429 | if c[#c] < 0 then 430 | -- switch the sign and fix components 431 | bi.sign = -bi.sign 432 | for i = 1, #c - 1 do 433 | v = c[i] 434 | c[i] = rsaCrypt.radix - v 435 | c[i+1] = c[i+1] + 1 436 | end 437 | c[#c] = -c[#c] 438 | end 439 | -- carry for components larger than radix 440 | for i = 1, #c do 441 | v = c[i] 442 | if v > rsaCrypt.radix then 443 | c[i+1] = (c[i+1] or 0) + rsaCrypt.fl(v / rsaCrypt.radix) 444 | c[i] = rsaCrypt.cmod(v, rsaCrypt.radix) 445 | end 446 | end 447 | -- trim off leading zeros 448 | if not notrunc then 449 | for i = #c, 2, -1 do 450 | if c[i] == 0 then 451 | c[i] = nil 452 | else 453 | break 454 | end 455 | end 456 | end 457 | -- check for -0 458 | if #c == 1 and c[1] == 0 and bi.sign == -1 then 459 | bi.sign = 1 460 | end 461 | end 462 | 463 | rsaCrypt.negate = function (a) 464 | local bi = rsaCrypt.clone(a) 465 | bi.sign = -bi.sign 466 | return bi 467 | end 468 | 469 | rsaCrypt.compare = function (a, b) 470 | local ac, bc = a.comps, b.comps 471 | local as, bs = a.sign, b.sign 472 | if ac == bc then 473 | return 0 474 | elseif as > bs then 475 | return 1 476 | elseif as < bs then 477 | return -1 478 | elseif #ac > #bc then 479 | return as 480 | elseif #ac < #bc then 481 | return -as 482 | end 483 | for i = #ac, 1, -1 do 484 | if ac[i] > bc[i] then 485 | return as 486 | elseif ac[i] < bc[i] then 487 | return -as 488 | end 489 | end 490 | return 0 491 | end 492 | 493 | rsaCrypt.lt = function (a, b) 494 | return rsaCrypt.compare(a, b) < 0 495 | end 496 | 497 | rsaCrypt.eq = function (a, b) 498 | return rsaCrypt.compare(a, b) == 0 499 | end 500 | 501 | rsaCrypt.le = function (a, b) 502 | return rsaCrypt.compare(a, b) <= 0 503 | end 504 | 505 | rsaCrypt.addint = function (a, n) 506 | local bi = rsaCrypt.clone(a) 507 | if bi.sign == 1 then 508 | bi.comps[1] = bi.comps[1] + n 509 | else 510 | bi.comps[1] = bi.comps[1] - n 511 | end 512 | rsaCrypt.normalize(bi) 513 | return bi 514 | end 515 | 516 | rsaCrypt.add = function (a, b) 517 | if type(a) == "number" then 518 | return rsaCrypt.addint(b, a) 519 | elseif type(b) == "number" then 520 | return rsaCrypt.addint(a, b) 521 | end 522 | local bi = rsaCrypt.clone(a) 523 | local sign = bi.sign == b.sign 524 | local c = bi.comps 525 | for i = #c + 1, #b.comps do 526 | c[i] = 0 527 | end 528 | local bc = b.comps 529 | for i = 1, #bc do 530 | local v = bc[i] 531 | if sign then 532 | c[i] = c[i] + v 533 | else 534 | c[i] = c[i] - v 535 | end 536 | end 537 | rsaCrypt.normalize(bi) 538 | return bi 539 | end 540 | 541 | rsaCrypt.sub = function (a, b) 542 | if type(b) == "number" then 543 | return rsaCrypt.addint(a, -b) 544 | elseif type(a) == "number" then 545 | a = rsaCrypt.bigint(a) 546 | end 547 | return rsaCrypt.add(a, rsaCrypt.negate(b)) 548 | end 549 | 550 | rsaCrypt.mulint = function (a, b) 551 | local bi = rsaCrypt.clone(a) 552 | if b < 0 then 553 | b = -b 554 | bi.sign = -bi.sign 555 | end 556 | local bc = bi.comps 557 | for i = 1, #bc do 558 | bc[i] = bc[i] * b 559 | end 560 | rsaCrypt.normalize(bi) 561 | return bi 562 | end 563 | 564 | rsaCrypt.multiply = function (a, b) 565 | local bi = rsaCrypt.alloc() 566 | local c = bi.comps 567 | local ac, bc = a.comps, b.comps 568 | for i = 1, #ac + #bc do 569 | c[i] = 0 570 | end 571 | for i = 1, #ac do 572 | for j = 1, #bc do 573 | c[i+j-1] = c[i+j-1] + ac[i] * bc[j] 574 | end 575 | -- keep the zeroes 576 | rsaCrypt.normalize(bi, true) 577 | end 578 | rsaCrypt.normalize(bi) 579 | if bi ~= rsaCrypt.bigint(0) then 580 | bi.sign = a.sign * b.sign 581 | end 582 | return bi 583 | end 584 | 585 | rsaCrypt.kmul = function (a, b) 586 | local ac, bc = a.comps, b.comps 587 | local an, bn = #a.comps, #b.comps 588 | local bi, bj, bk, bl = rsaCrypt.alloc(), rsaCrypt.alloc(), rsaCrypt.alloc(), rsaCrypt.alloc() 589 | local ic, jc, kc, lc = bi.comps, bj.comps, bk.comps, bl.comps 590 | 591 | local n = rsaCrypt.fl((math.max(an, bn) + 1) / 2) 592 | for i = 1, n do 593 | ic[i] = (i + n <= an) and ac[i+n] or 0 594 | jc[i] = (i <= an) and ac[i] or 0 595 | kc[i] = (i + n <= bn) and bc[i+n] or 0 596 | lc[i] = (i <= bn) and bc[i] or 0 597 | end 598 | rsaCrypt.normalize(bi) 599 | rsaCrypt.normalize(bj) 600 | rsaCrypt.normalize(bk) 601 | rsaCrypt.normalize(bl) 602 | local ik = bi * bk 603 | local jl = bj * bl 604 | local mid = (bi + bj) * (bk + bl) - ik - jl 605 | local mc = mid.comps 606 | local ikc = ik.comps 607 | local jlc = jl.comps 608 | for i = 1, #ikc + n*2 do -- fill it up 609 | jlc[i] = jlc[i] or 0 610 | end 611 | for i = 1, #mc do 612 | jlc[i+n] = jlc[i+n] + mc[i] 613 | end 614 | for i = 1, #ikc do 615 | jlc[i+n*2] = jlc[i+n*2] + ikc[i] 616 | end 617 | jl.sign = a.sign * b.sign 618 | rsaCrypt.normalize(jl) 619 | return jl 620 | end 621 | 622 | rsaCrypt.kthresh = 12 623 | 624 | rsaCrypt.mul = function (a, b) 625 | if type(a) == "number" then 626 | return rsaCrypt.mulint(b, a) 627 | elseif type(b) == "number" then 628 | return rsaCrypt.mulint(a, b) 629 | end 630 | if #a.comps < rsaCrypt.kthresh or #b.comps < rsaCrypt.kthresh then 631 | return rsaCrypt.multiply(a, b) 632 | end 633 | return rsaCrypt.kmul(a, b) 634 | end 635 | 636 | rsaCrypt.divint = function (numer, denom) 637 | local bi = rsaCrypt.clone(numer) 638 | if denom < 0 then 639 | denom = -denom 640 | bi.sign = -bi.sign 641 | end 642 | local r = 0 643 | local c = bi.comps 644 | for i = #c, 1, -1 do 645 | r = r * rsaCrypt.radix + c[i] 646 | c[i] = rsaCrypt.fl(r / denom) 647 | r = rsaCrypt.cmod(r, denom) 648 | end 649 | rsaCrypt.normalize(bi) 650 | return bi 651 | end 652 | 653 | rsaCrypt.multi_divide = function (numer, denom) 654 | local n = #denom.comps 655 | local approx = rsaCrypt.divint(numer, denom.comps[n]) 656 | for i = n, #approx.comps do 657 | approx.comps[i - n + 1] = approx.comps[i] 658 | end 659 | for i = #approx.comps, #approx.comps - n + 2, -1 do 660 | approx.comps[i] = nil 661 | end 662 | local rem = approx * denom - numer 663 | if rem < denom then 664 | quotient = approx 665 | else 666 | quotient = approx - rsaCrypt.multi_divide(rem, denom) 667 | end 668 | return quotient 669 | end 670 | 671 | rsaCrypt.multi_divide_wrap = function (numer, denom) 672 | -- we use a successive approximation method, but it doesn't work 673 | -- if the high order component is too small. adjust if needed. 674 | if denom.comps[#denom.comps] < rsaCrypt.radix_sqrt then 675 | numer = rsaCrypt.mulint(numer, rsaCrypt.radix_sqrt) 676 | denom = rsaCrypt.mulint(denom, rsaCrypt.radix_sqrt) 677 | end 678 | return rsaCrypt.multi_divide(numer, denom) 679 | end 680 | 681 | rsaCrypt.div = function (numer, denom) 682 | if type(denom) == "number" then 683 | if denom == 0 then 684 | error("divide by 0", 2) 685 | end 686 | return rsaCrypt.divint(numer, denom) 687 | elseif type(numer) == "number" then 688 | numer = rsaCrypt.bigint(numer) 689 | end 690 | -- check signs and trivial cases 691 | local sign = 1 692 | local cmp = rsaCrypt.compare(denom, rsaCrypt.bigint(0)) 693 | if cmp == 0 then 694 | error("divide by 0", 2) 695 | elseif cmp == -1 then 696 | sign = -sign 697 | denom = rsaCrypt.negate(denom) 698 | end 699 | cmp = rsaCrypt.compare(numer, rsaCrypt.bigint(0)) 700 | if cmp == 0 then 701 | return rsaCrypt.bigint(0) 702 | elseif cmp == -1 then 703 | sign = -sign 704 | numer = rsaCrypt.negate(numer) 705 | end 706 | cmp = rsaCrypt.compare(numer, denom) 707 | if cmp == -1 then 708 | return rsaCrypt.bigint(0) 709 | elseif cmp == 0 then 710 | return rsaCrypt.bigint(sign) 711 | end 712 | local bi 713 | -- if small enough, do it the easy way 714 | if #denom.comps == 1 then 715 | bi = rsaCrypt.divint(numer, denom.comps[1]) 716 | else 717 | bi = rsaCrypt.multi_divide_wrap(numer, denom) 718 | end 719 | if sign == -1 then 720 | bi = rsaCrypt.negate(bi) 721 | end 722 | return bi 723 | end 724 | 725 | rsaCrypt.intrem = function (bi, m) 726 | if m < 0 then 727 | m = -m 728 | end 729 | local rad_r = 1 730 | local r = 0 731 | local bc = bi.comps 732 | for i = 1, #bc do 733 | local v = bc[i] 734 | r = rsaCrypt.cmod(r + v * rad_r, m) 735 | rad_r = rsaCrypt.cmod(rad_r * rsaCrypt.radix, m) 736 | end 737 | if bi.sign < 1 then 738 | r = -r 739 | end 740 | return r 741 | end 742 | 743 | rsaCrypt.intmod = function (bi, m) 744 | local r = rsaCrypt.intrem(bi, m) 745 | if r < 0 then 746 | r = r + m 747 | end 748 | return r 749 | end 750 | 751 | rsaCrypt.rem = function (bi, m) 752 | if type(m) == "number" then 753 | return rsaCrypt.bigint(rsaCrypt.intrem(bi, m)) 754 | elseif type(bi) == "number" then 755 | bi = rsaCrypt.bigint(bi) 756 | end 757 | 758 | return bi - ((bi / m) * m) 759 | end 760 | 761 | rsaCrypt.mod = function (a, m) 762 | local bi = rsaCrypt.rem(a, m) 763 | if bi.sign == -1 then 764 | bi = bi + m 765 | end 766 | return bi 767 | end 768 | 769 | rsaCrypt.printscale = 10000000 770 | rsaCrypt.printscalefmt = string.format("%%.%dd", math.log10(rsaCrypt.printscale)) 771 | rsaCrypt.makestr = function (bi, s) 772 | if bi >= rsaCrypt.bigint(rsaCrypt.printscale) then 773 | rsaCrypt.makestr(rsaCrypt.divint(bi, rsaCrypt.printscale), s) 774 | end 775 | table.insert(s, string.format(rsaCrypt.printscalefmt, rsaCrypt.intmod(bi, rsaCrypt.printscale))) 776 | end 777 | 778 | rsaCrypt.biginttostring = function (bi) 779 | local s = {} 780 | if bi < rsaCrypt.bigint(0) then 781 | bi = rsaCrypt.negate(bi) 782 | table.insert(s, "-") 783 | end 784 | rsaCrypt.makestr(bi, s) 785 | s = table.concat(s):gsub("^0*", "") 786 | if s == "" then s = "0" end 787 | return s 788 | end 789 | 790 | rsaCrypt.biginttonumber = function (bi) 791 | return tonumber(rsaCrypt.biginttostring(bi)) 792 | end 793 | 794 | rsaCrypt.bigintmt = { 795 | __add = rsaCrypt.add, 796 | __sub = rsaCrypt.sub, 797 | __mul = rsaCrypt.mul, 798 | __div = rsaCrypt.div, 799 | __mod = rsaCrypt.mod, 800 | __unm = rsaCrypt.negate, 801 | __eq = rsaCrypt.eq, 802 | __lt = rsaCrypt.lt, 803 | __le = rsaCrypt.le, 804 | __tostring = rsaCrypt.biginttostring, 805 | } 806 | 807 | rsaCrypt.cache = {} 808 | rsaCrypt.ncache = 0 809 | 810 | rsaCrypt.bigint = function (n) 811 | if rsaCrypt.cache[n] then 812 | return rsaCrypt.cache[n] 813 | end 814 | local bi 815 | if type(n) == "string" then 816 | local digits = { n:byte(1, -1) } 817 | for i = 1, #digits do 818 | digits[i] = string.char(digits[i]) 819 | end 820 | local start = 1 821 | local sign = 1 822 | if digits[i] == '-' then 823 | sign = -1 824 | start = 2 825 | end 826 | bi = rsaCrypt.bigint(0) 827 | for i = start, #digits do 828 | bi = rsaCrypt.addint(rsaCrypt.mulint(bi, 10), tonumber(digits[i])) 829 | end 830 | bi = rsaCrypt.mulint(bi, sign) 831 | else 832 | bi = rsaCrypt.alloc() 833 | bi.comps[1] = n 834 | rsaCrypt.normalize(bi) 835 | end 836 | if rsaCrypt.ncache > 100 then 837 | rsaCrypt.cache = {} 838 | rsaCrypt.ncache = 0 839 | end 840 | rsaCrypt.cache[n] = bi 841 | rsaCrypt.ncache = rsaCrypt.ncache + 1 842 | return bi 843 | end 844 | 845 | -- 846 | -- Start of my code 847 | -- 848 | 849 | rsaCrypt.powersTwo = { 850 | rsaCrypt.bigint("2"), 851 | rsaCrypt.bigint("4"), 852 | rsaCrypt.bigint("8"), 853 | rsaCrypt.bigint("16"), 854 | rsaCrypt.bigint("32"), 855 | rsaCrypt.bigint("64"), 856 | rsaCrypt.bigint("128"), 857 | rsaCrypt.bigint("256"), 858 | rsaCrypt.bigint("512"), 859 | rsaCrypt.bigint("1024"), 860 | rsaCrypt.bigint("2048"), 861 | rsaCrypt.bigint("4096"), 862 | rsaCrypt.bigint("8192"), 863 | rsaCrypt.bigint("16384"), 864 | rsaCrypt.bigint("32768"), 865 | rsaCrypt.bigint("65536"), 866 | rsaCrypt.bigint("131072"), 867 | rsaCrypt.bigint("262144"), 868 | rsaCrypt.bigint("524288"), 869 | rsaCrypt.bigint("1048576"), 870 | rsaCrypt.bigint("2097152"), 871 | rsaCrypt.bigint("4194304"), 872 | rsaCrypt.bigint("8388608"), 873 | rsaCrypt.bigint("16777216"), 874 | rsaCrypt.bigint("33554432"), 875 | rsaCrypt.bigint("67108864"), 876 | rsaCrypt.bigint("134217728"), 877 | rsaCrypt.bigint("268435456"), 878 | rsaCrypt.bigint("536870912"), 879 | rsaCrypt.bigint("1073741824"), 880 | rsaCrypt.bigint("2147483648"), 881 | rsaCrypt.bigint("4294967296"), 882 | rsaCrypt.bigint("8589934592"), 883 | rsaCrypt.bigint("17179869184"), 884 | rsaCrypt.bigint("34359738368"), 885 | rsaCrypt.bigint("68719476736"), 886 | rsaCrypt.bigint("137438953472"), 887 | rsaCrypt.bigint("274877906944"), 888 | rsaCrypt.bigint("549755813888"), 889 | rsaCrypt.bigint("1099511627776"), 890 | rsaCrypt.bigint("2199023255552"), 891 | rsaCrypt.bigint("4398046511104"), 892 | rsaCrypt.bigint("8796093022208"), 893 | rsaCrypt.bigint("17592186044416"), 894 | rsaCrypt.bigint("35184372088832"), 895 | rsaCrypt.bigint("70368744177664"), 896 | rsaCrypt.bigint("140737488355328"), 897 | rsaCrypt.bigint("281474976710656"), 898 | rsaCrypt.bigint("562949953421312"), 899 | rsaCrypt.bigint("1125899906842624"), 900 | rsaCrypt.bigint("2251799813685248"), 901 | rsaCrypt.bigint("4503599627370496"), 902 | rsaCrypt.bigint("9007199254740992"), 903 | rsaCrypt.bigint("18014398509481984"), 904 | rsaCrypt.bigint("36028797018963968"), 905 | rsaCrypt.bigint("72057594037927936"), 906 | rsaCrypt.bigint("144115188075855872"), 907 | rsaCrypt.bigint("288230376151711744"), 908 | rsaCrypt.bigint("576460752303423488"), 909 | rsaCrypt.bigint("1152921504606846976"), 910 | rsaCrypt.bigint("2305843009213693952"), 911 | rsaCrypt.bigint("4611686018427387904"), 912 | rsaCrypt.bigint("9223372036854775808"), 913 | rsaCrypt.bigint("18446744073709551616"), 914 | rsaCrypt.bigint("36893488147419103232"), 915 | rsaCrypt.bigint("73786976294838206464"), 916 | rsaCrypt.bigint("147573952589676412928"), 917 | rsaCrypt.bigint("295147905179352825856"), 918 | rsaCrypt.bigint("590295810358705651712"), 919 | rsaCrypt.bigint("1180591620717411303424"), 920 | rsaCrypt.bigint("2361183241434822606848"), 921 | rsaCrypt.bigint("4722366482869645213696"), 922 | rsaCrypt.bigint("9444732965739290427392"), 923 | rsaCrypt.bigint("18889465931478580854784"), 924 | rsaCrypt.bigint("37778931862957161709568"), 925 | rsaCrypt.bigint("75557863725914323419136"), 926 | rsaCrypt.bigint("151115727451828646838272"), 927 | rsaCrypt.bigint("302231454903657293676544"), 928 | rsaCrypt.bigint("604462909807314587353088"), 929 | rsaCrypt.bigint("1208925819614629174706176"), 930 | rsaCrypt.bigint("2417851639229258349412352"), 931 | rsaCrypt.bigint("4835703278458516698824704"), 932 | rsaCrypt.bigint("9671406556917033397649408"), 933 | rsaCrypt.bigint("19342813113834066795298816"), 934 | rsaCrypt.bigint("38685626227668133590597632"), 935 | rsaCrypt.bigint("77371252455336267181195264"), 936 | rsaCrypt.bigint("154742504910672534362390528"), 937 | rsaCrypt.bigint("309485009821345068724781056"), 938 | rsaCrypt.bigint("618970019642690137449562112"), 939 | rsaCrypt.bigint("1237940039285380274899124224"), 940 | rsaCrypt.bigint("2475880078570760549798248448"), 941 | rsaCrypt.bigint("4951760157141521099596496896"), 942 | rsaCrypt.bigint("9903520314283042199192993792"), 943 | rsaCrypt.bigint("19807040628566084398385987584"), 944 | rsaCrypt.bigint("39614081257132168796771975168"), 945 | rsaCrypt.bigint("79228162514264337593543950336"), 946 | rsaCrypt.bigint("158456325028528675187087900672"), 947 | rsaCrypt.bigint("316912650057057350374175801344"), 948 | rsaCrypt.bigint("633825300114114700748351602688"), 949 | rsaCrypt.bigint("1267650600228229401496703205376"), 950 | rsaCrypt.bigint("2535301200456458802993406410752"), 951 | rsaCrypt.bigint("5070602400912917605986812821504"), 952 | rsaCrypt.bigint("10141204801825835211973625643008"), 953 | rsaCrypt.bigint("20282409603651670423947251286016"), 954 | rsaCrypt.bigint("40564819207303340847894502572032"), 955 | rsaCrypt.bigint("81129638414606681695789005144064"), 956 | rsaCrypt.bigint("162259276829213363391578010288128"), 957 | rsaCrypt.bigint("324518553658426726783156020576256"), 958 | rsaCrypt.bigint("649037107316853453566312041152512"), 959 | rsaCrypt.bigint("1298074214633706907132624082305024"), 960 | rsaCrypt.bigint("2596148429267413814265248164610048"), 961 | rsaCrypt.bigint("5192296858534827628530496329220096"), 962 | rsaCrypt.bigint("10384593717069655257060992658440192"), 963 | rsaCrypt.bigint("20769187434139310514121985316880384"), 964 | rsaCrypt.bigint("41538374868278621028243970633760768"), 965 | rsaCrypt.bigint("83076749736557242056487941267521536"), 966 | rsaCrypt.bigint("166153499473114484112975882535043072"), 967 | rsaCrypt.bigint("332306998946228968225951765070086144"), 968 | rsaCrypt.bigint("664613997892457936451903530140172288"), 969 | rsaCrypt.bigint("1329227995784915872903807060280344576"), 970 | rsaCrypt.bigint("2658455991569831745807614120560689152"), 971 | rsaCrypt.bigint("5316911983139663491615228241121378304"), 972 | rsaCrypt.bigint("10633823966279326983230456482242756608"), 973 | rsaCrypt.bigint("21267647932558653966460912964485513216"), 974 | rsaCrypt.bigint("42535295865117307932921825928971026432"), 975 | rsaCrypt.bigint("85070591730234615865843651857942052864"), 976 | rsaCrypt.bigint("170141183460469231731687303715884105728"), 977 | rsaCrypt.bigint("340282366920938463463374607431768211456"), 978 | rsaCrypt.bigint("680564733841876926926749214863536422912"), 979 | rsaCrypt.bigint("1361129467683753853853498429727072845824"), 980 | rsaCrypt.bigint("2722258935367507707706996859454145691648"), 981 | rsaCrypt.bigint("5444517870735015415413993718908291383296"), 982 | rsaCrypt.bigint("10889035741470030830827987437816582766592"), 983 | rsaCrypt.bigint("21778071482940061661655974875633165533184"), 984 | rsaCrypt.bigint("43556142965880123323311949751266331066368"), 985 | rsaCrypt.bigint("87112285931760246646623899502532662132736"), 986 | rsaCrypt.bigint("174224571863520493293247799005065324265472"), 987 | rsaCrypt.bigint("348449143727040986586495598010130648530944"), 988 | rsaCrypt.bigint("696898287454081973172991196020261297061888"), 989 | rsaCrypt.bigint("1393796574908163946345982392040522594123776"), 990 | rsaCrypt.bigint("2787593149816327892691964784081045188247552"), 991 | rsaCrypt.bigint("5575186299632655785383929568162090376495104"), 992 | rsaCrypt.bigint("11150372599265311570767859136324180752990208"), 993 | rsaCrypt.bigint("22300745198530623141535718272648361505980416"), 994 | rsaCrypt.bigint("44601490397061246283071436545296723011960832"), 995 | rsaCrypt.bigint("89202980794122492566142873090593446023921664"), 996 | rsaCrypt.bigint("178405961588244985132285746181186892047843328"), 997 | rsaCrypt.bigint("356811923176489970264571492362373784095686656"), 998 | rsaCrypt.bigint("713623846352979940529142984724747568191373312"), 999 | rsaCrypt.bigint("1427247692705959881058285969449495136382746624"), 1000 | rsaCrypt.bigint("2854495385411919762116571938898990272765493248"), 1001 | rsaCrypt.bigint("5708990770823839524233143877797980545530986496"), 1002 | rsaCrypt.bigint("11417981541647679048466287755595961091061972992"), 1003 | rsaCrypt.bigint("22835963083295358096932575511191922182123945984"), 1004 | rsaCrypt.bigint("45671926166590716193865151022383844364247891968"), 1005 | rsaCrypt.bigint("91343852333181432387730302044767688728495783936"), 1006 | rsaCrypt.bigint("182687704666362864775460604089535377456991567872"), 1007 | rsaCrypt.bigint("365375409332725729550921208179070754913983135744"), 1008 | rsaCrypt.bigint("730750818665451459101842416358141509827966271488"), 1009 | rsaCrypt.bigint("1461501637330902918203684832716283019655932542976"), 1010 | rsaCrypt.bigint("2923003274661805836407369665432566039311865085952"), 1011 | rsaCrypt.bigint("5846006549323611672814739330865132078623730171904"), 1012 | rsaCrypt.bigint("11692013098647223345629478661730264157247460343808"), 1013 | rsaCrypt.bigint("23384026197294446691258957323460528314494920687616"), 1014 | rsaCrypt.bigint("46768052394588893382517914646921056628989841375232"), 1015 | rsaCrypt.bigint("93536104789177786765035829293842113257979682750464"), 1016 | rsaCrypt.bigint("187072209578355573530071658587684226515959365500928"), 1017 | rsaCrypt.bigint("374144419156711147060143317175368453031918731001856"), 1018 | rsaCrypt.bigint("748288838313422294120286634350736906063837462003712"), 1019 | rsaCrypt.bigint("1496577676626844588240573268701473812127674924007424"), 1020 | rsaCrypt.bigint("2993155353253689176481146537402947624255349848014848"), 1021 | rsaCrypt.bigint("5986310706507378352962293074805895248510699696029696"), 1022 | rsaCrypt.bigint("11972621413014756705924586149611790497021399392059392"), 1023 | rsaCrypt.bigint("23945242826029513411849172299223580994042798784118784"), 1024 | rsaCrypt.bigint("47890485652059026823698344598447161988085597568237568"), 1025 | rsaCrypt.bigint("95780971304118053647396689196894323976171195136475136"), 1026 | rsaCrypt.bigint("191561942608236107294793378393788647952342390272950272"), 1027 | rsaCrypt.bigint("383123885216472214589586756787577295904684780545900544"), 1028 | rsaCrypt.bigint("766247770432944429179173513575154591809369561091801088"), 1029 | rsaCrypt.bigint("1532495540865888858358347027150309183618739122183602176"), 1030 | rsaCrypt.bigint("3064991081731777716716694054300618367237478244367204352"), 1031 | rsaCrypt.bigint("6129982163463555433433388108601236734474956488734408704"), 1032 | rsaCrypt.bigint("12259964326927110866866776217202473468949912977468817408"), 1033 | rsaCrypt.bigint("24519928653854221733733552434404946937899825954937634816"), 1034 | rsaCrypt.bigint("49039857307708443467467104868809893875799651909875269632"), 1035 | rsaCrypt.bigint("98079714615416886934934209737619787751599303819750539264"), 1036 | rsaCrypt.bigint("196159429230833773869868419475239575503198607639501078528"), 1037 | rsaCrypt.bigint("392318858461667547739736838950479151006397215279002157056"), 1038 | rsaCrypt.bigint("784637716923335095479473677900958302012794430558004314112"), 1039 | rsaCrypt.bigint("1569275433846670190958947355801916604025588861116008628224"), 1040 | rsaCrypt.bigint("3138550867693340381917894711603833208051177722232017256448"), 1041 | rsaCrypt.bigint("6277101735386680763835789423207666416102355444464034512896"), 1042 | rsaCrypt.bigint("12554203470773361527671578846415332832204710888928069025792"), 1043 | rsaCrypt.bigint("25108406941546723055343157692830665664409421777856138051584"), 1044 | rsaCrypt.bigint("50216813883093446110686315385661331328818843555712276103168"), 1045 | rsaCrypt.bigint("100433627766186892221372630771322662657637687111424552206336"), 1046 | rsaCrypt.bigint("200867255532373784442745261542645325315275374222849104412672"), 1047 | rsaCrypt.bigint("401734511064747568885490523085290650630550748445698208825344"), 1048 | rsaCrypt.bigint("803469022129495137770981046170581301261101496891396417650688"), 1049 | rsaCrypt.bigint("1606938044258990275541962092341162602522202993782792835301376"), 1050 | rsaCrypt.bigint("3213876088517980551083924184682325205044405987565585670602752"), 1051 | rsaCrypt.bigint("6427752177035961102167848369364650410088811975131171341205504"), 1052 | rsaCrypt.bigint("12855504354071922204335696738729300820177623950262342682411008"), 1053 | rsaCrypt.bigint("25711008708143844408671393477458601640355247900524685364822016"), 1054 | rsaCrypt.bigint("51422017416287688817342786954917203280710495801049370729644032"), 1055 | rsaCrypt.bigint("102844034832575377634685573909834406561420991602098741459288064"), 1056 | rsaCrypt.bigint("205688069665150755269371147819668813122841983204197482918576128"), 1057 | rsaCrypt.bigint("411376139330301510538742295639337626245683966408394965837152256"), 1058 | rsaCrypt.bigint("822752278660603021077484591278675252491367932816789931674304512"), 1059 | rsaCrypt.bigint("1645504557321206042154969182557350504982735865633579863348609024"), 1060 | rsaCrypt.bigint("3291009114642412084309938365114701009965471731267159726697218048"), 1061 | rsaCrypt.bigint("6582018229284824168619876730229402019930943462534319453394436096"), 1062 | rsaCrypt.bigint("13164036458569648337239753460458804039861886925068638906788872192"), 1063 | rsaCrypt.bigint("26328072917139296674479506920917608079723773850137277813577744384"), 1064 | rsaCrypt.bigint("52656145834278593348959013841835216159447547700274555627155488768"), 1065 | rsaCrypt.bigint("105312291668557186697918027683670432318895095400549111254310977536"), 1066 | rsaCrypt.bigint("210624583337114373395836055367340864637790190801098222508621955072"), 1067 | rsaCrypt.bigint("421249166674228746791672110734681729275580381602196445017243910144"), 1068 | rsaCrypt.bigint("842498333348457493583344221469363458551160763204392890034487820288"), 1069 | rsaCrypt.bigint("1684996666696914987166688442938726917102321526408785780068975640576"), 1070 | rsaCrypt.bigint("3369993333393829974333376885877453834204643052817571560137951281152"), 1071 | rsaCrypt.bigint("6739986666787659948666753771754907668409286105635143120275902562304"), 1072 | rsaCrypt.bigint("13479973333575319897333507543509815336818572211270286240551805124608"), 1073 | rsaCrypt.bigint("26959946667150639794667015087019630673637144422540572481103610249216"), 1074 | rsaCrypt.bigint("53919893334301279589334030174039261347274288845081144962207220498432"), 1075 | rsaCrypt.bigint("107839786668602559178668060348078522694548577690162289924414440996864"), 1076 | rsaCrypt.bigint("215679573337205118357336120696157045389097155380324579848828881993728"), 1077 | rsaCrypt.bigint("431359146674410236714672241392314090778194310760649159697657763987456"), 1078 | rsaCrypt.bigint("862718293348820473429344482784628181556388621521298319395315527974912"), 1079 | rsaCrypt.bigint("1725436586697640946858688965569256363112777243042596638790631055949824"), 1080 | rsaCrypt.bigint("3450873173395281893717377931138512726225554486085193277581262111899648"), 1081 | rsaCrypt.bigint("6901746346790563787434755862277025452451108972170386555162524223799296"), 1082 | rsaCrypt.bigint("13803492693581127574869511724554050904902217944340773110325048447598592"), 1083 | rsaCrypt.bigint("27606985387162255149739023449108101809804435888681546220650096895197184"), 1084 | rsaCrypt.bigint("55213970774324510299478046898216203619608871777363092441300193790394368"), 1085 | rsaCrypt.bigint("110427941548649020598956093796432407239217743554726184882600387580788736"), 1086 | rsaCrypt.bigint("220855883097298041197912187592864814478435487109452369765200775161577472"), 1087 | rsaCrypt.bigint("441711766194596082395824375185729628956870974218904739530401550323154944"), 1088 | rsaCrypt.bigint("883423532389192164791648750371459257913741948437809479060803100646309888"), 1089 | rsaCrypt.bigint("1766847064778384329583297500742918515827483896875618958121606201292619776"), 1090 | rsaCrypt.bigint("3533694129556768659166595001485837031654967793751237916243212402585239552"), 1091 | rsaCrypt.bigint("7067388259113537318333190002971674063309935587502475832486424805170479104"), 1092 | rsaCrypt.bigint("14134776518227074636666380005943348126619871175004951664972849610340958208"), 1093 | rsaCrypt.bigint("28269553036454149273332760011886696253239742350009903329945699220681916416"), 1094 | rsaCrypt.bigint("56539106072908298546665520023773392506479484700019806659891398441363832832"), 1095 | rsaCrypt.bigint("113078212145816597093331040047546785012958969400039613319782796882727665664"), 1096 | rsaCrypt.bigint("226156424291633194186662080095093570025917938800079226639565593765455331328"), 1097 | rsaCrypt.bigint("452312848583266388373324160190187140051835877600158453279131187530910662656"), 1098 | rsaCrypt.bigint("904625697166532776746648320380374280103671755200316906558262375061821325312"), 1099 | rsaCrypt.bigint("1809251394333065553493296640760748560207343510400633813116524750123642650624"), 1100 | rsaCrypt.bigint("3618502788666131106986593281521497120414687020801267626233049500247285301248"), 1101 | rsaCrypt.bigint("7237005577332262213973186563042994240829374041602535252466099000494570602496"), 1102 | rsaCrypt.bigint("14474011154664524427946373126085988481658748083205070504932198000989141204992"), 1103 | rsaCrypt.bigint("28948022309329048855892746252171976963317496166410141009864396001978282409984"), 1104 | rsaCrypt.bigint("57896044618658097711785492504343953926634992332820282019728792003956564819968"), 1105 | rsaCrypt.bigint("115792089237316195423570985008687907853269984665640564039457584007913129639936"), 1106 | } 1107 | 1108 | rsaCrypt.powersTwo[0] = rsaCrypt.bigint("1") 1109 | 1110 | rsaCrypt.bigZero = rsaCrypt.bigint(0) 1111 | rsaCrypt.bigOne = rsaCrypt.bigint(1) 1112 | 1113 | rsaCrypt.numberToBytes = function (num, bits, byteSize) 1114 | if bits > #rsaCrypt.powersTwo then 1115 | error("Too many bits. Must be <= " .. #rsaCrypt.powersTwo .. ".") 1116 | end 1117 | 1118 | num = rsaCrypt.bigint(num) 1119 | 1120 | local resultBits = {} 1121 | resultBits[1] = {} 1122 | for i = bits - 1, 0, -1 do 1123 | local expVal = rsaCrypt.powersTwo[i] 1124 | local resultant = num - expVal 1125 | if expVal <= resultant then 1126 | -- Invalid data! 1127 | return nil 1128 | end 1129 | 1130 | if resultant < rsaCrypt.bigZero then 1131 | -- A zero bit 1132 | if #(resultBits[#resultBits]) >= byteSize then 1133 | table.insert(resultBits, {0}) 1134 | else 1135 | table.insert(resultBits[#resultBits], 0) 1136 | end 1137 | else 1138 | -- A one bit 1139 | num = resultant 1140 | if #(resultBits[#resultBits]) >= byteSize then 1141 | table.insert(resultBits, {1}) 1142 | else 1143 | table.insert(resultBits[#resultBits], 1) 1144 | end 1145 | end 1146 | 1147 | if num == rsaCrypt.bigint(0) then 1148 | break 1149 | end 1150 | end 1151 | 1152 | local results = {} 1153 | for _, binarySeq in pairs(resultBits) do 1154 | local thisResult = 0 1155 | for k, bin in pairs(binarySeq) do 1156 | if bin == 1 then 1157 | thisResult = thisResult + 2^(byteSize - k) 1158 | end 1159 | end 1160 | table.insert(results, thisResult) 1161 | end 1162 | 1163 | return results 1164 | end 1165 | 1166 | rsaCrypt.bytesToNumber = function (bytes, bits, byteSize) 1167 | if bits > #rsaCrypt.powersTwo then 1168 | error("Too many bits. Must be <= " .. #rsaCrypt.powersTwo .. ".") 1169 | end 1170 | 1171 | if #bytes > bits/byteSize then 1172 | error("Too many bytes to store into the number of bits available. Must be <= " .. 1173 | bits/byteSize .. ".") 1174 | end 1175 | 1176 | local binary = {} 1177 | for _, byte in pairs(bytes) do 1178 | for i = byteSize - 1, 0, -1 do 1179 | if byte - (2 ^ i) < 0 then 1180 | table.insert(binary, 0) 1181 | else 1182 | table.insert(binary, 1) 1183 | byte = byte - (2 ^ i) 1184 | end 1185 | end 1186 | end 1187 | 1188 | local num = rsaCrypt.bigint(0) 1189 | for i = 1, #binary do 1190 | if binary[i] == 1 then 1191 | num = num + rsaCrypt.powersTwo[bits - i] 1192 | end 1193 | end 1194 | 1195 | return tostring(num) 1196 | end 1197 | 1198 | rsaCrypt.encodeBigNumbers = function (numbers) 1199 | for k, v in pairs(numbers) do 1200 | numbers[k] = tostring(v) 1201 | end 1202 | return numbers 1203 | end 1204 | 1205 | rsaCrypt.stringToBytes = function (str) 1206 | local result = {} 1207 | for i = 1, #str do 1208 | table.insert(result, string.byte(str, i)) 1209 | end 1210 | return result 1211 | end 1212 | 1213 | rsaCrypt.bytesToString = function (bytes) 1214 | local str = "" 1215 | for _, v in pairs(bytes) do 1216 | str = str .. string.char(v) 1217 | end 1218 | return str 1219 | end 1220 | 1221 | rsaCrypt.modexp = function (base, exponent, modulus) 1222 | local r = 1 1223 | 1224 | while true do 1225 | if exponent % 2 == rsaCrypt.bigOne then 1226 | r = r * base % modulus 1227 | end 1228 | exponent = exponent / 2 1229 | 1230 | if exponent == rsaCrypt.bigZero then 1231 | break 1232 | end 1233 | base = base * base % modulus 1234 | end 1235 | 1236 | return r 1237 | end 1238 | 1239 | rsaCrypt.crypt = function (key, number) 1240 | local exp 1241 | if key.public then 1242 | exp = rsaCrypt.bigint(key.public) 1243 | else 1244 | exp = rsaCrypt.bigint(key.private) 1245 | end 1246 | 1247 | return tostring(rsaCrypt.modexp(rsaCrypt.bigint(number), exp, rsaCrypt.bigint(key.shared))) 1248 | end 1249 | 1250 | -- 1251 | -- END OF LIBRARY 1252 | -- 1253 | 1254 | 1255 | -- 1256 | -- RSA Key Generator 1257 | -- By 1lann 1258 | -- 1259 | -- Refer to license: http://pastebin.com/9gWSyqQt 1260 | -- 1261 | 1262 | rsaKeygen = {} 1263 | 1264 | -- 1265 | -- Start of my (1lann's) code 1266 | -- 1267 | 1268 | rsaKeygen.bigZero = rsaCrypt.bigint(0) 1269 | rsaKeygen.bigOne = rsaCrypt.bigint(1) 1270 | 1271 | rsaKeygen.gcd = function (a, b) 1272 | if b ~= rsaKeygen.bigZero then 1273 | return rsaKeygen.gcd(b, a % b) 1274 | else 1275 | return a 1276 | end 1277 | end 1278 | 1279 | rsaKeygen.modexp = function (base, exponent, modulus) 1280 | local r = 1 1281 | 1282 | while true do 1283 | if exponent % 2 == rsaKeygen.bigOne then 1284 | r = r * base % modulus 1285 | end 1286 | exponent = exponent / 2 1287 | 1288 | if exponent == rsaKeygen.bigZero then 1289 | break 1290 | end 1291 | base = base * base % modulus 1292 | end 1293 | 1294 | return r 1295 | end 1296 | 1297 | rsaKeygen.bigRandomWithLength = function (length, cap) 1298 | if not cap then 1299 | cap = 999999999 1300 | end 1301 | 1302 | local randomString = tostring(math.random(100000000, cap)) 1303 | 1304 | while true do 1305 | randomString = randomString .. 1306 | tostring(math.random(100000000, cap)) 1307 | if #randomString >= length then 1308 | local finalRandom = randomString:sub(1, length) 1309 | if finalRandom:sub(-1, -1) == "2" then 1310 | return rsaCrypt.bigint(finalRandom:sub(1, -2) .. "3") 1311 | elseif finalRandom:sub(-1, -1) == "4" then 1312 | return rsaCrypt.bigint(finalRandom:sub(1, -2) .. "5") 1313 | elseif finalRandom:sub(-1, -1) == "6" then 1314 | return rsaCrypt.bigint(finalRandom:sub(1, -2) .. "7") 1315 | elseif finalRandom:sub(-1, -1) == "8" then 1316 | return rsaCrypt.bigint(finalRandom:sub(1, -2) .. "9") 1317 | elseif finalRandom:sub(-1, -1) == "0" then 1318 | return rsaCrypt.bigint(finalRandom:sub(1, -2) .. "1") 1319 | else 1320 | return rsaCrypt.bigint(finalRandom) 1321 | end 1322 | end 1323 | end 1324 | end 1325 | 1326 | rsaKeygen.bigRandom = function (minNum, maxNum) 1327 | if maxNum < rsaCrypt.bigint(1000000000) then 1328 | return rsaCrypt.bigint(math.random(rsaCrypt.biginttonumber(minNum), 1329 | rsaCrypt.biginttonumber(maxNum))) 1330 | end 1331 | 1332 | local maxString = tostring(maxNum) 1333 | local cap = tonumber(tostring(maxNum):sub(1, 9)) 1334 | local range = #maxString - #tostring(minNum) 1335 | 1336 | if range == 0 then 1337 | return rsaKeygen.bigRandomWithLength(#maxString, cap) 1338 | end 1339 | 1340 | if #maxString > 30 then 1341 | return rsaKeygen.bigRandomWithLength(#maxString - 1) 1342 | end 1343 | 1344 | local randomLength = math.random(1, 2^(#maxString - 1)) 1345 | for i = 1, #maxString - 1 do 1346 | if randomLength <= (2^i) then 1347 | return rsaKeygen.bigRandomWithLength(i) 1348 | end 1349 | end 1350 | end 1351 | 1352 | rsaKeygen.isPrime = function (n) 1353 | if type(n) == "number" then 1354 | n = rsaCrypt.bigint(n) 1355 | end 1356 | 1357 | if n % 2 == rsaKeygen.bigZero then 1358 | return false 1359 | end 1360 | 1361 | local s, d = 0, n - rsaKeygen.bigOne 1362 | while d % 2 == rsaKeygen.bigZero do 1363 | s, d = s + 1, d / 2 1364 | end 1365 | 1366 | for i = 1, 3 do 1367 | local a = rsaKeygen.bigRandom(rsaCrypt.bigint(2), n - 2) 1368 | local x = rsaKeygen.modexp(a, d, n) 1369 | if x ~= rsaKeygen.bigOne and x + 1 ~= n then 1370 | for j = 1, s do 1371 | x = rsaKeygen.modexp(x, rsaCrypt.bigint(2), n) 1372 | if x == rsaKeygen.bigOne then 1373 | return false 1374 | elseif x == n - 1 then 1375 | a = rsaKeygen.bigZero 1376 | break 1377 | end 1378 | end 1379 | if a ~= rsaKeygen.bigZero then 1380 | return false 1381 | end 1382 | end 1383 | end 1384 | 1385 | return true 1386 | end 1387 | 1388 | rsaKeygen.generateLargePrime = function () 1389 | local i = 0 1390 | while true do 1391 | write(".") 1392 | os.sleep(0.1) 1393 | local randomNumber = rsaKeygen.bigRandomWithLength(39) 1394 | 1395 | if rsaKeygen.isPrime(randomNumber) then 1396 | return randomNumber 1397 | end 1398 | end 1399 | end 1400 | 1401 | rsaKeygen.generatePQ = function (e) 1402 | local randomPrime 1403 | while true do 1404 | randomPrime = rsaKeygen.generateLargePrime() 1405 | if rsaKeygen.gcd(e, randomPrime - 1) == rsaKeygen.bigOne then 1406 | return randomPrime 1407 | end 1408 | end 1409 | end 1410 | 1411 | rsaKeygen.euclidean = function (a, b) 1412 | local x, y, u, v = rsaKeygen.bigZero, rsaKeygen.bigOne, rsaKeygen.bigOne, rsaKeygen.bigZero 1413 | while a ~= rsaKeygen.bigZero do 1414 | local q, r = b / a, b % a 1415 | local m, n = x - u * q, y - v * q 1416 | b, a, x, y, u, v = a, r, u, v, m, n 1417 | end 1418 | return b, x, y 1419 | end 1420 | 1421 | rsaKeygen.modinv = function (a, m) 1422 | local gcdnum, x, y = rsaKeygen.euclidean(a, m) 1423 | if gcdnum ~= rsaKeygen.bigOne then 1424 | return nil 1425 | else 1426 | return x % m 1427 | end 1428 | end 1429 | 1430 | rsaKeygen.generateKeyPair = function () 1431 | while true do 1432 | local e = rsaKeygen.generateLargePrime() 1433 | write("-") 1434 | sleep(0.1) 1435 | local p = rsaKeygen.generatePQ(e) 1436 | write("-") 1437 | sleep(0.1) 1438 | local q = rsaKeygen.generatePQ(e) 1439 | write("-") 1440 | sleep(0.1) 1441 | 1442 | local n = p * q 1443 | local phi = (p - 1) * (q - 1) 1444 | local d = rsaKeygen.modinv(e, phi) 1445 | 1446 | -- 104328 is just a magic number (can be any semi-unique number) 1447 | local encrypted = rsaKeygen.modexp(rsaCrypt.bigint(104328), e, n) 1448 | local decrypted = rsaKeygen.modexp(encrypted, d, n) 1449 | 1450 | write("+") 1451 | sleep(0.1) 1452 | counter = 0 1453 | 1454 | if decrypted == rsaCrypt.bigint(104328) then 1455 | counter = 0 1456 | return { 1457 | shared = tostring(n), 1458 | public = tostring(e), 1459 | }, { 1460 | shared = tostring(n), 1461 | private = tostring(d), 1462 | } 1463 | end 1464 | end 1465 | end 1466 | 1467 | 1468 | -- KillaVanilla's RNG('s), composed of the Mersenne Twister RNG and the ISAAC algorithm. 1469 | 1470 | -- Exposed functions: 1471 | -- initalize_mt_generator(seed) - Seed the Mersenne Twister RNG. 1472 | -- extract_mt() - Get a number from the Mersenne Twister RNG. 1473 | -- seed_from_mt(seed) - Seed the ISAAC RNG, optionally seeding the Mersenne Twister RNG beforehand. 1474 | -- generate_isaac() - Force a reseed. 1475 | -- random(min, max) - Get a random number between min and max. 1476 | 1477 | isaac = {} 1478 | 1479 | -- Helper functions: 1480 | isaac.toBinary = function (a) -- Convert from an integer to an arbitrary-length table of bits 1481 | local b = {} 1482 | local copy = a 1483 | while true do 1484 | table.insert(b, copy % 2) 1485 | copy = math.floor(copy / 2) 1486 | if copy == 0 then 1487 | break 1488 | end 1489 | end 1490 | return b 1491 | end 1492 | 1493 | isaac.fromBinary = function (a) -- Convert from an arbitrary-length table of bits (from toBinary) to an integer 1494 | local dec = 0 1495 | for i=#a, 1, -1 do 1496 | dec = dec * 2 + a[i] 1497 | end 1498 | return dec 1499 | end 1500 | 1501 | -- ISAAC internal state: 1502 | isaac.aa = 0 1503 | isaac.bb = 0 1504 | isaac.cc = 0 1505 | isaac.randrsl = {} -- Acts as entropy/seed-in. Fill to randrsl[256]. 1506 | isaac.mm = {} -- Fill to mm[256]. Acts as output. 1507 | 1508 | -- Mersenne Twister State: 1509 | isaac.MT = {} -- Twister state 1510 | isaac.index = 0 1511 | 1512 | -- Other variables for the seeding mechanism 1513 | isaac.mtSeeded = false 1514 | isaac.mtSeed = math.random(1, 2^31-1) 1515 | 1516 | -- The Mersenne Twister can be used as an RNG for non-cryptographic purposes. 1517 | -- Here, we're using it to seed the ISAAC algorithm, which *can* be used for cryptographic purposes. 1518 | 1519 | isaac.initalize_mt_generator = function (seed) 1520 | isaac.index = 0 1521 | isaac.MT[0] = seed 1522 | for i=1, 623 do 1523 | local full = ( (1812433253 * bit.bxor(isaac.MT[i-1], bit.brshift(isaac.MT[i-1], 30) ) )+i) 1524 | local b = isaac.toBinary(full) 1525 | while #b > 32 do 1526 | table.remove(b, 1) 1527 | end 1528 | isaac.MT[i] = isaac.fromBinary(b) 1529 | end 1530 | end 1531 | 1532 | isaac.generate_mt = function () -- Restock the MT with new random numbers. 1533 | for i=0, 623 do 1534 | local y = bit.band(isaac.MT[i], 0x80000000) 1535 | y = y + bit.band(isaac.MT[(i+1)%624], 0x7FFFFFFF) 1536 | isaac.MT[i] = bit.bxor(isaac.MT[(i+397)%624], bit.brshift(y, 1)) 1537 | if y % 2 == 1 then 1538 | isaac.MT[i] = bit.bxor(isaac.MT[i], 0x9908B0DF) 1539 | end 1540 | end 1541 | end 1542 | 1543 | isaac.extract_mt = function (min, max) -- Get one number from the Mersenne Twister. 1544 | if isaac.index == 0 then 1545 | isaac.generate_mt() 1546 | end 1547 | local y = isaac.MT[isaac.index] 1548 | min = min or 0 1549 | max = max or 2^32-1 1550 | --print("Accessing: isaac.MT["..isaac.index.."]...") 1551 | y = bit.bxor(y, bit.brshift(y, 11) ) 1552 | y = bit.bxor(y, bit.band(bit.blshift(y, 7), 0x9D2C5680) ) 1553 | y = bit.bxor(y, bit.band(bit.blshift(y, 15), 0xEFC60000) ) 1554 | y = bit.bxor(y, bit.brshift(y, 18) ) 1555 | isaac.index = (isaac.index+1) % 624 1556 | return (y % max)+min 1557 | end 1558 | 1559 | isaac.seed_from_mt = function (seed) -- seed ISAAC with numbers from the MT: 1560 | if seed then 1561 | isaac.mtSeeded = false 1562 | isaac.mtSeed = seed 1563 | end 1564 | if not isaac.mtSeeded or (math.random(1, 100) == 50) then -- Always seed the first time around. Otherwise, seed approximately once per 100 times. 1565 | isaac.initalize_mt_generator(isaac.mtSeed) 1566 | isaac.mtSeeded = true 1567 | isaac.mtSeed = isaac.extract_mt() 1568 | end 1569 | for i=1, 256 do 1570 | isaac.randrsl[i] = isaac.extract_mt() 1571 | end 1572 | end 1573 | 1574 | isaac.mix = function (a,b,c,d,e,f,g,h) 1575 | a = a % (2^32-1) 1576 | b = b % (2^32-1) 1577 | c = c % (2^32-1) 1578 | d = d % (2^32-1) 1579 | e = e % (2^32-1) 1580 | f = f % (2^32-1) 1581 | g = g % (2^32-1) 1582 | h = h % (2^32-1) 1583 | a = bit.bxor(a, bit.blshift(b, 11)) 1584 | d = (d + a) % (2^32-1) 1585 | b = (b + c) % (2^32-1) 1586 | b = bit.bxor(b, bit.brshift(c, 2) ) 1587 | e = (e + b) % (2^32-1) 1588 | c = (c + d) % (2^32-1) 1589 | c = bit.bxor(c, bit.blshift(d, 8) ) 1590 | f = (f + c) % (2^32-1) 1591 | d = (d + e) % (2^32-1) 1592 | d = bit.bxor(d, bit.brshift(e, 16) ) 1593 | g = (g + d) % (2^32-1) 1594 | e = (e + f) % (2^32-1) 1595 | e = bit.bxor(e, bit.blshift(f, 10) ) 1596 | h = (h + e) % (2^32-1) 1597 | f = (f + g) % (2^32-1) 1598 | f = bit.bxor(f, bit.brshift(g, 4) ) 1599 | a = (a + f) % (2^32-1) 1600 | g = (g + h) % (2^32-1) 1601 | g = bit.bxor(g, bit.blshift(h, 8) ) 1602 | b = (b + g) % (2^32-1) 1603 | h = (h + a) % (2^32-1) 1604 | h = bit.bxor(h, bit.brshift(a, 9) ) 1605 | c = (c + h) % (2^32-1) 1606 | a = (a + b) % (2^32-1) 1607 | return a,b,c,d,e,f,g,h 1608 | end 1609 | 1610 | isaac.isaac = function () 1611 | local x, y = 0, 0 1612 | for i=1, 256 do 1613 | x = isaac.mm[i] 1614 | if (i % 4) == 0 then 1615 | isaac.aa = bit.bxor(isaac.aa, bit.blshift(isaac.aa, 13)) 1616 | elseif (i % 4) == 1 then 1617 | isaac.aa = bit.bxor(isaac.aa, bit.brshift(isaac.aa, 6)) 1618 | elseif (i % 4) == 2 then 1619 | isaac.aa = bit.bxor(isaac.aa, bit.blshift(isaac.aa, 2)) 1620 | elseif (i % 4) == 3 then 1621 | isaac.aa = bit.bxor(isaac.aa, bit.brshift(isaac.aa, 16)) 1622 | end 1623 | isaac.aa = (isaac.mm[ ((i+128) % 256)+1 ] + isaac.aa) % (2^32-1) 1624 | y = (isaac.mm[ (bit.brshift(x, 2) % 256)+1 ] + isaac.aa + isaac.bb) % (2^32-1) 1625 | isaac.mm[i] = y 1626 | isaac.bb = (isaac.mm[ (bit.brshift(y,10) % 256)+1 ] + x) % (2^32-1) 1627 | isaac.randrsl[i] = isaac.bb 1628 | end 1629 | end 1630 | 1631 | isaac.randinit = function (flag) 1632 | local a,b,c,d,e,f,g,h = 0x9e3779b9,0x9e3779b9,0x9e3779b9,0x9e3779b9,0x9e3779b9,0x9e3779b9,0x9e3779b9,0x9e3779b9-- 0x9e3779b9 is the golden ratio 1633 | isaac.aa = 0 1634 | isaac.bb = 0 1635 | isaac.cc = 0 1636 | for i=1,4 do 1637 | a,b,c,d,e,f,g,h = isaac.mix(a,b,c,d,e,f,g,h) 1638 | end 1639 | for i=1, 256, 8 do 1640 | if flag then 1641 | a = (a + isaac.randrsl[i]) % (2^32-1) 1642 | b = (b + isaac.randrsl[i+1]) % (2^32-1) 1643 | c = (c + isaac.randrsl[i+2]) % (2^32-1) 1644 | d = (b + isaac.randrsl[i+3]) % (2^32-1) 1645 | e = (e + isaac.randrsl[i+4]) % (2^32-1) 1646 | f = (f + isaac.randrsl[i+5]) % (2^32-1) 1647 | g = (g + isaac.randrsl[i+6]) % (2^32-1) 1648 | h = (h + isaac.randrsl[i+7]) % (2^32-1) 1649 | end 1650 | a,b,c,d,e,f,g,h = isaac.mix(a,b,c,d,e,f,g,h) 1651 | isaac.mm[i] = a 1652 | isaac.mm[i+1] = b 1653 | isaac.mm[i+2] = c 1654 | isaac.mm[i+3] = d 1655 | isaac.mm[i+4] = e 1656 | isaac.mm[i+5] = f 1657 | isaac.mm[i+6] = g 1658 | isaac.mm[i+7] = h 1659 | end 1660 | 1661 | if flag then 1662 | for i=1, 256, 8 do 1663 | a = (a + isaac.randrsl[i]) % (2^32-1) 1664 | b = (b + isaac.randrsl[i+1]) % (2^32-1) 1665 | c = (c + isaac.randrsl[i+2]) % (2^32-1) 1666 | d = (b + isaac.randrsl[i+3]) % (2^32-1) 1667 | e = (e + isaac.randrsl[i+4]) % (2^32-1) 1668 | f = (f + isaac.randrsl[i+5]) % (2^32-1) 1669 | g = (g + isaac.randrsl[i+6]) % (2^32-1) 1670 | h = (h + isaac.randrsl[i+7]) % (2^32-1) 1671 | a,b,c,d,e,f,g,h = isaac.mix(a,b,c,d,e,f,g,h) 1672 | isaac.mm[i] = a 1673 | isaac.mm[i+1] = b 1674 | isaac.mm[i+2] = c 1675 | isaac.mm[i+3] = d 1676 | isaac.mm[i+4] = e 1677 | isaac.mm[i+5] = f 1678 | isaac.mm[i+6] = g 1679 | isaac.mm[i+7] = h 1680 | end 1681 | end 1682 | isaac.isaac() 1683 | randcnt = 256 1684 | end 1685 | 1686 | isaac.generate_isaac = function (entropy) 1687 | isaac.aa = 0 1688 | isaac.bb = 0 1689 | isaac.cc = 0 1690 | if entropy and #entropy >= 256 then 1691 | for i=1, 256 do 1692 | isaac.randrsl[i] = entropy[i] 1693 | end 1694 | else 1695 | isaac.seed_from_mt() 1696 | end 1697 | for i=1, 256 do 1698 | isaac.mm[i] = 0 1699 | end 1700 | isaac.randinit(true) 1701 | isaac.isaac() 1702 | isaac.isaac() -- run isaac twice 1703 | end 1704 | 1705 | isaac.getRandom = function () 1706 | if #isaac.mm > 0 then 1707 | return table.remove(isaac.mm, 1) 1708 | else 1709 | isaac.generate_isaac() 1710 | return table.remove(isaac.mm, 1) 1711 | end 1712 | end 1713 | 1714 | isaac.random = function (min, max) 1715 | if not max then 1716 | max = 2^32-1 1717 | end 1718 | if not min then 1719 | min = 0 1720 | end 1721 | return (isaac.getRandom() % max) + min 1722 | end 1723 | 1724 | 1725 | -- AES implementation 1726 | -- By KillaVanilla 1727 | 1728 | aes = {} 1729 | 1730 | aes.sbox = { 1731 | [0]=0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, 1732 | 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, 1733 | 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, 1734 | 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, 1735 | 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, 1736 | 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, 1737 | 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, 1738 | 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, 1739 | 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, 1740 | 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, 1741 | 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, 1742 | 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, 1743 | 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, 1744 | 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, 1745 | 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, 1746 | 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16} 1747 | 1748 | aes.inv_sbox = { 1749 | [0]=0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB, 1750 | 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, 1751 | 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, 1752 | 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25, 1753 | 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, 1754 | 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, 1755 | 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06, 1756 | 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, 1757 | 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, 1758 | 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E, 1759 | 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, 1760 | 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, 1761 | 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F, 1762 | 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, 1763 | 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, 1764 | 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D} 1765 | 1766 | aes.Rcon = { 1767 | [0]=0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 1768 | 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 1769 | 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 1770 | 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 1771 | 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 1772 | 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 1773 | 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 1774 | 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 1775 | 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 1776 | 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 1777 | 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 1778 | 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 1779 | 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 1780 | 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 1781 | 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 1782 | 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d} 1783 | 1784 | -- Finite-field multiplication lookup tables: 1785 | 1786 | aes.mul_2 = { 1787 | [0]=0x00,0x02,0x04,0x06,0x08,0x0a,0x0c,0x0e,0x10,0x12,0x14,0x16,0x18,0x1a,0x1c,0x1e, 1788 | 0x20,0x22,0x24,0x26,0x28,0x2a,0x2c,0x2e,0x30,0x32,0x34,0x36,0x38,0x3a,0x3c,0x3e, 1789 | 0x40,0x42,0x44,0x46,0x48,0x4a,0x4c,0x4e,0x50,0x52,0x54,0x56,0x58,0x5a,0x5c,0x5e, 1790 | 0x60,0x62,0x64,0x66,0x68,0x6a,0x6c,0x6e,0x70,0x72,0x74,0x76,0x78,0x7a,0x7c,0x7e, 1791 | 0x80,0x82,0x84,0x86,0x88,0x8a,0x8c,0x8e,0x90,0x92,0x94,0x96,0x98,0x9a,0x9c,0x9e, 1792 | 0xa0,0xa2,0xa4,0xa6,0xa8,0xaa,0xac,0xae,0xb0,0xb2,0xb4,0xb6,0xb8,0xba,0xbc,0xbe, 1793 | 0xc0,0xc2,0xc4,0xc6,0xc8,0xca,0xcc,0xce,0xd0,0xd2,0xd4,0xd6,0xd8,0xda,0xdc,0xde, 1794 | 0xe0,0xe2,0xe4,0xe6,0xe8,0xea,0xec,0xee,0xf0,0xf2,0xf4,0xf6,0xf8,0xfa,0xfc,0xfe, 1795 | 0x1b,0x19,0x1f,0x1d,0x13,0x11,0x17,0x15,0x0b,0x09,0x0f,0x0d,0x03,0x01,0x07,0x05, 1796 | 0x3b,0x39,0x3f,0x3d,0x33,0x31,0x37,0x35,0x2b,0x29,0x2f,0x2d,0x23,0x21,0x27,0x25, 1797 | 0x5b,0x59,0x5f,0x5d,0x53,0x51,0x57,0x55,0x4b,0x49,0x4f,0x4d,0x43,0x41,0x47,0x45, 1798 | 0x7b,0x79,0x7f,0x7d,0x73,0x71,0x77,0x75,0x6b,0x69,0x6f,0x6d,0x63,0x61,0x67,0x65, 1799 | 0x9b,0x99,0x9f,0x9d,0x93,0x91,0x97,0x95,0x8b,0x89,0x8f,0x8d,0x83,0x81,0x87,0x85, 1800 | 0xbb,0xb9,0xbf,0xbd,0xb3,0xb1,0xb7,0xb5,0xab,0xa9,0xaf,0xad,0xa3,0xa1,0xa7,0xa5, 1801 | 0xdb,0xd9,0xdf,0xdd,0xd3,0xd1,0xd7,0xd5,0xcb,0xc9,0xcf,0xcd,0xc3,0xc1,0xc7,0xc5, 1802 | 0xfb,0xf9,0xff,0xfd,0xf3,0xf1,0xf7,0xf5,0xeb,0xe9,0xef,0xed,0xe3,0xe1,0xe7,0xe5, 1803 | } 1804 | 1805 | aes.mul_3 = { 1806 | [0]=0x00,0x03,0x06,0x05,0x0c,0x0f,0x0a,0x09,0x18,0x1b,0x1e,0x1d,0x14,0x17,0x12,0x11, 1807 | 0x30,0x33,0x36,0x35,0x3c,0x3f,0x3a,0x39,0x28,0x2b,0x2e,0x2d,0x24,0x27,0x22,0x21, 1808 | 0x60,0x63,0x66,0x65,0x6c,0x6f,0x6a,0x69,0x78,0x7b,0x7e,0x7d,0x74,0x77,0x72,0x71, 1809 | 0x50,0x53,0x56,0x55,0x5c,0x5f,0x5a,0x59,0x48,0x4b,0x4e,0x4d,0x44,0x47,0x42,0x41, 1810 | 0xc0,0xc3,0xc6,0xc5,0xcc,0xcf,0xca,0xc9,0xd8,0xdb,0xde,0xdd,0xd4,0xd7,0xd2,0xd1, 1811 | 0xf0,0xf3,0xf6,0xf5,0xfc,0xff,0xfa,0xf9,0xe8,0xeb,0xee,0xed,0xe4,0xe7,0xe2,0xe1, 1812 | 0xa0,0xa3,0xa6,0xa5,0xac,0xaf,0xaa,0xa9,0xb8,0xbb,0xbe,0xbd,0xb4,0xb7,0xb2,0xb1, 1813 | 0x90,0x93,0x96,0x95,0x9c,0x9f,0x9a,0x99,0x88,0x8b,0x8e,0x8d,0x84,0x87,0x82,0x81, 1814 | 0x9b,0x98,0x9d,0x9e,0x97,0x94,0x91,0x92,0x83,0x80,0x85,0x86,0x8f,0x8c,0x89,0x8a, 1815 | 0xab,0xa8,0xad,0xae,0xa7,0xa4,0xa1,0xa2,0xb3,0xb0,0xb5,0xb6,0xbf,0xbc,0xb9,0xba, 1816 | 0xfb,0xf8,0xfd,0xfe,0xf7,0xf4,0xf1,0xf2,0xe3,0xe0,0xe5,0xe6,0xef,0xec,0xe9,0xea, 1817 | 0xcb,0xc8,0xcd,0xce,0xc7,0xc4,0xc1,0xc2,0xd3,0xd0,0xd5,0xd6,0xdf,0xdc,0xd9,0xda, 1818 | 0x5b,0x58,0x5d,0x5e,0x57,0x54,0x51,0x52,0x43,0x40,0x45,0x46,0x4f,0x4c,0x49,0x4a, 1819 | 0x6b,0x68,0x6d,0x6e,0x67,0x64,0x61,0x62,0x73,0x70,0x75,0x76,0x7f,0x7c,0x79,0x7a, 1820 | 0x3b,0x38,0x3d,0x3e,0x37,0x34,0x31,0x32,0x23,0x20,0x25,0x26,0x2f,0x2c,0x29,0x2a, 1821 | 0x0b,0x08,0x0d,0x0e,0x07,0x04,0x01,0x02,0x13,0x10,0x15,0x16,0x1f,0x1c,0x19,0x1a, 1822 | } 1823 | 1824 | aes.mul_9 = { 1825 | [0]=0x00,0x09,0x12,0x1b,0x24,0x2d,0x36,0x3f,0x48,0x41,0x5a,0x53,0x6c,0x65,0x7e,0x77, 1826 | 0x90,0x99,0x82,0x8b,0xb4,0xbd,0xa6,0xaf,0xd8,0xd1,0xca,0xc3,0xfc,0xf5,0xee,0xe7, 1827 | 0x3b,0x32,0x29,0x20,0x1f,0x16,0x0d,0x04,0x73,0x7a,0x61,0x68,0x57,0x5e,0x45,0x4c, 1828 | 0xab,0xa2,0xb9,0xb0,0x8f,0x86,0x9d,0x94,0xe3,0xea,0xf1,0xf8,0xc7,0xce,0xd5,0xdc, 1829 | 0x76,0x7f,0x64,0x6d,0x52,0x5b,0x40,0x49,0x3e,0x37,0x2c,0x25,0x1a,0x13,0x08,0x01, 1830 | 0xe6,0xef,0xf4,0xfd,0xc2,0xcb,0xd0,0xd9,0xae,0xa7,0xbc,0xb5,0x8a,0x83,0x98,0x91, 1831 | 0x4d,0x44,0x5f,0x56,0x69,0x60,0x7b,0x72,0x05,0x0c,0x17,0x1e,0x21,0x28,0x33,0x3a, 1832 | 0xdd,0xd4,0xcf,0xc6,0xf9,0xf0,0xeb,0xe2,0x95,0x9c,0x87,0x8e,0xb1,0xb8,0xa3,0xaa, 1833 | 0xec,0xe5,0xfe,0xf7,0xc8,0xc1,0xda,0xd3,0xa4,0xad,0xb6,0xbf,0x80,0x89,0x92,0x9b, 1834 | 0x7c,0x75,0x6e,0x67,0x58,0x51,0x4a,0x43,0x34,0x3d,0x26,0x2f,0x10,0x19,0x02,0x0b, 1835 | 0xd7,0xde,0xc5,0xcc,0xf3,0xfa,0xe1,0xe8,0x9f,0x96,0x8d,0x84,0xbb,0xb2,0xa9,0xa0, 1836 | 0x47,0x4e,0x55,0x5c,0x63,0x6a,0x71,0x78,0x0f,0x06,0x1d,0x14,0x2b,0x22,0x39,0x30, 1837 | 0x9a,0x93,0x88,0x81,0xbe,0xb7,0xac,0xa5,0xd2,0xdb,0xc0,0xc9,0xf6,0xff,0xe4,0xed, 1838 | 0x0a,0x03,0x18,0x11,0x2e,0x27,0x3c,0x35,0x42,0x4b,0x50,0x59,0x66,0x6f,0x74,0x7d, 1839 | 0xa1,0xa8,0xb3,0xba,0x85,0x8c,0x97,0x9e,0xe9,0xe0,0xfb,0xf2,0xcd,0xc4,0xdf,0xd6, 1840 | 0x31,0x38,0x23,0x2a,0x15,0x1c,0x07,0x0e,0x79,0x70,0x6b,0x62,0x5d,0x54,0x4f,0x46, 1841 | } 1842 | 1843 | aes.mul_11 = { 1844 | [0]=0x00,0x0b,0x16,0x1d,0x2c,0x27,0x3a,0x31,0x58,0x53,0x4e,0x45,0x74,0x7f,0x62,0x69, 1845 | 0xb0,0xbb,0xa6,0xad,0x9c,0x97,0x8a,0x81,0xe8,0xe3,0xfe,0xf5,0xc4,0xcf,0xd2,0xd9, 1846 | 0x7b,0x70,0x6d,0x66,0x57,0x5c,0x41,0x4a,0x23,0x28,0x35,0x3e,0x0f,0x04,0x19,0x12, 1847 | 0xcb,0xc0,0xdd,0xd6,0xe7,0xec,0xf1,0xfa,0x93,0x98,0x85,0x8e,0xbf,0xb4,0xa9,0xa2, 1848 | 0xf6,0xfd,0xe0,0xeb,0xda,0xd1,0xcc,0xc7,0xae,0xa5,0xb8,0xb3,0x82,0x89,0x94,0x9f, 1849 | 0x46,0x4d,0x50,0x5b,0x6a,0x61,0x7c,0x77,0x1e,0x15,0x08,0x03,0x32,0x39,0x24,0x2f, 1850 | 0x8d,0x86,0x9b,0x90,0xa1,0xaa,0xb7,0xbc,0xd5,0xde,0xc3,0xc8,0xf9,0xf2,0xef,0xe4, 1851 | 0x3d,0x36,0x2b,0x20,0x11,0x1a,0x07,0x0c,0x65,0x6e,0x73,0x78,0x49,0x42,0x5f,0x54, 1852 | 0xf7,0xfc,0xe1,0xea,0xdb,0xd0,0xcd,0xc6,0xaf,0xa4,0xb9,0xb2,0x83,0x88,0x95,0x9e, 1853 | 0x47,0x4c,0x51,0x5a,0x6b,0x60,0x7d,0x76,0x1f,0x14,0x09,0x02,0x33,0x38,0x25,0x2e, 1854 | 0x8c,0x87,0x9a,0x91,0xa0,0xab,0xb6,0xbd,0xd4,0xdf,0xc2,0xc9,0xf8,0xf3,0xee,0xe5, 1855 | 0x3c,0x37,0x2a,0x21,0x10,0x1b,0x06,0x0d,0x64,0x6f,0x72,0x79,0x48,0x43,0x5e,0x55, 1856 | 0x01,0x0a,0x17,0x1c,0x2d,0x26,0x3b,0x30,0x59,0x52,0x4f,0x44,0x75,0x7e,0x63,0x68, 1857 | 0xb1,0xba,0xa7,0xac,0x9d,0x96,0x8b,0x80,0xe9,0xe2,0xff,0xf4,0xc5,0xce,0xd3,0xd8, 1858 | 0x7a,0x71,0x6c,0x67,0x56,0x5d,0x40,0x4b,0x22,0x29,0x34,0x3f,0x0e,0x05,0x18,0x13, 1859 | 0xca,0xc1,0xdc,0xd7,0xe6,0xed,0xf0,0xfb,0x92,0x99,0x84,0x8f,0xbe,0xb5,0xa8,0xa3, 1860 | } 1861 | 1862 | aes.mul_13 = { 1863 | [0]=0x00,0x0d,0x1a,0x17,0x34,0x39,0x2e,0x23,0x68,0x65,0x72,0x7f,0x5c,0x51,0x46,0x4b, 1864 | 0xd0,0xdd,0xca,0xc7,0xe4,0xe9,0xfe,0xf3,0xb8,0xb5,0xa2,0xaf,0x8c,0x81,0x96,0x9b, 1865 | 0xbb,0xb6,0xa1,0xac,0x8f,0x82,0x95,0x98,0xd3,0xde,0xc9,0xc4,0xe7,0xea,0xfd,0xf0, 1866 | 0x6b,0x66,0x71,0x7c,0x5f,0x52,0x45,0x48,0x03,0x0e,0x19,0x14,0x37,0x3a,0x2d,0x20, 1867 | 0x6d,0x60,0x77,0x7a,0x59,0x54,0x43,0x4e,0x05,0x08,0x1f,0x12,0x31,0x3c,0x2b,0x26, 1868 | 0xbd,0xb0,0xa7,0xaa,0x89,0x84,0x93,0x9e,0xd5,0xd8,0xcf,0xc2,0xe1,0xec,0xfb,0xf6, 1869 | 0xd6,0xdb,0xcc,0xc1,0xe2,0xef,0xf8,0xf5,0xbe,0xb3,0xa4,0xa9,0x8a,0x87,0x90,0x9d, 1870 | 0x06,0x0b,0x1c,0x11,0x32,0x3f,0x28,0x25,0x6e,0x63,0x74,0x79,0x5a,0x57,0x40,0x4d, 1871 | 0xda,0xd7,0xc0,0xcd,0xee,0xe3,0xf4,0xf9,0xb2,0xbf,0xa8,0xa5,0x86,0x8b,0x9c,0x91, 1872 | 0x0a,0x07,0x10,0x1d,0x3e,0x33,0x24,0x29,0x62,0x6f,0x78,0x75,0x56,0x5b,0x4c,0x41, 1873 | 0x61,0x6c,0x7b,0x76,0x55,0x58,0x4f,0x42,0x09,0x04,0x13,0x1e,0x3d,0x30,0x27,0x2a, 1874 | 0xb1,0xbc,0xab,0xa6,0x85,0x88,0x9f,0x92,0xd9,0xd4,0xc3,0xce,0xed,0xe0,0xf7,0xfa, 1875 | 0xb7,0xba,0xad,0xa0,0x83,0x8e,0x99,0x94,0xdf,0xd2,0xc5,0xc8,0xeb,0xe6,0xf1,0xfc, 1876 | 0x67,0x6a,0x7d,0x70,0x53,0x5e,0x49,0x44,0x0f,0x02,0x15,0x18,0x3b,0x36,0x21,0x2c, 1877 | 0x0c,0x01,0x16,0x1b,0x38,0x35,0x22,0x2f,0x64,0x69,0x7e,0x73,0x50,0x5d,0x4a,0x47, 1878 | 0xdc,0xd1,0xc6,0xcb,0xe8,0xe5,0xf2,0xff,0xb4,0xb9,0xae,0xa3,0x80,0x8d,0x9a,0x97, 1879 | } 1880 | 1881 | aes.mul_14 = { 1882 | [0]=0x00,0x0e,0x1c,0x12,0x38,0x36,0x24,0x2a,0x70,0x7e,0x6c,0x62,0x48,0x46,0x54,0x5a, 1883 | 0xe0,0xee,0xfc,0xf2,0xd8,0xd6,0xc4,0xca,0x90,0x9e,0x8c,0x82,0xa8,0xa6,0xb4,0xba, 1884 | 0xdb,0xd5,0xc7,0xc9,0xe3,0xed,0xff,0xf1,0xab,0xa5,0xb7,0xb9,0x93,0x9d,0x8f,0x81, 1885 | 0x3b,0x35,0x27,0x29,0x03,0x0d,0x1f,0x11,0x4b,0x45,0x57,0x59,0x73,0x7d,0x6f,0x61, 1886 | 0xad,0xa3,0xb1,0xbf,0x95,0x9b,0x89,0x87,0xdd,0xd3,0xc1,0xcf,0xe5,0xeb,0xf9,0xf7, 1887 | 0x4d,0x43,0x51,0x5f,0x75,0x7b,0x69,0x67,0x3d,0x33,0x21,0x2f,0x05,0x0b,0x19,0x17, 1888 | 0x76,0x78,0x6a,0x64,0x4e,0x40,0x52,0x5c,0x06,0x08,0x1a,0x14,0x3e,0x30,0x22,0x2c, 1889 | 0x96,0x98,0x8a,0x84,0xae,0xa0,0xb2,0xbc,0xe6,0xe8,0xfa,0xf4,0xde,0xd0,0xc2,0xcc, 1890 | 0x41,0x4f,0x5d,0x53,0x79,0x77,0x65,0x6b,0x31,0x3f,0x2d,0x23,0x09,0x07,0x15,0x1b, 1891 | 0xa1,0xaf,0xbd,0xb3,0x99,0x97,0x85,0x8b,0xd1,0xdf,0xcd,0xc3,0xe9,0xe7,0xf5,0xfb, 1892 | 0x9a,0x94,0x86,0x88,0xa2,0xac,0xbe,0xb0,0xea,0xe4,0xf6,0xf8,0xd2,0xdc,0xce,0xc0, 1893 | 0x7a,0x74,0x66,0x68,0x42,0x4c,0x5e,0x50,0x0a,0x04,0x16,0x18,0x32,0x3c,0x2e,0x20, 1894 | 0xec,0xe2,0xf0,0xfe,0xd4,0xda,0xc8,0xc6,0x9c,0x92,0x80,0x8e,0xa4,0xaa,0xb8,0xb6, 1895 | 0x0c,0x02,0x10,0x1e,0x34,0x3a,0x28,0x26,0x7c,0x72,0x60,0x6e,0x44,0x4a,0x58,0x56, 1896 | 0x37,0x39,0x2b,0x25,0x0f,0x01,0x13,0x1d,0x47,0x49,0x5b,0x55,0x7f,0x71,0x63,0x6d, 1897 | 0xd7,0xd9,0xcb,0xc5,0xef,0xe1,0xf3,0xfd,0xa7,0xa9,0xbb,0xb5,0x9f,0x91,0x83,0x8d, 1898 | } 1899 | 1900 | aes.bxor = bit.bxor 1901 | aes.insert = table.insert 1902 | 1903 | aes.copy = function (input) 1904 | local c = {} 1905 | for i, v in pairs(input) do 1906 | c[i] = v 1907 | end 1908 | return c 1909 | end 1910 | 1911 | aes.subBytes = function (input, invert) 1912 | for i=1, #input do 1913 | if not (aes.sbox[input[i]] and aes.inv_sbox[input[i]]) then 1914 | error("subBytes: input["..i.."] > 0xFF") 1915 | end 1916 | if invert then 1917 | input[i] = aes.inv_sbox[input[i]] 1918 | else 1919 | input[i] = aes.sbox[input[i]] 1920 | end 1921 | end 1922 | return input 1923 | end 1924 | 1925 | aes.shiftRows = function (input) 1926 | local copy = {} 1927 | -- Row 1: No change 1928 | copy[1] = input[1] 1929 | copy[2] = input[2] 1930 | copy[3] = input[3] 1931 | copy[4] = input[4] 1932 | -- Row 2: Offset 1 1933 | copy[5] = input[6] 1934 | copy[6] = input[7] 1935 | copy[7] = input[8] 1936 | copy[8] = input[5] 1937 | -- Row 3: Offset 2 1938 | copy[9] = input[11] 1939 | copy[10] = input[12] 1940 | copy[11] = input[9] 1941 | copy[12] = input[10] 1942 | -- Row 4: Offset 3 1943 | copy[13] = input[16] 1944 | copy[14] = input[13] 1945 | copy[15] = input[14] 1946 | copy[16] = input[15] 1947 | return copy 1948 | end 1949 | 1950 | aes.invShiftRows = function (input) 1951 | local copy = {} 1952 | -- Row 1: No change 1953 | copy[1] = input[1] 1954 | copy[2] = input[2] 1955 | copy[3] = input[3] 1956 | copy[4] = input[4] 1957 | -- Row 2: Offset 1 1958 | copy[5] = input[8] 1959 | copy[6] = input[5] 1960 | copy[7] = input[6] 1961 | copy[8] = input[7] 1962 | -- Row 3: Offset 2 1963 | copy[9] = input[11] 1964 | copy[10] = input[12] 1965 | copy[11] = input[9] 1966 | copy[12] = input[10] 1967 | -- Row 4: Offset 3 1968 | copy[13] = input[14] 1969 | copy[14] = input[15] 1970 | copy[15] = input[16] 1971 | copy[16] = input[13] 1972 | return copy 1973 | end 1974 | 1975 | aes.finite_field_mul = function (a,b) -- Multiply two numbers in GF(256), assuming that polynomials are 8 bits wide 1976 | local product = 0 1977 | local mulA, mulB = a,b 1978 | for i=1, 8 do 1979 | --print("FFMul: MulA: "..mulA.." MulB: "..mulB) 1980 | if mulA == 0 or mulB == 0 then 1981 | break 1982 | end 1983 | if bit.band(1, mulB) > 0 then 1984 | product = aes.bxor(product, mulA) 1985 | end 1986 | mulB = bit.brshift(mulB, 1) 1987 | local carry = bit.band(0x80, mulA) 1988 | mulA = bit.band(0xFF, bit.blshift(mulA, 1)) 1989 | if carry > 0 then 1990 | mulA = aes.bxor( mulA, 0x1B ) 1991 | end 1992 | end 1993 | return product 1994 | end 1995 | 1996 | aes.mixColumn = function (column) 1997 | local output = {} 1998 | --print("MixColumn: #column: "..#column) 1999 | output[1] = aes.bxor( aes.mul_2[column[1]], aes.bxor( aes.mul_3[column[2]], aes.bxor( column[3], column[4] ) ) ) 2000 | output[2] = aes.bxor( column[1], aes.bxor( aes.mul_2[column[2]], aes.bxor( aes.mul_3[column[3]], column[4] ) ) ) 2001 | output[3] = aes.bxor( column[1], aes.bxor( column[2], aes.bxor( aes.mul_2[column[3]], aes.mul_3[column[4]] ) ) ) 2002 | output[4] = aes.bxor( aes.mul_3[column[1]], aes.bxor( column[2], aes.bxor( column[3], aes.mul_2[column[4]] ) ) ) 2003 | return output 2004 | end 2005 | 2006 | aes.invMixColumn = function (column) 2007 | local output = {} 2008 | --print("InvMixColumn: #column: "..#column) 2009 | output[1] = aes.bxor( aes.mul_14[column[1]], aes.bxor( aes.mul_11[column[2]], aes.bxor( aes.mul_13[column[3]], aes.mul_9[column[4]] ) ) ) 2010 | output[2] = aes.bxor( aes.mul_9[column[1]], aes.bxor( aes.mul_14[column[2]], aes.bxor( aes.mul_11[column[3]], aes.mul_13[column[4]] ) ) ) 2011 | output[3] = aes.bxor( aes.mul_13[column[1]], aes.bxor( aes.mul_9[column[2]], aes.bxor( aes.mul_14[column[3]], aes.mul_11[column[4]] ) ) ) 2012 | output[4] = aes.bxor( aes.mul_11[column[1]], aes.bxor( aes.mul_13[column[2]], aes.bxor( aes.mul_9[column[3]], aes.mul_14[column[4]] ) ) ) 2013 | return output 2014 | end 2015 | 2016 | aes.mixColumns = function (input, invert) 2017 | --print("MixColumns: #input: "..#input) 2018 | -- Ooops. I mixed the ROWS instead of the COLUMNS on accident. 2019 | local output = {} 2020 | --[[ 2021 | local c1 = { input[1], input[2], input[3], input[4] } 2022 | local c2 = { input[5], input[6], input[7], input[8] } 2023 | local c3 = { input[9], input[10], input[11], input[12] } 2024 | local c4 = { input[13], input[14], input[15], input[16] } 2025 | ]] 2026 | local c1 = { input[1], input[5], input[9], input[13] } 2027 | local c2 = { input[2], input[6], input[10], input[14] } 2028 | local c3 = { input[3], input[7], input[11], input[15] } 2029 | local c4 = { input[4], input[8], input[12], input[16] } 2030 | if invert then 2031 | c1 = aes.invMixColumn(c1) 2032 | c2 = aes.invMixColumn(c2) 2033 | c3 = aes.invMixColumn(c3) 2034 | c4 = aes.invMixColumn(c4) 2035 | else 2036 | c1 = aes.mixColumn(c1) 2037 | c2 = aes.mixColumn(c2) 2038 | c3 = aes.mixColumn(c3) 2039 | c4 = aes.mixColumn(c4) 2040 | end 2041 | --[[ 2042 | output[1] = c1[1] 2043 | output[2] = c1[2] 2044 | output[3] = c1[3] 2045 | output[4] = c1[4] 2046 | 2047 | output[5] = c2[1] 2048 | output[6] = c2[2] 2049 | output[7] = c2[3] 2050 | output[8] = c2[4] 2051 | 2052 | output[9] = c3[1] 2053 | output[10] = c3[2] 2054 | output[11] = c3[3] 2055 | output[12] = c3[4] 2056 | 2057 | output[13] = c4[1] 2058 | output[14] = c4[2] 2059 | output[15] = c4[3] 2060 | output[16] = c4[4] 2061 | ]] 2062 | 2063 | output[1] = c1[1] 2064 | output[5] = c1[2] 2065 | output[9] = c1[3] 2066 | output[13] = c1[4] 2067 | 2068 | output[2] = c2[1] 2069 | output[6] = c2[2] 2070 | output[10] = c2[3] 2071 | output[14] = c2[4] 2072 | 2073 | output[3] = c3[1] 2074 | output[7] = c3[2] 2075 | output[11] = c3[3] 2076 | output[15] = c3[4] 2077 | 2078 | output[4] = c4[1] 2079 | output[8] = c4[2] 2080 | output[12] = c4[3] 2081 | output[16] = c4[4] 2082 | 2083 | return output 2084 | end 2085 | 2086 | aes.addRoundKey = function (input, exp_key, round) 2087 | local output = {} 2088 | for i=1, 16 do 2089 | assert(input[i], "input["..i.."]=nil!") 2090 | assert(exp_key[ ((round-1)*16)+i ], "round_key["..(((round-1)*16)+i).."]=nil!") 2091 | output[i] = aes.bxor( input[i], exp_key[ ((round-1)*16)+i ] ) 2092 | end 2093 | return output 2094 | end 2095 | 2096 | aes.key_schedule = function (enc_key) 2097 | local function core(in1, in2, in3, in4, i) 2098 | local s1 = in2 2099 | local s2 = in3 2100 | local s3 = in4 2101 | local s4 = in1 2102 | s1 = aes.bxor(aes.sbox[s1], aes.Rcon[i]) 2103 | s2 = aes.sbox[s2] 2104 | s3 = aes.sbox[s3] 2105 | s4 = aes.sbox[s4] 2106 | return s1, s2, s3, s4 2107 | end 2108 | 2109 | local n, b, key_type = 0, 0, 0 2110 | 2111 | -- Len | n | b | 2112 | -- 128 |16 |176| 2113 | -- 192 |24 |208| 2114 | -- 256 |32 |240| 2115 | 2116 | -- Determine keysize: 2117 | 2118 | if #enc_key < 16 then 2119 | error("Encryption key is too small; key size must be more than 16 bytes.") 2120 | elseif #enc_key >= 16 and #enc_key < 24 then 2121 | n = 16 2122 | b = 176 2123 | --key_type = 1 2124 | elseif #enc_key >= 24 and #enc_key < 32 then 2125 | n = 24 2126 | b = 208 2127 | --key_type = 2 2128 | else 2129 | n = 32 2130 | b = 240 2131 | --key_type = 3 2132 | end 2133 | 2134 | local exp_key = {} 2135 | local rcon_iter = 1 2136 | for i=1, n do 2137 | exp_key[i] = enc_key[i] 2138 | end 2139 | while #exp_key < b do 2140 | local t1 = exp_key[#exp_key] 2141 | local t2 = exp_key[#exp_key-1] 2142 | local t3 = exp_key[#exp_key-2] 2143 | local t4 = exp_key[#exp_key-3] 2144 | t1, t2, t3, t4 = core(t1, t2, t3, t4, rcon_iter) 2145 | rcon_iter = rcon_iter+1 2146 | t1 = aes.bxor(t1, exp_key[#exp_key-(n-1)]) 2147 | t2 = aes.bxor(t2, exp_key[#exp_key-(n-2)]) 2148 | t3 = aes.bxor(t3, exp_key[#exp_key-(n-3)]) 2149 | t4 = aes.bxor(t4, exp_key[#exp_key-(n-4)]) 2150 | aes.insert(exp_key, t1) 2151 | aes.insert(exp_key, t2) 2152 | aes.insert(exp_key, t3) 2153 | aes.insert(exp_key, t4) 2154 | for i=1, 3 do 2155 | t1 = aes.bxor(exp_key[#exp_key], exp_key[#exp_key-(n-1)]) 2156 | t2 = aes.bxor(exp_key[#exp_key-1], exp_key[#exp_key-(n-2)]) 2157 | t3 = aes.bxor(exp_key[#exp_key-2], exp_key[#exp_key-(n-3)]) 2158 | t4 = aes.bxor(exp_key[#exp_key-3], exp_key[#exp_key-(n-4)]) 2159 | aes.insert(exp_key, t1) 2160 | aes.insert(exp_key, t2) 2161 | aes.insert(exp_key, t3) 2162 | aes.insert(exp_key, t4) 2163 | end 2164 | if key_type == 3 then -- If we're processing a 256 bit key... 2165 | -- Take the previous 4 bytes of the expanded key, run them through the sbox, 2166 | -- then XOR them with the previous n bytes of the expanded key, then output them 2167 | -- as the next 4 bytes of expanded key. 2168 | t1 = aes.bxor(aes.sbox[exp_key[#exp_key]], exp_key[#exp_key-(n-1)]) 2169 | t2 = aes.bxor(aes.sbox[exp_key[#exp_key-1]], exp_key[#exp_key-(n-2)]) 2170 | t3 = aes.bxor(aes.sbox[exp_key[#exp_key-2]], exp_key[#exp_key-(n-3)]) 2171 | t4 = aes.bxor(aes.sbox[exp_key[#exp_key-3]], exp_key[#exp_key-(n-4)]) 2172 | aes.insert(exp_key, t1) 2173 | aes.insert(exp_key, t2) 2174 | aes.insert(exp_key, t3) 2175 | aes.insert(exp_key, t4) 2176 | end 2177 | if key_type == 2 or key_type == 3 then -- If we're processing a 192-bit or 256-bit key.. 2178 | local i = 2 2179 | if key_type == 3 then 2180 | i = 3 2181 | end 2182 | for j=1, i do 2183 | t1 = aes.bxor(exp_key[#exp_key], exp_key[#exp_key-(n-1)]) 2184 | t2 = aes.bxor(exp_key[#exp_key-1], exp_key[#exp_key-(n-2)]) 2185 | t3 = aes.bxor(exp_key[#exp_key-2], exp_key[#exp_key-(n-3)]) 2186 | t4 = aes.bxor(exp_key[#exp_key-3], exp_key[#exp_key-(n-4)]) 2187 | aes.insert(exp_key, t1) 2188 | aes.insert(exp_key, t2) 2189 | aes.insert(exp_key, t3) 2190 | aes.insert(exp_key, t4) 2191 | end 2192 | end 2193 | end 2194 | return exp_key 2195 | end 2196 | 2197 | -- Transform a string of bytes into 16 byte blocks, adding padding to ensure that each block contains 16 bytes. 2198 | -- For example: 2199 | -- "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" (contains 28 0xFF bytes) 2200 | -- Is transformed into this: 2201 | -- {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0,0,0,0} (16 0xFF bytes, followed by 12 0xFF bytes and 4 0x00 bytes for padding) 2202 | 2203 | aes.breakIntoBlocks = function (data) 2204 | if type(data) ~= "string" then 2205 | error("breakIntoBlocks: data is not a string", 2) 2206 | end 2207 | while (#data % 16) ~= 0 do 2208 | data = data.."\0" 2209 | end 2210 | local blocks = {} 2211 | local blockNum = 1 2212 | local output = {} 2213 | for i=1, #data, 16 do 2214 | blocks[blockNum] = {} 2215 | for j=1, 16 do 2216 | blocks[blockNum][j] = string.byte(data, ((blockNum-1)*16)+j, ((blockNum-1)*16)+j) 2217 | end 2218 | blockNum = blockNum+1 2219 | end 2220 | return blocks 2221 | end 2222 | 2223 | -- Transform a string into a series of blocks. 2224 | 2225 | -- For example, to get a key from a string: 2226 | -- local key = strToBlocks(keyStr) 2227 | -- key = key[1] 2228 | 2229 | aes.strToBlocks = function (str) 2230 | local rawBytestream = {} 2231 | local blocks = {} 2232 | for i=1, #str do 2233 | rawBytestream[i] = string.byte(str, i, i) 2234 | end 2235 | for i=1, math.ceil(#rawBytestream / 16) do 2236 | blocks[i] = {} 2237 | for j=1, 16 do 2238 | blocks[i][j] = rawBytestream[ ((i-1)*16)+j ] or 0 2239 | end 2240 | end 2241 | return blocks 2242 | end 2243 | 2244 | -- Encrypt / Decrypt individual blocks: 2245 | 2246 | aes.encrypt_block = function (data, key) 2247 | local exp_key = aes.key_schedule(key) 2248 | local state = data 2249 | local nr = 0 2250 | 2251 | if #exp_key == 176 then -- Key type 1 (128-bits) 2252 | nr = 10 2253 | elseif #exp_key == 208 then -- Key type 2 (192-bits) 2254 | nr = 12 2255 | elseif #exp_key == 240 then -- Key type 3 (256-bits) 2256 | nr = 14 2257 | else 2258 | error("encrypt_block: Unknown key size?", 2) 2259 | end 2260 | 2261 | -- Inital round: 2262 | state = aes.addRoundKey(state, exp_key, 1) 2263 | 2264 | -- Repeat (Nr-1) times: 2265 | for round_num = 2, nr-1 do 2266 | state = aes.subBytes(state) 2267 | state = aes.shiftRows(state) 2268 | state = aes.mixColumns(state) 2269 | state = aes.addRoundKey(state, exp_key, round_num) 2270 | end 2271 | 2272 | -- Final round (No mixColumns()): 2273 | state = aes.subBytes(state) 2274 | state = aes.shiftRows(state) 2275 | state = aes.addRoundKey(state, exp_key, nr) 2276 | return state 2277 | end 2278 | 2279 | aes.decrypt_block = function (data, key) 2280 | local exp_key = aes.key_schedule(key) 2281 | local state = data 2282 | local nr = 0 2283 | 2284 | if #exp_key == 176 then -- Key type 1 (128-bits) 2285 | nr = 10 2286 | elseif #exp_key == 208 then -- Key type 2 (192-bits) 2287 | nr = 12 2288 | elseif #exp_key == 240 then -- Key type 3 (256-bits) 2289 | nr = 14 2290 | else 2291 | error("decrypt_block: Unknown key size?", 2) 2292 | end 2293 | 2294 | -- Inital round: 2295 | state = aes.addRoundKey(state, exp_key, nr) 2296 | 2297 | -- Repeat (Nr-1) times: 2298 | for round_num = nr-1, 2, -1 do 2299 | state = aes.invShiftRows(state) 2300 | state = aes.subBytes(state, true) 2301 | state = aes.addRoundKey(state, exp_key, round_num) 2302 | state = aes.mixColumns(state, true) 2303 | end 2304 | 2305 | -- Final round (No mixColumns()): 2306 | state = aes.invShiftRows(state) 2307 | state = aes.subBytes(state, true) 2308 | state = aes.addRoundKey(state, exp_key, 1) 2309 | return state 2310 | end 2311 | 2312 | aes.encrypt_block_customExpKey = function (data, exp_key--[[, key_type]]) -- Encrypt blocks, but using a precalculated expanded key instead of performing the key expansion on every step like with the normal encrypt_block(2) call 2313 | local state = data 2314 | local nr = 0 2315 | if #exp_key == 176 then -- Key type 1 (128-bits) 2316 | nr = 10 2317 | elseif #exp_key == 208 then -- Key type 2 (192-bits) 2318 | nr = 12 2319 | elseif #exp_key == 240 then -- Key type 3 (256-bits) 2320 | nr = 14 2321 | else 2322 | error("encrypt_block: Unknown key size?", 2) 2323 | end 2324 | 2325 | -- Inital round: 2326 | state = aes.addRoundKey(state, exp_key, 1) 2327 | 2328 | -- Repeat (Nr-1) times: 2329 | for round_num = 2, nr-1 do 2330 | state = aes.subBytes(state) 2331 | state = aes.shiftRows(state) 2332 | state = aes.mixColumns(state) 2333 | state = aes.addRoundKey(state, exp_key, round_num) 2334 | end 2335 | 2336 | -- Final round (No mixColumns()): 2337 | state = aes.subBytes(state) 2338 | state = aes.shiftRows(state) 2339 | state = aes.addRoundKey(state, exp_key, nr) 2340 | return state 2341 | end 2342 | 2343 | aes.decrypt_block_customExpKey = function (data, exp_key--[[, key_type]]) 2344 | local state = data 2345 | local nr = 0 2346 | if #exp_key == 176 then -- Key type 1 (128-bits) 2347 | nr = 10 2348 | elseif #exp_key == 208 then -- Key type 2 (192-bits) 2349 | nr = 12 2350 | elseif #exp_key == 240 then -- Key type 3 (256-bits) 2351 | nr = 14 2352 | else 2353 | error("decrypt_block: Unknown key size?", 2) 2354 | end 2355 | 2356 | -- Inital round: 2357 | state = aes.addRoundKey(state, exp_key, nr) 2358 | 2359 | -- Repeat (Nr-1) times: 2360 | for round_num = nr-1, 2, -1 do 2361 | state = aes.invShiftRows(state) 2362 | state = aes.subBytes(state, true) 2363 | state = aes.addRoundKey(state, exp_key, round_num) 2364 | state = aes.mixColumns(state, true) 2365 | end 2366 | 2367 | -- Final round (No mixColumns()): 2368 | state = aes.invShiftRows(state) 2369 | state = aes.subBytes(state, true) 2370 | state = aes.addRoundKey(state, exp_key, 1) 2371 | return state 2372 | end 2373 | 2374 | -- Encrypt / Decrypt bytestreams (tables of bytes): 2375 | 2376 | -- ECB (electronic codebook) Mode (not secure, do not use): 2377 | 2378 | aes.encrypt_bytestream_ecb = function (data, key) 2379 | local blocks = {} 2380 | local outputBytestream = {} 2381 | local exp_key = aes.key_schedule(key) 2382 | for i=1, #data, 16 do 2383 | local block = {} 2384 | for j=1, 16 do 2385 | block[j] = data[i+(j-1)] or 0 2386 | end 2387 | block = aes.encrypt_block_customExpKey(block, exp_key) 2388 | for j=1, 16 do 2389 | table.insert(outputBytestream, block[j]) 2390 | end 2391 | os.queueEvent("") 2392 | os.pullEvent("") 2393 | end 2394 | return outputBytestream 2395 | end 2396 | 2397 | aes.decrypt_bytestream_ecb = function (data, key) 2398 | local outputBytestream = {} 2399 | local exp_key = aes.key_schedule(key) 2400 | for i=1, #data, 16 do 2401 | local block = {} 2402 | for j=1, 16 do 2403 | block[j] = data[i+(j-1)] or 0 2404 | end 2405 | block = aes.decrypt_block_customExpKey(block, exp_key) 2406 | for j=1, 16 do 2407 | table.insert(outputBytestream, block[j]) 2408 | end 2409 | os.queueEvent("") 2410 | os.pullEvent("") 2411 | end 2412 | for i=#outputBytestream, 1, -1 do 2413 | if outputBytestream[i] ~= 0 then 2414 | break 2415 | else 2416 | outputBytestream[i] = nil 2417 | end 2418 | end 2419 | return outputBytestream 2420 | end 2421 | 2422 | -- CBC (cipher-block chaining) mode: 2423 | 2424 | aes.encrypt_bytestream = function (data, key, init_vector) 2425 | local blocks = { init_vector } 2426 | local outputBytestream = {} 2427 | local exp_key = aes.key_schedule(key) 2428 | if not init_vector then 2429 | error("encrypt_bytestream: No initalization vector was passed.", 2) 2430 | end 2431 | for i=1, #data do 2432 | if data[i] == nil or data[i] >= 256 then 2433 | if type(data[i]) == "number" then 2434 | error("encrypt_bytestream: Invalid data at i="..i.." data[i]="..data[i], 2) 2435 | else 2436 | error("encrypt_bytestream: Invalid data at i="..i.." data[i]="..type(data[i]), 2) 2437 | end 2438 | end 2439 | end 2440 | local s = os.clock() 2441 | for i=1, math.ceil(#data/16) do 2442 | local block = {} 2443 | if not blocks[i] then 2444 | error("encrypt_bytestream: blocks["..i.."] is nil! Input size: "..#data, 2) 2445 | end 2446 | for j=1, 16 do 2447 | block[j] = data[((i-1)*16)+j] or 0 2448 | block[j] = aes.bxor(block[j], blocks[i][j]) -- XOR this block with the previous one 2449 | end 2450 | --print("#bytes: "..#block) 2451 | block = aes.encrypt_block_customExpKey(block, exp_key) 2452 | table.insert(blocks, block) 2453 | for j=1, 16 do 2454 | aes.insert(outputBytestream, block[j]) 2455 | end 2456 | if os.clock() - s >= 2.5 then 2457 | os.queueEvent("") 2458 | os.pullEvent("") 2459 | s = os.clock() 2460 | end 2461 | end 2462 | return outputBytestream 2463 | end 2464 | 2465 | aes.decrypt_bytestream = function (data, key, init_vector) 2466 | local blocks = { init_vector } 2467 | local outputBytestream = {} 2468 | local exp_key = aes.key_schedule(key) 2469 | if not init_vector then 2470 | error("decrypt_bytestream: No initalization vector was passed.", 2) 2471 | end 2472 | local s = os.clock() 2473 | for i=1, math.ceil(#data/16) do 2474 | local block = {} 2475 | if not blocks[i] then 2476 | error("decrypt_bytestream: blocks["..i.."] is nil! Input size: "..#data, 2) 2477 | end 2478 | for j=1, 16 do 2479 | block[j] = data[((i-1)*16)+j] or 0 2480 | end 2481 | table.insert(blocks, block) 2482 | local dec_block = aes.decrypt_block_customExpKey(block, exp_key) 2483 | for j=1, 16 do 2484 | dec_block[j] = aes.bxor(dec_block[j], blocks[i][j]) -- We use XOR on the plaintext, not the ciphertext 2485 | table.insert(outputBytestream, dec_block[j]) 2486 | end 2487 | if os.clock() - s >= 2.5 then 2488 | os.queueEvent("") 2489 | os.pullEvent("") 2490 | s = os.clock() 2491 | end 2492 | end 2493 | -- Remove padding: 2494 | for i=#outputBytestream, #outputBytestream-15, -1 do 2495 | if outputBytestream[i] ~= 0 then 2496 | break 2497 | else 2498 | outputBytestream[i] = nil 2499 | end 2500 | end 2501 | return outputBytestream 2502 | end 2503 | 2504 | -- Encrypt / Decrypt strings: 2505 | 2506 | aes.encrypt_str = function (data, key, iv) 2507 | local byteStream = {} 2508 | for i=1, #data do 2509 | table.insert(byteStream, string.byte(data, i, i)) 2510 | end 2511 | local output_bytestream = {} 2512 | if iv then 2513 | output_bytestream = aes.encrypt_bytestream(byteStream, key, iv) 2514 | else 2515 | output_bytestream = aes.encrypt_bytestream_ecb(byteStream, key) 2516 | end 2517 | local output = "" 2518 | for i=1, #output_bytestream do 2519 | output = output..string.char(output_bytestream[i]) 2520 | end 2521 | return output 2522 | end 2523 | 2524 | aes.decrypt_str = function (data, key, iv) 2525 | local byteStream = {} 2526 | for i=1, #data do 2527 | table.insert(byteStream, string.byte(data, i, i)) 2528 | end 2529 | local output_bytestream = {} 2530 | if iv then 2531 | output_bytestream = aes.decrypt_bytestream(byteStream, key, iv) 2532 | else 2533 | output_bytestream = aes.decrypt_bytestream_ecb(byteStream, key) 2534 | end 2535 | local output = "" 2536 | for i=1, #output_bytestream do 2537 | output = output..string.char(output_bytestream[i]) 2538 | end 2539 | return output 2540 | end 2541 | 2542 | aes.davies_meyer = function (data, h0) 2543 | local last_h = h0 2544 | for dm_iter=1, 16 do 2545 | for i=1, math.ceil(#data/16) do 2546 | local block = {} 2547 | for j=1, 16 do 2548 | block[j] = data[((i-1)*16)+j] or 0 2549 | end 2550 | local block = aes.encrypt_block(last_h, block) 2551 | for j=1, 16 do 2552 | block[j] = aes.bxor(block[j], last_h[j]) -- XOR h[i-1] with h[i]. 2553 | end 2554 | last_h = block 2555 | os.queueEvent("") 2556 | os.pullEvent("") 2557 | end 2558 | end 2559 | return last_h 2560 | end 2561 | 2562 | aes.increment_ctr = function (blk) 2563 | local cpy = {} 2564 | for i=1, 16 do 2565 | cpy[i] = blk[i] or 0 2566 | end 2567 | cpy[1] = cpy[1] + incAmt 2568 | for i=2, 16 do 2569 | if cpy[i-1] <= 255 then 2570 | break 2571 | end 2572 | local carry = cpy[i-1] - 255 2573 | cpy[i] = cpy[i]+carry 2574 | end 2575 | return cpy 2576 | end 2577 | 2578 | aes.counter_mode_context = { 2579 | key = {}, 2580 | ctr = {}, 2581 | stream_cache = {}, -- Use "leftover" bytes from generate() here. 2582 | set_key = function(self, key) 2583 | if type(key) == "string" then 2584 | if #key < 16 then 2585 | error("set_key: Key length ("..#key..") must be at least 16 characters!", 2) 2586 | end 2587 | for i=1, 16 do 2588 | self.key[i] = string.byte(key, i, i) 2589 | end 2590 | elseif type(key) == "table" then 2591 | if #key < 16 then 2592 | error("set_key: Key length ("..#key..") must be at least 16 bytes!", 2) 2593 | end 2594 | for i=1, 16 do 2595 | if type(key[i]) ~= "number" or key[i] > 255 or key[i] < 0 then 2596 | if type(key[i]) == "nil" then 2597 | error("set_key: Value key["..i.."] is invalid: nil", 2) 2598 | else 2599 | error("set_key: Value key["..i.."] is invalid: "..key[i], 2) 2600 | end 2601 | end 2602 | self.key[i] = key[i] 2603 | end 2604 | else 2605 | error("set_key: Key type is not supported: "..type(key), 2) 2606 | end 2607 | end, 2608 | set_ctr = function(self, ctr) 2609 | if type(ctr) == "string" then 2610 | if #ctr < 16 then 2611 | error("set_ctr: Counter length ("..#ctr..") must be at least 16 characters!", 2) 2612 | end 2613 | for i=1, 16 do 2614 | self.ctr[i] = string.byte(ctr, i, i) 2615 | end 2616 | elseif type(ctr) == "table" then 2617 | if #ctr < 16 then 2618 | error("set_ctr: Counter length ("..#ctr..") must be at least 16 bytes!", 2) 2619 | end 2620 | for i=1, 16 do 2621 | if type(ctr[i]) ~= "number" or ctr[i] > 255 or ctr[i] < 0 then 2622 | if type(ctr[i]) == "nil" then 2623 | error("set_ctr: Value ctr["..i.."] is invalid: nil", 2) 2624 | else 2625 | error("set_ctr: Value ctr["..i.."] is invalid: "..ctr[i], 2) 2626 | end 2627 | end 2628 | self.ctr[i] = ctr[i] 2629 | end 2630 | elseif type(ctr) == "number" then 2631 | local b1 = bit.band( ctr, 0xFF ) 2632 | local b2 = bit.band( bit.brshift(bit.band( ctr, 0xFF00 ), 8), 0xFF ) 2633 | local b3 = bit.band( bit.brshift(bit.band( ctr, 0xFF0000 ), 16), 0xFF ) 2634 | local b4 = bit.band( bit.brshift(bit.band( ctr, 0xFF000000 ), 24), 0xFF ) 2635 | self.ctr = {} 2636 | for i=1, 16 do 2637 | self.ctr[i] = 0 2638 | end 2639 | self.ctr[1] = b1 2640 | self.ctr[2] = b2 2641 | self.ctr[3] = b3 2642 | self.ctr[4] = b4 2643 | else 2644 | error("set_ctr: Counter type is not supported: "..type(ctr), 2) 2645 | end 2646 | end, 2647 | generate = function(self, bytes) 2648 | local genBytes = {} 2649 | if #self.stream_cache >= bytes then 2650 | for i=1, bytes do 2651 | table.insert(genBytes, table.remove(self.stream_cache)) 2652 | end 2653 | else 2654 | for i=1, #self.stream_cache do 2655 | table.insert(genBytes, table.remove(self.stream_cache)) 2656 | end 2657 | local blocksToGenerate = math.ceil((bytes - #genBytes) / 16) 2658 | for i=1, blocksToGenerate-1 do 2659 | self.ctr = aes.increment_ctr(self.ctr) 2660 | local block = aes.encrypt_block(self.ctr, self.key) 2661 | for i=1, 16 do 2662 | table.insert(genBytes, block[i]) 2663 | end 2664 | end 2665 | self.ctr = aes.increment_ctr(self.ctr) 2666 | local block = aes.encrypt_block(self.ctr, self.key) 2667 | for i=1, (bytes - #genBytes) do 2668 | table.insert(genBytes, table.remove(block)) 2669 | end 2670 | for i=1, #block do 2671 | table.insert(self.stream_cache, table.remove(block)) 2672 | end 2673 | end 2674 | return genBytes 2675 | end, 2676 | } 2677 | 2678 | aes.new_ctrMode = function (key, iv) 2679 | local context = { 2680 | stream_cache = {}, 2681 | key = {}, 2682 | iv = {}, 2683 | __index = aes.counter_mode_context, 2684 | } 2685 | setmetatable(context, context) 2686 | context:set_key(key) 2687 | context:set_ctr(iv) 2688 | return context 2689 | end 2690 | 2691 | 2692 | -- Simple thread API by immibis 2693 | 2694 | threadAPI = {} 2695 | 2696 | threadAPI.threads = {} 2697 | threadAPI.starting = {} 2698 | threadAPI.eventFilter = nil 2699 | 2700 | rawset(os, "startThread", function(fn, blockTerminate) 2701 | table.insert(threadAPI.starting, { 2702 | cr = coroutine.create(fn), 2703 | blockTerminate = blockTerminate or false, 2704 | error = nil, 2705 | dead = false, 2706 | filter = nil 2707 | }) 2708 | end) 2709 | 2710 | threadAPI.tick = function (t, evt, ...) 2711 | if t.dead then return end 2712 | if t.filter ~= nil and evt ~= t.filter then return end 2713 | if evt == "terminate" and t.blockTerminate then return end 2714 | 2715 | coroutine.resume(t.cr, evt, ...) 2716 | t.dead = (coroutine.status(t.cr) == "dead") 2717 | end 2718 | 2719 | threadAPI.tickAll = function () 2720 | if #threadAPI.starting > 0 then 2721 | local clone = threadAPI.starting 2722 | threadAPI.starting = {} 2723 | for _,v in ipairs(clone) do 2724 | threadAPI.tick(v) 2725 | table.insert(threadAPI.threads, v) 2726 | end 2727 | end 2728 | local e 2729 | if threadAPI.eventFilter then 2730 | e = {threadAPI.eventFilter(coroutine.yield())} 2731 | else 2732 | e = {coroutine.yield()} 2733 | end 2734 | local dead = nil 2735 | for k,v in ipairs(threadAPI.threads) do 2736 | threadAPI.tick(v, unpack(e)) 2737 | if v.dead then 2738 | if dead == nil then dead = {} end 2739 | table.insert(dead, k - #dead) 2740 | end 2741 | end 2742 | if dead ~= nil then 2743 | for _,v in ipairs(dead) do 2744 | table.remove(threadAPI.threads, v) 2745 | end 2746 | end 2747 | end 2748 | 2749 | rawset(os, "setGlobalEventFilter", function(fn) 2750 | if threadAPI.eventFilter ~= nil then error("This can only be set once!") end 2751 | threadAPI.eventFilter = fn 2752 | rawset(os, "setGlobalEventFilter", nil) 2753 | end) 2754 | 2755 | threadAPI.startThreading = function (mainThread) 2756 | if type(mainThread) == "function" then 2757 | os.startThread(mainThread) 2758 | else 2759 | os.startThread(function() shell.run("shell") end) 2760 | end 2761 | 2762 | while #threadAPI.threads > 0 or #threadAPI.starting > 0 do 2763 | threadAPI.tickAll() 2764 | end 2765 | 2766 | print("All threads terminated!") 2767 | print("Exiting thread manager") 2768 | end 2769 | 2770 | ------- END THIRD PARTY ------- 2771 | 2772 | ------- BEGIN CRYPTONET ------- 2773 | -- The following code was written by me (SiliconSloth). 2774 | 2775 | 2776 | -- Channel used to send discovery requests and responses. 2777 | DISCOVERY_CHANNEL = 65531 2778 | -- If set to true CryptoNet will also broadcast all messages over the Rednet 2779 | -- reapter channel, which allows CryptoNet messages to be repeated by the built-in 2780 | -- program repeat. Disabling this is a little more secure as an attacker won't know 2781 | -- which channel you are communicating over. 2782 | local repeatMessages = true 2783 | -- Whether to print log messages or not. 2784 | local loggingEnabled = true 2785 | -- Directory CryptoNet looks for files in. 2786 | local workingDir = "" 2787 | -- All servers currently open on this computer. 2788 | local allServers = {} 2789 | -- All client sockets (opened with connect()) open on this computer. 2790 | local allClientSockets = {} 2791 | 2792 | 2793 | local function log(message) 2794 | if loggingEnabled then 2795 | print("[CryptoNet] "..message) 2796 | end 2797 | end 2798 | 2799 | 2800 | -- 2801 | -- ACCESSORS 2802 | -- 2803 | 2804 | function getLoggingEnabled() 2805 | return loggingEnabled 2806 | end 2807 | 2808 | 2809 | function setLoggingEnabled(enabled) 2810 | loggingEnabled = enabled 2811 | end 2812 | 2813 | 2814 | function getRepeatMessages() 2815 | return repeatMessages 2816 | end 2817 | 2818 | 2819 | function setRepeatMessages(repMsgs) 2820 | repeatMessages = repMsgs 2821 | end 2822 | 2823 | 2824 | function getWorkingDirectory() 2825 | return workingDir 2826 | end 2827 | 2828 | 2829 | function setWorkingDirectory(dir) 2830 | if type(dir) ~= "string" then 2831 | error("Directory must be a string.", 2) 2832 | end 2833 | workingDir = dir 2834 | end 2835 | 2836 | 2837 | function getAllServers() 2838 | return allServers 2839 | end 2840 | 2841 | 2842 | function getAllClientSockets() 2843 | return allClientSockets 2844 | end 2845 | 2846 | 2847 | -- 2848 | -- VALIDITY CHECKS 2849 | -- 2850 | 2851 | -- Check that the key is a 16 element table of numbers. 2852 | function keyValid(key) 2853 | if not (type(key) == "table" and #key == 16) then 2854 | return false 2855 | end 2856 | -- Make sure all elements are numbers. 2857 | for _,v in pairs(key) do 2858 | if type(v) ~= "number" then 2859 | return false 2860 | end 2861 | end 2862 | return true 2863 | end 2864 | 2865 | 2866 | -- Check that a table has all the parts required to be a valid private key. 2867 | function privateKeyValid(key) 2868 | return type(key) == "table" and type(key.private) == "string" and type(key.shared) == "string" 2869 | end 2870 | 2871 | 2872 | -- Check that a table has all the parts required to be a valid public key. 2873 | function publicKeyValid(key) 2874 | return type(key) == "table" and type(key.public) == "string" and type(key.shared) == "string" 2875 | end 2876 | 2877 | 2878 | -- Check that a table has all the parts required to be a valid server certificate. 2879 | -- If ignoreKey is true it is acceptable for a server to have no key, 2880 | -- but if present it must be valid. 2881 | -- The signature is always optional but must be valid (syntactically, 2882 | -- it isn't actually verified here) if present. 2883 | function certificateValid(certificate, ignoreKey) 2884 | -- All certificates must contain the server name. 2885 | if type(certificate) ~= "table" or type(certificate.name) ~= "string" then 2886 | return false 2887 | end 2888 | 2889 | -- A certificate must contain the server's public key, unless ignoreKey is true. 2890 | if certificate.key == nil and not ignoreKey then 2891 | return false 2892 | end 2893 | -- Ensure that the public key is valid, if present. 2894 | if certificate.key ~= nil and not publicKeyValid(certificate.key) then 2895 | return false 2896 | end 2897 | 2898 | -- A certificate should only have a signature if it also contains a key. 2899 | if certificate.key == nil and certificate.signature ~= nil then 2900 | return false 2901 | end 2902 | -- If a signature is present (which it doesn't need to be), it must be a string. 2903 | if certificate.signature ~= nil and type(certificate.signature) ~= "string" then 2904 | return false 2905 | end 2906 | 2907 | return true 2908 | end 2909 | 2910 | 2911 | -- Check that a table has everything it needs to be a valid server. 2912 | function serverValid(server) 2913 | return type(server) == "table" 2914 | and type(server.name) == "string" 2915 | and certificateValid(server.certificate) 2916 | and privateKeyValid(server.privateKey) 2917 | and type(server.modemSide) == "string" 2918 | and type(server.channel) == "number" 2919 | and type(server.userTable) == "table" 2920 | and type(server.userTablePath) == "string" 2921 | and type(server.sockets) == "table" 2922 | end 2923 | 2924 | 2925 | -- Check that a table has everything it needs to be a valid socket. 2926 | function socketValid(socket) 2927 | return type(socket) == "table" 2928 | and type(socket.sender) == "string" 2929 | and type(socket.target) == "string" 2930 | and keyValid(socket.key) 2931 | and type(socket.modemSide) == "string" 2932 | and type(socket.channel) == "number" 2933 | and type(socket.permissionLevel) == "number" 2934 | and type(socket.receivedMessages) == "table" 2935 | end 2936 | 2937 | 2938 | -- Check that all the entries in a user table are valid. 2939 | function userTableValid(userTable) 2940 | if type(userTable) ~= "table" then 2941 | return false 2942 | end 2943 | for username,entry in pairs(userTable) do 2944 | if type(username) ~= "string" or type(entry[1]) ~= "table" or type(entry[2]) ~= "number" then 2945 | return false 2946 | end 2947 | end 2948 | return true 2949 | end 2950 | 2951 | 2952 | -- 2953 | -- HELPERS 2954 | -- 2955 | 2956 | -- Used to process modem side arguments passed to functions. 2957 | function resolveModemSide(modemSide) 2958 | -- If no modem side argument is provided, search for a modem and use that side. 2959 | if modemSide == nil then 2960 | for _,side in pairs(peripheral.getNames()) do 2961 | if peripheral.getType(side) == "modem" then 2962 | modemSide = side 2963 | break 2964 | end 2965 | end 2966 | if modemSide == nil then 2967 | error("Could not find a modem.", 3) 2968 | end 2969 | else 2970 | -- If an argument was provided, check that it is a valid side. 2971 | local found = false 2972 | for _,side in pairs(redstone.getSides()) do 2973 | if side == modemSide then 2974 | found = true 2975 | break 2976 | end 2977 | end 2978 | if not found then 2979 | error(tostring(modemSide).." is not a valid side.", 3) 2980 | end 2981 | end 2982 | if peripheral.getType(modemSide) ~= "modem" then 2983 | error("No modem on side "..modemSide..".", 3) 2984 | end 2985 | 2986 | log("Using modem "..modemSide..".") 2987 | return modemSide 2988 | end 2989 | 2990 | 2991 | -- Decides which channel a server should communicate on, based on its name. 2992 | -- This function will always return the same channel for a given server name, 2993 | -- allowing clients to find out the channel of a server without any prior 2994 | -- communications with it. 2995 | function getChannel(serverName) 2996 | local nameHash = sha256.digest(serverName) 2997 | -- Use the first two bytes of the hash as the channel number, so that the full range 2998 | -- of acceptable channels can be used. 2999 | local channel = nameHash[1] + nameHash[2]*2^8 3000 | -- Avoid clashing with the lower channels, which are likely being used by 3001 | -- standard Rednet users. 3002 | if channel < 100 then 3003 | channel = channel + 100 3004 | -- Reserve the highest channels for Rednet and CryptoNet's internal use. 3005 | elseif channel > 65530 then 3006 | channel = channel - 5 3007 | end 3008 | 3009 | return channel 3010 | end 3011 | 3012 | 3013 | -- Check if any servers or sockets on this machine are using the specified channel 3014 | -- on the specified modem. 3015 | function channelInUse(channel, modemSide) 3016 | -- Check the client sockets. 3017 | for _,socket in pairs(allClientSockets) do 3018 | if socket.channel == channel and socket.modemSide == modemSide then 3019 | return true 3020 | end 3021 | end 3022 | -- Check the server channels. 3023 | for _,server in pairs(allServers) do 3024 | if server.channel == channel and server.modemSide == modemSide then 3025 | return true 3026 | end 3027 | end 3028 | 3029 | return false 3030 | end 3031 | 3032 | 3033 | -- Convert a table of bytes into a string. 3034 | local function bytesToString(bytes) 3035 | local str = "" 3036 | for _,byte in pairs(bytes) do 3037 | local ok, char = pcall(string.char, byte) 3038 | -- If there are invalid bytes in the string, return nil without raising an error. 3039 | -- This is to prevent attackers from crashing the system by sending invalid characters 3040 | -- in encrypted messages. 3041 | if not ok then 3042 | return nil 3043 | end 3044 | str = str..char 3045 | end 3046 | return str 3047 | end 3048 | 3049 | 3050 | -- Serialize pretty much any Lua data type as a string so that it can be encrypted 3051 | -- and sent over CryptoNet. The resulting string starts with a characer 3052 | -- identifying the type of the data, followed by a string representation of the data. 3053 | local function serializeAny(value) 3054 | if type(value) == "nil" then 3055 | return "x" 3056 | elseif type(value) == "boolean" then 3057 | return value and "b1" or "b0" 3058 | elseif type(value) == "number" then 3059 | return "n"..tostring(value) 3060 | elseif type(value) == "string" then 3061 | return "s"..value 3062 | elseif type(value) == "table" then 3063 | return "t"..textutils.serialize(value) 3064 | else 3065 | error("Can't serialize "..type(value).."s.", 2) 3066 | end 3067 | end 3068 | 3069 | 3070 | -- Deserialize data serialized by serializeAny. 3071 | local function deserializeAny(str) 3072 | local typeChar = str:sub(1,1) 3073 | local valueStr = str:sub(2) 3074 | if typeChar == "x" then 3075 | return nil 3076 | elseif typeChar == "b" then 3077 | return valueStr == "1" 3078 | elseif typeChar == "n" then 3079 | return tonumber(valueStr) 3080 | elseif typeChar == "s" then 3081 | return valueStr 3082 | elseif typeChar == "t" then 3083 | return textutils.unserialize(valueStr) 3084 | else 3085 | error("Invalid type character: "..typeChar, 2) 3086 | end 3087 | end 3088 | 3089 | 3090 | -- Serialize a certificate or RSA key into a string, for saving to a file. 3091 | -- The textutils functions don't seem to like the huge strings of numbers in 3092 | -- the keys, so quotation marks must be added to them before serialization, 3093 | -- which is what this function does. 3094 | function serializeCertOrKey(obj) 3095 | if type(obj) ~= "table" then 3096 | error("Can only serialize tables.", 2) 3097 | end 3098 | -- Add the certificate name, if it exists. 3099 | local output = {name=obj.name} 3100 | 3101 | -- If this is a key, add its number string parts with quotes around them 3102 | -- to keep textutils happy. 3103 | if type(obj.public) == "string" then 3104 | output.public = "\""..obj.public.."\"" 3105 | end 3106 | if type(obj.private) == "string" then 3107 | output.private = "\""..obj.private.."\"" 3108 | end 3109 | if type(obj.shared) == "string" then 3110 | output.shared = "\""..obj.shared.."\"" 3111 | end 3112 | 3113 | -- If this is a certificate with a key, do the above for the key. 3114 | if type(obj.key) == "table" then 3115 | output.key = {} 3116 | if type(obj.key.public) == "string" then 3117 | output.key.public = "\""..obj.key.public.."\"" 3118 | end 3119 | if type(obj.key.private) == "string" then 3120 | output.key.private = "\""..obj.key.private.."\"" 3121 | end 3122 | if type(obj.key.shared) == "string" then 3123 | output.key.shared = "\""..obj.key.shared.."\"" 3124 | end 3125 | end 3126 | 3127 | -- If the certificate has a signature, that must have quotes as well. 3128 | if type(obj.signature) == "string" then 3129 | output.signature = "\""..obj.signature.."\"" 3130 | end 3131 | 3132 | -- Serialize the table as normal. 3133 | return textutils.serialize(output) 3134 | end 3135 | 3136 | 3137 | -- Deserialize certificates or RSA keys serialized by serializeCertOrKey(). 3138 | -- This involves deserializing as normal and removing the quotation marks added 3139 | -- during serialization. 3140 | function deserializeCertOrKey(str) 3141 | if str == nil then return nil end 3142 | -- Deserialize as normal. 3143 | local output = textutils.unserialize(str) 3144 | if type(output) ~= "table" then 3145 | return output 3146 | end 3147 | 3148 | -- If this is a key, remove the quotes from the number string parts. 3149 | if type(output.public) == "string" then 3150 | output.public = string.gsub(output.public, "\"", "") 3151 | end 3152 | if type(output.private) == "string" then 3153 | output.private = string.gsub(output.private, "\"", "") 3154 | end 3155 | if type(output.shared) == "string" then 3156 | output.shared = string.gsub(output.shared, "\"", "") 3157 | end 3158 | 3159 | -- If this is a certificate with a key, do the above for the key. 3160 | if output.key ~= nil then 3161 | if type(output.key.public) == "string" then 3162 | output.key.public = string.gsub(output.key.public, "\"", "") 3163 | end 3164 | if type(output.key.private) == "string" then 3165 | output.key.private = string.gsub(output.key.private, "\"", "") 3166 | end 3167 | if type(output.key.shared) == "string" then 3168 | output.key.shared = string.gsub(output.key.shared, "\"", "") 3169 | end 3170 | end 3171 | 3172 | if type(output.signature) == "string" then 3173 | output.signature = string.gsub(output.signature, "\"", "") 3174 | end 3175 | 3176 | return output 3177 | end 3178 | 3179 | 3180 | -- Generate random 16 byte sequence that can be used as a key or 3181 | -- initialization vector for AES encryption. 3182 | function generateKey() 3183 | local iv = {} 3184 | -- Convert four 4-byte integers into 16 bytes. 3185 | for j=1,4 do 3186 | local num = isaac.random() 3187 | for i=0,3 do 3188 | -- Extract 8 bits at a time, by shifting right and applying a mask. 3189 | table.insert(iv, bit.band(bit.brshift(num, 8*i), 2^8-1)) 3190 | end 3191 | end 3192 | return iv 3193 | end 3194 | 3195 | 3196 | -- Generate an unsigned certificate and corresponding private key for a server 3197 | -- with the given name. The certificate is distributed to clients, who can use 3198 | -- the public key it contains to encrypt messages using RSA such that only 3199 | -- this server can read them, using the private key. 3200 | function generateCertificate(name) 3201 | log("Generating keys... (may take some time)") 3202 | publicKey, privateKey = rsaKeygen.generateKeyPair() 3203 | print("") 3204 | log("Done!") 3205 | -- The certificate contains the name and public key of the server. 3206 | return {name=name, key=publicKey}, privateKey 3207 | end 3208 | 3209 | 3210 | -- Load a certificate authority public key from the specified file and validate it, 3211 | -- or just validate the key itself if passed directly as the argument. 3212 | -- If key is left nil, a default filename of "certAuth.key" is used. 3213 | -- 3214 | -- key (string or key table, default: "certAuth.key"): 3215 | -- The file to load the key from, or the key itself to validate. 3216 | -- 3217 | -- Returns the loaded key, or nil if not found or invalid. 3218 | function loadCertAuthKey(key) 3219 | if key == nil then 3220 | -- Default value. 3221 | key = "certAuth.key" 3222 | end 3223 | -- If key is a file path... 3224 | if type(key) == "string" then 3225 | local keyFilename = key 3226 | -- Make paths relative to the current CryptoNet working directory. 3227 | local keyPath = workingDir == "" and keyFilename or workingDir.."/"..keyFilename 3228 | log("Checking "..keyPath.." for cert auth key...") 3229 | if fs.isDir(keyPath) or not fs.exists(keyPath) then 3230 | if fs.isDir(keyPath) then 3231 | log(keyFilename.." is not a file, will not be able to verify signatures.") 3232 | else 3233 | log(keyFilename.." does not exist, will not be able to verify signatures.") 3234 | end 3235 | return nil 3236 | else 3237 | local file = fs.open(keyPath, "r") 3238 | key = deserializeCertOrKey(file.readAll()) 3239 | file.close() 3240 | 3241 | if not publicKeyValid(key) then 3242 | log(keyFilename.." does not contain a valid cert auth key, will not be able to verify signatures.") 3243 | return nil 3244 | else 3245 | log("Loaded cert auth key from "..keyFilename..".") 3246 | return key 3247 | end 3248 | end 3249 | -- If the argument is not a string it should be the key table itself, 3250 | -- so just validate it and return unchanged if valid. 3251 | elseif publicKeyValid(key) then 3252 | return key 3253 | else 3254 | log("Invalid cert auth key, won't be able to verify signatures.") 3255 | return nil 3256 | end 3257 | end 3258 | 3259 | 3260 | -- Verify that the signature on a certificate is valid, using the public key 3261 | -- of the trusted certificate authority. 3262 | function verifyCertificate(certificate, key) 3263 | -- Signatures are made by encrypting the certificate's hash using the cert auth's private key. 3264 | -- If the signature was generated by the certificate authority that uses the provided public key, 3265 | -- decrypting the signature with this key should yield the certificate's hash. 3266 | 3267 | -- Find the hash of the certificate. 3268 | local hash = sha256.digest(certificate.name..certificate.key.public..certificate.key.shared) 3269 | -- Decrypt the signature using the provided public key. 3270 | local sigHash = rsaCrypt.bytesToString(rsaCrypt.numberToBytes(rsaCrypt.crypt(key, certificate.signature), 32*8, 8)) 3271 | -- See whether the decrypted signature matches the expected hash. 3272 | return tostring(hash) == sigHash 3273 | end 3274 | 3275 | 3276 | -- 3277 | -- SEND FUNCTIONS 3278 | -- 3279 | 3280 | -- Send an unencrypted message in the Rednet format using the cryptoNet protocol. 3281 | -- CryptoNet uses this internally for sending various message types. 3282 | -- If enabled, this function will also send every message it sends on the Rednet 3283 | -- repeat channel, allowing the Rednet repeat command to repeat CryptoNet messages. 3284 | -- Since these messages are in the format Rednet uses, CryptoNet should be fully 3285 | -- compatible with any networking systems designed for Rednet. 3286 | local function sendInternal(modemSide, channel, target, message, msgType, sender) 3287 | -- Generate the message in exactly the same format as Rednet. 3288 | local nMessageID = math.random(1, 2147483647) 3289 | local tMessage = { 3290 | nMessageID = nMessageID, 3291 | nRecipient = channel, 3292 | message = {message=message, msgType=msgType, target=target, sender=sender}, 3293 | sProtocol = "cryptoNet", 3294 | } 3295 | 3296 | local modem = peripheral.wrap(modemSide) 3297 | modem.transmit(channel, channel, tMessage) 3298 | -- Allow Rednet repeaters to repeat the message if enabled. 3299 | if repeatMessages then 3300 | modem.transmit(rednet.CHANNEL_REPEAT, channel, tMessage) 3301 | end 3302 | end 3303 | 3304 | 3305 | -- Send an encrypted internal message. Unlike the user-facing send() function, 3306 | -- this one only allows strings to be sent. 3307 | local function sendEncryptedInternal(socket, message) 3308 | if type(message) ~= "string" then 3309 | error("Message must be a string.", 2) 3310 | end 3311 | if not socketValid(socket) then 3312 | error("Invalid socket.", 2) 3313 | end 3314 | -- Use unique IVs for every message. 3315 | local iv = generateKey() 3316 | local ok, encrypted = pcall(aes.encrypt_str, message, socket.key, iv) 3317 | if ok then 3318 | -- Send the encrypted message and the IVs used to generate it. 3319 | -- We have to send the encrypted string as a table of bytes, because some of 3320 | -- the special characters in the string seem to get lost in transmission otherwise. 3321 | sendInternal(socket.modemSide, socket.channel, socket.target, {{string.byte(encrypted, 1, encrypted:len())}, iv}, "encrypted_message", socket.sender) 3322 | else 3323 | error("Encryption failed: "..encrypted:sub(8), 2) 3324 | end 3325 | end 3326 | 3327 | 3328 | -- Send an encrypted message over the given socket. The message can be pretty much 3329 | -- any Lua data type. 3330 | function send(socket, message) 3331 | if not socketValid(socket) then 3332 | error("Invalid socket.", 2) 3333 | end 3334 | -- Convert the message to a string before sending, so it can be encrypted. 3335 | -- It will be deserialized at the other end. 3336 | sendEncryptedInternal(socket, serializeAny(message)) 3337 | end 3338 | 3339 | 3340 | -- Send an unencrypted message over CryptoNet. Useful for streams of high speed, 3341 | -- non-sensitive data. Unencrypted messages have no security features applied, 3342 | -- so can be easily exploited by attackers. Only use for non-critical messages. 3343 | function sendUnencrypted(socket, message) 3344 | if not socketValid(socket) then 3345 | error("Invalid socket.", 2) 3346 | end 3347 | -- Just send the message as-is. 3348 | sendInternal(socket.modemSide, socket.channel, socket.target, message, "plain_message", socket.sender) 3349 | end 3350 | 3351 | 3352 | -- 3353 | -- LOGIN SYSTEM 3354 | -- 3355 | 3356 | -- Hash a password using the username and server name as a salt. 3357 | -- Used to secure passwords before they are sent over CryptoNet to a server. 3358 | -- Technically this is unnecessary as the connection is encrypted anyway, 3359 | -- but it means that even if this is somehow compromised (e.g. with a spoof attack) 3360 | -- the attacker won't know the actual password and be able to use it on the user's 3361 | -- other accounts, if they use the same password for multiple things. 3362 | function hashPassword(username, password, serverName) 3363 | if type(username) ~= "string" then 3364 | error("Username must be a string.", 2) 3365 | end 3366 | if type(password) ~= "string" then 3367 | error("Password must be a string.", 2) 3368 | end 3369 | if type(serverName) ~= "string" then 3370 | error("Server name must be a string.", 2) 3371 | end 3372 | 3373 | return tostring(sha256.digest(serverName..username..password)) 3374 | end 3375 | 3376 | 3377 | -- Load the user table stored at the given path, defaulting to an empty table 3378 | -- if the file does not exist. 3379 | function loadUserTable(path) 3380 | if type(path) ~= "string" then 3381 | error("Path must be a string.", 2) 3382 | end 3383 | if not fs.exists(path) then 3384 | log(path.." does not exist, creating empty user table.") 3385 | return {} 3386 | end 3387 | if fs.isDir(path) then 3388 | error(path.." is not a file, could not load user table.", 2) 3389 | end 3390 | 3391 | local file = fs.open(path, "r") 3392 | local userTable = textutils.unserialize(file.readAll()) 3393 | file.close() 3394 | 3395 | if not userTableValid(userTable) then 3396 | error(path.." does not contain a valid user table, user table could not be loaded.", 2) 3397 | end 3398 | 3399 | log("Loaded user table from "..path..".") 3400 | return userTable 3401 | end 3402 | 3403 | 3404 | -- Save the given user table to the given file. 3405 | function saveUserTable(userTable, path) 3406 | if type(path) ~= "string" then 3407 | error("Path must be a string.", 2) 3408 | end 3409 | if not userTableValid(userTable) then 3410 | error("Not a valid user table", 2) 3411 | end 3412 | 3413 | if fs.isDir(path) then 3414 | error(path.." already exists and is a directory.", 2) 3415 | end 3416 | 3417 | local file = fs.open(path, "w") 3418 | file.write(textutils.serialize(userTable)) 3419 | file.close() 3420 | log("Saved user table to "..path..".") 3421 | end 3422 | 3423 | 3424 | -- Add a user to the given server with the provided details. 3425 | -- The provided password should already have been hashed by hashPassword(). 3426 | -- Default permission level is 1. If there is only one server running, 3427 | -- that server will be used by default. 3428 | function addUserHashed(username, passHash, permissionLevel, server) 3429 | if type(username) ~= "string" then 3430 | error("Username must be a string.", 2) 3431 | end 3432 | if type(passHash) ~= "string" then 3433 | error("Password hash must be a string.", 2) 3434 | end 3435 | if permissionLevel == nil then 3436 | permissionLevel = 1 3437 | elseif type(permissionLevel) ~= "number" then 3438 | error("Permission level must be a number", 2) 3439 | end 3440 | 3441 | -- If there is exactly one server running, default to it. 3442 | if server == nil then 3443 | if #allServers == 0 then 3444 | error("No servers running.", 2) 3445 | elseif #allServers == 1 then 3446 | server = allServers[1] 3447 | else 3448 | error("Please specify a server.", 2) 3449 | end 3450 | elseif not serverValid(server) then 3451 | error("Invalid server.", 2) 3452 | end 3453 | 3454 | if server.userTable[username] ~= nil then 3455 | error("User "..username.." already exists.", 2) 3456 | end 3457 | 3458 | -- The password is hashed again before going in the database, so that even if 3459 | -- an attacker has access to this file they do not have the original password 3460 | -- required to log into the server from the outside. 3461 | -- PBKDF2 is used over the standard SHA256 digest as it is theoretically harder 3462 | -- to crack. 3463 | server.userTable[username] = {sha256.pbkdf2(passHash, server.name..username, 8), permissionLevel} 3464 | log("Added user "..username..".") 3465 | saveUserTable(server.userTable, server.userTablePath) 3466 | end 3467 | 3468 | 3469 | -- Add a user to the given (local) server's user table with the provided details. 3470 | -- The user table is saved to disk, so is non volatile. 3471 | -- The server parameter can be left blank if exactly one server is running. 3472 | function addUser(username, password, permissionLevel, server) 3473 | if type(username) ~= "string" then 3474 | error("Username must be a string.", 2) 3475 | end 3476 | if type(password) ~= "string" then 3477 | error("Password must be a string.", 2) 3478 | end 3479 | if permissionLevel == nil then 3480 | permissionLevel = 1 3481 | elseif type(permissionLevel) ~= "number" then 3482 | error("Permission level must be a number", 2) 3483 | end 3484 | 3485 | -- If there is exactly one server running, default to it. 3486 | if server == nil then 3487 | if #allServers == 0 then 3488 | error("No servers running.", 2) 3489 | elseif #allServers == 1 then 3490 | server = allServers[1] 3491 | else 3492 | error("Please specify a server.", 2) 3493 | end 3494 | elseif not serverValid(server) then 3495 | error("Invalid server.", 2) 3496 | end 3497 | 3498 | if server.userTable[username] ~= nil then 3499 | error("User "..username.." already exists.", 2) 3500 | end 3501 | 3502 | -- When users log into the server remotely their passwords will be hashed 3503 | -- before being sent, so we must perform the same process here before 3504 | -- adding it to the table. 3505 | addUserHashed(username, hashPassword(username, password, server.name), permissionLevel, server) 3506 | end 3507 | 3508 | 3509 | -- Remove a user from a server. 3510 | -- The server parameter can be left blank if exactly one server is running. 3511 | function deleteUser(username, server) 3512 | if type(username) ~= "string" then 3513 | error("Username must be a string.", 2) 3514 | end 3515 | 3516 | -- If there is exactly one server running, default to it. 3517 | if server == nil then 3518 | if #allServers == 0 then 3519 | error("No servers running.", 2) 3520 | elseif #allServers == 1 then 3521 | server = allServers[1] 3522 | else 3523 | error("Please specify a server.", 2) 3524 | end 3525 | elseif not serverValid(server) then 3526 | error("Invalid server.", 2) 3527 | end 3528 | 3529 | if server.userTable[username] == nil then 3530 | error("No user called "..username..".", 2) 3531 | else 3532 | server.userTable[username] = nil 3533 | log("Deleted user "..username..".") 3534 | saveUserTable(server.userTable, server.userTablePath) 3535 | end 3536 | end 3537 | 3538 | 3539 | -- Check if a user exists on the server. 3540 | -- The server parameter can be left blank if exactly one server is running. 3541 | function userExists(username, server) 3542 | if type(username) ~= "string" then 3543 | error("Username must be a string.", 2) 3544 | end 3545 | 3546 | -- If there is exactly one server running, default to it. 3547 | if server == nil then 3548 | if #allServers == 0 then 3549 | error("No servers running.", 2) 3550 | elseif #allServers == 1 then 3551 | server = allServers[1] 3552 | else 3553 | error("Please specify a server.", 2) 3554 | end 3555 | elseif not serverValid(server) then 3556 | error("Invalid server.", 2) 3557 | end 3558 | 3559 | return server.userTable[username] ~= nil 3560 | end 3561 | 3562 | 3563 | -- Get the hashed password of a user from the users table. 3564 | -- The original password cannot be (easily) retrieved from this hash. 3565 | -- Returns nil if the user does not exist. 3566 | -- The server parameter can be left blank if exactly one server is running. 3567 | function getPasswordHash(username, server) 3568 | if type(username) ~= "string" then 3569 | error("Username must be a string.", 2) 3570 | end 3571 | 3572 | -- If there is exactly one server running, default to it. 3573 | if server == nil then 3574 | if #allServers == 0 then 3575 | error("No servers running.", 2) 3576 | elseif #allServers == 1 then 3577 | server = allServers[1] 3578 | else 3579 | error("Please specify a server.", 2) 3580 | end 3581 | elseif not serverValid(server) then 3582 | error("Invalid server.", 2) 3583 | end 3584 | 3585 | if server.userTable[username] == nil then 3586 | return nil 3587 | end 3588 | return server.userTable[username][1] 3589 | end 3590 | 3591 | 3592 | -- Get the permission level of a user. 3593 | -- Returns nil if the user does not exist. 3594 | -- The server parameter can be left blank if exactly one server is running. 3595 | function getPermissionLevel(username, server) 3596 | if type(username) ~= "string" then 3597 | error("Username must be a string.", 2) 3598 | end 3599 | 3600 | -- If there is exactly one server running, default to it. 3601 | if server == nil then 3602 | if #allServers == 0 then 3603 | error("No servers running.", 2) 3604 | elseif #allServers == 1 then 3605 | server = allServers[1] 3606 | else 3607 | error("Please specify a server.", 2) 3608 | end 3609 | elseif not serverValid(server) then 3610 | error("Invalid server.", 2) 3611 | end 3612 | 3613 | if server.userTable[username] == nil then 3614 | return nil 3615 | end 3616 | return server.userTable[username][2] 3617 | end 3618 | 3619 | 3620 | -- Set the hashed password of a user in the table. 3621 | -- Assumes the provided passowrd has already been hashed with hashPassword(). 3622 | -- The server parameter can be left blank if exactly one server is running. 3623 | function setPasswordHashed(username, passHash, server) 3624 | if type(username) ~= "string" then 3625 | error("Username must be a string.", 2) 3626 | end 3627 | if type(passHash) ~= "string" then 3628 | error("Password hash must be a string.", 2) 3629 | end 3630 | 3631 | -- If there is exactly one server running, default to it. 3632 | if server == nil then 3633 | if #allServers == 0 then 3634 | error("No servers running.", 2) 3635 | elseif #allServers == 1 then 3636 | server = allServers[1] 3637 | else 3638 | error("Please specify a server.", 2) 3639 | end 3640 | elseif not serverValid(server) then 3641 | error("Invalid server.", 2) 3642 | end 3643 | 3644 | if server.userTable[username] == nil then 3645 | error("No user called "..username..".", 2) 3646 | end 3647 | 3648 | -- Hash the password again before storing. 3649 | server.userTable[username][1] = sha256.pbkdf2(passHash, server.name..username, 8) 3650 | log("Updated password for "..username..".") 3651 | saveUserTable(server.userTable, server.userTablePath) 3652 | end 3653 | 3654 | 3655 | -- Sets the password of a user in the table. 3656 | -- The server parameter can be left blank if exactly one server is running. 3657 | function setPassword(username, password, server) 3658 | if type(username) ~= "string" then 3659 | error("Username must be a string.", 2) 3660 | end 3661 | if type(password) ~= "string" then 3662 | error("Password must be a string.", 2) 3663 | end 3664 | 3665 | -- If there is exactly one server running, default to it. 3666 | if server == nil then 3667 | if #allServers == 0 then 3668 | error("No servers running.", 2) 3669 | elseif #allServers == 1 then 3670 | server = allServers[1] 3671 | else 3672 | error("Please specify a server.", 2) 3673 | end 3674 | elseif not serverValid(server) then 3675 | error("Invalid server.", 2) 3676 | end 3677 | 3678 | if server.userTable[username] == nil then 3679 | error("No user called "..username..".", 2) 3680 | end 3681 | 3682 | -- Hash the password before adding, to mimic the hashing performed by clients 3683 | -- logging in remotely. 3684 | setPasswordHashed(username, hashPassword(username, password, server.name), server) 3685 | end 3686 | 3687 | 3688 | -- Set the permission level of a user in the table. 3689 | -- The server parameter can be left blank if exactly one server is running. 3690 | function setPermissionLevel(username, permissionLevel, server) 3691 | if type(username) ~= "string" then 3692 | error("Username must be a string.", 2) 3693 | end 3694 | if type(permissionLevel) ~= "number" then 3695 | error("Permission level must be a number.", 2) 3696 | end 3697 | 3698 | -- If there is exactly one server running, default to it. 3699 | if server == nil then 3700 | if #allServers == 0 then 3701 | error("No servers running.", 2) 3702 | elseif #allServers == 1 then 3703 | server = allServers[1] 3704 | else 3705 | error("Please specify a server.", 2) 3706 | end 3707 | elseif not serverValid(server) then 3708 | error("Invalid server.", 2) 3709 | end 3710 | 3711 | if server.userTable[username] == nil then 3712 | error("No user called "..username..".", 2) 3713 | end 3714 | 3715 | server.userTable[username][2] = permissionLevel 3716 | log("Updated permission level for "..username..".") 3717 | saveUserTable(server.userTable, server.userTablePath) 3718 | end 3719 | 3720 | 3721 | -- Check that the given password matches the one in the table. 3722 | -- Assumes the password has already been hashed by hashPassword(). 3723 | -- The server parameter can be left blank if exactly one server is running. 3724 | function checkPasswordHashed(username, passHash, server) 3725 | if type(username) ~= "string" then 3726 | error("Username must be a string.", 2) 3727 | end 3728 | if type(passHash) ~= "string" then 3729 | error("Password hash must be a string.", 2) 3730 | end 3731 | 3732 | -- If there is exactly one server running, default to it. 3733 | if server == nil then 3734 | if #allServers == 0 then 3735 | error("No servers running.", 2) 3736 | elseif #allServers == 1 then 3737 | server = allServers[1] 3738 | else 3739 | error("Please specify a server.", 2) 3740 | end 3741 | elseif not serverValid(server) then 3742 | error("Invalid server.", 2) 3743 | end 3744 | 3745 | if server.userTable[username] == nil then 3746 | return nil 3747 | end 3748 | 3749 | -- Since we can't unhash the passwords in the table, we must instead 3750 | -- hash the query password and compare it to the hash in the table. 3751 | -- If they are the same, then the original passwords were the same. 3752 | local hash = sha256.pbkdf2(passHash, server.name..username, 8) 3753 | -- Check if all the bytes of the hashes are equal. 3754 | for i=1,#hash do 3755 | if hash[i] ~= server.userTable[username][1][i] then 3756 | return false 3757 | end 3758 | end 3759 | return true 3760 | end 3761 | 3762 | 3763 | -- Check that the given password matches the one in the table. 3764 | -- The server parameter can be left blank if exactly one server is running. 3765 | function checkPassword(username, password, server) 3766 | if type(username) ~= "string" then 3767 | error("Username must be a string.", 2) 3768 | end 3769 | if type(password) ~= "string" then 3770 | error("Password must be a string.", 2) 3771 | end 3772 | 3773 | -- If there is exactly one server running, default to it. 3774 | if server == nil then 3775 | if #allServers == 0 then 3776 | error("No servers running.", 2) 3777 | elseif #allServers == 1 then 3778 | server = allServers[1] 3779 | else 3780 | error("Please specify a server.", 2) 3781 | end 3782 | elseif not serverValid(server) then 3783 | error("Invalid server.", 2) 3784 | end 3785 | 3786 | -- Mimic the client-side hashing before checking. 3787 | return checkPasswordHashed(username, hashPassword(username, password, server.name), server) 3788 | end 3789 | 3790 | 3791 | -- Log into the server connected to this socket, remote or local, 3792 | -- with the specified username and password. 3793 | -- Assumes the password has already been hashed by hashPassword(). 3794 | -- If executed on a server socket, the event details of the attempt are returned. 3795 | -- 3796 | -- If successful, the user's details will be stored in the socket. 3797 | -- If the socket is already logged in, the username will be overwritten 3798 | -- but the permission level will be set to the highest of the old and new one. 3799 | -- This allows an admin account to log in then log in as a normal user 3800 | -- to temporarily gain elevated privileges as that account. 3801 | function loginHashed(socket, username, passHash) 3802 | if not socketValid(socket) then 3803 | error("Invalid socket.", 2) 3804 | end 3805 | if type(username) ~= "string" then 3806 | error("Username must be a string.", 2) 3807 | end 3808 | if type(passHash) ~= "string" then 3809 | error("Password hash must be a string.", 2) 3810 | end 3811 | 3812 | if socket.server == nil then 3813 | -- If this is a client socket, send a login request to the server. 3814 | sendEncryptedInternal(socket, "lr"..textutils.serialize({username, passHash})) 3815 | log("Sent login request for "..username.." to "..socket.target..".") 3816 | else 3817 | -- If this is a server socket, try to log in as the user 3818 | -- and send the result to the client. 3819 | if socket.server.userTable[username] == nil then 3820 | log("Failed login attempt for "..username..".") 3821 | sendEncryptedInternal(socket, "lf"..username) 3822 | return "login_failed", username, socket, socket.server 3823 | else 3824 | if checkPasswordHashed(username, passHash, socket.server) then 3825 | -- If the password was correct, log the user into the socket. 3826 | socket.username = username 3827 | -- Set the permission level to the greatest of the socket's original 3828 | -- permission level and the new one, so admins can temporarily transfer 3829 | -- their elevated rights to normal accounts. 3830 | socket.permissionLevel = math.max(socket.permissionLevel, getPermissionLevel(username, socket.server)) 3831 | -- Tell the client-side socket that the attempt was successful, so it can 3832 | -- change its details as well. 3833 | sendEncryptedInternal(socket, "ls"..textutils.serialize({username, socket.permissionLevel})) 3834 | log(username.." logged in successfully.") 3835 | return "login", username, socket, socket.server 3836 | else 3837 | log("Failed login attempt for "..username..".") 3838 | sendEncryptedInternal(socket, "lf"..username) 3839 | return "login_failed", username, socket, socket.server 3840 | end 3841 | end 3842 | end 3843 | end 3844 | 3845 | 3846 | -- Log into the server connected to this socket, remote or local, 3847 | -- with the specified username and password. 3848 | -- The password will be hashed before sending for extra security. 3849 | -- If executed on a server socket, the event details of the attempt are returned. 3850 | -- 3851 | -- If successful, the user's details will be stored in the socket. 3852 | -- If the socket is already logged in, the username will be overwritten 3853 | -- but the permission level will be set to the highest of the old and new one. 3854 | -- This allows an admin account to log in then log in as a normal user 3855 | -- to temporarily gain elevated privileges as that account. 3856 | function login(socket, username, password) 3857 | if not socketValid(socket) then 3858 | error("Invalid socket.", 2) 3859 | end 3860 | if type(username) ~= "string" then 3861 | error("Username must be a string.", 2) 3862 | end 3863 | if type(password) ~= "string" then 3864 | error("Password must be a string.", 2) 3865 | end 3866 | 3867 | -- Get the server name based on whether this is a client or server socket. 3868 | local serverName = socket.server == nil and socket.target or socket.sender 3869 | -- Hash the password before sending. 3870 | return loginHashed(socket, username, hashPassword(username, password, serverName)) 3871 | end 3872 | 3873 | 3874 | -- Log out of the user account currently logged in on this socket. 3875 | -- If executed on a server socket, the event details are returned. 3876 | function logout(socket) 3877 | if not socketValid(socket) then 3878 | error("Invalid socket.", 2) 3879 | end 3880 | 3881 | -- Tell the other end to log out as well. 3882 | sendEncryptedInternal(socket, "lo") 3883 | if socket.server == nil then 3884 | -- If this is a client socket, all we can do is ask the server to log out. 3885 | -- The actual logging out is only performed once a response is received 3886 | -- from the server. 3887 | log("Sent logout request to "..socket.target..".") 3888 | else 3889 | -- If this is a server socket, we can actually logout. 3890 | local username = socket.username 3891 | socket.username = nil 3892 | socket.permissionLevel = 0 3893 | 3894 | if username == nil then 3895 | log("Already logged out.") 3896 | else 3897 | log(username.." logged out.") 3898 | end 3899 | return "logout", username, socket, server 3900 | end 3901 | end 3902 | 3903 | 3904 | -- 3905 | -- CORE NETWORKING 3906 | -- 3907 | 3908 | -- Check if a Rednet-format message is a CryptoNet one, and return its contents 3909 | -- if so. If it is invalid or has been processed before nil is returned. 3910 | local function extractMessage(message, receivedIDs) 3911 | -- Check the list of alrady received message IDs to see if any of them are 3912 | -- more than 5 seconds old and can be deleted. The purpose of this list is 3913 | -- to avoid processing messages processed by Rednet's repeat program 3914 | -- more than once, but repeat is unlikely to take 5 seconds to repeat a message. 3915 | -- Since the message IDs are randomly generated, it is good to remove them 3916 | -- from the list as soon as possible to reduce the chance of a future message 3917 | -- with same ID from being blocked. 3918 | -- Note that CryptoNet has a seperate more advanced system for preventing 3919 | -- attackers from sending the same encrypted message twice, handled elsewhere. 3920 | local toDelete = {} 3921 | for id, time in pairs(receivedIDs) do 3922 | -- List the ID for deletion if it is more than 5 seconds old. 3923 | if os.clock() - time > 5 then 3924 | table.insert(toDelete, id) 3925 | end 3926 | end 3927 | -- Remove all the deleted IDs. 3928 | for _,id in pairs(toDelete) do 3929 | receivedIDs[id] = nil 3930 | end 3931 | 3932 | -- Check that the message follows the Rednet format and is using the cryptoNet protocol. 3933 | if type(message) == "table" and message.sProtocol == "cryptoNet" and type(message.message) == "table" and type(message.nMessageID) == "number" then 3934 | -- If this message ID has not been received already recently, 3935 | -- return the message contents. 3936 | if not receivedIDs[message.nMessageID] then 3937 | receivedIDs[message.nMessageID] = os.clock() 3938 | return message.message 3939 | end 3940 | -- Always keep the latest timestamp of the ID. 3941 | receivedIDs[message.nMessageID] = os.clock() 3942 | end 3943 | return 3944 | end 3945 | 3946 | 3947 | -- Create and host a CryptoNet server, which other machines can remotely connect 3948 | -- to. This function will load the certificate and private key of the server 3949 | -- from the specified files, or generate new ones if no existing files are found. 3950 | -- Note that serverName is the only required parameter; all the others have 3951 | -- sensible defaults. 3952 | -- 3953 | -- serverName (string, required): 3954 | -- The name of the server, which clients will use to connect to it. 3955 | -- Also determines the channel that the server communicates on. 3956 | -- 3957 | -- discoverable (boolean, default: true): 3958 | -- Whether this server responds to discover() requests. 3959 | -- Disabling this is more secure as it means clients can't connect unless 3960 | -- they already know the name of the server. 3961 | -- 3962 | -- hideCertificate (boolean, default: false): 3963 | -- If true the server will not distribute its certificate to clients, 3964 | -- either in discover() or connect() requests, meaning clients can only 3965 | -- connect if they have already been given the certificate manually. 3966 | -- Useful if you only want certain manually authorised clients to be able to connect. 3967 | -- 3968 | -- modemSide (string, default: a side that has a modem): 3969 | -- The modem the server should use. 3970 | -- 3971 | -- certificate (table or string, default: ".crt"): 3972 | -- The certificate of the server. This can either be the certificate table itself, 3973 | -- or the name of a file that contains it. If the certicate and key files do not 3974 | -- exist, new ones will be generated and saved to the specified files. 3975 | -- 3976 | -- privateKey (table or string, default: "_private.key"): 3977 | -- The private key of the server. This can either be the key table itself, 3978 | -- or the name of a file that contains it. If the certicate and key files do not 3979 | -- exist, new ones will be generated and saved to the specified files. 3980 | -- 3981 | -- userTablePath (string, default: "_users.tbl"): 3982 | -- Path at which to store the user login details table, 3983 | -- if/when users are added to the server. 3984 | -- 3985 | -- Returns: The server table, containing the following information: 3986 | -- name: The server name 3987 | -- certificate: The server's certificate 3988 | -- privateKey: The server's private key 3989 | -- modemSide: The modem used by the server 3990 | -- channel: The channel number the server communicates on 3991 | -- hideCertificate: Whether the server distributes its certificate to clients 3992 | -- discoverable: Whether the server responds to discover() requests 3993 | -- userTable: The table of user login details for the server, 3994 | -- loaded from file or empty by default 3995 | -- userTablePath: The name of the user table file 3996 | -- sockets: The table of the server's sockets, used to communicate with clients. 3997 | -- Starts empty and is populated as clients connect. 3998 | function host(serverName, discoverable, hideCertificate, modemSide, certificate, privateKey, userTablePath) 3999 | if type(serverName) ~= "string" then 4000 | error("Server name must be a string.", 2) 4001 | end 4002 | -- Don't allow duplicate server names. 4003 | for _,server in pairs(allServers) do 4004 | if server.name == serverName then 4005 | error("Server called "..serverName.." already exists.", 2) 4006 | end 4007 | end 4008 | 4009 | modemSide = resolveModemSide(modemSide) 4010 | local modem = peripheral.wrap(modemSide) 4011 | 4012 | -- Generate default file names if none were provided, then get the paths 4013 | -- relative to the current working directory. 4014 | local certFilename = type(certificate) == "string" and certificate or serverName..".crt" 4015 | local keyFilename = type(privateKey) == "string" and privateKey or serverName.."_private.key" 4016 | local certificatePath = workingDir == "" and certFilename or workingDir.."/"..certFilename 4017 | local keyPath = workingDir == "" and keyFilename or workingDir.."/"..keyFilename 4018 | 4019 | -- Now that we've extracted the filenames above, only store the actual certificate 4020 | -- and key in these variables. 4021 | if type(certificate) == "string" then certificate = nil end 4022 | if type(privateKey) == "string" then privateKey = nil end 4023 | 4024 | if certificate ~= nil and not certificateValid(certificate) then 4025 | error("Invalid certificate.", 2) 4026 | end 4027 | if privateKey ~= nil and not privateKeyValid(privateKey) then 4028 | error("Invalid private key.", 2) 4029 | end 4030 | 4031 | -- Try loading the certificate from file. 4032 | if certificate == nil then 4033 | log("Checking "..certificatePath.." for certificate...") 4034 | if fs.isDir(certificatePath) then 4035 | error(certFilename.." already exists and is a directory, not a certificate.", 2) 4036 | elseif fs.exists(certificatePath) then 4037 | local file = fs.open(certificatePath, "r") 4038 | certificate = deserializeCertOrKey(file.readAll()) 4039 | file.close() 4040 | 4041 | if not certificateValid(certificate) then 4042 | error(certFilename.." already exists and is not a valid certificate.", 2) 4043 | else 4044 | log("Loaded certificate from "..certFilename..".") 4045 | end 4046 | else 4047 | log("Certificate file not found, will need to generate a new one.") 4048 | end 4049 | end 4050 | 4051 | -- Try loading the private key from file. 4052 | if privateKey == nil then 4053 | log("Checking "..keyPath.." for private key...") 4054 | if fs.isDir(keyPath) then 4055 | error(keyFilename.." already exists and is a directory, not a keyfile.", 2) 4056 | elseif fs.exists(keyPath) then 4057 | local file = fs.open(keyPath, "r") 4058 | privateKey = deserializeCertOrKey(file.readAll()) 4059 | file.close() 4060 | 4061 | if not privateKeyValid(privateKey) then 4062 | error(keyFilename.." already exists and is not a valid keyfile.", 2) 4063 | else 4064 | log("Loaded private key from "..keyFilename..".") 4065 | end 4066 | else 4067 | log("Private keyfile not found, will need to generate a new one.") 4068 | end 4069 | end 4070 | 4071 | -- If we have no certificate or private key yet, generate them. 4072 | -- You can't just provide one and not the other, as the public and private 4073 | -- keys must be generated as a pair. 4074 | if certificate == nil and privateKey == nil then 4075 | log("No certificate or private key found, generating new ones.") 4076 | certificate, privateKey = generateCertificate(serverName) 4077 | 4078 | local file = fs.open(certificatePath, "w") 4079 | file.write(serializeCertOrKey(certificate)) 4080 | file.close() 4081 | log("Saved certificate to "..certificatePath..".") 4082 | 4083 | file = fs.open(keyPath, "w") 4084 | file.write(serializeCertOrKey(privateKey)) 4085 | file.close() 4086 | log("Saved private key to "..keyPath..". Do not share this with anyone!") 4087 | elseif certificate ~= nil and privateKey == nil then 4088 | error("Have a certificate but not a private key, need both or neither.", 2) 4089 | elseif certificate == nil and privateKey ~= nil then 4090 | error("Have a private key but not a certificate, need both or neither.", 2) 4091 | end 4092 | 4093 | -- It is possible for an attacker to host a server with the same name as yours, 4094 | -- confusing and tricking clients. Having a certifiate authority sign 4095 | -- the certificates of trusted servers prevents this. 4096 | if certificate.signature == nil then 4097 | log("Warning: Your certificate does not have a signature.") 4098 | else 4099 | log("Certificate is signed.") 4100 | end 4101 | 4102 | -- Open the server's channel (derived from the server name) so it can be used 4103 | -- for communication. 4104 | local channel = getChannel(serverName) 4105 | modem.open(channel) 4106 | log("Hosting on channel "..channel..".") 4107 | 4108 | if hideCertificate then 4109 | log("Your server is set to require clients to already have its certificate in order to connect to it.") 4110 | end 4111 | 4112 | -- Allow clients to use discover() to get the name and certificate 4113 | -- of this server without prior knowledge of it. 4114 | if discoverable or discoverable == nil then 4115 | modem.open(DISCOVERY_CHANNEL) 4116 | log("Your server is discoverable.") 4117 | else 4118 | log("Your server is not discoverable.") 4119 | end 4120 | 4121 | -- Load the server's user table from file, or create a new one if none was found. 4122 | if userTablePath == nil then 4123 | userTablePath = serverName.."_users.tbl" 4124 | end 4125 | local userTable 4126 | if type(userTablePath) == "string" then 4127 | -- Append the current working directory to the table path. 4128 | userTablePath = workingDir == "" and userTablePath or workingDir.."/"..userTablePath 4129 | userTable = loadUserTable(userTablePath) 4130 | else 4131 | error("userTablePath must be a string.", 2) 4132 | end 4133 | 4134 | -- Create the server table. 4135 | local server = { 4136 | name = serverName, 4137 | certificate = certificate, 4138 | privateKey = privateKey, 4139 | modemSide = modemSide, 4140 | channel = channel, 4141 | hideCertificate = hideCertificate, 4142 | discoverable = discoverable or discoverable == nil, -- Default to true 4143 | userTable = userTable, 4144 | userTablePath = userTablePath, 4145 | sockets = {} -- New servers have no connections yet. 4146 | } 4147 | 4148 | table.insert(allServers, server) 4149 | log("Server ready.") 4150 | return server 4151 | end 4152 | 4153 | 4154 | -- Close a socket or server, such that it will not listen for messages anymore. 4155 | -- Closing a server closes all its sockets. 4156 | function close(socket) 4157 | if socketValid(socket) then 4158 | -- Let the other end of the socket know it has been closed. 4159 | -- Don't send if this one was closed remotely, since the other end clearly 4160 | -- already knows. 4161 | if not socket.closedRemotely then 4162 | sendEncryptedInternal(socket, "c") 4163 | end 4164 | if socket.server == nil then 4165 | -- If this is a client socket, remove it from the list of client sockets. 4166 | -- This will stop handleModemEvent() from processing messages for it. 4167 | for i=1,#allClientSockets do 4168 | if allClientSockets[i] == socket then 4169 | table.remove(allClientSockets, i) 4170 | break 4171 | end 4172 | end 4173 | else 4174 | -- If this is a server socket, remove it from the server's socket list. 4175 | -- This will stop handleModemEvent() from processing messages for it. 4176 | socket.server.sockets[socket.target] = nil 4177 | end 4178 | 4179 | -- If this was the only socket communicating on its channel, close the channel 4180 | -- on the modem. Don't close the channel if another socket is still using it. 4181 | if not channelInUse(socket.channel, socket.modemSide) then 4182 | peripheral.wrap(socket.modemSide).close(socket.channel) 4183 | log("Closed socket channel "..socket.channel.." on modem "..socket.modemSide..".") 4184 | end 4185 | log("Closed socket.") 4186 | 4187 | elseif serverValid(socket) then 4188 | -- If this is a server being closed... 4189 | local server = socket 4190 | -- Create a copy of the server's socket list and close them all. 4191 | -- Closing a socket will remove it from the server's socket list, 4192 | -- so we make a copy so it doesn't change while we're trying to iterate 4193 | -- over it. 4194 | local socketsCopy = {} 4195 | for _,soc in pairs(server.sockets) do 4196 | table.insert(socketsCopy, soc) 4197 | end 4198 | for _,soc in pairs(socketsCopy) do 4199 | close(soc) 4200 | end 4201 | 4202 | -- Remove the closed server from the server list. 4203 | -- This will stop handleModemEvent() from processing messages for it. 4204 | for i=1,#allServers do 4205 | if allServers[i] == server then 4206 | table.remove(allServers, i) 4207 | break 4208 | end 4209 | end 4210 | 4211 | -- If this was the only server/socket communicating on its channel, close the channel 4212 | -- on the modem. Don't close the channel if another socket is still using it. 4213 | if not channelInUse(server.channel, server.modemSide) then 4214 | peripheral.wrap(server.modemSide).close(server.channel) 4215 | log("Closed server channel "..server.channel.." on modem "..server.modemSide..".") 4216 | end 4217 | 4218 | -- If this was the only server using the discovery channel, close it. 4219 | if server.discoverable then 4220 | found = false 4221 | for _,srvr in pairs(allServers) do 4222 | if srvr.discoverable and srvr.modemSide == server.modemSide then 4223 | found = true 4224 | break 4225 | end 4226 | end 4227 | if not found then 4228 | peripheral.wrap(server.modemSide).close(DISCOVERY_CHANNEL) 4229 | log("Closed discovery channel.") 4230 | end 4231 | end 4232 | else 4233 | error("Must be a valid socket or server.", 2) 4234 | end 4235 | end 4236 | 4237 | 4238 | -- Close all sockets and servers on this machine. 4239 | function closeAll() 4240 | -- Iteratve backwards so the list isn't chaning in front of us. 4241 | for i=#allClientSockets,1,-1 do 4242 | close(allClientSockets[i]) 4243 | end 4244 | for i=#allServers,1,-1 do 4245 | close(allServers[i]) 4246 | end 4247 | log("Closed all sockets and servers.") 4248 | end 4249 | 4250 | 4251 | -- Process an encrypted message sent over CryptoNet to a socket, 4252 | -- that has already been decrypted. 4253 | -- Decrypted messages start with one or two characters that specify the type 4254 | -- of the message, which may either be an internal message (e.g. login requests) 4255 | -- or an encrypted message sent by a user using the send() function. 4256 | -- 4257 | -- May return the details of a CryptoNet event caused by the message, 4258 | -- or nil if none occurs. Also returns a status boolean to say whether the 4259 | -- message turned out to have a valid format. 4260 | local function handleDecryptedMessage(socket, message) 4261 | local ok = true 4262 | local result = nil 4263 | if message == "c" then 4264 | log("Connection closed by other end.") 4265 | socket.closedRemotely = true 4266 | -- Close our end of the socket too. 4267 | close(socket) 4268 | socket.closedRemotely = nil 4269 | result = {"connection_closed", socket, socket.server} 4270 | elseif message:sub(1,2) == "lr" then 4271 | -- Login requests have the format lr{username,password} 4272 | -- Note that the password will have already been hashed using hashPassword() 4273 | -- by the client before sending. 4274 | local request = textutils.unserialize(message:sub(3)) 4275 | if type(request) == "table" and type(request[1]) == "string" and type(request[2]) == "string" then 4276 | result = {loginHashed(socket, request[1], request[2])} 4277 | else 4278 | ok = false 4279 | end 4280 | elseif message:sub(1,2) == "lf" then 4281 | -- Runs on client when server says the login failed. Format: lfusername 4282 | log("Failed login attempt for "..message:sub(3)..".") 4283 | result = {"login_failed", message:sub(3), socket, socket.server} 4284 | elseif message:sub(1,2) == "ls" then 4285 | -- Runs on client when server says the login was successful. 4286 | -- Format: ls{username,permissionLevel} 4287 | local details = textutils.unserialize(message:sub(3)) 4288 | if type(details) == "table" and type(details[1]) == "string" and type(details[2]) == "number" then 4289 | socket.username = details[1] 4290 | socket.permissionLevel = details[2] 4291 | log(socket.username.." logged in successfully.") 4292 | result = {"login", socket.username, socket, socket.server} 4293 | else 4294 | -- Response was invalid. 4295 | ok = false 4296 | end 4297 | elseif message == "lo" then 4298 | -- Logout. 4299 | if socket.server == nil then 4300 | -- On client side just reset the user details, the server will already 4301 | -- have logged out its socket. 4302 | local username = socket.username 4303 | socket.username = nil 4304 | socket.permissionLevel = 0 4305 | 4306 | if username == nil then 4307 | log("Already logged out.") 4308 | else 4309 | log(username.." logged out.") 4310 | end 4311 | result = {"logout", username, socket, nil} 4312 | else 4313 | -- On server side call logout() to also send a message to the client 4314 | -- to tell it to log out. 4315 | result = {logout(socket)} 4316 | end 4317 | else 4318 | -- If the message had none of the above internal message types, 4319 | -- it must be a user-generated encrypted message, which will start with 4320 | -- a data type character. Attempt to deserialize the message as such. 4321 | ok, message = pcall(deserializeAny, message) 4322 | if ok then 4323 | result = {"encrypted_message", message, socket, socket.server} 4324 | end 4325 | end 4326 | return ok, result 4327 | end 4328 | 4329 | 4330 | -- See if the given CryptoNet message is relevant to this server, and act upon 4331 | -- it as needed. May return the details of a CryptoNet event caused by the message, 4332 | -- or nil if none occurs. 4333 | local function handleServerMessage(server, message, messageChannel) 4334 | -- Check if this message is a discovery request, 4335 | -- and respond to it if and only if the server is discoverable. 4336 | if messageChannel == DISCOVERY_CHANNEL and message.msgType == "discovery_request" and server.discoverable then 4337 | -- Remove the public key and signature from the certificate if needed. 4338 | local certificate = server.hideCertificate and {name=server.name} or server.certificate 4339 | sendInternal(server.modemSide, DISCOVERY_CHANNEL, nil, certificate, "discovery_response") 4340 | log("Responded to discovery request.") 4341 | -- If this is a message directed at this server... 4342 | elseif messageChannel == server.channel and message.target == server.name then 4343 | if message.msgType == "certificate_request" and not server.hideCertificate then 4344 | sendInternal(server.modemSide, server.channel, nil, server.certificate, "certificate_response") 4345 | log("Responded to certificate request.") 4346 | elseif message.msgType == "connection_request" and type(message.message) == "string" then 4347 | -- The client will have sent a session key, encryped using the server's public key. 4348 | -- We need to use the private key to decrypt it and use the session key to send 4349 | -- an acknowledgement to the client. 4350 | local encryptedKey = message.message 4351 | if server.sockets[encryptedKey] ~= nil then 4352 | -- This is probably a repeated message, as we have already processed it before. 4353 | log("Received duplicate connection request, ignoring it.") 4354 | else 4355 | -- Try to decrypt the session key using the server's private key. 4356 | local ok, numKey = pcall(rsaCrypt.crypt, server.privateKey, encryptedKey) 4357 | ok, sessKey = pcall(rsaCrypt.numberToBytes, numKey, 16*8, 8) 4358 | -- Validate the key, which should be a table of 16 bytes. 4359 | if ok and (sessKey == nil or #sessKey ~= 16) then 4360 | ok = false 4361 | end 4362 | if not ok then 4363 | log("Received invalid session key.") 4364 | else 4365 | -- Send a message back to the client encrypted with the session key 4366 | -- to prove that we have received it correctly. 4367 | -- The client knows what the message is supposed to be, 4368 | -- allowing it to validate it. 4369 | local response = tostring(sha256.digest(server.name..server.certificate.key.public..server.certificate.key.shared..numKey)) 4370 | -- Encrypt the message. 4371 | local iv = generateKey() 4372 | response = aes.encrypt_str(response, sessKey, iv) 4373 | -- From now on the client will be identified by it's encrypted session key. 4374 | sendInternal(server.modemSide, server.channel, encryptedKey, {{string.byte(response, 1, response:len())}, iv}, "connection_response") 4375 | log("Responded to connection request.") 4376 | 4377 | -- Create the socket object pointing to the client. 4378 | local socket = {sender=server.name, target=encryptedKey, key=sessKey, modemSide=server.modemSide, 4379 | channel=server.channel, server=server, permissionLevel=0, receivedMessages={}} 4380 | server.sockets[encryptedKey] = socket 4381 | return {"connection_opened", socket, server} 4382 | end 4383 | end 4384 | elseif message.msgType == "encrypted_message" and type(message.message) == "table" and #message.message == 2 4385 | and type(message.message[1]) == "table" and type(message.message[2]) == "table" then 4386 | -- If this is an encrypted message, try decrypting it with the session key 4387 | -- and handle the decrypted message as needed. 4388 | local socket = server.sockets[message.sender] 4389 | local encrypted = bytesToString(message.message[1]) 4390 | local iv = message.message[2] 4391 | if socket == nil then 4392 | log("Received a message from a sender who has yet to open a connection.") 4393 | elseif encrypted == nil then 4394 | log("Received invalid message.") 4395 | elseif socket.receivedMessages[encrypted] then 4396 | -- The encryption algorithm adds random numbers to each message before 4397 | -- encrypting it, so even if two messages are identical their encrypted 4398 | -- versions will probably be different. Therefore if we receive the exact 4399 | -- same encrypted message twice it is most likely a malicious duplicate 4400 | -- made by someone without the session key, and so should be ignored. 4401 | log("Received duplicate message, ignoring it.") 4402 | else 4403 | -- Remember we have received this message so we don't accept it again 4404 | -- (see above). 4405 | socket.receivedMessages[encrypted] = true 4406 | local ok, decrypted = pcall(aes.decrypt_str, encrypted, socket.key, iv) 4407 | if ok then 4408 | local ok, result = handleDecryptedMessage(socket, decrypted) 4409 | if ok and result ~= null then 4410 | return result 4411 | end 4412 | end 4413 | if not ok then 4414 | log("Received invalid message.") 4415 | end 4416 | end 4417 | elseif message.msgType == "plain_message" then 4418 | local socket = server.sockets[message.sender] 4419 | if socket ~= nil then 4420 | return {"plain_message", message.message, socket, server} 4421 | else 4422 | log("Received a message from a sender who has yet to open a connection.") 4423 | end 4424 | end 4425 | end 4426 | end 4427 | 4428 | 4429 | -- See if the given CryptoNet message is relevant to this client socket, and act upon 4430 | -- it as needed. 4431 | -- 4432 | -- May return the details of a CryptoNet event caused by the message, 4433 | -- or nil if none occurs. 4434 | local function handleClientMessage(socket, message, messageChannel) 4435 | -- If this is a message directed at this socket... 4436 | if messageChannel == socket.channel and message.sender == socket.target and message.target == socket.sender then 4437 | if message.msgType == "encrypted_message" and type(message.message) == "table" and #message.message == 2 4438 | and type(message.message[1]) == "table" and type(message.message[2]) == "table" then 4439 | local encrypted = bytesToString(message.message[1]) 4440 | local iv = message.message[2] 4441 | if encrypted == nil then 4442 | log("Received invalid message.") 4443 | elseif socket.receivedMessages[encrypted] then 4444 | -- The encryption algorithm adds random numbers to each message before 4445 | -- encrypting it, so even if two messages are identical their encrypted 4446 | -- versions will probably be different. Therefore if we receive the exact 4447 | -- same encrypted message twice it is most likely a malicious duplicate 4448 | -- made by someone without the session key, and so should be ignored. 4449 | log("Received duplicate message, ignoring it.") 4450 | else 4451 | socket.receivedMessages[encrypted] = true 4452 | -- Decrypt the message with the session key and handle as needed. 4453 | local ok, decrypted = pcall(aes.decrypt_str, encrypted, socket.key, iv) 4454 | if ok then 4455 | local ok, result = handleDecryptedMessage(socket, decrypted) 4456 | if ok then 4457 | return result 4458 | end 4459 | end 4460 | if not ok then 4461 | log("Received invalid message.") 4462 | end 4463 | end 4464 | elseif message.msgType == "plain_message" then 4465 | return {"plain_message", message.message, socket, nil} 4466 | end 4467 | end 4468 | end 4469 | 4470 | 4471 | -- Check if the given modem_message event is a CryptoNet message, and if so 4472 | -- decrypt and act upon it as needed. 4473 | -- 4474 | -- receivedIDs: A table of recently received message IDs, used to block any 4475 | -- more messages with the same ID within a cooldown period, on the basis that they 4476 | -- are probably the same message repeated. 4477 | -- 4478 | -- May return the details of a CryptoNet event caused by the message, 4479 | -- or nil if none occurs. 4480 | local function handleModemEvent(event, receivedIDs) 4481 | -- Check if the modem message was a CryptoNet-formatted message, and extract 4482 | -- the message contents. 4483 | local message = extractMessage(event[5], receivedIDs) 4484 | if message ~= nil then 4485 | -- Try passing the message to all servers on this machine. 4486 | for _,server in pairs(allServers) do 4487 | local result = handleServerMessage(server, message, event[3]) 4488 | if result ~= nil then 4489 | return result 4490 | end 4491 | end 4492 | 4493 | -- Try passing the message to all client sockets on this machine. 4494 | for _,socket in pairs(allClientSockets) do 4495 | local result = handleClientMessage(socket, message, event[3]) 4496 | if result ~= nil then 4497 | return result 4498 | end 4499 | end 4500 | end 4501 | 4502 | return nil 4503 | end 4504 | 4505 | 4506 | -- Listens for and handles CryptoNet messages for all sockets and servers 4507 | -- on this machine. Returns when a message is received that invokes a 4508 | -- user-facing CryptoNet event, with the details of said event. 4509 | -- Should ideally be executed inside a while loop alongside event handling logic. 4510 | -- 4511 | -- It is recommended that users use startEventLoop() over a listen() loop, 4512 | -- as it creates a new thread for each event received, allowing for calls to sleep() 4513 | -- and pullEvent() in event handling code without freezing the rest of the server. 4514 | function listen() 4515 | -- Message IDs recently received by this machine that we don't want to 4516 | -- process repeat copies of. 4517 | local receivedIDs = {} 4518 | -- Keep listening for and handling modem_messages until 4519 | -- a CryptoNet event is raised. 4520 | while true do 4521 | local event = {os.pullEvent("modem_message")} 4522 | local newEvent = handleModemEvent(event, receivedIDs) 4523 | if newEvent ~= nil then 4524 | return table.unpack(newEvent) 4525 | end 4526 | end 4527 | end 4528 | 4529 | 4530 | -- Request the certificates of all online CryptoNet servers on the network. 4531 | -- Some servers may have been set to not respond to discovery requests, 4532 | -- and some will only contain the server name in the certificate, excluding 4533 | -- the public key required to connect to the server. 4534 | -- 4535 | -- This function can optionally use a certificate authority public key 4536 | -- to verify the signatures of certificates, only returning certificates 4537 | -- with valid signatures. By default discover() looks for the public key 4538 | -- in "certAuth.key". 4539 | -- 4540 | -- timeout (number, default: 1): 4541 | -- The time in seconds to spend listening for responses. 4542 | -- 4543 | -- certAuthKey (table or string, default: "certAuth.key"): 4544 | -- The certificate authority public key used to verify signatures, 4545 | -- or the path of the file to load it from. If no valid key is found 4546 | -- the discovery will still go ahead, but signatures will not be checked. 4547 | -- 4548 | -- allowUnsigned (boolean, default: false): 4549 | -- Whether to include certificates with no valid signature in the results. 4550 | -- If no valid cert auth key is provided this is ignored, as the certificates 4551 | -- cannot be checked without a key. 4552 | -- 4553 | -- modemSide (string, default: a side with a modem): 4554 | -- The modem to use to send and receive messages. 4555 | -- 4556 | -- Returns a table of the certificates received, all of which will include 4557 | -- the name of server and possibly also the public key and signature. 4558 | function discover(timeout, certAuthKey, allowUnsigned, modemSide) 4559 | -- Load and validate the key. 4560 | certAuthKey = loadCertAuthKey(certAuthKey) 4561 | 4562 | modemSide = resolveModemSide(modemSide) 4563 | local modem = peripheral.wrap(modemSide) 4564 | -- Remember if the modem was already open so we can 4565 | -- close it afterwards if it wasn't. 4566 | local wasOpen = modem.isOpen(DISCOVERY_CHANNEL) 4567 | modem.open(DISCOVERY_CHANNEL) 4568 | 4569 | log("Discovering...") 4570 | sendInternal(modemSide, DISCOVERY_CHANNEL, nil, nil, "discovery_request") 4571 | 4572 | -- List of response message IDs we've already received 4573 | -- so we can ignore duplicates. 4574 | local receivedIDs = {} 4575 | -- The received certificates. 4576 | local certificates = {} 4577 | -- Set a timer for when the timeout expires. 4578 | local timer = os.startTimer((type(timeout) == "number") and timeout or 1) 4579 | while true do 4580 | -- Wait for either a modem_message or timer event. 4581 | local event = {os.pullEvent()} 4582 | if event[1] == "modem_message" and event[3] == DISCOVERY_CHANNEL then 4583 | -- See if this is a CryptoNet-formatted message and exract its contents. 4584 | local message = extractMessage(event[5], receivedIDs) 4585 | -- If this is a discovery_response with a correctly formatted certifiate... 4586 | if message ~= nil and message.msgType == "discovery_response" and certificateValid(message.message, true) then 4587 | local certificate = message.message 4588 | local found = false 4589 | -- If we have already received an identical certificate don't add this one. 4590 | for _,cert in pairs(certificates) do 4591 | if certificate.name == cert.name and ((certificate.key == nil and cert.key == nil) or (certificate.key ~= nil and cert.key ~= nil 4592 | and certificate.key.public == cert.key.public and certificate.key.shared == cert.key.shared)) and certificate.signature == cert.signature then 4593 | found = true 4594 | break 4595 | end 4596 | end 4597 | 4598 | if not found then 4599 | table.insert(certificates, certificate) 4600 | end 4601 | end 4602 | elseif event[1] == "timer" and event[2] == timer then 4603 | -- Stop listening for events once the time is up. 4604 | break 4605 | end 4606 | end 4607 | 4608 | -- Close the discovery channel if it wasn't open before we started. 4609 | if not wasOpen then 4610 | modem.close(DISCOVERY_CHANNEL) 4611 | end 4612 | 4613 | -- If we have a valid cert auth key to use, 4614 | -- verify the signatures of the received certificates. 4615 | -- If allowUnsigned is false any certificates without valid signatures 4616 | -- will be removed. 4617 | if certAuthKey ~= nil and #certificates > 0 then 4618 | log("Checking signatures...") 4619 | -- Iterate backwards as we will be deleting from the list. 4620 | for i=#certificates,1,-1 do 4621 | local certificate = certificates[i] 4622 | if certificate.signature == nil then 4623 | if not allowUnsigned then 4624 | log("Discarding "..certificate.name.." as it has no signature.") 4625 | table.remove(certificates, i) 4626 | end 4627 | else 4628 | local ok, valid = pcall(verifyCertificate, certificate, certAuthKey) 4629 | if ok and valid then 4630 | -- Keep the certificate. 4631 | log(certificate.name.." has a valid signature.") 4632 | else 4633 | log("Discarding "..certificate.name.." as it has an invalid signature.") 4634 | table.remove(certificates, i) 4635 | end 4636 | end 4637 | end 4638 | end 4639 | 4640 | return certificates 4641 | end 4642 | 4643 | 4644 | -- Request the certificate of a server with the given name. 4645 | -- Note that some servers may not respond to these requests, 4646 | -- expecting trusted clients to have been given the certificate manually. 4647 | -- All the certificates returned will contain the public key of their server. 4648 | -- 4649 | -- If multiple certificates are received with the same server name, 4650 | -- there is no way to tell which one is the real server (the others are probably 4651 | -- malicious fakes), so none of them are returned. To avoid this situation, 4652 | -- this function can optionally use a certificate authority public key to 4653 | -- verify the signatures of received certificates, ignoring any with invalid 4654 | -- signatures. By default requestCertificate() looks in "certAuth.key" 4655 | -- for the key. 4656 | -- If multiple signed certificates are received, this implies that 4657 | -- the certificate authority has authorized an impersonator, so none of them 4658 | -- are returned as we don't know which is the real one. 4659 | -- 4660 | -- serverName (string, required): 4661 | -- The name of the server to request the certificate of. 4662 | -- 4663 | -- timeout (number, default: 1): 4664 | -- The length of time in seconds to wait for responses. 4665 | -- The function will always wait the full time, to allow for duplicates. 4666 | -- 4667 | -- certAuthKey (table or string, default: "certAuth.key"): 4668 | -- The certificate authority public key used to verify signatures, 4669 | -- or the path of the file to load it from. If no valid key is found 4670 | -- the request will still go ahead, but signatures will not be checked. 4671 | -- 4672 | -- allowUnsigned (boolean, default: false): 4673 | -- Whether to accept certificates with no valid signature. 4674 | -- If no valid cert auth key is provided this is ignored, as the certificates 4675 | -- cannot be checked without a key. 4676 | -- 4677 | -- modemSide (string, default: a side with a modem): 4678 | -- The modem to use to send and receive messages. 4679 | -- 4680 | -- Returns the certificate of the server if exactly one is received, or nil 4681 | -- if zero or more than one acceptable certificates are found. 4682 | -- Also returns a table of all acceptable certificates received. 4683 | function requestCertificate(serverName, timeout, certAuthKey, allowUnsigned, modemSide) 4684 | if type(serverName) ~= "string" then 4685 | error("Server name must be a string.", 2) 4686 | end 4687 | certAuthKey = loadCertAuthKey(certAuthKey) 4688 | 4689 | modemSide = resolveModemSide(modemSide) 4690 | local modem = peripheral.wrap(modemSide) 4691 | local channel = getChannel(serverName) 4692 | -- Remember if the modem was already open so we can 4693 | -- close it afterwards if it wasn't. 4694 | local wasOpen = modem.isOpen(channel) 4695 | modem.open(channel) 4696 | 4697 | log("Requesting certificate...") 4698 | sendInternal(modemSide, channel, serverName, nil, "certificate_request") 4699 | 4700 | -- List of response message IDs we've already received 4701 | -- so we can ignore duplicates. 4702 | local receivedIDs = {} 4703 | -- The received certificates. 4704 | local certificates = {} 4705 | -- Set a timer for when the timeout expires. 4706 | local timer = os.startTimer((type(timeout) == "number") and timeout or 1) 4707 | while true do 4708 | -- Wait for either a modem_message or timer event. 4709 | local event = {os.pullEvent()} 4710 | if event[1] == "modem_message" and event[3] == channel then 4711 | -- See if this is a CryptoNet-formatted message and exract its contents. 4712 | local message = extractMessage(event[5], receivedIDs) 4713 | -- If this is a certificate_response with a correctly formatted certifiate, 4714 | -- for the correct server... 4715 | if message ~= nil and message.msgType == "certificate_response" and certificateValid(message.message) and message.message.name == serverName then 4716 | local certificate = message.message 4717 | local found = false 4718 | -- If we have already received an identical certificate don't add this one. 4719 | for _,cert in pairs(certificates) do 4720 | if certificate.key.public == cert.key.public and certificate.key.shared == cert.key.shared and certificate.signature == cert.signature then 4721 | found = true 4722 | break 4723 | end 4724 | end 4725 | 4726 | if not found then 4727 | table.insert(certificates, certificate) 4728 | end 4729 | end 4730 | elseif event[1] == "timer" and event[2] == timer then 4731 | -- Stop listening for events once the time is up. 4732 | break 4733 | end 4734 | end 4735 | 4736 | -- Close the channel if it wasn't open before we started. 4737 | if not wasOpen then 4738 | modem.close(channel) 4739 | end 4740 | 4741 | -- If we have a valid cert auth key to use, 4742 | -- verify the signatures of the received certificates. 4743 | -- If allowUnsigned is false any certificates without valid signatures 4744 | -- will be removed. 4745 | local signedCount = 0 4746 | if certAuthKey ~= nil and #certificates > 0 then 4747 | log("Checking signatures...") 4748 | -- Iterate backwards as we will be deleting from the list. 4749 | for i=#certificates,1,-1 do 4750 | local certificate = certificates[i] 4751 | if certificate.signature == nil then 4752 | if not allowUnsigned then 4753 | log("Discarding a certificate as it has no signature.") 4754 | table.remove(certificates, i) 4755 | end 4756 | else 4757 | local ok, valid = pcall(verifyCertificate, certificate, certAuthKey) 4758 | if ok and valid then 4759 | -- Keep the certificate. 4760 | log("This certificate has a valid signature.") 4761 | signedCount = signedCount + 1 4762 | else 4763 | log("Discarding a certificate as it has an invalid signature.") 4764 | table.remove(certificates, i) 4765 | end 4766 | end 4767 | end 4768 | end 4769 | 4770 | if #certificates == 1 then 4771 | log("One certificate found, good.") 4772 | return certificates[1], certificates 4773 | else 4774 | if #certificates == 0 then 4775 | log("No certificates found.") 4776 | elseif signedCount > 1 then 4777 | log("Multiple ("..signedCount..") certificates had valid signatures, has the certificate authority authorized impersonators?") 4778 | else 4779 | log("Multiple ("..#certificates..") certificates found, some may be malicious.") 4780 | end 4781 | -- Don't return any certificate as the chosen one, but still return the whole list. 4782 | return nil, certificates 4783 | end 4784 | end 4785 | 4786 | 4787 | -- Open an encrypted connection to a CryptoNet server, returning a socket object 4788 | -- that can be used to send and receive messages from the server. 4789 | -- 4790 | -- serverName (string, default: inferred from certificate): 4791 | -- The name of the server to connect to. 4792 | -- 4793 | -- timeout (number, default: 5): 4794 | -- The number of seconds to wait for a response to the connection request. 4795 | -- Will terminate early if a response is received. 4796 | -- 4797 | -- certTimeout (number, default: 1): 4798 | -- The number of seconds to wait for certificate responses, 4799 | -- if no certificate was provided. 4800 | -- 4801 | -- certificate (table or string, default: ".crt"): 4802 | -- The certificate of the server. Can either be the certificate of 4803 | -- the server itself, or the name of a file that contains it. 4804 | -- If no valid certificate is found a certificate request 4805 | -- will be sent to the server. 4806 | -- 4807 | -- modemSide (string, default: a side with a modem): 4808 | -- The modem to use to send and receive messages. 4809 | -- 4810 | -- certAuthKey (table or string, default: "certAuth.key"): 4811 | -- The certificate authority public key used to verify signatures, 4812 | -- or the path of the file to load it from. If no valid key is found 4813 | -- the connection will still go ahead, but signatures will not be checked. 4814 | -- 4815 | -- allowUnsigned (boolean, default: false): 4816 | -- Whether to accept certificates with no valid signature. 4817 | -- If no valid cert auth key is provided this is ignored, as the certificates 4818 | -- cannot be checked without a key. 4819 | -- This does not apply to the certificate provided by the user (if present), 4820 | -- which is never verified (we trust them to get their own certificate right), 4821 | -- only to certificates received through a certificate request. 4822 | -- 4823 | -- Returns a socket object that can be used to communicate with the server, 4824 | -- with the following attributes: 4825 | -- sender: The encrypted session key of this socket, which acts as the client's 4826 | -- temporary identity to the server 4827 | -- target: The name of the server 4828 | -- key: The session key for this socket's session 4829 | -- modemSide: The modem used by the socket 4830 | -- channel: The channel the server (and this socket) use to communicate 4831 | -- permissionLevel: The permission level of the user logged into the socket, 4832 | -- initialized to 0. 4833 | -- receivedMessages: The encrypted messages received by this socket, 4834 | -- used to prevent replay attacks using duplicate messages. 4835 | -- Every time a message is encrypted the encrypted version will be different 4836 | -- due to randomness in the algorithm, so if we get the exact same message 4837 | -- twice it is probably a malicious duplicate. 4838 | function connect(serverName, timeout, certTimeout, certificate, modemSide, certAuthKey, allowUnsigned) 4839 | if serverName ~= nil and type(serverName) ~= "string" then 4840 | error("Server name must be a string or nil.", 2) 4841 | end 4842 | if certificate == nil then 4843 | if type(serverName) == "string" then 4844 | -- If a server name was given but not a certificate, 4845 | -- try to load a corresponding certificate from file. 4846 | certificate = serverName..".crt" 4847 | else 4848 | -- Need a way to identify the server. 4849 | error("Server name and certificate can't both be nil.", 2) 4850 | end 4851 | end 4852 | 4853 | -- If the certificate is a file path... 4854 | if type(certificate) == "string" then 4855 | local certFilename = certificate 4856 | -- Make paths relative to the current CryptoNet working directory. 4857 | local certPath = workingDir == "" and certFilename or workingDir.."/"..certFilename 4858 | log("Checking "..certPath.." for certificate...") 4859 | if fs.isDir(certPath) or not fs.exists(certPath) then 4860 | if fs.isDir(certPath) then 4861 | log(certFilename.." is not a file, will need to request certificate.") 4862 | else 4863 | log(certFilename.." does not exist, will need to request certificate.") 4864 | end 4865 | certificate = nil 4866 | else 4867 | local file = fs.open(certPath, "r") 4868 | certificate = deserializeCertOrKey(file.readAll()) 4869 | file.close() 4870 | 4871 | if not certificateValid(certificate) then 4872 | log(certFilename.." does not contain a valid certificate, will need to request certificate.") 4873 | certificate = nil 4874 | else 4875 | log("Loaded certificate from "..certFilename..".") 4876 | end 4877 | end 4878 | elseif not certificateValid(certificate) then 4879 | -- If certificate was not a string, it should be a valid certificate. 4880 | error("Invalid certificate.", 2) 4881 | end 4882 | 4883 | -- Infer serverName from the certificate. 4884 | if serverName == nil then 4885 | if certificate ~= nil then 4886 | serverName = certificate.name 4887 | else 4888 | error("Failed to load name from certificate, and no name was provided.", 2) 4889 | end 4890 | end 4891 | 4892 | modemSide = resolveModemSide(modemSide) 4893 | local modem = peripheral.wrap(modemSide) 4894 | local channel = getChannel(serverName) 4895 | -- Remember if the modem was already open so we can 4896 | -- close it afterwards if it wasn't. 4897 | local wasOpen = modem.isOpen(channel) 4898 | modem.open(channel) 4899 | 4900 | -- If we have no certificate yet, request it from the server. 4901 | if certificate == nil then 4902 | certificate = requestCertificate(serverName, certTimeout, certAuthKey, allowUnsigned, modemSide) 4903 | if certificate == nil then 4904 | -- Close the modem channel if it wasn't open before we started. 4905 | if not wasOpen then 4906 | modem.close(channel) 4907 | end 4908 | error("Failed to request certificate from server.", 2) 4909 | end 4910 | end 4911 | 4912 | -- An AES session key is used to encrypt the messages sent and received over 4913 | -- this socket. Before sending messages we need to generate a session key 4914 | -- and send it to the server. RSA encryption using the server's public key 4915 | -- (contained in its certificate) is used to send the session key; 4916 | -- the server will use its private key to decrypt the message. 4917 | log("Generating session key...") 4918 | local sessKey = generateKey() 4919 | local numKey = rsaCrypt.bytesToNumber(sessKey, 16*8, 8) 4920 | local encryptedKey = rsaCrypt.crypt(certificate.key, numKey) 4921 | -- The server will send a response encrypted with the session key to prove 4922 | -- that it has received is successfully. We know what the response content 4923 | -- is supposed to be, allowing us to verify the response. 4924 | local expectedResponse = tostring(sha256.digest(serverName..certificate.key.public..certificate.key.shared..numKey)) 4925 | sendInternal(modemSide, channel, serverName, encryptedKey, "connection_request") 4926 | 4927 | log("Awaiting response...") 4928 | -- List of response message IDs we've already received 4929 | -- so we can ignore duplicates. 4930 | local receivedIDs = {} 4931 | -- Set a timer for when the timeout expires. 4932 | local timer = os.startTimer((type(timeout) == "number") and timeout or 5) 4933 | while true do 4934 | -- Wait for either a modem_message or timer event. 4935 | local event = {os.pullEvent()} 4936 | if event[1] == "modem_message" and event[3] == channel then 4937 | -- See if this is a CryptoNet-formatted message and exract its contents. 4938 | local message = extractMessage(event[5], receivedIDs) 4939 | -- If the message is a valid connection_response directed at this socket, 4940 | -- containing a valid encrypted message... 4941 | if message ~= nil and message.msgType == "connection_response" and message.target == encryptedKey and type(message.message) == "table" 4942 | and #message.message == 2 and type(message.message[1]) == "table" and type(message.message[2]) == "table" then 4943 | -- Decrypt using the session key. 4944 | local ok, actualResponse = pcall(aes.decrypt_str, bytesToString(message.message[1]), sessKey, message.message[2]) 4945 | -- Compare the response to what we know the response content is supposed 4946 | -- to be, to see if the session key was received correctly. 4947 | if ok and actualResponse == expectedResponse then 4948 | log("Connection successful.") 4949 | -- Once we have received a valid response we know the connection has 4950 | -- been opened on the server, so we can stop listening. 4951 | os.cancelTimer(timer) 4952 | break 4953 | else 4954 | log("Received an invalid response.") 4955 | end 4956 | end 4957 | elseif event[1] == "timer" and event[2] == timer then 4958 | -- If the timeout expires abort the connection attempt. 4959 | -- Close the modem channel if it wasn't open before we started. 4960 | if not wasOpen then 4961 | modem.close(channel) 4962 | end 4963 | error("Did not receive a response before timeout.", 2) 4964 | end 4965 | end 4966 | 4967 | -- Create and return the socket object. 4968 | local socket = {sender=encryptedKey, target=serverName, key=sessKey, modemSide=modemSide, channel=channel, permissionLevel=0, receivedMessages={}} 4969 | table.insert(allClientSockets, socket) 4970 | return socket 4971 | end 4972 | 4973 | 4974 | -- 4975 | -- EVENT LOOP 4976 | -- 4977 | 4978 | -- Run a background loop that listens for events of any kind, and calls 4979 | -- an optional event handler on every event. 4980 | -- The event handler is always called in a new thread, so it is okay to use 4981 | -- blocking functions such as sleep() and pullEvent() within onEvent 4982 | -- without freezing the whole program. Errors raised during event handling 4983 | -- are printed without terminating the whole program, so errors processing one 4984 | -- event won't bring down the entire system. 4985 | -- 4986 | -- Any modem_message events are also sent to CryptoNet for handling, 4987 | -- allowing all sockets and servers on this machine to listen for messages 4988 | -- in the background. Both the modem_message itself and any CryptoNet events invoked 4989 | -- by it are sent to the event handler, on seperate iterations of the event loop. 4990 | local function eventLoop(onEvent) 4991 | -- List of response message IDs we've already received 4992 | -- so we can ignore duplicates. 4993 | local receivedIDs = {} 4994 | while true do 4995 | -- Wrap everything in pcall so any errors won't exit the entire program, 4996 | -- only this iteration of the loop. 4997 | local ok, msg = pcall(function() 4998 | -- Listen for all event types. 4999 | local event = {os.pullEvent()} 5000 | if event[1] == "modem_message" then 5001 | local newEvent = handleModemEvent(event, receivedIDs) 5002 | if newEvent ~= nil then 5003 | -- This event will be processed on a later iteration of the loop. 5004 | os.queueEvent(table.unpack(newEvent)) 5005 | end 5006 | end 5007 | -- Call the event handler in a new thread. 5008 | if onEvent ~= nil then 5009 | os.startThread(function () 5010 | -- We need another pcall here since this is in a different thread 5011 | -- to the outer pcall, so that one won't be able to catch errors 5012 | -- from the handler. 5013 | local ok, msg = pcall(onEvent, event) 5014 | if not ok then 5015 | -- Make sure pressing Ctrl+T can still terminate the program. 5016 | if msg == "Terminated" then 5017 | error("Terminated", 0) 5018 | else 5019 | -- Print the error without crashing. 5020 | print(msg) 5021 | end 5022 | end 5023 | end) 5024 | end 5025 | end) 5026 | if not ok then 5027 | -- Make sure pressing Ctrl+T can still terminate the program. 5028 | if msg == "Terminated" then 5029 | error("Terminated", 0) 5030 | else 5031 | -- Print the error without crashing. 5032 | print(msg) 5033 | end 5034 | end 5035 | end 5036 | end 5037 | 5038 | 5039 | -- Run a background loop that listens for events of any kind, and calls 5040 | -- the given event handler (which should take one argument) on them. 5041 | -- The event handler is always called in a new thread, so it is okay to use 5042 | -- blocking functions such as sleep() and pullEvent() within onEvent 5043 | -- without freezing the whole program. Errors raised during event handling 5044 | -- are printed without terminating the whole program, so errors processing one 5045 | -- event won't bring down the entire system. 5046 | -- 5047 | -- Any modem_message events are also sent to CryptoNet for handling, 5048 | -- allowing all sockets and servers on this machine to listen for messages 5049 | -- in the background. Both the modem_message itself and any CryptoNet events invoked 5050 | -- by it are sent to the event handler, on separate iterations of the event loop. 5051 | -- 5052 | -- The onStart function is called once after the loop starts, 5053 | -- after the threading system has been started. 5054 | -- onStart and onEvent are both optional. 5055 | -- os.startThread() can be called from within onStart and onEvent 5056 | -- (and any functions called by them) to start new threads without blocking 5057 | -- the current one. 5058 | function startEventLoop(onStart, onEvent) 5059 | if onStart ~= nil and type(onStart) ~= "function" then 5060 | error("onStart is not a function.", 2) 5061 | end 5062 | if onEvent ~= nil and type(onEvent) ~= "function" then 5063 | error("onEvent is not a function.", 2) 5064 | end 5065 | 5066 | -- Start the threading system so os.startThread() can be used. 5067 | threadAPI.startThreading(function () 5068 | -- Start the actual event loop in a different thread. 5069 | os.startThread(function () eventLoop(onEvent) end) 5070 | -- Call onStart in this thread. 5071 | if onStart ~= nil then 5072 | local ok, msg = pcall(onStart) 5073 | if not ok then 5074 | -- Print the error without crashing. 5075 | print(msg) 5076 | end 5077 | end 5078 | end) 5079 | end 5080 | 5081 | 5082 | -- 5083 | -- CERTIFICATE AUTHORITY 5084 | -- 5085 | 5086 | -- Generate the public and private keys used by a certificate authority 5087 | -- to sign certificates. The keys will be written to the specified files, 5088 | -- which both have sensible default names. 5089 | function initCertificateAuthority(publicFilename, privateFilename) 5090 | if publicFilename == nil then 5091 | publicFilename = "certAuth.key" 5092 | end 5093 | if privateFilename == nil then 5094 | privateFilename = "certAuth_private.key" 5095 | end 5096 | -- Math paths relative to the current CryptoNet working directory. 5097 | local publicPath = workingDir == "" and publicFilename or workingDir.."/"..publicFilename 5098 | local privatePath = workingDir == "" and privateFilename or workingDir.."/"..privateFilename 5099 | 5100 | if fs.exists(publicPath) then 5101 | error(publicPath.." already exists, please delete both your existing keyfiles in order to generate new ones.", 2) 5102 | end 5103 | if fs.exists(privatePath) then 5104 | error(privatePath.." already exists, please delete both your existing keyfiles in order to generate new ones.", 2) 5105 | end 5106 | 5107 | log("Generating key pair... (may take some time)") 5108 | publicKey, privateKey = rsaKeygen.generateKeyPair() 5109 | print("") 5110 | log("Done!") 5111 | 5112 | local file = fs.open(publicPath, "w") 5113 | file.write(serializeCertOrKey(publicKey)) 5114 | file.close() 5115 | log("Saved public key to "..publicPath..". Give this to client users.") 5116 | 5117 | file = fs.open(privatePath, "w") 5118 | file.write(serializeCertOrKey(privateKey)) 5119 | file.close() 5120 | log("Saved private key to "..privatePath..". Do not share this with anyone!") 5121 | 5122 | log("Initialization successful.") 5123 | end 5124 | 5125 | 5126 | -- Sign a certificate using the certificate authority's private key. 5127 | -- Both arguments can either be the certificate/key itself, or a path to 5128 | -- a file that contains it. The signed certificate is returned, and written 5129 | -- to the path the certificate was stored in, if it was loaded from file. 5130 | function signCertificate(certificate, privateKey) 5131 | local certPath = nil 5132 | if type(certificate) == "string" then 5133 | -- Make paths relative to the current CryptoNet working directory. 5134 | certPath = workingDir == "" and certificate or workingDir.."/"..certificate 5135 | if not fs.exists(certPath) then 5136 | error(certPath.." does not exist.", 2) 5137 | end 5138 | if fs.isDir(certPath) then 5139 | error(certPath.." is not a file.", 2) 5140 | end 5141 | 5142 | local file = fs.open(certPath, "r") 5143 | certificate = deserializeCertOrKey(file.readAll()) 5144 | file.close() 5145 | 5146 | if not certificateValid(certificate) then 5147 | error(certPath.." does not contain a valid certificate.", 2) 5148 | end 5149 | log("Loaded certificate from "..certPath..".") 5150 | elseif not certificateValid(certificate) then 5151 | -- If certificate is not a file path it should be a valid certificate. 5152 | error("Not a valid certificate or file.", 2) 5153 | end 5154 | 5155 | -- Default value. 5156 | if privateKey == nil then 5157 | privateKey = "certAuth_private.key" 5158 | end 5159 | if type(privateKey) == "string" then 5160 | -- Make paths relative to the current CryptoNet working directory. 5161 | local keyPath = workingDir == "" and privateKey or workingDir.."/"..privateKey 5162 | if not fs.exists(keyPath) then 5163 | error(keyPath.." does not exist.", 2) 5164 | end 5165 | if fs.isDir(keyPath) then 5166 | error(keyPath.." is not a file.", 2) 5167 | end 5168 | 5169 | local file = fs.open(keyPath, "r") 5170 | privateKey = deserializeCertOrKey(file.readAll()) 5171 | file.close() 5172 | 5173 | if not privateKeyValid(privateKey) then 5174 | error(keyPath.." does not contain a valid private key.", 2) 5175 | end 5176 | log("Loaded private key from "..keyPath..".") 5177 | elseif not privateKeyValid(privateKey) then 5178 | -- If privateKey is not a file path it should be a valid private key. 5179 | error("Not a valid private key or file.", 2) 5180 | end 5181 | 5182 | -- The signature is just the contents of the certificate hashed and encrypted. 5183 | -- Clients can verify the signature by decrypting it with the cert auth public key 5184 | -- and seeing if it matches the contents of the certificate. 5185 | log("Generating signature...") 5186 | local hash = sha256.digest(certificate.name..certificate.key.public..certificate.key.shared) 5187 | certificate.signature = rsaCrypt.crypt(privateKey, rsaCrypt.bytesToNumber(hash, 32*8, 8)) 5188 | 5189 | -- If the certificate was loaded from a file, save it back there. 5190 | if certPath ~= nil then 5191 | local file = fs.open(certPath, "w") 5192 | file.write(serializeCertOrKey(certificate)) 5193 | file.close() 5194 | log("Saved certificate to "..certPath..".") 5195 | end 5196 | return certificate 5197 | end 5198 | 5199 | -- CryptoNet's command line interface, used by a certificate authority 5200 | -- to sign certificates. 5201 | -- Supports two commands: initCertAuth and signCert. 5202 | -- 5203 | -- initCertAuth is used to generate the keys used to sign and verify certificates. 5204 | -- The public key should be distributed to all clients using the certificate 5205 | -- authority, while the private key should be kept secure on the cert auth's 5206 | -- machine. 5207 | -- 5208 | -- Certificates to be signed should be copied to the cert auth machine, 5209 | -- e.g. using floppy disks. signCert is then used to sign the certificate, 5210 | -- which can then be transferred back to the server machine. 5211 | -- Only sign the certificates of trusted servers, and don't sign two certificates 5212 | -- with the same name and different public keys. 5213 | 5214 | -- Only run if executed on the command line, not when imported. 5215 | if shell ~= nil and (debug.getinfo(2) == nil or debug.getinfo(2).name ~= "require") then 5216 | setLoggingEnabled(true) 5217 | -- Set the CryptoNet working directory to match the system one. 5218 | setWorkingDirectory(shell.dir()) 5219 | 5220 | local args = {...} 5221 | if args[1] == "signCert" then 5222 | -- Sign a certificate loaded from a file. 5223 | local certPath = args[2] 5224 | if certPath == nil then 5225 | log("Usage: cryptoNet signCert ") 5226 | return 5227 | end 5228 | 5229 | -- Make paths relative to the working directory. 5230 | certPath = workingDir == "" and certPath or workingDir.."/"..certPath 5231 | -- Optional private key file argument, can be omitted to use default. 5232 | local keyPath = args[3] 5233 | local ok, msg = pcall(signCertificate, certPath, keyPath) 5234 | 5235 | if not ok then 5236 | log("Error: "..msg:sub(8)) 5237 | end 5238 | elseif args[1] == "initCertAuth" then 5239 | -- Generate the cert auth key pair and save them to the specified files. 5240 | -- The file arguments can be omitted to use the default values. 5241 | local ok, msg = pcall(initCertificateAuthority, args[2], args[3]) 5242 | if not ok then 5243 | log("Error: "..msg:sub(8)) 5244 | end 5245 | else 5246 | log("Invalid command.") 5247 | end 5248 | end 5249 | 5250 | -- 5251 | -- MODULE EXPORT 5252 | -- 5253 | 5254 | return { 5255 | getLoggingEnabled = getLoggingEnabled, 5256 | setLoggingEnabled = setLoggingEnabled, 5257 | getRepeatMessages = getRepeatMessages, 5258 | setRepeatMessages = setRepeatMessages, 5259 | getWorkingDirectory = getWorkingDirectory, 5260 | setWorkingDirectory = setWorkingDirectory, 5261 | getAllServers = getAllServers, 5262 | getAllClientSockets = getAllClientSockets, 5263 | keyValid = keyValid, 5264 | privateKeyValid = privateKeyValid, 5265 | publicKeyValid = publicKeyValid, 5266 | certificateValid = certificateValid, 5267 | serverValid = serverValid, 5268 | socketValid = socketValid, 5269 | userTableValid = userTableValid, 5270 | resolveModemSide = resolveModemSide, 5271 | getChannel = getChannel, 5272 | channelInUse = channelInUse, 5273 | serializeCertOrKey = serializeCertOrKey, 5274 | deserializeCertOrKey = deserializeCertOrKey, 5275 | generateKey = generateKey, 5276 | generateCertificate = generateCertificate, 5277 | loadCertAuthKey = loadCertAuthKey, 5278 | verifyCertificate = verifyCertificate, 5279 | send = send, 5280 | sendUnencrypted = sendUnencrypted, 5281 | hashPassword = hashPassword, 5282 | loadUserTable = loadUserTable, 5283 | saveUserTable = saveUserTable, 5284 | addUserHashed = addUserHashed, 5285 | addUser = addUser, 5286 | deleteUser = deleteUser, 5287 | userExists = userExists, 5288 | getPasswordHash = getPasswordHash, 5289 | getPermissionLevel = getPermissionLevel, 5290 | setPasswordHashed = setPasswordHashed, 5291 | setPassword = setPassword, 5292 | setPermissionLevel = setPermissionLevel, 5293 | checkPasswordHashed = checkPasswordHashed, 5294 | checkPassword = checkPassword, 5295 | loginHashed = loginHashed, 5296 | login = login, 5297 | logout = logout, 5298 | host = host, 5299 | close = close, 5300 | closeAll = closeAll, 5301 | listen = listen, 5302 | discover = discover, 5303 | requestCertificate = requestCertificate, 5304 | connect = connect, 5305 | startEventLoop = startEventLoop, 5306 | initCertificateAuthority = initCertificateAuthority, 5307 | signCertificate = signCertificate 5308 | } 5309 | -------------------------------------------------------------------------------- /door.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SiliconSloth/CryptoNet/dcfcf94220aaea39bdc6b86da6afa8f247b20f51/door.png -------------------------------------------------------------------------------- /doorExample.md: -------------------------------------------------------------------------------- 1 | # Password Secured Door 2 | 3 | This example will show you how CryptoNet can be applied to a common application in ComputerCraft, 4 | password locked doors. The user opens the door by entering a username and password on a client 5 | machine next to the door. If they log in successfully, a server hidden below the door will open 6 | the door, then close it again after the user has walked through. Since the server is buried in 7 | the ground and the user can only interact directly with the client machine, the user cannot 8 | simply close the program and turn on the redstone signal manually. CryptoNet's 9 | secure hashed password storage and encrypted networking make it ideal for this task. 10 | 11 | ![Setup](door.png) 12 | 13 | ##### Client: 14 | ```lua 15 | os.loadAPI("cryptoNet") 16 | 17 | -- Ask the user for their username and password and send it to the server. 18 | function enterDetails(socket) 19 | write("Name: ") 20 | local name = read() 21 | write("Password: ") 22 | local password = read("*") 23 | cryptoNet.login(socket, name, password) 24 | print("Logging in...") 25 | -- Now we wait for onEvent() to pick up the result. 26 | end 27 | 28 | -- Connect to the server when the program starts. 29 | function onStart() 30 | print("Connecting...") 31 | local socket = cryptoNet.connect("CryptoDoor") 32 | print("Connected.") 33 | enterDetails(socket) 34 | end 35 | 36 | function onEvent(event) 37 | local msgType = event[1] 38 | -- The user logged in successfully, and the door has opened. 39 | if msgType == "login" then 40 | print("Welcome!") 41 | -- The user got the username or password wrong, so ask them to enter it again. 42 | elseif msgType == "login_failed" then 43 | print("Bad credentials. Go away!") 44 | local socket = event[3] 45 | enterDetails(socket) 46 | -- The user has been logged out by the server, which it does after the door 47 | -- has been closed. Prompt the user for their details again. 48 | elseif msgType == "logout" then 49 | print("Door closed.") 50 | local socket = event[3] 51 | enterDetails(socket) 52 | end 53 | end 54 | 55 | cryptoNet.setLoggingEnabled(false) 56 | cryptoNet.startEventLoop(onStart, onEvent) 57 | ``` 58 | 59 | ##### Server: 60 | ```lua 61 | os.loadAPI("cryptoNet") 62 | 63 | function onEvent(event) 64 | -- Open the door when a user logs in successfully. 65 | if event[1] == "login" then 66 | print("Opening door...") 67 | -- Assume the door is above the computer. 68 | rs.setOutput("top", true) 69 | 70 | -- Wait for the user to walk over the pressure plate behind the door. 71 | while not rs.getInput("back") do 72 | os.pullEvent("redstone") 73 | end 74 | 75 | -- Close the door behind the user, then log out ready for the next person. 76 | rs.setOutput("top", false) 77 | print("Door closed.") 78 | cryptoNet.logout(event[3]) 79 | end 80 | end 81 | 82 | function onStart() 83 | -- Set the server to not responsd to discovery requests for extra security. 84 | -- For extra security we could set hideCertificate to true and copy the .crt 85 | -- file to the client computer, to stop attackers imitating the server. 86 | cryptoNet.host("CryptoDoor", false) 87 | end 88 | 89 | cryptoNet.startEventLoop(onStart, onEvent) 90 | ``` 91 | 92 | ##### Adding users to the server: 93 | ```lua 94 | -- This can just be run in the interactive Lua prompt 95 | os.loadAPI("cryptoNet") 96 | cryptoNet.host("CryptoDoor") 97 | cryptoNet.addUser("Bobby", "mypass123") 98 | cryptoNet.closeAll() 99 | ``` 100 | --------------------------------------------------------------------------------