local ecc = require("ecc") string.toHex = function(str) return str:gsub(".", function(ch) return string.format("%02x", ch:byte()) end) end string.fromHex = function(hex) return hex:gsub("%x%x", function(d) return string.char(tonumber(d, 16)) end) end local keypair = {} if fs.exists("/.id_dh.json") then local fp = io.open("/.id_dh.json", "r") local d = textutils.unserializeJSON(fp:read()) keypair.sk = string.fromHex(d.secret) keypair.pk = string.fromHex(d.public) fp:close() else printError("no identity found, generating...") local sk, pk = ecc.keypair(ecc.random.random()) io.open("/.id_dh.json", "w"):write(textutils.serializeJSON({ secret = string.toHex(sk), public = string.toHex(pk) })):close() keypair.sk = string.char(table.unpack(sk)) keypair.pk = string.char(table.unpack(pk)) end print("pubkey: "..string.toHex(keypair.pk)) local running = true local known_hosts = {} parallel.waitForAll(function() while running do -- dh:discover sender rednet.broadcast(keypair.pk, "dh:discover") os.sleep(10) end end, function() while running do -- dh:discover handler local id, pk, proto = rednet.receive("dh:discover") if proto == "dh:discover" then print("DH discover from "..id.." with key "..pk) local nonce = string.toHex(ecc.random.random()) local key = ecc.exchange(keypair.sk, pk) known_hosts[id] = { id = id, pk = pk, sk = key, verified = false, nonce = nonce, t = os.clock() } known_hosts[pk] = known_hosts[id] rednet.send(id, { pk = keypair.pk, msg = ecc.encrypt(nonce, key) }, "dh:pair") end end end, function() while running do -- dh:pair handler local id, msg, proto = rednet.receive("dh:pair") if proto == "dh:pair" then local key = ecc.exchange(keypair.sk, msg.pk) known_hosts[id] = { id = id, pk = msg.pk, sk = key, verified = false, nonce = ecc.decrypt(msg.msg, msg.msg) } end end end)