I want to encrypt credit card numbers. I want to apply AES-CTR mode. Is it suitable for that?
How can I store nonce and counter values for an individual credit card number?
How can I send the counter values (clear/cipher text)?
Should we use a fresh key for every credit card number?

  • $\begingroup$ Do you have a low and hard limit on the size of the encrypted form of a card number, like that must fit in 8 bytes, or perhaps 16 decimal digits? If yes, forget AES-CTR and study Format Preserving Encryption. $\endgroup$ – fgrieu Mar 23 '15 at 7:28

AES-CTR is very appropriate.

Since a credit card number is 16 characters long, it can be encrypted using a single 128-bit block without any encoding. You will only need 1 block, and hence not require a block counter, just the nonce. Depending on the amount of card numbers being stored, you would only need to store a portion of the full nonce.

A 32-bit nonce will encode a 128-bit block, allowing you to encode 4 billion card numbers using a single key. The resultant ciphertext (including nonce) will be 20 bytes, or 160-bits. The nonce and encoded card number are stored and transmitted together. Text encoding this for storage in a database that does not allow storage of binary data will take approximately 28 bytes.

I would assume you may also want to encode the expiration and card verification number, that would require encoding all the digits to fit in the block, which is not difficult. All that data will fit into an 80-bit space with proper encoding. You could get the ciphertext down to 14 bytes or less.

There are more space efficient methods of storing credit card numbers, but this is simple, easy to debug, and very portable. It is also fast. If your database does not have integrity verification, you may want to add this to the ciphertext, assuming you have the space to do so.

If you have any specific limitations or requirements, those would be helpful in choosing the most appropriate method of encryption.

  • $\begingroup$ Credit card account numbers are 16 digits today only by convention. The ISO standard (7314?) permits card numbers up to 22 digits in length. I've seen some debit card account numbers that are already up to 19 digits in length. I wouldn't recommend coupling the encryption mechanism to an arbitrary attribute controlled by 12,000 random bankers. $\endgroup$ – John Deters Mar 24 '15 at 13:10
  • $\begingroup$ @JohnDeters a 22 digit credit card number can still be encoded to be stored in less than 80 bits of data, and the expiration and cvv can be encoded in less than 30 bits, allowing a single block iteration to encrypt it. What countries have you seen using the larger card numbers, or are they non default merchant cards? $\endgroup$ – Richie Frame Mar 24 '15 at 20:08
  • $\begingroup$ it's been a few years since I've seen them, but they were issued by American banks. I was,also basing my statement on your wording choice of "characters", not digits. 16 characters is 128 bits (ASCII), but you can obviously encode many more digits if you are willing to encode it as a big integer or BCD value. That conversion also risks loss of fidelity in the case where an issuer encodes any other value, such as a driver's license or proprietary gift card. $\endgroup$ – John Deters Mar 24 '15 at 22:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.