Azure IoT 中級(7)- (案例3)設備通過X509證書經DPS驗證後註冊到IoT Hub並開始通信

案例-設備通過X509證書經DPS驗證後註冊到IoT Hub並開始通信

 

本案例步驟:

注意,前兩個步驟已經在之前的章節中介紹過,本文從第3個步驟開始介紹。

1. 通過openssl和微軟示例Powershell腳本生成CA Root證書;

2. 將CA Root證書上傳到DPS服務並完成所有權驗證;

3. 通過openssl和微軟示例Powershll腳本生成 設備證書;

4. 模擬程序(C#)使用設備證書 向DPS進行身份驗證並註冊到IoT Hub中;

5. 模擬程序使用設備證書直接向IoT Hub 發送遙測消息。

 

其中第4/5步驟的邏輯圖如下:

 

視頻講解:

您可以在B站觀看視頻講解:https://www.bilibili.com/video/av93099113/

或在本站觀看:https://www.51azure.cloud/post/2020/3/4/azure-iot-7-device-with-x509-reg-through-dps-to-iot-hub-send-telemetry

 

圖文講解:

3. 通過openssl和微軟示例Powershll腳本生成 設備證書;

執行如下命令,生成設備證書,其中mydevice001 表示證書名稱,也就是最終註冊到IoT Hub中的設備ID:

New-CACertsDevice mydevice001

 

 

需要輸入證書密碼,此密碼由用戶定義,這裏我們輸入了 12345678

 

按照提示再次輸入密碼,即可如下圖生成證書,我們在設備中使用的是 mydevice001.pfx 證書文件。

 

4. 模擬程序(C#)使用設備證書 向DPS進行身份驗證並註冊到IoT Hub中;

將證書拷貝到示例代碼中,該實例代碼我們在第三講《Azure IoT 中級(3)-(案例1)使用DPS通過對稱密鑰進行單個設備註冊》中使用過

下載地址:https://codeload.github.com/Azure-Samples/azure-iot-samples-csharp/zip/master

本節使用的是 azure-iot-samples-csharp-master\provisioning\Samples\device\X509Sample 項目

代碼中需要修改的地方:

”GlobalDeviceEndpoint“ 改成"global.azure-devices-provisioning.cn"

"s_certificateFileName"改成證書的名稱,此處爲”mydevice001.pfx“

”s_idScope“改成實際的DPS的 id scope。

using Microsoft.Azure.Devices.Provisioning.Client;
using Microsoft.Azure.Devices.Provisioning.Client.Transport;
using Microsoft.Azure.Devices.Shared;
using System;
using System.IO;
using System.Security.Cryptography.X509Certificates;
using System.Text;
namespace Microsoft.Azure.Devices.Provisioning.Client.Samples
{
    public static class Program
    {
        // The Provisioning Hub IDScope.
        // For this sample either:
        // - pass this value as a command-prompt argument
        // - set the DPS_IDSCOPE environment variable 
        // - create a launchSettings.json (see launchSettings.json.template) containing the variable
       // private static string s_idScope = Environment.GetEnvironmentVariable("");
        private static string s_idScope = "0cn0000DC5D";
        // In your Device Provisioning Service please go to "Manage enrollments" and select "Individual Enrollments".
        // Select "Add individual enrollment" then fill in the following:
        // Mechanism: X.509
        // Certificate: 
        //    You can generate a self-signed certificate by running the GenerateTestCertificate.ps1 powershell script.
        //    Select the public key 'certificate.cer' file. ('certificate.pfx' contains the private key and is password protected.)
        //    For production code, it is advised that you install the certificate in the CurrentUser (My) store.
        // DeviceID: iothubx509device1
        // X.509 certificates may also be used for enrollment groups.
        // In your Device Provisioning Service please go to "Manage enrollments" and select "Enrollment Groups".
        // Select "Add enrollment group" then fill in the following:
        // Group name: <your  group name>
        // Attestation Type: Certificate
        // Certificate Type: 
        //    choose CA certificate then link primary and secondary certificates 
        //    OR choose Intermediate certificate and upload primary and secondary certificate files
        // You may also change other enrollemtn group parameters according to your needs
        private const string GlobalDeviceEndpoint = "global.azure-devices-provisioning.cn";
        private static string s_certificateFileName = "mydevice001.pfx";
        public static int Main(string[] args)
        {
            if (string.IsNullOrWhiteSpace(s_idScope) && (args.Length > 0))
            {
                s_idScope = args[0];
            }
            if (string.IsNullOrWhiteSpace(s_idScope))
            {
                Console.WriteLine("ProvisioningDeviceClientX509 <IDScope>");
                return 1;
            }
            X509Certificate2 certificate = LoadProvisioningCertificate();
            using (var security = new SecurityProviderX509Certificate(certificate))
            // Select one of the available transports:
            // To optimize for size, reference only the protocols used by your application.
            using (var transport = new ProvisioningTransportHandlerAmqp(TransportFallbackType.TcpOnly))
            // using (var transport = new ProvisioningTransportHandlerHttp())
            // using (var transport = new ProvisioningTransportHandlerMqtt(TransportFallbackType.TcpOnly))
            // using (var transport = new ProvisioningTransportHandlerMqtt(TransportFallbackType.WebSocketOnly))
            {
                ProvisioningDeviceClient provClient =
                    ProvisioningDeviceClient.Create(GlobalDeviceEndpoint, s_idScope, security, transport);
                var sample = new ProvisioningDeviceClientSample(provClient, security);
                sample.RunSampleAsync().GetAwaiter().GetResult();
            }
            return 0;
        }
        private static X509Certificate2 LoadProvisioningCertificate()
        {
            string certificatePassword = ReadCertificatePassword();
            var certificateCollection = new X509Certificate2Collection();
            certificateCollection.Import(s_certificateFileName, certificatePassword, X509KeyStorageFlags.UserKeySet);
            X509Certificate2 certificate = null;
            foreach (X509Certificate2 element in certificateCollection)
            {
                Console.WriteLine($"Found certificate: {element?.Thumbprint} {element?.Subject}; PrivateKey: {element?.HasPrivateKey}");
                if (certificate == null && element.HasPrivateKey)
                {
                    certificate = element;
                }
                else
                {
                    element.Dispose();
                }
            }
            if (certificate == null)
            {
                throw new FileNotFoundException($"{s_certificateFileName} did not contain any certificate with a private key.");
            }
            else
            {
                Console.WriteLine($"Using certificate {certificate.Thumbprint} {certificate.Subject}");
            }
            return certificate;
        }
        private static string ReadCertificatePassword()
        {
            var password = new StringBuilder();
            Console.WriteLine($"Enter the PFX password for {s_certificateFileName}:");
            while(true)
            {
                ConsoleKeyInfo key = Console.ReadKey(true);
                if (key.Key == ConsoleKey.Backspace)
                {
                    if (password.Length > 0)
                    {
                        password.Remove(password.Length - 1, 1);
                        Console.Write("\b \b");
                    }
                }
                else if (key.Key == ConsoleKey.Enter)
                {
                    Console.WriteLine();
                    break;
                }
                else
                {
                    Console.Write('*');
                    password.Append(key.KeyChar);
                }
            }
            return password.ToString();
        }
    }
}

 

執行代碼前,在DPS中添加組註冊,選擇證書方式,並從下拉列表裏選擇上一節內容配置到DPS中的證書:

 

執行代碼:

輸入證書密碼,程序返回DPS將設備註冊到的IoT Hub的名稱和設備ID

此時,便完成了設備通過X509證書通過DPS註冊到IoT Hub的步驟,可以在Portal-DPS中檢查到如下結果:

 

同時,可以在IoT Hub中看到如下設備,驗證方式是SelfSigned:

 

5. 模擬程序使用設備證書直接向IoT Hub 發送遙測消息

本步驟參考如下文檔:

https://docs.azure.cn/zh-cn/iot-hub/iot-hub-security-x509-get-started#create-an-x509-device-for-your-iot-hub

示例代碼如下:

需要修改的地方有:

44行mydevice001.pfx, 和 12345678,替換成你的證書路徑和 證書密碼;

45行mydevice001換成你的deviceid

46行iot hub 換成第四步中,DPS返回的IoT Hub

 

using System;
using Microsoft.Azure.Devices.Client;
using Microsoft.Azure.Devices.Shared;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;
using System.Text;
namespace x509device
{
    class Program
    {
        private static int MESSAGE_COUNT = 5;
        private const int TEMPERATURE_THRESHOLD = 30;
        private static String deviceId = "mydevice001";
        private static float temperature;
        private static float humidity;
        private static Random rnd = new Random();
        static async Task SendEvent(DeviceClient deviceClient)
        {
            string dataBuffer;
            Console.WriteLine("Device sending {0} messages to IoTHub...\n", MESSAGE_COUNT);
            for (int count = 0; count < MESSAGE_COUNT; count++)
            {
                temperature = rnd.Next(20, 35);
                humidity = rnd.Next(60, 80);
                dataBuffer = string.Format("{{\"deviceId\":\"{0}\",\"messageId\":{1},\"temperature\":{2},\"humidity\":{3}}}", deviceId, count, temperature, humidity);
                Message eventMessage = new Message(Encoding.UTF8.GetBytes(dataBuffer));
                eventMessage.Properties.Add("temperatureAlert", (temperature > TEMPERATURE_THRESHOLD) ? "true" : "false");
                Console.WriteLine("\t{0}> Sending message: {1}, Data: [{2}]", DateTime.Now.ToLocalTime(), count, dataBuffer);
                await deviceClient.SendEventAsync(eventMessage);
            }
        }
        static void Main(string[] args)
        {
            try
            {
                var cert = new X509Certificate2("mydevice001.pfx", "12345678");
                var auth = new DeviceAuthenticationWithX509Certificate("mydevice001", cert);
                var deviceClient = DeviceClient.Create("seanyuiothub.azure-devices.cn", auth, TransportType.Amqp_Tcp_Only);
                if (deviceClient == null)
                {
                    Console.WriteLine("Failed to create DeviceClient!");
                }
                else
                {
                    Console.WriteLine("Successfully created DeviceClient!");
                    SendEvent(deviceClient).Wait();
                }
                Console.WriteLine("Exiting...\n");
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error in sample: {0}", ex.Message);
            }
        }
    }
}

 

運行程序,看到如下發送遙測結果成功:

 

 

 

本系列其他文章:

  1. (視頻)Azure IoT 中級(1)-Device Provisioning Service(DPS)概覽
  2. (視頻)Azure IoT 中級(2)-理解DPS組註冊和單獨註冊
  3. (視頻)Azure IoT 中級(3)-(案例1)使用DPS通過對稱密鑰進行單個設備註冊
  4. (視頻)Azure IoT 中級(4)-(案例2)使用DPS通過對稱密鑰進行設備組註冊
  5. (視頻)Azure IoT 中級(5)- 在 DPS/IoT Hub中使用X509證書的準備工作(1)瞭解證書鏈
  6. (視頻)Azure IoT 中級(6)- 在 DPS/IoT Hub中使用X509證書的準備工作(2)創建自簽名證書並驗證所有權
  7. (視頻)Azure IoT 中級(7)- (案例3)設備通過X509證書經DPS驗證後註冊到IoT Hub並開始通信

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章