How does one substitute the CVC3, ATC and unpredictable number in EMV contactless track data? - contactless-smartcard

I'm trying to assemble proper track data given a CVC3 and a bunch of positional parameters. But the EMV C-2 Kernel book is about as obtuse as you could imagine (would it kill somebody to include an example!?!). Can anyone help work this example:
9f62 - pcvc3(t1) - Position of CVC3 in track1: 0x38 (4-6?)
9f63 - punatc(t1) - Unpredictable Number Track1 Pos: 0x3C6 (2-3 7-10?)
9f64 - natc(t1) - Digits in track1 ATC: 4
9f65 - pcvc3(t2) - Position of CVC3 in track2: 0x38 (4-6)
9f66 - punatc(t2) - Unpredictable Number Track2 Pos: 0x3C6 (2-3 7-10?)
9f67 - Digits in track2 ATC: 4
After successful checksum generation:
9f61 - track2 CVC3 - 2EF4
9f60 - track1 CVC3 - 609B
9f36 - ATC - 1E47
assuming the discretionary data field starts out as all 0s, how does it end up? The spec says this:
Convert the binary encoded CVC3 (Track2) to the BCD encoding of the
corresponding number expressed in base 10. Copy the q least significant digits of the
BCD encoded CVC3 (Track2) in the eligible positions of the 'Discretionary Data' in
Track 2 Data. The eligible positions are indicated by the q non-zero bits in
PCVC3(Track2).
I read that as:
CVC3 = 0x609B = 24731 (so copy 731? What does BCD have to do with this? Or are they just saying "copy the 731 as bcd encoded to the byte array"?)

yes you are correct it is rather obtuse. you are correct that you would convert your p values (pCVC3, and PUNATC) to binary. (0011 1000, 0011 1100 0110 for your track1 p values) you then right align the proper values with the discretionary data. example
Bxxxxxxxxxxxxxxxx^ /^14111014010000000000
....000000000000000000CCC000
....00000000000000AAAA000UU0
so you say that you CVC3 for track 1 is 609B which is 24,731, since you PCVC3 is asking for only 3 characters youd set 731 in. your ATC is 1E47 which is 7,751. your PUNATC is asking for 4 digits so you'd use 7751. FYI... if the ATC is lower than the requested characters you'd pad with 0's. Your unpredictable number is even more tricky... so you make a 4 byte random number. convert it to a uint (base 10) and then mark the 8 most significant bytes as 0. example. lets say your random 4 bytes is 29A6 06AE. in base 10 that is 698,746,542. mark out the first 8 characters with 0. and you are left with 000,000,002. you'd place 02 in for you unpredictable number placment.. so.. all that said your track would look like this
Bxxxxxxxxxxxxxxxx^ /^14111014017751731020
the last character is equal to the length of the unpredicatable number (numeric) digits. which was 02.. so the last digit is 2 making your final track data
%Bxxxxxxxxxxxxxxxx^ /^1411014017751731022;
track2 is very similar. good luck with it. I understand your frustrations with this. :)

Related

How hexadecimal representation matches word size?

What does the statement "hexadecimal matches cleanly with modulo 8 word sizes, such as 8, 16, 32, and 64 bits" mean?
Since a single hex digit can represent exactly 4 bits of binary data, any word size that's a multiple of 4 can be exactly represented with a fixed number of hex digits.
And every word size that's a multiple of 8 (i.e. the common ones) can be represented with a number of digits that's a multiple of 2:
8 bits can store values from 00 to FF
16 bits can store values from 0000 to FFFF
32 bits can store values from 00000000 to FFFFFFFF
...
All 2-digit hex numbers can be represented in 8 bits and all 8 bit values can be represented in 2 hex digits. If a hex editor displays some value as CA FE BA BE you can easily grasp that it's 4 bytes and thus 32 bits. Getting that information from the decimal 3405707966 is not quite as trivial (no matter how you group the digits: there's no nice "byte boundaries" in that representation).
If you compare this with decimal, the same isn't true. For example, 8 bits can represent values from 0 to 255 (decimal). So you need up to 3 digits in decimal to represent 8-bit values. But there are 3-digit decimal values that you can't represent in 8 bits: 256 (or anything higher than that) doesn't map onto 8 bits. So the mapping isn't perfect for decimal numbers.

ISO 8583 Field 22

I'm trying to build an parser to deserialze into object. Socket will send byte into parser. For the length of field 22 POS Entry Mode will N3 and byte will be always 2 digit. How to get the value for this field ?
You read the ASCII value of this field, and convert it into an integer.
if it says N3 that means they are three digits numeric field, so if the value say 51, you cast it to 051 and send the ASCII equivalent
Field 22 is pos entry mode. It's 3 digit numeric value. If format is BCD then 2 bytes contains 4 digits[ 0 (padded) + 3 digit POS entry mode). If format is ascci then it is 3 byte.

Is there a way to represent a number in binary where bits have approximately uniform significance?

I'm wondering if it is possible to represent a number as a sequence of bits, each having approximately the same significance, such that if we flip one of the bits, the overall value does not change by much.
For example, we can use sequences of 4-bits, where each group represents a value from 0 to 15 and the overall value is the sum of all these values.
0110 0101 1101 1010 1011 → 6 + 5 + 13 + 10 + 11 = 45
and now flipping any bit can only incur in a maximum difference of 8 in the final value.
Some drawbacks obviously exist with this approach:
values have multiple representations, with some values having more representations than other ones (for example, there are 39280 distinct representations for the number 38, and only 1 for the number 0);
the amount of values that can be represented is greatly reduced (this representation allows for integers from 0 to 75, while 20 bits could normally represent 220 ~ 1 million different integers).
Are there any resources I can find concerning this problem? I can't seem to find anything online, but maybe I'm not searching with the right keywords. What other alternatives exist to my approach? Do they improve on its disadvantages?

ISO 8583 Rev 93 Alphabetic & Numeric Characters Packing/Unpacking

I am faced with the task of sending ISO 8583 Rev 93 messages and am using openiso8583.net. The company that is consuming my messages gave message samples and I am unclear about the following Field attributes:
Special Characters
Alphabetic & Numeric Characters
Alphabetic & Special Characters
Number & Special Characters
Alphabetic, Numeric, & Special Characters
Here is the example:
Signon Reply
0810822000000200000004000000000000000501130427000005F0F00001
NUM |FLDNAME |FIELD DESCRIPTION |LEN |T|FIELD VALUE
-----|--------|-------------------------------|----|-|--------------------------
N/A |MSGTYPE |MESSAGE TYPE |F2 |H|0810`
N/A |BITMAP1 |FIRST BITMAP |B8 |H|8220000002000000`
1 |BITMAP2 |SECOND BITMAP |B8 |H|0400000000000000`
7 |MISDTMDT|TRANSMISSION DATE AND TIME |F5 |H|0501130427`
11 |MISDSTAN|SYSTEM TRACE AUDIT NUMBER |F3 |H|000005`
39 |MISDRSPC|RESPONSE CODE |F2 |C|00` <------?
70 |MISDNMIC|NETWORK MANAGEMENT INFO CODE |F2 |H|0001`
First, take a look at the message bytes:
0810822000000200000004000000000000000501130427000005*F0F0*0001
My question is how the two bytes { 0xF0, 0xF0 } translates to "00". If the company was sending ASCII, I would expect "00" to be { 0x30, 0x30 }. BCD is used for Numeric values but I can't seem to figure out how character values are being encoded.
Here is the description for field 39:
039:
Network Response Code
Attributes:
an 2*
Description:
A field that indicates the result of a previous related request. It will indicate
approval or reason for rejection if not approved. It is also used to indicate to the
device processor whether or not machines that are capable of retaining the customer's
card should do so.
Format:
In transaction replies, the response code must contain one of the following values
with their corresponding meanings. For debit/host-data-capture 0220 / 0420 messages, a
response code of '00' must be returned to indicate the transaction was approved. For
EBT transactions, please refer to section 4.8 EBT Transaction Receipt Requirements.
an2 means Alphabetic & Numeric Characters
Bitmap 1 is 64 bits
Bitmap 2 is 64 bits
Msg Type is 4 bytes
Field 7 is Numeric 4-bit BCD (Packed unsigned) 10, 5 bytes
Field 11 is Numeric 4-bit BCD (Packed unsigned) 6, 3 bytes
Field 39 is an 2, I assume 2 bytes
Field 70 is Numeric 4-bit BCD (Packed unsigned) 3, 2 bytes
Any clues or pointers would be greatly appreciated. Maybe someone knows of some encoding I clearly do not or can give a general explenation of how characters are encoded for ISO 8583 Rev 93. I do realize that each company can have different implementations though.
I hate answering my own questions quickly but...I just found the answer.
EBCDIC
I guess not being a programmer in the days of punch cards slowed me down on this one
0xF0 = '0'

SQL - Create Unique AlphaNumeric based on a 10-digit integer stored as VARCHAR

I'm trying to emulate a function in SQL that a client has produced in Excel. In effect, they have a unique, 10-digit numeric value (VARCHAR) as the primary key in one of their enterprise database systems. Within another database, they require a unique, 5-digit alphanumeric identifier. They want that 5-digit alphanumeric value to be a representation of the 10-digit number. So what they did in excel was to split the 10-digit number into pairs, then convert each of those pairs into a hexadecimal value, then stitch them back together.
The EXCEL equation is:
=IF(VALUE(MID(A2,1,4))>0,DEC2HEX(VALUE(MID(A2,3,2)))&DEC2HEX(VALUE(MID(A2,5,2)))&DEC2HEX(VALUE(MID(A2,7,2)))&DEC2HEX(VALUE(MID(A2,9,2))),DEC2HEX(VALUE(MID(A2,5,2)))&DEC2HEX(VALUE(MID(A2,7,2)))&DEC2HEX((VALUE(MID(A2,9,2)))))
I need the SQL equivalent of this. Of course, should someone out there know a better way to accomplish their goal of "a 5-digit alphanumeric identifier" based off the 10-digit number, I'm all ears.
ADDED 8/2/2011
First of all, thank you to everyone for the replies. Nice to see folks willing to help and even enjoying it! Based on all the responses, I'm apt to tell my client they're intent is sound, only their method is off kilter. I'd also like to recommend a solution. So the challenge remains, just modified slightly:
CHALLENGE: Within SQL, take a 10 digit, unique NUMERIC string and represent it ALPHANUMERICALLY in as few characters as possible. The resulting string must also be unique.
Note that the first 3-4 characters in the 10-digit string are likely to be zeros, and that they could be stripped to shorten the resulting alphanumeric string. Not required, but perhaps helpful.
This problem is inherently impossible. You have a 10 digit numeric value that you want to convert to a 5 digit alphanumeric value. Since there are 10 numeric characters, this means that there are 10^10 = 10 000 000 000 unique values for your 10 digit number. Since there are 36 alphanumeric characters (26 letters + 10 numbers), there are 36^5 = 60 466 176 unique values for your 5 digit number. You cannot map a set of 10 billion elements into a set with around 60 million.
Now, lets take a closer look at what your client's code is doing:
So what they did in excel was to split the 10-digit number into pairs, then convert each of those pairs into a hexadecimal value, then stitch them back together.
This isn't 100% accurate. The excel code never uses the first 2 digits, but performs this operation on the remaining 8. There are two main problems with this algorithm which may not be intuitively obvious:
Two 10 digit numbers can map to the same 5 digit number. Consider the numbers 1000000117 and 1000001701. The last four digits of 1000000117 get mapped to 1 11, where the last four digits of 1000001701 get mapped to 11 1. This causes both to map to 00111.
The 5 digit number may not even end up being 5 digits! For example, 1000001616 gets mapped to 001010.
So, what is a possible solution? Well, if you don't care if that 5 digit number is unique or not, in MySQL you can use something like:
hex(<NUMERIC VALUE> % 0xFFFFF)
The log of 10^10 base 2 is 33.219280948874
> return math.log(10 ^ 10) / math.log(2)
33.219280948874
> = 2 ^ 33.21928
9999993422.9114
So, it takes 34 bits to represent this number. In hex this will take 34/4 = 8.5 characters, much more than 5.
> return math.log(10 ^ 10) / math.log(16)
8.3048202372184
The Excel macro is ignoring the first 4 (or 6) characters of the 10 character string.
You could try encoding in base 36 instead of 16. This will get you to 7 characters or less.
> return math.log(10 ^ 10) / math.log(36)
6.4254860446923
The popular base 64 encoding will get you to 6 characters
> return math.log(10 ^ 10) / math.log(64)
5.5365468248123
Even Ascii85 encoding won't get you down to 5.
> return math.log(10 ^ 10) / math.log(85)
5.1829075929158
You need base 100 to get to 5 characters
> return math.log(10 ^ 10) / math.log(100)
5
There aren't 100 printable ASCII characters, so this is not going to work, as zkhr explained as well, unless you're willing to go beyond ASCII.
I found your question interesting (although I don't claim to know the answer) - I googled a bit for you out of interest and found this which may help you http://dpatrickcaldwell.blogspot.com/2009/05/converting-decimal-to-hexadecimal-with.html