iOS:使用Grabba读取非接触式VISA智能卡数据

时间:2018-07-03 12:33:19

标签: ios credit-card apdu contactless-smartcard emv

我有一个Grabba智能卡读卡器。我正在尝试使用APDU命令获取卡信息。我已经阅读了很多有关EMV标准和相关的ISO 7816-4标准的信息,但是我无法成功执行简单的select命令。这是一些细节:

我已经成功为我的VISA卡供电并获得了其属性:

NSError *error = nil;
GRGrabbaSmartcardSession *session = [GRGrabba.sharedGrabba.smartcard startSession:&error];
NSLog(@"EMV : smartCardInsertedEvent : Attribute : %@", [session getATR]);

结果:3b690000 8072a445 6400ff00 10

当我在here上解析此属性时,会获得我的卡的以下信息:

Attribute parser result

我的非接触式卡是来自土耳其的Akbank的信用卡,但在this list中被列为来自土耳其的Denizbank卡。

现在我正打算在卡上运行以下选择命令:

NSError *error = nil;
GRGrabbaSmartcardSession *session = [GRGrabba.sharedGrabba.smartcard startSession:&error];
NSLog(@"EMV : smartCardInsertedEvent : Attribute : %@", [session getATR]);
session.protocol = 1;
uint8_t aid[] = {'2', 'P', 'A', 'Y', '.', 'S', 'Y', 'S', '.', 'D', 'D', 'F', '0', '1'};
NSData *data = [NSData dataWithBytes:aid length:sizeof(aid)];
NSError *err = nil;
GRGrabbaCommandAPDU *apduCMD =
        [[GRGrabbaCommandAPDU alloc]
                initWithCLA:0x00
                        INS:0xA4
                         P1:0x04
                         P2:0x00
                       Data:data
                         Le:0x00
                      Error:&err];

GRGrabbaResponseAPDU *response = [[GRGrabbaResponseAPDU alloc] initWithData:nil SW1:0 SW2:0];
BOOL success = [session exchangeAPDUCommand:apduCMD withResponse:response error:&error];

if (!success) {
    NSLog(@"EMV : smartCardInsertedEvent : ERROR: Could not read ADF");
    return;
}

但是由于无法读取ADF错误而失败。谁能告诉我我在做什么错?

更新:

我尝试了以下组合,但仍然无法成功运行select命令:

PROTOCOL DATA           CLA     LE   STATUS
0        1PAY.SYS.DDF01 0x00    -    unrecognised SW in response: SW1 = 61, SW2 = 52
0        1PAY.SYS.DDF01 0x00    0x00 Smartcard protocol error.
0        2PAY.SYS.DDF01 0x00    -    unrecognised SW in response: SW1 = 61, SW2 = 66
0        2PAY.SYS.DDF01 0x00    0x00 Smartcard protocol error.
0        1PAY.SYS.DDF01 0x80    -    card returned Incorrect application CLA - SW1 = 6E, SW2 = 00
0        1PAY.SYS.DDF01 0x80    0x00 card returned Incorrect application CLA - SW1 = 6E, SW2 = 00
0        2PAY.SYS.DDF01 0x80    -    card returned Incorrect application CLA - SW1 = 6E, SW2 = 00
0        2PAY.SYS.DDF01 0x80    0x00 card returned Incorrect application CLA - SW1 = 6E, SW2 = 00
1        1PAY.SYS.DDF01 0x00    -    unrecognised SW in response: SW1 = 00, SW2 = 00
1        1PAY.SYS.DDF01 0x00    0x00 unrecognised SW in response: SW1 = 00, SW2 = 00
1        2PAY.SYS.DDF01 0x00    -    unrecognised SW in response: SW1 = 00, SW2 = 00
1        2PAY.SYS.DDF01 0x00    0x00 unrecognised SW in response: SW1 = 00, SW2 = 00
1        1PAY.SYS.DDF01 0x80    -    unrecognised SW in response: SW1 = 00, SW2 = 00 
1        1PAY.SYS.DDF01 0x80    0x00 unrecognised SW in response: SW1 = 00, SW2 = 00
1        2PAY.SYS.DDF01 0x80    -    unrecognised SW in response: SW1 = 00, SW2 = 00
1        2PAY.SYS.DDF01 0x80    0x00 unrecognised SW in response: SW1 = 00, SW2 = 00

2 个答案:

答案 0 :(得分:2)

以下两个结果看起来很好:

PROTOCOL DATA           CLA     LE   STATUS
0        1PAY.SYS.DDF01 0x00    -    unrecognised SW in response: SW1 = 61, SW2 = 52
0        2PAY.SYS.DDF01 0x00    -    unrecognised SW in response: SW1 = 61, SW2 = 66

状态字61xx表示等待的响应数据有xx个字节,您需要发出GET RESPONSE命令来获取实际的响应数据。

因此,您需要将协议设置为0,

session.protocol = 0;

发出SELECT命令(用于2PAY.SYS.DDF01)

uint8_t aid[] = {'2', 'P', 'A', 'Y', '.', 'S', 'Y', 'S', '.', 'D', 'D', 'F', '0', '1'};
NSData *data = [NSData dataWithBytes:aid length:sizeof(aid)];
NSError *err = nil;
GRGrabbaCommandAPDU *apduCMD =
        [[GRGrabbaCommandAPDU alloc]
                initWithCLA:0x00
                        INS:0xA4
                         P1:0x04
                         P2:0x00
                       Data:data
                      Error:&err];
GRGrabbaResponseAPDU *response = [[GRGrabbaResponseAPDU alloc] initWithData:nil SW1:0 SW2:0];
BOOL success = [session exchangeAPDUCommand:apduCMD withResponse:response error:&error];

并评估SW1。如果SW1等于0x90,则您已设置并且已经具有响应数据。如果它等于0x61,那么您将需要发出GET RESPONSE命令,并将Le设置为SW2指示的长度:

if (response.sw1 == 0x61) {
    GRGrabbaCommandAPDU *apduGETRESPCMD =
            [[GRGrabbaCommandAPDU alloc]
                    initWithCLA:0x00
                            INS:0xC0
                             P1:0x00
                             P2:0x00
                             Le:response.sw2
                      Error:&err];
    BOOL success = [session exchangeAPDUCommand:apduGETRESPCMD withResponse:response error:&error];
}

注意:我对上述代码中的语法和字段名称不太有信心...一旦您开始使用,便可以对其进行修复。

答案 1 :(得分:1)

我没有使用过Grabba,也不确定您是在接触式还是非接触式中使用它,但是由于您正在处理T = 0卡,因此您可以尝试在不带Le的情况下发出命令。