使用 AVR-IoT WG 的安全物联网 RFID 门禁系统

AVR-IoT WG 开发板

智能、安全、互联。这是Microchip通过其AVR-IoT WG开发板(型号AC164160)实现的典型物联网解决方案的三个要素。该开发板以ATmega4808 MCU作为智能应用控制器,ATWINC1510 Wi-Fi模块用于连接云服务,以及ATECC608A CryptoAuthentication安全 元件;具备实现小型、经济且可扩展的物联网节点所需的所有组件。我们决定充分利用这些组件,设计一个以AVR-IoT WG为中心的RFID门禁系统。由于该开发板包含一个mikroBUS插座,因此使用了MikroElectronika的RFID click板来提供RFID读取功能。使用SPI接口与此扩展板通信,而不是USART接口,从而允许将mikroBUS插座上的一个USART信号用作简单锁式电磁铁的控制信号。

AVR-IoT WG上预装的演示应用程序可通过基于网络的Atmel START工具获取。只需访问https://start.atmel.com并在项目列表中搜索“avriot”。该项目名为“AVR IoT WG Sensor Node”。该演示项目仅从板载温度传感器和光传感器进行定期测量,并在每次测量后将收集的数据发送到Google Cloud进行进一步处理和/或可视化。通过将此项目导入Atmel Studio 7.0,我们能够修改源代码以定期检查RFID标签的存在,如果存在,则尝试读取其UID。这些UID可以安全地发送到Google Cloud,并与具有适当授权的用户数据库进行比较。根据比较结果,Google Cloud可以向节点发送响应,提供比较结果。如果UID与批准列表中的匹配,则可以启动电磁铁,解锁系统。

硬件组件

对于感兴趣的人,以下是开发板上主要硬件组件的列表。

  • ATmega4808
    • 8位AVR微控制器
    • 20 MHz
    • 48 KB闪存,6 KB SRAM和265 B集成EEPROM
    • 工作电压:1.8V – 5.5V
    • 32引脚封装
  • WINC1510
    • 低功耗 Wi-Fi 模块 (802.11 b/g/n)
    • SPI 接口
    • 片上网络栈以卸载 MCU
      • 集成网络 IP 栈以最小化主机 CPU 需求
      • 网络功能包括 TCP、UDP、DHCP、ARP、HTTP、TLS 和 DNS
      • Wi-Fi 和 TLS 安全的硬件加速器以改善连接时间
    • 小尺寸 (21.7 x 14.7 x 2.1 毫米)
  • ATECC608A
    • 加密认证设备
    • 带有基于硬件的安全密钥存储的加密协处理器
    • 硬件支持 ECDSA、ECDH、SHA-256、AES-128
    • 唯一的 72 位序列号
  • MCP9808
    • ±0.5°C (±1°C) 最大精度的数字温度传感器
    • -20°C 至 100°C (-40°C 至 125°C) 的感应范围
    • 用户可编程的温度限制和警报
  • TEMT6000
    • 环境光传感器
    • 适应人眼响应
  • 电池连接器
  • mikroBUS 连接器
    • 本身不是组件,但仍然是一个出色的功能。以下是引脚图:

接口

AVR-IoT WG 包含一个 Nano 嵌入式调试器 (nEDBG) IC,通过提供大容量存储接口、串行端口接口和通过 USB 的 UPDI 接口来简化用户的接口操作。大容量存储接口允许开发板在主机 PC 上显示为可移动存储设备。这个标记为“CURIOSITY”的驱动器包含演示网页以及提供有关开发板信息的多个文件,例如序列号、固件版本和公钥。用户还可以使用“拖放(drag and drop)”功能更改 Wi-Fi 设置并重新编程开发板。串行命令行界面允许用户通过终端应用程序(如 PuTTY 或 TeraTerm)与开发板通信。使用可用的命令,用户可以重置开发板、更改 Wi-Fi 凭据、获取诊断信息等。最后,UPDI(统一编程和调试接口)允许 Atmel Studio 7.0 在开发板插入 PC 后识别它。然后,用户可以从 Atmel START 下载并打开演示应用程序,进行任何更改并重新编程开发板。


a) 大容量存储设备


b) 串行命令行界面


c) Atmel Studio 7.0

1 与 AVR-IoT WG 接口的各种方式

有关如何使用这些接口的更多详细信息,请参阅用户指南

安全连接到 Google Cloud

大多数人可能想知道,ATECC608A 安全元件究竟做了什么来使开发板“安全”?嗯,它本身并不能!在这个参考设计中,实际上是 ATECC608A 和 WINC1510 Wi-Fi 模块的组合实现了与 Google Cloud 的安全连接。要理解这一点,必须熟悉与安全系统相关的元素;机密性(Confidentiality)、完整性(Integrity)和真实性(Authenticity)。永远记住:CIA

由于 WINC1510 使用 TLS 与 Google Cloud 的 MQTT 服务器通信(这是 Google 要求的),所有发送到和从 Google Cloud 接收的消息都是加密的,因此无法被窃听的第三方读取。因此,WINC1510 模块在应用程序中实现了机密性。TLS 还通过对消息进行哈希处理来执行完整性检查,在发送前和接收后进行。哈希意味着消息被用作单向函数的输入,该函数生成一个称为摘要的值。仅凭这个摘要,几乎不可能确定原始消息是什么。然后,这个摘要附加在消息的末尾,因此,如果消息在传输和接收之间以任何方式被修改,修改后的消息的摘要将与原始消息的摘要不匹配。

剩下的就是身份验证,这正是ATECC608A发挥作用的地方。Google Cloud需要确保与其通信的设备确实是我们的板子,而不是其他伪装成我们板子的设备。因此,我们需要在开始发送和接收数据之前提供身份证明。我们通过使用ATECC608A生成的私钥/公钥对来实现这一点。一旦ATECC608A生成了这个密钥对,私钥就会被锁定在设备中,因此它永远不会被黑客攻击或窃取。这使得私钥比传统密码更适合用于身份验证。然而,问题仍然存在:当私钥被锁定在安全内存中,甚至我们无法读取它时,我们如何使用它来证明我们的身份?

答案是使用公钥!私钥/公钥对背后的想法非常简单:如果使用公钥加密某些数据,那么只有私钥可以解密它,反之亦然。因此,通过在注册设备时向Google Cloud提供我们的公钥,它可以尝试解密由ATECC608A使用我们的私钥加密的数据。如果它能够成功解密数据,那么Google Cloud就知道数据来自我们的设备,因为只有它包含与公钥对应的私钥。

让我们更详细地看一下这一点,以及AVR-IoT WG演示项目如何连接到Google Cloud的MQTT服务器。当MQTT客户端构建连接数据包时,它必须包含客户端ID、用户名和密码。然而,在Google Cloud中,用户名被忽略,因此可以为空。客户端ID采用以下形式:projects/{project-id}/locations/{cloud-region}/registries/{registry-id}/devices/{device-id} 。例如,在下面设置的示例项目中,客户端ID将是projects/avr-iot-rfid-ac/locations/us-central1/registries/rfid_readers/devices/d012313D1E521D10BFE。密码是一个JSON Web Token(JWT),其形式如下:{Base64url encoded header}.{Base64url encoded payload}.{Base64url encoded signature} 。头部仅包含两个字段,指示签名算法和令牌类型。有效载荷包含3个字段:令牌创建时的时间戳(“iat”)、令牌过期时的时间戳(“exp”)和云项目ID(“aud”)。签名是通过将base64编码的头部和有效载荷发送到ATECC608A来计算的,在那里它们将使用私钥进行加密。生成的加密数据随后进行base64编码,并用于完成JWT,如图2所示。


2 如何使用ATECC608A安全元件创建用于设备身份验证的JWT

一旦Google Cloud接收到这个密码,它基本上会反向执行这个过程,只是它使用公钥来解密签名。如果解密结果是一个与头部和有效载荷部分匹配的字节数组,那么设备被认为是真实的。还要注意的是,JWT是有时间限制的,即仅在签发时间和过期时间之间有效,以防止重放攻击。这就是为什么我放心与你分享这个JWT。它已于2019年1月4日14:27:46 CST(Unix时间戳为1546633666)过期,不再有效。

RFID Click

Mikroelectronika的RFID click板(MIKROE-1434)采用了STMicroelectronics的CR95HF 13.56MHz非接触式收发器,并配备了模拟前端和天线。默认的通信接口是mikroBUS SPI,但通过简单的焊桥重新配置,USART线路也可用。它运行在3.3V电压下,并支持以下协议:

  • ISO/IEC 14443 A型和B型标签
  • ISO/IEC 15693标签
  • ISO/IEC 18000-3M1标签
  • NFC论坛标签:类型1、2、3和4
  • ST SRI和LRI标签
  • ST双接口EEPROM

遗憾的是,在撰写本文时,Atmel START不支持此click板。因此,添加到应用程序中的CR95HF库文件源自ST的STSW-STM32031示例项目,该项目演示了如何使用STM3210B-EVAL板通过ISO/IEC 15693标准与CR95HF进行接口。为了节省时间,没有将整个库移植到ATmega上,而是从示例项目中复制了初始化模块和读取标签UID所需的函数。图3显示了项目中包含的库文件。


3 :添加 到项目解决方案中的修改后的CR95HF库文件

该项目使用这些廉价的RFID标签进行了测试。然而,DigiKey在RFID应答器、标签类别中提供了许多其他类型的RFID标签。

电磁铁和驱动电路

本项目中的执行器是来自Adafruit的1512锁式电磁铁。由于它消耗约650mA的电流,因此无法直接由AVR-IoT WG板驱动。相反,该板将打开一个MOSFET,从而驱动电磁铁。该电路的原理图如下所示。在MOSFET的栅极上添加了一个弱下拉电阻,以防止在板未通电时电磁铁被驱动。请注意,门连接到mikroBUS插座的“RX”引脚,因为我们不使用USART通信。RX引脚已在项目代码中配置为GPIO。

Atmel Studio 项目

该项目是通过修改AVR-IoT WG板上的演示项目创建的。该项目在start.atmel.com上称为“AVR IoT WG传感器节点”。我不会详细介绍所做的每一个更改,但我会指出主要的更改。第一个重要的修改是向云中间件添加订阅功能。这使得开发板能够订阅来自Google Cloud IoT Core的命令。下一个重大变化是添加了CR95HF NFC读取器IC的库,以允许从ISO15693标签读取UID。然后添加了一个回调函数,当从Google Cloud接收到“YES”命令时,收回电磁铁几秒钟。

最终的项目代码可以在这里找到:https://github.com/mkmielke/avr-iot-rfid-ac。它仍然可以通过Atmel START进行配置,因为这样配置引脚更方便。然而,使用START时应谨慎,因为它所做的某些更改可能会与上述修改冲突。如果您想从头到尾探索对演示项目所做的每一个更改,请随意查看提交历史记录

该项目还有一些未来的工作可以做,例如;缓存UID,这样就不必每次都使用云,或者在连接失败时作为备份,添加通过开发板上的一个按钮配置标签的功能,等等。

Google Cloud

项目架构

通过将我们的设备连接到Google Cloud,我们可以将MCU的几项任务卸载到云端,包括数据处理和数据库管理。对于这个项目,评估板上的MCU所做的只是维护Google Cloud连接并定期检查RFID标签的存在。如果找到标签,则读取其UID并发送到云端。如果从Google Cloud接收到命令,设备将相应地做出反应。在这种情况下,该命令将是一个简单的“YES”或“NO”,取决于上述UID是否具有适当的授权。下面的项目图更详细地解释了如何在Google Cloud中实现这一点。


4 Google Cloud项目的架构

远程设备通过Cloud IoT Core服务连接到Google Cloud(在本项目中只有一个RFID读取器,但可以有更多)。每次设备向IoT Core发送数据时,该数据都会被转发到Cloud Pub/Sub主题。可以为每个设备或不同的设备组创建单独的Pub/Sub主题。然后,Pub/Sub主题将触发一个Cloud Function,并将从IoT Core接收到的数据传递给它。Cloud Function将向SQL数据库发出查询,我们通过Cloud Storage Bucket填充该数据库。根据查询结果,Cloud Function将使用IoT Core API向最初发送数据的远程设备发送命令。这并不是唯一的方法。可以使用Bigtable服务而不是Cloud SQL,可以为每个设备创建多个Cloud Function,等等。请注意,SQL数据库在Google Cloud上每周需要几美元来运行,但对于像这样的小项目,其他所有服务都是免费的。

设置 Google Cloud 项目

对于那些想要重现此项目或只是好奇它是如何设置的人,以下步骤已记录供您参考。

  1. 创建一个新的Google Cloud项目。我创建了一个名为“AVR-IoT RFID AC”的项目,项目ID为“avr-iot-rfid-ac”。

  2. 从导航菜单中选择Pub/Sub,并在需要时启用Pub/Sub API。创建一个主题。我创建了一个名为“level_9”的主题作为示例(图5)。您可以随意命名您的主题(例如“front_entrance”、“my_vault”、“vip_restroom”等)。如果您有多个RFID读取器,可以为每个读取器创建一个主题。


5 创建一个新的Pub/Sub主题

  1. 从导航菜单中选择IoT Core,并在需要时启用IoT Core API。创建设备注册表。这是一个具有相似属性的已注册IoT设备的集合。在图6中,我创建了一个名为“rfid_readers”的注册表。如果我有用于level 1、level 2等的读取器,它们都将放入此注册表中。选择正确的区域和协议(我们只使用MQTT)。在“默认遥测主题(Default telemetry topic)”下拉菜单中,选择我们刚刚创建的Pub/Sub主题。如果设备未指定子文件夹(我们的设备没有),这是IoT Core将转发设备接收到的任何数据的地方。此时,您可以为每个Pub/Sub主题添加更多遥测主题。

  2. 在注册表设置中,创建设备并添加其公钥。为此,点击“创建设备(Create device)”以进入图7所示的表单。输入设备ID。我选择使用ATECC608A提供的唯一ID,并在前面加上“d”(与Microchip在其演示应用程序中使用的方案相同)。在“身份验证(Authentication)”下选择“上传(Upload)”,在“公钥格式(Public key format)”下选择“ES256”。然后,浏览公钥值并从CURIOSITY驱动器中选择PUBKEY.TXT(参见图1a)。点击“创建(Create)”。


6 创建新设备注册表


7 在注册表中创建新设备

  1. 从导航菜单中选择SQL并创建新的SQL实例。选择“MySQL”并点击下一步。点击“选择第二代(Choose Second Generation)”。为您的MySQL实例设置ID并为root用户设置密码,如图8所示。点击“创建(Create)”。为了节省成本,您可以在实例详细信息页面上点击“编辑(Edit)”,将机器类型更改为“db-f1-micro”并禁用自动备份。

  2. 通过点击图9中红色圆圈中的图标激活Cloud Shell,并输入清单1中提供的命令,将您自己的值替换到占位符中(参见图9作为示例)。这将创建一个数据库和表。该表将有两列;UID列和Name列。UID列是主键,这意味着它必须是唯一的且不能为空。


8 创建SQL实例


9 创建一个名为“permissions”的数据库,并在其中创建一个名为“level_9”的表

清单 1 :连接到SQL实例并创建新数据库和表的命令

  1. 此时,您可以使用shell手动将名称和ID添加到数据库中(例如INSERT INTO <table_name> VALUES ( "E004015006068493", "Matt Mielke" ); )。另一个选项是创建一个包含ID和名称的CSV文件,并将该文件导入到您的数据库中。例如,我创建了文件“Level 9 Access.txt”,其中包含几个随机名称和UID,以及我的名字和我的RFID标签的UID(见清单2)。由于只有云存储上的数据可以导入到我们的SQL实例中,我们必须首先将文件上传到云存储。只需从导航菜单中选择存储,创建一个存储桶,为其命名,然后点击“创建(Create)”,如图10所示。在存储桶详细信息页面上,点击“上传文件(Upload files)”并浏览您的CSV文件。上传完成后,返回您的SQL实例详细信息页面,点击“导入(Import)”以导入数据,如图11所示。最后,图12展示了如何使用云Shell验证CSV文件内容是否已成功导入到表中。请注意,由于表的UID列是主键,您可以向CSV文件中添加名称并重新导入,而无需先清空表。重复的行将不会被添加。但是,您必须手动从表中删除行,因为从CSV文件中删除它们不会有任何效果。

清单 2 “Level 9 Access.txt”的内容

"E0040171DF8B7267","Safia Hunt",
"E0040194D2A82AC7","Myles Cooley",
"E00401FE2DA29176","Stella Findlay",
"E00401D3CDB4A3F0","Ella Marshall",
"E004011D64B96F89","Darrel Goodman",
"E004010A66C51AE5","Marion Kenny",
"E004013CBF3A9B46","Marli Frazier",
"E00401BB66668BD1","Sumaiya Moses",
"E00401A743A2327C","Ansh Green",
"E004013FEB644E0B","Kirstie Jaramillo",
"E0040102FA202721","Loki Hills",
"E00401000114BEB9","Maariyah May",
"E004016655C5E457","Nabeel North",
"E004012F95648AE1","Ciara Rodriguez",
"E004015006068493","Matt Mielke",


10 创建存储桶


11 将CSV文件导入SQL实例


12 :验证 CSV文件是否成功导入到表中

  1. 最后,从导航菜单中选择云函数,并在需要时启用云函数API。创建一个新的云函数并为其命名。在“触发器(Trigger)”下拉菜单中,选择“Cloud Pub/Sub”,在“主题(Topic)”下拉菜单中,选择您的遥测数据发布到的主题。使用“运行时(Runtime)”下拉菜单选择您喜欢的编程语言。我选择了Python,然后将清单3中提供的代码放在main.py标签中,将清单4中的内容放在requirements.txt标签中。如果您想使用我的代码,请务必首先更改“TODO (developer)”部分中声明的参数以匹配您的SQL实例。如果您愿意,可以删除调试打印语句。如果您保留它们,可以通过打开云Shell并运行命令:gcloud functions logs read –limit x 来读取它们的输出,其中x是要获取的条目数。此函数可以根据触发它的Pub/Sub主题,甚至遥测事件发送到的子文件夹,修改为查询数据库中的不同表。


13 创建云函数

清单 3 :main.py

清单 4 : requirements.txt

# Function dependencies, for example:
# package>=version
google.auth
google-api-python-client
pymysql
  1. 在 Atmel Studio 中,导入项目并打开文件 IoT_Sensor_Node_config.h,以便您可以修改云配置部分以匹配您的 Google Cloud 项目(图 14)。不要使用“重新配置 Atmel Start 项目(Re-Configure Atmel Start Project)”选项,因为它会撤销对原始演示项目所做的许多更改。


14: 更新项目代码以匹配您的云配置

请注意,在撰写本文时,Google Cloud 中使用的几个元素仍处于测试阶段(例如,使用 Python 3.7 编写云函数),因此可能会在不兼容的情况下进行更改,恕不另行通知。