0 votes
by (120 points)

Hi I am evaluating Rebex TlsSocket to establish secured TLS1.2 MQTT connection with Aws IoT Hub. We have volume field devices and a successful trial should help us connect all the field devices with AWS IoT Hub.

I referred to this article and followed all steps https://forum.rebex.net/9807/how-to-use-tlssocket-directly?show=9807#q9807

Code:

this.tlsSocket = new TlsClientSocket();
tlsSocket.LogWriter = new Rebex.FileLogWriter(@"D:\log.txt",Rebex.LogLevel.Debug);
this.tlsSocket.Connect(new IPEndPoint(this.remoteIpAddress, this.remotePort));
tlsSocket.Parameters.Version = TlsVersion.TLS12;
//var cert = Certificate.LoadPfx("devicecert.pfx", "");
tlsSocket.Parameters.CertificateRequestHandler = CertificateRequestHandler.CreateRequestHandler(clientCert);
tlsSocket.Parameters.CertificateVerifier = CertificateVerifier.Default;
tlsSocket.ValidatingCertificate += new EventHandler<SslCertificateValidationEventArgs>(tlsSocket_ValidatingCertificate);

I am getting following error:

2023-05-23 00:12:00 INFO TlsSocket(54267293)[1] TLS: Performing client certificate authentication.
2023-05-23 00:12:00 DEBUG TlsSocket(54267293)[1] TLS: Error while processing TLS packet: System.Security.Cryptography.CryptographicException: Unable to create SHA256 hash using 楍牣獯景⁴湅慨据摥䌠祲瑰杯慲桰捩倠潲楶敤⁲ㅶ〮� (0x80090008).
   at ghric.xtdkc.wbbry(Byte[] p0, aippr p1)
   at Rebex.Security.Cryptography.AsymmetricKeyAlgorithm.SignHash(Byte[] hash, SignatureHashAlgorithm hashAlgorithm)
   at ghric.autbd.hwlnr(Byte[] p0, Int32 p1, Int32 p2, ivnfx p3)
   at ghric.autbd.fwlia(Byte[] p0, Int32 p1, Int32 p2)
   at ghric.yexzh.fcfxr(Byte[] p0, Int32 p1, Int32 p2)
   at ghric.yexzh.loqiv()
2023-05-23 00:12:01 INFO TlsSocket(54267293)[1] TLS: Fatal Alert:InternalError was sent.
2023-05-23 00:13:07 Opening log file.
2023-05-23 00:13:07 INFO FileLogWriter(1)[1] Info: Assembly: Rebex.Common R5.11 for .NET Compact Framework 3.5

My client Certificate file "devicecert.pfx does not have any password set. I am able to use same certificate on .NET 4.5 Windows to connect.

Applies to: Rebex TLS

1 Answer

0 votes
by (138k points)

PFX support is limited on .NET CF 3.5 on platforms that don't support SHA-2, which seems to be the case here.

As a workaround, load the certificate and the private key from files. To create those two files, load the PFX file on .NET 4.5 on Windows and convert it to a .cer/.pri file pair:

var cert = Certificate.LoadPfx("devicecert.pfx", password); 
cert.Save("devicecert.cer", CertificateFormat.Base64Der);
cert.SavePrivateKey("devicecert.key", password, PrivateKeyFormat.Base64Pkcs8, true);

Then, in .NET CF 3.5 application, load the certificate from those two files instead of the PFX:

var clientCert = Certificate.LoadDerWithKey("devicecert.cer", "devicecert.key", "password");
ago by (120 points)
2023-05-29 22:17:16.854 DEBUG TlsClientSocket(1)[5] TLS: Verifying server key exchange signature.
2023-05-29 22:17:16.881 DEBUG TlsClientSocket(1)[5] TLS: Using ephemeral ECDH public key exchange with NIST P-256 curve.
2023-05-29 22:17:16.895 DEBUG TlsClientSocket(1)[5] TLS: Client certificate authentication was requested.
2023-05-29 22:17:16.895 DEBUG TlsClientSocket(1)[5] TLS: Suitable client certificate is available ('CN=AWS IoT Certificate').
2023-05-29 22:17:16.910 DEBUG TlsClientSocket(1)[5] TLS: HandshakeMessage:Certificate was sent.
2023-05-29 22:17:16.922 DEBUG TlsClientSocket(1)[6] TLS: HandshakeMessage:ClientKeyExchange was sent.
2023-05-29 22:17:16.945 INFO TlsClientSocket(1)[6] TLS: Performing client certificate authentication.
2023-05-29 22:17:16.975 DEBUG TlsClientSocket(1)[6] TLS: Error while processing TLS packet: System.Security.Cryptography.CryptographicException: Unable to export private key in order to use a more capable algorithm. ---> System.Security.Cryptography.CryptographicException: Private key is not exportable.
   at xoosa.nghvv.jyowc(Boolean p0, ICspAsymmetricAlgorithm p1, Boolean p2)
   at xoosa.njzfh.kbjyg(Boolean p0)
   at xoosa.uzrll.zdwrd(rdmyh p0, Func`2 p1, String p2)
   --- End of inner exception stack trace ---
   at xoosa.uzrll.zdwrd(rdmyh p0, Func`2 p1, String p2)
   at xoosa.uzrll.zzwgx(wkbqw p0)
   at xoosa.uzrll.aqxjn(inlme p0)
   at xoosa.uzrll.cnpdg(Byte[] p0, inlme p1)
   at Rebex.Security.Cryptography.AsymmetricKeyAlgorithm.SignHash(Byte[] hash, SignatureHashAlgorithm hashAlgorithm)
   at Rebex.Security.Certificates.Certificate.SignHash(Byte[] hash, SignatureHashAlgorithm alg, Boolean silent)
   at xoosa.ftwpq.<OnHandshakeReceivedClient>d__46.tbjgj()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at xoosa.ftwpq.<OnHandshakeReceived>d__44.rqnzf()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at xoosa.sccnz.<ProcessHandshakeAsync>d__73.jqlma()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at xoosa.sccnz.<processInnerAsync>d__79.bantj()
2023-05-29 22:17:16.983 INFO TlsClientSocket(1)[6] TLS: Fatal Alert:InternalError was sent.
ago by (120 points)
Hi Lukas,

If you have any working sample / instruction to use TLS library with AWs IoT for WinCE6 devices then it will be great. We can follow the same process.
ago by (138k points)
Sorry, we don't have any ready-to-use sample code yet.

The last log was created on desktop Windows, right? Did you use Certificate.LoadPfx there? In that case, specify the KeySetOptions.AlwaysCng option in the LoadPfx call. Otherwise, the key might get imported in to the legacy CryptoAPI container which is not fully capable.

But just guessing here, it's hard to tell with partial log and no code.
ago by (120 points)
Sorry my bad for not specifying the code.
Tried the KeySetOptions.AlwaysCng option getting error.

var cert = Certificate.LoadPfx("devicecert.pfx", string.Empty, KeySetOptions.AlwaysCng);
            cert.Save("device.cer", CertificateFormat.Base64Der);
            cert.SavePrivateKey("device.key", "", PrivateKeyFormat.Base64Pkcs8, false);


Error:
System.Security.Cryptography.CryptographicException: 'Unable to export CNG key (0x80090029).'
ago by (138k points)
For key conversion, you have to specify KeySetOptions.Exportable as well:
    var cert = Certificate.LoadPfx("devicecert.pfx", string.Empty, KeySetOptions.AlwaysCng | KeySetOptions.Exportable);
    cert.Save("device.cer", CertificateFormat.Base64Der);
    cert.SavePrivateKey("device.key", "", PrivateKeyFormat.Base64Pkcs8, false);
...