security - final round?

This commit is contained in:
kepler155c@gmail.com 2019-06-29 22:02:00 -04:00
parent e75a357209
commit 1c29197983
3 changed files with 47 additions and 24 deletions

View File

@ -6,7 +6,6 @@
]]--
local Event = require('opus.event')
local SHA = require('opus.crypto.sha2')
local network = _G.network
local os = _G.os
@ -39,7 +38,7 @@ end
function transport.write(socket, data)
socket.transmit(socket.dport, socket.dhost, data)
socket.wseq = SHA.digest(socket.wseq):toHex()
socket.wseq = socket.wrng:nextInt(5)
end
function transport.ping(socket)
@ -113,7 +112,8 @@ Event.on('modem_message', function(_, _, dport, dhost, msg, distance)
_syslog('got ' .. msg.seq)
else
socket.activityTimer = os.clock()
socket.rseq = SHA.digest(socket.rseq):toHex()
socket.rseq = socket.rrng:nextInt(5)
table.insert(socket.messages, { msg.data, distance })
if not socket.messages[2] then -- table size is 1

View File

@ -10,12 +10,13 @@ local bxor = bit32.bxor
local band = bit32.band
local blshift = bit32.lshift
local brshift = bit32.arshift
local os = _G.os
local textutils = _G.textutils
local mod = 2^32
local tau = {("expand 16-byte k"):byte(1,-1)}
local sigma = {("expand 32-byte k"):byte(1,-1)}
local null32 = {("A"):rep(32):byte(1,-1)}
local null12 = {("A"):rep(12):byte(1,-1)}
local function rotl(n, b)
local s = n/(2^(32-b))
@ -164,7 +165,35 @@ local function decrypt(data, key)
return textutils.unserialise(tostring(ptx))
end
local obj = {}
local mt = {['__index'] = obj}
function obj:nextInt(byte)
if byte < 1 or byte > 6 then error("Can only return 1-6 bytes", 2) end
local output = 0
for i = 0, byte-1 do
if #self.block == 0 then
self.cnt = self.cnt + 1
self.block = crypt(null32, self.seed, null12, self.cnt)
end
local newByte = table.remove(self.block)
output = output + (newByte * (2^(8*i)))
end
return output
end
local function newRNG(seed)
local o = {}
o.seed = seed
o.cnt = 0
o.block = {}
return setmetatable(o, mt)
end
return {
encrypt = encrypt,
decrypt = decrypt,
newRNG = newRNG,
}

View File

@ -64,13 +64,16 @@ function socketClass:ping()
end
function socketClass:setupEncryption(x)
local timer = Util.timer()
self.rrng = Crypto.newRNG(
SHA.pbkdf2(self.sharedKey, x and "3rseed" or "4sseed", 1))
self.wrng = Crypto.newRNG(
SHA.pbkdf2(self.sharedKey, x and "4sseed" or "3rseed", 1))
self.sharedKey = ECC.exchange(self.privKey, self.remotePubKey)
self.enckey = SHA.pbkdf2(self.sharedKey, "1enc", 1)
self.hmackey = SHA.pbkdf2(self.sharedKey, "2hmac", 1)
self.rseq = SHA.pbkdf2(self.sharedKey, x and "3rseed" or "4sseed", 1):toHex()
self.wseq = SHA.pbkdf2(self.sharedKey, x and "4sseed" or "3rseed", 1):toHex()
_syslog('shared in ' .. timer())
--self.enckey = SHA.pbkdf2(self.sharedKey, "1enc", 1)
--self.hmackey = SHA.pbkdf2(self.sharedKey, "2hmac", 1)
self.rseq = self.rrng:nextInt(5)
self.wseq = self.wrng:nextInt(5)
end
function socketClass:close()
@ -99,8 +102,6 @@ local function newSocket(isLoopback)
shost = os.getComputerID(),
sport = i,
transmit = device.wireless_modem.transmit,
wseq = math.random(100, 100000),
rseq = math.random(100, 100000),
timers = { },
messages = { },
}
@ -121,7 +122,7 @@ function Socket.connect(host, port, options)
if not device.wireless_modem then
return false, 'Wireless modem not found', 'NOMODEM'
end
local timer = Util.timer()
local socket = newSocket(host == os.getComputerID())
socket.dhost = tonumber(host)
socket.privKey, socket.pubKey = network.getKeyPair()
@ -143,7 +144,8 @@ local timer = Util.timer()
if e == 'modem_message' and
sport == socket.sport and
type(msg) == 'table' and
msg.dhost == socket.shost then
msg.dhost == socket.shost and
type(msg.pk) == 'string' then
os.cancelTimer(timerId)
@ -152,10 +154,7 @@ local timer = Util.timer()
socket.connected = true
socket.remotePubKey = Util.hexToByteArray(msg.pk)
socket:setupEncryption(true)
-- Logger.log('socket', 'connection established to %d %d->%d',
-- host, socket.sport, socket.dport)
network.getTransport().open(socket)
_syslog('connection in ' .. timer())
return socket
elseif msg.type == 'NOPASS' then
@ -181,24 +180,23 @@ local function trusted(socket, msg, options)
local identifier = options and options.identifier or getIdentifier()
if identifier and msg.t and type(msg.t) == 'table' then
if identifier and type(msg.t) == 'table' then
local data = Crypto.decrypt(msg.t, Util.hexToByteArray(identifier))
if data and data.ts and tonumber(data.ts) then
_G._syslog('time diff ' .. math.abs(os.epoch('utc') - data.ts))
if math.abs(os.epoch('utc') - data.ts) < 4096 then
socket.remotePubKey = Util.hexToByteArray(data.pk)
socket.privKey, socket.pubKey = network.getKeyPair()
socket:setupEncryption()
return true
end
_G._syslog('time diff ' .. math.abs(os.epoch('utc') - data.ts))
end
end
end
function Socket.server(port, options)
device.wireless_modem.open(port)
-- Logger.log('socket', 'Waiting for connections on port ' .. port)
while true do
local _, _, sport, dport, msg = os.pullEvent('modem_message')
@ -212,8 +210,6 @@ function Socket.server(port, options)
local socket = newSocket(msg.shost == os.getComputerID())
socket.dport = dport
socket.dhost = msg.shost
socket.wseq = msg.wseq
socket.rseq = msg.rseq
socket.options = options
if not Security.hasPassword() then
@ -233,8 +229,6 @@ function Socket.server(port, options)
pk = Util.byteArrayToHex(socket.pubKey),
})
-- Logger.log('socket', 'Connection established %d->%d', socket.sport, socket.dport)
network.getTransport().open(socket)
return socket