This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
The_King_JAZ's profile picture

I Made Another Bank

Started by The_King_JAZ, 31 January 2016 - 11:21 PM
The_King_JAZ #1
Posted 01 February 2016 - 12:21 AM
So over a year ago, I posted my first banking program which proved to be poorly made. It had several security issues and proved to be very confusing to read. This time, I hope I solved the second problem, and I know that I did better with making it more secure. This bank consists of three separate programs: an account setup program, a terminal, and the bank itself. The three programs are intended to be on separate computers for now, but I will work on combining the account setup and terminal programs in the future. The terminal is only used to send/receive information between the user and the bank. The bank (assumed to be hidden somewhere secure) is where balances are stored. There is still a banking card, like there was in the first program, but this time, it becomes more of an optional feature, being that one can use their account number and password to log in. This bank also features a GUI which is more organized than the last, more clickable than the last, and more customize-able than the last (because…why not?).

As fun as it sounds, it still has its issues:
- Only one client may be logged in at a time (otherwise the bank gets confused)
- If a client is logged into his/her account, a new account cannot be made
- Overriding the Bank program (assumed to be the Bank computer's startup program) can lead to security issues
- Terminal crashes when attempts are made to send money to the same account from which it was sent (i.e. account 000001 attempts to make a payment to account 000001)

NOTE: Make sure that the bank program is running before you attempt to log in with the Terminal. Otherwise, the terminal will soft-lock.

Please feel free to make changes and re-post the program, as long as you give me credit. Also, assistance is always welcome! If you find something else wrong with the program, or you fix one of the known issues listed above, please feel free to note it in a reply!

EDIT:
The following changes have been made:
- A bug in the Terminal program (terminal soft-locks when requesting balance) has been fixed.
- The Terminal now requires you to enter a password even when you enter a Bank Card associated with the account you are attempting to access.
- An Account Setup program is now available
- The Bank program has been edited to allow for Account Setup (Apparently, I had it set up for another program before, but I couldn't find that program)
- Password Encryption is now implemented

The programs can be found here:
ACCOUNT SETUP
TERMINAL
BANK
Edited on 04 February 2016 - 09:31 PM
Kronix #2
Posted 01 February 2016 - 01:05 AM

These pastes no longer exist.
Lupus590 #3
Posted 01 February 2016 - 08:13 AM
@OP did they have the expiry date set to never?
Edited on 01 February 2016 - 07:14 AM
The_King_JAZ #4
Posted 01 February 2016 - 04:29 PM
@OP did they have the expiry date set to never?

I reposted the programs on pastebin. I was using computer craft the first time (pastebin put (program name)), which might have been the problem. I updated my post last night and the links that are now there should work.
Edited on 01 February 2016 - 03:30 PM
Kronix #5
Posted 02 February 2016 - 01:39 AM
How would one go about registering an account? It doesn't appear obvious.
The_King_JAZ #6
Posted 02 February 2016 - 02:19 AM
How would one go about registering an account? It doesn't appear obvious.
Right. That's another thing I forgot to implement. So as of right now, there is no way to do that without going into the actual bank computer and creating a directory called "acc" with other directories in it, which would be the account numbers. Inside the accounts' directories would be files named "BALANCE" for holding the balance, "COLORS" for holding the desired color scheme, and "PASS" for storing the password. So for an account numbered 000001, the paths should be:

acc/000001/BALANCE
acc/000001/COLORS
acc/000001/PASS

I will definitely create another program that will make new accounts later on.

EDIT:
The BALANCE file should hold a number greater than or equal to 0, the COLORS file should hold a number equivalent to colors.x when x = one of the sixteen colors available to the advanced computers, and the PASS file should hold only the password. I should also put another file for storing a name and use that as yet another security feature (I don't know why I didn't because a name is required when manually logging in). I'd have to look at how the bank cards are set up, too, so that I can share that information as well. As soon as I get the account setup program written, I will share that as well.

Another edit:
I guess this program isn't very user friendly…xD I'll definitely have to work on that.
Edited on 02 February 2016 - 01:29 AM
The_King_JAZ #7
Posted 04 February 2016 - 06:10 AM
The Banking Cards are set up like so:
There is 1 file named "acc" with the path disk/acc/acc (I must have intended for there to be more than one file, but chose to only have one file in the directory). Inside this file, there are three lines, containing the following information:

Name
Account Number/Name
Password

This is so that one can log in to his/her account simply by putting his/her card in the terminal's disk drive.
I have planned a program to set up an account completely, including the files on both the Bank computer and the floppy disk. All I need to do now is implement it into the Bank program and test it out.
Creator #8
Posted 04 February 2016 - 08:00 AM
Maybe have the hash of the password on the disk, in order to protect it if anyone else manages to get his hands onto the disk.
Goof #9
Posted 04 February 2016 - 09:52 AM
Maybe have the hash of the password on the disk, in order to protect it if anyone else manages to get his hands onto the disk.
Or even better; Have a salted hash be saved to the disk. that'd prevent from rainbow lookup tables etc.
The_King_JAZ #10
Posted 04 February 2016 - 05:51 PM
Maybe have the hash of the password on the disk, in order to protect it if anyone else manages to get his hands onto the disk.
Or even better; Have a salted hash be saved to the disk. that'd prevent from rainbow lookup tables etc.

How exactly would I implement a hash or a salted hash of passwords? And I think I would probably store the password on the bank computer itself, rather than the disk. I would then change the Terminal program to still require a password for logging in to the account with a banking card. But the thing is, I would have to 1) hash the password before storing it on the Bank computer, and 2) hash the password before broadcasting it from the Terminal to the Bank. How would I do this? (I'm not very good with this kind of stuff, if you can't already tell…more of a learning experience for me, really)
Edited on 04 February 2016 - 05:13 PM
Lupus590 #11
Posted 04 February 2016 - 07:00 PM
Maybe have the hash of the password on the disk, in order to protect it if anyone else manages to get his hands onto the disk.
Or even better; Have a salted hash be saved to the disk. that'd prevent from rainbow lookup tables etc.

How exactly would I implement a hash or a salted hash of passwords? And I think I would probably store the password on the bank computer itself, rather than the disk. I would then change the Terminal program to still require a password for logging in to the account with a banking card. But the thing is, I would have to 1) hash the password before storing it on the Bank computer, and 2) hash the password before broadcasting it from the Terminal to the Bank. How would I do this? (I'm not very good with this kind of stuff, if you can't already tell…more of a learning experience for me, really)

there are some encryption APIs on the forums, do a search
Goof #12
Posted 04 February 2016 - 07:26 PM
Maybe have the hash of the password on the disk, in order to protect it if anyone else manages to get his hands onto the disk.
Or even better; Have a salted hash be saved to the disk. that'd prevent from rainbow lookup tables etc.

How exactly would I implement a hash or a salted hash of passwords? And I think I would probably store the password on the bank computer itself, rather than the disk. I would then change the Terminal program to still require a password for logging in to the account with a banking card. But the thing is, I would have to 1) hash the password before storing it on the Bank computer, and 2) hash the password before broadcasting it from the Terminal to the Bank. How would I do this? (I'm not very good with this kind of stuff, if you can't already tell…more of a learning experience for me, really)
Well. To hash something in cc, it'd prefer the sha256 API in the pure lua topic-link.
Salting, if you do not know what the hash+salt is, go check it up on here(wiki)

When around with that, for storing the passwords you do the following process

Client: (with disk database)
sha256 the password read with a random generated SALT string.
transmit the hashed string and save the salt somewhere near the hash output.

Example (disk):
SpoilerCreating an account

-- put the sha256 code here. (Wont work with os.loadAPI)

local x="abcdefghijklmnopqrstuwvxyz1234567890/*-+.,_;:"
local function randomsalt( len )
	local str = ""
	len = len or 128
	for c = 1, len do
		local d = math.random(1,x:len())
		str = str .. x:sub(d,d)
	end
	return str
end

local random_salt = randomsalt( 128 ) --# Generate a salt of 128 characters (length)
print("New account")
write("account name:" )
local user = read()
write("account password:" )
local input = sha256.sha256(read("*") .. random_salt)

--# save the data (disk)
local handle = fs.open( "/disk/accounts/"..user, "w" )
handle.writeLine( input ) --# Hashed password here
handle.writeLine( random_salt ) --# Salt here
handle.close() --# Remember to close the handle

Logging in on a previous account

-- put the sha256 code here. (Wont work with os.loadAPI)

print("Login to account")
write("account name:" )
local user = read()
--# gather the salt from this user
local hash, salt
for k, v in pairs( fs.list("/disk/accounts/") ) do --# go through all accounts
    if v == user then --# if the account name matches the input then
        local x = fs.open( "/disk/accounts/" .. v, "r" )
        hash, salt = x.readLine(), x.readLine() --# get the data
        x.close()
    end
end
if not hash then
    print("Username invalid")
    return
end

write("account password:" )
local input = sha256.sha256(read("*") .. salt) --# add the known salt to the hash
if input == hash then --# validate hashes
    print("logged in")
else
    print("invalid") --# invalid hash
end

However there are other methods of doing this.


If you were to do the accounts on the bank computer (i guess this is the server database)
you could let clients lookup for a username, then let the bank return the SALT for that specific account ID.

The client then types a passphrase and hashes it with the salt received from the bank server.
That hash is then transferred to the bank server for validation.
In this case the bank can respond with "Valid" or "Invalid", or some other stuff, to identify correct and incorrect credentials.

I hope this explains some of your questions!
Feel free to ask if you have more. :)/>/>/> (Preferably in a PM)
Edited on 04 February 2016 - 07:11 PM
The_King_JAZ #13
Posted 04 February 2016 - 07:49 PM
I have edited the Terminal and Bank programs and also created an Account Setup program. The changes I have made and the links to the new versions of the programs and the link to the Account Setup program have been edited into the first post. I still haven't made any changes regarding passwords, aside from requiring the user to enter their password even when they've inserted their card.
Edited on 04 February 2016 - 06:50 PM
The_King_JAZ #14
Posted 04 February 2016 - 07:57 PM
I hope this explains some of your questions!

It does, thank you. I will mess with it for a bit and come to you with any questions that arise. :)/>
The_King_JAZ #15
Posted 04 February 2016 - 08:32 PM
Okay, so I messed around with it a little. Please correct me if I'm wrong. I'm just trying to understand how this works.

- Does the random salt help to further encrypt the password (being that I use "sha256(read("*")..random_salt)" )?
- And if so, is that why the random salt is required when I load it up again (using sha256(password..random_salt) to encrypt the password the same way it was when it was first entered)?
- And so I never truly decrypt the password, I just encrypt the password again under the same circumstances and match the two encryptions of the same password.

Correct?
Goof #16
Posted 04 February 2016 - 09:05 PM
Okay, so I messed around with it a little. Please correct me if I'm wrong. I'm just trying to understand how this works.

- Does the random salt help to further encrypt the password (being that I use "sha256(read("*")..random_salt)" )?
- And if so, is that why the random salt is required when I load it up again (using sha256(password..random_salt) to encrypt the password the same way it was when it was first entered)?
- And so I never truly decrypt the password, I just encrypt the password again under the same circumstances and match the two encryptions of the same password.

Correct?
All of those statements are correct.

The salt adds an extra layer to the original passwords, which means that you won't be able to look up the hash 03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4 on the web and get the result instant (1234)

So yes, you're correct.
The_King_JAZ #17
Posted 04 February 2016 - 10:40 PM
I believe I have successfully implemented password encryption. I have edited the first post to provide links to the new programs. It's coming together, guys! I am also thinking about making an Advanced Wireless Pocket Computer program that can act as a terminal and account setup program. For now, though, I need to figure out how to allow the Bank to communicate with more than one Terminal or Account Setup computer at a time.
Lupus590 #18
Posted 04 February 2016 - 11:13 PM
I need to figure out how to allow the Bank to communicate with more than one Terminal or Account Setup computer at a time.

Have the server give the client a token when it logs in, future transactions from the client then are prefixed with the token so that it can be identified.

You will have to encrypted the client server connection.
Edited on 04 February 2016 - 10:14 PM
The_King_JAZ #19
Posted 05 February 2016 - 01:35 AM
Have the server give the client a token when it logs in, future transactions from the client then are prefixed with the token so that it can be identified.

How exactly do you propose that I do this? I can think of a few ways in my head that I could potentially have this work, but I'd have to test them out…

You will have to encrypted the client server connection.

I figured as much. It shouldn't be difficult now that I understand how to use sha256.
Lupus590 #20
Posted 05 February 2016 - 10:26 AM
a token is something which is unique to the client and the session which can identify the user.

I'm not familiar with how it works (so someone correct me if I'm wrong)but you can do a similar thing that you would for hashing and salting passwords. Except use the username instead of the password and salt with the time that the session started. The server should store when the session started as request the user to re-log-in if the session seams stale (I.E. the client stopped communicating the the server, probably meaning that the user is away)
Goof #21
Posted 05 February 2016 - 03:15 PM
Have the server give the client a token when it logs in, future transactions from the client then are prefixed with the token so that it can be identified.

How exactly do you propose that I do this? I can think of a few ways in my head that I could potentially have this work, but I'd have to test them out…

You will have to encrypted the client server connection.

I figured as much. It shouldn't be difficult now that I understand how to use sha256.
a token is something which is unique to the client and the session which can identify the user.

I'm not familiar with how it works (so someone correct me if I'm wrong)but you can do a similar thing that you would for hashing and salting passwords. Except use the username instead of the password and salt with the time that the session started. The server should store when the session started as request the user to re-log-in if the session seams stale (I.E. the client stopped communicating the the server, probably meaning that the user is away)
Well. first of all. We need to understand what everything does and is.
Lets say the following scenario:
We have the bank server listening for "PING"'s from clients around the world.
In response the bank server calculates a unique string (I would prefer getting the real world time, and hashing that with some salt)
the response would be as follows: (sending a serialized table)

{
  auth_token = "[color=#000000]1af3464cb7ef46b2bc380183c87aabe5f780293bb747a0c28f96788d8ce97e93a32463df2fd324daf2ffae27f28bc8c1b078986112dbd2dddaf48e5f7ab7fa1c",[/color]
  expires = 500, --# seconds
}
this token is actually a sha512 hash of the current real time and salt. (sha512 is not possible in cc, yet)

The client gets this message and responds corresponding to this new token, which expires in 500 seconds, if no actions has been made.
(like an auto-logoff if you do not respond)

The bank server stores this token in a database, which links to a client. When the token expires, this database index would be removed, and the client no longer has a valid authentication to do anything. (Unless a new token is generated)



Now to the encryption part
When you send data through modem messages it's "most" secure to encrypt it. AES allows to decrypt and encrypt a string, which is what we want in the scenario to communicate between the client and server.
Lets use AES and encode the output with base64. (to allow transferring the encoded data)
AES accepts two arguments. The password and the string to be encrypted.
However it is really insecure to have a hardcoded password for the encrypted messages.
(Maybe use something with key exchanges to privately calculate a string and let that be the password)


Give it a try and tell us if you dont/do get it to work :rolleyes:/>
And if I wasn't clear enough, please tell me ;)/>
The_King_JAZ #22
Posted 05 February 2016 - 10:44 PM
I have a few questions:

1. How would I communicate with computers around the Minecraft world? I believe that there is a limitation on how far wireless rednet can reach.
2. How would I go about getting the real-world time? I only know how to get the Minecraft time from the CC computers.
3. Would I keep the current implementations of sha256 in my Terminal and Account Setup programs? Or would it be replaced by AES? And if it would be, what is the difference between AES and sha256?
4. Finally, what does base64 do? Is it another salt generator (looking at the code, I could tell that it looked similar to the one you helped me out with yesterday, so I assumed it was)? If it is, I'm assuming I would replace my current salt generator with this new one (since it does appear more advanced, as it uses more characters than the one I currently use)?

I guess I don't really understand this whole thing (but I'm not ready to give up!). I am a beginner when it comes to programming; I've only been doing this since March of 2014, and, aside from what I've learned here and from the basic descriptions of the different APIs in CC, I'm mostly self-taught, using trial and error to teach myself. So, for the most part, I don't really understand much when it comes to programming. :/
Lupus590 #23
Posted 05 February 2016 - 11:14 PM
I'll answer what I can and leave the other questions to those who know better than I do:
1: if you are running computercraft 1.6 or later and your comunications are via rednet, then set up a bunch of computers around the world and have them run the repeat program
2: there is an API on the forums which uses the HTTP API to pull the time of a web server: http://www.computercraft.info/forums2/index.php?/topic/25193-get-real-time-in-cc/
KingofGamesYami #24
Posted 05 February 2016 - 11:22 PM
3. sha256 is a hash, which means you cannot reverse it to get the original text. AES is an encryption algorithm; you can reverse it if you have the 'key'.

Example of sha

local hash = "0f2389ufawn2f9p2hf3p9h" --#not an actual hash, just keyboard mashing
if hash == sha256( read() ) then
  print( "You input the correct password!" )
else
  print( "You input the wrong password!" )
end

Example of AES

local key = "unbreakable"
rednet.broadcast( AES.encrypt( read(), key ) )


local key = "unbreakable"
local id, msg = rednet.receive()
print( AES.decrypt( msg, key ) )

**Warning! I have not actually made sure any of the example are actually viable. They are just for demonstration!!**

4. base64 converts text into a series of 64 characters. You could call binary base2, if you wanted.
Edited on 05 February 2016 - 10:34 PM
Creator #25
Posted 06 February 2016 - 03:50 PM
I have developed a small Diffie Hellman algorithm, which allows two parties to exchange a key. I could let you use it if you want.
Edited on 06 February 2016 - 02:51 PM
The_King_JAZ #26
Posted 06 February 2016 - 06:45 PM
Sure! I'll just have to figure out how it's used before I start using it with my bank.
Creator #27
Posted 06 February 2016 - 08:13 PM
It is very simple: DH.connect(AwrappedModem,AChannel)

One issue I am having is the numbers. Lua only supports relatively small numbers, so I will have to look into a BigNum library, to make the shared secret secure.
Creator #28
Posted 08 February 2016 - 05:09 PM
Found BigNum. The framework works fine. Will probably work some more on it, but the main part is ready.

To try it, run this:

pastebin run 33PCDPv7 Tunnel

To load it, attach this code in the beginning:


dofile = function(path,...)
local f = loadfile(path)
setfenv(f,_G)
return f(...)
end
local Tunnel = dofile("Tunnel/init.lua","Tunnel")

To establish a secure connection, run


local Key = Tunnel.DH.connect(modem,channel)

on both computers simultaneously.

You can then

AESKey = Tunnel.SHA.sha256(tostring(Key))

to get the key you will be using for


Cyphertext = Tunnel.AES.encryptBytes(AESKey,text)

I added the function encryptBytes so that you send a table, since strings get altered when the char is over 127.

Cyphertext is actually cyphertable.
Edited on 08 February 2016 - 04:13 PM