PHP Classes

File: tests/Unit/Protocol/SecureEncodingTest.php

Recommend this page to a friend!
  Packages of Gianfrancesco Aurecchia   OPC UA Client   tests/Unit/Protocol/SecureEncodingTest.php   Download  
File: tests/Unit/Protocol/SecureEncodingTest.php
Role: Example script
Content type: text/plain
Description: Example script
Class: OPC UA Client
Control devices that support the OPC UA protocol
Author: By
Last change:
Date: 4 days ago
Size: 10,275 bytes
 

Contents

Class file image Download
<?php declare(strict_types=1); use PhpOpcua\Client\Module\Browse\BrowseService; use PhpOpcua\Client\Module\Browse\GetEndpointsService; use PhpOpcua\Client\Module\History\HistoryReadService; use PhpOpcua\Client\Module\ReadWrite\CallService; use PhpOpcua\Client\Module\ReadWrite\ReadService; use PhpOpcua\Client\Module\ReadWrite\WriteService; use PhpOpcua\Client\Module\Subscription\MonitoredItemService; use PhpOpcua\Client\Module\Subscription\PublishService; use PhpOpcua\Client\Module\Subscription\SubscriptionService; use PhpOpcua\Client\Protocol\SessionService; use PhpOpcua\Client\Security\CertificateManager; use PhpOpcua\Client\Security\SecureChannel; use PhpOpcua\Client\Security\SecurityMode; use PhpOpcua\Client\Security\SecurityPolicy; use PhpOpcua\Client\Types\BuiltinType; use PhpOpcua\Client\Types\DataValue; use PhpOpcua\Client\Types\NodeId; use PhpOpcua\Client\Types\Variant; /** * Creates a SessionService with an active SecureChannel (Sign mode, no encryption needed). * The SecureChannel needs symmetric keys to build messages, so we set them up via OPN exchange. */ function createSecureSession(): SessionService { $privKey = openssl_pkey_new(['private_key_bits' => 2048, 'private_key_type' => OPENSSL_KEYTYPE_RSA]); $csr = openssl_csr_new(['CN' => 'test'], $privKey); $cert = openssl_csr_sign($csr, null, $privKey, 365); openssl_x509_export($cert, $certPem); $cm = new CertificateManager(); $tmpFile = tempnam(sys_get_temp_dir(), 'opcua_se_cert_'); file_put_contents($tmpFile, $certPem); $clientDer = $cm->loadCertificatePem($tmpFile); unlink($tmpFile); // Use same cert for both client and server (self-signed test) $sc = new SecureChannel( SecurityPolicy::Basic256Sha256, SecurityMode::Sign, $clientDer, $privKey, $clientDer, ); // Generate OPN to get clientNonce $sc->createOpenSecureChannelMessage(); // Build and process an OPN response to derive symmetric keys $serverNonce = random_bytes(32); $response = buildEncryptedOPNResponse( $clientDer, $privKey, // server cert/key (same as client for test) $clientDer, $privKey, // client cert/key $sc->getClientNonce(), $serverNonce, 500, 600, SecurityPolicy::Basic256Sha256, ); $sc->processOpenSecureChannelResponse($response); return new SessionService(0, 0, $sc); } describe('Secure encoding: SubscriptionService', function () { it('encodes CreateSubscription via secure channel', function () { $session = createSecureSession(); $service = new SubscriptionService($session); $bytes = $service->encodeCreateSubscriptionRequest(1, NodeId::numeric(0, 0)); // Sign mode: MSG header is present, body is plaintext + HMAC signature expect(substr($bytes, 0, 3))->toBe('MSG'); expect(strlen($bytes))->toBeGreaterThan(50); }); it('encodes ModifySubscription via secure channel', function () { $session = createSecureSession(); $service = new SubscriptionService($session); $bytes = $service->encodeModifySubscriptionRequest(1, NodeId::numeric(0, 0), 42); expect(substr($bytes, 0, 3))->toBe('MSG'); }); it('encodes DeleteSubscriptions via secure channel', function () { $session = createSecureSession(); $service = new SubscriptionService($session); $bytes = $service->encodeDeleteSubscriptionsRequest(1, NodeId::numeric(0, 0), [10, 20]); expect(substr($bytes, 0, 3))->toBe('MSG'); }); it('encodes SetPublishingMode via secure channel', function () { $session = createSecureSession(); $service = new SubscriptionService($session); $bytes = $service->encodeSetPublishingModeRequest(1, NodeId::numeric(0, 0), true, [42]); expect(substr($bytes, 0, 3))->toBe('MSG'); }); }); describe('Secure encoding: ReadService', function () { it('encodes ReadMulti via secure channel', function () { $session = createSecureSession(); $service = new ReadService($session); $bytes = $service->encodeReadMultiRequest(1, [ ['nodeId' => NodeId::numeric(1, 100)], ], NodeId::numeric(0, 0)); expect(substr($bytes, 0, 3))->toBe('MSG'); }); }); describe('Secure encoding: BrowseService', function () { it('encodes Browse via secure channel', function () { $session = createSecureSession(); $service = new BrowseService($session); $bytes = $service->encodeBrowseRequest(1, NodeId::numeric(0, 85), NodeId::numeric(0, 0)); expect(substr($bytes, 0, 3))->toBe('MSG'); }); it('encodes BrowseNext via secure channel', function () { $session = createSecureSession(); $service = new BrowseService($session); $bytes = $service->encodeBrowseNextRequest(1, 'cont-point', NodeId::numeric(0, 0)); expect(substr($bytes, 0, 3))->toBe('MSG'); }); }); describe('Secure encoding: CallService', function () { it('encodes Call via secure channel', function () { $session = createSecureSession(); $service = new CallService($session); $bytes = $service->encodeCallRequest( 1, NodeId::numeric(0, 2253), NodeId::numeric(0, 11492), [new Variant(BuiltinType::String, 'test')], NodeId::numeric(0, 0), ); expect(substr($bytes, 0, 3))->toBe('MSG'); }); }); describe('Secure encoding: MonitoredItemService', function () { it('encodes CreateMonitoredItems via secure channel', function () { $session = createSecureSession(); $service = new MonitoredItemService($session); $bytes = $service->encodeCreateMonitoredItemsRequest( 1, NodeId::numeric(0, 0), 42, [['nodeId' => NodeId::numeric(1, 100)]], ); expect(substr($bytes, 0, 3))->toBe('MSG'); }); it('encodes CreateEventMonitoredItem via secure channel', function () { $session = createSecureSession(); $service = new MonitoredItemService($session); $bytes = $service->encodeCreateEventMonitoredItemRequest( 1, NodeId::numeric(0, 0), 42, NodeId::numeric(0, 2253), ['EventId', 'EventType'], 5, ); expect(substr($bytes, 0, 3))->toBe('MSG'); }); it('encodes DeleteMonitoredItems via secure channel', function () { $session = createSecureSession(); $service = new MonitoredItemService($session); $bytes = $service->encodeDeleteMonitoredItemsRequest(1, NodeId::numeric(0, 0), 42, [1, 2]); expect(substr($bytes, 0, 3))->toBe('MSG'); }); }); describe('Secure encoding: HistoryReadService', function () { it('encodes HistoryReadRaw via secure channel', function () { $session = createSecureSession(); $service = new HistoryReadService($session); $bytes = $service->encodeHistoryReadRawRequest( 1, NodeId::numeric(0, 0), NodeId::numeric(1, 100), new DateTimeImmutable('2024-01-01'), new DateTimeImmutable('2024-01-02'), 100, true, ); expect(substr($bytes, 0, 3))->toBe('MSG'); }); it('encodes HistoryReadProcessed via secure channel', function () { $session = createSecureSession(); $service = new HistoryReadService($session); $bytes = $service->encodeHistoryReadProcessedRequest( 1, NodeId::numeric(0, 0), NodeId::numeric(1, 100), new DateTimeImmutable('2024-01-01'), new DateTimeImmutable('2024-01-02'), 500.0, NodeId::numeric(0, 2341), ); expect(substr($bytes, 0, 3))->toBe('MSG'); }); it('encodes HistoryReadAtTime via secure channel', function () { $session = createSecureSession(); $service = new HistoryReadService($session); $bytes = $service->encodeHistoryReadAtTimeRequest( 1, NodeId::numeric(0, 0), NodeId::numeric(1, 100), [new DateTimeImmutable('2024-01-01 12:00:00')], ); expect(substr($bytes, 0, 3))->toBe('MSG'); }); }); describe('Secure encoding: PublishService', function () { it('encodes Publish via secure channel', function () { $session = createSecureSession(); $service = new PublishService($session); $bytes = $service->encodePublishRequest(1, NodeId::numeric(0, 0)); expect(substr($bytes, 0, 3))->toBe('MSG'); }); it('encodes Publish with acks via secure channel', function () { $session = createSecureSession(); $service = new PublishService($session); $bytes = $service->encodePublishRequest(1, NodeId::numeric(0, 0), [ ['subscriptionId' => 42, 'sequenceNumber' => 1], ]); expect(substr($bytes, 0, 3))->toBe('MSG'); }); }); describe('Secure encoding: WriteService', function () { it('encodes Write via secure channel', function () { $session = createSecureSession(); $service = new WriteService($session); $bytes = $service->encodeWriteRequest( 1, NodeId::numeric(1, 100), new DataValue(new Variant(BuiltinType::Int32, 42)), NodeId::numeric(0, 0), ); expect(substr($bytes, 0, 3))->toBe('MSG'); }); }); describe('Secure encoding: GetEndpointsService', function () { it('encodes GetEndpoints via secure channel', function () { $session = createSecureSession(); $service = new GetEndpointsService($session); $bytes = $service->encodeGetEndpointsRequest(1, 'opc.tcp://localhost:4840', NodeId::numeric(0, 0)); expect(substr($bytes, 0, 3))->toBe('MSG'); }); }); describe('Secure encoding: SessionService', function () { it('encodes CreateSession via secure channel', function () { $session = createSecureSession(); $bytes = $session->encodeCreateSessionRequest(1, 'opc.tcp://localhost:4840'); expect(substr($bytes, 0, 3))->toBe('MSG'); }); });