fluzwup / Cryptonomicon

Tool to help debug cryptographic issues encountered with EMV chip cards.
5 stars 4 forks source link

Bug CVV2 - Year Month inverted #2

Closed Pascal66 closed 3 years ago

Pascal66 commented 5 years ago

Yours:

CVK A/B: 0123456789ABCDEF0123456789ABCDEF PAN: 1234560123456789 Expiration date: 1222 Service Code: 226 Value Type: CVV2/CVC2 Verification value: 802

Good: CVK A/B: 0123456789ABCDEF0123456789ABCDEF PAN: 1234560123456789 Expiration date: 2212 Service Code: 226 Value Type: CVV2/CVC2 *Verification value: 393

Checked with BP-Tools. // use 000 as service code, swap year/month for CVC2 in your code.

fluzwup commented 5 years ago

You need to swap the year/month in the data for CVV2 and CVC2.

Pascal66 commented 5 years ago

Where this come from please ? Like a wrote, I've tested with another tool, and thy didn't swap

fluzwup commented 5 years ago

This is correct: $ ./cryptonomicon cvc key=0123456789ABCDEF0123456789ABCDEF PAN=1234560123456789 data=2212226 CVC/CVV is 538, iCVC/iCVV is 774, CVC2/CVV2 is 802 The code swaps the dates and replaces the service code for the iCVV and CVV2.

Here is what you are getting: $ ./cryptonomicon cvc key=0123456789ABCDEF0123456789ABCDEF PAN=1234560123456789 data=1222226 CVC/CVV is 615, iCVC/iCVV is 202, CVC2/CVV2 is 393 Manually switching the date gives you the wrong values, but this is how you're getting 393. I'll dig up the EMV manual reference for you.

Pascal66 commented 5 years ago

I understand. I see somewhere that's swapping YYMM is a variation:

"One CVV variant, now commonly called CVV2 (Visa), or Indent CVC (MasterCard), uses '000' as the service code parameter to the CVV algorithm.

Another variation to the CVV algorithm can be introduced by changing the format of the expiration date. While the date is always the concatenation of the 2-digit month (MM) andlast 2 digits of the year (YY), it can be in either YYMM or MMYY formats. For instance, Visa CVV2s are usually calculated using the YYMM format."

fluzwup commented 5 years ago

Unfortunately, I can't find anything in the documentation I have on exactly how the CVV/iCVV/CVV2 are supposed to be generated. It pre-dates EMV chips, so it's not in the EMV documentation. I have a scanned table with steps for the algorithm, but it's useless for determining the order of the YYMM or MMYY, as it uses "0047" where the date would be (and of course the scanned image is trimmed down to just the table, so I have no idea what book or document it came from). You might look at the references in this article: https://en.wikipedia.org/wiki/Card_security_code and see if those lead anywhere.

What I can provide is an example of a Paybment Card Industry certified HSM doing the same operation, and getting the same results. Our HSM prohibits weak keys, so I'm using the Visa CEMEA region test CVKA and CVKB in this operation. Those are proprietary, so I've masked out the clear key values in the cryptonomicon statement (but left a bit so you can compare if you have access to those keys). The keys used in the HSM command are encrypted under the HSM's master key, which is why they don't match the unmasked bits.

Here is the breakdown on the token specifiers for the Generate CVC command input (Generate CVV uses the same format): AV: account number CA and CB: Card verification key parts A and B FA: expiration date in MMYY format FG: service code FT: CVV2/CSC2 generation

And the response tokens: FC: the generated CVV/CSC FT: the generated CVV2/CSC2

This uses the actual service code, and generates the CVV: Request: [AOGCVC;CA644CA38E3B1A4C57;CBC6B3F3EC4B2D5808;AV1234560123456789;FA2212;FB226;] Response:[AOGCVC;FC659;]

This uses 999 as the service code, and generates the iCVV: Request: [AOGCVC;CA644CA38E3B1A4C57;CBC6B3F3EC4B2D5808;AV1234560123456789;FA2212;FB999;] Response:[AOGCVC;FC756;]

This uses 000 as the service code, and sets the FT flag to generate the CVV2: Request: [AOGCVC;CA644CA38E3B1A4C57;CBC6B3F3EC4B2D5808;AV1234560123456789;FA2212;FB000;FT;] Response:[AOGCVC;FC457;FT637;]

Here is the same set of data for the Generate CVV command: Request: [AOGCVV;CA644CA38E3B1A4C57;CBC6B3F3EC4B2D5808;AV1234560123456789;FA2212;FB226;] Response:[AOGCVV;FC659;] Request: [AOGCVV;CA644CA38E3B1A4C57;CBC6B3F3EC4B2D5808;AV1234560123456789;FA2212;FB999;] Response:[AOGCVV;FC756;] Request: [AOGCVV;CA644CA38E3B1A4C57;CBC6B3F3EC4B2D5808;AV1234560123456789;FA2212;FB000;FT;] Response:[AOGCVV;FC457;FT637;]

And here is the Generate Checksum command run on the CVKA + CVKB: Request: [AOGCKD;FUS;AS4;BG644CA38E3B1A4C57C6B3F3EC4B2D5808;] Response:[AOGCKD;FUS;AEB1A6D3;] The token after AE is the KCV, so it is B1A6D3.

Compare the output to the output of cryptonomicon, when using the fake PAN and the Visa CEMEA CVKA + CVKB: $ ./cryptonomicon cvc key=B3D33xxxxxxxxxxxxxxxxxxxxxxx9494 PAN=1234560123456789 data=2212226 CVC/CVV is 659, iCVC/iCVV is 756, CVC2/CVV2 is 637

And to verify the checksum of the key: $ ./cryptonomicon kcv key=B3D3xxxxxxxxxxxxxxxxxxxxxxxx9494 KCV is B1A6D3

It's not the answer I'd like to give you, but it's the best I can do right now. The comparison against the HSM is actually the gold standard for me, since that's the tool we are required by Payment Card Industry regulations to use on actual transactions.

Pascal66 commented 5 years ago

Ok, I'm back on it. As CVV (with YYMM inversion or not) going to be forgotten, Only focusing on dCCV

fluzwup commented 2 years ago

Just FYI, I was working on my PDF indexer code, and happened to think to look up MMYY in the (massive) index generated by all my Visa, MasterCard, and EMV PDF documents. I found a reference that states that the CVV2 typically uses MMYY. The document is "Payment Technology Standards Manual" from Visa, section 3:

"The CVV2 value is computed using the same algorithm for the Card Verification Value (CVV) described in Chapter 2, with the exception of the expiration date which is input using embossed or printed format (MMYY). The CVV2 may also be calculated under the YYMM format; please check with your Visa local representative."