Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ---------------------------
- -- Initial Loading Start --
- ---------------------------
- local d = false
- local mod = nil
- for k, v in pairs(peripheral.getNames()) do
- if peripheral.getType(v) == "modem" then
- rednet.open(v)
- mod = peripheral.wrap(v)
- d = true
- end
- end
- if not d or not mod then
- error("A modem is required!")
- end
- local function gen_nonce(size)
- local n = {}
- for i = 1, size do
- n[#n + 1] = math.random(0, 255)
- end
- return n
- end
- local function cc_encrypt(msg, key)
- local nonce = gen_nonce(12)
- local ctx = rlwe.crypt(msg, key, nonce)
- return nonce, ctx
- end
- local function cc_decrypt(ctx, key, nonce)
- return rlwe.crypt(ctx, key, nonce)
- end
- local function download_file(url, target)
- local ht = http.get(url)
- local data = ht.readAll()
- ht.close()
- local file = fs.open(target, "w")
- file.write(data)
- file.close()
- end
- local function read_file(target, mode)
- local f = fs.open(target, mode or "r")
- local a = f.readAll()
- f.close()
- return a
- end
- local function write_file(target, data, mode)
- local f = fs.open(target, mode or "w")
- f.write(data)
- f.close()
- end
- local function getAPI(url, name)
- local apiloc = "/" .. name
- if (not fs.exists(apiloc)) then
- local newapiloc = shell and shell.resolveProgram(name) or nil
- if type(newapiloc) ~= "string" then
- download_file(url, "/" .. name)
- else
- apiloc = newapiloc
- end
- end
- os.loadAPI(apiloc)
- if type(_G[name]) ~= "table" then
- error(name .. " failed to load!")
- return
- end
- end
- getAPI("https://pastebin.com/raw/eUtZh54f", "rlwe")
- -------------------------
- -- Initial Loading End --
- -------------------------
- local RINGNET_API = {}
- local session_keys = {}
- local crypt_sk = {}
- local crypt_channels = {}
- local all_connections = {}
- local our_rids = {}
- local msg_counter = {}
- local ongoing_handshakes = {}
- local _debug = false
- local handshake_id
- if (fs.exists("/.rlwe_hid")) then
- handshake_id = read_file("/.rlwe_hid")
- else
- handshake_id = string.sub(rlwe.digest(tostring(os.getComputerID()) .. tostring(math.random(1, 99999))):toHex(), 1, 8)
- write_file("/.rlwe_hid", handshake_id)
- end
- local static_pubkey = nil
- local static_privkey = nil
- local pkv_table = {}
- ----------------------------
- -- Helper Functions Begin --
- ----------------------------
- local function mesoData(mes)
- if (type(mes) == "string") then
- return textutils.unserialize(mes) or {}
- elseif (type(mes) == "table") then
- return mes
- end
- return {}
- end
- local function get_msg_counter(id)
- return msg_counter[id] or 0
- end
- local function get_handshakeID()
- return handshake_id
- end
- RINGNET_API.get_handshakeID = get_handshakeID
- local function set_debug(a)
- _debug = a
- end
- RINGNET_API.setDebug = set_debug
- local function logDebug(mes)
- if not _debug then
- return false
- end
- print("[DEBUG] " .. tostring(mes))
- end
- local function isConnectionID(id)
- for k, v in pairs(all_connections) do
- if v == id then
- return true
- end
- end
- return false
- end
- local function isOurRid(id)
- for k, v in pairs(our_rids) do
- if v == id then
- return true
- end
- end
- return false
- end
- local function getRidIndex(id)
- for k, v in pairs(our_rids) do
- if v == id then
- return k
- end
- end
- return 0
- end
- local function drop_rid(rid)
- table.remove(our_rids, getRidIndex(rid))
- ongoing_handshakes[tostring(rid)] = nil
- end
- local function openChannel(ch)
- mod.open(ch)
- end
- RINGNET_API.openChannel = openChannel
- local function all_clients()
- return all_connections
- end
- RINGNET_API.all_clients = all_clients
- local function get_fingerprint()
- return rlwe.digest(static_pubkey):toHex()
- end
- RINGNET_API.get_fingerprint = get_fingerprint
- local function to_hex(a)
- return ("%02x"):rep(#a):format(unpack(a))
- end
- --------------------------
- -- Helper Functions End --
- --------------------------
- logDebug("Our handshake-UID is " .. tostring(handshake_id) .. "!")
- ----------------------
- -- Make static keys --
- ----------------------
- if fs.exists("/.rlwe_pubkey") and fs.exists("/.rlwe_privkey") then
- static_pubkey = rlwe.decodePolynomial(read_file("/.rlwe_pubkey", "rb"))
- static_privkey = rlwe.decodePolynomial(read_file("/.rlwe_privkey", "rb"))
- logDebug("Loaded static keys!")
- else
- local new_sk, new_pk = rlwe.keyPair()
- write_file("/.rlwe_pubkey", rlwe.encodePolynomial(new_pk), "wb")
- write_file("/.rlwe_privkey", rlwe.encodePolynomial(new_sk), "wb")
- static_pubkey = new_pk
- static_privkey = new_sk
- logDebug("Generated static keys!")
- end
- if fs.exists("/.rlwe_auth") then
- pkv_table = textutils.unserialize(read_file("/.rlwe_auth"))
- end
- ----------------------------
- -- Actual functions begin --
- ----------------------------
- local function connectionHandler(clientMode)
- while true do
- local _, side, sfrq, rfrq, mes, dist = os.pullEvent("modem_message")
- if (type(mes) == "string") then
- mes = textutils.unserialize(mes)
- end
- if (type(mes) == "table") then
- local srid = tostring(mes.rid)
- logDebug(tostring(mes.type))
- --if (mes.type == "RLWE_DATA") then
- logDebug(
- tostring(mes.type) ..
- "|" ..
- tostring(type(mes.cid) == "string") ..
- "|" ..
- tostring(type(session_keys[mes.cid]) == "table") ..
- "|" ..
- tostring(type(mes.dnonce) == "table") ..
- "|" ..
- tostring(type(mes.dctx) == "string") ..
- "|" .. tostring(type(mes.dhmac) == "string") .. "|" .. tostring(sfrq == crypt_channels[mes.cid])
- )
- --end
- if
- (mes.type == "RLWE_OPEN" and mes.target == handshake_id and type(mes.rid) == "number" and #srid >= 5 and
- type(mes.pkc) == "string")
- then
- mes.pkc = rlwe.decodePolynomial(mes.pkc)
- local fix_mu, fix_mask = rlwe.exchange(static_privkey, mes.pkc)
- local temp_sks, temp_pks = rlwe.keyPair()
- local temp_pks_hmac = rlwe.hmac(temp_pks, fix_mu)
- local temp_mu, temp_mask = rlwe.exchange(temp_sks, mes.pkc)
- logDebug("temp_mu: " .. to_hex(temp_mu))
- local ekey = rlwe.hmac("1enc", temp_mu)
- local hkey = rlwe.hmac("2hmac", temp_mu)
- local cxkey = rlwe.hmac("3cxid", temp_mu)
- local ckey = {unpack(rlwe.hmac("4channel", temp_mu), 1, 2)}
- local cid = cxkey:toHex()
- session_keys[cid] = {
- enckey = ekey,
- cidkey = cxkey,
- chankey = ckey,
- hmackey = hkey
- }
- crypt_channels[cid] = bit.bor(bit.blshift(ckey[1], 8), ckey[2])
- logDebug("Agreed on channel " .. tostring(crypt_channels[cid]) .. "!")
- openChannel(crypt_channels[cid])
- mod.transmit(
- sfrq,
- sfrq,
- textutils.serialize(
- {
- type = "RLWE_TUNNEL1",
- rid = mes.rid,
- from = handshake_id,
- fix_pks = rlwe.encodePolynomial(static_pubkey),
- temp_pks = rlwe.encodePolynomial(temp_pks),
- temp_pks_hmac = tostring(temp_pks_hmac),
- fix_mask = string.char(unpack(fix_mask)),
- temp_mask = string.char(unpack(temp_mask))
- }
- )
- )
- elseif
- (mes.type == "RLWE_TUNNEL1" and isOurRid(mes.rid) and type(mes.rid) == "number" and ongoing_handshakes[srid] and
- type(mes.from) == "string" and
- string.len(mes.from) == 8 and
- type(mes.fix_pks) == "string" and
- type(mes.temp_pks) == "string" and
- type(mes.temp_pks_hmac) == "string" and
- type(mes.fix_mask) == "string" and
- type(mes.temp_mask) == "string" and
- type(crypt_sk[mes.rid]) == "table")
- then
- mes.fix_pks = rlwe.decodePolynomial(mes.fix_pks)
- mes.temp_pks = rlwe.decodePolynomial(mes.temp_pks)
- mes.fix_mask = {mes.fix_mask:byte(1, -1)}
- mes.temp_mask = {mes.temp_mask:byte(1, -1)}
- local continue = true
- -- Do we have a hash stored for this HID? If so, check against it, and drop the connection if they don't match.
- if type(pkv_table[mes.from]) == "string" then
- local sha_fix_pks = pkv_table[mes.from]
- if (not (tostring(rlwe.digest(mes.fix_pks)) == tostring(sha_fix_pks))) then
- drop_rid(mes.rid)
- logDebug("VERIFICATION FAILED, DROPPING CONNECTION!")
- logDebug("SPECIFIC CHECK: SHA(FIXED_PKS) == FIXED_PKS_HASH")
- logDebug("RID " .. srid .. " | HID " .. mes.from)
- continue = false
- else
- logDebug("Verification success!")
- end
- end
- if continue then
- pkv_table[mes.from] = rlwe.digest(mes.fix_pks)
- write_file("/.rlwe_auth", textutils.serialize(pkv_table))
- local skc = crypt_sk[mes.rid]
- local fix_mu = rlwe.exchange(skc, mes.fix_pks, mes.fix_mask)
- local continue_b = true
- if (not (tostring(rlwe.hmac(mes.temp_pks, fix_mu)) == tostring(mes.temp_pks_hmac))) then
- continue_b = false
- drop_rid(mes.rid)
- logDebug("VERIFICATION FAILED, DROPPING CONNECTION!")
- logDebug("SPECIFIC CHECK: HMAC(temp_pks, fix_mu) == TEMP_PKS_HMAC")
- logDebug("RID " .. srid .. " | HID " .. mes.from)
- end
- if continue_b then
- local temp_mu = rlwe.exchange(skc, mes.temp_pks, mes.temp_mask)
- local ekey = rlwe.hmac("1enc", temp_mu)
- local hkey = rlwe.hmac("2hmac", temp_mu)
- local cxkey = rlwe.hmac("3cxid", temp_mu)
- local ckey = {unpack(rlwe.hmac("4channel", temp_mu), 1, 2)}
- local cid = cxkey:toHex()
- session_keys[cid] = {
- enckey = ekey,
- cidkey = cxkey,
- chankey = ckey,
- hmackey = hkey
- }
- logDebug("temp_mu: " .. to_hex(temp_mu))
- crypt_channels[cid] = bit.bor(bit.blshift(ckey[1], 8), ckey[2])
- openChannel(crypt_channels[cid])
- logDebug("Agreed on channel " .. tostring(crypt_channels[cid]) .. "!")
- os.queueEvent("tunnel_finish", cid, mes.from)
- mod.transmit(
- crypt_channels[cid],
- crypt_channels[cid],
- textutils.serialize(
- {
- type = "RLWE_FINISHED",
- cid = cid
- }
- )
- )
- end
- end
- elseif (mes.type == "RLWE_FINISHED" and type(session_keys[mes.cid]) == "table" and sfrq == crypt_channels[mes.cid]) then
- os.queueEvent("tunnel_finish", mes.cid, mes.from)
- logDebug("Got finish message from server!")
- elseif
- (mes.type == "RLWE_DATA" and type(mes.cid) == "string" and type(session_keys[mes.cid]) == "table" and
- type(mes.dnonce) == "table" and
- type(mes.dctx) == "string" and
- type(mes.dhmac) == "string" and
- sfrq == crypt_channels[mes.cid])
- then
- local ekey = session_keys[mes.cid]["enckey"]
- local hkey = session_keys[mes.cid]["hmackey"]
- local chmac =
- tostring(
- rlwe.hmac(tostring(get_msg_counter(mes.cid)) .. tostring(mes.dctx) .. string.char(unpack(mes.dnonce)), hkey)
- )
- logDebug("Message counter: " .. tostring(textutils.serialize(msg_counter)))
- logDebug("Our hmac: " .. tostring(chmac))
- logDebug("Their hmac: " .. tostring(mes.dhmac))
- logDebug("Our hkey: " .. tostring(hkey))
- logDebug("Our hstr:" .. tostring(get_msg_counter(mes.cid)) .. tostring(mes.dctx))
- if (mes.dhmac == chmac) then
- msg_counter[mes.cid] = (get_msg_counter(mes.cid) + 1)
- logDebug("HMAC matched!")
- local dctx = tostring(cc_decrypt(mes.dctx, ekey, mes.dnonce))
- logDebug("Decrypted: " .. dctx)
- logDebug("New message counter for " .. tostring(mes.cid) .. ": " .. tostring(get_msg_counter(mes.cid)))
- os.queueEvent("secure_receive", mes.cid, dctx, dist)
- end
- end
- end
- sleep(0)
- end
- end
- RINGNET_API.connectionHandler = connectionHandler
- local function openTunnel(targetID, frq)
- assert(type(targetID) == "string", "openTunnel requires a HUID!")
- assert(type(frq) == "number", "openTunnel modem frequency must be a number!")
- local rid = math.random(100000, 999999)
- ongoing_handshakes[tostring(rid)] = true
- table.insert(our_rids, rid)
- logDebug("OUR RID IS " .. tostring(rid))
- local skc, pkc = rlwe.keyPair()
- crypt_sk[rid] = skc
- mod.transmit(
- frq,
- frq,
- textutils.serialize(
- {
- type = "RLWE_OPEN",
- rid = rid,
- target = targetID,
- pkc = rlwe.encodePolynomial(pkc)
- }
- )
- )
- end
- RINGNET_API.openTunnel = openTunnel
- local function sendData(targetCID, data)
- assert(type(targetCID) == "string", "targetCID must be a string!")
- assert(type(data) == "string", "data must be a string!")
- if (type(data) == "table") then
- data = textutils.serialize(data)
- end
- data = tostring(data)
- assert(type(session_keys) == "table", "Oh god, there is no session key table!")
- local keys = session_keys[targetCID]
- assert(type(session_keys[targetCID]) == "table", "No encryption key for " .. tostring(targetCID))
- assert(type(crypt_channels[targetCID]) == "number", "No channel for " .. tostring(targetCID))
- local ekey = keys["enckey"]
- local hkey = keys["hmackey"]
- local dnonce, dctx = cc_encrypt(data, ekey)
- logDebug("Message counter: " .. tostring(get_msg_counter(targetCID)))
- logDebug("Our hkey: " .. tostring(hkey))
- logDebug("Our hstr: " .. tostring(get_msg_counter(targetCID)) .. tostring(dctx))
- logDebug(targetCID .. ": " .. tostring(crypt_channels[targetCID]))
- mod.transmit(
- crypt_channels[targetCID],
- crypt_channels[targetCID],
- textutils.serialize(
- {
- type = "RLWE_DATA",
- cid = targetCID,
- dhmac = tostring(
- rlwe.hmac(tostring(get_msg_counter(targetCID)) .. tostring(dctx) .. string.char(unpack(dnonce)), hkey)
- ),
- dctx = tostring(dctx),
- dnonce = dnonce
- }
- )
- )
- msg_counter[targetCID] = get_msg_counter(targetCID) + 1
- end
- RINGNET_API.sendData = sendData
- return RINGNET_API
Advertisement
Add Comment
Please, Sign In to add comment