[英]Azure IoT Hub Unauthorized Access for Additional Devices
我在嘗試使用 x509 證書通過 DPS 將第二個設備注冊到 IoT 中心時遇到問題。 我的根證書頒發機構在 DPS 和 IoT 中心(通過 openssl 生成)上都存在並經過驗證。 至於客戶端證書,一旦應用程序啟動(如果不存在),我就會在下面的代碼中生成它。 困擾我的是每台設備都正確注冊到 Azure DPS,但只有第一個設備獲得授權和注冊。 這可能是我在創建客戶端證書期間正在做的事情弄亂了它嗎? 此外,在設備注冊到 IoT 中心期間,在此行中發現錯誤:
DeviceRegistrationResult result = await provisioningDeviceClient.RegisterAsync().ConfigureAwait(false);
添加錯誤:
2019/12/16 09:37:38.309|錯誤| 嘗試啟動服務時發現錯誤設備無法注冊@IoT 中心:設備無法正確配置:AMQP 傳輸異常 | Tidel.DeviceAgent.DeviceAgent |
客戶端證書生成
X509Certificate2 caRootCertificate;
X509Store caStore = new X509Store(StoreName.Root, StoreLocation.LocalMachine);
caStore.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
X509Certificate2Collection signerCollection = (X509Certificate2Collection)caStore.Certificates.Find(X509FindType.FindByIssuerName, "CERTNAME", true);
caStore.Close();
if (signerCollection.Count != 0)
{
caRootCertificate = signerCollection[0];
using (var rsa = RSA.Create())
{
rsa.KeySize = 2048;
var clientCertificateRequest = new CertificateRequest($"CN={_writableOptions.Value.RegistrationId}", rsa, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
clientCertificateRequest.CertificateExtensions.Add(new X509BasicConstraintsExtension(false, false, 0, false));
var issuerSubjectKey = caRootCertificate.Extensions["Subject Key Identifier"].RawData;
var segment = new ArraySegment<byte>(issuerSubjectKey, 2, issuerSubjectKey.Length - 2);
var authorityKeyIdentifier = new byte[segment.Count + 4];
authorityKeyIdentifier[0] = 0x30;
authorityKeyIdentifier[1] = 0x16;
authorityKeyIdentifier[2] = 0x80;
authorityKeyIdentifier[3] = 0x14;
segment.CopyTo(authorityKeyIdentifier, 4);
clientCertificateRequest.CertificateExtensions.Add(new X509Extension("2.5.29.35", authorityKeyIdentifier, false));
var sanBuilder = new SubjectAlternativeNameBuilder();
sanBuilder.AddDnsName(_writableOptions.Value.RegistrationId);
var sanExtension = sanBuilder.Build();
clientCertificateRequest.CertificateExtensions.Add(sanExtension);
clientCertificateRequest.CertificateExtensions.Add(new X509EnhancedKeyUsageExtension(new OidCollection { new Oid("1.3.6.1.5.5.7.3.2") }, false));
clientCertificateRequest.CertificateExtensions.Add(new X509SubjectKeyIdentifierExtension(clientCertificateRequest.PublicKey, false));
var notBefore = DateTimeOffset.UtcNow.AddDays(-1);
if (notBefore < caRootCertificate.NotBefore)
{
notBefore = new DateTimeOffset(caRootCertificate.NotBefore);
}
var notAfter = DateTimeOffset.UtcNow.AddDays(365);
if (notAfter > caRootCertificate.NotAfter)
{
notAfter = new DateTimeOffset(caRootCertificate.NotAfter);
}
var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
var unixTime = Convert.ToInt64((DateTime.UtcNow - epoch).TotalSeconds);
var serial = BitConverter.GetBytes(unixTime);
using (var cert = clientCertificateRequest.Create(caRootCertificate, notBefore, notAfter, serial))
{
X509Certificate2 client = cert.CopyWithPrivateKey(rsa);
return await Task.FromResult(client);
}
}
}
else
{
throw new FileNotFoundException($"Could not find a root certificate.");
}
設備注冊到 DPS
Attestation attestation = X509Attestation.CreateFromClientCertificates(new X509Certificate2(certificate.Export(X509ContentType.Cert)));
IndividualEnrollment individualEnrollment = new IndividualEnrollment(_writableOptions.Value.RegistrationId, attestation)
{
DeviceId = _writableOptions.Value.DeviceId,
ProvisioningStatus = ProvisioningStatus.Enabled
};
individualEnrollmentResult = await _provisioningServiceClient.CreateOrUpdateIndividualEnrollmentAsync(individualEnrollment).ConfigureAwait(false);
設備注冊到 IOT HUB
using (var certificatePassword = new X509Certificate2(certificate.GetRawCertData(), _writableOptions.Value.CertPass))
{
using (var security = new SecurityProviderX509Certificate(certificatePassword))
{
using (var transport = new ProvisioningTransportHandlerAmqp(TransportFallbackType.TcpOnly))
{
ProvisioningDeviceClient provisioningDeviceClient = ProvisioningDeviceClient.Create(_writableOptions.Value.AzureEndpoint, _writableOptions.Value.IdScope, security, transport);
DeviceRegistrationResult result = await provisioningDeviceClient.RegisterAsync().ConfigureAwait(false);
IAuthenticationMethod authenticationMethod = new DeviceAuthenticationWithX509Certificate(result.DeviceId, certificate);
DeviceClient deviceClient = DeviceClient.Create(result.AssignedHub, authenticationMethod, TransportType.Amqp_Tcp_Only);
return await Task.FromResult(deviceClient);
}
}
}
我想通了這個問題。 在商店中生成證書時,我使用 FindByIssuerName 來定位證書。
X509Certificate2Collection signerCollection = (X509Certificate2Collection)caStore.Certificates.Find(X509FindType.FindByIssuerName, "CERTNAME", true);
進一步調查后,商店里有兩個名稱完全相同的證書。 問題:MMC 管理單元只顯示一個證書。 環顧四周后,建議在某處對商店運行 storerepair 命令。 運行 store repair 命令后,我可以在 MMC 中看到兩個證書,並且能夠刪除有問題的證書,從而阻止檢測到有效證書。
Windows 版本:Windows Embedded 8.1 Industry Pro
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.