turtle5204

WIP Ring LWE networking

Apr 21st, 2018
140
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 5.59 KB | None | 0 0
  1. local d = false
  2. for k, v in pairs(peripheral.getNames()) do
  3.     if peripheral.getType(v) == "modem" then
  4.         rednet.open(v)
  5.         d = true
  6.     end
  7. end
  8. if not d then
  9.     error("A modem is required!")
  10. end
  11.  
  12. DEBUG = false
  13.  
  14. dist_cache = {}
  15.  
  16. local function print_debug(stuff)
  17.     if DEBUG == true then
  18.         print(stuff)
  19.     end
  20. end
  21.  
  22. local function download_file(url, target)
  23.     local ht = http.get(url)
  24.     local data = ht.readAll()
  25.     ht.close()
  26.     local file = fs.open(target, "w")
  27.     file.write(data)
  28.     file.close()
  29. end
  30.  
  31. local ringloc = "/ring"
  32. if (not fs.exists(ringloc)) then
  33.     local newringloc = shell and shell.resolveProgram("ring") or nil
  34.     if type(newringloc) ~= "string" then
  35.         download_file("https://pastebin.com/raw/hCbYTgRs", "/ring")
  36.     else
  37.         ringloc = newringloc
  38.     end
  39. end
  40. os.loadAPI(ringloc)
  41. if not ring then
  42.     error("Ring LWE API failed to load!")
  43.     return
  44. end
  45.  
  46. local aesloc = "/aes"
  47. if (not fs.exists(aesloc)) then
  48.     local newaesloc = shell and shell.resolveProgram("aes") or nil
  49.     if type(newaesloc) ~= "string" then
  50.         download_file(
  51.             "https://gist.githubusercontent.com/SquidDev/86925e07cbabd70773e53d781bd8b2fe/raw/aeslua.min.lua",
  52.             "/aes"
  53.         )
  54.     else
  55.         aesloc = newaesloc
  56.     end
  57. end
  58. os.loadAPI(aesloc)
  59. if not aes then
  60.     error("AES API failed to load!")
  61.     return
  62. end
  63.  
  64. local function aes_encrypt(key, data, ...)
  65.     return aes.encrypt(string.char(table.unpack(key)), data, ...)
  66. end
  67.  
  68. local function aes_decrypt(key, data)
  69.     return aes.decrypt(string.char(table.unpack(key)), data)
  70. end
  71.  
  72. function recv_with_dist(sProtocolFilter, nTimeout)
  73.     -- The parameters used to be ( nTimeout ), detect this case for backwards compatibility
  74.     if type(sProtocolFilter) == "number" and nTimeout == nil then
  75.         sProtocolFilter, nTimeout = nil, sProtocolFilter
  76.     end
  77.     if sProtocolFilter ~= nil and type(sProtocolFilter) ~= "string" then
  78.         error("bad argument #1 (expected string, got " .. type(sProtocolFilter) .. ")", 2)
  79.     end
  80.     if nTimeout ~= nil and type(nTimeout) ~= "number" then
  81.         error("bad argument #2 (expected number, got " .. type(nTimeout) .. ")", 2)
  82.     end
  83.  
  84.     -- Start the timer
  85.     local timer = nil
  86.     local sFilter = nil
  87.     if nTimeout then
  88.         timer = os.startTimer(nTimeout)
  89.         sFilter = nil
  90.     else
  91.         sFilter = "modem_message"
  92.     end
  93.  
  94.     -- Wait for events
  95.     while true do
  96.         local sEvent, sModem, nChannel, nReplyChannel, tMessage, nDistance = os.pullEvent(sFilter)
  97.         if sEvent == "modem_message" then
  98.             -- Return the first matching rednet_message
  99.             local message = tMessage.message
  100.             if tMessage.sProtocol == nil or tMessage.sProtocol == sProtocolFilter then
  101.                 return nReplyChannel, message, tMessage.sProtocol, nDistance
  102.             end
  103.         elseif sEvent == "timer" then
  104.             -- Return nil if we timeout
  105.             if p1 == timer then
  106.                 return nil
  107.             end
  108.         end
  109.     end
  110. end
  111.  
  112. -- Receiving handshake!
  113. function initiate_handshake(p)
  114.     while true do
  115.         local from, mes, prot, dist = recv_with_dist(p)
  116.         local data = {}
  117.         if (type(mes) == "string") then
  118.             data = textutils.unserialize(mes)
  119.         end
  120.         if (dist_cache[from] ~= false and type(dist_cache[from]) ~= "number") then
  121.             if (data.moving_mode) then
  122.                 dist_cache[from] = false
  123.             else
  124.                 dist_cache[from] = dist
  125.             end
  126.         end
  127.         print_debug(textutils.serialize(tostring(data)))
  128.         print_debug(data.type)
  129.         if type(data) == "table" and data.type == "RingLWE_h1" then --YES! We got a handshake.
  130.             print_debug("Got a handshake!")
  131.             local mu, c = ring.encapsulate(data.capsule)
  132.             sleep(0.1)
  133.             local ctx = aes_encrypt(mu, "verification string")
  134.             print_debug("aes: " .. tostring(ctx))
  135.             rednet.send(
  136.                 from,
  137.                 textutils.serialize(
  138.                     {
  139.                         type = "RingLWE_h2",
  140.                         capsule = c,
  141.                         verify = ctx
  142.                     }
  143.                 ),
  144.                 prot
  145.             )
  146.             return mu, c, from
  147.         end
  148.         sleep(0)
  149.     end
  150. end
  151.  
  152. function start_handshake(id, p)
  153.     local s1, b = ring.keyPair()
  154.     rednet.send(
  155.         id,
  156.         textutils.serialize(
  157.             {
  158.                 type = "RingLWE_h1",
  159.                 capsule = b,
  160.                 moving_mode = (pocket ~= nil)
  161.             }
  162.         ),
  163.         p
  164.     )
  165.     print_debug("Sent handshake.")
  166.     while true do
  167.         local from, mes, prot, dist = recv_with_dist(p)
  168.         local data = {}
  169.         if (type(mes) == "string") then
  170.             data = textutils.unserialize(mes)
  171.         end
  172.         if data.type == "RingLWE_h2" then --YES! We got a handshake.
  173.             print_debug("We got a return handshake!")
  174.             if (dist_cache[from] ~= nil and type(dist_cache[from]) == "number" and dist_cache[from] ~= dist) then
  175.                 print_debug("ALERT! ALERT! DISTANCE CHECK FAILED AGAINST " .. tostring(from))
  176.             end
  177.             local their_capsule = data.capsule
  178.             local mu = ring.decapsulate(s1, their_capsule)
  179.             if (aes_decrypt(mu, tostring(data.verify))) then
  180.                 print_debug("Woo! Ring Exchange worked!")
  181.             end
  182.             return mu
  183.         end
  184.         sleep(0)
  185.     end
  186. end
  187.  
  188. function send_ring(data, mu, p, id)
  189.     if (type(data) ~= "string") then
  190.         data = tostring(data)
  191.     end
  192.     if (type(id) == "number") then
  193.         rednet.send(
  194.             id,
  195.             textutils.serialize(
  196.                 {
  197.                     type = "RingLWE_d",
  198.                     ctx = aes_encrypt(mu, data)
  199.                 }
  200.             ),
  201.             p
  202.         )
  203.     else
  204.         rednet.broadcast(
  205.             textutils.serialize(
  206.                 {
  207.                     type = "RingLWE_d",
  208.                     ctx = aes_encrypt(mu, data)
  209.                 }
  210.             ),
  211.             p
  212.         )
  213.     end
  214. end
  215.  
  216. function recv_ring(mu, p)
  217.     local from, mes, prot, dist = recv_with_dist(p)
  218.     if (dist_cache[from] ~= nil and type(dist_cache[from]) == "number" and dist_cache[from] ~= dist) then
  219.         print_debug("ALERT! ALERT! DISTANCE CHECK FAILED AGAINST " .. tostring(from))
  220.     end
  221.     local data = {}
  222.     if (type(mes) == "string") then
  223.         data = textutils.unserialize(mes)
  224.     end
  225.     print_debug(tostring(data.type))
  226.     print_debug(tostring(mes))
  227.     if (data.type == "RingLWE_d") then
  228.         return aes_decrypt(mu, tostring(data.ctx))
  229.     end
  230. end
Advertisement
Add Comment
Please, Sign In to add comment