12:53, EET
February 23, 2024
Hello.
I am working with an application based on the opc-ua-sdk. We are having issues with the client validating the certificate our server provides.
I have a server certificate that is signed by a CA certificate that in turn is signed by a root certificate.
I have a pfx-file containing the server key and can extract .der- and .pem-files containing the private and public portion of the certificate.
In addition I have two .der-file containing the CA and root certificates.
When configuring the server, I have been following the samples, and am using ApplicationIdentity.loadOrCreateCertificate(…) to load the server certificate.
The problem is that the clients report that “The Certificate is NOT SIGNED BY A TRUSTED SIGNER!” when they try to connect.
The root certificate has been added as a trusted certificate on the client, so I suspect the server responds with the server certificate,
but not the intermediate certificate that the client can verify that it is signed by the trusted root certificate.
How can I configure the server to respond with both the server certificate as well as the CA certificate so the client knows my server is trustworthy?
15:20, EET
April 3, 2012
Hi,
Unfortunately the SDK only supports sending the leaf certificate.
Basically you must also copy the intermediate certificate to the client side as a workaround.
Most applications still nowadays use a self-signed cert. In the rare occasion one might have a (self-signed) CA cert for a “factory floor”, but having a “full proper chain” is basically nonexistent (yes, this means you cannot revoke that factory floor self-signed CA cert, but revocation lists are also basically nonexistent as well).
This may improve once there is support for GDS (GlobalDiscoveryServer), but this will take time.
Also, since the certificate is made outside of the SDK, it is probably better to use constructor com.prosysopc.ua.ApplicationIdentity.ApplicationIdentity(Cert, PrivKey) instead of loadOrCreate (and com.prosysopc.ua.stack.transport.security.Cert.load + com.prosysopc.ua.stack.transport.security.PrivKey.load) and then setApplicationDescription(..)
If you do that, there could potentially be a … solution, though this is not tested, but depending how much you are willing to try:
You could subtype com.prosysopc.ua.stack.transport.security.Cert, override com.prosysopc.ua.stack.transport.security.Cert.getEncoded() and have it return the full encoded chain (IMPORTANT! the leaf-cert must be the first certificate, i.e. the direction is from leaf towars the root, as applications not supporting chains will only take the first cert). You can make the same byte[] go to the super-constructor com.prosysopc.ua.stack.transport.security.Cert.Cert(byte[]) (but it will only take the first cert from it, thus why you must override the getEncoded).
You can load each individual part with com.prosysopc.ua.stack.transport.security.Cert.load(File), then ‘getCertificate’ and for that (X509Certificate) call java.security.cert.Certificate.getEncoded() to get the encoded form and then concat those. IF you do this, and it works, please let us know
16:37, EET
February 23, 2024
Hello, and thank you for your quick response. It is unfortunate this is not supported by the sdk out of the box. We will have to discuss with our customer how important this is for them.
We used to use the constructor, but saw no way of adding an intermediate certificate, so we explored the loadOrCreate-methods.
My knowledge of certificates and standards leave a lot to be desired, so I’m not exactly sure how the different representations of certificates and chains fit together.
I will try to explain the possible solution the way I see it, and welcome any feedback on whether I understood your proposal.
Today the Cert-class can read a .der-file (using CertificateUtils) and create an internal representation for the first certificate in the file.
When clients connect to the server, the server calls the getEncoded()-method and sends the resulting byte-array to the client.
To make the server send a certificate chain, we would have to extend the Cert-class and override the getEncoded()-method to send a byte-array representing the entire certificate chain instead.
Our new CertificateChain-class would probably take in a number of File-objects that together represents the entire chain (or as much of it as we need).
Our override of getEncoded() would need to combine the byte-arrays of all certificates in the chain in some way.
We could potentially just let our class contain a list of Cert- or X509Certificate-objects and let our overridden methods use the existing methods on those in some way.
I think the theory sounds quite simple, but there are some things that are still unclear to me.
Would a combined byte-representation of a chain of certificates just be the byte-representation of each individual certificate concatenated?
Would we need to indicate that the byte array consists of multiple certificates instead of just one, or is that implicit?
The cert-class also contains a Thumbprint. Will this be affected by concatenated multiple certificates? Is this also something I would need to override?
14:37, EET
April 3, 2012
https://reference.opcfoundation.org/Core/Part6/v105/docs/6.2.6
“Chains are stored in a ByteString by simply appending the DER encoded form of the Certificates. The first Certificate shall be the end Certificate followed by its issuer. If the root CA is sent as part of the chain, it is last Certificate appended to the ByteString.”
The getEncoded is used to form the ByteString. Thus, as far as I’m aware, just concatenate them (I assume the .der form is self-describing so any decoder knows when the first cert ends etc.). Since the chain is only used for the signature (i.e. signed by the root CA) validation of the cert, only the getEncoded override should be relevant and the others need to be as-is as only the leaf cert (alone) is used for everything else.
11:02, EET
February 23, 2024
Concatenating all the certificates seems to work. The client now reports seeing the entire certificate chain. I am encountering another issue when trying to connect from the client, however. I get a ‘BadApplicationSignatureInvalid’. I’m not quite sure where the error occurs, It seems the client asks the server to end the session, so perhaps we need to do something more:
2024-02-28 09:54:31,008 [OPC-UA-Stack-Blocking-Work-Executor-23] DEBUG c.p.u.s.t.t.n.OpcTcpServerConnection – handleSecureMessage: secureChannelId=2msg=ActivateSessionRequest
2024-02-28 09:54:31,036 [OPC-UA-Stack-Blocking-Work-Executor-27] DEBUG c.p.u.s.t.t.n.OpcTcpServerConnection – handleSecureMessage: secureChannelId=2msg=CloseSessionRequest
I think I will have to try debugging the server-code to figure out exactly what happens. The client I’m using is UAExpert, which I understand is the reference client implementation.
11:36, EET
February 23, 2024
It seems the error occurs in the class SessionManager during the activateSession-method. Another method is called that verifies the certificates and their signatures. In that method, the getEncoded-method from my new CertificateChain-class is called to get the certificate, and I assume it is compared to the thumbprint to make sure the certificate is valid.
So I believe we might have encountered a limitation of the proposed solution. For the client, the getEncoded-method should return the concatenated byte-streams of all certificates int he chain, but when verifying the individual certificate, the getEncoded-method should only return the byte-array that corresponds to the thumbprint.
If I try to make my CertificateChain return the thumbprint of the entire chain, I will instead get an error earlier during connection when the server tries looking up the available certificates: “Requested Application Instance Certificate is not found in the server”.
13:11, EET
April 3, 2012
Ok.. hmm in practice then we would need to do some changes to the SDK. Making support for this isn’t exactly in our roadmap so I think best would be if you contact sales@prosysopc.com and link this forum post.
Most Users Ever Online: 1919
Currently Online:
36 Guest(s)
Currently Browsing this Page:
1 Guest(s)
Top Posters:
Heikki Tahvanainen: 402
hbrackel: 144
rocket science: 88
pramanj: 86
Francesco Zambon: 83
Ibrahim: 78
Sabari: 62
kapsl: 57
gjevremovic: 49
Xavier: 43
Member Stats:
Guest Posters: 0
Members: 726
Moderators: 7
Admins: 1
Forum Stats:
Groups: 3
Forums: 15
Topics: 1529
Posts: 6471
Newest Members:
gabriellabachus, Deakin, KTP25Zof, Wojciech Kubala, efrennowell431, wilfredostuart, caitlynfajardo, jeromechubb7, franciscagrimwad, adult_galleryModerators: Jouni Aro: 1026, Pyry: 1, Petri: 0, Bjarne Boström: 1032, Jimmy Ni: 26, Matti Siponen: 349, Lusetti: 0
Administrators: admin: 1