3
votes

i have some issues with reading the IBAN number from the german CashCards (also known as Geldkarte). I can communicate with my card, and i get some informations from it. but i don`t know which commandApdu i must send to the card, to get the IBAN number...

The application runs on Java 7 and i use the java.smartcardio api Protocoll is T=1

my commandApdu to get the date looks like this:

byte[] commandBytes = new byte[]{0x00, (byte)0xa4, 0x04, 0x00, 0x07, (byte)0xa0, 0x00, 0x00, 0x00,0x04, 0x30, 0x60, 0x00};

the information i get is:

6F 32 84 07 A0 00 00 00 04 30 60 A5 27 50 07 4D 61 65 73 74 72 6F 87 01 03 9F 38 09 9F 33 02 9F 35 01 9F 40 01 5F 2D 04 64 65 65 6E BF 0C 05 9F 4D 02 19 0A 

Can anyone tell me the correct apdu for getting the IBAN number?

i am sorry if i forgott some information needed, but this is my first question in this board :-)

3

3 Answers

1
votes

Okay so the card has sent back this:

6F328407A0000000043060A52750074D61657374726F8701039F38099F33029F35019F40015F2D046465656EBF0C059F4D02190A

Which translates to:

6F File Control Information (FCI) Template
    84 Dedicated File (DF) Name
        A0000000043060
    A5 File Control Information (FCI) Proprietary Template
        50 Application Label
            M a e s t r o
        87 Application Priority Indicator
            03
        9F38 Processing Options Data Object List (PDOL)
            9F33029F35019F4001
        5F2D Language Preference
            d e e n
        BF0C File Control Information (FCI) Issuer Discretionary Data
            9F4D Log Entry
                190A

So now you've selected the application you'll want to send a series of 'Read Record' commands to it to get the data out of it like (Card number, expiry date, card holder name, IBAN (if it's in there, haven't seen it before)). The structure of the 'Read Record' command can be found in EMV Book 3 however here's some rough psuedocode as to what your Read Record loop should look like. Off the top of my head I usually set NUM_SFIS to 5 and NUM_RECORDS to 16 as there's not usually anything past these points.

for (int sfiNum = 1; sfiNum <= NUM_SFIS; sfiNum++) 
{ 
    for (int rec = 1; rec <= NUM_RECORDS; rec++) 
    {
          byte[] response = tag.transceive(new byte[]{0x00,(byte)0xB2 (byte)rec, (byte)((byte)(sfiNum << 3) | 4), 0x00});
    }
}
1
votes

i solved my problem after a long time this way: At first send a command to the card, to select the aid (application identifier):

private static byte[] aidWithPossibleIban = new byte[] { 0x00, (byte) 0xa4,
            0x04, 0x00, 0x09, (byte) 0xa0, 0x00, 0x00, 0x00, 0x59, 0x45, 0x43,
            0x01, 0x00, 0x00 };

then i hat to raise the security-level:

private static byte[] cmdRaiseSecurityLevel = new byte[] { 0x00, 0x22,
            (byte) 0xf3, 0x02 };

last thing to do was to read the record:

private static byte[] readSelectedRecord = new byte[] { 0x00, (byte) 0xb2,
            0x01, (byte) 0xa4, 0x00 };

regards Andreas

1
votes

I would like to add, the IBAN returning from the card is not straightforward.

The IBAN returned is that of the main Bank, and then the account number from the card holder in other record. Therefore one must come out with the right IBAN through code as the check digit has to be calculated as seen here

Since in records we find Country Code (DE), Bankleitzahl BLZ (8 Digits) and Account Number (10 digits), Check Digit can be calculated through

 public string ReturnIBAN(string lkz, string blz, string kntnr, bool groupedReturn = true)
    {
        string bban = string.Empty;

        lkz = lkz.ToUpper();
        switch (lkz)
        {
            case "AT":
                {
                    bban = blz.PadLeft(5, '0') + kntnr.PadLeft(11, '0');
                }
                break;
            case "DE":
                {
                    bban = blz.PadLeft(8, '0') + kntnr.PadLeft(10, '0');
                }
                break;
            case "CH":
                {
                    bban = blz.PadLeft(5, '0') + kntnr.PadLeft(12, '0');
                }
                break;
        }
        string sum = bban + lkz.Aggregate("", (current, c) => current + (c - 55).ToString()) + "00";

        var d = decimal.Parse(sum);
        var checksum = 98 - (d % 97);
        string iban = lkz + checksum.ToString().PadLeft(2, '0') + bban;
        return groupedReturn ? iban.Select((c, i) => (i % 4 == 3) ? c + " " : c + "").Aggregate("", (current, c) => current + c) : iban;
    }

Source (In German): here