nauful / LibUA

Open-source OPC UA client and server library
Apache License 2.0
258 stars 93 forks source link

Basic256Sha256 - Error Incomplete private key - missing CRT in OpenSecureChannel #94

Closed thomas4232 closed 2 years ago

thomas4232 commented 2 years ago

Hi, I am trying to connect to KepServerEX6 with Basic256Sha256.

I generated certificates with OPENSSL like that:

openssl genrsa -out C:\Daten\Temp\OPCUA\key.pem 2048

openssl req -x509 -days 365 -new -out C:\Daten\Temp\OPCUA\certificate.pem -key C:\Daten\Temp\OPCUA\key.pem -config ssl.conf

openssl x509 -outform der -in C:\Daten\Temp\OPCUA\certificate.pem -out C:\Daten\Temp\OPCUA\certificate.crt

The certificate.crt is imported to the trusted clients in OPCUA Configuration Manager

But when I am trying to connect I am getting the Error Incomplete private key - missing CRT

It is thrown by the line 254 in Client.cs:

var msgSign = UASecurity.RsaPkcs15Sha_Sign(new ArraySegment<byte>(sendBuf.Buffer, 0, sendBuf.Position),
                        ApplicationPrivateKey, config.SecurityPolicy);

Is anybody knowing a solution. Is it a bug or are my keys invalid?

nauful commented 2 years ago

.crt files do not contain a private key: https://stackoverflow.com/questions/56339685/crt-file-does-not-contain-a-privatekey Therefore you cannot use this as a local certificate (cannot sign outgoing messages).

thomas4232 commented 2 years ago

I am getting unable to load certificates. What is the recommended way to create the private and public certificates which can be used for connecting to the server like this: openRes = client.OpenSecureChannel(MessageSecurityMode.SignAndEncrypt, SecurityPolicy.Basic256Sha256, serverCert);

thomas4232 commented 2 years ago

Just to add I am working on Unity (Mono) and the certificates can't be created in code. So how to create a working public and private certificate e.g. with OpenSSL or other tool which will work with LibUA and KepServer

nauful commented 2 years ago

See if this works: https://stackoverflow.com/a/56340368

As far as I understand it, you need a single file which contains your public certificate and private key, which is different from the distributable certificate (public certificate only).

thomas4232 commented 2 years ago

Thanks but https://stackoverflow.com/a/56340368 - did not worked. Still same message (missing CRT).

I also tried to use Opc.Ua.CertificateGenerator.exe to generate certificates. But with this certificates same problem. Still get the message in Line 254 of Client.cs Incomplete private key - missing CRT

so now I am totally at a loss how to get it running.

nauful commented 2 years ago

If you merge the .crt and private key into a .pfx file and load the .pfx file, does that work? It should contain a private key.

game4automation commented 2 years ago

This is exactly what I did but I still get the error missing CRT. Did you have been able to create working Certificates on your own?

nauful commented 2 years ago

Can I see your client code? If I generate separate .der and .pem files as in the sample client, that works for me:

class DemoClient : Client
{
    X509Certificate2 appCertificate = null;
    RSACryptoServiceProvider cryptPrivateKey = null;

    public override X509Certificate2 ApplicationCertificate
    {
        get { return appCertificate; }
    }

    public override RSACryptoServiceProvider ApplicationPrivateKey
    {
        get { return cryptPrivateKey; }
    }

    private void LoadCertificateAndPrivateKey()
    {
        try
        {
            // Try to load existing (public key) and associated private key
            appCertificate = new X509Certificate2("ClientCert.der");
            cryptPrivateKey = new RSACryptoServiceProvider();

            var rsaPrivParams = UASecurity.ImportRSAPrivateKey(File.ReadAllText("ClientKey.pem"));
            cryptPrivateKey.ImportParameters(rsaPrivParams);
        }

... rest isn't needed.

From the original example, this should replace ClientKey.pem: C:\Daten\Temp\OPCUA\key.pem This should replace ClientCertificate.der: C:\Daten\Temp\OPCUA\certificate.crt

thomas4232 commented 2 years ago

Thanks a lot.

With the certificates generated by the demo client the Incomplete private key - missing CRT error is not there any more.

My test ist with KepServerEx. But there OPCUAConfigurationManager when trying to import ClientCert.der (which was created by the demo client) - there is an error message that this certificate is not a valid certificate.

So my question is - what is the way for creating valid working certificates on a manual way via openssl or any other tool. I can't create them in my application and I just want to use existing certificates which are already generated. Is there any tool to do this?

nauful commented 2 years ago

I think the problem might be the way they are loaded. Can you show me how you load the .pem and .der files?

nauful commented 2 years ago

Or rather, in your case, the .pem and .crt files.

thomas4232 commented 2 years ago

This here how I load the certificates within the Unity script:

private void LoadCertificateAndPrivateKey() {

    if (Privatecertpath == "" || Publiccertpath == "")
        return;
    try
    {
        // Try to load existing (public key) and associated private key

        appCertificate = new X509Certificate2(Publiccertpath);
        cryptPrivateKey = new RSACryptoServiceProvider();

        var rsaPrivParams = UASecurity.ImportRSAPrivateKey(File.ReadAllText(Privatecertpath));
        cryptPrivateKey.ImportParameters(rsaPrivParams);
    }
    catch (Exception e)
    {
        Debug.LogError("Failure in certificates " + e.Message);

    }
}
thomas4232 commented 2 years ago

And how to generate valid .der and .pem file on a manual way?

nauful commented 2 years ago

Private would be a key, not a cert. This should work, let me know if it still fails: http://www.herongyang.com/Cryptography/Certificate-Format-OpenSSL-Generate-in-DER-and-PEM.html