#IoT Device Provisioning Example with Send/Receive Messages
1 messages · Page 1 of 1 (latest)
There a bunch of IoT Hub samples there. And some examples on the repo readme too. I'm pretty sure that is covered there...
yes, it's in the sample. Remember, it's a 2 steps approach: step 1: provisioning. Step 2 with the provisioned elements, you can connect to IoT Hub.
Hi Jose,
I am currently struggling with the provisioning part, as it keeps failing. I want to make sure I am inputting the correct values. I am trying to use the DPS example.
Should we use the Global device endpoint instead of the Service endpoint (which includes my domain name)?
The ID Scope is obtained from the portal.
I plan to use the group enrolment option, as the aim is to have a key that allows my device to connect based on the firmware. However, when it comes to:
const string SasKey = "alongkeyencodedbase64"
Do I simply obtain this from the portal? If so, which field should I use?
Do I need to perform any additional steps (for example, deriving a device key), or can I use it directly?
I also have attached root certs i am using for your refernce.
Thanks.
@keen skiff have you checked the Lear docs about this?
https://learn.microsoft.com/azure/iot-dps/quick-create-simulated-device-symm-key?pivots=programming-language-ansi-c&WT.mc_id=DT-MVP-5004179#create-a-device-enrollment
Yes, but that is for individual enrollment, meaning I would need to do this for each device individually? We could have batches of 100 devices so the reason for grouping is that it would unessarily time consuming to do this for each device.
So does the libary support group enrollement?
havene't touch this almost since I wrote it 😄 Let me refresh my memory and have a look
ok, so, here is the high level:
- DPS generates (or you provide) one group symmetric key
- Each device does NOT use the group key directly
- Instead, each device derives its own device key from:
- The group key
- Its unique registration ID
This is required for security and enforced by DPS. See https://learn.microsoft.com/en-us/azure/iot-dps/how-to-legacy-device-symm-key?tabs=windows&pivots=programming-language-csharp and https://learn.microsoft.com/en-us/azure/iot-dps/concepts-symmetric-key-attestation?tabs=windows
for each device, you need to compute the key with something like:
device_key = HMAC-SHA256(
decoded_group_key,
registration_id
)
- Result is Base64‑encoded
- That derived key is what the device uses for SAS authentication
- DPS validates it by recomputing the same value (see the previous link where it's explained)
Each device only needs:
- Scope ID (from DPS)
- Registration ID (unique per device)
- Derived device key (the one you've processed)
No IoT Hub hostname or device ID is required up front (DPS handles that).
You can flash each device with a config file in the internal storage with the 3 needed elements. Computing the key is easy and can be done at flash time (script, small C# code) and you can use nanoff to deploy the config file
The IoT Hub and the device ID and key will be given by DPS so that then you can connect
That's about it 🙂 Thanks for giving me the opportunity to refresh my memory 🙂
Note: I really don't recommend you to flash the master key on the device and do the computation here. It's risky as if that one get stolen or lost, you can enrol almost any device with it or mess up your system. That's one of the reason, DPS only accept a derivative key that it can recompute.
Thanks
This is how i am computing my key.
private static string ComputeDeviceKey(string groupPrimaryKeyBase64, string registrationId) { byte[] groupKey = Convert.FromBase64String(groupPrimaryKeyBase64); var hmac = new HMACSHA256(groupKey); byte[] deviceKey = hmac.ComputeHash( Encoding.UTF8.GetBytes(registrationId)); return Convert.ToBase64String(deviceKey); }
No, I prefer to compute the key on the device; otherwise, it would be easier just to use a standard SAS key , by registering all devices
I checked my device key being generated against the examples using PowerShell
And they are identical, so I think the keys are correct, but I am getting these exceptions:
++++ Exception System.Net.Sockets.SocketException - CLR_E_FAIL (4) ++++ ++++ Message: ++++ System.Net.Security.SslNative::SecureConnect [IP: 0000] ++++ ++++ System.Net.Security.SslStream::Authenticate [IP: 0054] ++++ ++++ System.Net.Security.SslStream::AuthenticateAsClient [IP: 000a] ++++ ++++ nanoFramework.M2Mqtt.MqttNetworkChannel::Connect [IP: 0063] ++++ ++++ nanoFramework.Azure.Devices.Provisioning.Client.ProvisioningDeviceClient::.ctor [IP: 008f] ++++ ++++ nanoFramework.Azure.Devices.Provisioning.Client.ProvisioningDeviceClient::Create [IP: 000a] ++++ ++++ BluetoothLESerial.azureiothub::TryProvisionDevice [IP: 00b5] ++++ ++++ BluetoothLESerial.azureiothub::WorkerLoop [IP: 0098] ++++ ++++ Exception nanoFramework.M2Mqtt.Exceptions.MqttConnectionException - 0x00000000 (4) ++++ ++++ Message: Socket exception connecting to the broker: -9984 ++++ nanoFramework.M2Mqtt.MqttClient::Connect [IP: 0049] ++++ ++++ nanoFramework.Azure.Devices.Provisioning.Client.ProvisioningDeviceClient::.ctor [IP: 008f] ++++ ++++ nanoFramework.Azure.Devices.Provisioning.Client.ProvisioningDeviceClient::Create [IP: 000a] ++++ ++++ BluetoothLESerial.azureiothub::TryProvisionDevice [IP: 00b5] ++++ ++++ BluetoothLESerial.azureiothub::WorkerLoop [IP: 0098] ++++ Exception thrown: 'nanoFramework.M2Mqtt.Exceptions.MqttConnectionException' in nanoFramework.M2Mqtt.dll
I am very new to DPS,
Previously, with LTE devices, I would pre-register all my device IDs, then use the https API to allow the device to generate SAS. This way, there is no chance of a device being compromised; it can generate more devices, so I am thinking DPS could be a security vulnerability.
@keen skiff the above looks like an issue with the root CA. A couple of suggestions: either use the one included in the Azure SDK, or if you're using another, make sure to test it with a plain simple app (like the SSL in samples repo) connecting to an Azure IoT endpoint just to check the connection (and validate the SSL negotiation).
I believe we just need to use DigiCert Global Root G2. I will copy the file content from the sample to see if it makes a difference. Is it possible to disable the root certificate check for testing purposes?
It seems the samples have Baltimore CyberTrust Root and DigiCert Global Root G2
I believe DigiCert Global Root G2 should be sufficient. I have attached what i am using
@keen skiff have you tested with a sample app as I've suggested above?
Just trying, it uses
X509Certificate2 deviceCert = new X509Certificate2(cert, privateKey, "1234");
Where else my required projects require the group, I was using
_deviceKey = ComputeDeviceKey(GroupPrimaryKey, RegistrationID);
I believe the sample using X509?
So for my _deviceKey? Do i need to do anything in perticualr?
I suggest you focus on one issue at a time. 😅
Either root CA or computing the device key...
Ok, so which example would you recommend I start with? Regardless of the authentication method, I still need the root certificate, which is DigiCert Global Root G2. However, it seems the DPS example requires us to provide our own X.509 certificate, so I will need to look at how I can generate my own key and certificate.
I have never used 509 certs so will need to check how to use to create it
From the above I think we're not on the same page....
My previous answers were related with the root CA cert to CONNECT to Azure endpoint.
If you're looking for a cert to sign the device keys, that's a totally different story.
My issue seems to be failing at this point:
provisioning = ProvisioningDeviceClient.Create( DpsAddress, IdScope, RegistrationID, _deviceKey, _azureCA); }
Double check your CA cert.
This is the Global G2 cert?
First of all, does this library support group provisioning, as there seem to be no examples of with the Nano Framework? This worked with free rtos example in C, so was trying to replicate this
I just tried Individual enrollment, same issue, so how can I check that the cert i am applying is correct? Are there any debug changes I can do? Should the sting include
-----BEGIN CERTIFICATE-----
Yes, that has to be there. You just grab the certificate content and paste it as it is. Don't mess with it.
Still, if your issue is with System.Net.Security.SslStream::Authenticate I strongly suggest that you "debug" the certificate with the SSL sample app has I've recomended
Yes, i am just using the following process:
string pem = Properties.Resources.GetString(
Properties.Resources.StringResources.DigiCertGlobalRootG2);
Which example app did you recomend, was this independent from the Azure IoT examples?
SSL sample in the Samples repo
great thank i will check it out
Check the sample pointed out few times. Read the DPS docs. Everything is documented. Just follow the docs!
CA Certs can be specific to your DPS, just read the doc and check which one is the right one.
i think you are correct. for some reason my when i check the string and the object its referring to the old Baltimore Cyber Trust cert which is now expired. I have made sure the project includes on the G2 cert, but it seems it not being loaded.
Can it be that the old certs are being cached some how in project?
Maybe i need to delete a file manually?
certs aren't cached in the project
if you feel better, manually delete bin and obj folders
ok let me try
and yes Baltimore should not be used anymore
For some reason, when I run the SSL projects, it corrupts something on my device, where i need to reflash the ESp32. I expirmenting with connecting with Azure IoT Hub using basic methods
Normally if you need to reflash, it is because the system is in a boot loop. If this happens again. putty in with baud rate 921600 and see where it breaks (place Debug.WriteLine along the executing path).
Ok will give that ago.
I am still having issues with SSL.
I am placing my Cert as a string variable instead.
` private const string AzureRootCertPem ="MIID ...=";
Then calling:
_azureIoT = new DeviceClient(
IotBrokerAddress,
DeviceID,
SasKey,
azureCert: new X509Certificate(cert));
bool ok = _azureIoT.Open();
`
Then i am getting:
[AzureBasic] Opening connection... ++++ Exception System.Exception - CLR_E_FAIL (1) ++++ ++++ Message: ++++ System.Convert::FromBase64String [IP: 0000] ++++ ++++ nanoFramework.Azure.Devices.Helper::GetSharedAccessSignature [IP: 0021] ++++ ++++ nanoFramework.Azure.Devices.Client.DeviceClient::Open [IP: 0099] ++++ ++++ BluetoothLESerial.AzureIotHubBasic::Start [IP: 0044] ++++ ++++ BluetoothLESerial.Program::Main [IP: 014f] ++++ Exception thrown: 'System.Exception' in mscorlib.dll [AzureBasic] Start failed: Exception was thrown: System.Exception
Is there anything additional I can do for debugging to see what is causing this?
When I try to run the TLS project ParseCertificate and run the code, it seems to be just running my actual application. For some reason, it is as if I can not overwrite the previous project. Am I missing a step?
Also, how can I confirm that my date and time are also set correctly?
Out of curosity, is it possible to connect wire shark to modules to see what is happening or what points its failing?
Just use debug and breakpoint and you will see what is happening.
All this is perfectly working. I have some devices connecting like this to IoT hub. The sample is based on this.
Ok, for example, if we want to see what is happening inside, I can not place a breakpoint inside the compiled functions.
_azureIoT = new DeviceClient( IotBrokerAddress, DeviceID, SasKey, azureCert: new X509Certificate(cert)); bool ok = _azureIoT.Open();
I am trying to connect using the basic method. My device ID is a valid ID, the SAS key is valid for a week, and the cert is GIgiG2. I don't use a client cert, but just the root cert.
Additionally, is there any issue with the library version I need to keep in mind?
If there is a dependency mismatch on the library version then you will not be able to deploy (error during deployment proccess).
ok
How do i add a break point inside actuall libary, to see the point it fails, is this possible?
Possible but you need to download the source code of the libary then add it to you project and add the reference to that library project. Remember to remove the nuget of that library from your project.
I am using ESp32-s3, would that have any reflection on what is happenong
Default official firmware has reflection enabled.
ok
At the moment i am just depending on the output display in VS if i was to use the direct COM port, can i get more information on what's happening?
baudrate 115200 you see the RTOS boot message, at 912600 you see the Debug.WriteLine and Console.WriteLine messages. Debug.WriteLine will not appear in release mode app.
So it the RTOS that i need to read, as Debug.Write, i Can already see it?
Just to confirm these are the packeges i am using:
Are these correct? As i have M2Mqtt and M2Mqtt.Core.
Just want to make sure there is no clash with libaries or any compatability issues?
<packages> <package id="nanoFramework.Azure.Devices.Client" version="1.2.107" targetFramework="netnano1.0" /> <package id="nanoFramework.CoreLibrary" version="1.17.11" targetFramework="netnano1.0" /> <package id="nanoFramework.Device.Bluetooth" version="1.1.115" targetFramework="netnano1.0" /> <package id="nanoFramework.Hardware.Esp32" version="1.6.37" targetFramework="netnano1.0" /> <package id="nanoFramework.Json" version="2.2.203" targetFramework="netnano1.0" /> <package id="nanoFramework.M2Mqtt" version="5.1.209" targetFramework="netnano1.0" /> <package id="nanoFramework.M2Mqtt.Core" version="5.1.209" targetFramework="netnano1.0" /> <package id="nanoFramework.Networking.Sntp" version="1.6.42" targetFramework="netnano1.0" /> <package id="nanoFramework.ResourceManager" version="1.2.32" targetFramework="netnano1.0" /> <package id="nanoFramework.Runtime.Events" version="1.11.32" targetFramework="netnano1.0" /> <package id="nanoFramework.Runtime.Native" version="1.7.11" targetFramework="netnano1.0" /> <package id="nanoFramework.System.Collections" version="1.5.67" targetFramework="netnano1.0" /> <package id="nanoFramework.System.Device.Wifi" version="1.5.139" targetFramework="netnano1.0" /> <package id="nanoFramework.System.IO.Streams" version="1.1.96" targetFramework="netnano1.0" /> <package id="nanoFramework.System.Math" version="1.5.116" targetFramework="netnano1.0" /> <package id="nanoFramework.System.Net" version="1.11.50" targetFramework="netnano1.0" /> <package id="nanoFramework.System.Net.Http" version="1.5.200" targetFramework="netnano1.0" /> <package id="nanoFramework.System.Text" version="1.3.42" targetFramework="netnano1.0" /> <package id="nanoFramework.System.Threading" version="1.1.52" targetFramework="netnano1.0" /> </packages>
what message do you get when you debug with Visual Studio?
If you have Debug.WriteLine in your code. If you use some serial terminal (i use putty or teraterm) then with baudrate 921600 I can see the Debug.WriteLine output. The debug session of VS must be off/stopped for the serial terminal to work.
This is output i am getting when i try to open a connection:
[NET] Online: 192.168.1.187 DNS OK -> 51.104.30.143
[SNTP] Started, waiting for time sync...
[SNTP] Final UTC time = 04/10/2026 09:23:08
[AzureBasic] Creating DeviceClient...
[AzureBasic] Opening connection...
++++ Exception System.Net.Sockets.SocketException - CLR_E_FAIL (1) ++++
++++ Message:
++++ System.Net.Security.SslNative::SecureConnect [IP: 0000] ++++
++++ System.Net.Security.SslStream::Authenticate [IP: 0054] ++++
++++ System.Net.Security.SslStream::AuthenticateAsClient [IP: 000a] ++++
++++ nanoFramework.M2Mqtt.MqttNetworkChannel::Connect [IP: 0098] ++++
++++ nanoFramework.Azure.Devices.Client.DeviceClient::Open [IP: 00b6] ++++
++++ BluetoothLESerial.AzureIotHubBasic::Start [IP: 0046] ++++
++++ BluetoothLESerial.Program::Main [IP: 014f] ++++
++++ Exception nanoFramework.M2Mqtt.Exceptions.MqttConnectionException - 0x00000000 (1) ++++
++++ Message: Socket exception connecting to the broker: -29312
++++ nanoFramework.M2Mqtt.MqttClient::Connect [IP: 0049] ++++
++++ nanoFramework.Azure.Devices.Client.DeviceClient::Open [IP: 00b6] ++++
++++ BluetoothLESerial.AzureIotHubBasic::Start [IP: 0046] ++++
++++ BluetoothLESerial.Program::Main [IP: 014f] ++++
Exception thrown: 'nanoFramework.M2Mqtt.Exceptions.MqttConnectionException' in nanoFramework.M2Mqtt.dll
Is serial terminal nessary, if i am using VS?
no, serial terminal is only necessary to see if the MCU is doing a boot loop.
It looks like you have a socket error. First is the dateTime correct on the MCU (date time is in UTC). second is your CA cert valid and the correct one.
Cert or key issue.
I am confident the SAS and root cert is correct , as this what i am using for other devices and it working.
But i am declaring them as strings.
Is there any other way to verify they are formated correctly before i call an OPEN
@keen skiff I'll ask this one last time: have you validated the root CA with the sample client app connecting an Azure endpoint?
Well the SSL example projects, is not able to run, it just stops loading, so i have tried to port the code on my project, but not much luck. I believe this is the ParseCertificate project?
Unless i need to configure it in particular way?
Also there is plugin for Azure Full Managed? Is that of any advantage to use
Parsing a certificate does not validate if it can be used to connect to Azure.
Please use the SecureClient WiFi sample.
On slightly side questions
I am trying to run project, but the output display seems to be running the previous project(my project); Why does this happen?
Do i need to do something before jumping to this new project.
It
Error: a2000000 Waiting for debug commands... The nanoDevice runtime is loading the application assemblies and starting execution. The program '[1] .NET nanoFramework application: Managed' has exited with code 0 (0x0).
I get error when running the new project
Are you using Generics in your code
No i am just running the example project SecureClient WiFi sample.
Are you using the preview firmware or preview VS extension
Previous Firmware
Is this a running the Sample code or your own code. Normally Error: a200000 is due to syntax that is not supported.
Well i am now trying to run the sample code
And what firmware are you using on your device (which hardware, BTW)?
Hadrware is ESP32-S3-WROOM.
What must i type in cmd to confirm the firmware? Sorry..
The second icon in the Device Explorer
Firmware build Info:
Date: Apr 8 2026
Type: MinSizeRel build, chip rev. >= 0, support for PSRAM, support for BLE
CLR Version: 1.16.0.449
Compiler: GNU ARM GCC v14.2.0
can you run this #1431334376054198272 message in a hello world to see if you have enough memory
Well i have dev kit with 16mb PSRAM, so memory is not an issue, or attest i dont it should
Where do i run # uknown?
public static void PrintMemory(string msg)
{
NativeMemory.GetMemoryInfo(NativeMemory.MemoryType.Internal, out uint totalSize, out uint totalFreeSize, out uint largestBlock);
Debug.WriteLine($"\n{msg}-> Internal Total Mem {totalSize} Total Free {totalFreeSize} Largest Block {largestBlock}");
Debug.WriteLine($"nF Mem {nanoFramework.Runtime.Native.GC.Run(false)}\n ");
NativeMemory.GetMemoryInfo(NativeMemory.MemoryType.SpiRam, out uint totalSize1, out uint totalFreeSize1, out uint largestBlock1);
Debug.WriteLine($"\n{msg}-> SpiRam Total Mem {totalSize1} Total Free {totalFreeSize1} Largest Block {largestBlock1}");
}
}```
Can you run the hello world app from the executable template?
Just create a new project and deploy
ok, i can add that at start of my project
Hello World-> Internal Total Mem 284548 Total Free 40152 Largest Block 31744
nF Mem 15612
Hello World-> SpiRam Total Mem 0 Total Free 0 Largest Block 0
This is my usage:
`Hello World-> Internal Total Mem 284548 Total Free 40152 Largest Block 31744
nF Mem 15612
Hello World-> SpiRam Total Mem 0 Total Free 0 Largest Block 0`
By the way i am using
nanoFramework.Azure.Devices.Client
but what is nanoFramework.Azure.Devices.Client.FullyManged? As this is not yet insalled?
as explained in those nugets, the fully managed is to be used with AT Modems for example. It has no dependency on anything native for networking.
Ok, i been doing a little debugging, using the Step into option, and this is what it displays before the exception. It seems it could be related to SAS Key
tep into: Stepping over non-user code 'System.Web.Private.HttpUtility.IsSafe' Step into: Stepping over non-user code 'System.Web.Private.HttpUtility.UrlEncodeBytesToBytesInternal' Step into: Stepping over non-user code 'System.Web.Private.HttpUtility.UrlEncodeToBytes' Step into: Stepping over non-user code 'System.Web.Private.HttpUtility.UrlEncode' Step into: Stepping over non-user code 'System.Web.Private.HttpUtility.UrlEncode' Step into: Stepping over non-user code 'System.Web.Private.HttpUtility.UrlEncode' Step into: Stepping over non-user code 'nanoFramework.Azure.Devices.Helper.GetSharedAccessSignature' ++++ Exception System.Exception - CLR_E_FAIL (1) ++++ ++++ Message: ++++ System.Convert::FromBase64String [IP: 0000] ++++ ++++ nanoFramework.Azure.Devices.Helper::GetSharedAccessSignature [IP: 0021] ++++ ++++ nanoFramework.Azure.Devices.Client.DeviceClient::Open [IP: 0099] ++++ ++++ BluetoothLESerial.AzureIotHubBasic::Start [IP: 0045] ++++ ++++ BluetoothLESerial.Program::Main [IP: 0156] ++++ Exception thrown: 'System.Exception' in mscorlib.dll
Just to confirm, the SAS key needs to be the token
https://learn.microsoft.com/en-us/azure/iot-hub/authenticate-authorize-sas?tabs=node
In this formate
SharedAccessSignature sr=myhub.azure-devices.net%2fdevices%2fdevice1&sig=13y8ejUk2z7PLmvtwR5RqlGBOVwiq7rQR3WZ5xZX3N4%3D&se=1456971697
This shows that you do not have PSRAM in your ESP32, so not enough memory to run TLS.
- Either the firmware is not correct or the ESP32 S3 really does not have PSRAM
- What is the make and model of the ESP32 S3 do you have?
Internal Total Mem 284548 Total Free 40152 Largest Block 31744 nF Mem 15612
a) Total Free is the max free memory in the native side
b) Largest Block is the largest contiguous free memory
c) nF Mem is the free memory that nanoframework c# has access to.
SpiRam Total Mem 0 Total Free 0 Largest Block 0
SpiRam is the PSRAM
I am using the following:
https://eu.mouser.com/ProductDetail/Espressif-Systems/ESP32-S3-DevKitC-1-N32R16V?qs=sqEgtWRSLJ3pTWIVKUeIew%3D%3D&countryCode=GB¤cyCode=GBP
This is my device information:
C:\Users\djosh>nanoff --platform esp32 --serialport COM8 --devicedetails
.NET nanoFramework Firmware Flasher v2.5.131+6bd4d0daab
Copyright (C) 2019 .NET Foundation and nanoFramework project contributors
Reading details from chip...OK
Connected to:
ESP32-S3 (ESP32-S3 (QFN56) (revision v0.2)) Features Wi-Fi, BT 5 (LE), Dual Core + LP Core, 240MHz, Embedded PSRAM 16MB (AP_1v8) Flash size 32MB unknown from MACRONIX (manufacturer 0x194 device 0x-32711) PSRAM: 16MB Crystal 40MHz MAC 90:E5:B1:CB:D2:88
The firmware is ESP32_S3_BLE , What must i have installed, as I don't see a PSRAM variation for the S3?
In addition to this, I have realised that the SAS key should be the device primary key, with the token generated internally. Previously, I was generating the token myself. I no longer receive an interrupt; instead, the system hangs when the Open connection is called, which may indicate a memory issue, as previously mentioned.
Flash it with the ESP32_S3_ALL firmware then run the memory test.
nanoff --target ESP32_S3_ALL --update --serialport COMx --masserase
Thanks, I got it working, i can communicate with Azure IoT Hub
Hello World-> Internal Total Mem 317307 Total Free 110815 Largest Block 31744 nF Mem 15411540 Hello World-> SpiRam Total Mem 16777216 Total Free 1307860 Largest Block 1277952
I have some general questions regarding security regarding IoT Hub, I will open a new post
Wow I am jealous, you have 15MB of nF ram.