是否可以像读取 RFID 标签一样读取 iPhone 的 NFC 芯片?
Is it possible to read the iPhone's NFC chip as if it were an RFID tag?
我知道 iPhone 6 无法读取 RFID 标签,而且我知道 iPhone API 只允许使用 NFC 进行 Apple Pay,但是它是吗?可以像读取 RFID 标签一样读取 iPhone 的 NFC 芯片吗?
也就是说,通过将 RFID reader 与 Arduino 等设备一起使用,RFID reader 是否能够检索任何类型的被动信息,例如芯片的唯一 ID 或类似性质的信息或 Raspberry Pi?
当您按住拇指尝试使用 Apple Pay 付款时,似乎可以检测到来自 iPhone 的信号。但是,它会在每次按下时发出不同的 ID 号。这使得几乎不可能做任何与安全相关的事情。
这是一段视频,介绍了它的工作原理。 https://www.youtube.com/watch?v=fhpMVFte2mE
because the iPhone spits out different NFC tag #'s each time. the reader is set to use any tag this is not good for secure applications like locks like in the video above.
正如已经写的那样,防冲突标识符(在RFID中经常用作the ID),是动态的,每次激活 iPhone 中的安全元素时都会发生变化。您可以尝试访问安全元件上的 EMV 支付卡("tokenized" 信用卡)。该信用卡至少包含一个 PAN(标记化主帐号),可能还包含用于签名验证的 public 密钥。该信息应该是静态的(即使在标记化的情况下),因此可用于识别设备。
查看非接触式支付系统 (http://emvco.com) 的 EMV 规范,了解如何访问支付应用程序。基本上你会做类似下面的事情:
- SELECT PPSE
- 在select响应中查找支付申请的AID
- SELECT支付申请(通过AID)
- READ RECORD(文件 + 记录编号)包含 PAN/ICC public 键的记录
你需要一些非接触式智能卡 reader 来发送必要的 APDU 命令。仅执行防冲突以获取 ID 的 RFID reader 是不够的。然而,对于 Arduino 和 RPI,都有这样的 readers(例如 NFC shield)。
使用PN532板。使用基于 Arduino 的主机简化工作,使用 this library。
定义连接。
#include <Arduino.h>
#include <SPI.h>
#include <PN532_SPI.h>
#include <PN532.h>
PN532_SPI intfc(SPI,5);
PN532 nfc(intfc);
检查 card/phone 是否存在:
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 public key,确实是卡独有的,但是在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);
}
还有这个:
/*
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 = %x\n", buf, v);
fromHexBuf[x+1] = v;
x=x+1;
i--;
}
return &fromHexBuf[0];
}
我知道 iPhone 6 无法读取 RFID 标签,而且我知道 iPhone API 只允许使用 NFC 进行 Apple Pay,但是它是吗?可以像读取 RFID 标签一样读取 iPhone 的 NFC 芯片吗?
也就是说,通过将 RFID reader 与 Arduino 等设备一起使用,RFID reader 是否能够检索任何类型的被动信息,例如芯片的唯一 ID 或类似性质的信息或 Raspberry Pi?
当您按住拇指尝试使用 Apple Pay 付款时,似乎可以检测到来自 iPhone 的信号。但是,它会在每次按下时发出不同的 ID 号。这使得几乎不可能做任何与安全相关的事情。
这是一段视频,介绍了它的工作原理。 https://www.youtube.com/watch?v=fhpMVFte2mE
because the iPhone spits out different NFC tag #'s each time. the reader is set to use any tag this is not good for secure applications like locks like in the video above.
正如
查看非接触式支付系统 (http://emvco.com) 的 EMV 规范,了解如何访问支付应用程序。基本上你会做类似下面的事情:
- SELECT PPSE
- 在select响应中查找支付申请的AID
- SELECT支付申请(通过AID)
- READ RECORD(文件 + 记录编号)包含 PAN/ICC public 键的记录
你需要一些非接触式智能卡 reader 来发送必要的 APDU 命令。仅执行防冲突以获取 ID 的 RFID reader 是不够的。然而,对于 Arduino 和 RPI,都有这样的 readers(例如 NFC shield)。
使用PN532板。使用基于 Arduino 的主机简化工作,使用 this library。
定义连接。
#include <Arduino.h>
#include <SPI.h>
#include <PN532_SPI.h>
#include <PN532.h>
PN532_SPI intfc(SPI,5);
PN532 nfc(intfc);
检查 card/phone 是否存在:
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 public key,确实是卡独有的,但是在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);
}
还有这个:
/*
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 = %x\n", buf, v);
fromHexBuf[x+1] = v;
x=x+1;
i--;
}
return &fromHexBuf[0];
}