From ab73e3f2f9e4155596007b317e750c3eb250d8d2 Mon Sep 17 00:00:00 2001 From: "kepler155c@gmail.com" Date: Fri, 5 May 2017 21:43:17 -0400 Subject: [PATCH] security start --- apps/trust.lua | 14 ++-- sys/apis/crypto.lua | 151 ++++++++++++++++++++++++++++++++++++++++++ sys/apis/socket.lua | 7 +- sys/apis/terminal.lua | 15 +++++ sys/extensions/os.lua | 5 ++ sys/network/trust.lua | 21 ++++-- 6 files changed, 199 insertions(+), 14 deletions(-) create mode 100644 sys/apis/crypto.lua diff --git a/apps/trust.lua b/apps/trust.lua index 1ad04c7..c04e7d3 100644 --- a/apps/trust.lua +++ b/apps/trust.lua @@ -1,6 +1,8 @@ require = requireInjector(getfenv(1)) local Socket = require('socket') local SHA1 = require('sha1') +local Terminal = require('terminal') +local Crypto = require('crypto') local remoteId local args = { ... } @@ -21,7 +23,11 @@ if not remoteId then end print('Password') -local password = read() +local password = Terminal.readPassword('Enter password: ') + +if not password then + error('Invalid password') +end print('connecting...') local socket = Socket.connect(remoteId, 19) @@ -45,11 +51,9 @@ end local secretKey = os.getSecretKey() local publicKey = modexp(exchange.base, secretKey, exchange.primeMod) +local password = SHA1.sha1(password) -socket:write({ - password = SHA1.sha1(password), - publicKey = publicKey, -}) +socket:write(Crypto.encrypt({ pk = publicKey }, password)) print(socket:read(2) or 'No response') diff --git a/sys/apis/crypto.lua b/sys/apis/crypto.lua new file mode 100644 index 0000000..34c3bf6 --- /dev/null +++ b/sys/apis/crypto.lua @@ -0,0 +1,151 @@ +-- https://github.com/PixelToast/ComputerCraft/blob/master/apis/enc + +local Crypto = { } + +local function serialize(t) + local sType = type(t) + if sType == "table" then + local lstcnt=0 + for k,v in pairs(t) do + lstcnt = lstcnt + 1 + end + local result = "{" + local aset=1 + for k,v in pairs(t) do + if k==aset then + result = result..serialize(v).."," + aset=aset+1 + else + result = result..("["..serialize(k).."]="..serialize(v)..",") + end + end + result = result.."}" + return result + elseif sType == "string" then + return string.format("%q",t) + elseif sType == "number" or sType == "boolean" or sType == "nil" then + return tostring(t) + elseif sType == "function" then + local status,data=pcall(string.dump,t) + if status then + data2="" + for char in string.gmatch(data,".") do + data2=data2..zfill(string.byte(char)) + end + return 'f("'..data2..'")' + else + error("Invalid function: "..data) + end + else + error("Could not serialize type "..sType..".") + end +end + +local function unserialize( s ) + local func, e = loadstring( "return "..s, "serialize" ) + if not func then + return s,e + else + setfenv( func, { + f=function(S) + return loadstring(splitnum(S)) + end, + }) + return func() + end +end + +local function sure(N,n) + if (l2-n)<1 then N="0" end + return N +end + +local function splitnum(S) + Out="" + for l1=1,#S,2 do + l2=(#S-l1)+1 + CNum=tonumber("0x"..sure(string.sub(S,l2-1,l2-1),1) .. sure(string.sub(S,l2,l2),0)) + Out=string.char(CNum)..Out + end + return Out +end + +local function zfill(N) + N=string.format("%X",N) + Zs="" + if #N==1 then + Zs="0" + end + return Zs..N +end + +local function wrap(N) + return N-(math.floor(N/256)*256) +end + +local function checksum(S) + local sum=0 + for char in string.gmatch(S,".") do + math.randomseed(string.byte(char)+sum) + sum=sum+math.random(0,9999) + end + math.randomseed(sum) + return sum +end + +local function genkey(len,psw) + checksum(psw) + local key={} + local tKeys={} + for l1=1,len do + local num=math.random(1,len) + while tKeys[num] do + num=math.random(1,len) + end + tKeys[num]=true + key[l1]={num,math.random(0,255)} + end + return key +end + +function Crypto.encrypt(data,psw) + data=serialize(data) + local chs=checksum(data) + local key=genkey(#data,psw) + local out={} + local cnt=1 + for char in string.gmatch(data,".") do + table.insert(out,key[cnt][1],zfill(wrap(string.byte(char)+key[cnt][2])),chars) + cnt=cnt+1 + end + return string.sub(serialize({chs,table.concat(out)}),2,-3) +end + +function Crypto.decrypt(data,psw) + local oData=data + data=unserialize("{"..data.."}") + if type(data)~="table" then + return oData + end + local chs=data[1] + data=data[2] + local key=genkey((#data)/2,psw) + local sKey={} + for k,v in pairs(key) do + sKey[v[1]]={k,v[2]} + end + local str=splitnum(data) + local cnt=1 + local out={} + for char in string.gmatch(str,".") do + table.insert(out,sKey[cnt][1],string.char(wrap(string.byte(char)-sKey[cnt][2]))) + cnt=cnt+1 + end + out=table.concat(out) + if checksum(out or "")==chs then + return unserialize(out) + end + return oData,out,chs +end + +return Crypto diff --git a/sys/apis/socket.lua b/sys/apis/socket.lua index 0f26df7..27fbfe9 100644 --- a/sys/apis/socket.lua +++ b/sys/apis/socket.lua @@ -1,4 +1,5 @@ local Logger = require('logger') +local Crypto = require('crypto') local socketClass = { } @@ -168,7 +169,7 @@ function Socket.connect(host, port) type = 'OPEN', shost = socket.shost, dhost = socket.dhost, - sharedKey = exchange.publicKey, + t = Crypto.encrypt({ ts = os.time() }, exchange.publicKey), }) local timerId = os.startTimer(3) @@ -206,8 +207,10 @@ function trusted(msg, port) local pubKey = trustList[msg.shost] if pubKey then + local data = Crypto.decrypt(msg.t or '', pubKey) + --local sharedKey = modexp(pubKey, exchange.secretKey, public.primeMod) - return pubKey == msg.sharedKey + return data.ts and tonumber(data.ts) and math.abs(os.time() - data.ts) < 1 end end diff --git a/sys/apis/terminal.lua b/sys/apis/terminal.lua index ab6bae5..234b559 100644 --- a/sys/apis/terminal.lua +++ b/sys/apis/terminal.lua @@ -150,4 +150,19 @@ function Terminal.mirror(ct, dt) end end +function Terminal.readPassword(prompt) + if prompt then + term.write(prompt) + end + local fn = term.write + term.write = function() end + local s = read(prompt) + term.write = fn + + if s == '' then + return + end + return s +end + return Terminal diff --git a/sys/extensions/os.lua b/sys/extensions/os.lua index ccb7775..2a076bf 100644 --- a/sys/extensions/os.lua +++ b/sys/extensions/os.lua @@ -67,6 +67,11 @@ function os.getSecretKey() return Util.readFile('.secret') end +function os.getPassword() + Config.load('os', config) + return config.password +end + os.lock = function() --os.locked = true diff --git a/sys/network/trust.lua b/sys/network/trust.lua index 08142a5..282b56f 100644 --- a/sys/network/trust.lua +++ b/sys/network/trust.lua @@ -1,5 +1,6 @@ local Socket = require('socket') local process = require('process') +local Crypto = require('crypto') process:newThread('trust_server', function() @@ -11,14 +12,20 @@ process:newThread('trust_server', function() local data = socket:read(2) if data then - if os.verifyPassword(data.password) then - local trustList = Util.readTable('.known_hosts') or { } - trustList[socket.dhost] = data.publicKey - Util.writeTable('.known_hosts', trustList) - - socket:write('Trust accepted') + local password = os.getPassword() + if not password then + socket:write('No password has been set') else - socket:write('Invalid password or password is not set') + data = Crypto.decrypt(data, password) + if data and data.pk then + local trustList = Util.readTable('.known_hosts') or { } + trustList[socket.dhost] = data.pk + Util.writeTable('.known_hosts', trustList) + + socket:write('Trust accepted') + else + socket:write('Invalid password or password is not set') + end end end socket:close()