使用密码保护读写NFC标签

12

我需要把文本数据写入/读取一个NFC标签。我希望读/写操作的工作方式如下:

  1. 第一次写操作,我应该能够设置密码。
  2. 下一次任何人尝试读取或写入时,如果他有密码,则他应该能够进行读/写操作。
  3. 没有其他应用程序能够修改我的标签,除非使用我在第1步设置的密码。

我原本想到的另一种方法是将加密数据写入标签,并且在写入完成后将标签设置为只读。我能够做到这一点。但现在我意识到,将标签设置为只读并不是很高效。

我在互联网上搜索了很多,但仍未找到任何可靠的文章或指南。因此,如果有人已经实现了NFC标签的密码保护,请给我指导。

3个回答

20
  • Android provides a high-level API for reading and writing NFC tags (through the NDEF format).
  • For more advanced features, such as password protection or mutual authentication, you need to use low-level APIs that are specific to the tag type and manufacturer.
  • Not all Android devices support all types of NFC tags or all features of a given tag.
  • NFC标签(实际上是实现了五种NFC Forum标签操作规范之一的NFC Forum标签)是一种简单的数据存储器,没有任何安全机制(除了将内存锁定为只读)。这些标签旨在以NDEF格式存储可自由阅读的数据。未标准化任何针对标签内容读取(或将标签内容复制到其他标签)的身份验证或保护机制。

    然而,一些现有的标签产品实现了超出NFC Forum规定的额外安全功能。

    最简单的机制是短“密码”(通常是32位值)。对于身份验证,此密码以明文形式传输到标签,并且标签确认/拒绝身份验证。(请注意,通过NFC的明文传输意味着任何窃听通信的人都可以获得密码。)支持此类型密码保护的某些标签可以使用身份验证在不访问、只读访问和读/写访问之间切换定义的内存区域。

    • 实现此类型密码验证的产品包括Infineon SLE66R01P、NXP MIFARE Ultralight EV1和NXP NTAG21x等。

    更复杂的方法是使用共享密钥进行相互挑战-响应身份验证。与简单的明文密码相比,这意味着被动窃听者无法发现共享的密钥。与密码类似,大多数现有标签产品中的身份验证状态可以用于在不访问、只读访问和读/写访问之间切换定义的内存区域。但是,并非所有标签都会将内存访问和身份验证阶段加密绑定在一起。

    • 实现三次相互身份验证的产品包括NXP MIFARE Classic*、NXP MIFARE Ultralight C、NXP MIFARE DESFire(EV1)、Sony FeliCa卡等。

      *)请注意,自2008年以来,MIFARE Classic 的专有身份验证和加密协议已知存在漏洞。此外,MIFARE Classic 仅受支持具有 NXP NFC 芯片组的 Android 设备。

    在Android上实现任何形式的身份验证时,您应该注意以下事项:

    1. Android提供了高级API用于读写NFC标签(通过NDEF格式)。
    2. 对于更高级的功能,例如密码保护或相互身份验证,您需要使用特定于标签类型和制造商的低级API。
    3. 并非所有Android设备都支持所有类型的NFC标签或给定标签的所有功能。
  • 如果您仍希望通过NDEF消息(自定义记录或Android应用程序记录)从自动启动您的应用程序中受益,则需要具有包含该NDEF消息的可自由读取的存储器区域。由于密码保护/身份验证不属于NFC Forum规范的一部分,因此Android本身无法对标签进行身份验证(Android也没有正确的密钥/密码)。因此,NDEF存储器区域(对于具有扁平线性可寻址存储器的标签,通常是标签存储器的前N个块)必须在没有身份验证的情况下可读。

  • 即使您不在应用程序清单中使用NFC过滤器,只使用前台调度系统(或读卡器模式API),您仍可能希望使用NDEF来发现/过滤您自己的标签。

  • 您不能使用NDEF抽象层(即Ndef/ NdefFormatable类)访问受保护的存储器区域。相反,您需要使用标签技术类之一(NfcA、...、IsoDep)交换标签平台特定的低级命令。还不要尝试混合使用多个标签类别(例如,使用NfcA发送身份验证命令,然后使用Ndef读取数据)。虽然这在某些设备上有效,但大多数设备在切换这些通信对象时会重置与标签的通信。

  • 一些Android设备(主要是Android 5之前)存在有关标签存在检查机制的已知问题,可能会干扰身份验证(即存在检查可能会在身份验证命令之间发送命令,导致身份验证失败)。使用读卡器模式API可以克服此问题。

  • 最后,请注意,如果您将密码/身份验证密钥存储在应用程序中,攻击者可以轻松地反向工程化您的应用程序以获取密钥。


  • 感谢您分享如此棒的内容,是否有关于如何与已加密标签进行 Android 通信的教程? - Shawn

    3
    一些标签,例如MIFARE DESFire,原生支持密码/加密,可重现此功能的更常见的标签(Topaz/MIFARE Ultralight等)在本质上是不可能的,因为NFC标签没有内置防止数据被复制的保护(按设计而来)。您可以在编码之前对数据进行加密,但这需要工具了解加密方法(例如独立的应用程序,与Android操作系统分开)。便宜的标签只能永久设为只读模式。
    换句话说,大多数 NFC 标签都不能支持您想要实现的目标,但存在一些更昂贵的标签,支持更大量的数据和基于密码的加密等工具。
    由于 MIFARE DESFIRE 遵守 ISO 14443-4 规范,如果您使用 Android,则可以使用 IsoDep 方法。有关如何读取/写入密码等详细信息,请参见相关文章:How well does the Android NFC API support Mifare Desfire?

    0

    我目前正在从事基于NFC的预付费充值计量项目。我直接来回答你到目前为止所问的问题。密码保护功能适用于许多NFC标签,如Mifare经典系列、Ultralight系列、NTag21x系列。

    以下是您的问题的答案:

    1. 如何设置密码?
      请参考相应数据表,然后研究存储器组织。之后找到您想要写入密码的页面或地址。例如对于Mifare经典卡,扇区尾块是密码密钥块。因此,只需将密码写入该块即可。保持正确的逻辑以编写密码,否则卡片可能会被锁定。
    2. 无论您写入什么密码,都无法读取。因此,只有知道该密钥的人才有权访问该标签。
    3. 您可以使用NFC访问条件将整个标签存储器配置为读写。

    您需要做的就是参考数据表。


    我猜这是错误的。据我所知,密码只与“写入权限”有关,这意味着即使您不知道其密码,仍然可以读取数据。 - c-an
    @c-an 这不是真的,也就是说,护照确实有一种密码读保护,你需要解析一些数据才能读取标签/芯片。 - Cyber
    @Cyber,好的。但是解析听起来好像还是可以读取的。就像制作哈希一样。那么,你如何实现它? - c-an
    1
    @c-an,你可以在这里看一下,这个扫描仪不是最稳定的,但仍然很好地展示了如何解析必要的“哈希”以访问电子护照数据:https://github.com/rgex/bondi-androidpassport-reader - Cyber

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接