Share via


如何在不使用 SDK 的情況下透過 HTTPS 使用對稱金鑰

在本操作說明文章中,您將透過 HTTPS 使用對稱金鑰布建裝置,而不需使用 Azure IoT DPS 裝置 SDK。 大部分的語言都提供連結庫來傳送 HTTP 要求,但在本文中,您將使用 cURL 命令行工具來透過 HTTPS 傳送和接收特定語言。

您可以依照本文中的步驟,在 Linux 或 Windows 計算機上執行。 如果您在 Windows 子系統 Linux 版 (WSL) 上執行或在 Linux 電腦上執行,您可以在 Bash 提示字元中輸入本機系統上的所有命令。 如果您在 Windows 上執行,請在 GitBash 提示字元中輸入本機系統上的所有命令。

根據您選擇的註冊項目類型而定,本文有不同的路徑。 安裝必要條件之後,請務必先閱讀概 再繼續進行。

必要條件

  • 如果您沒有 Azure 訂用帳戶,請在開始前建立免費帳戶

  • 使用 Azure 入口網站 完成設定 IoT 中樞 裝置布建服務中的步驟。

  • 請確定 您的電腦已安裝 Python 3.7 或更新版本。 您可以執行 python --version來檢查 Python 版本。

  • 如果您在 Windows 中執行,請安裝最新版本的 Git。 請確定 Git 已新增至命令視窗可存取的環境變數。 請參閱 Software Freedom Conservancy 的 Git 用戶端工具 ,以取得要安裝之最新版 git 的工具,其中包括 Git Bash,您可以用來與本機 Git 存放庫互動的命令行應用程式。 在 Windows 上,您會在 GitBash 提示字元中輸入本機系統上的所有命令。

  • Azure CLI。 您有兩個選項可用來執行本文中的 Azure CLI 命令:

    • 使用 Azure Cloud Shell,這是在瀏覽器中執行 CLI 命令的互動式殼層。 建議您使用此選項,因為您不需要安裝任何專案。 如果您是第一次使用 Cloud Shell,請登入 Azure 入口網站。 請遵循 Cloud Shell 快速入門中的步驟來啟動 Cloud Shell選取 Bash 環境
    • 您可以選擇性地在本機電腦上執行 Azure CLI。 如果已安裝 Azure CLI,請執行 az upgrade 以將 CLI 和擴充功能升級至目前的版本。 若要安裝 Azure CLI,請參閱 安裝 Azure CLI
  • 如果您是在Linux或 WSL 環境中執行,請開啟Bash提示字元以在本機執行命令。 如果您是在 Windows 環境中執行,請開啟 GitBash 提示字元。

概觀

在本文中,您可以使用 個別註冊註冊群組 ,透過 DPS 布建。

建立個別註冊或註冊群組項目之後,請繼續 建立 SAS 令牌 ,並使用 DPS 註冊您的裝置

使用個別註冊

如果您想要建立要用於本文的新個別註冊,您可以使用 az iot dps enrollment create 命令來建立對稱密鑰證明的個別註冊。

下列命令會為您的 DPS 實例建立具有預設配置原則的註冊專案,並讓 DPS 為您的裝置指派主要和次要密鑰:

az iot dps enrollment create -g {resource_group_name} --dps-name {dps_name} --enrollment-id {enrollment_id} --attestation-type symmetrickey
  • 取代您的資源群組和 DPS 實例名稱。

  • 註冊標識碼是裝置的註冊標識碼。 註冊標識碼是英數位元的不區分大小寫字串(最多 128 個字元長),加上特殊字元:'-'、、'.''_'':'。 最後一個字元必須是英數位元或虛線 ('-')。 請確定您在命令中使用的註冊識別碼遵守此格式。

指派的對稱金鑰會在回應的證明屬性中傳回:


{
  "allocationPolicy": null,
  "attestation": {
    "symmetricKey": {
      "primaryKey": "G3vn0IZH9oK3d4wsxFpWBtd2KUrtjI+39dZVRf26To8w9OX0LaFV9yZ93ELXY7voqHEUsNhnb9bt717UP87KxA==",
      "secondaryKey": "4lNxgD3lUAOEOied5/xOocyiUSCAgS+4b9OvXLDi8ug46/CJzIn/3rN6Ys6gW8SMDDxMQDaMRnIoSd1HJ5qn/g=="
    },
    "tpm": null,
    "type": "symmetricKey",
    "x509": null
  },

  ...

}

記下個別註冊專案的主要金鑰和註冊標識碼(註冊標識元),您將在本文稍後使用。

如果您想要使用本文的現有個別註冊,您可以使用 az iot dps enrollment show 命令取得主鍵

az iot dps enrollment show -g {resource_group_name} --dps-name {dps_name} --enrollment-id {enrollment_id} --show-keys true

使用註冊群組

如果您想要建立要用於本文的新註冊群組,您可以使用 az iot dps enrollment-group create 命令來建立對稱密鑰證明的註冊群組。

下列命令會為您的 DPS 實例建立具有預設配置原則的註冊群組專案,並讓 DPS 為註冊群組指派主要和次要密鑰:

az iot dps enrollment-group create -g {resource_group_name} --dps-name {dps_name} --enrollment-id {enrollment_id}
  • 取代您的資源群組和 DPS 實例名稱。

  • 註冊標識碼是英數位元的不區分大小寫字串(最多 128 個字元長),加上特殊字元:'-'、、'.''_'':'。 最後一個字元必須是英數位元或虛線 ('-')。 它可以是您選擇用於註冊群組的任何名稱。

指派的對稱金鑰會在回應的證明屬性中傳回:


{
  "allocationPolicy": null,
  "attestation": {
    "symmetricKey": {
      "primaryKey": "G3vn0IZH9oK3d4wsxFpWBtd2KUrtjI+39dZVRf26To8w9OX0LaFV9yZ93ELXY7voqHEUsNhnb9bt717UP87KxA==",
      "secondaryKey": "4lNxgD3lUAOEOied5/xOocyiUSCAgS+4b9OvXLDi8ug46/CJzIn/3rN6Ys6gW8SMDDxMQDaMRnIoSd1HJ5qn/g=="
    },
    "tpm": null,
    "type": "symmetricKey",
    "x509": null
  },

  ...

}

記下主鍵。

如果您想要使用本文的現有個別註冊,您可以使用 az iot dps enrollment-group show 命令取得主鍵

az iot dps enrollment-group show -g {resource_group_name} --dps-name {dps_name} --enrollment-id {enrollment_id} --show-keys true

衍生裝置金鑰

搭配群組註冊使用對稱密鑰證明時,您不會直接使用註冊群組密鑰。 相反地,您會從註冊群組密鑰衍生每個裝置的唯一密鑰。 如需詳細資訊,請參閱 使用對稱密鑰群組註冊。

在本節中,您將從註冊群組主鍵產生裝置密鑰,以計算裝置唯一 註冊標識碼的 HMAC-SHA256 。 結果接著會轉換成Base64格式。

  1. 使用 openssl 產生您的唯一索引鍵。 您將使用下列 Bash 殼層腳稿。 {primary-key}取代為您稍早複製的註冊群組主要金鑰,並以您要用於裝置的註冊識別碼取代 {contoso-simdevice}。 註冊標識碼是英數位元的不區分大小寫字串(最多 128 個字元長),加上特殊字元:'-'、、'.''_'':'。 最後一個字元必須是英數位元或虛線 ('-')。

    KEY={primary-key}
    REG_ID={contoso-simdevice}
    
    keybytes=$(echo $KEY | base64 --decode | xxd -p -u -c 1000)
    echo -n $REG_ID | openssl sha256 -mac HMAC -macopt hexkey:$keybytes -binary | base64
    
  2. 文稿會輸出類似下列索引鍵的內容:

    p3w2DQr9WqEGBLUSlFi1jPQ7UWQL4siAGy75HFTFbf8=
    

記下衍生的裝置金鑰和您用來產生它的註冊識別碼,您將在下一節中使用它們。

您也可以使用 Azure CLI 或 PowerShell 來衍生裝置密鑰。 若要深入瞭解,請參閱 衍生裝置密鑰

建立 SAS 令牌

使用對稱金鑰證明時,裝置會使用共用存取簽章 (SAS) 令牌向 DPS 進行驗證。 針對透過個別註冊佈建的裝置,令牌會使用註冊項目中設定的主要或次要密鑰進行簽署。 針對透過註冊群組佈建的裝置,令牌會使用衍生的裝置密鑰進行簽署,接著會使用註冊群組專案中的主要或次要密鑰集來產生令牌。 令牌會指定到期時間和目標資源 URI。

下列 Python 腳本可用來產生 SAS 令牌:

from base64 import b64encode, b64decode
from hashlib import sha256
from time import time
from urllib.parse import quote_plus, urlencode
from hmac import HMAC

def generate_sas_token(uri, key, policy_name, expiry=3600):
     ttl = time() + expiry
     sign_key = "%s\n%d" % ((quote_plus(uri)), int(ttl))
     print(sign_key)
     signature = b64encode(HMAC(b64decode(key), sign_key.encode('utf-8'), sha256).digest())

     rawtoken = {
         'sr' :  uri,
         'sig': signature,
         'se' : str(int(ttl))
     }

     if policy_name is not None:
         rawtoken['skn'] = policy_name

     return 'SharedAccessSignature ' + urlencode(rawtoken)

uri = '[resource_uri]'
key = '[device_key]'
expiry = [expiry_in_seconds]
policy= '[policy]'

print(generate_sas_token(uri, key, policy, expiry))

其中:

  • [resource_uri] 是您嘗試使用此令牌存取之資源的 URI。 針對 DPS,其格式 [dps_id_scope]/registrations/[dps_registration_id]為 ,其中 [dps_id_scope] 是 DPS 實例的識別碼範圍,而 [dps_registration_id] 是您用於裝置的註冊標識碼。

    您可以從 Azure 入口網站 中實例的 [概觀] 窗格取得 DPS 實例的標識符範圍,也可以使用 az iot dps show Azure CLI 命令(將佔位符取代為您的資源組名和 DPS 實例):

    az iot dps show -g {resource_group_name} --name {dps_name}
    
  • [device_key] 是與您的裝置相關聯的裝置密鑰。 此金鑰是個別註冊中為您指定的或自動產生的金鑰,或群組註冊的衍生密鑰。

    • 如果您使用個別註冊,請使用您在使用個別註冊儲存的主鍵。

    • 如果您使用註冊群組,請使用您在使用註冊群組產生的衍生裝置密鑰。

  • [expiry_in_seconds] 是此 SAS 令牌的有效期間,以秒為單位。

  • [policy] 是與裝置密鑰相關聯的原則。 針對 DPS 裝置註冊,原則會硬式編碼為「註冊」。

名為 my-symkey-device 且有效期間為 30 天的裝置輸入範例集可能如下所示。

uri = '0ne00111111/registrations/my-symkey-device'
key = '18RQk/hOPJR9EbsJlk2j8WA6vWaj/yi+oaYg7zmxfQNdOyMSu+SJ8O7TSlZhDJCYmn4rzEiVKIzNiVAWjLxrGA=='
expiry = 2592000
policy='registration'

修改裝置和 DPS 實例的腳本,並將其儲存為 Python 檔案;例如, generate_token.py。 執行文稿, 例如 python generate_token.py。 它應該會輸出類似下列的 SAS 令牌:

0ne00111111%2Fregistrations%2Fmy-symkey-device
1663952627
SharedAccessSignature sr=0ne00111111%2Fregistrations%2Fmy-symkey-device&sig=eNwg52xQdFTNf7bgPAlAJBCIcONivq%2Fck1lf3wtxI4A%3D&se=1663952627&skn=registration

複製並儲存以 開頭的 SharedAccessSignature整行。 這一行是SAS令牌。 在下列各節中,您將需要用到它。

若要深入瞭解如何搭配 DPS 使用 SAS 令牌及其結構,請參閱 使用 SAS 控制 DPS 的存取權。

註冊您的裝置

您可以呼叫 註冊裝置 REST API,以透過 DPS 布建裝置。

使用下列 curl 命令:

curl -L -i -X PUT -H 'Content-Type: application/json' -H 'Content-Encoding:  utf-8' -H 'Authorization: [sas_token]' -d '{"registrationId": "[registration_id]"}' https://global.azure-devices-provisioning.net/[dps_id_scope]/registrations/[registration_id]/register?api-version=2019-03-31

其中:

  • -L 指示 curl 遵循 HTTP 重新導向。

  • –i 指示 curl 在輸出中包含通訊協議標頭。 這些標頭並非絕對必要,但它們可能很有用。

  • -X PUT 告知 curl 這是 HTTP PUT 命令。 此 API 呼叫的必要專案。

  • -H 'Content-Type: application/json' 告知 DPS 我們正在張貼 JSON 內容,而且必須是 『application/json』。

  • -H 'Content-Encoding: utf-8' 告知 DPS 我們用於訊息本文的編碼方式。 設定為 OS/客戶端的適當值;不過,通常是 utf-8

  • -H 'Authorization: [sas_token]' 告知 DPS 使用您的 SAS 令牌進行驗證。 將 [sas_token] 取代為您在建立 SAS 令牌中 產生的令牌

  • -d '{"registrationId": "[registration_id]"}',參數 –d 是我們張貼之訊息的「數據」或本文。 它必須是 JSON,格式為 '{“registrationId”:“[registration_id”}'。 請注意,對於 curl,它會以單引弧括住;否則,您必須逸出 JSON 中的雙引號。

  • 最後,最後一個參數是要張貼至 的 URL。 針對「一般」(亦即非內部部署)DPS,會使用全域 DPS 端點 global.azure-devices-provisioning.nethttps://global.azure-devices-provisioning.net/[dps_id_scope]/registrations/[registration_id]/register?api-version=2019-03-31。 請注意,您必須將 和 [registration_id] 取代[dps_scope_id]為適當的值。

例如:

curl -L -i -X PUT -H 'Content-Type: application/json' -H 'Content-Encoding:  utf-8' -H 'Authorization: SharedAccessSignature sr=0ne00111111%2Fregistrations%2Fmy-symkey-device&sig=eNwg52xQdFTNf7bgPAlAJBCIcONivq%2Fck1lf3wtxI4A%3D&se=1663952627&skn=registration' -d '{"registrationId": "my-symkey-device"}' https://global.azure-devices-provisioning.net/0ne00111111/registrations/my-symkey-device/register?api-version=2021-06-01

成功的呼叫會有類似下列的回應:

HTTP/1.1 202 Accepted
Date: Wed, 31 Aug 2022 22:02:49 GMT
Content-Type: application/json; charset=utf-8
Transfer-Encoding: chunked
Location: https://global.azure-devices-provisioning.net/0ne00111111/registrations/my-symkey-device/register
Retry-After: 3
x-ms-request-id: a021814f-0cf6-4ce9-a1e9-ead7eb5118d9
Strict-Transport-Security: max-age=31536000; includeSubDomains

{"operationId":"5.316aac5bdc130deb.b1e02da8-c3a0-4ff2-a121-7ea7a6b7f550","status":"assigning"}

回應包含作業標識碼和狀態。 在這裡情況下,狀態會設定為 assigning。 DPS 註冊可能是長時間執行的作業,因此會以異步方式完成。 一般而言,您將使用 作業狀態查閱 REST API 輪詢 狀態,以判斷裝置是否已指派或是否發生失敗。

DPS 的有效狀態值如下:

  • assigned:狀態呼叫的傳回值會指出已指派裝置 IoT 中樞 的內容。

  • assigning:作業仍在執行中。

  • disabled:D PS 中已停用註冊記錄,因此無法指派裝置。

  • failed:指派失敗。 回應中registrationState將會傳errorCode回 並errorMessage傳回 ,以指出失敗的內容。

  • unassigned

若要呼叫 作業狀態查閱 API,請使用下列 curl 命令:

curl -L -i -X GET -H 'Content-Type: application/json' -H 'Content-Encoding:  utf-8' -H 'Authorization: [sas_token]' https://global.azure-devices-provisioning.net/[dps_id_scope]/registrations/[registration_id]/operations/[operation_id]?api-version=2019-03-31

您將使用與註冊裝置要求中相同的標識碼範圍、註冊標識碼和SAS令牌。 使用註冊裝置回應中傳回的作業標識碼。

例如:

curl -L -i -X GET -H 'Content-Type: application/json' -H 'Content-Encoding:  utf-8' -H 'Authorization: SharedAccessSignature sr=0ne00111111%2Fregistrations%2Fmy-symkey-device&sig=eNwg52xQdFTNf7bgPAlAJBCIcONivq%2Fck1lf3wtxI4A%3D&se=1663952627&skn=registration' https://global.azure-devices-provisioning.net/0ne00111111/registrations/my-symkey-device/operations/5.316aac5bdc130deb.f4f1828c-4dab-4ca9-98b2-dfc63b5835d6?api-version=2021-06-01

下列輸出顯示已成功指派之裝置的回應。 請注意, status 屬性是 assigned ,而且 registrationState.assignedHub 屬性會設定為布建裝置的IoT中樞。

HTTP/1.1 200 OK
Date: Wed, 31 Aug 2022 22:05:23 GMT
Content-Type: application/json; charset=utf-8
Transfer-Encoding: chunked
x-ms-request-id: ffb98d42-023e-4e75-afb0-1807ff091cbb
Strict-Transport-Security: max-age=31536000; includeSubDomains

{
   "operationId":"5.316aac5bdc130deb.b1e02da8-c3a0-4ff2-a121-7ea7a6b7f550",
   "status":"assigned",
   "registrationState":{
      "registrationId":"my-symkey-device",
      "createdDateTimeUtc":"2022-08-31T22:02:50.5163352Z",
      "assignedHub":"MyExampleHub.azure-devices.net",
      "deviceId":"my-symkey-device",
      "status":"assigned",
      "substatus":"initialAssignment",
      "lastUpdatedDateTimeUtc":"2022-08-31T22:02:50.7370676Z",
      "etag":"IjY5MDAzNTUyLTAwMDAtMDMwMC0wMDAwLTYzMGZkYThhMDAwMCI="
   }
}

傳送遙測訊息

您必須先為指派裝置的IoT中樞建立SAS令牌,才能傳送遙測訊息。 您可以使用用來簽署 DPS 實例 SAS 令牌的相同主要金鑰或衍生裝置金鑰來簽署此權杖。

為您的IoT中樞建立SAS令牌

若要建立 SAS 令牌,您可以執行相同的程式代碼,以下列變更建立 DPS 實例的令牌:

uri = '[resource_uri]'
key = '[device_key]'
expiry = [expiry_in_seconds]
policy= None

其中:

  • [resource_uri] 是您嘗試使用此令牌存取之資源的 URI。 針對將訊息傳送至 IoT 中樞的裝置,其格式 [iot-hub-host-name]/devices/[device-id]為 。

    • 針對 [iot-hub-host-name],請使用上一節中 屬性中所assignedHub傳回 IoT 中樞 主機名。

    • 針對 [device-id],請使用上一節中 屬性中傳回的 deviceId 裝置標識碼。

  • [device_key] 是與您的裝置相關聯的裝置密鑰。 此金鑰是個別註冊中為您指定的或自動產生的金鑰,或群組註冊的衍生密鑰。 (這是您先前用來建立 DPS 令牌的相同金鑰。

    • 如果您使用個別註冊,請使用您在使用個別註冊儲存的主鍵。

    • 如果您使用註冊群組,請使用您在使用註冊群組產生的衍生裝置密鑰。

  • [expiry_in_seconds] 是此 SAS 令牌的有效期間,以秒為單位。

  • policy=None 將遙測傳送至IoT中樞的裝置不需要任何原則,因此此參數會設定為 None

名為 傳送 IoT 中樞 至名為 MyExampleHub 且令牌有效期間為一小時的裝置輸入範例集my-symkey-device,可能如下所示:

uri = 'MyExampleHub.azure-devices.net/devices/my-symkey-device'
key = '18RQk/hOPJR9EbsJlk2j8WA6vWaj/yi+oaYg7zmxfQNdOyMSu+SJ8O7TSlZhDJCYmn4rzEiVKIzNiVAWjLxrGA=='
expiry = 3600
policy= None

下列輸出顯示這些輸入的範例 SAS 令牌:

SharedAccessSignature sr=MyExampleHub.azure-devices.net%2Fdevices%2Fmy-symkey-device&sig=f%2BwW8XOKeJOtiPc9Iwjc4OpExvPM7NlhM9qxN2a1aAM%3D&se=1663119026

若要深入瞭解如何為 IoT 中樞 建立 SAS 令牌,包括其他程式設計語言中的範例程式代碼,請參閱使用共用存取簽章控制對 IoT 中樞 的存取。

注意

為了方便起見,您可以使用 Azure CLI az iot hub generate-sas-token 命令來取得向 IoT 中樞註冊之裝置的 SAS 令牌。 例如,下列命令會產生一小時的SAS令牌。 {iothub_name}針對 ,您只需要主機火腿的第一個部分,例如 MyExampleHub

az iot hub generate-sas-token -d {device_id} -n {iothub_name}

將數據傳送至IoT中樞

您可以呼叫 IoT 中樞 傳送裝置事件 REST API,以將遙測傳送至裝置。

使用下列 curl 命令:

curl -L -i -X POST -H 'Content-Type: application/json' -H 'Content-Encoding:  utf-8' -H 'Authorization: [sas_token]' -d '{"temperature": 30}' https://[assigned_iot_hub_name].azure-devices.net/devices/[device_id]/messages/events?api-version=2020-03-13

其中:

  • -X POST 告知 curl 這是 HTTP POST 命令。 此 API 呼叫的必要專案。

  • -H 'Content-Type: application/json'告知 IoT 中樞 我們張貼 JSON 內容,而且必須是 『application/json』。

  • -H 'Content-Encoding: utf-8'會告知 IoT 中樞 訊息本文所使用的編碼方式。 設定為 OS/客戶端的適當值;不過,通常是 utf-8

  • -H 'Authorization: [sas_token]'告知 IoT 中樞 使用您的 SAS 令牌進行驗證。 將取代 [sas_token] 為您為指派的IoT中樞所產生的令牌。

  • -d '{"temperature": 30}',參數 –d 是我們張貼之訊息的「數據」或本文。 在本文中,我們會張貼單一溫度數據點。 內容類型已指定為 application/json,因此,針對此要求,本文為 JSON。 請注意,對於 curl,它會以單引弧括住;否則,您必須逸出 JSON 中的雙引號。

  • 最後一個參數是要張貼至的URL。 針對傳送裝置事件 API,URL 為: https://[assigned_iot_hub_name].azure-devices.net/devices/[device_id]/messages/events?api-version=2020-03-13

    • 將取代 [assigned_iot_hub_name] 為您裝置指派給的IoT中樞名稱。

    • 將取代 [device_id] 為您註冊裝置時所指派的裝置識別碼。 對於透過註冊群組布建的裝置,裝置標識碼將會是註冊標識碼。 針對個別註冊,您可以選擇性地指定與註冊專案中註冊標識碼不同的裝置標識碼。

例如,若裝置標識碼為 my-symkey-device 將遙測數據點傳送至名為 MyExampleHub的IoT中樞,

curl -L -i -X POST -H 'Content-Type: application/json' -H 'Content-Encoding:  utf-8' -H 'Authorization: SharedAccessSignature sr=MyExampleHub.azure-devices.net%2Fdevices%2Fmy-symkey-device&sig=f%2BwW8XOKeJOtiPc9Iwjc4OpExvPM7NlhM9qxN2a1aAM%3D&se=1663119026' -d '{"temperature": 30}' https://MyExampleHub.azure-devices.net/devices/my-symkey-device/messages/events?api-version=2020-03-13

成功的呼叫會有類似下列的回應:

HTTP/1.1 204 No Content
Content-Length: 0
Vary: Origin
Server: Microsoft-HTTPAPI/2.0
x-ms-request-id: 9e278582-3561-417b-b807-76426195920f
Date: Wed, 14 Sep 2022 00:32:53 GMT

後續步驟

  • 若要深入瞭解對稱密鑰證明,請參閱 對稱密鑰證明

  • 若要深入瞭解 SAS 令牌及其結構,請參閱 使用 SAS 控制 DPS 的存取。