# Secure way to store fixed size string of digits

I need to store a string of digits (0-9) of a fixed size in my database securely.

I've already performed a rainbow table attack on a plain hash, and it broke it in a matter of seconds.

One option I had was to break the string into 2 or more parts and store them separately, within reason (i.e do not have the resources for multiple servers), but I feel like this will only delay an attacker a small amount.

The other option is using salted hashes, but I'm not sure if this will help in this case.

Does anyone have any suggestions?

-
Define "securely". $\;$ You want to achieve confidentiality, but what about integrity, and high insurance of availability despite hardware mishaps? $\;$ When you need the data, is it for the purpose of testing if some string is that 9-digit string, or do you need to retrieve that value? $\;$ If you can retrieve that 9-digit string value, and the adversary can't, what can the system use to differentiate you from the adversary? $\;$ What is it reasonable to believe an attacker can/can't do on your system? –  fgrieu Jul 23 '14 at 16:59
So basically I am using this value as a unique identifier for a user. So I don't need to worry about needing a two-way function. –  Brad W Jul 23 '14 at 17:08
An administrator can search for users using this string of digits, and the system should return zero to one results. I don't care about retrieving the value at a later point. –  Brad W Jul 23 '14 at 17:15
"and the system should return zero to one results", indicating whether such a user exists or whether a given user has that identifier? $\;$ –  Ricky Demer Jul 23 '14 at 17:26
Store the information on a memory stick and keep the stick in your pocket until you need to enter it into your system. –  William Hird Jul 23 '14 at 19:16

It'll be the same situation that NY City suffered some days ago: when you have little variability on your data, i.e., they have a fixed-small size, it'll always be fast to brute force.

You don't say how long your number is, so I'll assume it can range from 0 - 10,000,000,000 (so, a unique number for each human being on Earth today, plus some spare). You said that you'll have 9 digits, so anything I say below will be 100 times faster.

In that case, using any kind of hash will only delay the attack by some amount. If you use MD5 hash, some hardwares can calculate 28 Billion hashes/sec.

If you use a unique, random salt for each number, once the attacker finds our the salt (it's not secret, since it's stored in the database), he'll only need to calculate those hashes including the salt, and will take 1 sec for each number you have. No good.

Other hashes (SHA in general, Scrypt, etc and etc) will again slow things down, perhaps requiring more memory, but they won't do magic: in the end it'll be just a matter of time.

And what about changing your digits, for example encoding it so that it'll have letters on it? Still, won't solve your problem, because your data can only have 10 billion variations (in my hipotheses, your case might be even worst).

And what about making another table, with correspondence, that was a proposed solution to the NY City data? Won't do any good to you, since if someone is able to access your number, or their hashes, probably he'll be able to access those data too.

What would I do in your case?

1 - If the data will be inside your system, in your database, and in your company, and not available via web systems: protect as hard as you can using firewalls, blocking who can access the database, scrutiny of your workers, and pray. If some computer of your network is compromised, it might have privileges to access the database, and you're gone.

2 - The data must be exchanged with other systems or other companies: although there are hardware designed to protect data communication (quantum encryption, etc), you'll have to worry about your insiders again, and external attacks on your computers, and the previous scenario still applies.

3 - Does your data really needs to be secret? Perhaps what you can do (or I would do) is nothing. If you have a small number of possibilities for your data, concatenating more information (be it a salt, the email of the user, anything else) won't help, since all that "information" will be stored somehow in your database, or in your code, and will be accessible anyhow.

Protect only the hardware with physical protection (like using HSM) isn't enought. You also need to worry about the ways the application needs to access that information, and in what aspect it would be different if a hacker gained control of one computer inside your company and what he also would be able to do with a keylogger, screenlogger, and so on.

-
So basically I have to rely on the security of the data transport and physical security of the storage? –  Brad W Jul 23 '14 at 18:09
I'll update my answer in few minutes... –  woliveirajr Jul 23 '14 at 18:20
Thanks for all the points mentioned. The data does need to be concealed in some way or another, and I understand that there isn't much you can do about an inside job (authorized user) and we have a decent amount of security to protect our hardware from unauthorized users. The big problem is that the application that uses this data is a web application –  Brad W Jul 23 '14 at 18:44
Put the data in another server (if possible), firewall between them, assure that the software/database will sanitize any query and will only provide the needed answer (and can't be fooled in providing more), that it won't provide more than x answers per second/minute/day/whatever (to avoid some brute-force from web)... –  woliveirajr Jul 23 '14 at 18:51
Yeah, after some quick research something like the way amazon stores credit card information is likely the best route to take. –  Brad W Jul 23 '14 at 18:55