We have a system where we want to prevent the same credit card number being registered for two different accounts. As we don't store the credit card number internally - just the last four digits and expiration date - we cannot simply compare credit card numbers and expiration dates.
Our current idea is to store a hash (SHA-1) in our system of the credit card information when the card is registered, and to compare hashes to determine if a card has been used before.
Usually, a salt is used to avoid dictionary attacks. I assume we are vulnerable in this case, so we should probably store a salt along with the hash.
Do you guys see any flaws in this method? Is this a standard way of solving this problem?
Most credit card cloning fraud is done through the use of skimmers. Skimmers read credit card information such as numbers, PINs, CVV data through the magnetic stripe, and can be attached to hardware such as point of sale (POS) terminals, or ATMs, allowing them to steal whoever uses that hardware's information.
Credit card cloning refers to making an unauthorized copy of a credit card. This practice is also sometimes called skimming. Thieves copy information at a credit card terminal using an electronic device and transfer the data from the stolen card to a new card or rewrite an existing card with the information.
Credit card cloning or skimming is the illegal act of making unauthorized copies of credit or debit cards. This enables criminals to use them for payments, effectively stealing the cardholder's money and/or putting the cardholder in debt.
Let's do a little math: Credit card numbers are 16 digits long. The first seven digits are 'major industry' and issuer numbers, and the last digit is the luhn checksum. That leaves 8 digits 'free', for a total of 100,000,000 account numbers, multiplied by the number of potential issuer numbers (which is not likely to be very high). There are implementations that can do millions of hashes per second on everyday hardware, so no matter what salting you do, this is not going to be a big deal to brute force.
By sheer coincidence, when looking for something giving hash algorithm benchmarks, I found this article about storing credit card hashes, which says:
Storing credit cards using a simple single pass of a hash algorithm, even when salted, is fool-hardy. It is just too easy to brute force the credit card numbers if the hashes are compromised.
...
When hashing credit card number, the hashing must be carefully designed to protect against brute forcing by using strongest available cryptographic hash functions, large salt values, and multiple iterations.
The full article is well worth a thorough read. Unfortunately, the upshot seems to be that any circumstance that makes it 'safe' to store hashed credit card numbers will also make it prohibitively expensive to search for duplicates.
People are over thinking the design of this, I think. Use a salted, highly secure (e.g. "computationally expensive") hash like sha-256, with a per-record unique salt.
You should do a low-cost, high accuracy check first, then do the high-cost definitive check only if that check hits.
Step 1:
Look for matches to the last 4 digits (and possibly also the exp. date, though there's some subtleties there that may need addressing).
Step 2:
If the simple check hits, use the salt, get the hash value, do the in depth check.
The last 4 digits of the cc# are the most unique (partly because it includes the LUHN check digit as well) so the percentage of in depth checks you will do that won't ultimately match (the false positive rate) will be very, very low (a fraction of a percent), which saves you a tremendous amount of overhead relative to the naive "do the hash check every time" design.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With