4

I understand PCI DSS 3.0 allows hashes of cardnumbers to be stored separately from encrypted values, but I'm startled at the efficiency of tools like hashcat in discovering card numbers from hashed data given the limited entropy.

Since, for lookup purposes, a random salt is not an option (since often you only have the cardnumber to do the lookup), then any salt would have to be static to lookup the hash.

I read one suggestion that said,

A secret key can be effectively used as a salt value, albeit this defeats some of the reasons for hashing in the first place and requires the same key management as encryption. http://www.integrigy.com/files/Integrigy_Hashing_Credit_Card_Numbers_Unsafe_Practices.pdf

My question is, if I am using a "secret key" for a salt, which is subject to discovery and brute force (though its length might make the latter impractical), why not just encrypt the value with AES256, and do the lookups via the encrypted value?

Is there any security advantage to hashing with a "secret but uniform salt", versus deterministic encryption?

3 Answers3

3

Performing the card lookups against a hash rather than against an encrypted value is done for speed so it is for performance, rather than security, benefit.

In terms of security and the lookup functionality, you could consider a static salt (pepper) as well as an additional, somewhat dynamic salt (such as the expiry date of the card number).

AndyMac
  • 3,159
  • 12
  • 21
  • Credit cards I see usually expire in next few years. Assuming 5, that only gives you 12*5 = 60 different salts. That's not very unique. – domen Feb 09 '15 at 10:35
  • 1
    not to mention using exp. date as salt means leaking another information about the card that's part of card security – jficz Mar 22 '15 at 23:09
0

The difference between a hash function and an encryption is that a hash is suppose to be a one way function while with encryption you can easily get the original data.

If your encryption key gets stolen you can read out all card numbers directly. If your salt gets stolen you still have to brute force it. Depending on your hash function this might be harder as you might think.

With a weak hash function like md5 or sha1 brute forcing would be simple and hashing is not a big improvement. But with a memory and CPU intensive hash you can gain some security here.

Have a look at bcrypt or maybe even scrypt. With bcrypt you can increase the needed CPU time with a parameter to make it harder to brute force. Scrypt is memory heavy so it can't be brute forced with GPUs but is kind of new (2009).

PiTheNumber
  • 5,414
  • 4
  • 21
  • 36
  • So, the advantage of the (pepper)hash would be that we could add security by keeping it secret. And, then on top of that, a slower hash function might make it non-trivial to crack, even if the key was discovered? I'm concluding that slow hash + pepper gives greater security, because it gives the cracker 2 barriers instead of one. – Clayton Hall Jan 09 '15 at 13:57
  • 1
    In both cases you have a secret pepper or password (1. barrier). But yes with slow hash + pepper you are more secure as with a symmetric encryption like AES. The 2. barrier would be to brute force the slow hash function. – PiTheNumber Jan 09 '15 at 14:58
  • SHA1 is not considered weak _yet_. – SilverlightFox Feb 08 '15 at 12:21
  • @SilverlightFox It might not have the official status yet but other functions are recommended for [password hashing](http://security.stackexchange.com/questions/211/how-to-securely-hash-passwords). I think card numbers are just like weak passwords that can be brute forced. But you are right SHA1 is not weak. It just not optimal in this use case. – PiTheNumber Feb 09 '15 at 07:56
  • 2
    Hashing doesn't help you here, even with bcrypt and scrypt. There are only 15 "free" digits in a credit card (the last number is a check digit), leaving `log2(10^15)` or roughly 50 bits of entropy. Worse, card tokens are frequently stored alongside their cleartext bin number (the first six digits) and their last four digits. This leaves only *five* digits, or less than six bits of entropy to break any individual card. Long story short, your best option is likely to use an HMAC with a key stored in an HSM. – Stephen Touset Feb 09 '15 at 15:38
0

In fact although you might be said to be performing the hash for lookup performance, it is being done to be PCI compliant. There are two ways of looking at this.

  1. Do x, it is the right thing to do.
  2. Do x, or we'll get caught not doing it.

Doing x to prevent cracking does not really come into it, since there are only about 5 numbers to guess in some cases. 6 digits of BIN, 1 check digit, and it has to pass Luhn.

It should only useful together with expiry dates, cvv, and billing details.

Checking and input card number against a hash is odd. Is it being used as a defacto password? Or is the decrypted value being checked against the hash ?

That is, if the user is authenticated, we can use the "Vault stored" card for a transaction, why are we checking the card number again ?

The only other reason to hash is to level an index, which otherwise would have an almighty great hotspot on each of the BINs, cardinality of the following digits aside.

mckenzm
  • 487
  • 2
  • 6
  • Hashing the cardnumber is probably not necessary for a retailer. But in a card vendor scenario, one of the expected services is IVR activation. The normal prodedure, is dial in, enter the 16 digits of the card number, and activate the card. In this scenario, the only way to lookup the card to activate is by some deterministic value based on the cardnumber. – Clayton Hall Jul 07 '15 at 14:59