Advertisement
Tatantyler

Secure Rednet Tunnels

Apr 28th, 2013
1,004
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 25.50 KB | None | 0 0
  1. -- Rednet Tunneling
  2. -- By KillaVanilla
  3.  
  4. local function downloadAPI(code, name)
  5.     local webHandle = http.get("http://pastebin.com/raw.php?i="..code)
  6.     if webHandle then
  7.         local apiData = webHandle.readAll()
  8.         webHandle.close()
  9.         local apiHandle = fs.open(name, "w")
  10.         apiHandle.write(apiData)
  11.         apiHandle.close()
  12.         return true
  13.     else
  14.         print("Could not retrieve API: "..name.."!")
  15.         print("Ensure that the HTTP API is enabled.")
  16.         return false
  17.     end
  18. end
  19.  
  20. if (not AES) and (not fs.exists("AES")) then
  21.     downloadAPI("rCYDnCxn", "AES")
  22. end
  23.  
  24. if (not base64) and (not fs.exists("base64")) then
  25.     downloadAPI("pp3kpb19", "base64")
  26. end
  27.  
  28. if (not random) and (not fs.exists("random")) then
  29.     downloadAPI("D1th4Htw", "random")
  30. end
  31.  
  32. if not AES then
  33.     os.loadAPI("AES")
  34. end
  35.  
  36. if not base64 then
  37.     os.loadAPI("base64")
  38. end
  39.  
  40. if not random then
  41.     os.loadAPI("random")
  42. end
  43.  
  44.  
  45. local connFreq = 15 -- The key exchange is done on this frequency.
  46. local tunnelFreq = 20 -- Encrypted data is sent on this frequency.
  47. local connections = {} -- Temporary keys, for open connections.
  48. handlerRunning = false -- Make sure that we don't have two handler coroutines running at the same time
  49.  
  50. function mod_exp(base, exp, mod)
  51.     local result = 1
  52.     while exp > 0 do
  53.         if (exp % 2) == 1 then
  54.             result = (result*base) % mod
  55.         end
  56.         exp = math.floor(exp/2)
  57.         base = (base*base) % mod
  58.         os.queueEvent("theres_a_hole_in_the_sky")
  59.         os.pullEvent()
  60.     end
  61.     --term.setCursorPos(x,y+1)
  62.     return result
  63. end
  64.  
  65. function fermat(n, k)
  66.     for i=1, k do
  67.         local a = random.random(1, n-1)
  68.         local e = mod_exp(a, n-1, n)
  69.         if e ~= 1 then
  70.             --print("a: "..a.." e: "..e)
  71.             return false
  72.         end
  73.         os.queueEvent("theres_a_hole_in_the_sky")
  74.         os.pullEvent()
  75.     end
  76.     return true
  77. end
  78.  
  79. function miller_rabin(n, k)
  80.     local s, d = 0, 0
  81.     assert(n >= 2)
  82.     if n == 2 then
  83.         return true
  84.     end
  85.     if n%2 == 0 then
  86.         return false
  87.     end
  88.     -- Write n-1 as (2^s)*d, by repeatedly dividing n-1 by two:
  89.     d = n-1
  90.     while true do
  91.         local quot = math.floor(d / 2)
  92.         local rem = d % 2
  93.         if rem == 1 then
  94.             break
  95.         end
  96.         s = s+1
  97.         d = quot
  98.         os.queueEvent("theres_a_hole_in_the_sky")
  99.         os.pullEvent()
  100.     end
  101.    
  102.     -- WitnessLoop:
  103.     for i=1, k do
  104.         a = random.random(2, n-2)
  105.         local x = mod_exp(a, d, n)
  106.         if not (x == 1 or x == n-1) then -- If x == 1 or x == n-1 then continue
  107.             local continuing = false
  108.             for j=1, s-1 do
  109.                 x = (x*x) % n
  110.                 if x == 1 then -- if x == 1 then return COMPOSITE (false)
  111.                     return false
  112.                 end
  113.                 if x == n-1 then -- If x == n-1 then do next WitnessLoop...
  114.                     continuing = true
  115.                     break
  116.                 end
  117.                 os.queueEvent("theres_a_hole_in_the_sky")
  118.                 os.pullEvent()
  119.             end
  120.             if not continuing then
  121.                 return false
  122.             end
  123.         end
  124.         os.queueEvent("theres_a_hole_in_the_sky")
  125.         os.pullEvent()
  126.     end
  127.     return true
  128. end
  129.  
  130. function generatePrime(k, debug) -- Generate somewhat-large primes (nowhere near big enough, but using BigInt will just slow things down too much)
  131.     random.generate_isaac()
  132.     local tries = 0
  133.     local x,y = term.getCursorPos()
  134.     while true do
  135.         local current = random.random(10000000, 90000000)
  136.         tries = tries+1
  137.         if debug then
  138.             term.setCursorPos(x,y)
  139.             term.clearLine()
  140.         end
  141.         if current % 2 == 0 then
  142.             current = current+1
  143.         end
  144.         if debug then
  145.             write("Attempt: "..tries..": "..current)
  146.         end
  147.         if fermat(current, k) then
  148.             if debug then
  149.                 term.setCursorPos(x,y+3)
  150.                 term.clearLine()
  151.                 write("Last Fermat Success: "..tries..": "..current)
  152.             end
  153.             if miller_rabin(current, k) then
  154.                 if debug then
  155.                     term.setCursorPos(1,y+4)
  156.                 end
  157.                 return current
  158.             else
  159.                 if debug then
  160.                     term.setCursorPos(x,y+2)
  161.                     term.clearLine()
  162.                     write("Last Miller-Rabin Failure: "..tries..": "..current)
  163.                 end
  164.             end
  165.         else
  166.             if debug then
  167.                 term.setCursorPos(x,y+1)
  168.                 term.clearLine()
  169.                 write("Last Fermat Failure: "..tries..": "..current)
  170.             end
  171.         end
  172.         os.queueEvent("there's_a_hole_in_the_sky")
  173.         os.pullEvent()
  174.     end
  175. end
  176.  
  177. local function listen(timeout)
  178.     local timer = {}
  179.     if timeout then
  180.         timer = os.startTimer(timeout)
  181.     end
  182.     while true do
  183.         local event = {os.pullEvent()}
  184.         if event[1] == "timer" then
  185.             if event[2] == timer then
  186.                 return
  187.             end
  188.         elseif event[1] == "modem_message" then
  189.             if textutils.unserialize(event[5]) then
  190.                 return event[3], event[4], textutils.unserialize(event[5])
  191.             end
  192.         end
  193.     end
  194. end
  195.  
  196. local function incrementBlock(blk, incAmt)
  197.     local cpy = {}
  198.     for i=1, 16 do
  199.         cpy[i] = blk[i] or 0
  200.     end
  201.     cpy[1] = cpy[1] + incAmt
  202.     for i=2, 16 do
  203.         if cpy[i-1] <= 255 then
  204.             break
  205.         end
  206.         local carry = cpy[i-1] - 255
  207.         cpy[i] = cpy[i]+carry
  208.     end
  209.     return cpy
  210. end
  211.  
  212. function getHandlerStatus()
  213.     return handlerRunning
  214. end
  215.  
  216. -- Connection Establishing:
  217. -- Client sends "Connect" message with a[1-4], base, and p, for Diffie-Hellman Key Exchange.
  218. -- Server calculates b[1-4] and s[1-4] and sends a "Connect_Key" message with b[1-4]. The server also encrypts a "test block" of all 0xFF's using s.
  219. -- Client calculates s[1-4], and encrypts a "test block" of all 0xFF's using s.
  220. -- Server sends the test block, which is checked by the client. If the blocks match, then the client sends a success message. All communications from here are encrypted using s.
  221. -- The server makes an entry in the connection table for the new connection, and sends the client the connection ID.
  222.  
  223. -- If any side of the connection is held up for more than 30 seconds, the connection is automatically torn down.
  224.  
  225. function connectionHandler(modem, debug)
  226.     if handlerRunning then
  227.         if debug then
  228.             print("connection_handler: another handler instance is already running!")
  229.         end
  230.         return false
  231.     end
  232.     handlerRunning = true
  233.     modem.open(connFreq)
  234.     modem.open(tunnelFreq)
  235.     while true do
  236.         local tFreq, rFreq, msg = listen()
  237.         if msg[1] == "Tunneling" then
  238.             local id = msg[2]
  239.             --print(msg[1].." : "..msg[3])
  240.             if msg[3] == "Connect" then
  241.                 if debug then
  242.                     print("connect_server: Incoming connection attempt by ID "..id.."...")
  243.                 end
  244.                
  245.                 local k1 = random.random()
  246.                 local k2 = random.random()
  247.                 local k3 = random.random()
  248.                 local k4 = random.random()
  249.                
  250.                 local iv_k1 = random.random()
  251.                 local iv_k2 = random.random()
  252.                 local iv_k3 = random.random()
  253.                 local iv_k4 = random.random()
  254.                
  255.                 local a1 = msg[4]
  256.                 local a2 = msg[5]
  257.                 local a3 = msg[6]
  258.                 local a4 = msg[7]
  259.                
  260.                 local iv_a1 = msg[8]
  261.                 local iv_a2 = msg[9]
  262.                 local iv_a3 = msg[10]
  263.                 local iv_a4 = msg[11]
  264.                
  265.                 local base = msg[12]
  266.                 local p = msg[13]
  267.                
  268.                 local b1 = mod_exp(base, k1, p)
  269.                 local b2 = mod_exp(base, k2, p)
  270.                 local b3 = mod_exp(base, k3, p)
  271.                 local b4 = mod_exp(base, k4, p)
  272.                
  273.                 local iv_b1 = mod_exp(base, iv_k1, p)
  274.                 local iv_b2 = mod_exp(base, iv_k2, p)
  275.                 local iv_b3 = mod_exp(base, iv_k3, p)
  276.                 local iv_b4 = mod_exp(base, iv_k4, p)
  277.                
  278.                 local s = {}
  279.                 local s1 = mod_exp(a1, k1, p)
  280.                 local s2 = mod_exp(a2, k2, p)
  281.                 local s3 = mod_exp(a3, k3, p)
  282.                 local s4 = mod_exp(a4, k4, p)
  283.                
  284.                 s[1] = bit.brshift(bit.band( s1, 0xFF000000 ), 24)
  285.                 s[2] = bit.brshift(bit.band( s1, 0x00FF0000 ), 16)
  286.                 s[3] = bit.brshift(bit.band( s1, 0x0000FF00 ), 8)
  287.                 s[4] = bit.band( s1, 0x000000FF )
  288.                
  289.                 s[5] = bit.brshift(bit.band( s2, 0xFF000000 ), 24)
  290.                 s[6] = bit.brshift(bit.band( s2, 0x00FF0000 ), 16)
  291.                 s[7] = bit.brshift(bit.band( s2, 0x0000FF00 ), 8)
  292.                 s[8] = bit.band( s2, 0x000000FF )
  293.                
  294.                 s[9] = bit.brshift(bit.band( s3, 0xFF000000 ), 24)
  295.                 s[10] = bit.brshift(bit.band( s3, 0x00FF0000 ), 16)
  296.                 s[11] = bit.brshift(bit.band( s3, 0x0000FF00 ), 8)
  297.                 s[12] = bit.band( s3, 0x000000FF )
  298.                
  299.                 s[13] = bit.brshift(bit.band( s4, 0xFF000000 ), 24)
  300.                 s[14] = bit.brshift(bit.band( s4, 0x00FF0000 ), 16)
  301.                 s[15] = bit.brshift(bit.band( s4, 0x0000FF00 ), 8)
  302.                 s[16] = bit.band( s4, 0x000000FF )
  303.                
  304.                 local iv = {}
  305.                 local iv1 = mod_exp(iv_a1, iv_k1, p)
  306.                 local iv2 = mod_exp(iv_a2, iv_k2, p)
  307.                 local iv3 = mod_exp(iv_a3, iv_k3, p)
  308.                 local iv4 = mod_exp(iv_a4, iv_k4, p)
  309.                
  310.                 iv[1] = bit.brshift(bit.band( iv1, 0xFF000000 ), 24)
  311.                 iv[2] = bit.brshift(bit.band( iv1, 0x00FF0000 ), 16)
  312.                 iv[3] = bit.brshift(bit.band( iv1, 0x0000FF00 ), 8)
  313.                 iv[4] = bit.band( iv1, 0x000000FF )
  314.                
  315.                 iv[5] = bit.brshift(bit.band( iv2, 0xFF000000 ), 24)
  316.                 iv[6] = bit.brshift(bit.band( iv2, 0x00FF0000 ), 16)
  317.                 iv[7] = bit.brshift(bit.band( iv2, 0x0000FF00 ), 8)
  318.                 iv[8] = bit.band( iv2, 0x000000FF )
  319.                
  320.                 iv[9] = bit.brshift(bit.band( iv3, 0xFF000000 ), 24)
  321.                 iv[10] = bit.brshift(bit.band( iv3, 0x00FF0000 ), 16)
  322.                 iv[11] = bit.brshift(bit.band( iv3, 0x0000FF00 ), 8)
  323.                 iv[12] = bit.band( iv3, 0x000000FF )
  324.                
  325.                 iv[13] = bit.brshift(bit.band( iv4, 0xFF000000 ), 24)
  326.                 iv[14] = bit.brshift(bit.band( iv4, 0x00FF0000 ), 16)
  327.                 iv[15] = bit.brshift(bit.band( iv4, 0x0000FF00 ), 8)
  328.                 iv[16] = bit.band( iv4, 0x000000FF )
  329.                
  330.                 if debug then
  331.                     print("connect_server: Numbers generated...")
  332.                 end
  333.                
  334.                 local test_block = {}
  335.                
  336.                 for i=1, 16 do
  337.                     test_block[i] = 0xFF
  338.                 end
  339.                
  340.                 test_block = AES.encrypt_bytestream(test_block, s, iv)
  341.                 if debug then
  342.                     print("connect_server: Sending our keys and the test block...")
  343.                 end
  344.                 modem.transmit( tFreq, rFreq, textutils.serialize({"Tunneling", os.computerID(), "Connect_Key", b1, b2, b3, b4, iv_b1, iv_b2, iv_b3, iv_b4, test_block}) )
  345.                 while true do
  346.                     local _, __, msg2 = listen(30)
  347.                     if msg2 == nil then
  348.                         break
  349.                     end
  350.                     if msg2[1] == "Tunneling" and msg2[2] == id and msg2[3] == "Connection_Established" then
  351.                         local newID = random.random()
  352.                         while true do
  353.                             if not connections[newID] then
  354.                                 break
  355.                             else
  356.                                 newID = random.random()
  357.                             end
  358.                         end
  359.                         if debug then
  360.                             print("connect_server: Connection established. Sending ID...")
  361.                         end
  362.                         local e_str = textutils.serialize({"Connection_ID", newID})
  363.                         local e = {}
  364.                         for i=1, #e_str do
  365.                             e[i] = string.byte(e_str, i, i)
  366.                         end
  367.                         e = AES.encrypt_bytestream(e, s, iv)
  368.                         e = base64.encode(e)
  369.                         modem.transmit( tFreq, rFreq, textutils.serialize({"Tunneling", os.computerID(), e}) )
  370.                         connections[ newID ] = {s, iv}
  371.                         os.queueEvent("secure_connection_open", id, newID)
  372.                         break
  373.                     end
  374.                 end
  375.             elseif msg[3] == "Data" then
  376.                 if debug then
  377.                     print("data_server: Incoming data on connection "..msg[5])
  378.                 end
  379.                 if connections[msg[5]] then
  380.                     local data_bytes = AES.decrypt_bytestream(base64.decode(msg[4]), connections[msg[5]][1], connections[msg[5]][2])
  381.                     local data_str = ""
  382.                     for i=1, #data_bytes do
  383.                         data_str = data_str..string.char(data_bytes[i])
  384.                     end
  385.                     if type(textutils.unserialize(data_str)) == "table" then
  386.                         local data_table = textutils.unserialize(data_str)
  387.                         local packetType = data_table[1]
  388.                         local senderID = data_table[2]
  389.                         connections[msg[5]][2] = data_table[3]
  390.                         local data1 = data_table[4]
  391.                         local data2 = data_table[5]
  392.                         local data3 = data_table[6]
  393.                         if debug then
  394.                             if packetType == "Message" then
  395.                                 print("data_server: Incoming data from "..senderID.." on connection "..msg[5].." : "..data1)
  396.                             elseif packetType == "fakeModemMsg" then
  397.                                 print("data_server: Incoming fake modem_message from "..senderID.." on connection "..msg[5]..": "..data1)
  398.                                 print("data_server: tFreq / rFreq: "..data2.."/"..data3)
  399.                             elseif packetType == "close" then
  400.                                 print("data_server: Closing connection: "..msg[5])
  401.                             elseif packetType == "newKey" then
  402.                                 print("data_server: New key sent by other party.")
  403.                             elseif packetType == "ack_pos" then
  404.                                 print("data_server: Positive acknowledgement received.")
  405.                             elseif packetType == "ack_neg" then
  406.                                 print("data_server: Negative acknowledgement received.")
  407.                             else
  408.                                 print("data_server: Unknown packet type: "..packetType)
  409.                             end
  410.                         end
  411.                         if packetType == "Message" then
  412.                             os.queueEvent("secure_receive", senderID, msg[5], data1)
  413.                         elseif packetType == "fakeModemMsg" then
  414.                             os.queueEvent("modem_message", "left", data2, data3, data1)
  415.                             os.queueEvent("secure_receive", senderID, msg[5], data1)
  416.                         elseif packetType == "close" then
  417.                             connections[msg[5]] = nil
  418.                             os.queueEvent("secure_connection_close", senderID, msg[5])
  419.                         elseif packetType == "newKey" then
  420.                             connections[msg[5]] = { data1, data2 }
  421.                             os.queueEvent("secure_connection_newKey", senderID, msg[5])
  422.                         elseif packetType == "newID" then
  423.                             if not connections[data1] then
  424.                                 if debug then
  425.                                     print("data_server: Switching connection "..msg[5].." to "..data1)
  426.                                 end
  427.                                 sendTunnel_raw(modem, msg[5], "ack_pos")
  428.                                 local cpy = {connections[msg[5]][1], connections[msg[5]][2]}
  429.                                 connections[data1] = cpy
  430.                                 connections[msg[5]] = nil
  431.                                 os.queueEvent("secure_connection_newID",  senderID, msg[5], data1)
  432.                             else
  433.                                 sendTunnel_raw(modem, msg[5], "ack_neg")
  434.                             end
  435.                         elseif packetType == "ack_pos" then
  436.                             os.queueEvent("secure_connection_ack", msg[5], senderID)
  437.                         elseif packetType == "ack_neg" then
  438.                             os.queueEvent("secure_connection_nak", msg[5], senderID)
  439.                         end
  440.                     end
  441.                 end
  442.             end
  443.         end
  444.     end
  445. end
  446.  
  447. function sendTunnel_raw(modem, id, packetType, data1, data2, data3)
  448.     if connections[id] then
  449.         local newIV = {}
  450.         for i=1, 16 do
  451.             newIV[i] = math.random(0, 255)
  452.         end
  453.         local enc_str = ""
  454.         local sec_msg = textutils.serialize({packetType, os.computerID(), newIV, data1, data2, data3})
  455.         local enc_bytes = {}
  456.         for i=1, #sec_msg do
  457.             enc_bytes[i] = string.byte(sec_msg, i, i)
  458.         end
  459.         enc_bytes = AES.encrypt_bytestream(enc_bytes, connections[id][1], connections[id][2])
  460.         enc_str = base64.encode(enc_bytes)
  461.         local data_str = textutils.serialize( {"Tunneling", math.random(1,0xFFFF), "Data", enc_str, id} )
  462.         connections[id][2] = {}
  463.         for i=1, 16 do
  464.             connections[id][2][i] = newIV[i]
  465.         end
  466.         modem.transmit(tunnelFreq, tunnelFreq, data_str)
  467.         return true
  468.     else
  469.         return false
  470.     end
  471. end
  472.  
  473.  
  474. function sendTunnel(modem, id, data)
  475.     --[[
  476.     if connections[id] then
  477.         local enc_str = ""
  478.         local sec_msg = textutils.serialize({"Message", os.computerID(), data})
  479.         local enc_bytes = {}
  480.         for i=1, #sec_msg do
  481.             enc_bytes[i] = string.byte(sec_msg, i, i)
  482.         end
  483.         enc_bytes = AES.encrypt_bytestream(enc_bytes, connections[id][1], connections[id][3])
  484.         enc_str = base64.encode(enc_bytes)
  485.         local data_str = textutils.serialize( {"Tunneling", math.random(1,0xFFFF), "Data", enc_str, id} )
  486.         modem.transmit(tunnelFreq, tunnelFreq, data_str)
  487.         return true
  488.     else
  489.         return false
  490.     end
  491.     ]]
  492.     return sendTunnel_raw(modem, id, "Message", data)
  493. end
  494.  
  495. function sendTunnel_withFreq(modem, id, data, tFreq, rFreq) -- Send a "fake" (but still encrypted) modem transmission.
  496.     --[[
  497.     if connections[id] then
  498.         local enc_str = ""
  499.         local sec_msg = textutils.serialize({os.computerID(), data, tFreq, rFreq})
  500.         local enc_bytes = {}
  501.         for i=1, #sec_msg do
  502.             enc_bytes[i] = string.byte(sec_msg, i, i)
  503.         end
  504.         enc_bytes = AES.encrypt_bytestream(enc_bytes, connections[id][1], connections[id][3])
  505.         enc_str = base64.encode(enc_bytes)
  506.         local data_str = textutils.serialize( {"Tunneling", math.random(1,0xFFFF), "Data", enc_str, id} )
  507.         modem.transmit(tunnelFreq, tunnelFreq, data_str)
  508.         return true
  509.     else
  510.         return false
  511.     end
  512.     ]]
  513.     return sendTunnel_raw(modem, id, "fakeModemMsg", data, tFreq, rFreq)
  514. end
  515.  
  516. function listenTunnel(id, timeout)
  517.     local timer = {}
  518.     if not connections[id] then
  519.         return false
  520.     end
  521.     if timeout then
  522.         timer = os.startTimer(timeout)
  523.     end
  524.     while true do
  525.         local event = {os.pullEvent()}
  526.         if event[1] == "timer" and event[2] == timer then
  527.             return nil
  528.         elseif event[1] == "secure_receive" and event[3] == id then
  529.             return event[2], event[4]
  530.         end
  531.     end
  532. end
  533.  
  534. function closeTunnel(modem, id)
  535.     if connections[id] then
  536.         --modem.transmit(tunnelFreq, tunnelFreq, textutils.serialize( {"Tunneling", os.computerID(), "Close", id} ))
  537.         sendTunnel_raw(modem, id, "close")
  538.         connections[id] = nil
  539.         os.queueEvent("secure_connection_close", id)
  540.         return true
  541.     end
  542.     return false
  543. end
  544.  
  545. function getAllOpenConnections()
  546.     local ids = {}
  547.     for i, v in pairs(connections) do
  548.         table.insert(ids, i)
  549.     end
  550.     return ids
  551. end
  552.  
  553. function getConnectionDetails(conn)
  554.     return {connections[conn][1], connections[conn][2]}
  555. end
  556.  
  557. function installTunnelAsModem(modem, id, side) -- Create a fake (wireless) "modem" peripheral. Cannot override (any) "real" modems.
  558.     if not peripheral.tunnelHijackInPlace then
  559.         peripheral.tunnelHijackInPlace = true
  560.         peripheral.old = {}
  561.         peripheral.tunnels = {}
  562.         for i,v in pairs(peripheral) do
  563.             if i ~= "old" then
  564.                 peripheral.old[i] = v
  565.             end
  566.         end
  567.         peripheral.isPresent = function(methodSide)
  568.             return peripheral.old.isPresent(methodSide) or (peripheral.tunnels[methodSide] ~= nil)
  569.         end
  570.         peripheral.getType = function(methodSide)
  571.             if peripheral.old.isPresent(methodSide) then
  572.                 return peripheral.old.getType(methodSide)
  573.             elseif peripheral.tunnels[methodSide] ~= nil then
  574.                 return "modem"
  575.             end
  576.         end
  577.         peripheral.wrap = function(methodSide)
  578.             if peripheral.old.isPresent(methodSide) then
  579.                 return peripheral.old.wrap(methodSide)
  580.             elseif peripheral.tunnels[methodSide] ~= nil then
  581.                 local copy = {}
  582.                 for i,v in pairs(peripheral.tunnels[methodSide]) do
  583.                     copy[i] = v
  584.                 end
  585.             end
  586.         end
  587.         peripheral.getMethods = function(methodSide)
  588.             if peripheral.old.isPresent(methodSide) then
  589.                 return peripheral.old.getMethods(methodSide)
  590.             elseif peripheral.tunnels[methodSide] ~= nil then
  591.                 local copy = {}
  592.                 local ctr = 1
  593.                 for i,v in pairs(peripheral.tunnels[methodSide]) do
  594.                     copy[ctr] = i
  595.                     ctr = ctr+1
  596.                 end
  597.                 return copy
  598.             end
  599.         end
  600.         peripheral.call = function(...)
  601.             local args = {...}
  602.             local side = args[1]
  603.             local method = args[2]
  604.             if peripheral.tunnels[side] ~= nil then
  605.                 if peripheral.tunnels[side][method] ~= nil then
  606.                     return peripheral.tunnels[side][method](unpack(args, 3))
  607.                 end
  608.             elseif peripheral.old.isPresent(side) then
  609.                 return peripheral.old.call(unpack(args))
  610.             end
  611.         end
  612.         peripheral.getNames = function()
  613.             local names = peripheral.old.getNames()
  614.             for i,v in pairs(peripheral.tunnels) do
  615.                 table.insert(names, i)
  616.             end
  617.             return names
  618.         end
  619.     end
  620.     peripheral.tunnels[side] = {}
  621.     peripheral.tunnels[side].id = id
  622.     peripheral.tunnels[side].modem = modem
  623.     peripheral.tunnels[side].isOpen = function()
  624.         return connections[peripheral.tunnels[side].id] ~= nil
  625.     end
  626.     peripheral.tunnels[side].open = function()
  627.         return true
  628.     end
  629.     peripheral.tunnels[side].close = function()
  630.         closeTunnel(peripheral.tunnels[side].modem, peripheral.tunnels[side].id)
  631.         return true
  632.     end
  633.     peripheral.tunnels[side].closeAll = function()
  634.         closeTunnel(peripheral.tunnels[side].modem, peripheral.tunnels[side].id)
  635.         return true
  636.     end
  637.     peripheral.tunnels[side].isWireless = function()
  638.         return true
  639.     end
  640.     peripheral.tunnels[side].transmit = function(tFreq, rFreq, data)
  641.         sendTunnel_withFreq(peripheral.tunnels[side].modem, peripheral.tunnels[side].id, data, tFreq, rFreq)
  642.     end
  643.     local copy = {}
  644.     for i,v in pairs(peripheral.tunnels[side]) do
  645.         copy[i] = v
  646.     end
  647.     return copy
  648. end
  649.  
  650. function switchConnectionID(modem, oldID, newID)
  651.     sendTunnel_raw(modem, oldID, "newID", newID)
  652.     local timer = os.startTimer(30)
  653.     while true do
  654.         local event, t = os.pullEvent()
  655.         if event == "timer" and t == timer then
  656.             return false
  657.         elseif event == "secure_connection_nak" and t == oldID then
  658.             return false
  659.         elseif event == "secure_connection_ack" and t == oldID then
  660.             connections[newID] = {connections[oldID][1], connections[oldID][2]}
  661.             connections[oldID] = nil
  662.             os.queueEvent("secure_connection_newID",  senderID, oldID, newID)
  663.             return true
  664.         end
  665.     end
  666.     return false
  667. end
  668.  
  669. function switchKey(modem, id, key, iv)
  670.     sendTunnel_raw(modem, id, "newKey", key, iv)
  671.     connections[id] = {key, iv}
  672.     os.queueEvent("secure_connection_newKey", id)
  673. end
  674.  
  675. function openConnectionRaw(connID, key, iv)
  676.     --[[
  677.     local tempID = openTunnel(modem, compID)
  678.     if switchConnectionID(modem, tempID, connID) then
  679.         sendTunnel_raw(modem, "newKey", key, iv)
  680.         return true
  681.     end
  682.     return false
  683.     ]]
  684.     connections[connID] = {key, iv}
  685. end
  686.  
  687. function openTunnel(modem, id, debug)
  688.     modem.open(connFreq)
  689.     modem.open(tunnelFreq)
  690.     local base = math.random(1, 3)
  691.     if base == 1 then
  692.         base = 2
  693.     elseif base == 2 then
  694.         base = 3
  695.     else
  696.         base = 5
  697.     end
  698.     -- Generate 8 different numbers, because AES needs 16 bytes of key, as well as 16 bytes for the IV.
  699.     -- We're running 8 different D-H exchanges with the same base.
  700.     local p = generatePrime(100, debug)
  701.    
  702.     local k1 = random.random()
  703.     local k2 = random.random()
  704.     local k3 = random.random()
  705.     local k4 = random.random()
  706.    
  707.     local iv1 = random.random()
  708.     local iv2 = random.random()
  709.     local iv3 = random.random()
  710.     local iv4 = random.random()
  711.    
  712.     local s1 = 0
  713.     local s2 = 0
  714.     local s3 = 0
  715.     local s4 = 0
  716.    
  717.     local iv_s1 = 0
  718.     local iv_s2 = 0
  719.     local iv_s3 = 0
  720.     local iv_s4 = 0
  721.    
  722.     local a1 = mod_exp(base, k1, p)
  723.     local a2 = mod_exp(base, k2, p)
  724.     local a3 = mod_exp(base, k3, p)
  725.     local a4 = mod_exp(base, k4, p)
  726.    
  727.     local iv_a1 = mod_exp(base, iv1, p)
  728.     local iv_a2 = mod_exp(base, iv2, p)
  729.     local iv_a3 = mod_exp(base, iv3, p)
  730.     local iv_a4 = mod_exp(base, iv4, p)
  731.     if debug then
  732.         print("connect: Numbers generated...")
  733.     end
  734.     modem.transmit(connFreq, connFreq, textutils.serialize({"Tunneling", os.computerID(), "Connect", a1, a2, a3, a4, iv_a1, iv_a2, iv_a3, iv_a4, base, p}))
  735.     while true do
  736.         local tFreq, rFreq, msg = listen(30)
  737.         if tFreq == nil then
  738.             return false
  739.         else
  740.             if tFreq == connFreq then
  741.                 if msg then
  742.                     if msg[1] == "Tunneling" and msg[2] == id and msg[3] == "Connect_Key" then
  743.                         if debug then
  744.                             print("connect: Server has sent its keys...")
  745.                         end
  746.                         s1 = mod_exp(msg[4], k1, p)
  747.                         s2 = mod_exp(msg[5], k2, p)
  748.                         s3 = mod_exp(msg[6], k3, p)
  749.                         s4 = mod_exp(msg[7], k4, p)
  750.                        
  751.                         iv_s1 = mod_exp(msg[8], iv1, p)
  752.                         iv_s2 = mod_exp(msg[9], iv2, p)
  753.                         iv_s3 = mod_exp(msg[10], iv3, p)
  754.                         iv_s4 = mod_exp(msg[11], iv4, p)
  755.                         local serv_test_block = msg[12]
  756.                         local our_test_block = {}
  757.                         for i=1, 16 do
  758.                             our_test_block[i] = 0xFF
  759.                         end
  760.                        
  761.                         local s = {}
  762.                         local iv = {}
  763.                        
  764.                         s[1] = bit.brshift(bit.band( s1, 0xFF000000 ), 24)
  765.                         s[2] = bit.brshift(bit.band( s1, 0x00FF0000 ), 16)
  766.                         s[3] = bit.brshift(bit.band( s1, 0x0000FF00 ), 8)
  767.                         s[4] = bit.band( s1, 0x000000FF )
  768.                        
  769.                         s[5] = bit.brshift(bit.band( s2, 0xFF000000 ), 24)
  770.                         s[6] = bit.brshift(bit.band( s2, 0x00FF0000 ), 16)
  771.                         s[7] = bit.brshift(bit.band( s2, 0x0000FF00 ), 8)
  772.                         s[8] = bit.band( s2, 0x000000FF )
  773.                        
  774.                         s[9] = bit.brshift(bit.band( s3, 0xFF000000 ), 24)
  775.                         s[10] = bit.brshift(bit.band( s3, 0x00FF0000 ), 16)
  776.                         s[11] = bit.brshift(bit.band( s3, 0x0000FF00 ), 8)
  777.                         s[12] = bit.band( s3, 0x000000FF )
  778.                        
  779.                         s[13] = bit.brshift(bit.band( s4, 0xFF000000 ), 24)
  780.                         s[14] = bit.brshift(bit.band( s4, 0x00FF0000 ), 16)
  781.                         s[15] = bit.brshift(bit.band( s4, 0x0000FF00 ), 8)
  782.                         s[16] = bit.band( s4, 0x000000FF )
  783.                        
  784.                         iv[1] = bit.brshift(bit.band( iv_s1, 0xFF000000 ), 24)
  785.                         iv[2] = bit.brshift(bit.band( iv_s1, 0x00FF0000 ), 16)
  786.                         iv[3] = bit.brshift(bit.band( iv_s1, 0x0000FF00 ), 8)
  787.                         iv[4] = bit.band( iv_s1, 0x000000FF )
  788.                        
  789.                         iv[5] = bit.brshift(bit.band( iv_s2, 0xFF000000 ), 24)
  790.                         iv[6] = bit.brshift(bit.band( iv_s2, 0x00FF0000 ), 16)
  791.                         iv[7] = bit.brshift(bit.band( iv_s2, 0x0000FF00 ), 8)
  792.                         iv[8] = bit.band( iv_s2, 0x000000FF )
  793.                        
  794.                         iv[9] = bit.brshift(bit.band( iv_s3, 0xFF000000 ), 24)
  795.                         iv[10] = bit.brshift(bit.band( iv_s3, 0x00FF0000 ), 16)
  796.                         iv[11] = bit.brshift(bit.band( iv_s3, 0x0000FF00 ), 8)
  797.                         iv[12] = bit.band( iv_s3, 0x000000FF )
  798.                        
  799.                         iv[13] = bit.brshift(bit.band( iv_s4, 0xFF000000 ), 24)
  800.                         iv[14] = bit.brshift(bit.band( iv_s4, 0x00FF0000 ), 16)
  801.                         iv[15] = bit.brshift(bit.band( iv_s4, 0x0000FF00 ), 8)
  802.                         iv[16] = bit.band( iv_s4, 0x000000FF )
  803.                        
  804.                         if debug then
  805.                             print("connect: Testing key..")
  806.                         end
  807.                         our_test_block = AES.encrypt_bytestream(our_test_block, s, iv)
  808.                         for i=1, 16 do
  809.                             if our_test_block[i] ~= serv_test_block[i] then
  810.                                 return false
  811.                             end
  812.                         end
  813.                         modem.transmit(connFreq, connFreq, textutils.serialize({"Tunneling", os.computerID(), "Connection_Established"}))
  814.                         if debug then
  815.                             print("connect: Connection established...")
  816.                         end
  817.                         while true do
  818.                             local _, __, msg2 = listen(30)
  819.                             if msg2 == nil then
  820.                                 return false
  821.                             elseif msg2[1] == "Tunneling" and msg2[2] == id then
  822.                                 local d = AES.decrypt_bytestream(base64.decode(msg2[3]), s, iv)
  823.                                 local d_str = ""
  824.                                 for i=1, #d do
  825.                                     d_str = d_str..string.char(d[i])
  826.                                 end
  827.                                 if textutils.unserialize(d_str) then
  828.                                     d = textutils.unserialize(d_str)
  829.                                     if d[1] == "Connection_ID" then
  830.                                         if debug then
  831.                                             print("connect: Recieved connection ID.")
  832.                                         end
  833.                                         connections[ d[2] ] = {s, iv}
  834.                                         os.queueEvent("secure_connection_open", id, d[2])
  835.                                         return d[2]
  836.                                     else
  837.                                         return false
  838.                                     end
  839.                                 else
  840.                                     return false
  841.                                 end
  842.                             end
  843.                         end
  844.                     end
  845.                 end
  846.             end
  847.         end
  848.     end
  849. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement