Advertisement
Piorjade

ComputerCraft modEM API

Dec 21st, 2016
271
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 7.79 KB | None | 0 0
  1. --[[
  2.         modEM
  3.  
  4.     A custom peripheral API wrapper.
  5.  
  6.     This API is specifically made to create secure connections between two computers.
  7.  
  8.  
  9.     How it works:
  10.     You specify a channel for the connection, the 2nd computer connects to it.
  11.     Ones the API recognizes a 2nd connection, it generates a random number (between 1 and 65535) and passes it to the 2nd computer.
  12.     It then generates a random string, containing symbols and numbers, and passes that to the 2nd computer too.
  13.     The API then closes the channel and opens a new one using the new generated number.
  14.     The 2nd computer connects to that using the number the API gave him.
  15.     Now why is that all necessary?
  16.     It passes a random number and opens a new channel on that to prevent from a 3rd party being able to listen on it.
  17.     Sure he can guess the number but it'd need a while.
  18.  
  19.     It also passes a random string to the 2nd computer, because it ENCRYPTS the messages using that string.
  20.     Which leads to a higher security if a 3rd party is listening on that channel too.
  21.  
  22.  
  23.  
  24.     This is mainly made for future secret projects :)
  25.  
  26.     ~Piorjade 2016
  27.  
  28. ]]
  29.  
  30. --[[
  31.       THIS IS THE ENCRYPTION API MADE BY "PixelToast"
  32. ]]
  33.  
  34. local function zfill(N)
  35.     N=string.format("%X",N)
  36.     Zs=""
  37.     if #N==1 then
  38.         Zs="0"
  39.     end
  40.     return Zs..N
  41. end
  42.  
  43. local function serializeImpl(t)
  44.     local sType = type(t)
  45.     if sType == "table" then
  46.         local lstcnt=0
  47.         for k,v in pairs(t) do
  48.             lstcnt = lstcnt + 1
  49.         end
  50.         local result = "{"
  51.         local aset=1
  52.         for k,v in pairs(t) do
  53.             if k==aset then
  54.                 result = result..serializeImpl(v)..","
  55.                 aset=aset+1
  56.             else
  57.                 result = result..("["..serializeImpl(k).."]="..serializeImpl(v)..",")
  58.             end
  59.         end
  60.         result = result.."}"
  61.         return result
  62.     elseif sType == "string" then
  63.         return string.format("%q",t)
  64.     elseif sType == "number" or sType == "boolean" or sType == "nil" then
  65.         return tostring(t)
  66.     elseif sType == "function" then
  67.         local status,data=pcall(string.dump,t)
  68.         if status then
  69.             return 'func('..string.format("%q",data)..')'
  70.         else
  71.             error()
  72.         end
  73.     else
  74.         error()
  75.     end
  76. end
  77.  
  78. local function split(T,func)
  79.     if func then
  80.         T=func(T)
  81.     end
  82.     local Out={}
  83.     if type(T)=="table" then
  84.         for k,v in pairs(T) do
  85.             Out[split(k)]=split(v)
  86.         end
  87.     else
  88.         Out=T
  89.     end
  90.     return Out
  91. end
  92.  
  93. local function serialize( t )
  94.     t=split(t)
  95.     return serializeImpl( t, tTracking )
  96. end
  97.  
  98. local function unserialize( s )
  99.     local func, e = loadstring( "return "..s, "serialize" )
  100.     local funcs={}
  101.     if not func then
  102.         return e
  103.     end
  104.     setfenv( func, {
  105.         func=function(S)
  106.             local new={}
  107.             funcs[new]=S
  108.             return new
  109.         end,
  110.     })
  111.     return split(func(),function(val)
  112.         if funcs[val] then
  113.             return loadstring(funcs[val])
  114.         else
  115.             return val
  116.         end
  117.     end)
  118. end
  119.  
  120. local function sure(N,n)
  121.     if (l2-n)<1 then N="0" end
  122.     return N
  123. end
  124.  
  125. local function splitnum(S)
  126.     Out=""
  127.     for l1=1,#S,2 do
  128.         l2=(#S-l1)+1
  129.         CNum=tonumber("0x"..sure(string.sub(S,l2-1,l2-1),1) .. sure(string.sub(S,l2,l2),0))
  130.         Out=string.char(CNum)..Out
  131.     end
  132.     return Out
  133. end
  134.  
  135. local function wrap(N)
  136.     return N-(math.floor(N/256)*256)
  137. end
  138.  
  139. local function checksum(S,num)
  140.     local sum=0
  141.     for char in string.gmatch(S,".") do
  142.         for l1=1,(num or 1) do
  143.             math.randomseed(string.byte(char)+sum)
  144.             sum=sum+math.random(0,9999)
  145.         end
  146.     end
  147.     math.randomseed(sum)
  148.     return sum
  149. end
  150.  
  151. local function genkey(len,psw)
  152.     checksum(psw)
  153.     local key={}
  154.     local tKeys={}
  155.     for l1=1,len do
  156.         local num=math.random(1,len)
  157.         while tKeys[num] do
  158.             num=math.random(1,len)
  159.         end
  160.         tKeys[num]=true
  161.         key[l1]={num,math.random(0,255)}
  162.     end
  163.     return key
  164. end
  165.  
  166. local function encrypt(data,psw)
  167.     data=serialize(data)
  168.     local chs=checksum(data)
  169.     local key=genkey(#data,psw)
  170.     local out={}
  171.     local cnt=1
  172.     for char in string.gmatch(data,".") do
  173.         table.insert(out,key[cnt][1],zfill(wrap(string.byte(char)+key[cnt][2])),chars)
  174.         cnt=cnt+1
  175.     end
  176.     return string.sub(serialize({chs,table.concat(out)}),2,-3)
  177. end
  178.  
  179. local function decrypt(data,psw)
  180.     local oData=data
  181.     data=unserialize("{"..data.."}")
  182.     if type(data)~="table" then
  183.         return oData
  184.     end
  185.     local chs=data[1]
  186.     data=data[2]
  187.     local key=genkey((#data)/2,psw)
  188.     local sKey={}
  189.     for k,v in pairs(key) do
  190.         sKey[v[1]]={k,v[2]}
  191.     end
  192.     local str=splitnum(data)
  193.     local cnt=1
  194.     local out={}
  195.     for char in string.gmatch(str,".") do
  196.         table.insert(out,sKey[cnt][1],string.char(wrap(string.byte(char)-sKey[cnt][2])))
  197.         cnt=cnt+1
  198.     end
  199.     out=table.concat(out)
  200.     if checksum(out or "")==chs then
  201.         return unserialize(out)
  202.     end
  203.     return oData,out,chs
  204. end
  205.  
  206. --[[
  207.   ENCRYPTION API ENDS HERE
  208.  
  209. ]]
  210. local chan = 0
  211. local encryption = "abc"
  212. local isConnected = false
  213.  
  214. local function makeString(l)
  215.         if l < 1 then return nil end -- Check for l < 1
  216.         local s = "" -- Start string
  217.         for i = 1, l do
  218.             n = math.random(32, 126) -- Generate random number from 32 to 126
  219.             if n == 96 then n = math.random(32, 95) end
  220.                 s = s .. string.char(n) -- turn it into character and add to string
  221.         end
  222.         return s -- Return string
  223. end
  224.  
  225. function open(side)
  226.   if modem then
  227.     return false, "modemWrapped"
  228.   end
  229.   modem = peripheral.wrap(side)
  230. end
  231.  
  232. function close()
  233.   modem.closeAll()
  234.   isConnected = false
  235.   chan = 0
  236.   encryption = "abc"
  237.   modem = nil
  238. end
  239.  
  240. function host(startingChannel, side, timout)
  241.   if modem then
  242.     return false, "modemWrapped"
  243.   end
  244.   if type(timeout) == "number" then
  245.     local timerID = os.startTimer(timeout)
  246.   end
  247.   if startingChannel == nil or startingChannel < 1 or startingChannel > 65535 then
  248.     startingChannel = os.getComputerID()
  249.   end
  250.   chan = startingChannel
  251.   if type(side) ~= "string" then return false end
  252.   open(side)
  253.   modem.open(chan)
  254.   while true do
  255.     local ev, a, b, c, msg, dis = os.pullEvent()
  256.     if ev == "modem_message" and msg == "Connected." then
  257.       local tab = {
  258.         msg = "ok",
  259.         newPort = 1,
  260.         decPass = "abc",
  261.       }
  262.       tab.newPort = math.random(1, 65535)
  263.       tab.decPass = makeString(6)
  264.       encryption = tab.decPass
  265.       modem.transmit(chan, chan, textutils.serialize(tab))
  266.       modem.close(chan)
  267.       chan = tab.newPort
  268.       modem.open(chan)
  269.       isConnected = true
  270.       break
  271.     elseif ev == "timer" and a == timerID then
  272.       close()
  273.       return false, "timeout"
  274.     end
  275.   end
  276. end
  277.  
  278. function connect(startingChannel, timeout)
  279.   if modem == nil then return false, "No opened modem." end
  280.   if type(timeout) == "number" then
  281.     local timerID = os.startTimer(timeout)
  282.   end
  283.   chan = startingChannel
  284.   modem.closeAll()
  285.   modem.open(chan)
  286.   modem.transmit(chan, chan, "Connected.")
  287.   while true do
  288.  
  289.     ev, side, sendChan, repChan, msg, distance = os.pullEvent()
  290.  
  291.     if ev == "modem_message" then
  292.       msg = textutils.unserialize(msg)
  293.       if msg.msg == "ok" then
  294.         modem.closeAll()
  295.         chan = msg.newPort
  296.         modem.open(chan)
  297.         encryption = msg.decPass
  298.         break
  299.       end
  300.     elseif ev == "timer" and side == timerID then
  301.       close()
  302.       return false, "timeout"
  303.     end
  304.   end
  305.   isConnected = true
  306. end
  307.  
  308. function receive(timeout)
  309.  
  310.   if not isConnected then
  311.     return false, "noConnection"
  312.   end
  313.   if not modem then return false, "No opened modem." end
  314.   if type(timeout) == "number" then
  315.     local timerID = os.startTimer(timout)
  316.   end
  317.   while true do
  318.     local ev, a, b, c, msg, dis = os.pullEvent()
  319.     if ev == "timer" and a == timerID then
  320.       return false, "timeout"
  321.     elseif ev == "modem_message" and msg ~= nil then
  322.       return decrypt(msg, encryption)
  323.     end
  324.   end
  325. end
  326.  
  327. function send(msg)
  328.   if not isConnected then
  329.     return false, "noConnection"
  330.   end
  331.   if not modem then return false, "No opened modem." end
  332.   modem.transmit(chan, chan, encrypt(msg, encryption))
  333.   return
  334. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement