Advertisement
HydrantHunter

cc10 Host

Jun 12th, 2013
3,726
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 58.07 KB | None | 0 0
  1. --[[     cc10 Host     ]]--
  2. --[[      by Dog       ]]--
  3. --[[ aka HydrantHunter ]]--
  4. --[[ pastebin CR92ZjdE ]]--
  5. local cc10Hver = "2.0.04"
  6. --[[
  7. Tested with/requires:
  8.   - Minecraft 1.6.4+
  9.   - ComputerCraft 1.63+
  10.     - A Computer (standard or advanced) with a wireless modem, or a Wireless Turtle (standard or advanced)
  11.     - cc10 Remote running on an Advanced Wireless Pocket Computer
  12.  
  13. Special thanks to: Anavrins   (pbkdf2/sha256 hashing)
  14.                    SquidDev   (AES encryption/decryption)
  15.                    Alex Kloss (base64 encoder/decoder)
  16. ]]--
  17. local tArgs = { ... }
  18. --# CONFIGURATION
  19. --# Default Settings
  20. local termX, termY = term.getSize()
  21. local thisCC = tostring(os.getComputerID())
  22. local config = "/data/cc10HostCfg"
  23. local ccSettings = {
  24.   side = "top";
  25.   state = 0;
  26.   outputType = "UD";
  27.   onState = 15;
  28.   restore = true;
  29.   name = "cc10host";
  30.   note = "short note";
  31.   color = "I";
  32.   password = false;
  33.   newColors = true;
  34.   hashedPWs = false;
  35.   loc = { dim = "Overworld", x = "No GPS Fix", y = "No GPS Fix", z = "No GPS Fix" };
  36. }
  37. local cc10Types = {
  38.   A = "Analog           ";
  39.   UA = "Universal Analog ";
  40.   D = "Digital          ";
  41.   UD = "Universal Digital";
  42.   PS = "Pulsed (short)   ";
  43.   PL = "Pulsed (long)    ";
  44.   P3 = "Pulsed (3 pulses)";
  45. }
  46. local newCmdData, unlockedClients = { }, { }
  47. unlockedClients.count = 0
  48. local netSide = "none"
  49. local lockState = false
  50. local client, ccKernel
  51. --# Color Definitions
  52. local white = colors.white
  53. local black = colors.black
  54. local gray = colors.gray
  55. local silver = colors.lightGray
  56. local brown = colors.brown
  57. local orange = colors.orange
  58. local red = colors.red
  59. local green = colors.green
  60. local blue = colors.blue
  61. local sky = colors.lightBlue
  62. local purple = colors.purple
  63. if not term.isColor() then
  64.   gray = colors.black
  65.   silver = colors.white
  66.   brown = colors.white
  67.   orange = colors.white
  68.   red = colors.white
  69.   green = colors.white
  70.   blue = colors.black
  71.   sky = colors.white
  72.   purple = colors.white
  73. end
  74. local colorBurst = {
  75.   P = { "Purple", purple };
  76.   B = { "Blue", blue };
  77.   S = { "Sky", sky };
  78.   G = { "Green", green };
  79.   R = { "Red", red };
  80.   O = { "Orange", orange };
  81.   N = { "Brown", brown };
  82.   I = { "Silver", silver };
  83. }
  84. --# END CONFIGURATION
  85.  
  86. -- Lua 5.1+ base64 v3.0 (c) 2009 by Alex Kloss <alexthkloss@web.de>
  87. -- licensed under the terms of the LGPL2
  88. -- http://lua-users.org/wiki/BaseSixtyFour
  89. -- character table string
  90. local b='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
  91. -- encoding
  92. function encode(data)
  93.   return ((data:gsub('.', function(x)
  94.     local r,b='',x:byte()
  95.     for i=8,1,-1 do r=r..(b%2^i-b%2^(i-1)>0 and '1' or '0') end
  96.     return r;
  97.   end)..'0000'):gsub('%d%d%d?%d?%d?%d?', function(x)
  98.     if (#x < 6) then return '' end
  99.     local c=0
  100.     for i=1,6 do c=c+(x:sub(i,i)=='1' and 2^(6-i) or 0) end
  101.     return b:sub(c+1,c+1)
  102.   end)..({ '', '==', '=' })[#data%3+1])
  103. end
  104. -- decoding
  105. function decode(data)
  106.   data = string.gsub(data, '[^'..b..'=]', '')
  107.   return (data:gsub('.', function(x)
  108.     if (x == '=') then return '' end
  109.     local r,f='',(b:find(x)-1)
  110.     for i=6,1,-1 do r=r..(f%2^i-f%2^(i-1)>0 and '1' or '0') end
  111.     return r;
  112.   end):gsub('%d%d%d?%d?%d?%d?%d?%d?', function(x)
  113.     if (#x ~= 8) then return '' end
  114.     local c=0
  115.     for i=1,8 do c=c+(x:sub(i,i)=='1' and 2^(8-i) or 0) end
  116.     return string.char(c)
  117.   end))
  118. end
  119.  
  120. -- AES Lua implementation by SquidDev
  121. -- https://gist.github.com/SquidDev/86925e07cbabd70773e53d781bd8b2fe
  122. local encrypt, decrypt
  123. do
  124.   local function _W(f) local e=setmetatable({}, {__index = _ENV or getfenv()}) if setfenv then setfenv(f, e) end return f(e) or e end
  125.   local bit=_W(function(_ENV, ...)
  126.   --[[
  127.     This bit API is designed to cope with unsigned integers instead of normal integers
  128.     To do this we add checks for overflows: (x > 2^31 ? x - 2 ^ 32 : x)
  129.     These are written in long form because no constant folding.
  130.   ]]
  131.   local floor = math.floor
  132.   local lshift, rshift
  133.  
  134.   rshift = function(a,disp)
  135.     return floor(a % 4294967296 / 2^disp)
  136.   end
  137.  
  138.   lshift = function(a,disp)
  139.     return (a * 2^disp) % 4294967296
  140.   end
  141.  
  142.   return {
  143.     -- bit operations
  144.     bnot = bit32 and bit32.bnot or bit.bnot,
  145.     band = bit32 and bit32.band or bit.band,
  146.     bor  = bit32 and bit32.bor or bit.bor,
  147.     bxor = bit32 and bit32.bxor or bit.bxor,
  148.     rshift = rshift,
  149.     lshift = lshift,
  150.   }
  151.   end)
  152.  
  153.   local gf=_W(function(_ENV, ...)
  154.   -- finite field with base 2 and modulo irreducible polynom x^8+x^4+x^3+x+1 = 0x11d
  155.   local bxor = bit32 and bit32.bxor or bit.bxor
  156.   local lshift = bit.lshift
  157.   -- private data of gf
  158.   local n = 0x100
  159.   local ord = 0xff
  160.   local irrPolynom = 0x11b
  161.   local exp = {}
  162.   local log = {}
  163.   --
  164.   -- add two polynoms (its simply xor)
  165.   --
  166.   local function add(operand1, operand2)
  167.     return bxor(operand1,operand2)
  168.   end
  169.   --
  170.   -- subtract two polynoms (same as addition)
  171.   --
  172.   local function sub(operand1, operand2)
  173.     return bxor(operand1,operand2)
  174.   end
  175.   --
  176.   -- inverts element
  177.   -- a^(-1) = g^(order - log(a))
  178.   --
  179.   local function invert(operand)
  180.     -- special case for 1
  181.     if (operand == 1) then
  182.       return 1
  183.     end
  184.     -- normal invert
  185.     local exponent = ord - log[operand]
  186.     return exp[exponent]
  187.   end
  188.   --
  189.   -- multiply two elements using a logarithm table
  190.   -- a*b = g^(log(a)+log(b))
  191.   --
  192.   local function mul(operand1, operand2)
  193.     if (operand1 == 0 or operand2 == 0) then
  194.       return 0
  195.     end
  196.     local exponent = log[operand1] + log[operand2]
  197.     if (exponent >= ord) then
  198.       exponent = exponent - ord
  199.     end
  200.     return exp[exponent]
  201.   end
  202.   --
  203.   -- divide two elements
  204.   -- a/b = g^(log(a)-log(b))
  205.   --
  206.   local function div(operand1, operand2)
  207.     if (operand1 == 0)  then
  208.       return 0
  209.     end
  210.     -- TODO: exception if operand2 == 0
  211.     local exponent = log[operand1] - log[operand2]
  212.     if (exponent < 0) then
  213.       exponent = exponent + ord
  214.     end
  215.     return exp[exponent]
  216.   end
  217.   --
  218.   -- print logarithmic table
  219.   --
  220.   local function printLog()
  221.     for i = 1, n do
  222.       print("log(", i-1, ")=", log[i-1])
  223.     end
  224.   end
  225.   --
  226.   -- print exponentiation table
  227.   --
  228.   local function printExp()
  229.     for i = 1, n do
  230.       print("exp(", i-1, ")=", exp[i-1])
  231.     end
  232.   end
  233.   --
  234.   -- calculate logarithmic and exponentiation table
  235.   --
  236.   local function initMulTable()
  237.     local a = 1
  238.     for i = 0,ord-1 do
  239.       exp[i] = a
  240.       log[a] = i
  241.       -- multiply with generator x+1 -> left shift + 1
  242.       a = bxor(lshift(a, 1), a)
  243.       -- if a gets larger than order, reduce modulo irreducible polynom
  244.       if a > ord then
  245.         a = sub(a, irrPolynom)
  246.       end
  247.     end
  248.   end
  249.  
  250.   initMulTable()
  251.  
  252.   return {
  253.     add = add,
  254.     sub = sub,
  255.     invert = invert,
  256.     mul = mul,
  257.     div = div,
  258.     printLog = printLog,
  259.     printExp = printExp,
  260.   }
  261.   end)
  262.  
  263.   util=_W(function(_ENV, ...)
  264.   -- Cache some bit operators
  265.   local bxor = bit.bxor
  266.   local rshift = bit.rshift
  267.   local band = bit.band
  268.   local lshift = bit.lshift
  269.   local sleepCheckIn
  270.   --
  271.   -- calculate the parity of one byte
  272.   --
  273.   local function byteParity(byte)
  274.     byte = bxor(byte, rshift(byte, 4))
  275.     byte = bxor(byte, rshift(byte, 2))
  276.     byte = bxor(byte, rshift(byte, 1))
  277.     return band(byte, 1)
  278.   end
  279.   --
  280.   -- get byte at position index
  281.   --
  282.   local function getByte(number, index)
  283.     return index == 0 and band(number,0xff) or band(rshift(number, index*8),0xff)
  284.   end
  285.   --
  286.   -- put number into int at position index
  287.   --
  288.   local function putByte(number, index)
  289.     return index == 0 and band(number,0xff) or lshift(band(number,0xff),index*8)
  290.   end
  291.   --
  292.   -- convert byte array to int array
  293.   --
  294.   local function bytesToInts(bytes, start, n)
  295.     local ints = {}
  296.     for i = 0, n - 1 do
  297.       ints[i + 1] =
  298.           putByte(bytes[start + (i*4)], 3) +
  299.           putByte(bytes[start + (i*4) + 1], 2) +
  300.           putByte(bytes[start + (i*4) + 2], 1) +
  301.           putByte(bytes[start + (i*4) + 3], 0)
  302.       if n % 10000 == 0 then sleepCheckIn() end
  303.     end
  304.     return ints
  305.   end
  306.   --
  307.   -- convert int array to byte array
  308.   --
  309.   local function intsToBytes(ints, output, outputOffset, n)
  310.     n = n or #ints
  311.     for i = 0, n - 1 do
  312.       for j = 0,3 do
  313.         output[outputOffset + i*4 + (3 - j)] = getByte(ints[i + 1], j)
  314.       end
  315.       if n % 10000 == 0 then sleepCheckIn() end
  316.     end
  317.     return output
  318.   end
  319.   --
  320.   -- convert bytes to hexString
  321.   --
  322.   local function bytesToHex(bytes)
  323.     local hexBytes = ""
  324.     for i,byte in ipairs(bytes) do
  325.       hexBytes = hexBytes .. string.format("%02x ", byte)
  326.     end
  327.     return hexBytes
  328.   end
  329.  
  330.   local function hexToBytes(bytes)
  331.     local out = {}
  332.     for i = 1, #bytes, 2 do
  333.       out[#out + 1] = tonumber(bytes:sub(i, i + 1), 16)
  334.     end
  335.     return out
  336.   end
  337.   --
  338.   -- convert data to hex string
  339.   --
  340.   local function toHexString(data)
  341.     local type = type(data)
  342.     if (type == "number") then
  343.       return string.format("%08x",data)
  344.     elseif (type == "table") then
  345.       return bytesToHex(data)
  346.     elseif (type == "string") then
  347.       local bytes = {string.byte(data, 1, #data)}
  348.       return bytesToHex(bytes)
  349.     else
  350.       return data
  351.     end
  352.   end
  353.  
  354.   local function padByteString(data)
  355.     local dataLength = #data
  356.     local random1 = math.random(0,255)
  357.     local random2 = math.random(0,255)
  358.     local prefix = string.char(random1,
  359.       random2,
  360.       random1,
  361.       random2,
  362.       getByte(dataLength, 3),
  363.       getByte(dataLength, 2),
  364.       getByte(dataLength, 1),
  365.       getByte(dataLength, 0)
  366.     )
  367.     data = prefix .. data
  368.     local padding, paddingLength = "", math.ceil(#data/16)*16 - #data
  369.     for i=1,paddingLength do
  370.       padding = padding .. string.char(math.random(0,255))
  371.     end
  372.     return data .. padding
  373.   end
  374.  
  375.   local function properlyDecrypted(data)
  376.     local random = {string.byte(data,1,4)}
  377.     if (random[1] == random[3] and random[2] == random[4]) then
  378.       return true
  379.     end
  380.     return false
  381.   end
  382.  
  383.   local function unpadByteString(data)
  384.     if (not properlyDecrypted(data)) then
  385.       return nil
  386.     end
  387.     local dataLength = putByte(string.byte(data,5), 3)
  388.              + putByte(string.byte(data,6), 2)
  389.              + putByte(string.byte(data,7), 1)
  390.              + putByte(string.byte(data,8), 0)
  391.     return string.sub(data,9,8+dataLength)
  392.   end
  393.  
  394.   local function xorIV(data, iv)
  395.     for i = 1,16 do
  396.       data[i] = bxor(data[i], iv[i])
  397.     end
  398.   end
  399.  
  400.   local function increment(data)
  401.     local i = 16
  402.     while true do
  403.       local value = data[i] + 1
  404.       if value >= 256 then
  405.         data[i] = value - 256
  406.         i = (i - 2) % 16 + 1
  407.       else
  408.         data[i] = value
  409.         break
  410.       end
  411.     end
  412.   end
  413.  
  414.   -- Called every encryption cycle
  415.   local push, pull, time = os.queueEvent, coroutine.yield, os.time
  416.   local oldTime = time()
  417.   local function sleepCheckIn()
  418.     local newTime = time()
  419.     if newTime - oldTime >= 0.03 then -- (0.020 * 1.5)
  420.       oldTime = newTime
  421.       push("sleep")
  422.       pull("sleep")
  423.     end
  424.   end
  425.  
  426.   local function getRandomData(bytes)
  427.     local char, random, sleep, insert = string.char, math.random, sleepCheckIn, table.insert
  428.     local result = {}
  429.     for i=1,bytes do
  430.       insert(result, random(0,255))
  431.       if i % 10240 == 0 then sleep() end
  432.     end
  433.     return result
  434.   end
  435.  
  436.   local function getRandomString(bytes)
  437.     local char, random, sleep, insert = string.char, math.random, sleepCheckIn, table.insert
  438.     local result = {}
  439.     for i=1,bytes do
  440.       insert(result, char(random(0,255)))
  441.       if i % 10240 == 0 then sleep() end
  442.     end
  443.     return table.concat(result)
  444.   end
  445.  
  446.   return {
  447.     byteParity = byteParity,
  448.     getByte = getByte,
  449.     putByte = putByte,
  450.     bytesToInts = bytesToInts,
  451.     intsToBytes = intsToBytes,
  452.     bytesToHex = bytesToHex,
  453.     hexToBytes = hexToBytes,
  454.     toHexString = toHexString,
  455.     padByteString = padByteString,
  456.     properlyDecrypted = properlyDecrypted,
  457.     unpadByteString = unpadByteString,
  458.     xorIV = xorIV,
  459.     increment = increment,
  460.     sleepCheckIn = sleepCheckIn,
  461.     getRandomData = getRandomData,
  462.     getRandomString = getRandomString,
  463.   }
  464.   end)
  465.  
  466.   aes=_W(function(_ENV, ...)
  467.   -- Implementation of AES with nearly pure lua
  468.   -- AES with lua is slow, really slow :-)
  469.   local putByte = util.putByte
  470.   local getByte = util.getByte
  471.   -- some constants
  472.   local ROUNDS = 'rounds'
  473.   local KEY_TYPE = "type"
  474.   local ENCRYPTION_KEY=1
  475.   local DECRYPTION_KEY=2
  476.   -- aes SBOX
  477.   local SBox = {}
  478.   local iSBox = {}
  479.   -- aes tables
  480.   local table0 = {}
  481.   local table1 = {}
  482.   local table2 = {}
  483.   local table3 = {}
  484.   local tableInv0 = {}
  485.   local tableInv1 = {}
  486.   local tableInv2 = {}
  487.   local tableInv3 = {}
  488.   -- round constants
  489.   local rCon = {
  490.     0x01000000,
  491.     0x02000000,
  492.     0x04000000,
  493.     0x08000000,
  494.     0x10000000,
  495.     0x20000000,
  496.     0x40000000,
  497.     0x80000000,
  498.     0x1b000000,
  499.     0x36000000,
  500.     0x6c000000,
  501.     0xd8000000,
  502.     0xab000000,
  503.     0x4d000000,
  504.     0x9a000000,
  505.     0x2f000000,
  506.   }
  507.   --
  508.   -- affine transformation for calculating the S-Box of AES
  509.   --
  510.   local function affinMap(byte)
  511.     mask = 0xf8
  512.     result = 0
  513.     for i = 1,8 do
  514.       result = bit.lshift(result,1)
  515.       parity = util.byteParity(bit.band(byte,mask))
  516.       result = result + parity
  517.       -- simulate roll
  518.       lastbit = bit.band(mask, 1)
  519.       mask = bit.band(bit.rshift(mask, 1),0xff)
  520.       mask = lastbit ~= 0 and bit.bor(mask, 0x80) or bit.band(mask, 0x7f)
  521.     end
  522.     return bit.bxor(result, 0x63)
  523.   end
  524.   --
  525.   -- calculate S-Box and inverse S-Box of AES
  526.   -- apply affine transformation to inverse in finite field 2^8
  527.   --
  528.   local function calcSBox()
  529.     for i = 0, 255 do
  530.       inverse = i ~= 0 and gf.invert(i) or i
  531.       mapped = affinMap(inverse)
  532.       SBox[i] = mapped
  533.       iSBox[mapped] = i
  534.     end
  535.   end
  536.   --
  537.   -- Calculate round tables
  538.   -- round tables are used to calculate shiftRow, MixColumn and SubBytes
  539.   -- with 4 table lookups and 4 xor operations.
  540.   --
  541.   local function calcRoundTables()
  542.     for x = 0,255 do
  543.       byte = SBox[x]
  544.       table0[x] = putByte(gf.mul(0x03, byte), 0)
  545.                 + putByte(             byte , 1)
  546.                 + putByte(             byte , 2)
  547.                 + putByte(gf.mul(0x02, byte), 3)
  548.       table1[x] = putByte(             byte , 0)
  549.                 + putByte(             byte , 1)
  550.                 + putByte(gf.mul(0x02, byte), 2)
  551.                 + putByte(gf.mul(0x03, byte), 3)
  552.       table2[x] = putByte(             byte , 0)
  553.                 + putByte(gf.mul(0x02, byte), 1)
  554.                 + putByte(gf.mul(0x03, byte), 2)
  555.                 + putByte(             byte , 3)
  556.       table3[x] = putByte(gf.mul(0x02, byte), 0)
  557.                 + putByte(gf.mul(0x03, byte), 1)
  558.                 + putByte(             byte , 2)
  559.                 + putByte(             byte , 3)
  560.     end
  561.   end
  562.   --
  563.   -- Calculate inverse round tables
  564.   -- does the inverse of the normal roundtables for the equivalent
  565.   -- decryption algorithm.
  566.   --
  567.   local function calcInvRoundTables()
  568.     for x = 0,255 do
  569.       byte = iSBox[x]
  570.       tableInv0[x] = putByte(gf.mul(0x0b, byte), 0)
  571.                  + putByte(gf.mul(0x0d, byte), 1)
  572.                  + putByte(gf.mul(0x09, byte), 2)
  573.                  + putByte(gf.mul(0x0e, byte), 3)
  574.       tableInv1[x] = putByte(gf.mul(0x0d, byte), 0)
  575.                  + putByte(gf.mul(0x09, byte), 1)
  576.                  + putByte(gf.mul(0x0e, byte), 2)
  577.                  + putByte(gf.mul(0x0b, byte), 3)
  578.       tableInv2[x] = putByte(gf.mul(0x09, byte), 0)
  579.                  + putByte(gf.mul(0x0e, byte), 1)
  580.                  + putByte(gf.mul(0x0b, byte), 2)
  581.                  + putByte(gf.mul(0x0d, byte), 3)
  582.       tableInv3[x] = putByte(gf.mul(0x0e, byte), 0)
  583.                  + putByte(gf.mul(0x0b, byte), 1)
  584.                  + putByte(gf.mul(0x0d, byte), 2)
  585.                  + putByte(gf.mul(0x09, byte), 3)
  586.     end
  587.   end
  588.   --
  589.   -- rotate word: 0xaabbccdd gets 0xbbccddaa
  590.   -- used for key schedule
  591.   --
  592.   local function rotWord(word)
  593.     local tmp = bit.band(word,0xff000000)
  594.     return (bit.lshift(word,8) + bit.rshift(tmp,24))
  595.   end
  596.   --
  597.   -- replace all bytes in a word with the SBox.
  598.   -- used for key schedule
  599.   --
  600.   local function subWord(word)
  601.     return putByte(SBox[getByte(word,0)],0)
  602.       + putByte(SBox[getByte(word,1)],1)
  603.       + putByte(SBox[getByte(word,2)],2)
  604.       + putByte(SBox[getByte(word,3)],3)
  605.   end
  606.   --
  607.   -- generate key schedule for aes encryption
  608.   --
  609.   -- returns table with all round keys and
  610.   -- the necessary number of rounds saved in [ROUNDS]
  611.   --
  612.   local function expandEncryptionKey(key)
  613.     local keySchedule = {}
  614.     local keyWords = math.floor(#key / 4)
  615.     if ((keyWords ~= 4 and keyWords ~= 6 and keyWords ~= 8) or (keyWords * 4 ~= #key)) then
  616.       error("Invalid key size: " .. tostring(keyWords))
  617.       return nil
  618.     end
  619.     keySchedule[ROUNDS] = keyWords + 6
  620.     keySchedule[KEY_TYPE] = ENCRYPTION_KEY
  621.     for i = 0,keyWords - 1 do
  622.       keySchedule[i] = putByte(key[i*4+1], 3)
  623.                + putByte(key[i*4+2], 2)
  624.                + putByte(key[i*4+3], 1)
  625.                + putByte(key[i*4+4], 0)
  626.     end
  627.     for i = keyWords, (keySchedule[ROUNDS] + 1)*4 - 1 do
  628.       local tmp = keySchedule[i-1]
  629.       if ( i % keyWords == 0) then
  630.         tmp = rotWord(tmp)
  631.         tmp = subWord(tmp)
  632.         local index = math.floor(i/keyWords)
  633.         tmp = bit.bxor(tmp,rCon[index])
  634.       elseif (keyWords > 6 and i % keyWords == 4) then
  635.         tmp = subWord(tmp)
  636.       end
  637.       keySchedule[i] = bit.bxor(keySchedule[(i-keyWords)],tmp)
  638.     end
  639.     return keySchedule
  640.   end
  641.   --
  642.   -- Inverse mix column
  643.   -- used for key schedule of decryption key
  644.   --
  645.   local function invMixColumnOld(word)
  646.     local b0 = getByte(word,3)
  647.     local b1 = getByte(word,2)
  648.     local b2 = getByte(word,1)
  649.     local b3 = getByte(word,0)
  650.     return putByte(gf.add(gf.add(gf.add(gf.mul(0x0b, b1),
  651.                          gf.mul(0x0d, b2)),
  652.                          gf.mul(0x09, b3)),
  653.                          gf.mul(0x0e, b0)),3)
  654.        + putByte(gf.add(gf.add(gf.add(gf.mul(0x0b, b2),
  655.                          gf.mul(0x0d, b3)),
  656.                          gf.mul(0x09, b0)),
  657.                          gf.mul(0x0e, b1)),2)
  658.        + putByte(gf.add(gf.add(gf.add(gf.mul(0x0b, b3),
  659.                          gf.mul(0x0d, b0)),
  660.                          gf.mul(0x09, b1)),
  661.                          gf.mul(0x0e, b2)),1)
  662.        + putByte(gf.add(gf.add(gf.add(gf.mul(0x0b, b0),
  663.                          gf.mul(0x0d, b1)),
  664.                          gf.mul(0x09, b2)),
  665.                          gf.mul(0x0e, b3)),0)
  666.   end
  667.   --
  668.   -- Optimized inverse mix column
  669.   -- look at http://fp.gladman.plus.com/cryptography_technology/rijndael/aes.spec.311.pdf
  670.   -- TODO: make it work
  671.   --
  672.   local function invMixColumn(word)
  673.     local b0 = getByte(word,3)
  674.     local b1 = getByte(word,2)
  675.     local b2 = getByte(word,1)
  676.     local b3 = getByte(word,0)
  677.     local t = bit.bxor(b3,b2)
  678.     local u = bit.bxor(b1,b0)
  679.     local v = bit.bxor(t,u)
  680.     v = bit.bxor(v,gf.mul(0x08,v))
  681.     w = bit.bxor(v,gf.mul(0x04, bit.bxor(b2,b0)))
  682.     v = bit.bxor(v,gf.mul(0x04, bit.bxor(b3,b1)))
  683.     return putByte( bit.bxor(bit.bxor(b3,v), gf.mul(0x02, bit.bxor(b0,b3))), 0)
  684.        + putByte( bit.bxor(bit.bxor(b2,w), gf.mul(0x02, t              )), 1)
  685.        + putByte( bit.bxor(bit.bxor(b1,v), gf.mul(0x02, bit.bxor(b0,b3))), 2)
  686.        + putByte( bit.bxor(bit.bxor(b0,w), gf.mul(0x02, u              )), 3)
  687.   end
  688.   --
  689.   -- generate key schedule for aes decryption
  690.   --
  691.   -- uses key schedule for aes encryption and transforms each
  692.   -- key by inverse mix column.
  693.   --
  694.   local function expandDecryptionKey(key)
  695.     local keySchedule = expandEncryptionKey(key)
  696.     if (keySchedule == nil) then
  697.       return nil
  698.     end
  699.     keySchedule[KEY_TYPE] = DECRYPTION_KEY
  700.     for i = 4, (keySchedule[ROUNDS] + 1)*4 - 5 do
  701.       keySchedule[i] = invMixColumnOld(keySchedule[i])
  702.     end
  703.     return keySchedule
  704.   end
  705.   --
  706.   -- xor round key to state
  707.   --
  708.   local function addRoundKey(state, key, round)
  709.     for i = 0, 3 do
  710.       state[i + 1] = bit.bxor(state[i + 1], key[round*4+i])
  711.     end
  712.   end
  713.   --
  714.   -- do encryption round (ShiftRow, SubBytes, MixColumn together)
  715.   --
  716.   local function doRound(origState, dstState)
  717.     dstState[1] =  bit.bxor(bit.bxor(bit.bxor(
  718.           table0[getByte(origState[1],3)],
  719.           table1[getByte(origState[2],2)]),
  720.           table2[getByte(origState[3],1)]),
  721.           table3[getByte(origState[4],0)])
  722.     dstState[2] =  bit.bxor(bit.bxor(bit.bxor(
  723.           table0[getByte(origState[2],3)],
  724.           table1[getByte(origState[3],2)]),
  725.           table2[getByte(origState[4],1)]),
  726.           table3[getByte(origState[1],0)])
  727.     dstState[3] =  bit.bxor(bit.bxor(bit.bxor(
  728.           table0[getByte(origState[3],3)],
  729.           table1[getByte(origState[4],2)]),
  730.           table2[getByte(origState[1],1)]),
  731.           table3[getByte(origState[2],0)])
  732.     dstState[4] =  bit.bxor(bit.bxor(bit.bxor(
  733.           table0[getByte(origState[4],3)],
  734.           table1[getByte(origState[1],2)]),
  735.           table2[getByte(origState[2],1)]),
  736.           table3[getByte(origState[3],0)])
  737.   end
  738.   --
  739.   -- do last encryption round (ShiftRow and SubBytes)
  740.   --
  741.   local function doLastRound(origState, dstState)
  742.     dstState[1] = putByte(SBox[getByte(origState[1],3)], 3)
  743.           + putByte(SBox[getByte(origState[2],2)], 2)
  744.           + putByte(SBox[getByte(origState[3],1)], 1)
  745.           + putByte(SBox[getByte(origState[4],0)], 0)
  746.     dstState[2] = putByte(SBox[getByte(origState[2],3)], 3)
  747.           + putByte(SBox[getByte(origState[3],2)], 2)
  748.           + putByte(SBox[getByte(origState[4],1)], 1)
  749.           + putByte(SBox[getByte(origState[1],0)], 0)
  750.     dstState[3] = putByte(SBox[getByte(origState[3],3)], 3)
  751.           + putByte(SBox[getByte(origState[4],2)], 2)
  752.           + putByte(SBox[getByte(origState[1],1)], 1)
  753.           + putByte(SBox[getByte(origState[2],0)], 0)
  754.     dstState[4] = putByte(SBox[getByte(origState[4],3)], 3)
  755.           + putByte(SBox[getByte(origState[1],2)], 2)
  756.           + putByte(SBox[getByte(origState[2],1)], 1)
  757.           + putByte(SBox[getByte(origState[3],0)], 0)
  758.   end
  759.   --
  760.   -- do decryption round
  761.   --
  762.   local function doInvRound(origState, dstState)
  763.     dstState[1] =  bit.bxor(bit.bxor(bit.bxor(
  764.           tableInv0[getByte(origState[1],3)],
  765.           tableInv1[getByte(origState[4],2)]),
  766.           tableInv2[getByte(origState[3],1)]),
  767.           tableInv3[getByte(origState[2],0)])
  768.     dstState[2] =  bit.bxor(bit.bxor(bit.bxor(
  769.           tableInv0[getByte(origState[2],3)],
  770.           tableInv1[getByte(origState[1],2)]),
  771.           tableInv2[getByte(origState[4],1)]),
  772.           tableInv3[getByte(origState[3],0)])
  773.     dstState[3] =  bit.bxor(bit.bxor(bit.bxor(
  774.           tableInv0[getByte(origState[3],3)],
  775.           tableInv1[getByte(origState[2],2)]),
  776.           tableInv2[getByte(origState[1],1)]),
  777.           tableInv3[getByte(origState[4],0)])
  778.     dstState[4] =  bit.bxor(bit.bxor(bit.bxor(
  779.           tableInv0[getByte(origState[4],3)],
  780.           tableInv1[getByte(origState[3],2)]),
  781.           tableInv2[getByte(origState[2],1)]),
  782.           tableInv3[getByte(origState[1],0)])
  783.   end
  784.   --
  785.   -- do last decryption round
  786.   --
  787.   local function doInvLastRound(origState, dstState)
  788.     dstState[1] = putByte(iSBox[getByte(origState[1],3)], 3)
  789.           + putByte(iSBox[getByte(origState[4],2)], 2)
  790.           + putByte(iSBox[getByte(origState[3],1)], 1)
  791.           + putByte(iSBox[getByte(origState[2],0)], 0)
  792.     dstState[2] = putByte(iSBox[getByte(origState[2],3)], 3)
  793.           + putByte(iSBox[getByte(origState[1],2)], 2)
  794.           + putByte(iSBox[getByte(origState[4],1)], 1)
  795.           + putByte(iSBox[getByte(origState[3],0)], 0)
  796.     dstState[3] = putByte(iSBox[getByte(origState[3],3)], 3)
  797.           + putByte(iSBox[getByte(origState[2],2)], 2)
  798.           + putByte(iSBox[getByte(origState[1],1)], 1)
  799.           + putByte(iSBox[getByte(origState[4],0)], 0)
  800.     dstState[4] = putByte(iSBox[getByte(origState[4],3)], 3)
  801.           + putByte(iSBox[getByte(origState[3],2)], 2)
  802.           + putByte(iSBox[getByte(origState[2],1)], 1)
  803.           + putByte(iSBox[getByte(origState[1],0)], 0)
  804.   end
  805.   --
  806.   -- encrypts 16 Bytes
  807.   -- key           encryption key schedule
  808.   -- input         array with input data
  809.   -- inputOffset   start index for input
  810.   -- output        array for encrypted data
  811.   -- outputOffset  start index for output
  812.   --
  813.   local function encrypt(key, input, inputOffset, output, outputOffset)
  814.     --default parameters
  815.     inputOffset = inputOffset or 1
  816.     output = output or {}
  817.     outputOffset = outputOffset or 1
  818.     local state = {}
  819.     local tmpState = {}
  820.     if (key[KEY_TYPE] ~= ENCRYPTION_KEY) then
  821.       error("No encryption key: " .. tostring(key[KEY_TYPE]) .. ", expected " .. ENCRYPTION_KEY)
  822.       return
  823.     end
  824.     state = util.bytesToInts(input, inputOffset, 4)
  825.     addRoundKey(state, key, 0)
  826.     local round = 1
  827.     while (round < key[ROUNDS] - 1) do
  828.       -- do a double round to save temporary assignments
  829.       doRound(state, tmpState)
  830.       addRoundKey(tmpState, key, round)
  831.       round = round + 1
  832.       doRound(tmpState, state)
  833.       addRoundKey(state, key, round)
  834.       round = round + 1
  835.     end
  836.     doRound(state, tmpState)
  837.     addRoundKey(tmpState, key, round)
  838.     round = round +1
  839.     doLastRound(tmpState, state)
  840.     addRoundKey(state, key, round)
  841.     util.sleepCheckIn()
  842.     return util.intsToBytes(state, output, outputOffset)
  843.   end
  844.   --
  845.   -- decrypt 16 bytes
  846.   -- key           decryption key schedule
  847.   -- input         array with input data
  848.   -- inputOffset   start index for input
  849.   -- output        array for decrypted data
  850.   -- outputOffset  start index for output
  851.   ---
  852.   local function decrypt(key, input, inputOffset, output, outputOffset)
  853.     -- default arguments
  854.     inputOffset = inputOffset or 1
  855.     output = output or {}
  856.     outputOffset = outputOffset or 1
  857.     local state = {}
  858.     local tmpState = {}
  859.     if (key[KEY_TYPE] ~= DECRYPTION_KEY) then
  860.       error("No decryption key: " .. tostring(key[KEY_TYPE]))
  861.       return
  862.     end
  863.     state = util.bytesToInts(input, inputOffset, 4)
  864.     addRoundKey(state, key, key[ROUNDS])
  865.     local round = key[ROUNDS] - 1
  866.     while (round > 2) do
  867.       -- do a double round to save temporary assignments
  868.       doInvRound(state, tmpState)
  869.       addRoundKey(tmpState, key, round)
  870.       round = round - 1
  871.       doInvRound(tmpState, state)
  872.       addRoundKey(state, key, round)
  873.       round = round - 1
  874.     end
  875.     doInvRound(state, tmpState)
  876.     addRoundKey(tmpState, key, round)
  877.     round = round - 1
  878.     doInvLastRound(tmpState, state)
  879.     addRoundKey(state, key, round)
  880.     util.sleepCheckIn()
  881.     return util.intsToBytes(state, output, outputOffset)
  882.   end
  883.  
  884.   -- calculate all tables when loading this file
  885.   calcSBox()
  886.   calcRoundTables()
  887.   calcInvRoundTables()
  888.  
  889.   return {
  890.     ROUNDS = ROUNDS,
  891.     KEY_TYPE = KEY_TYPE,
  892.     ENCRYPTION_KEY = ENCRYPTION_KEY,
  893.     DECRYPTION_KEY = DECRYPTION_KEY,
  894.     expandEncryptionKey = expandEncryptionKey,
  895.     expandDecryptionKey = expandDecryptionKey,
  896.     encrypt = encrypt,
  897.     decrypt = decrypt,
  898.   }
  899.   end)
  900.  
  901.   local buffer=_W(function(_ENV, ...)
  902.   local function new ()
  903.     return {}
  904.   end
  905.  
  906.   local function addString (stack, s)
  907.     table.insert(stack, s)
  908.   end
  909.  
  910.   local function toString (stack)
  911.     return table.concat(stack)
  912.   end
  913.  
  914.   return {
  915.     new = new,
  916.     addString = addString,
  917.     toString = toString,
  918.   }
  919.   end)
  920.  
  921.   ciphermode=_W(function(_ENV, ...)
  922.   local public = {}
  923.   --
  924.   -- Encrypt strings
  925.   -- key - byte array with key
  926.   -- string - string to encrypt
  927.   -- modefunction - function for cipher mode to use
  928.   --
  929.   local random, unpack = math.random, unpack or table.unpack
  930.   function public.encryptString(key, data, modeFunction, iv)
  931.     if iv then
  932.       local ivCopy = {}
  933.       for i = 1, 16 do ivCopy[i] = iv[i] end
  934.       iv = ivCopy
  935.     else
  936.       iv = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
  937.     end
  938.     local keySched = aes.expandEncryptionKey(key)
  939.     local encryptedData = buffer.new()
  940.     for i = 1, #data/16 do
  941.       local offset = (i-1)*16 + 1
  942.       local byteData = {string.byte(data,offset,offset +15)}
  943.       iv = modeFunction(keySched, byteData, iv)
  944.       buffer.addString(encryptedData, string.char(unpack(byteData)))
  945.     end
  946.     return buffer.toString(encryptedData)
  947.   end
  948.   --
  949.   -- the following 4 functions can be used as
  950.   -- modefunction for encryptString
  951.   --
  952.   -- Electronic code book mode encrypt function
  953.   function public.encryptECB(keySched, byteData, iv)
  954.     aes.encrypt(keySched, byteData, 1, byteData, 1)
  955.   end
  956.  
  957.   -- Cipher block chaining mode encrypt function
  958.   function public.encryptCBC(keySched, byteData, iv)
  959.     util.xorIV(byteData, iv)
  960.     aes.encrypt(keySched, byteData, 1, byteData, 1)
  961.     return byteData
  962.   end
  963.  
  964.   -- Output feedback mode encrypt function
  965.   function public.encryptOFB(keySched, byteData, iv)
  966.     aes.encrypt(keySched, iv, 1, iv, 1)
  967.     util.xorIV(byteData, iv)
  968.     return iv
  969.   end
  970.  
  971.   -- Cipher feedback mode encrypt function
  972.   function public.encryptCFB(keySched, byteData, iv)
  973.     aes.encrypt(keySched, iv, 1, iv, 1)
  974.     util.xorIV(byteData, iv)
  975.     return byteData
  976.   end
  977.  
  978.   function public.encryptCTR(keySched, byteData, iv)
  979.     local nextIV = {}
  980.     for j = 1, 16 do nextIV[j] = iv[j] end
  981.     aes.encrypt(keySched, iv, 1, iv, 1)
  982.     util.xorIV(byteData, iv)
  983.     util.increment(nextIV)
  984.     return nextIV
  985.   end
  986.   --
  987.   -- Decrypt strings
  988.   -- key - byte array with key
  989.   -- string - string to decrypt
  990.   -- modefunction - function for cipher mode to use
  991.   --
  992.   function public.decryptString(key, data, modeFunction, iv)
  993.     if iv then
  994.       local ivCopy = {}
  995.       for i = 1, 16 do ivCopy[i] = iv[i] end
  996.       iv = ivCopy
  997.     else
  998.       iv = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
  999.     end
  1000.     local keySched
  1001.     if modeFunction == public.decryptOFB or modeFunction == public.decryptCFB or modeFunction == public.decryptCTR then
  1002.       keySched = aes.expandEncryptionKey(key)
  1003.     else
  1004.       keySched = aes.expandDecryptionKey(key)
  1005.     end
  1006.     local decryptedData = buffer.new()
  1007.     for i = 1, #data/16 do
  1008.       local offset = (i-1)*16 + 1
  1009.       local byteData = {string.byte(data,offset,offset +15)}
  1010.       iv = modeFunction(keySched, byteData, iv)
  1011.       buffer.addString(decryptedData, string.char(unpack(byteData)))
  1012.     end
  1013.     return buffer.toString(decryptedData)
  1014.   end
  1015.   --
  1016.   -- the following 4 functions can be used as
  1017.   -- modefunction for decryptString
  1018.   --
  1019.   -- Electronic code book mode decrypt function
  1020.   function public.decryptECB(keySched, byteData, iv)
  1021.     aes.decrypt(keySched, byteData, 1, byteData, 1)
  1022.     return iv
  1023.   end
  1024.  
  1025.   -- Cipher block chaining mode decrypt function
  1026.   function public.decryptCBC(keySched, byteData, iv)
  1027.     local nextIV = {}
  1028.     for j = 1, 16 do nextIV[j] = byteData[j] end
  1029.     aes.decrypt(keySched, byteData, 1, byteData, 1)
  1030.     util.xorIV(byteData, iv)
  1031.     return nextIV
  1032.   end
  1033.  
  1034.   -- Output feedback mode decrypt function
  1035.   function public.decryptOFB(keySched, byteData, iv)
  1036.     aes.encrypt(keySched, iv, 1, iv, 1)
  1037.     util.xorIV(byteData, iv)
  1038.     return iv
  1039.   end
  1040.  
  1041.   -- Cipher feedback mode decrypt function
  1042.   function public.decryptCFB(keySched, byteData, iv)
  1043.     local nextIV = {}
  1044.     for j = 1, 16 do nextIV[j] = byteData[j] end
  1045.     aes.encrypt(keySched, iv, 1, iv, 1)
  1046.     util.xorIV(byteData, iv)
  1047.     return nextIV
  1048.   end
  1049.  
  1050.   public.decryptCTR = public.encryptCTR
  1051.   return public
  1052.   end)
  1053.  
  1054.   -- Simple API for encrypting strings.
  1055.   --
  1056.   AES128 = 16
  1057.   AES192 = 24
  1058.   AES256 = 32
  1059.   ECBMODE = 1
  1060.   CBCMODE = 2
  1061.   OFBMODE = 3
  1062.   CFBMODE = 4
  1063.   CTRMODE = 4
  1064.  
  1065.   local function pwToKey(password, keyLength, iv)
  1066.     local padLength = keyLength
  1067.     if (keyLength == AES192) then
  1068.       padLength = 32
  1069.     end
  1070.     if (padLength > #password) then
  1071.       local postfix = ""
  1072.       for i = 1,padLength - #password do
  1073.         postfix = postfix .. string.char(0)
  1074.       end
  1075.       password = password .. postfix
  1076.     else
  1077.       password = string.sub(password, 1, padLength)
  1078.     end
  1079.     local pwBytes = {string.byte(password,1,#password)}
  1080.     password = ciphermode.encryptString(pwBytes, password, ciphermode.encryptCBC, iv)
  1081.     password = string.sub(password, 1, keyLength)
  1082.     return {string.byte(password,1,#password)}
  1083.   end
  1084.   --
  1085.   -- Encrypts string data with password password.
  1086.   -- password  - the encryption key is generated from this string
  1087.   -- data      - string to encrypt (must not be too large)
  1088.   -- keyLength - length of aes key: 128(default), 192 or 256 Bit
  1089.   -- mode      - mode of encryption: ecb, cbc(default), ofb, cfb
  1090.   --
  1091.   -- mode and keyLength must be the same for encryption and decryption.
  1092.   --
  1093.   function encrypt(password, data, keyLength, mode, iv)
  1094.     assert(password ~= nil, "Empty password.")
  1095.     assert(data ~= nil, "Empty data.")
  1096.     local mode = mode or CBCMODE
  1097.     local keyLength = keyLength or AES128
  1098.     local key = pwToKey(password, keyLength, iv)
  1099.     local paddedData = util.padByteString(data)
  1100.     if mode == ECBMODE then
  1101.       return ciphermode.encryptString(key, paddedData, ciphermode.encryptECB, iv)
  1102.     elseif mode == CBCMODE then
  1103.       return ciphermode.encryptString(key, paddedData, ciphermode.encryptCBC, iv)
  1104.     elseif mode == OFBMODE then
  1105.       return ciphermode.encryptString(key, paddedData, ciphermode.encryptOFB, iv)
  1106.     elseif mode == CFBMODE then
  1107.       return ciphermode.encryptString(key, paddedData, ciphermode.encryptCFB, iv)
  1108.     elseif mode == CTRMODE then
  1109.       return ciphermode.encryptString(key, paddedData, ciphermode.encryptCTR, iv)
  1110.     else
  1111.       error("Unknown mode", 2)
  1112.     end
  1113.   end
  1114.   --
  1115.   -- Decrypts string data with password password.
  1116.   -- password  - the decryption key is generated from this string
  1117.   -- data      - string to encrypt
  1118.   -- keyLength - length of aes key: 128(default), 192 or 256 Bit
  1119.   -- mode      - mode of decryption: ecb, cbc(default), ofb, cfb
  1120.   --
  1121.   -- mode and keyLength must be the same for encryption and decryption.
  1122.   --
  1123.   function decrypt(password, data, keyLength, mode, iv)
  1124.     local mode = mode or CBCMODE
  1125.     local keyLength = keyLength or AES128
  1126.     local key = pwToKey(password, keyLength, iv)
  1127.     local plain
  1128.     if mode == ECBMODE then
  1129.       plain = ciphermode.decryptString(key, data, ciphermode.decryptECB, iv)
  1130.     elseif mode == CBCMODE then
  1131.       plain = ciphermode.decryptString(key, data, ciphermode.decryptCBC, iv)
  1132.     elseif mode == OFBMODE then
  1133.       plain = ciphermode.decryptString(key, data, ciphermode.decryptOFB, iv)
  1134.     elseif mode == CFBMODE then
  1135.       plain = ciphermode.decryptString(key, data, ciphermode.decryptCFB, iv)
  1136.     elseif mode == CTRMODE then
  1137.       plain = ciphermode.decryptString(key, data, ciphermode.decryptCTR, iv)
  1138.     else
  1139.       error("Unknown mode", 2)
  1140.     end
  1141.     result = util.unpadByteString(plain)
  1142.     if (result == nil) then
  1143.       return nil
  1144.     end
  1145.     return result
  1146.   end
  1147. end
  1148.  
  1149. -- SHA-256, HMAC and PBKDF2 functions in ComputerCraft
  1150. -- By Anavrins
  1151. -- For help and details, you can PM me on the CC forums
  1152. -- http://www.computercraft.info/forums2/index.php?/user/12870-anavrins
  1153. -- Pastebin: http://pastebin.com/6UV4qfNF
  1154. -- You may use this code in your projects without asking me, as long as credit is given and this header is kept intact
  1155. local digest, hmac, pbkdf2
  1156. do
  1157.   local mod32 = 2^32
  1158.   local sha_hashlen = 32
  1159.   local sha_blocksize = 64
  1160.   local band    = bit32 and bit32.band or bit.band
  1161.   local bnot    = bit32 and bit32.bnot or bit.bnot
  1162.   local bxor    = bit32 and bit32.bxor or bit.bxor
  1163.   local blshift = bit32 and bit32.lshift or bit.blshift
  1164.   local upack   = unpack
  1165.  
  1166.   local function rrotate(n, b)
  1167.     local s = n/(2^b)
  1168.     local f = s%1
  1169.     return (s-f) + f*mod32
  1170.   end
  1171.  
  1172.   local function brshift(int, by) -- Thanks bit32 for bad rshift
  1173.     local s = int / (2^by)
  1174.     return s - s%1
  1175.   end
  1176.  
  1177.   local H = {
  1178.     0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
  1179.     0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,
  1180.   }
  1181.  
  1182.   local K = {
  1183.     0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
  1184.     0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
  1185.     0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
  1186.     0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
  1187.     0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
  1188.     0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
  1189.     0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
  1190.     0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
  1191.   }
  1192.  
  1193.   local function counter(incr)
  1194.     local t1, t2 = 0, 0
  1195.     if 0xFFFFFFFF - t1 < incr then
  1196.       t2 = t2 + 1
  1197.       t1 = incr - (0xFFFFFFFF - t1) - 1    
  1198.     else t1 = t1 + incr
  1199.     end
  1200.     return t2, t1
  1201.   end
  1202.  
  1203.   local function BE_toInt(bs, i)
  1204.     return blshift((bs[i] or 0), 24) + blshift((bs[i+1] or 0), 16) + blshift((bs[i+2] or 0), 8) + (bs[i+3] or 0)
  1205.   end
  1206.  
  1207.   local function preprocess(data)
  1208.     local len = #data
  1209.     local proc = {}
  1210.     data[#data+1] = 0x80
  1211.     while #data%64~=56 do data[#data+1] = 0 end
  1212.     local blocks = math.ceil(#data/64)
  1213.     for i = 1, blocks do
  1214.       proc[i] = {}
  1215.       for j = 1, 16 do
  1216.         proc[i][j] = BE_toInt(data, 1+((i-1)*64)+((j-1)*4))
  1217.       end
  1218.     end
  1219.     proc[blocks][15], proc[blocks][16] = counter(len*8)
  1220.     return proc
  1221.   end
  1222.  
  1223.   local function digestblock(w, C)
  1224.     for j = 17, 64 do
  1225.       local v = w[j-15]
  1226.       local s0 = bxor(bxor(rrotate(w[j-15], 7), rrotate(w[j-15], 18)), brshift(w[j-15], 3))
  1227.       local s1 = bxor(bxor(rrotate(w[j-2], 17), rrotate(w[j-2], 19)), brshift(w[j-2], 10))
  1228.       w[j] = (w[j-16] + s0 + w[j-7] + s1)%mod32
  1229.     end
  1230.     local a, b, c, d, e, f, g, h = upack(C)
  1231.     for j = 1, 64 do
  1232.       local S1 = bxor(bxor(rrotate(e, 6), rrotate(e, 11)), rrotate(e, 25))
  1233.       local ch = bxor(band(e, f), band(bnot(e), g))
  1234.       local temp1 = (h + S1 + ch + K[j] + w[j])%mod32
  1235.       local S0 = bxor(bxor(rrotate(a, 2), rrotate(a, 13)), rrotate(a, 22))
  1236.       local maj = bxor(bxor(band(a, b), band(a, c)), band(b, c))
  1237.       local temp2 = (S0 + maj)%mod32
  1238.       h, g, f, e, d, c, b, a = g, f, e, (d+temp1)%mod32, c, b, a, (temp1+temp2)%mod32
  1239.     end
  1240.     C[1] = (C[1] + a)%mod32
  1241.     C[2] = (C[2] + b)%mod32
  1242.     C[3] = (C[3] + c)%mod32
  1243.     C[4] = (C[4] + d)%mod32
  1244.     C[5] = (C[5] + e)%mod32
  1245.     C[6] = (C[6] + f)%mod32
  1246.     C[7] = (C[7] + g)%mod32
  1247.     C[8] = (C[8] + h)%mod32
  1248.     return C
  1249.   end
  1250.  
  1251.   local mt = {
  1252.     __tostring = function(a) return string.char(unpack(a)) end,
  1253.     __index = {
  1254.       toHex = function(self, s) return ("%02x"):rep(#self):format(unpack(self)) end,
  1255.       isEqual = function(self, t)
  1256.         if type(t) ~= "table" then return false end
  1257.         if #self ~= #t then return false end
  1258.         local ret = 0
  1259.         for i = 1, #self do
  1260.           ret = bit32.bor(ret, bxor(self[i], t[i]))
  1261.         end
  1262.         return ret == 0
  1263.       end
  1264.     }
  1265.   }
  1266.  
  1267.   local function toBytes(t, n)
  1268.     local b = {}
  1269.     for i = 1, n do
  1270.       b[(i-1)*4+1] = band(brshift(band(t[i], 0xFF000000), 24), 0xFF)
  1271.       b[(i-1)*4+2] = band(brshift(band(t[i], 0xFF0000), 16), 0xFF)
  1272.       b[(i-1)*4+3] = band(brshift(band(t[i], 0xFF00), 8), 0xFF)
  1273.       b[(i-1)*4+4] = band(t[i], 0xFF)
  1274.     end
  1275.     return setmetatable(b, mt)
  1276.   end
  1277.  
  1278.   digest = function(data)
  1279.     data = data or ""
  1280.     data = type(data) == "string" and {data:byte(1,-1)} or data
  1281.     data = preprocess(data)
  1282.     local C = {upack(H)}
  1283.     for i = 1, #data do C = digestblock(data[i], C) end
  1284.     return toBytes(C, 8)
  1285.   end
  1286.  
  1287.   hmac = function(data, key)
  1288.     local data = type(data) == "table" and {upack(data)} or {tostring(data):byte(1,-1)}
  1289.     local key = type(key) == "table" and {upack(key)} or {tostring(key):byte(1,-1)}
  1290.     local blocksize = sha_blocksize
  1291.     key = #key > blocksize and digest(key) or key
  1292.     local ipad = {}
  1293.     local opad = {}
  1294.     local padded_key = {}
  1295.     for i = 1, blocksize do
  1296.       ipad[i] = bxor(0x36, key[i] or 0)
  1297.       opad[i] = bxor(0x5C, key[i] or 0)
  1298.     end
  1299.     for i = 1, #data do
  1300.       ipad[blocksize+i] = data[i]
  1301.     end
  1302.     ipad = digest(ipad)
  1303.     for i = 1, blocksize do
  1304.       padded_key[i] = opad[i]
  1305.       padded_key[blocksize+i] = ipad[i]
  1306.     end
  1307.     return digest(padded_key)
  1308.   end
  1309.  
  1310.   pbkdf2 = function(pass, salt, iter, dklen)
  1311.     local out = {}
  1312.     local hashlen = sha_hashlen
  1313.     local block = 1
  1314.     dklen = dklen or 32
  1315.     while dklen > 0 do
  1316.       local ikey = {}
  1317.       local isalt = type(salt) == "table" and {upack(salt)} or {tostring(salt):byte(1,-1)}
  1318.       local clen = dklen > hashlen and hashlen or dklen
  1319.       local iCount = #isalt
  1320.       isalt[iCount+1] = band(brshift(band(block, 0xFF000000), 24), 0xFF)
  1321.       isalt[iCount+2] = band(brshift(band(block, 0xFF0000), 16), 0xFF)
  1322.       isalt[iCount+3] = band(brshift(band(block, 0xFF00), 8), 0xFF)
  1323.       isalt[iCount+4] = band(block, 0xFF)
  1324.       for j = 1, iter do
  1325.         isalt = hmac(isalt, pass)
  1326.         for k = 1, clen do ikey[k] = bxor(isalt[k], ikey[k] or 0) end
  1327.         if j % 200 == 0 then os.queueEvent("PBKDF2", j) coroutine.yield("PBKDF2") end
  1328.       end
  1329.       dklen = dklen - clen
  1330.       block = block+1
  1331.       for k = 1, clen do out[#out+1] = ikey[k] end
  1332.     end
  1333.     return setmetatable(out, mt)
  1334.   end
  1335. end
  1336.  
  1337. local function saveData()
  1338.   local devConfig = fs.open(config, "w") or error("saveData(): Cannot open " .. config .. " for writing", 0)
  1339.   devConfig.write(textutils.serialize(ccSettings))
  1340.   devConfig.close()
  1341. end
  1342.  
  1343. local function clearTerm()
  1344.   term.setBackgroundColor(black)
  1345.   term.setTextColor(white)
  1346.   term.clear()
  1347.   term.setCursorPos(1, 1)
  1348. end
  1349.  
  1350. local function drawElement(x, y, w, h, txtColor, bgColor, text)
  1351.   text = text and tostring(text) or ""
  1352.   local txtLen = #text
  1353.   w = math.max(w, txtLen)
  1354.   local spacer = (w - txtLen) / 2
  1355.   local txtLine = string.rep(" ", math.floor(spacer)) .. text .. string.rep(" ", math.ceil(spacer))
  1356.   if txtColor then term.setTextColor(txtColor) end
  1357.   if bgColor then term.setBackgroundColor(bgColor) end
  1358.   if h == 1 then
  1359.     term.setCursorPos(x, y)
  1360.     term.write(txtLine)
  1361.   else
  1362.     local line, textRow = string.rep(" ", w), y + math.floor(h / 2)
  1363.     for i = y, y + h - 1 do
  1364.       term.setCursorPos(x, i)        
  1365.       term.write(i == textRow and txtLine or line) --# Draw one line of the 'element' (box/rectangle/line-seg)
  1366.     end
  1367.   end
  1368. end
  1369.  
  1370. local function staticTermScreen()
  1371.   local hText = ccSettings.name .. " / # " .. thisCC .. " / " .. "cc10Host " .. cc10Hver
  1372.   term.setBackgroundColor(black)
  1373.   term.clear()
  1374.   drawElement(1, 1, termX, 1, white, blue, hText)
  1375.   drawElement(2, 3, 1, 1, gray, black, "Description:")
  1376.   drawElement(2, 5, 1, 1, nil, nil, "Output side:  ")
  1377.   term.setTextColor(orange)
  1378.   term.write(ccSettings.side)
  1379.   drawElement(2, 6, 1, 1, gray, nil, "Output type:")
  1380.   drawElement(2, 7, 1, 1, nil, nil, "Output level:")
  1381.   if ccSettings.password then drawElement(2, 9, 1, 1, nil, nil, "Unlocked clients:") end
  1382.   drawElement(2, 11, 1, 1, nil, nil, "Assigned color:")
  1383.   drawElement(2, 13, 1, 1, nil, nil, "Restore output on restart:")
  1384. end
  1385.  
  1386. local function shutDown()
  1387.   rednet.unhost("cc10", ccSettings.name .. thisCC)
  1388.   if rednet.isOpen(netSide) then rednet.close(netSide) end
  1389.   term.write("cc10Host is OFFLINE")
  1390.   term.setCursorPos(1, 5)
  1391. end
  1392.  
  1393. local function foregroundShell()
  1394.   clearTerm()
  1395.   if fs.exists(tArgs[1]) then
  1396.     local unpack = unpack or table.unpack
  1397.       shell.run(unpack(tArgs))
  1398.     clearTerm()
  1399.   else
  1400.     term.write(tArgs[1] .. " missing")
  1401.     term.setCursorPos(1, 3)
  1402.   end
  1403.   shutDown()
  1404. end
  1405.  
  1406. local function charInput()
  1407.   local _, char
  1408.   while true do
  1409.     _, char = os.pullEvent("char")
  1410.     if char:lower() == "q" then
  1411.       clearTerm()
  1412.       return shutDown()
  1413.     end
  1414.   end
  1415. end
  1416.  
  1417. do
  1418.   local validCommands = {
  1419.     ON = true;      --# ALL ON
  1420.     OFF = true;     --# ALL OFF
  1421.     restore = true; --# turn state restore OFF
  1422.     locDim = true;  --# change dimension
  1423.     name = true;    --# change name
  1424.     note = true;    --# change note
  1425.     lvl = true;     --# set analog output level
  1426.     color = true;   --# set color
  1427.     lock = true;    --# re-lock host in relation to client
  1428.   }
  1429.  
  1430.   local validActions = {
  1431.     restore = function(state) ccSettings.restore = state end;  --# turn state restore ON/OFF
  1432.     locDim = function(newDim) ccSettings.loc.dim = newDim end; --# change dimension
  1433.     name = function(newName)                                   --# change name
  1434.       if ccSettings.name == os.getComputerLabel() then os.setComputerLabel(newName) end
  1435.       ccSettings.name = newName
  1436.       if not tArgs[1] then staticTermScreen() end
  1437.     end;
  1438.     note = function(newNote) ccSettings.note = newNote end;    --# change note
  1439.     lvl = function(newLevel, currentLevel)                     --# set analog output level
  1440.       ccSettings.onState = math.max(1, math.min(15, newLevel))
  1441.       if currentLevel > 0 then
  1442.         rs.setAnalogOutput(ccSettings.side, ccSettings.onState)
  1443.         ccSettings.state = ccSettings.onState
  1444.       end
  1445.     end;
  1446.     color = function(newColor) if colorBurst[newColor] then ccSettings.color = newColor end end; --# change color
  1447.     lock = function(_, _, client)                              --# re-lock host in relation to client
  1448.       if not ccSettings.password or not unlockedClients[client] then return end
  1449.       lockState = true
  1450.       unlockedClients[client] = nil
  1451.       unlockedClients.count = math.max(0, unlockedClients.count - 1)
  1452.     end;
  1453.     unlock = function(pw, _, client)                           --# unlock client in relation to host
  1454.       if not lockState then return end
  1455.       if ccSettings.password and pw == ccSettings.password then
  1456.         lockState = false
  1457.         unlockedClients[client] = true
  1458.         unlockedClients.count = unlockedClients.count + 1
  1459.       end
  1460.     end;
  1461.   }
  1462.  
  1463.   local function reportStatus()
  1464.     local dataPack = textutils.serialize({
  1465.       program = "cc10host";
  1466.       cc = tonumber(thisCC);
  1467.       name = ccSettings.name;
  1468.       note = ccSettings.note;
  1469.       color = ccSettings.color;
  1470.       state = ccSettings.state;
  1471.       onState = ccSettings.onState;
  1472.       outputType = ccSettings.outputType;
  1473.       restore = ccSettings.restore;
  1474.       lockState = lockState;
  1475.       quietCount = 0;
  1476.       loc = { dim = ccSettings.loc.dim, x = ccSettings.loc.x, y = ccSettings.loc.y, z = ccSettings.loc.z };
  1477.     })
  1478.     encKey = tostring(client) .. "cc!10" .. thisCC
  1479.     local encryptedData = encode(encrypt(encKey, dataPack))
  1480.     if not rednet.isOpen(netSide) then rednet.open(netSide) end
  1481.     rednet.send(client, encryptedData, "cc10")
  1482.   end
  1483.  
  1484.   local function updateStatus(newStatus)
  1485.     if newStatus == "Noise" then return end
  1486.     ccSettings.state = rs.getAnalogOutput(ccSettings.side)
  1487.     if validActions[newStatus] then
  1488.       validActions[newStatus](newCmdData.action, ccSettings.state, client)
  1489.       if newStatus ~= "lock" and newStatus ~= "unlock" then saveData() end
  1490.       return reportStatus()
  1491.     elseif cc10Types[newStatus] then --# Toggle outputType
  1492.       ccSettings.outputType = newStatus
  1493.       if newStatus == "D" or newStatus == "UD" or newStatus:sub(1, 1) == "P" then
  1494.         ccSettings.onState = 15
  1495.         if newStatus:sub(1, 1) ~= "P" and ccSettings.state > 0 then
  1496.           rs.setAnalogOutput(ccSettings.side, 15)
  1497.           ccSettings.state = 15
  1498.         elseif newStatus:sub(1, 1) == "P" then
  1499.           rs.setAnalogOutput(ccSettings.side, 0)
  1500.           ccSettings.state = 0
  1501.           ccSettings.restore = false
  1502.         end
  1503.       elseif newStatus == "A" or newStatus == "UA" then
  1504.         ccSettings.onState = ccSettings.state > 0 and ccSettings.state or (ccSettings.onState > 0 and ccSettings.onState or 15)
  1505.       end
  1506.       saveData()
  1507.       return reportStatus()
  1508.     elseif newStatus == "ON" or newStatus == "OFF" then
  1509.       if ccSettings.outputType:sub(1, 1) == "U" then
  1510.         newStatus = newStatus == "ON" and ccSettings.onState or 0
  1511.       else
  1512.         newStatus = rs.getAnalogOutput(ccSettings.side)
  1513.       end
  1514.     elseif newStatus == "cc10QRY" then
  1515.       local state = ccSettings.state
  1516.       if state > 0 and ccSettings.onState ~= state then ccSettings.onState = state saveData() end
  1517.       return reportStatus()
  1518.     end
  1519.     local newStatusNum = tonumber(newStatus)
  1520.     if not newStatusNum then return end --# ignore invalid broadcasts
  1521.     newStatus = math.max(0, math.min(newStatusNum, 15))
  1522.     rs.setAnalogOutput(ccSettings.side, newStatus)
  1523.     ccSettings.state = newStatus
  1524.     if ccSettings.outputType:sub(1, 1) == "P" and newStatus > 0 then
  1525.       reportStatus()
  1526.       if (ccSettings.outputType == "PS" or ccSettings.outputType == "PL") then
  1527.         sleep(ccSettings.outputType == "PS" and 0.5 or 2)
  1528.       else
  1529.         for i = 1, 2 do
  1530.           sleep(0.5)
  1531.           rs.setAnalogOutput(ccSettings.side, 0)
  1532.           sleep(0.5)
  1533.           rs.setAnalogOutput(ccSettings.side, newStatus)
  1534.         end
  1535.         sleep(0.5)
  1536.       end
  1537.       rs.setAnalogOutput(ccSettings.side, 0)
  1538.       ccSettings.state = 0
  1539.     end
  1540.     ccSettings.onState = (ccSettings.state > 0 and ccSettings.state < 16) and ccSettings.state or ccSettings.onState
  1541.     saveData()
  1542.     reportStatus()
  1543.   end
  1544.  
  1545.   local function netReceive()
  1546.     local success, complete, id, message, encryptedMessage, decryptedMessage, decodedMessage, encKey = false, false
  1547.     while true do
  1548.       if not rednet.isOpen(netSide) then rednet.open(netSide) end
  1549.       id, encryptedMessage = rednet.receive("cc10")
  1550.       complete, message = false, { }
  1551.       if type(encryptedMessage) == "string" then
  1552.         success, decodedMessage = pcall(decode, encryptedMessage)
  1553.         if success and type(decodedMessage) == "string" then
  1554.           encKey = thisCC .. "cc!10" .. tostring(id)
  1555.           success, decryptedMessage = pcall(decrypt, encKey, decodedMessage)
  1556.           if success and type(decryptedMessage) == "string" then
  1557.             success, message = pcall(textutils.unserialize, decryptedMessage)
  1558.             if success and type(message) == "table" and message.program and message.program == "cc10" then
  1559.               complete = true
  1560.             end
  1561.           else
  1562.             encKey = tostring(id) .. "cc!10_Broadcast" .. tostring(id)
  1563.             success, decryptedMessage = pcall(decrypt, encKey, decodedMessage)
  1564.             if success and type(decryptedMessage) == "string" then
  1565.               success, message = pcall(textutils.unserialize, decryptedMessage)
  1566.               if success and type(message) == "table" and message.program and message.program == "cc10" then
  1567.                 complete = true
  1568.               end
  1569.             end
  1570.           end
  1571.         end
  1572.       end
  1573.       if complete then
  1574.         client = id
  1575.         newCmdData = { }
  1576.         for k, v in pairs(message) do
  1577.           newCmdData[k] = v
  1578.         end
  1579.         lockState = true
  1580.         if ccSettings.password then
  1581.           if unlockedClients[client] then lockState = false end
  1582.         else
  1583.           lockState = false
  1584.         end
  1585.         if not lockState then
  1586.           if validCommands[newCmdData.cmd] then return newCmdData.cmd end
  1587.           if newCmdData.cmd == "changeOutputType" or newCmdData.cmd == "QRY" or newCmdData.cmd == "set" then
  1588.             return newCmdData.action
  1589.           end
  1590.         elseif newCmdData.cmd == "QRY" or newCmdData.cmd == "unlock" then
  1591.           return newCmdData.cmd == "QRY" and newCmdData.action or newCmdData.cmd
  1592.         end
  1593.       end
  1594.       return "Noise"
  1595.     end
  1596.   end
  1597.  
  1598.   ccKernel = function()
  1599.     local ccState, ccColor
  1600.     while true do
  1601.       if not tArgs[1] then
  1602.         drawElement(16, 3, 1, 1, silver, black, ccSettings.note .. string.rep(" ", 21 - #ccSettings.note))
  1603.         drawElement(16, 6, 1, 1, cc10Types[ccSettings.outputType] and sky or red, nil, cc10Types[ccSettings.outputType] or "Error            ")
  1604.         ccState, ccColor = ccSettings.state, ccSettings.color
  1605.         drawElement(16, 7, 1, 1, ccState == 0 and red or green, nil, tostring(ccState) .. "  ")
  1606.         if ccSettings.password then drawElement(20, 9, 1, 1, silver, nil, tostring(unlockedClients.count) .. "  ") end
  1607.         drawElement(18, 11, 1, 1, colorBurst[ccColor][2] or red, nil, (colorBurst[ccColor][1] or "Error") .. "      ")
  1608.         drawElement(29, 13, 1, 1, ccSettings.restore and green or red, nil, tostring(ccSettings.restore) .. "  ")
  1609.       end
  1610.       updateStatus(netReceive())
  1611.     end
  1612.   end
  1613. end
  1614.  
  1615. local function firstRun()
  1616.   if not fs.exists("/data") then fs.makeDir("/data") end
  1617.   term.clear()
  1618.   drawElement(2, 2, 1, 1, nil, nil, "Please name this device")
  1619.   drawElement(3, 3, 1, 1, nil, nil, "(8 characters or less)")
  1620.   repeat --# Set computer name
  1621.     term.setCursorPos(2, 5)
  1622.     local newName = read():sub(1, 8)
  1623.     ccSettings.name = newName
  1624.   until newName ~= ""
  1625.   if not os.getComputerLabel() then os.setComputerLabel(ccSettings.name) end --# Set computer label
  1626.   term.clear()
  1627.   drawElement(2, 2, 1, 1, nil, nil, "Please type in a short")
  1628.   drawElement(2, 3, 1, 1, nil, nil, "device description (21 chars.)")
  1629.   repeat --# Set computer description
  1630.     term.setCursorPos(2, 5)
  1631.     local newDesc = read():sub(1, 21)
  1632.     ccSettings.note = newDesc
  1633.   until newDesc ~= ""
  1634.   term.clear()
  1635.   drawElement(2, turtle and 1 or 2, 1, 1, nil, nil, "Redstone Output Type")
  1636.   drawElement(2, turtle and 3 or 4, 1, 1, nil, nil, "A = Analog")
  1637.   drawElement(2, turtle and 4 or 5, 1, 1, nil, nil, "D = Digital")
  1638.   drawElement(2, turtle and 5 or 6, 1, 1, nil, nil, "UA = Universal Analog")
  1639.   drawElement(2, turtle and 6 or 7, 1, 1, nil, nil, "UD = Universal Digital")
  1640.   drawElement(2, turtle and 7 or 8, 1, 1, nil, nil, "PS = Pulsed (0.5 seconds)")
  1641.   drawElement(2, turtle and 8 or 9, 1, 1, nil, nil, "PL = Pulsed (2 seconds)")
  1642.   drawElement(2, turtle and 9 or 10, 1, 1, nil, nil, "P3 = Pulsed (3 pulses)")
  1643.   drawElement(2, turtle and 11 or 12, 1, 1, nil, nil, "(Universal ~ ALL ON/OFF)")
  1644.   repeat --# Select analog or digital output
  1645.     term.setCursorPos(2, turtle and 13 or 14)
  1646.     local newType = string.upper(read())
  1647.     if cc10Types[newType] then
  1648.       ccSettings.outputType = newType
  1649.       if newType:sub(1, 1) == "P" then ccSettings.restore = false end
  1650.     end
  1651.   until cc10Types[newType]
  1652.   term.clear()
  1653.   term.setCursorPos(2, 2)
  1654.   local theseSides = { "top", "bottom", "left", "right", "front", "back" }
  1655.   drawElement(2, 2, 1, 1, nil, nil, "Please select the")
  1656.   drawElement(2, 3, 1, 1, nil, nil, "redstone output side")
  1657.   for k, v in pairs(theseSides) do --# Draw side list
  1658.     term.setCursorPos(2, k + 4)
  1659.     term.write(tostring(k) .. " = " .. string.upper(v:sub(1, 1)) .. v:sub(2))
  1660.   end
  1661.   repeat --# Select redstone output side
  1662.     term.setCursorPos(2, 12)
  1663.     local getSide = tonumber(read())
  1664.     ccSettings.side = theseSides[getSide]
  1665.   until theseSides[getSide]
  1666.   term.clear()
  1667.   drawElement(2, 2, 1, 1, nil, nil, "Select a color")
  1668.   local y = 3
  1669.   for k, v in pairs(colorBurst) do
  1670.     y = y + 1
  1671.     drawElement(2, y, 1, 1, nil, nil, k .. " = " .. v[1])
  1672.   end
  1673.   repeat --# Select color
  1674.     term.setCursorPos(2, 13)
  1675.     local newColor = string.upper(read():sub(1, 1))
  1676.     ccSettings.color = newColor
  1677.   until colorBurst[newColor]
  1678.   term.clear()
  1679.   drawElement(2, 2, 1, 1, nil, nil, "Would you like to password")
  1680.   drawElement(2, 3, 1, 1, nil, nil, "protect this device? [Y/N]")
  1681.   term.setCursorPos(2, 5)
  1682.   local lockQ = string.lower(read():sub(1, 1))
  1683.   if lockQ == "y" then
  1684.     local pass
  1685.     drawElement(2, 7, 1, 1, nil, nil, "Please enter a password...")
  1686.     repeat --# Set password
  1687.       term.setCursorPos(2, 9)
  1688.       pass = read()
  1689.     until pass ~= ""
  1690.     ccSettings.password = table.concat(pbkdf2(pass, "cc!10", 15))
  1691.     ccSettings.hashedPWs = true
  1692.   end
  1693.   saveData()
  1694. end
  1695.  
  1696. clearTerm()
  1697. if pocket then error("Computer or turtle REQUIRED.", 0) end
  1698. drawElement(2, 2, 1, 1, nil, nil, "Configuring hardware . . .")
  1699. for _, side in pairs(rs.getSides()) do
  1700.   if peripheral.isPresent(side) and peripheral.getType(side) == "modem" and peripheral.call(side, "isWireless") then
  1701.     netSide = side
  1702.     break
  1703.   end
  1704. end
  1705. if netSide == "none" then
  1706.   term.clear()
  1707.   drawElement(2, 2, 1, 1, red, black, "No wireless")
  1708.   drawElement(2, 3, 1, 1, nil, nil, "modem detected!")
  1709.   drawElement(2, 5, 1, 1, nil, nil, "cc10 REQUIRES")
  1710.   drawElement(2, 6, 1, 1, nil, nil, "a wireless modem.")
  1711.   term.setTextColor(colors.white)
  1712.   term.setCursorPos(1, 9)
  1713.   return
  1714. end
  1715. if not fs.exists(config) then
  1716.   firstRun()
  1717.   term.clear()
  1718.   drawElement(2, 4, 1, 1, nil, nil, "Configuration compelete . . .")
  1719. else
  1720.   drawElement(2, 4, 1, 1, nil, nil, "Ingesting configuration data . . .")
  1721.   local cc10Config = fs.open(config, "r") or error("init: Cannot open " .. config .. " for reading", 0)
  1722.   ccSettings = textutils.unserialize(cc10Config.readAll())
  1723.   cc10Config.close()
  1724.   if not ccSettings.newColors then
  1725.     local oldColors = {
  1726.       L = "S";
  1727.       Y = "I";
  1728.     }
  1729.     if oldColors[ccSettings.color] then ccSettings.color = oldColors[ccSettings.color] end
  1730.     ccSettings.newColors = true
  1731.     saveData()
  1732.   end
  1733.   if ccSettings.password and not ccSettings.hashedPWs then
  1734.     ccSettings.password = table.concat(pbkdf2(ccSettings.password, "cc!10", 15))
  1735.     ccSettings.hashedPWs = true
  1736.     saveData()
  1737.   end
  1738. end
  1739. if ccSettings.password then lockState = true end
  1740. if ccSettings.restore then
  1741.   drawElement(2, 6, 1, 1, nil, nil, "Restoring state . . .")
  1742.   rs.setAnalogOutput(ccSettings.side, ccSettings.onState)
  1743. else
  1744.   drawElement(2, 6, 1, 1, nil, nil, "Discovering state . . .")
  1745.   ccSettings.state = rs.getAnalogOutput(ccSettings.side)
  1746. end
  1747. drawElement(2, 8, 1, 1, nil, nil, "Acquiring GPS fix . . .")
  1748. if not rednet.isOpen(netSide) then rednet.open(netSide) end
  1749. ccSettings.loc.x, ccSettings.loc.y, ccSettings.loc.z = gps.locate(2)
  1750. if not ccSettings.loc.x then
  1751.   ccSettings.loc.x, ccSettings.loc.y, ccSettings.loc.z = "No GPS Fix", "No GPS Fix", "No GPS Fix"
  1752. end
  1753. drawElement(2, 10, 1, 1, nil, nil, "Hosting services . . .")
  1754. rednet.host("cc10", ccSettings.name .. thisCC)
  1755. if tArgs[1] then
  1756.     parallel.waitForAny(foregroundShell, ccKernel)
  1757. else
  1758.   staticTermScreen()
  1759.   parallel.waitForAny(ccKernel, charInput)
  1760. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement