使用对称密钥预配旧设备How to provision legacy devices using symmetric keys

许多旧设备的常见问题是它们的标识通常由单段信息组成。A common problem with many legacy devices is that they often have an identity that is composed of a single piece of information. 该信息通常为 MAC 地址或序列号。This identity information is usually a MAC address or a serial number. 旧设备可能没有证书、TPM 或可用于安全地识别设备的任何其他安全功能。Legacy devices may not have a certificate, TPM, or any other security feature that can be used to securely identify the device. IoT 中心设备预配服务包含对称密钥证明。The Device Provisioning Service for IoT hub includes symmetric key attestation. 对称密钥证明可以用于根据 MAC 地址或序列号等信息标识设备。Symmetric key attestation can be used to identify a device based off information like the MAC address or a serial number.

如果安装硬件安全模块 (HSM) 和证书比较轻松,这可能是标识和预配设备更好的方式。If you can easily install a hardware security module (HSM) and a certificate, then that may be a better approach for identifying and provisioning your devices. 这种方式可避免更新部署到所有设备上的代码,并且不必在设备映像中嵌入密钥。Since that approach may allow you to bypass updating the code deployed to all your devices, and you would not have a secret key embedded in your device image.

本文假定:HSM 或证书都是不可行的选择。This article assumes that neither an HSM or a certificate is a viable option. 但你有一些更新设备代码的方法,可供使用设备预配服务来预配设备。However, it is assumed that you do have some method of updating device code to use the Device Provisioning Service to provision these devices.

本文还假定,在安全的环境中进行设备更新,以防发生对组主密钥或派生的设备密钥未经授权的访问。This article also assumes that the device update takes place in a secure environment to prevent unauthorized access to the master group key or the derived device key.

本文面向基于 Windows 的工作站。This article is oriented toward a Windows-based workstation. 但是,你也可以在 Linux 上执行过程。However, you can perform the procedures on Linux. 对于 Linux 示例,请参阅如何进行多租户预配For a Linux example, see How to provision for multitenancy.


将基于标识每个设备的信息为该设备定义唯一注册 ID。A unique registration ID will be defined for each device based on information that identifies that device. 例如,MAC 地址或序列号。For example, the MAC address or a serial number.

将通过设备预配服务创建使用对称密钥证明的注册组。An enrollment group that uses symmetric key attestation will be created with the Device Provisioning Service. 注册组包括组的主密钥。The enrollment group will include a group master key. 将使用该主密钥对每个唯一注册 ID 进行哈希处理,为各设备生成一个唯一设备密钥。That master key will be used to hash each unique registration ID to produce a unique device key for each device. 设备将该派生设备密钥用于其唯一注册 ID,在设备预配服务中用作证明并且该设备被分配给 IoT 中心。The device will use that derived device key with its unique registration ID to attest with the Device Provisioning Service and be assigned to an IoT hub.

本文所示的设备代码采用快速入门:使用对称密钥预配模拟设备中所用的模式。The device code demonstrated in this article will follow the same pattern as the Quickstart: Provision a simulated device with symmetric keys. 该代码使用 Azure IoT C SDK 中的示例来模拟设备。The code will simulate a device using a sample from the Azure IoT C SDK. 如快速入门文章中所示,模拟设备将使用注册组(而不是各个注册)进行证明。The simulated device will attest with an enrollment group instead of an individual enrollment as demonstrated in the quickstart.

如果没有 Azure 订阅,可在开始前创建一个试用帐户If you don't have an Azure subscription, create a trial account before you begin.


准备 Azure IoT C SDK 开发环境Prepare an Azure IoT C SDK development environment

在本部分,你将准备一个用于生成 Azure IoT C SDK 的开发环境。In this section, you will prepare a development environment used to build the Azure IoT C SDK.

SDK 包含模拟设备的示例代码。The SDK includes the sample code for the simulated device. 该模拟设备将尝试在设备启动顺序期间进行预配。This simulated device will attempt provisioning during the device's boot sequence.

  1. 下载 CMake 生成系统Download the CMake build system.

    在进行 CMake 安装之前,必须在计算机上安装 Visual Studio 必备组件(Visual Studio 和“使用 C++ 的桌面开发”工作负荷)。It is important that the Visual Studio prerequisites (Visual Studio and the 'Desktop development with C++' workload) are installed on your machine, before starting the CMake installation. 满足先决条件并验证下载内容后,安装 CMake 生成系统。Once the prerequisites are in place, and the download is verified, install the CMake build system.

  2. 打开命令提示符或 Git Bash shell。Open a command prompt or Git Bash shell. 执行以下命令来克隆 Azure IoT C SDK GitHub 存储库:Execute the following command to clone the Azure IoT C SDK GitHub repository:

    git clone https://github.com/Azure/azure-iot-sdk-c.git --recursive

    应该预料到此操作需要几分钟才能完成。You should expect this operation to take several minutes to complete.

  3. 在 git 存储库的根目录中创建 cmake 子目录,并导航到该文件夹。Create a cmake subdirectory in the root directory of the git repository, and navigate to that folder.

    cd azure-iot-sdk-c
    mkdir cmake
    cd cmake
  4. 运行以下命令,生成特定于你的开发客户端平台的 SDK 版本。Run the following command, which builds a version of the SDK specific to your development client platform. 将在 cmake 目录中生成模拟设备的 Visual Studio 解决方案。A Visual Studio solution for the simulated device will be generated in the cmake directory.

    cmake -Dhsm_type_symm_key:BOOL=ON -Duse_prov_client:BOOL=ON  ..

    如果 cmake 找不到 C++ 编译器,则可能会在运行以上命令时出现生成错误。If cmake does not find your C++ compiler, you might get build errors while running the above command. 如果出现这种情况,请尝试在 Visual Studio 命令提示符窗口中运行该命令。If that happens, try running this command in the Visual Studio command prompt.

    生成成功后,最后的几个输出行如下所示:Once the build succeeds, the last few output lines will look similar to the following output:

    $ cmake -Dhsm_type_symm_key:BOOL=ON -Duse_prov_client:BOOL=ON  ..
    -- Building for: Visual Studio 15 2017
    -- Selecting Windows SDK version 10.0.16299.0 to target Windows 10.0.17134.
    -- The C compiler identification is MSVC 19.12.25835.0
    -- The CXX compiler identification is MSVC 19.12.25835.0
    -- Configuring done
    -- Generating done
    -- Build files have been written to: E:/IoT Testing/azure-iot-sdk-c/cmake

创建对称密钥注册组Create a symmetric key enrollment group

  1. 登录到 Azure 门户,并打开你的设备预配服务实例。Sign in to the Azure portal, and open your Device Provisioning Service instance.

  2. 选择“管理注册” 选项卡,然后单击页面顶部的“添加注册组” 按钮。Select the Manage enrollments tab, and then click the Add enrollment group button at the top of the page.

  3. 在“添加注册组” 中输入以下信息,然后单击“保存” 按钮。On Add Enrollment Group, enter the following information, and click the Save button.

    • 组名:输入 mylegacydevicesGroup name: Enter mylegacydevices.

    • 证明类型:选择“对称密钥” 。Attestation Type: Select Symmetric Key.

    • 自动生成密钥:选中此框。Auto Generate Keys: Check this box.

    • 选择要如何将设备分配到中心:选择“静态配置” ,以便可以分配到特定的中心。Select how you want to assign devices to hubs: Select Static configuration so you can assign to a specific hub.

    • 选择此组可分配到的 IoT 中心:选择你的中心之一。Select the IoT hubs this group can be assigned to: Select one of your hubs.


  4. 保存注册后,将生成“主要密钥” 和“辅助密钥” ,并将其添加到注册条目。Once you saved your enrollment, the Primary Key and Secondary Key will be generated and added to the enrollment entry. 对称密钥注册组在“注册组”选项卡的“组名”栏下显示为“mylegacydevices” 。Your symmetric key enrollment group appears as mylegacydevices under the Group Name column in the Enrollment Groups tab.

    打开注册并复制生成的“主要密钥” 的值。Open the enrollment and copy the value of your generated Primary Key. 此密钥是组主密钥。This key is your master group key.

选择设备的唯一注册 IDChoose a unique registration ID for the device

必须定义唯一注册 ID 来标识每个设备。A unique registration ID must be defined to identify each device. 可以使用 MAC 地址、序列号或设备中的任何唯一信息。You can use the MAC address, serial number, or any unique information from the device.

在此示例中,我们使用 MAC 地址和序列号的组合,构成以下注册 ID 字符串。In this example, we use a combination of a MAC address and serial number forming the following string for a registration ID.


为设备创建一个唯一注册 ID。Create a unique registration ID for your device. 有效字符为小写字母数字和短划线(“-”)。Valid characters are lowercase alphanumeric and dash ('-').

派生一个设备密钥Derive a device key

若要生成设备密钥,请使用组主键计算设备的唯一注册 ID 的 HMAC-SHA256,并将结果转换为 Base64 格式。To generate the device key, use the group master key to compute an HMAC-SHA256 of the unique registration ID for the device and convert the result into Base64 format.

不要在设备代码中包含你的组主键。Do not include your group master key in your device code.

Linux 工作站Linux workstations

如果使用的是 Linux 工作站,可以使用 openssl 生成派生的设备密钥,如以下示例中所示。If you are using a Linux workstation, you can use openssl to generate your derived device key as shown in the following example.

将“键” 值替换为前面记录的“主键” 。Replace the value of KEY with the Primary Key you noted earlier.

用注册 ID 替换 REG_ID 值 。Replace the value of REG_ID with your registration ID.


keybytes=$(echo $KEY | base64 --decode | xxd -p -u -c 1000)
echo -n $REG_ID | openssl sha256 -mac HMAC -macopt hexkey:$keybytes -binary | base64

基于 Windows 的工作站Windows-based workstations

如果使用的是基于 Windows 的工作站,可以使用 PowerShell 生成派生的设备密钥,如以下示例中所示。If you are using a Windows-based workstation, you can use PowerShell to generate your derived device key as shown in the following example.

将“键” 值替换为前面记录的“主键” 。Replace the value of KEY with the Primary Key you noted earlier.

用注册 ID 替换 REG_ID 值 。Replace the value of REG_ID with your registration ID.


$hmacsha256 = New-Object System.Security.Cryptography.HMACSHA256
$hmacsha256.key = [Convert]::FromBase64String($KEY)
$sig = $hmacsha256.ComputeHash([Text.Encoding]::ASCII.GetBytes($REG_ID))
$derivedkey = [Convert]::ToBase64String($sig)
echo "`n$derivedkey`n"

设备将使用派生的设备密钥和唯一注册 ID,于预配期间在注册组中执行对称密钥证明。Your device will use the derived device key with your unique registration ID to perform symmetric key attestation with the enrollment group during provisioning.

创建用于预配的设备映像Create a device image to provision

在本部分,你将更新你在较早前设置的位于 Azure IoT C SDK 中的名为 prov_dev_client_sample 的预配示例。In this section, you will update a provisioning sample named prov_dev_client_sample located in the Azure IoT C SDK you set up earlier.

此示例代码模拟将预配请求发送到你的设备预配服务实例的设备启动序列。This sample code simulates a device boot sequence that sends the provisioning request to your Device Provisioning Service instance. 启动序列将会使设备被识别并分配到你在注册组上配置的 IoT 中心。The boot sequence will cause the device to be recognized and assigned to the IoT hub you configured on the enrollment group.

  1. 在 Azure 门户中,选择设备预配服务的“概述”选项卡,记下“ID 范围”的值。 In the Azure portal, select the Overview tab for your Device Provisioning service and note down the ID Scope value.


  2. 在 Visual Studio 中,打开较早前通过运行 CMake 生成的 azure_iot_sdks.sln 解决方案文件。In Visual Studio, open the azure_iot_sdks.sln solution file that was generated by running CMake earlier. 解决方案文件应位于以下位置:The solution file should be in the following location:

  3. 在 Visual Studio 的“解决方案资源管理器”窗口中,导航到 Provision_Samples 文件夹。 In Visual Studio's Solution Explorer window, navigate to the Provision_Samples folder. 展开名为 prov_dev_client_sample 的示例项目。Expand the sample project named prov_dev_client_sample. 展开“源文件”,打开 prov_dev_client_sample.cExpand Source Files, and open prov_dev_client_sample.c.

  4. 找到 id_scope 常量,将值替换为前面复制的“ID 范围”值。 Find the id_scope constant, and replace the value with your ID Scope value that you copied earlier.

    static const char* id_scope = "0ne00002193";
  5. 在同一文件中找到 main() 函数的定义。Find the definition for the main() function in the same file. 确保 hsm_type 变量设置为 SECURE_DEVICE_TYPE_SYMMETRIC_KEY,如下所示:Make sure the hsm_type variable is set to SECURE_DEVICE_TYPE_SYMMETRIC_KEY as shown below:

    SECURE_DEVICE_TYPE hsm_type;
    //hsm_type = SECURE_DEVICE_TYPE_TPM;
    //hsm_type = SECURE_DEVICE_TYPE_X509;
  6. prov_dev_client_sample.c 中,找到已注释掉的对 prov_dev_set_symmetric_key_info() 的调用。Find the call to prov_dev_set_symmetric_key_info() in prov_dev_client_sample.c which is commented out.

    // Set the symmetric key if using they auth type
    //prov_dev_set_symmetric_key_info("<symm_registration_id>", "<symmetric_Key>");

    取消注释该函数调用,并将占位符值(包括尖括号)替换为设备的唯一注册 ID 以及生成的派生设备密钥。Uncomment the function call, and replace the placeholder values (including the angle brackets) with the unique registration ID for your device and the derived device key you generated.

    // Set the symmetric key if using they auth type
    prov_dev_set_symmetric_key_info("sn-007-888-abc-mac-a1-b2-c3-d4-e5-f6", "Jsm0lyGpjaVYVP2g3FnmnmG9dI/9qU24wNoykUmermc=");

    保存文件。Save the file.

  7. 右键单击“prov_dev_client_sample”项目, 然后选择“设为启动项目”。 Right-click the prov_dev_client_sample project and select Set as Startup Project.

  8. 在 Visual Studio 菜单中,选择“调试” > “开始执行(不调试)”以运行该解决方案。 On the Visual Studio menu, select Debug > Start without debugging to run the solution. 在重新生成项目的提示中单击“是”,以便在运行项目之前重新生成项目。 In the prompt to rebuild the project, click Yes, to rebuild the project before running.

    以下输出是模拟设备成功启动并连接到要分配到 IoT 中心的预配服务实例的示例:The following output is an example of the simulated device successfully booting up, and connecting to the provisioning Service instance to be assigned to an IoT hub:

    Provisioning API Version: 1.2.8
    Registering Device
    Registration Information received from service: 
    test-docs-hub.azure-devices.net, deviceId: sn-007-888-abc-mac-a1-b2-c3-d4-e5-f6
    Press enter key to exit:
  9. 在门户中,导航到模拟设备分配到的 IoT 中心,然后单击“IoT 设备” 选项卡。将模拟设备成功预配到中心以后,设备 ID 会显示在“IoT 设备” 边栏选项卡上,“状态”为“已启用” 。In the portal, navigate to the IoT hub your simulated device was assigned to and click the IoT Devices tab. On successful provisioning of the simulated to the hub, its device ID appears on the IoT Devices blade, with STATUS as enabled. 你可能需要单击顶部的“刷新”按钮 。You might need to click the Refresh button at the top.

    设备注册到 IoT 中心

安全注意事项Security concerns

请注意,这会使派生的设备密钥成为映像的一部分,不是推荐的安全最佳做法。Be aware that this leaves the derived device key included as part of the image, which is not a recommended security best practice. 充分体现了安全性和易用性各有利弊。This is one reason why security and ease-of-use are tradeoffs.

后续步骤Next steps