Author Topic: Event_Keypad - Create Keypads with Secure Passwords!  (Read 2216 times)


Keypad Events

Ever use events to create a password for a puzzle or secure door, only for some scoundrel to just save the build, read the events on their own server, and come back ready to dig through all your secret rooms? Most of you probably haven't even done that, because just rigging up the keypad with default events is a pain. Well, here to solve all your problems* is Event_Keypad!


Events:

This add-on provides two input and two output events, intended to all be used in building a keypad:

  • fxDTSBrick::keypadInputChar - Output - Takes a single character, and adds it to the client's input text. Works with any Torque supported character, and is case sensitive.
  • fxDTSBrick::keypadTest - Output - Checks the client's input against a hash and calls the appropriate input event on this brick. See below for more details. Leaving the hash blank will instead clear the client's input text.
  • fxDTSBrick::onKeypadCorrect and fxDTSBrick::onKeypadIncorrect - Inputs - Called by keypadTest depending on whether or not the client's input was correct.


About Hashes and Salts:

To keep passwords secret, the actual passwords are not kept by the events. Otherwise, someone could just load the build on their own server, wrench the brick, and read the password. However, you still want to be able to save and load the bricks yourself without losing all your passwords. Hashing provides the solution. A hash function takes some text, and converts it into different text in a way that cannot be reversed, and that the same input will always produce the same output. So we choose a password for our keypad, hash it, and what comes out is some unholy combination of numbers and letters. We make that the parameter for our keypadTest event. Then when someone enters their code and hits the test button, we use the same hash function on their input. If the resulting string of numbers and letters is the same, then the event knows that they have the right password, even though the event never actually knows what the password is.

But there's still a problem. If someone wrenches your brick and finds out your password's hash, and they know what hash function the add-on uses, they can run a script to quickly make thousands of guesses, hashing them, and checking them against your hash. A 4 digit numerical code can be broken in an instant. This is resolved by introducing a salt string. A salt string is a bit of secret text gets added to the input when the hash function is run. The salt is unique for each server, and can be viewed and set by super admins. By keeping the salt secret from regular users, the only way they'll be able to make guesses is by using the events on the server. It acts as a sort of master password, keeping the individual event passwords secure. It also means that by using the same salt, a save with keypad events can be transferred to other trusted users. As a consequence however, if you change a server's salt string, all existing keypad events set using the old salt will be invalidated.

There's a lot to the subject of securely storing passwords, and this is by no means a comprehensive summary. Fortunately, there are a bunch of commands that simplify this process for the scope of this add-on.


Server Commands:
  • /setBrickPassword [password] - Sets the value of the keypadTest event on the brick you're looking at. Must be holding a wrench, must have access to the brick's wrench events, and the brick must have exactly one keypadTest output event enabled.
  • /setKeypadSalt [salt] - Super Admin only. Sets the server's salt string, which is used in the hash function for every brick password.
  • /keypadSaltHelp - Displays a summary of how salt strings work, similar to the above paragraph. Super Admins should educate themselves with this before meddling with the server's salt string.


Using Keypad Events:

Didn't read any of the above and have no idea what you're doing? We got you covered! Here's the fast version.

For server hosts:
First, install and enable the mod. When you start the server, type "/setKeypadSalt abc123", substituting in a unique password. This password will be visible to your super admins. If you ever load your keypads on a different server, or if your server preferences ever get cleared, you will have to use the same keypad salt when you enter the command again. If you lose your keypad salt, all keypad test events in your build will have to be manually reset.

To build a keypad:
To build your keypad, you can start by creating a bunch of buttons with prints on them, using "onActivate->Self->keypadInputChar->X" where X is the brick's letter or number. You can also add events for any effects or sounds you want the button to have when you press it. Optionally, add a clear button that has the event "onActivate->Self->keypadTest->[empty string]". Then, set up an enter button with "onActivate->Self->keypadTest->[hash]", plus further onKeypadCorrect and onKeypadIncorrect events. Finally, fill in the "hash" portion of the keypadTest event by looking at the enter button, equipping a wrench, and typing in "/setBrickPassword 321password", substituting in your brick's password. You can then test your keypad by typing in the password on it, and pressing the enter button.


Example Save:

Included here is a save file with a simple keypad built on it. As you'll recall from above, the only way to use keypad events from a save is to have the same salt string as the server it was created with. In this case, you'll need to use "/setKeypadSalt cat" for the example to work. Setting the salt to anything else will invalidate the events, and if you did not know that "cat" was the salt I used to create this keypad, you would not be able to use this keypad on your own server. Once you've set the salt correctly, the code to the keypad is "1234".

Download Example Save


In Conclusion:

I believe that covers everything important. If you forget anything, the error messages should be detailed enough to explain what you did wrong. Special thanks goes to Ipquarx, for providing security advice. Additional thanks goes to Pecon, for hosting the test server for these events over the last 4 years.

*Will not actually solve all your problems, only the two described here.


so.... what was the password???



This is good an all, but why don't you make a salt for each keypad that is generated only for that hash? Most companies uses a unique salt for each user password. You are already storing the salt checksum, so storing the salt shouldn't be an issue.

Yes, I am well aware that knowing the salt makes it possible for attacks as well, but they still need to check all possibilities with the salt anyway, so why make it more complicated?

so.... what was the password???
No clue. Forgot it years ago and other people probably changed them a few times.

This is good an all, but why don't you make a salt for each keypad that is generated only for that hash? Most companies uses a unique salt for each user password. You are already storing the salt checksum, so storing the salt shouldn't be an issue.

Yes, I am well aware that knowing the salt makes it possible for attacks as well, but they still need to check all possibilities with the salt anyway, so why make it more complicated?
The point of making the salt unique and secret for the server was so that end users do not know the full hashing algorithm, making it much harder to brute force any hash, regardless of how complex the code is. Storing the salt with the brick would defeat the purpose of that. While it would make it difficult to brute force hashes as a batch (like you would if you were given a password database), it wouldn't allow the same level of security for individual ones. Using a secret server-wide salt means that those who don't know it will struggle to reverse engineer even a 4 digit numerical code.

I considered mixing the transform of the brick during the hashing stage, which would complicate brute forcing of batches. It would also resolve the possibility of an in-server brute force by building a event contraption that tries incrementing numbers against the hash taken from a numerical keypad. However, it would mean you have to reset your passwords if you move your keypad with a duplicator or something. That's one of a couple points where a bit of security was traded for usability. I did however leave the brick as a parameter to the add-on's hashing function, so if anyone feels like overwriting it, it's fairly straightforward to do so.

No clue. Forgot it years ago and other people probably changed them a few times.
The point of making the salt unique and secret for the server was so that end users do not know the full hashing algorithm, making it much harder to brute force any hash, regardless of how complex the code is. Storing the salt with the brick would defeat the purpose of that. While it would make it difficult to brute force hashes as a batch (like you would if you were given a password database), it wouldn't allow the same level of security for individual ones. Using a secret server-wide salt means that those who don't know it will struggle to reverse engineer even a 4 digit numerical code.

I considered mixing the transform of the brick during the hashing stage, which would complicate brute forcing of batches. It would also resolve the possibility of an in-server brute force by building a event contraption that tries incrementing numbers against the hash taken from a numerical keypad. However, it would mean you have to reset your passwords if you move your keypad with a duplicator or something. That's one of a couple points where a bit of security was traded for usability. I did however leave the brick as a parameter to the add-on's hashing function, so if anyone feels like overwriting it, it's fairly straightforward to do so.

I can see your point, and I understood that it was something like that. However, would you consider making so you store first the checksum and the password hash as you currently do, but also add an another salt that is visible, but locked to the password? Why I want to have different hash per password is to reduce the possibility to have two hashes looking the same because two bricks really got the same password.

I can see your point, and I understood that it was something like that. However, would you consider making so you store first the checksum and the password hash as you currently do, but also add an another salt that is visible, but locked to the password? Why I want to have different hash per password is to reduce the possibility to have two hashes looking the same because two bricks really got the same password.
Hmm. It should be possible to do without causing too many problems, and without even breaking existing uses of the mod. Though I'm kinda terrified at the prospect of explaining how the mod works after adding in a second salt string. It's already more complicated than I'd like for an add-on of its size. I'll put it in the "maybe" column.

Though I'm kinda terrified at the prospect of explaining how the mod works after adding in a second salt string.
i agree probably getting too complicated

I can see your point, and I understood that it was something like that. However, would you consider making so you store first the checksum and the password hash as you currently do, but also add an another salt that is visible, but locked to the password? Why I want to have different hash per password is to reduce the possibility to have two hashes looking the same because two bricks really got the same password.
even if pass is same people wouldnt be able to figure it out so it should be okay - given the way this works it probably only saves the hash if the host saves it, unless it converts the password into an event line saved into the brick

even if pass is same people wouldnt be able to figure it out so it should be okay - given the way this works it probably only saves the hash if the host saves it, unless it converts the password into an event line saved into the brick

People download the save and discovers the hash. It then bruteforces on the server that had the hash with their own event until they find a match. It's no harder than that and could easily be made with a script for automation.

Once when I used the same salt on a database I found out that a test account I made had the same hash as an another account. That's because they had the same password. I could write a documentation if you really think it's tedious explaining it.

People download the save and discovers the hash. It then bruteforces on the server that had the hash with their own event until they find a match. It's no harder than that and could easily be made with a script for automation.

Once when I used the same salt on a database I found out that a test account I made had the same hash as an another account. That's because they had the same password. I could write a documentation if you really think it's tedious explaining it.
no i totally understand your logic but do you /really/ need this level of security on a server? a serversided salt is already enough imo honestly - trying to reverse engineer the salt isnt efficient, esp with how long or short it can be

no i totally understand your logic but do you /really/ need this level of security on a server? a serversided salt is already enough imo honestly - trying to reverse engineer the salt isnt efficient, esp with how long or short it can be

This is a password we're talking about. When people hear password and hashing they mostly think that it's the safest thing in the world and therefore reuses their password as they think it's the safest thing in the world. Some even go so long that they use a basic password, like 123456(Which is the most used password!), ignoring the fact that if others uses it, then the whole thing is compromised.

Yes, of course, there's nothing to secure really. Other measures could be made to ensure the safety of peoples houses. But for this one I can guarantee that at least one will loose their password this way because they're so naive for either reusing their password or using the most used password of all time. Never underestimate how either smart some people are, or how big of an idiot others are. It's better to be safe than sorry.

But I wont push this any further. I just wanted to get out my 2 cents on this as I call it a security concern worth noting.

People download the save and discovers the hash. It then bruteforces on the server that had the hash with their own event until they find a match. It's no harder than that and could easily be made with a script for automation.
That would still be possible if the individual events' salts could be edited. Maybe I misunderstood your proposal? Being able to duplicate keypads within a server is by design.

I'm not too worried about anyone using a password for a Blockland build that they use for something more important. Brute forcing within a server will be a very slow process. It's feasible with 3 or 4 digit passwords, but for an alphanumeric code, it'll become much harder. Besides that, anyone who is going around typing their important passwords into Blockland servers is already a huge security liability to themselves. I could possibly take some measures that might save one or two of them from false confidence, but this add-on already spouts enough walls of text, and I'm willing to gamble that the few who do make that mistake don't stand to lose much.
« Last Edit: November 15, 2017, 02:22:55 PM by -Jetz- »

I read through you "wall-o-text" now and found out an misunderstanding of why a salt is used. Instead of explaining it with my broken english, I'll hand you a link to wikipedia to brief you about the topic:

Salt (cryptography)

tl;dr: Salt is to tackle the issue with rainbow-tables(precomputed hashes). Not to take down brute force attacks, which is what you explain.

Even if the salt is known, it would still be difficult with rainbow-tables. Brute force attacks is still possible. To tackle brute force attacks, the only way I can see is possible in Blockland is to add a time limit between failed tests. This shouldn't be needed, though, as it's hard as it is to type the password as it is now in a fast manner.

I read through you "wall-o-text" now and found out an misunderstanding of why a salt is used. Instead of explaining it with my broken english, I'll hand you a link to wikipedia to brief you about the topic:

Salt (cryptography)

tl;dr: Salt is to tackle the issue with rainbow-tables(precomputed hashes). Not to take down brute force attacks, which is what you explain.

Even if the salt is known, it would still be difficult with rainbow-tables. Brute force attacks is still possible. To tackle brute force attacks, the only way I can see is possible in Blockland is to add a time limit between failed tests. This shouldn't be needed, though, as it's hard as it is to type the password as it is now in a fast manner.
While you're not wrong with that being the usual purpose of salting, rainbow tables aren't really a realistic issue in Blockland. The main purpose of the salt here is to prevent clients from brute-forcing the hash itself when they download the events by saving. In this case this also works in it's favor, because the server can save/load builds with passwords in them without losing the original passwords; and as a bonus the hash remains very hard to crack from a client's perspective (assuming the salt string is long, as it should be). Overall it seems like this is the best way to do it that both enforces good security of the passwords, and works between saves/loads.