turtle5204

NEW NEW NEW ringnet api

Jun 9th, 2018
651
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 13.30 KB | None | 0 0
  1. ---------------------------
  2. -- Initial Loading Start --
  3. ---------------------------
  4. local d = false
  5. local mod = nil
  6. for k, v in pairs(peripheral.getNames()) do
  7.     if peripheral.getType(v) == "modem" then
  8.         rednet.open(v)
  9.         mod = peripheral.wrap(v)
  10.         d = true
  11.     end
  12. end
  13. if not d or not mod then
  14.     error("A modem is required!")
  15. end
  16.  
  17. local function gen_nonce(size)
  18.     local n = {}
  19.     for i = 1, size do
  20.         n[#n + 1] = math.random(0, 255)
  21.     end
  22.     return n
  23. end
  24.  
  25. local function cc_encrypt(msg, key)
  26.     local nonce = gen_nonce(12)
  27.     local ctx = rlwe.crypt(msg, key, nonce)
  28.     return nonce, ctx
  29. end
  30.  
  31. local function cc_decrypt(ctx, key, nonce)
  32.     return rlwe.crypt(ctx, key, nonce)
  33. end
  34.  
  35. local function download_file(url, target)
  36.     local ht = http.get(url)
  37.     local data = ht.readAll()
  38.     ht.close()
  39.     local file = fs.open(target, "w")
  40.     file.write(data)
  41.     file.close()
  42. end
  43.  
  44. local function read_file(target, mode)
  45.     local f = fs.open(target, mode or "r")
  46.     local a = f.readAll()
  47.     f.close()
  48.     return a
  49. end
  50.  
  51. local function write_file(target, data, mode)
  52.     local f = fs.open(target, mode or "w")
  53.     f.write(data)
  54.     f.close()
  55. end
  56.  
  57. local function getAPI(url, name)
  58.     local apiloc = "/" .. name
  59.     if (not fs.exists(apiloc)) then
  60.         local newapiloc = shell and shell.resolveProgram(name) or nil
  61.         if type(newapiloc) ~= "string" then
  62.             download_file(url, "/" .. name)
  63.         else
  64.             apiloc = newapiloc
  65.         end
  66.     end
  67.     os.loadAPI(apiloc)
  68.     if type(_G[name]) ~= "table" then
  69.         error(name .. " failed to load!")
  70.         return
  71.     end
  72. end
  73.  
  74. getAPI("https://pastebin.com/raw/eUtZh54f", "rlwe")
  75. -------------------------
  76. -- Initial Loading End --
  77. -------------------------
  78.  
  79. local RINGNET_API = {}
  80.  
  81. local session_keys = {}
  82. local crypt_sk = {}
  83. local crypt_channels = {}
  84. local all_connections = {}
  85. local our_rids = {}
  86. local msg_counter = {}
  87. local ongoing_handshakes = {}
  88. local _debug = false
  89.  
  90. local handshake_id
  91. if (fs.exists("/.rlwe_hid")) then
  92.     handshake_id = read_file("/.rlwe_hid")
  93. else
  94.     handshake_id = string.sub(rlwe.digest(tostring(os.getComputerID()) .. tostring(math.random(1, 99999))):toHex(), 1, 8)
  95.     write_file("/.rlwe_hid", handshake_id)
  96. end
  97.  
  98. local static_pubkey = nil
  99. local static_privkey = nil
  100.  
  101. local pkv_table = {}
  102.  
  103. ----------------------------
  104. -- Helper Functions Begin --
  105. ----------------------------
  106.  
  107. local function mesoData(mes)
  108.     if (type(mes) == "string") then
  109.         return textutils.unserialize(mes) or {}
  110.     elseif (type(mes) == "table") then
  111.         return mes
  112.     end
  113.     return {}
  114. end
  115.  
  116. local function get_msg_counter(id)
  117.     return msg_counter[id] or 0
  118. end
  119.  
  120. local function get_handshakeID()
  121.     return handshake_id
  122. end
  123. RINGNET_API.get_handshakeID = get_handshakeID
  124.  
  125. local function set_debug(a)
  126.     _debug = a
  127. end
  128. RINGNET_API.setDebug = set_debug
  129.  
  130. local function logDebug(mes)
  131.     if not _debug then
  132.         return false
  133.     end
  134.     print("[DEBUG] " .. tostring(mes))
  135. end
  136.  
  137. local function isConnectionID(id)
  138.     for k, v in pairs(all_connections) do
  139.         if v == id then
  140.             return true
  141.         end
  142.     end
  143.     return false
  144. end
  145.  
  146. local function isOurRid(id)
  147.     for k, v in pairs(our_rids) do
  148.         if v == id then
  149.             return true
  150.         end
  151.     end
  152.     return false
  153. end
  154.  
  155. local function getRidIndex(id)
  156.     for k, v in pairs(our_rids) do
  157.         if v == id then
  158.             return k
  159.         end
  160.     end
  161.     return 0
  162. end
  163.  
  164. local function drop_rid(rid)
  165.     table.remove(our_rids, getRidIndex(rid))
  166.     ongoing_handshakes[tostring(rid)] = nil
  167. end
  168.  
  169. local function openChannel(ch)
  170.     mod.open(ch)
  171. end
  172. RINGNET_API.openChannel = openChannel
  173.  
  174. local function all_clients()
  175.     return all_connections
  176. end
  177. RINGNET_API.all_clients = all_clients
  178.  
  179. local function get_fingerprint()
  180.     return rlwe.digest(static_pubkey):toHex()
  181. end
  182. RINGNET_API.get_fingerprint = get_fingerprint
  183.  
  184. local function to_hex(a)
  185.     return ("%02x"):rep(#a):format(unpack(a))
  186. end
  187.  
  188. --------------------------
  189. -- Helper Functions End --
  190. --------------------------
  191.  
  192. logDebug("Our handshake-UID is " .. tostring(handshake_id) .. "!")
  193.  
  194. ----------------------
  195. -- Make static keys --
  196. ----------------------
  197.  
  198. if fs.exists("/.rlwe_pubkey") and fs.exists("/.rlwe_privkey") then
  199.     static_pubkey = rlwe.decodePolynomial(read_file("/.rlwe_pubkey", "rb"))
  200.     static_privkey = rlwe.decodePolynomial(read_file("/.rlwe_privkey", "rb"))
  201.     logDebug("Loaded static keys!")
  202. else
  203.     local new_sk, new_pk = rlwe.keyPair()
  204.     write_file("/.rlwe_pubkey", rlwe.encodePolynomial(new_pk), "wb")
  205.     write_file("/.rlwe_privkey", rlwe.encodePolynomial(new_sk), "wb")
  206.     static_pubkey = new_pk
  207.     static_privkey = new_sk
  208.     logDebug("Generated static keys!")
  209. end
  210.  
  211. if fs.exists("/.rlwe_auth") then
  212.     pkv_table = textutils.unserialize(read_file("/.rlwe_auth"))
  213. end
  214.  
  215. ----------------------------
  216. -- Actual functions begin --
  217. ----------------------------
  218.  
  219. local function connectionHandler(clientMode)
  220.     while true do
  221.         local _, side, sfrq, rfrq, mes, dist = os.pullEvent("modem_message")
  222.         if (type(mes) == "string") then
  223.             mes = textutils.unserialize(mes)
  224.         end
  225.         if (type(mes) == "table") then
  226.             local srid = tostring(mes.rid)
  227.             logDebug(tostring(mes.type))
  228.             --if (mes.type == "RLWE_DATA") then
  229.             logDebug(
  230.                 tostring(mes.type) ..
  231.                     "|" ..
  232.                         tostring(type(mes.cid) == "string") ..
  233.                             "|" ..
  234.                                 tostring(type(session_keys[mes.cid]) == "table") ..
  235.                                     "|" ..
  236.                                         tostring(type(mes.dnonce) == "table") ..
  237.                                             "|" ..
  238.                                                 tostring(type(mes.dctx) == "string") ..
  239.                                                     "|" .. tostring(type(mes.dhmac) == "string") .. "|" .. tostring(sfrq == crypt_channels[mes.cid])
  240.             )
  241.             --end
  242.  
  243.             if
  244.                 (mes.type == "RLWE_OPEN" and mes.target == handshake_id and type(mes.rid) == "number" and #srid >= 5 and
  245.                     type(mes.pkc) == "string")
  246.              then
  247.                 mes.pkc = rlwe.decodePolynomial(mes.pkc)
  248.                 local fix_mu, fix_mask = rlwe.exchange(static_privkey, mes.pkc)
  249.                 local temp_sks, temp_pks = rlwe.keyPair()
  250.                 local temp_pks_hmac = rlwe.hmac(temp_pks, fix_mu)
  251.                 local temp_mu, temp_mask = rlwe.exchange(temp_sks, mes.pkc)
  252.                 logDebug("temp_mu: " .. to_hex(temp_mu))
  253.                 local ekey = rlwe.hmac("1enc", temp_mu)
  254.                 local hkey = rlwe.hmac("2hmac", temp_mu)
  255.                 local cxkey = rlwe.hmac("3cxid", temp_mu)
  256.                 local ckey = {unpack(rlwe.hmac("4channel", temp_mu), 1, 2)}
  257.                 local cid = cxkey:toHex()
  258.                 session_keys[cid] = {
  259.                     enckey = ekey,
  260.                     cidkey = cxkey,
  261.                     chankey = ckey,
  262.                     hmackey = hkey
  263.                 }
  264.  
  265.                 crypt_channels[cid] = bit.bor(bit.blshift(ckey[1], 8), ckey[2])
  266.                 logDebug("Agreed on channel " .. tostring(crypt_channels[cid]) .. "!")
  267.                 openChannel(crypt_channels[cid])
  268.  
  269.                 mod.transmit(
  270.                     sfrq,
  271.                     sfrq,
  272.                     textutils.serialize(
  273.                         {
  274.                             type = "RLWE_TUNNEL1",
  275.                             rid = mes.rid,
  276.                             from = handshake_id,
  277.                             fix_pks = rlwe.encodePolynomial(static_pubkey),
  278.                             temp_pks = rlwe.encodePolynomial(temp_pks),
  279.                             temp_pks_hmac = tostring(temp_pks_hmac),
  280.                             fix_mask = string.char(unpack(fix_mask)),
  281.                             temp_mask = string.char(unpack(temp_mask))
  282.                         }
  283.                     )
  284.                 )
  285.             elseif
  286.                 (mes.type == "RLWE_TUNNEL1" and isOurRid(mes.rid) and type(mes.rid) == "number" and ongoing_handshakes[srid] and
  287.                     type(mes.from) == "string" and
  288.                     string.len(mes.from) == 8 and
  289.                     type(mes.fix_pks) == "string" and
  290.                     type(mes.temp_pks) == "string" and
  291.                     type(mes.temp_pks_hmac) == "string" and
  292.                     type(mes.fix_mask) == "string" and
  293.                     type(mes.temp_mask) == "string" and
  294.                     type(crypt_sk[mes.rid]) == "table")
  295.              then
  296.                 mes.fix_pks = rlwe.decodePolynomial(mes.fix_pks)
  297.                 mes.temp_pks = rlwe.decodePolynomial(mes.temp_pks)
  298.                 mes.fix_mask = {mes.fix_mask:byte(1, -1)}
  299.                 mes.temp_mask = {mes.temp_mask:byte(1, -1)}
  300.                 local continue = true
  301.                 -- Do we have a hash stored for this HID? If so, check against it, and drop the connection if they don't match.
  302.                 if type(pkv_table[mes.from]) == "string" then
  303.                     local sha_fix_pks = pkv_table[mes.from]
  304.                     if (not (tostring(rlwe.digest(mes.fix_pks)) == tostring(sha_fix_pks))) then
  305.                         drop_rid(mes.rid)
  306.                         logDebug("VERIFICATION FAILED, DROPPING CONNECTION!")
  307.                         logDebug("SPECIFIC CHECK: SHA(FIXED_PKS) == FIXED_PKS_HASH")
  308.                         logDebug("RID " .. srid .. " | HID " .. mes.from)
  309.                         continue = false
  310.                     else
  311.                         logDebug("Verification success!")
  312.                     end
  313.                 end
  314.  
  315.                 if continue then
  316.                     pkv_table[mes.from] = rlwe.digest(mes.fix_pks)
  317.                     write_file("/.rlwe_auth", textutils.serialize(pkv_table))
  318.                     local skc = crypt_sk[mes.rid]
  319.                     local fix_mu = rlwe.exchange(skc, mes.fix_pks, mes.fix_mask)
  320.                     local continue_b = true
  321.                     if (not (tostring(rlwe.hmac(mes.temp_pks, fix_mu)) == tostring(mes.temp_pks_hmac))) then
  322.                         continue_b = false
  323.                         drop_rid(mes.rid)
  324.                         logDebug("VERIFICATION FAILED, DROPPING CONNECTION!")
  325.                         logDebug("SPECIFIC CHECK: HMAC(temp_pks, fix_mu) == TEMP_PKS_HMAC")
  326.                         logDebug("RID " .. srid .. " | HID " .. mes.from)
  327.                     end
  328.                     if continue_b then
  329.                         local temp_mu = rlwe.exchange(skc, mes.temp_pks, mes.temp_mask)
  330.  
  331.                         local ekey = rlwe.hmac("1enc", temp_mu)
  332.                         local hkey = rlwe.hmac("2hmac", temp_mu)
  333.                         local cxkey = rlwe.hmac("3cxid", temp_mu)
  334.                         local ckey = {unpack(rlwe.hmac("4channel", temp_mu), 1, 2)}
  335.                         local cid = cxkey:toHex()
  336.                         session_keys[cid] = {
  337.                             enckey = ekey,
  338.                             cidkey = cxkey,
  339.                             chankey = ckey,
  340.                             hmackey = hkey
  341.                         }
  342.  
  343.                         logDebug("temp_mu: " .. to_hex(temp_mu))
  344.  
  345.                         crypt_channels[cid] = bit.bor(bit.blshift(ckey[1], 8), ckey[2])
  346.                         openChannel(crypt_channels[cid])
  347.                         logDebug("Agreed on channel " .. tostring(crypt_channels[cid]) .. "!")
  348.                         os.queueEvent("tunnel_finish", cid, mes.from)
  349.                         mod.transmit(
  350.                             crypt_channels[cid],
  351.                             crypt_channels[cid],
  352.                             textutils.serialize(
  353.                                 {
  354.                                     type = "RLWE_FINISHED",
  355.                                     cid = cid
  356.                                 }
  357.                             )
  358.                         )
  359.                     end
  360.                 end
  361.             elseif (mes.type == "RLWE_FINISHED" and type(session_keys[mes.cid]) == "table" and sfrq == crypt_channels[mes.cid]) then
  362.                 os.queueEvent("tunnel_finish", mes.cid, mes.from)
  363.                 logDebug("Got finish message from server!")
  364.             elseif
  365.                 (mes.type == "RLWE_DATA" and type(mes.cid) == "string" and type(session_keys[mes.cid]) == "table" and
  366.                     type(mes.dnonce) == "table" and
  367.                     type(mes.dctx) == "string" and
  368.                     type(mes.dhmac) == "string" and
  369.                     sfrq == crypt_channels[mes.cid])
  370.              then
  371.                 local ekey = session_keys[mes.cid]["enckey"]
  372.                 local hkey = session_keys[mes.cid]["hmackey"]
  373.                 local chmac =
  374.                     tostring(
  375.                     rlwe.hmac(tostring(get_msg_counter(mes.cid)) .. tostring(mes.dctx) .. string.char(unpack(mes.dnonce)), hkey)
  376.                 )
  377.                 logDebug("Message counter: " .. tostring(textutils.serialize(msg_counter)))
  378.                 logDebug("Our hmac: " .. tostring(chmac))
  379.                 logDebug("Their hmac: " .. tostring(mes.dhmac))
  380.                 logDebug("Our hkey: " .. tostring(hkey))
  381.                 logDebug("Our hstr:" .. tostring(get_msg_counter(mes.cid)) .. tostring(mes.dctx))
  382.                 if (mes.dhmac == chmac) then
  383.                     msg_counter[mes.cid] = (get_msg_counter(mes.cid) + 1)
  384.                     logDebug("HMAC matched!")
  385.                     local dctx = tostring(cc_decrypt(mes.dctx, ekey, mes.dnonce))
  386.                     logDebug("Decrypted: " .. dctx)
  387.                     logDebug("New message counter for " .. tostring(mes.cid) .. ": " .. tostring(get_msg_counter(mes.cid)))
  388.                     os.queueEvent("secure_receive", mes.cid, dctx, dist)
  389.                 end
  390.             end
  391.         end
  392.         sleep(0)
  393.     end
  394. end
  395. RINGNET_API.connectionHandler = connectionHandler
  396.  
  397. local function openTunnel(targetID, frq)
  398.     assert(type(targetID) == "string", "openTunnel requires a HUID!")
  399.     assert(type(frq) == "number", "openTunnel modem frequency must be a number!")
  400.     local rid = math.random(100000, 999999)
  401.     ongoing_handshakes[tostring(rid)] = true
  402.     table.insert(our_rids, rid)
  403.     logDebug("OUR RID IS  " .. tostring(rid))
  404.     local skc, pkc = rlwe.keyPair()
  405.     crypt_sk[rid] = skc
  406.     mod.transmit(
  407.         frq,
  408.         frq,
  409.         textutils.serialize(
  410.             {
  411.                 type = "RLWE_OPEN",
  412.                 rid = rid,
  413.                 target = targetID,
  414.                 pkc = rlwe.encodePolynomial(pkc)
  415.             }
  416.         )
  417.     )
  418. end
  419. RINGNET_API.openTunnel = openTunnel
  420.  
  421. local function sendData(targetCID, data)
  422.     assert(type(targetCID) == "string", "targetCID must be a string!")
  423.     assert(type(data) == "string", "data must be a string!")
  424.     if (type(data) == "table") then
  425.         data = textutils.serialize(data)
  426.     end
  427.     data = tostring(data)
  428.     assert(type(session_keys) == "table", "Oh god, there is no session key table!")
  429.     local keys = session_keys[targetCID]
  430.     assert(type(session_keys[targetCID]) == "table", "No encryption key for " .. tostring(targetCID))
  431.     assert(type(crypt_channels[targetCID]) == "number", "No channel for " .. tostring(targetCID))
  432.     local ekey = keys["enckey"]
  433.     local hkey = keys["hmackey"]
  434.     local dnonce, dctx = cc_encrypt(data, ekey)
  435.     logDebug("Message counter: " .. tostring(get_msg_counter(targetCID)))
  436.     logDebug("Our hkey: " .. tostring(hkey))
  437.     logDebug("Our hstr: " .. tostring(get_msg_counter(targetCID)) .. tostring(dctx))
  438.     logDebug(targetCID .. ": " .. tostring(crypt_channels[targetCID]))
  439.     mod.transmit(
  440.         crypt_channels[targetCID],
  441.         crypt_channels[targetCID],
  442.         textutils.serialize(
  443.             {
  444.                 type = "RLWE_DATA",
  445.                 cid = targetCID,
  446.                 dhmac = tostring(
  447.                     rlwe.hmac(tostring(get_msg_counter(targetCID)) .. tostring(dctx) .. string.char(unpack(dnonce)), hkey)
  448.                 ),
  449.                 dctx = tostring(dctx),
  450.                 dnonce = dnonce
  451.             }
  452.         )
  453.     )
  454.     msg_counter[targetCID] = get_msg_counter(targetCID) + 1
  455. end
  456. RINGNET_API.sendData = sendData
  457. return RINGNET_API
Advertisement
Add Comment
Please, Sign In to add comment