We want the ability for payments made without logging in using one of their saved payment methods to be associated with the saved payment method. E.g. if they buy a recurring subscription to magazine 1 using credit card 1, then buy another subscription to magazine 2 with credit card 1 (yet again), when they login to their account it should show that both magazines have been purchased using the same payment method. (Not that they both were purchased using two separate cards that just so happen to end in the same last 4 digits.)
As they are not logged in during these two checkouts, there's no way for them to pick their existing payment method to use. Internally, we need to realize that this payment method has been used before and "dedup" them.
My solution to this problem is to use Blowfish to hash the card details:
private static String hashSalt(Long userId) {
final Long rounds = 10
String userHash = sha1("$userId" + GLOBAL_SALT).substring(0, 16)
return "\$2a\$$rounds\$$userHash"
}
private static String mergeCardDetails(String number, String cvv, String expirationMonth, String expirationYear) {
return "card:$number:$cvv:$expirationMonth:$expirationYear"
}
hash = BCrypt.hashpw(mergeCardDetails("4111111111111111", "123", "05", "22"), hashSalt(userId))
Currently the round count is set to 10. However, I realize this is a very low number as the search space for card numbers is very low.
My question, is how many rounds is appropriate for hashing card numbers, today?
I know that in the future the round count will need to be increased, resulting in duplicate payment methods...