我想使用 MQTTnet 复制此 Python 代码示例。
client = mqtt.Client(str(uuid4()))
current = dirname(__file__)
cerfile = join(current, "rcm_certchain_pem.cer")
keyfile = join(current, "rcm_pem_privkey.pkcs8")
context = create_default_context(Purpose.CLIENT_AUTH)
context.load_cert_chain(cerfile, keyfile)
client.tls_set_context(context)
client.tls_insecure_set(True)
client.connect("192.168.1.X", 1234)
我用 MQTTnet 尝试过这个。
var manager = new MqttFactory().CreateMqttClient();
var options = new MqttClientOptionsBuilder()
.WithCleanSession()
.WithClientId(Guid.NewGuid().ToString())
.WithTcpServer(address, port)
.WithTls(new MqttClientOptionsBuilderTlsParameters()
{
AllowUntrustedCertificates = true,
Certificates = new List<X509Certificate>
{
new X509Certificate2("Assets/rcm_certchain_pem.cer"),
new X509Certificate2("Assets/rcm_pem_privkey.pkcs8")
},
UseTls = true,
})
.WithKeepAlivePeriod(TimeSpan.FromSeconds(60))
.Build();
await manager.ConnectAsync(options, CancellationToken.None);
我总是遇到这个与加密相关的错误。
<Internal.Cryptography.CryptoThrowHelper+WindowsCryptographicException: Cannot find the requested object.
MQTTnet Wiki 中记录的示例(这不是您想要的)假设您有一个 PFX (PKCS12) 文件...其内容与您的密钥 + 证书相同,只是打包方式不同。
我尝试以编程方式创建 PFX,将其添加到 X509Certificate2 列表中,然后将其分配给 MqttClientOptionsBuilderTlsParameters.Certificates。笨重,但它有效。代码示例:
var mqttClientOptions = new MqttClientOptionsBuilder().
WithTcpServer(mybrokerhostname.com, 8883).
WithClientId(goofy-client-id)
);
MqttClientOptionsBuilderTlsParameters tlsParams = new MqttClientOptionsBuilderTlsParameters();
if (connectionData.VerifyCertificateChain)
{
byte[]? caCertFile = null;
X509Certificate2? caCert = null;
caCertFile = File.ReadAllBytes(connectionData.CaCertFilePath);
caCert = new X509Certificate2(caCertFile);
//Validate the server certificate using the user supplied CA certificate file.
tlsParams.UseTls = true;
tlsParams.CertificateValidationHandler = (certContext) =>
{
X509Chain chain = new X509Chain();
chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
chain.ChainPolicy.RevocationFlag = X509RevocationFlag.ExcludeRoot;
chain.ChainPolicy.VerificationFlags = X509VerificationFlags.NoFlag;
chain.ChainPolicy.VerificationTime = DateTime.Now;
chain.ChainPolicy.UrlRetrievalTimeout = new TimeSpan(0, 0, 0);
chain.ChainPolicy.CustomTrustStore.Add(caCert);
chain.ChainPolicy.TrustMode = X509ChainTrustMode.CustomRootTrust;
// convert provided X509Certificate to X509Certificate2
var x5092 = new X509Certificate2(certContext.Certificate);
return chain.Build(x5092);
};
}
else
{
//Don't bother verifying whether the server certificate is valid.
tlsParams.UseTls = true;
tlsParams.CertificateValidationHandler = _ => true;
}
List<X509Certificate2> clientCerts = new List<X509Certificate2>();
X509Certificate2? clientCert = null;
clientCert = X509Certificate2.CreateFromEncryptedPemFile(connectionData.ClientCertFilePath, connectionData.ClientKeyPassword, connectionData.ClientKeyFilePath);
var clientCertPFX = new X509Certificate2(clientCert.Export(X509ContentType.Pkcs12));
clientCerts.Add(clientCertPFX);
tlsParams.Certificates = clientCerts;
mqttClientOptions.WithTls(tlsParams);