First thing we need to talk about is hashing. Hashing is taking a string, putting it through an algorithm, and making it into a string of jumbled letters and numbers. For this example, we're going to use SHA, the Secure Hashing Algorithm. We're going to use the adaptation found here. SHA, for example, will take "Hello!" and turn it into "334d016f755cd6dc58c53a86e183882f8ec14f52fb05345887c8a5edd42c87b7".
So, another problem arises is that if someone gets into your password store, if people have the same password, their hashes are going to be the same. Since the algorithm is just math, it's going to produce the same output every time you put in the same string. So how do we combat this? Salting. Salting ensures that each users' hash is different, so that way it's almost impossible to get the password from the hash.
So, here's what we need:
- ComputerCraft Computer
- SHA API (I saved mine to the file "/sha")
- Time and patience
Here's how we start our program:
os.loadAPI("sha")
local passPath = "passwords" --Change this if you want a different password file
if not fs.exists(passPath) then --Create a password file
local f = fs.open(passPath, "w")
f.write(textutils.serialize({}))
f.close()
end
This first code block makes a password file if not given yet. Now we need to make sure that we have a secure input, meaning the user cannot terminate it. I tend to write my own, so I'll include it here. If I remember correctly, you can securely use the read() function if you set os.pullEvent to os.pullEventRaw before the read function.os.loadAPI("sha")
local passPath = "passwords" --Change this if you want a different password file
if not fs.exists(passPath) then --Create a password file
local f = fs.open(passPath, "w")
f.write(textutils.serialize({}))
f.close()
end
local function secureInput( mask, prestring )
local l = true
term.setCursorBlink(true)
local prestring = prestring or ""
local str = ""
local sx, sy = term.getCursorPos()
while l do
local e, a, b, c, d = os.pullEventRaw()
if e == "char" then
str = str .. a
elseif e == "key" then
if a == 14 then
str = str:sub(1, -2)
elseif a == 28 then
l = false
term.setBackgroundColour( colours.black )
term.setTextColour( colours.white )
print()
return str
end
end
term.setCursorPos(sx, sy)
term.setBackgroundColour( colours.white )
term.setTextColour( colours.black )
term.clearLine()
if mask then
write( prestring .. " > " .. string.rep(mask, #str) )
else
write( prestring .. " > " .. str )
end
end
end
I'm going to write this code in API form, so that way, you can use this in scripts other than login scripts.
Final code:
Brief explanation on how this works:
User enters username and password -> program checks to see if user even exists -> if so, it takes the salt, appends it to the end of what the user entered, and check to see if that equals the password.
Why the salt? As previously stated, it prevents two hashes being the same. So we add a salt to the password upon creation (see the script below) so that they do not have remotely similar hashes.
Before we can test, we need to make users. Here's a quick user maker I whipped up:
os.loadAPI("sha")
write("username :: ")
local u = read()
write("password :: ")
local p = read()
--Again, change passPath here
local passPath = "passwords"
local f = fs.open(passPath,"r")
local usrs = textutils.unserialize(f.readAll())
f.close()
if not usrs[u] then
local salt = os.time()
usrs[u] = {
pwd = sha.sha256( p .. salt ),
salt = salt,
}
local f = fs.open(passPath, "w")
f.write( textutils.serialize( usrs ) )
f.close()
end
As you can see, upon creation, passwords are salted using the os.time(). The salt can be anything, as long as its unique. Though technically in theory os.time() could be similar, it's quite unlikely that there'll be a collision, so it's good enough for now.Run that script a couple times, make the users, and see your passwords file. It should look something like this:
Try the login script!

In that gif, both users Eric and tutorials have the same password, but have different hashes. That way, a potential intruder won't know their passwords are the same!
Hopefully, this helped someone. If I need to revise something, let me know!
Edited by CompuTech, 31 August 2016 - 06:54 PM.













