v4.1.0
[v4.1.0] - 2026-04-13
Added
-
ECC security policies:
ECC_nistP256,ECC_nistP384,ECC_brainpoolP256r1, andECC_brainpoolP384r1. Full Elliptic Curve Cryptography support for OPC UA secure channels, including (see ECC disclaimer and 1.05.4 compliance roadmap):- ECDSA signatures (SHA-256 / SHA-384) for OpenSecureChannel (sign-only, no asymmetric encryption)
- ECDH ephemeral key agreement for symmetric key derivation
- HKDF-SHA256 / HKDF-SHA384 key derivation with mode-dependent salt (replaces P_SHA for ECC)
- HMAC-SHA256 / HMAC-SHA384 symmetric signing for MSG messages
- AES-128-CBC (P-256) / AES-256-CBC (P-384) symmetric encryption
- Auto-generated ECC certificates when no client certificate is provided (NIST P-256/P-384 or Brainpool P-256/P-384)
- Username/password authentication via
EccEncryptedSecretprotocol (ECDH + AES + ECDSA signature) ECDHPolicyUrirequest in CreateSessionAdditionalHeaderto obtain server ephemeral key- Parsing of
ECDHKey(EphemeralKeyType) from server'sAdditionalHeaderresponse - Raw R||S ECDSA signature format conversion (DER to/from raw) for OPN, ActivateSession, and EncryptedSecret
-
New
SecurityPolicyenum cases:EccNistP256,EccNistP384,EccBrainpoolP256r1,EccBrainpoolP384r1with methodsisEcc(),getEcdhCurveName(),getEphemeralKeyLength(). -
New
MessageSecuritymethods:computeEcdhSharedSecret(),deriveKeysHkdf(),generateEphemeralKeyPair(),loadEcPublicKeyFromBytes(),ecdsaDerToRaw(),ecdsaRawToDer(). -
New
CertificateManagermethods:getKeyType(), ECC certificate generation via optional$eccCurveNameparameter ongenerateSelfSignedCertificate(). -
7 new NIST ECC integration tests against the
uanetstandard-test-suiteECC server (port 4848): P-256 Sign, P-256 SignAndEncrypt (anonymous + admin + read), P-384 SignAndEncrypt (anonymous + admin), P-384 Sign. -
7 new Brainpool ECC integration tests against the
uanetstandard-test-suiteBrainpool server (port 4849): brainpoolP256r1 Sign, brainpoolP256r1 SignAndEncrypt (anonymous + admin + read), brainpoolP384r1 SignAndEncrypt (anonymous + admin), brainpoolP384r1 Sign. -
5 new granular exception classes for more precise error handling (all backward-compatible — extend existing exceptions):
OpenSslException(extendsSecurityException) — thrown when an OpenSSL function returns false.SignatureVerificationException(extendsSecurityException) — thrown when OPN or MSG signature verification fails.UnsupportedCurveException(extendsSecurityException) — thrown for unsupported ECC curves, with$curveNameproperty.MessageTypeException(extendsProtocolException) — thrown when the server responds with an unexpected message type, with$expectedand$actualproperties.HandshakeException(extendsProtocolException) — thrown when the HEL/ACK handshake fails with a server error, with$errorCodeproperty.
-
CertificateParseException(extendsSecurityException) — thrown for missing fields in parsed certificates. -
ECC disclaimer in README and Security documentation noting that no commercial OPC UA vendor supports ECC endpoints yet, and the implementation is tested exclusively against UA-.NETStandard.
-
ECC 1.05.4 compliance section in ROADMAP with detailed analysis of
LegacySequenceNumbersand per-message IV requirements.
Changed
- Unit test coverage raised to 99%+. Added 200+ unit tests across all source files. Every
src/class and trait now has dedicated coverage — Client traits, Security (SecureChannel, MessageSecurity, CertificateManager), Protocol (SessionService, MonitoredItemService), TrustStore (FileTrustStore), Cache (FileCache), and Types (DataValue). - Test infrastructure reorganized. Eliminated
*BoostTest.phpfiles. Extracted shared test helpers intotests/Unit/Helpers/ClientTestHelpers.php. Each source class now has its tests in the matching path (src/Foo/Bar.php→tests/Unit/Foo/BarTest.php). - Exception hierarchy granularized. Generic
SecurityExceptionandProtocolExceptionthrows replaced with specific subclasses (OpenSslException,SignatureVerificationException,UnsupportedCurveException,MessageTypeException,HandshakeException). All existingcatch (SecurityException)andcatch (ProtocolException)code continues to work unchanged. EnsuresOpenSslSuccesstrait. Extracted the duplicatedensureNotFalse()method fromCertificateManagerandMessageSecurityinto a shared trait insrc/Security/EnsuresOpenSslSuccess.php. Now throwsOpenSslExceptioninstead of genericSecurityException.MessageSecurity::getCoordinateSize(). Extracted duplicated EC coordinate size match expression into a reusable private method.- Diagnostic info parsing in
BrowseServiceandWriteService. Replaced manual byte-reading loops with$decoder->skipDiagnosticInfoArray()for correct OPC UA DiagnosticInfo format parsing. - Removed all inline comments from function bodies per CONTRIBUTING.md guidelines. Extracted
SessionService::readEccServerEphemeralKey()to replace commented ECC key parsing logic. - Removed
glob() === falsedead branches inFileTrustStoreandFileCache—glob()never returnsfalseon Linux with a valid pattern. FileTrustStore::parseCertificateInfochanged fromprivatetoprotectedto enable proper subclass-based testing.FileTrustStore::throwCertificateParseExceptionIfNull— new protected method replacing nullable ternary operators for certificate date fields, with dedicatedCertificateParseException.