In one of my application, I open binary files, and I got some error report by users on some files. When they send me the files, if I download them on Gmail in the desktop, the file displays nicely in my app. When I download them with the native Android GMail app, the file doesn't open.
Here are the first 64 bytes of the original file, and as it appear when downloaded from the desktop (displayed as hexa):
03 00 08 00 D8 0C 00 00 01 00 1C 00 BC 02 00 00
2D 00 00 00 00 00 00 00 00 01 00 00 D0 00 00 00
00 00 00 00 00 00 00 00 10 00 00 00 25 00 00 00
33 00 00 00 3D 00 00 00 44 00 00 00 49 00 00 00
And here are the first 64 bytes of the file downloaded with the native GMail app (hexa again) :
EF BF BD EF BF BD 2D EF BF BD 25 33 3D 44 49 4D
52 63 72 76 EF BF BD EF BF BD EF BF BD EF BF BD
EF BF BD EF BF BD EF BF BD EF BF BD EF BF BD EF
BF BD EF BF BD 29 2E 3E 43 54 59 69 6E 7F EF BF
Is there a sort of compression applied to this file or is the GMail app corrupting it ? Especially if you look at the end of the first sample, you have the following bytes 10, 25, 33, 3D, 44, 49, which also appear in the first line of the second sample, which leed me to think that it's a compression of some sort.
I'm not sure of the exact source, but if you look at http://www.cogsci.ed.ac.uk/~richard/utf-8.cgi?input=%F6&mode=char then that pattern is due to something trying to interpret the file as UTF-8, doing replacement, then writing the file as UTF-8.
Related
I am trying to read the information stored on my German Sparkasse Girocard. My app successfully recognizes the (ISODEP) tag. To read the stored information, I need to send a sequence of APDU commands, but I am not sure which.
From my understanding I need to send a SELECT command first:
byte[] SELECT = {
(byte) 0x00, // CLA Class
(byte) 0xA4, // INS Instruction
(byte) 0x04, // P1 Parameter 1
(byte) 0x00, // P2 Parameter 2
(byte) 0x09, // Lc
(byte) 0xD2,0x76,0x00,0x00,0x25,0x47,0x41,0x01,0x00, // AID
(byte) 0x00 //Le
};
Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
IsoDep tag = IsoDep.get(tagFromIntent);
tag.connect();
byte[] result = tag.transceive(SELECT);
text.setText(Integer.toHexString(result[0]) + ", " + Integer.toHexString(result[1]));
The status response should be 9000 if it works. I am getting 6F44 which indicates that there was some sort of error (I think). I am also not quite sure if I am using the correct AID, but it has also not worked using others, which I thought could be correct.
What is my error and which commands do I have to send to retrieve the data?
Thanks in advance.
Getting data from an EMV card (e.g. Girocard, Mastercard, Visacard) is more a "question and answer" puzzle - you are asking the card, get a response, analyze the data and ask the next question.
The analyzing part is done here by using the "TLV Utilities" from emvlab.org (https://emvlab.org/tlvutils/).
To get more information about the Application Identifier ("AID"s) see the complete list at: https://www.eftlab.com/knowledge-base/211-emv-aid-rid-pix/.
Here is an example of reading a German Girocard (mine is from a "Volksbank"):
Step 1: ask the card which applications are on the card using the "select PPSE" command. The 2 bytes at the end "90 00" say that the answer is successfull:
selectPpseCommand: 00 A4 04 00 0E 32 50 41 59 2E 53 59 53 2E 44 44 46 30 31 00
selectPpseResponse: 6F 67 84 0E 32 50 41 59 2E 53 59 53 2E 44 44 46 30 31 A5 55 BF 0C 52 61 19 4F 09 A0 00 00 00 59 45 43 01 00 87 01 01 9F 0A 08 00 01 05 01 00 00 00 00 61 1A 4F 0A A0 00 00 03 59 10 10 02 80 01 87 01 01 9F 0A 08 00 01 05 01 00 00 00 00 61 19 4F 09 D2 76 00 00 25 47 41 01 00 87 01 01 9F 0A 08 00 01 05 01 00 00 00 00 90 00
Parsed response:
6F File Control Information (FCI) Template
84 Dedicated File (DF) Name
325041592E5359532E4444463031
A5 File Control Information (FCI) Proprietary Template
BF0C File Control Information (FCI) Issuer Discretionary Data
61 Application Template
4F Application Identifier (AID) – card
A00000005945430100
87 Application Priority Indicator
01
9F0A Unknown tag
0001050100000000
61 Application Template
4F Application Identifier (AID) – card
A0000003591010028001
87 Application Priority Indicator
01
9F0A Unknown tag
0001050100000000
61 Application Template
4F Application Identifier (AID) – card
D27600002547410100
87 Application Priority Indicator
01
9F0A Unknown tag
0001050100000000
There are 3 applications with 3 different AIDs available on the card:
A00000005945430100: Zentraler Kreditausschuss (ZKA) Germany Girocard Electronic Cash
A0000003591010028001: Euro Alliance of Payment Schemes s.c.r.l. – EAPS Belgium Girocard EAPS ZKA (Germany)
D27600002547410100: ZKA Germany Girocard ATM
Step 2: Now I'm reading the first AID using the "Select AID" command - the AID is 18 characters = 9 bytes long:
selectAidCommand: 00 A4 04 00 09 A0 00 00 00 59 45 43 01 00 00
selectAidResponse: 6F 47 84 09 A0 00 00 00 59 45 43 01 00 A5 3A 50 08 67 69 72 6F 63 61 72 64 87 01 01 9F 38 06 9F 02 06 9F 1D 02 5F 2D 04 64 65 65 6E BF 0C 1A 9F 4D 02 19 0A 9F 6E 07 02 80 00 00 30 30 00 9F 0A 08 00 01 05 01 00 00 00 00 90 00
Parsed response:
6F File Control Information (FCI) Template
84 Dedicated File (DF) Name
A00000005945430100
A5 File Control Information (FCI) Proprietary Template
50 Application Label
g i r o c a r d
87 Application Priority Indicator
01
9F38 Processing Options Data Object List (PDOL)
9F02 06
9F1D 02
5F2D Language Preference
d e e n
BF0C File Control Information (FCI) Issuer Discretionary Data
9F4D Log Entry
190A
9F6E Unknown tag
02800000303000
9F0A Unknown tag
0001050100000000
Step 3: get the processing options to read the card details
This is the first "tricky" point as it is not easy how to explain to get the right data for your card/AID. In the above response there is a section for the Processing Options Data Object List (PDOL) the card is requesting and the length of the fields - here we do have 2 fields with a length of 6 and 2 bytes, in total 8 bytes. The 8 bytes are just 8 "x00"s with the "header" 83 08, so the complete length is 10 bytes = x0A:
9F38 Processing Options Data Object List (PDOL)
9F02 06
9F1D 02
A more detailed explanation can be found here: https://stackoverflow.com/a/20810855/8166854
getProcessingOptionsCommand: 80 A8 00 00 0A 83 08 00 00 00 00 00 01 00 00 00
getProcessingOptionsResponse: 77 1E 82 02 19 80 94 18 18 01 01 00 20 01 01 00 20 04 04 00 08 05 05 01 08 07 07 01 08 03 03 01
Parsed response:
77 Response Message Template Format 2
82 Application Interchange Profile
1980
94 Application File Locator (AFL)
18010100 20010100 20040400 08050501 08070701 08030301
The most important part for the next step is the "Application File Locator (AFL)" - we need to read the file system with the data that are coded in these 4 byte blocks.
Step 4: read the records from the card
This is the part where I get lost when trying to read the card. You need to get the SFI and RECORD from the first 3 bytes of an AFL block and run a read record command. The following command reads the 4th sector of the AFL list - the command may work or not with your card and if it works you may get different data from your card.
WARNING: providing the response data to an internet form may reveal data like account number or
credit card number - my response is masked so the account number is not 1111111111:
readRecordCommand: 00 B2 05 0C 00
readRecordResponse: 70 38 5F 24 03 21 12 31 5A 0A 67 26 42 89 11 11 11 11 11 7F 5F 34 01 02 5F 28 02 02 80 9F 07 02 FF C0 9F 0D 05 FC 40 A4 80 00 9F 0E 05 00 10 18 00 00 9F 0F 05 FC 40 A4 98 00 90 00
Parsed response:
70 EMV Proprietary Template
5F24 Application Expiration Date
211231
5A Application Primary Account Number (PAN)
6726428911111111117F
5F34 Application Primary Account Number (PAN) Sequence Number
02
5F28 Issuer Country Code
0280
9F07 Application Usage Control
FFC0
9F0D Issuer Action Code – Default
FC40A48000
9F0E Issuer Action Code – Denial
0010180000
9F0F Issuer Action Code – Online
FC40A49800
I strongly recommend that you use a library for the steps 3 and 4; I'm using
https://github.com/devnied/EMV-NFC-Paycard-Enrollment
for this.
This is just a basic explanation for the first steps but now you get some useful responds from your card - good luck for your next steps.
A complete Android example app for the above mentioned library is here (disclaimer: I'm the author):
https://github.com/AndroidCrypto/Android-EMV-NFC-Paycard-Example
I'm currently working a project with Open Mobile API. Basically, I got this problem when i exchange apdu to the UICC, all my commands converted automatically to the extended logical APDU command (CLA : 0xC1). I'm using Samsung Galaxy S6 Edge during this test with android version : 5.0.2.
APDU > Header [CLA INS P1 P2] 00 70 00 00 194,69 etu MANAGE CHANNEL
< Outgoing data 01
< Return code [SW1 SW2] 90 00
APDU > Header [CLA INS P1 P2] 01 A4 04 00 194,69 etu SELECT
Incoming data A0 00 00 05 59 10 10 FF FF FF FF 89 00 00 01 00
< Outgoing data 6F 1A 84 10 A0 00 00 05 59 10 10 FF FF FF FF 89
00 00 01 00 A5 06 73 00 9F 65 01 FF
< Return code [SW1 SW2] 90 00
APDU > Header [CLA INS P1 P2] C1 E2 91 00 187,69 etu
Incoming data BF 2D 00
< Return code [SW1 SW2] 6D 00
APDU > Header [CLA INS P1 P2] 00 70 80 01 192,69 etu MANAGE CHANNEL
< Return code [SW1 SW2] 90 00
What could be a problem? Who is responsible to change my CLA command to 0xC1? Why the phone change the CLA command to 0xC1?
Note : Based on my application log, I send this 81 E2 91 00 02 BF 2D 00
Thanks for your help.
I transmitted the following APDU command, from an android app, in my android phone,
send: 00 A4 04 00 07 A0 00 00 00 03 10 10 00
to an iPhone 6 through NFC and got the following response,
resp: 6F 39 84 07 A0 00 00 00 03 10 10 A5 2E 9F 38 1B 9F 66 04 9F 02 06 9F 03 06 9F 1A 02 95 05 5F 2A 02 9A 03 9C 01 9F 37 04 9F 4E 14 BF 0C 0D 9F 4D 02 14 01 9F 5A 05 11 08 40 08 40 90 00
Now, I've been trying to decrypt this using various sources, but the confusing part is to understand, whether this is the PKPaymenttoken data (which we receive in apple pay response) or is it just the encrypted card data from the passbook of iPhone 6.
I compared this result with the response that I got from PassKit- framework's-> paymentAuthorizationViewController method's-> payment.token string, both are completely different. So I guess its not the token response for apple pay. My concerns are,
Is this the encrypted card data itself? Can I decrypt it directly to get the card details? (After all, will Apple give out the card details that easily?)
My ultimate requirement is to accept payment through NFC in an Android phone from an iPhone6. So is my APDU request the correct one to obtain card data from iPhone6 (Passbook)?
Any thought is appreciated. Thanks.
I tried with the help of this link
https://github.com/devnied/EMV-NFC-Paycard-Enrollment
It really works. It gives device account number directly from the iPhone. No decryption needed to get this device account number.
How to use this lib
Download the library from this link
Use the code below
IProvider prov = new YourProvider();
// Create parser (true for contactless false otherwise)
EMVParser parser = new EMVParser(prov, true);
// Read card
EMVCard card = parser.readEmvCard();
You will get the card details in card object.
To answer your two major questions
This is just a response for APDU command, if you use the library I've mentioned, you will directly get the card details required for payment via any gateways.
The first answer is also the answer for your second question, you can read the iphone 6 from an android phone using the library. so just two steps Integrate the library -> get the card details -> forward to payment gateway. By this method, you need not send any private keys to the gateways, just send the card details like you do for normal card payment processing.
Is this the encrypted card data itself? Can I decrypt it directly to get the card details?
No and no. As Anand correctly pointed out in their answer, this is the FCI template returned in response to your SELECT (by AID/DF name) command concatenated with the status word 9000 (indicating success).
The FCI template is a TLV (tag-length-value) encoded data structure following basic encoding rules (BER). So your FCI
6F 39 84 07 A0 00 00 00 03 10 10 A5 2E 9F 38 1B 9F 66 04 9F 02 06 9F 03 06 9F 1A 02 95 05 5F 2A 02 9A 03 9C 01 9F 37 04 9F 4E 14 BF 0C 0D 9F 4D 02 14 01 9F 5A 05 11 08 40 08 40
decodes to (see http://www.emvlab.org/tlvutils/):
6F [39] File Control Information (FCI) Template
84 [07] Dedicated File (DF) Name
A0000000031010 (full AID of the application that you just selected)
A5 [2E] File Control Information (FCI) Proprietary Template
9F38 [1B] Processing Options Data Object List (PDOL)
9F66 04
9F02 06
9F03 06
9F1A 02
95 05
5F2A 02
9A 03
9C 01
9F37 04
9F4E 14
BF0C [0D] File Control Information (FCI) Issuer Discretionary Data
9F4D [02] Log Entry
1401 (Transaction log file with at most 1 record is available at SFI 0x14)
9F5A [05] Application Program Identifier (Program ID)
1108400840
My ultimate requirement is to accept payment [...]. So is my APDU request the correct one to obtain card data from iPhone6?
Partially, yes. After application selection, you will need to perform an EMV payment transaction (following the EMV specifications for contactless payment systems, you can get them form http://www.emvco.com/). However, be aware that this is not as easy as getting some "card data". You will need to retrieve some static card data from the contactless "card" (i.e. iPhone). In addition you will also need to let the iPhone generate some dynamic transaction cryptogram/transaction authorization code. You can then use this data to clear the transaction.
Its not encrypted data, it just FCI information
APDU send by you:
00 A4 04 00 07 A0 00 00 00 03 10 10 00.
P1=0x04 means you are selecting MF by DF name and P2=0x00 means returns FCI information.
Your response 6F 39 84 07 A0 00 00 00 03 10 10 A5 2E 9F 38 1B 9F 66 04 9F 02 06 9F 03 06 9F 1A 02 95 05 5F 2A 02 9A 03 9C 01 9F 37 04 9F 4E 14 BF 0C 0D 9F 4D 02 14 01 9F 5A 05 11 08 40 08 40 90 00
Your response description are as follows:
6F->its FCI templates(i.e. set of control parameters and management data).
39->6F tag length, these bytes are 6F tag data 84 07 A0 00 00 00 03 10 10 A5 2E 9F 38 1B 9F 66 04 9F 02 06 9F 03 06 9F 1A 02 95 05 5F 2A 02 9A 03 9C 01 9F 37 04 9F 4E 14 BF 0C 0D 9F 4D 02 14 01 9F 5A 05 11 08 40 08 40 90 00
84 means Tag for DF name
07 is the Lengths
A0 00 00 00 03 10 10 data values i.e. DF name
A5 is the Tag for Proprietary information encoded in BER-TLV
2E is the Length
9F 38 1B 9F 66 04 9F 02 06 9F 03 06 9F 1A 02 95 05 5F 2A 02 9A 03 9C 01 9F 37 04 9F 4E 14 BF 0C 0D 9F 4D 02 14 01 9F 5A 05 11 08 40 08 40 90 00->A5 tag values
I'm still trying to emulate a point of sale (POS) system and complete a transaction with Google wallet.
I've gotten further with great answers on stack overflow.
See Android isoDep.transceive on Generate AC command always returns 6D00 unsupported
Even though every step of the communication from the POS and Google Wallet is successful, I can't get past Google wallet stating
"Status unknown, Check with cashier to see if the payment was successful".
I just need Google wallet to state "Status pending" just like at McDonalds (in the US).
I actually don't care if the whole transaction processes and clears my bank.
I'm new to transaction processing and it seems like I'm missing a fundamental step.
Any ideas would be greatly appreciated.
The following are the successful steps.
Step 1 Select Proximity Payment System Environment (2PAY.SYS.DDF01)
Send = 00 A4 04 00 0E 32 50 41 59 2E 53 59 53 2E 44 44 46 30 31 00
Response = 6f2f 840e 325041592e5359532e4444463031 a51d bf0c1a61184f07a00000 00041010870101500a4d 617374657243617264 9000 (Success)
Step 2 Select Payment Service
Send = 00 A4 04 00 07 A0 00 00 00 04 10 10 00
Response = 6f1e 8407 a0000000041010 a513 500a 4d617374657243617264 870101 9f11 01 01 9000 (Success)
Step 3 Get Processing Options
Send = 80 a8 00 00 02 83 00 00
Response = 770a 8202 0000 9404 08010100 9000 (Success)
Step 4 Read Record
Send = 00 B2 01 0C 00
Response = 70 7c 9f 6c 02
00 01 9f 62 06
00 00 00 00 00
38 9f 63 06 00
00 00 00 03 c6
56 29 42 35 33
39 36 XX XX XX
XX 31 XX XX 39
XX XX XX XX 5e
20 2f 5e 31 34
30 37 31 30 31
34 30 31 30 30
30 30 30 30 30
30 30 30 9f 64
01 04 9f 65 02
00 38 9f 66 02
03 c6 9f 6b 13
53 96 XX XX 1X
X9 XX XX d1 40
71 01 40 10 00
00 00 00 0f 9f
67 01 04 9f 69
0f 9f 6a 04 9f
7e 01 9f 02 06
5f 2a 02 9f 1a
02 9000 (Success)
Step 5 Compute Crytographic Checksum
Send = 80 2A 8E 80 0F 00 00 00 12 00 00 00 00 00 01 00 08 40 08 40 00
Response = 77 0f 9f 61 02 XX XX 9f 60 02 XX XX 9f 36 02 20 fa 9000 (Success)
The "PayPass – M/Chip Transaction Processing" specification states
"After the completion of the COMPUTE CRYPTOGRAPHIC CHECKSUM response, the
PayPass card can be removed from the PayPass reader."
So I assumed POS to Google Wallet communication was done, but Google Wallet seems to need more information.
So I assumed POS to Google Wallet communication was done, but Google Wallet seems to need more information.
Correct. Google Wallet retrieves information about transactions trough the card issuer's online backend system (at least that was the case with pre 2.0 version of GW, but I would assume that's still the case). Thus if you do not perform a real transaction (one that runs through the Master Card network), Google Wallet has no means to retrieve details about the transaction for the online backend.
I am using the following code to read a structured binary file
FileInputStream objIS = new FileInputStream("/sdcard/waverider.usr");
DataInputStream objBR = new DataInputStream(objIS);
objwVer = objBR.readShort();
objwSVer = objBR.readShort();
objNoWaypoints = objBR.readShort();
System.out.println(objwVer);
System.out.println(objwSVer);
System.out.println(objNoWaypoints);
objIS.close();
This produces the result:
512
0
8706
The result I am after is
2
0
546
That is what I get with VB.net using:
objwVer = objBR.ReadInt16
objwSVer = objBR.ReadInt16
objNoWaypoints = objBR.ReadInt16
The binary file is as follow:
02 00 00 00 22 02 00 00 4b a9 c8 ff b2 2d 33 00
00 00 00 00 04 00 00 00 48 6f 6d 65 00 00 00 00
1c 68 53 0d 10 27 00 00 00 00 01 00 7e 8c c8 ff
Am I missing something here
9d 33 33 00 00 00 00 00 06 00 00 00
Your problem is that
your file is written in little endian byte order but your code is expecting big endian byte order.
Your stream is encoded in little-endian and DataInputStream only supports big-endian.
You could use ByteBuffer instead, which allows to parse little-endian formatted stream: http://developer.android.com/reference/java/nio/ByteOrder.html#LITTLE_ENDIAN
try JBBP framework, it is android compatible and its JBBPBitInputStream allows read data in different byte and bit order
new JBBPBitInputStream(in).readInt(JBBPByteOrder.LITTLE_ENDIAN);