Tatantyler

Deep Freeze

Oct 16th, 2012
554
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 10.33 KB | None | 0 0
  1. -- Full-Disk Encryption
  2.  
  3. local startupStub = [[
  4.     local oldOSPull = os.pullEvent
  5.     os.pullEvent = os.pullEventRaw
  6.     os.loadAPI("arcfour")
  7.    
  8.     local function getAllFilesInDir(dir, includeDirs)
  9.         dir = dir or ""
  10.         local files = {}
  11.         for i,v in ipairs(fs.list(dir)) do
  12.             if fs.isDir(dir.."/"..v) then
  13.                 if string.sub(v, 1,4) ~= "disk" and v ~= "rom" then
  14.                     if includeDirs then
  15.                         table.insert(files, v)
  16.                     end
  17.                     for i2, v2 in ipairs(getAllFilesInDir(dir.."/"..v, includeDirs)) do
  18.                         table.insert(files, v.."/"..v2)
  19.                     end
  20.                 end
  21.             else
  22.                 table.insert(files, v)
  23.             end
  24.         end
  25.         return files
  26.     end
  27.    
  28.     local function unpackFiles(files)
  29.         for i,v in pairs(files) do
  30.             local fileName = fs.getName(i)
  31.             local nameBegin = string.find(i, fileName)-1
  32.             if nameBegin then
  33.                 if not fs.exists(string.sub(i, 1, nameBegin)) then
  34.                     fs.makeDir(string.sub(i, 1, nameBegin))
  35.                 end
  36.                 local handle = fs.open(i, "w")
  37.                 handle.write(v)
  38.                 handle.close()
  39.             end
  40.         end
  41.     end
  42.    
  43.     if fs.exists "HDD" then
  44.         print "This computer's files have been encrypted."
  45.         print "Please enter your password."
  46.         local encrypt_key = read()
  47.         if #encrypt_key == 0 then
  48.             print("Invalid input.")
  49.             os.sleep(2)
  50.             os.reboot()
  51.         end
  52.         local handle = fs.open("HDD", "rb")
  53.         local bytes = {}
  54.         while true do
  55.             local byte = handle.read()
  56.             if byte then
  57.                 table.insert(bytes, byte)
  58.             else
  59.                 break
  60.             end
  61.         end
  62.         handle.close()
  63.         local ciphertext = string.char(unpack(bytes))
  64.         local files = arcfour.rc4_cipher(encrypt_key, ciphertext)
  65.         files = textutils.unserialize(files)
  66.         if type(files) == "table" then
  67.             unpackFiles(files)
  68.         else
  69.             print "Incorrect key/invalid file!"
  70.             os.sleep(2)
  71.             os.shutdown()
  72.         end
  73.     end
  74.    
  75.     local oldFSOpen = fs.open
  76.     local oldFSMove = fs.delete
  77.     local oldFSCopy = fs.copy
  78.     local oldFSDelete = fs.delete
  79.    
  80.     local oldShutdown = os.shutdown
  81.     os.shutdown = function()
  82.         files = getAllFilesInDir("", true)
  83.         for i,v in ipairs(files) do
  84.             if fs.exists(v) and v ~= "startup" and v ~= "HDD" and v ~= "arcfour" then
  85.                 oldFSDelete(v)
  86.             end
  87.         end
  88.         oldShutdown()
  89.     end
  90.    
  91.     local oldReboot = os.reboot
  92.     os.reboot = function()
  93.         files = getAllFilesInDir("", true)
  94.         for i,v in ipairs(files) do
  95.             if fs.exists(v) and v ~= "startup" and v ~= "HDD" and v ~= "arcfour" then
  96.                 oldFSDelete(v)
  97.             end
  98.         end
  99.         oldReboot()
  100.     end
  101.    
  102.     fs.open = function(file, mode)
  103.         if file ~= "startup" and file ~= "arcfour" and file ~= "HDD" then
  104.             return oldFSOpen(file, mode)
  105.         end
  106.     end
  107.    
  108.     fs.delete = function(file)
  109.         if file ~= "startup" and file ~= "arcfour" and file ~= "HDD" then
  110.             return oldFSDelete(file)
  111.         end
  112.     end
  113.    
  114.     fs.move = function(from, to)
  115.         if (to ~= "startup" and to ~= "arcfour" and to ~= "HDD") and (from ~= "startup" and from ~= "arcfour" and from ~= "HDD") then
  116.             return oldFSMove(from, to)
  117.         end
  118.     end
  119.    
  120.     fs.copy = function(from, to)
  121.         if (to ~= "startup" and to ~= "arcfour" and to ~= "HDD") and (from ~= "startup" and from ~= "arcfour" and from ~= "HDD") then
  122.             return oldFSCopy(from, to)
  123.         end
  124.     end
  125.    
  126.     if fs.exists("startup_2") then
  127.         os.pullEvent = oldOSPull
  128.         shell.run("startup_2")
  129.     else
  130.         shell.run("shell")
  131.     end
  132.    
  133.     os.shutdown()
  134.  
  135. ]]
  136.  
  137. local arc4API = [[
  138.  
  139. -- ARCFOUR implementation in pure Lua
  140. -- Copyright 2008 Rob Kendrick <rjek@rjek.com>
  141. -- Distributed under the MIT licence
  142. --[=[
  143. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated document
  144. ation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to
  145.  use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
  146.  to whom the Software is furnished to do so, subject to the following conditions:
  147.  
  148. The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
  149. Software.
  150.  
  151. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  152. WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  153. COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  154. OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  155. ]=]--
  156. -- To create a new context;
  157. --  rc4_context = arcfour.new_arc4(optional_key_string)
  158. --
  159. -- To schedule a key
  160. --  rc4_context:schedule(key_string)
  161. --
  162. -- To generate a string of bytes of "random" data from the generator
  163. --  bytes = rc4_context:generate(number_of_bytes)
  164. --
  165. -- To encrypt/decrypt a string
  166. --  ciphertext = rc4_context:cipher(plaintext)
  167. --
  168. -- Example usage;
  169. --  enc_state = arcfour.new "My Encryption Key"
  170. --  enc_state:generate(3072)
  171. --  ciphertext = enc_state:rc4_cipher "Hello, world!"
  172. --
  173. --  dec_state = arcfour.new "My Encryption Key"
  174. --  dec_state:generate(3072)
  175. --  plaintext = dec_state:rc4_cipher(ciphertext)
  176. --
  177. -- Best practise says to discard the first 3072 bytes from the generated
  178. -- stream to avoid leaking information about the key.  Additionally, if using
  179. -- a nonce, you should hash your key and nonce together, rather than
  180. -- concatenating them.
  181.  
  182. -- Given a binary boolean function b(x,y) defined by a table
  183. -- of four bits { b(0,0), b(0,1), b(1,0), b(1,1) },
  184. -- return a 2D lookup table f[][] where f[x][y] is b() applied
  185. -- bitwise to the lower eight bits of x and y.
  186.  
  187. local function make_byte_table(bits)
  188.     local f = { }
  189.     for i = 0, 255 do
  190.         f[i] = { }
  191.     end
  192.    
  193.     f[0][0] = bits[1] * 255
  194.  
  195.     local m = 1
  196.    
  197.     for k = 0, 7 do
  198.         for i = 0, m - 1 do
  199.             for j = 0, m - 1 do
  200.                 local fij = f[i][j] - bits[1] * m
  201.                 f[i  ][j+m] = fij + bits[2] * m
  202.                 f[i+m][j  ] = fij + bits[3] * m
  203.                 f[i+m][j+m] = fij + bits[4] * m
  204.             end
  205.         end
  206.         m = m * 2
  207.     end
  208.    
  209.     return f
  210. end
  211.  
  212. local byte_xor = make_byte_table { 0, 1, 1, 0 }
  213.  
  214. local function generate(self, count)
  215.     local S, i, j = self.S, self.i, self.j
  216.     local o = { }
  217.     local char = string.char
  218.    
  219.     for z = 1, count do
  220.         i = (i + 1) % 256
  221.         j = (j + S[i]) % 256
  222.         S[i], S[j] = S[j], S[i]
  223.         o[z] = char(S[(S[i] + S[j]) % 256])
  224.     end
  225.    
  226.     self.i, self.j = i, j
  227.     return table.concat(o)
  228. end
  229.  
  230. local function cipher(self, plaintext)
  231.     local pad = generate(self, #plaintext)
  232.     local r = { }
  233.     local byte = string.byte
  234.     local char = string.char
  235.    
  236.     for i = 1, #plaintext do
  237.         r[i] = char(byte_xor[byte(plaintext, i)][byte(pad, i)])
  238.     end
  239.    
  240.     return table.concat(r)
  241. end
  242.  
  243. local function schedule(self, key)
  244.     local S = self.S
  245.     local j, kz = 0, #key
  246.     local byte = string.byte
  247.    
  248.     for i = 0, 255 do
  249.         j = (j + S[i] + byte(key, (i % kz) + 1)) % 256;
  250.         S[i], S[j] = S[j], S[i]
  251.     end
  252. end
  253.  
  254. function new_arc4(key)
  255.     local S = { }
  256.     local r = {
  257.         S = S, i = 0, j = 0,
  258.         generate = generate,
  259.         cipher = cipher,
  260.         schedule = schedule
  261.     }
  262.    
  263.     for i = 0, 255 do
  264.         S[i] = i
  265.     end
  266.    
  267.     if key then
  268.         r:schedule(key)
  269.     end
  270.    
  271.     return r   
  272. end
  273.  
  274. function rc4_cipher(key, text)
  275.     local rc4 = new_arc4(key)
  276.     rc4:generate(3072)
  277.     local encrypted = rc4:cipher(text)
  278.     return encrypted
  279. end
  280.  
  281. ]]
  282. local args = {...}
  283.  
  284. if term.setTextColor == nil or not term.isColor() then
  285.     local oldTermSetTextColor = term.setTextColor
  286.     term.setTextColor = function() -- Pre-1.45 compatibility stub
  287.         return
  288.     end
  289. end
  290.  
  291.  
  292. local function getAllFilesInDir(dir, includeDirs)
  293.     dir = dir or ""
  294.     local files = {}
  295.     for i,v in ipairs(fs.list(dir)) do
  296.         if fs.isDir(dir.."/"..v) then
  297.             if string.sub(v, 1,4) ~= "disk" and v ~= "rom" then
  298.                 if includeDirs then
  299.                     table.insert(files, v)
  300.                 end
  301.                 for i2, v2 in ipairs(getAllFilesInDir(dir.."/"..v, includeDirs)) do
  302.                     table.insert(files, v.."/"..v2)
  303.                 end
  304.             end
  305.         else
  306.             table.insert(files, v)
  307.         end
  308.     end
  309.     return files
  310. end
  311.  
  312. local function packFiles(password, includeSelf)
  313.     if fs.exists("startup") then
  314.         fs.move("startup", "startup_2")
  315.     end
  316.     local fileList = getAllFilesInDir("", false)
  317.     local files = {}
  318.     for i,v in ipairs(fileList) do
  319.         if v ~= "arcfour" and v ~= "startup" and (v ~= shell.getRunningProgram() or includeSelf ~= nil) and v ~= "HDD" then
  320.             local handle = fs.open(v, "r")
  321.             local data = handle.readAll()
  322.             handle.close()
  323.             files[v] = data
  324.         end
  325.     end
  326.     local filesStr = textutils.serialize(files)
  327.     local ciphertext = arcfour.rc4_cipher(password, filesStr)
  328.     local cipherbytes = {}
  329.     for i=1, #ciphertext do
  330.         table.insert(cipherbytes, string.byte(ciphertext, i, i))
  331.     end
  332.     if fs.getFreeSpace("/") < #cipherbytes then
  333.         error "Insufficent space"
  334.     end
  335.     local handle = fs.open("HDD", "wb")
  336.     if handle then
  337.         for i=1, #cipherbytes do
  338.             term.clear()
  339.             term.setCursorPos(1,1)
  340.             term.setTextColor(colors.white)
  341.             print("Currently writing to hard drive image. This may take some time.")
  342.             for i=1, term.getSize()-1 do
  343.                 write("=")
  344.             end
  345.             print("Byte: "..i.."/"..#cipherbytes)
  346.             local progress = math.ceil(i/#cipherbytes*100)
  347.             print("Progress: "..progress.."%")
  348.             local num_bars = math.floor(progress/2)
  349.             print(" ")
  350.             for i=1, term.getSize()-1 do
  351.                 write("=")
  352.             end
  353.             term.setTextColor(colors.lime)
  354.             for i=1, num_bars do
  355.                 write("#")
  356.             end
  357.             term.setCursorPos(1, 9)
  358.             term.setTextColor(colors.white)
  359.             for i=1, term.getSize()-1 do
  360.                 write("=")
  361.             end
  362.             handle.write(cipherbytes[i])
  363.             os.sleep(0)
  364.         end
  365.         handle.close()
  366.         local startupHandle = fs.open("startup", "w")
  367.         startupHandle.write(startupStub)
  368.         startupHandle.close()
  369.         term.clear()
  370.         term.setCursorPos(1,1)
  371.         write("Writing complete. Restart now? (Y/N) >")
  372.         local yn = read()
  373.         yn = string.upper(yn)
  374.         if yn == "Y" then
  375.             os.reboot()
  376.         end
  377.     else
  378.         error("Couldn't open hard drive image!")
  379.     end
  380. end
  381.  
  382. if #args == 1 then
  383.     local handle = fs.open("arcfour", "w")
  384.     handle.write(arc4API)
  385.     handle.close()
  386.     os.loadAPI("arcfour")
  387.     if fs.exists "HDD" then
  388.         print("There already appears to be a hard drive image here.")
  389.         print("You cannot encrypt a frozen volume twice.")
  390.         write("Overwrite? (Y/N)> ")
  391.         local yn = read()
  392.         yn = string.upper(yn)
  393.         if yn ~= "Y" then
  394.             error("Cannot freeze volume twice")
  395.         end
  396.     end
  397.     packFiles(args[1], args[2])
  398. else
  399.     print("USAGE: "..fs.getName(shell.getRunningProgram()).." [password] [include encryptor]")
  400. end
  401.  
  402. local oldTermSetTextColor = term.setTextColor
  403. term.setTextColor = oldTermSetTextColor
Add Comment
Please, Sign In to add comment