Skip to content

Instantly share code, notes, and snippets.

@coolaj86
Created September 18, 2024 05:45
Show Gist options
  • Save coolaj86/1a1fc488d1be23165ae1d3eb3b783581 to your computer and use it in GitHub Desktop.
Save coolaj86/1a1fc488d1be23165ae1d3eb3b783581 to your computer and use it in GitHub Desktop.
Notes on PCI Compliance

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).

Key Takeaways

  • 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
  • We may store the expiration date to help customers avoid a lapse due to expiration

Credit Card Fingerprints / Identifiers

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.

Terminology

  • "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)

PCI Requirements

image

image

image

image

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment