Copied from https://github.com/bnnanet/bnna-payment-gateway.js/issues/5 for the immediate benefit of others, to be available as a Public gist until we make the whole repo public (once it's useful).
- We should limit stored data to what's required for a specific, known business purposes
(not "just in case it's useful") - We may, for internal use, salt and hash the full credit card number (with per-vendor salts)
- We MUST NOT expose that salt or hash via API
- We may create a 1:1 mapping with a random (or otherwise unrelated) key and the salted hash
- This is the user-facing identifier
- We may help customers identify their cards by showing storing and showing
- IIN (BIN) (i.e. the first 7 or 8 digits that identify the Issuer, Bank, and Program, ex: Amazon Chase Rewards)
- we should probably NOT store this, but rather just indicate the brand (i.e. Visa, MasterCard, etc)
- name on card
- the last 4 digits
- IIN (BIN) (i.e. the first 7 or 8 digits that identify the Issuer, Bank, and Program, ex: Amazon Chase Rewards)
- We may store the expiration date to help customers avoid a lapse due to expiration
Braintree is a PCI Level 1 Service Provider and the hashing of PANs for this purpose is included in our yearly on-site PCI audit. PCI-DSS does allow for a PAN (the primary account number, or credit card number) to be stored in hashed form using "strong cryptography" and they recommend (but do not require) that a salt be used as well. PCI-DSS v3 § 3.4(PDF link) The reason is to inhibit the ability of a malicious party who gets ahold of the hash from determining the PAN that was used as the input for the hash. The general consenus for password hashing is bcrypt, and that is what I would suggest here. For the cost, set it as high as your application allows. It likely isn't something you're going to be computing terribly frequently (I'd imagine, depending on your application, you're going to be looking at x hashes per minute or hour or day rather than per second) and the higher the cost, the harder it will be for an adversary who captures the hash to brute force.
- "PAN" means Card Number (Primary Account Number)
- "keyed cryptographic hashes" means "salted hash"
- "indexed token" means random id (not a hash of the card number)