# Alice's forgetful banking

Alice has a bank account number, but has forgotten which bank it is for. There are 4 banks, run by Bob, Carlos, David, and Eve.

She could find out by going to all of the banks and asking if they have the account number. However, if Eve learns Alice's account number, then Eve will go to Alice's actual bank and steal all of Alice's money.

Alice could hash the bank account number, and ask about the hash, but since the account number is only 8 digits, Eve could bruteforce the hash anyway. Then, Eve will go to Alice's bank and steal all of her money.

Alice could use a Zero Knowledge Proving Protocol, but how would the bank know which account number to check against without repeating the ZKPP for every account number? Each of them has thousands of customers.

Context: I'm writing a program to retrieve an encrypted copy of one's keys and friends-list for a project called Tox (http://wiki.tox.im/index.php/Proposal:Friendslist_Server). I'd like to make it automatically detect which server has it.

-
The problem here is that your identification token is also your authentication token, and worse, it only has an key space of approximately 27 bits. I don't see a way to create a secure scheme out of this. –  orlp Aug 8 '13 at 22:36
Can't you simply use the username for the lookup followed by a zero knowledge proof for the password hash? –  CodesInChaos Aug 9 '13 at 11:32
I don't understand the constraints. What parts of the system can we modify? Can we modify both the client (the software Alice runs or the procedure Alice follows) and the server (the code that the banks run for authenticating Alice or that process they use to help Alice check about that account number)? If you can change both endpoints, why are you limited to just 8-digit account numbers: why can't you choose arbitrarily long account numbers? (Also, you later mention cryptographic keys. If we're talking about keys, those won't be 8 digits long and won't be brute-forceable, so which is it?) –  D.W. Aug 10 '13 at 0:58
If the account number is a capability that's all that's needed to withdraw all of the money from that account, then 8 digits isn't enough. If a bank has ten million customers, simple random guessing will succeed with probability 10%. So the problem as specified can't be quite right. Something smells like we don't have all the real requirements/constraints.... Can you try editing the question to tell us the real problem you have? –  D.W. Aug 10 '13 at 1:01
@D.W. What parts of the system can we modify? Any part, but banks won't participate in any system that will allow an impostor customer to learn account numbers. If a bank has ten million customers I specified how many customers the bank has in the question. we don't have all the real requirements I specified the context in the question. –  Nick ODell Aug 11 '13 at 3:56

Private Set Intersection

How about a private set intersection protocol?

The banks input is a set of all of their account numbers, the user's input is their account number (a single member set). The output could be given to the user, or the bank, or both, depending on your needs.

You would need a way to protect against guessing account numbers. For example, I could just keep submitting account numbers to one of the banks until I find a valid account at that bank. Or, the bank could put tons, and tons of accounts in their set that they don't actually own with the hopes that your account number will be in there and they can figure out your account.

Both would be fairly easy to protect against if the account numbers are fairly large (say 256 bits) and randomly generated. The probability of success would be greatly limited. You could further limit the bank from submitting overly large sets as I think the size of the set is probably not kept hidden.

Another possibility

Another possibility would be to develop a multiparty set intersection protocol using multiparty computation. Use the paper I linked to as a basis (it only supports 2 parties). That way all parties participate in the protocol at the same time. An MPC framework such as VIFF will be helpful.

The idea is that all banks would input their account databases, the user would input their account number, and you find which set contains the account number and return to the user the ID of that bank. If 2 banks are found to have that account, someone likely falsifying accounts and return $\bot$.

-

As nightcracker notes in the comments, the real problem in your bank scenario is that the account number is doing double duty as both an identification token and as an authentication token.

The solution is equally simple: make the account number public and use it only for identification. Have Alice's bank issue her another number (let's call it a PIN) that isn't required to identify her account, but is required to withdraw money from it.

Of course, if some of the other banks are untrustworthy, they might claim to have Alice's account and ask for her PIN, only to then use it to steal money from her real account. To prevent this, Alice could (as you suggest) use a zero-knowledge proof protocol to verify her PIN to her real bank without allowing an impostor bank to learn it. Since the bank does know Alice's account number, they can use it to look up Alice's account information and verify her PIN against it.

The same solution should work for your actual problem: use the username to identify the user and the password to authenticate her. For the authentication step, I'd suggest an augmented PAKE protocol such as SRP, which will allow the user to prove her knowledge of her password to the server without ever having to actually disclose said password (or anything equivalent to it) to anyone.

@Nick: I gave some reasons in this answer, but the real problem in your scenario is that, with a combined account identifier/authenticator, you have no way of referring to the account without also disclosing the information needed to access it. (As for your second question, I'd say the optimal choice would be to use $M$ bits for identification and $N-M$ bits for authentication, where $M$ is the minimum number of bits needed to uniquely identify the user.) –  Ilmari Karonen Aug 9 '13 at 16:34