Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best way to prevent duplicate use of credit cards

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?

like image 930
Lars A. Brekken Avatar asked Sep 19 '08 15:09

Lars A. Brekken


People also ask

Why does my card keep getting cloned?

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.

Can someone duplicate a credit card?

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.

Can someone clone your debit card?

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.


2 Answers

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.

like image 118
Nick Johnson Avatar answered Sep 22 '22 02:09

Nick Johnson


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.

like image 27
Wedge Avatar answered Sep 23 '22 02:09

Wedge