security start

This commit is contained in:
kepler155c@gmail.com 2017-05-05 21:43:17 -04:00
parent bc5cc5e97b
commit ab73e3f2f9
6 changed files with 199 additions and 14 deletions

View File

@ -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')

151
sys/apis/crypto.lua Normal file
View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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()