我知道iPhone 6不可能读取RFID标签,而且我知道iPhone API只允许使用Apple Pay的NFC,但是是否有可能读取iPhone的NFC芯片,就好像它是RFID标签一样?
也就是说,RFID阅读器能够检索任何类型的被动信息,如芯片的唯一ID或那种性质的东西,通过使用RFID阅读器像Arduino或树莓派?
正如Michael Gillett已经写过的那样,防碰撞标识符(通常用作RFID中的ID)是动态的,并且随着iPhone中安全元素的每次激活而变化。您可以尝试做的是访问安全元件上的EMV支付卡("令牌化"信用卡)。该信用卡至少包含一个PAN(令牌化的主帐号),可能还包含用于签名验证的公钥。该信息应该是静态的(即使在标记化的情况下),因此,可以用来识别设备。
查看非接触式支付系统的EMV规范(http://emvco.com),以了解如何访问支付应用程序。基本上你会做如下的事情:
- 选择PPSE
- 在select response中查找付款申请的AID
- SELECT payment application (by AID)
- 读取包含PAN/ICC公钥的记录(文件+记录号)
您需要一些非接触式智能卡读卡器来发送必要的APDU命令。仅仅通过防碰撞来获取ID的RFID读取器是不够的。然而,对于Arduino和RPI,都有这样的读取器(例如NFC屏蔽)。
当你按住大拇指尝试Apple Pay支付时,似乎可以检测到来自iPhone的信号。但是,每次按下它都会发送一个不同的ID号。这使得几乎不可能做任何与安全相关的事情。
这是一个让它工作的人的视频。https://www.youtube.com/watch?v=fhpMVFte2mE
因为iPhone每次都会发出不同的NFC标签#。阅读器被设置为使用任何标签,这对于像上面视频中的锁这样的安全应用程序来说是不好的。
使用PN532板。简化工作与基于Arduino的主机,使用这个库。
定义连接。
#include <Arduino.h>
#include <SPI.h>
#include <PN532_SPI.h>
#include <PN532.h>
PN532_SPI intfc(SPI,5);
PN532 nfc(intfc);
检查卡/电话是否在:
success = nfc.inListPassiveTarget();
if (success) { ...
定义通信缓冲区:
uint8_t apdubuffer[255] = {};
uint8_t apdulen;
并发送SELECT PPSE命令:
apdulen = 255;
success2 = sendAPDU(0x00, 0xA4, 0x04, 0x00, "2PAY.SYS.DDF01", 0x00, &apdubuffer[0], &apdulen);
如果成功,则:
//fromHEX("A0000000031010") - VISA
//fromHEX("A0000000041010") - MC
success2 = sendAPDU(0x00, 0xA4, 0x04, 0x00, fromHEX("A0000000031010"), 0x00, &apdubuffer[0], &apdulen);
,你可以很好地读取卡的内部文件(SFI/RECs),例如:
success2 = sendAPDU(0x00, 0xB2, rec_num, (sfi_num << 3)+4, 0x00, &apdubuffer[0], &apdulen);
最好找到PAN/ICC公钥,事实上,作为唯一的卡片,但是在PAN/ICC之前会有很多字节,我认为非常独特,足以执行身份验证
毕竟,您需要这样的重载:
bool sendAPDU(byte cla, byte ins, byte p1, byte p2, String aid, byte le, uint8_t *response, uint8_t *resp_len)
{
uint8_t cmdbuf[255];
memset(&cmdbuf[0],0,255);
cmdbuf[0] = cla;
cmdbuf[1] = ins;
cmdbuf[2] = p1;
cmdbuf[3] = p2;
cmdbuf[4] = aid.length();
int i;
for (i=0;i<aid.length();i++)
cmdbuf[5+i] = aid[i];
cmdbuf[6+i] = le;
//printbuf((char*)&cmdbuf[0],5+aid.length());
return nfc.inDataExchange(&cmdbuf[0], 5+aid.length(), response, resp_len);
}
bool sendAPDU(byte cla, byte ins, byte p1, byte p2, uint8_t* aid, byte le, uint8_t *response, uint8_t *resp_len)
{
uint8_t cmdbuf[255];
memset(&cmdbuf[0],0,255);
cmdbuf[0] = cla;
cmdbuf[1] = ins;
cmdbuf[2] = p1;
cmdbuf[3] = p2;
cmdbuf[4] = aid[0];
int i;
for (i=0;i<aid[0];i++)
cmdbuf[5+i] = aid[i+1];
cmdbuf[6+i] = le;
//printbuf((char*)&cmdbuf[0],5+cmdbuf[4]);
return nfc.inDataExchange(&cmdbuf[0], 5+cmdbuf[4], response, resp_len);
}
bool sendAPDU(byte cla, byte ins, byte p1, byte p2, byte le, uint8_t *response, uint8_t *resp_len)
{
uint8_t cmdbuf[255];
memset(&cmdbuf[0],0,255);
cmdbuf[0] = cla;
cmdbuf[1] = ins;
cmdbuf[2] = p1;
cmdbuf[3] = p2;
cmdbuf[4] = le;
//printbuf((char*)&cmdbuf[0],5);
return nfc.inDataExchange(&cmdbuf[0], 5, response, resp_len);
}
和this too:
/*
Funny, non-C approach to return array from a function
Returns ptr to global static buf...
Just to improve readability of sendAPDU() function...
Not really needed in real app,
*/
uint8_t fromHexBuf[255];
uint8_t* fromHEX(String hexs) {
int i = hexs.length()/2;
fromHexBuf[0] = i;
int x=0;
while (i) {
char buf[3];
char *tmp;
buf[0] = hexs[2*x];
buf[1] = hexs[2*x+1];
buf[2] = 0;
uint8_t v = strtol(&buf[0], &tmp, 16);
//Serial.printf("-> %s = %xn", buf, v);
fromHexBuf[x+1] = v;
x=x+1;
i--;
}
return &fromHexBuf[0];
}