Home > Net >  How to implement "safe" password insertion?
How to implement "safe" password insertion?

Time:09-09

I couldn't come up with a good title for the question, but I hope I'll be able to make it more clear.

In some apps, such as cash machines or investment brokers, you don't insert passwords through a regular keyboard, but rather through a virtual one where each key maps to two different numbers. For example, imagine your password is 9657 and the following options appear on the interface:

  • A) 4 or 2
  • B) 5 or 1
  • C) 3 or 7
  • D) 6 or 0
  • E) 8 or 9

To insert your password, you'd have to type/click: E, D, B, C. That's because E maps to 9, D maps to 6, B maps to 5 and C maps to 7.

However, since each key can map to 2 different numbers, the sequence EDBC can also map to 15 other passwords. So how do I check if the user inserted the right one?

I mean, I know brute force is an option. More specifically - we can iterate over each all the passwords generated by the sequence EDBC and check if one of them is the right password. 8653, 8657, 8613, 8617... and so on.

But is there a more efficient way to do this? Checking a password against a hash can be computationally expensive, let alone 16, 32 or 64 different passwords for each login request.

Example

a screenshot of a login form similar to the one described. The form contains a password field, and below it there are 6 buttons, with the following labels: "6 or 3", "5 or 1", "9 or 8", "0 or 7", "2 or 4", "Clean". Below this set of buttons, there is a bigger button with the label "Sign In".

CodePudding user response:

Sounds like a poor security mechanism as it makes guessing and brute-force easier.

Assuming the algorithm has access to the actual password (pin code), you could map that password to its representation on the virtual keyboard then do a single comparison.

static readonly IReadOnlyDictionary<char, char> convertDigit = 
    new Dictionary<char, char>()
{
    {'4', 'A' }, {'2', 'A' },
    {'5', 'B' }, {'1', 'B' },
    {'3', 'C' }, {'7', 'C' },
    {'6', 'D' }, {'0', 'D' },
    {'8', 'E' }, {'9', 'E' },
};

string ConvertToKeys(string pin)
{
    return new string(pin.Select(d => convertDigit[d]).ToArray());
}
var pin = "9657"; // From database
var input = "EDBC"; // From virtual keypad

Console.WriteLine(input == ConvertToKeys(pin));

CodePudding user response:

Your numerical passwords are immaterial. Convert 9657 to EDBC and you are done.


In passing, checking a four character password against 64 others is peanuts.


For a truly paranoid solution, you can encode the password string as a single integer, using a base-5 decomposition (EDBC -> 4x125 3x25 1x5 2 = 582). Then comparison is done in a single instruction.

CodePudding user response:

The algorithm here is just a for-loop for each button press. Check whether the of digits the first button press can represent includes the first digit of the PIN. If so, continue to the second button press. If you make it through all the letters, then true, else false. This algorithm is O(n) over the number of digits in the PIN, though over such a tiny n, that doesn't really matter.

You never "insert the password" here. In fact that is the intended security measure. The downside is that the system must know the exact PIN rather than a hash of the PIN (but hashing PINs is generally a waste of time since their space is so small).

If there were something "inserted" here, the correct data-format would be something like:

89.60.51.37

(8 or 9, 6 or 0, 5 or 1, 3 or 7)

But the strength of this system is that the mapping of button to digits changes every time it's used, so hashing isn't really a great solution here. (granted it would only require computing and comparing 16 hashes, so maybe that's fine, but again, this space is so small that hashing doesn't offer much.)

  • Related