{"record":{"id":"4229b44d426ac0dc","repo":"mgth/LittleBigMouse","slug":"vidaa-rejected-tls-select-the-pkcs-12-client-certificate","errorCode":null,"errorMessage":"VIDAA rejected TLS. Select the PKCS#12 client certificate extracted from the official app.","messagePattern":"VIDAA rejected TLS\\. Select the PKCS#12 client certificate extracted from the official app\\.","errorType":"exception","errorClass":"AuthenticationException","httpStatus":null,"severity":"error","filePath":"LittleBigMouse.Plugins/LittleBigMouse.Plugin.Vcp.Avalonia/HisenseVidaa/VidaaMqttConnection.cs","lineNumber":69,"sourceCode":"                X509KeyStorageFlags.EphemeralKeySet | X509KeyStorageFlags.Exportable));\n        }\n\n        try\n        {\n            await ssl.AuthenticateAsClientAsync(new SslClientAuthenticationOptions\n            {\n                TargetHost = host,\n                ClientCertificates = certificates,\n                // Several VIDAA U6 brokers advertise newer TLS but abort encrypted\n                // application data after negotiating it. The official Android client\n                // uses TLS 1.2 for this MQTT channel.\n                EnabledSslProtocols = SslProtocols.Tls12,\n                CertificateRevocationCheckMode = X509RevocationMode.NoCheck,\n            }, cancellationToken).ConfigureAwait(false);\n        }\n        catch (AuthenticationException e) when (certificates.Count == 0)\n        {\n            throw new AuthenticationException(\n                \"VIDAA rejected TLS. Select the PKCS#12 client certificate extracted from the official app.\", e);\n        }\n\n        _stream = ssl;\n        await WritePacketAsync(BuildConnectPacket(clientId, username, password), cancellationToken)\n            .ConfigureAwait(false);\n        (byte Header, byte[] Payload) connack;\n        try\n        {\n            connack = await ReadPacketAsync(_stream, cancellationToken).ConfigureAwait(false);\n        }\n        catch (IOException e) when (certificates.Count == 0)\n        {\n            throw VidaaCertificate.MissingException(e);\n        }\n        if ((connack.Header >> 4) != 2 || connack.Payload.Length < 2)\n            throw new IOException(\"VIDAA returned an invalid MQTT connection response.\");\n        if (connack.Payload[1] != 0)","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/mgth/LittleBigMouse/blob/7a42f01d47d99d223b8ee33ba4019af82adf1c48/LittleBigMouse.Plugins/LittleBigMouse.Plugin.Vcp.Avalonia/HisenseVidaa/VidaaMqttConnection.cs#L51-L87","documentation":"During ConnectAsync the library performs the TLS handshake against the projector with SslProtocols.Tls12. If the handshake fails with AuthenticationException AND no client certificate was configured (certificates.Count == 0), it rethrows an AuthenticationException explaining that VIDAA requires the PKCS#12 client certificate extracted from the official app. This filter distinguishes 'missing client cert' from other TLS failures.","triggerScenarios":"Calling OpenMqttAsync/ConnectAsync without a certificatePath (or empty) while the VIDAA projector enforces mutual TLS: the server rejects the anonymous handshake during SslStream.AuthenticateAsClientAsync.","commonSituations":"First-time setup where the user never extracted the client certificate from the official Hisense app; config field for certificate path left blank; user thought only the server certificate was needed; projector firmware enforcing mTLS on the MQTT (port 36669) channel.","solutions":["Extract the PKCS#12 client certificate from the official Hisense VIDAA mobile app and supply its path (and password) to the connection.","Confirm the certificatePath configuration is actually set and non-empty so the certificate collection is populated.","Verify the .p12 loads correctly (correct password, PKCS#12 format) — an unloadable cert effectively means no cert is presented.","If a certificate IS configured and this still fires, check the exception's inner AuthenticationException for a different TLS cause (protocol mismatch, untrusted server chain)."],"exampleFix":"// before\nawait connection.OpenMqttAsync(certPath: null, password: null); // TLS rejected\n\n// after\nawait connection.OpenMqttAsync(\n    certPath: @\"C:\\certs\\vidaa-client.p12\",  // extracted from official VIDAA app\n    password: pfxPassword);","handlingStrategy":"validation","validationCode":"if (string.IsNullOrWhiteSpace(certificatePath))\n    throw new InvalidOperationException(\"VIDAA requires the PKCS#12 client certificate extracted from the official app; configure its path before connecting.\");","typeGuard":"static bool HasClientCertificate(string? path) =>\n    !string.IsNullOrWhiteSpace(path) && File.Exists(path);","tryCatchPattern":"try\n{\n    await connection.OpenMqttAsync(certificatePath, password, ct);\n}\ncatch (AuthenticationException ex) when (ex.Message.Contains(\"VIDAA rejected TLS\"))\n{\n    // instruct the user to extract and select the PKCS#12 client certificate from the official app\n}","preventionTips":["Always configure the client certificate extracted from the official Hisense VIDAA app before the first connection.","Validate the .p12 loads (correct password) at startup so the handshake actually presents it.","Keep the certificate path field mandatory in your setup UI for VIDAA projectors."],"tags":["csharp","tls","mtls","certificate","authentication"],"backgroundTag":"authentication-required","analyzedSha":"7a42f01d47d99d223b8ee33ba4019af82adf1c48","analyzedAt":"2026-09-16T00:35:00.514Z","contentChangedAt":"2026-09-16T00:35:00.514Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}