You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by ld...@apache.org on 2024/02/12 09:25:49 UTC

(plc4x) branch pg/security-policy created (now 2f89cb423f)

This is an automated email from the ASF dual-hosted git repository.

ldywicki pushed a change to branch pg/security-policy
in repository https://gitbox.apache.org/repos/asf/plc4x.git


      at 2f89cb423f Calculate padding overhead

This branch includes the following new commits:

     new 9bd9a9437e Draft
     new cc1046bdfe Draft v2
     new 8a9c112aac Fix signature
     new e1cb6b40c7 Draft - read variable from milo
     new a1a028028e Draft - read variable from milo - more tests
     new 3783526397 Draft - read application uri from cert
     new f312f3ad60 Draft - remove todo
     new 2472008d2a Create client signature in ActivateSessionRequest
     new 0aea62481c Write variables test - add connection conf
     new f26072de0d - Add SecurityPolicy - remove milo deps - add parametrized tests for security policies
     new e677593797 Add Basic256Sha256 support
     new 2f89cb423f Calculate padding overhead

The 12 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



(plc4x) 06/12: Draft - read application uri from cert

Posted by ld...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ldywicki pushed a commit to branch pg/security-policy
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit 37835263972567e122835dcbe08b9cbb41d0bd9e
Author: PatrykGala <pa...@gmail.com>
AuthorDate: Wed Jul 19 23:28:20 2023 +0200

    Draft - read application uri from cert
---
 .../java/opcua/config/OpcuaConfiguration.java      | 17 +++++++-----
 .../java/opcua/context/CertificateKeyPair.java     | 30 +++++++++++++++++++---
 .../plc4x/java/opcua/context/SecureChannel.java    |  2 +-
 3 files changed, 38 insertions(+), 11 deletions(-)

diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/config/OpcuaConfiguration.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/config/OpcuaConfiguration.java
index 45c2161ac8..fb23044f2a 100644
--- a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/config/OpcuaConfiguration.java
+++ b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/config/OpcuaConfiguration.java
@@ -21,12 +21,10 @@ package org.apache.plc4x.java.opcua.config;
 import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
 import org.apache.plc4x.java.opcua.context.CertificateGenerator;
 import org.apache.plc4x.java.opcua.context.CertificateKeyPair;
-import org.apache.plc4x.java.opcua.protocol.OpcuaProtocolLogic;
 import org.apache.plc4x.java.opcua.readwrite.PascalByteString;
 import org.apache.plc4x.java.spi.configuration.Configuration;
 import org.apache.plc4x.java.spi.configuration.annotations.ConfigurationParameter;
 import org.apache.plc4x.java.spi.configuration.annotations.defaults.BooleanDefaultValue;
-import org.apache.plc4x.java.spi.configuration.annotations.defaults.IntDefaultValue;
 import org.apache.plc4x.java.spi.configuration.annotations.defaults.StringDefaultValue;
 import org.apache.plc4x.java.transport.tcp.TcpTransportConfiguration;
 import org.bouncycastle.jce.provider.BouncyCastleProvider;
@@ -36,12 +34,13 @@ import org.slf4j.LoggerFactory;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
-import java.io.IOException;
 import java.nio.file.FileSystems;
-import java.nio.file.Path;
-import java.security.*;
-import java.security.cert.CertificateException;
+import java.security.KeyPair;
+import java.security.KeyStore;
+import java.security.PrivateKey;
+import java.security.Security;
 import java.security.cert.X509Certificate;
+import java.util.Optional;
 
 public class OpcuaConfiguration implements Configuration, TcpTransportConfiguration {
 
@@ -85,6 +84,9 @@ public class OpcuaConfiguration implements Configuration, TcpTransportConfigurat
     @ConfigurationParameter("keyStorePassword")
     private String keyStorePassword;
 
+    @ConfigurationParameter("applicationUri")
+    private String applicationUri;
+
     private CertificateKeyPair ckp;
 
     public boolean isDiscovery() {
@@ -231,5 +233,8 @@ public class OpcuaConfiguration implements Configuration, TcpTransportConfigurat
 
     public void setSenderCertificate(byte[] certificate) { this.senderCertificate = certificate; }
 
+    public Optional<String> getApplicationUri() {
+        return Optional.ofNullable(applicationUri).or(() -> ckp.getApplicationUri());
+    }
 }
 
diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/CertificateKeyPair.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/CertificateKeyPair.java
index ae65d8368b..9133a68bf4 100644
--- a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/CertificateKeyPair.java
+++ b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/CertificateKeyPair.java
@@ -18,9 +18,15 @@
  */
 package org.apache.plc4x.java.opcua.context;
 
+import io.vavr.control.Try;
+import org.bouncycastle.asn1.x509.GeneralName;
+
 import java.security.KeyPair;
 import java.security.MessageDigest;
 import java.security.cert.X509Certificate;
+import java.util.Collection;
+import java.util.List;
+import java.util.Optional;
 
 public class CertificateKeyPair {
 
@@ -28,16 +34,32 @@ public class CertificateKeyPair {
     private final X509Certificate certificate;
     private final byte[] thumbprint;
 
-    public CertificateKeyPair(KeyPair keyPair, X509Certificate certificate) throws Exception{
+    public CertificateKeyPair(KeyPair keyPair, X509Certificate certificate) throws Exception {
         this.keyPair = keyPair;
         this.certificate = certificate;
         MessageDigest messageDigest = MessageDigest.getInstance("SHA-1");
         this.thumbprint = messageDigest.digest(this.certificate.getEncoded());
     }
 
-    public KeyPair getKeyPair() { return keyPair; }
+    public KeyPair getKeyPair() {
+        return keyPair;
+    }
+
+    public X509Certificate getCertificate() {
+        return certificate;
+    }
 
-    public X509Certificate getCertificate() { return certificate; }
+    public byte[] getThumbPrint() {
+        return thumbprint;
+    }
 
-    public byte[] getThumbPrint() { return thumbprint; }
+    public Optional<String> getApplicationUri() {
+        Try<Collection<List<?>>> lists = Try.of(certificate::getSubjectAlternativeNames);
+        return lists.toJavaStream()
+            .flatMap(Collection::stream)
+            .filter(l -> l.size() == 2)
+            .filter(name -> name.get(0).equals(GeneralName.uniformResourceIdentifier))
+            .map(t -> (String) t.get(1))
+            .findAny();
+    }
 }
diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/SecureChannel.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/SecureChannel.java
index 798089ea25..e40f48befb 100644
--- a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/SecureChannel.java
+++ b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/SecureChannel.java
@@ -385,7 +385,7 @@ public class SecureChannel {
         int noOfDiscoveryUrls = -1;
         List<PascalString> discoveryUrls = new ArrayList<>(0);
 
-        ApplicationDescription clientDescription = new ApplicationDescription(APPLICATION_URI,
+        ApplicationDescription clientDescription = new ApplicationDescription(configuration.getApplicationUri().map(PascalString::new).orElse(APPLICATION_URI),
             PRODUCT_URI,
             applicationName,
             ApplicationType.applicationTypeClient,


(plc4x) 10/12: - Add SecurityPolicy - remove milo deps - add parametrized tests for security policies

Posted by ld...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ldywicki pushed a commit to branch pg/security-policy
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit f26072de0d990775a235953cb45c8cda5a986023
Author: PatrykGala <pa...@gmail.com>
AuthorDate: Sat Sep 16 11:57:21 2023 +0200

    - Add SecurityPolicy
    - remove milo deps
    - add parametrized tests for security policies
---
 plc4j/drivers/opcua/pom.xml                        |  10 +-
 .../opcua/readwrite/OpenSecureChannelRequest.java  |   2 +-
 .../apache/plc4x/java/opcua/OpcuaPlcDriver.java    |   3 +-
 .../java/opcua/config/OpcuaConfiguration.java      |  33 +++--
 .../opcua/context/AsymmetricEncryptionHandler.java |  26 ++--
 .../java/opcua/context/EncryptionHandler.java      | 137 +++++----------------
 .../plc4x/java/opcua/context/SecureChannel.java    |  39 +++---
 .../plc4x/java/opcua/context/SecurityPolicy.java   |  16 ---
 .../opcua/context/SymmetricEncryptionHandler.java  |  37 +++---
 .../plc4x/java/opcua/security/SecurityPolicy.java  | 117 ++++++++++++++++++
 .../opcua/{context => security}/SymmetricKeys.java |  27 ++--
 .../plc4x/java/opcua/OpcuaPlcDriverTest.java       |  97 ++++++++-------
 12 files changed, 286 insertions(+), 258 deletions(-)

diff --git a/plc4j/drivers/opcua/pom.xml b/plc4j/drivers/opcua/pom.xml
index fbc861ac64..333745bd2e 100644
--- a/plc4j/drivers/opcua/pom.xml
+++ b/plc4j/drivers/opcua/pom.xml
@@ -171,28 +171,28 @@
       <groupId>org.apache.plc4x</groupId>
       <artifactId>plc4j-utils-test-utils</artifactId>
       <version>0.11.0-SNAPSHOT</version>
-
+      <scope>test</scope>
     </dependency>
 
     <dependency>
       <groupId>org.eclipse.milo</groupId>
       <artifactId>sdk-client</artifactId>
-
+      <scope>test</scope>
     </dependency>
     <dependency>
       <groupId>org.eclipse.milo</groupId>
       <artifactId>stack-core</artifactId>
-
+      <scope>test</scope>
     </dependency>
     <dependency>
       <groupId>org.eclipse.milo</groupId>
       <artifactId>stack-client</artifactId>
-
+      <scope>test</scope>
     </dependency>
     <dependency>
       <groupId>org.eclipse.milo</groupId>
       <artifactId>server-examples</artifactId>
-
+      <scope>test</scope>
     </dependency>
 
     <dependency>
diff --git a/plc4j/drivers/opcua/src/main/generated/org/apache/plc4x/java/opcua/readwrite/OpenSecureChannelRequest.java b/plc4j/drivers/opcua/src/main/generated/org/apache/plc4x/java/opcua/readwrite/OpenSecureChannelRequest.java
index 0f3f536935..8c5091f53c 100644
--- a/plc4j/drivers/opcua/src/main/generated/org/apache/plc4x/java/opcua/readwrite/OpenSecureChannelRequest.java
+++ b/plc4j/drivers/opcua/src/main/generated/org/apache/plc4x/java/opcua/readwrite/OpenSecureChannelRequest.java
@@ -118,7 +118,7 @@ public class OpenSecureChannelRequest extends ExtensionObjectDefinition implemen
     writeSimpleEnumField(
         "securityMode",
         "MessageSecurityMode",
-        securityMode,//TODO patrykg
+        securityMode,
         new DataWriterEnumDefault<>(
             MessageSecurityMode::getValue,
             MessageSecurityMode::name,
diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/OpcuaPlcDriver.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/OpcuaPlcDriver.java
index 8df80ecd3b..bdb1881ff8 100644
--- a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/OpcuaPlcDriver.java
+++ b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/OpcuaPlcDriver.java
@@ -20,6 +20,7 @@ package org.apache.plc4x.java.opcua;
 
 import org.apache.plc4x.java.api.PlcConnection;
 import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
+import org.apache.plc4x.java.opcua.security.SecurityPolicy;
 import org.apache.plc4x.java.opcua.tag.OpcuaTag;
 import org.apache.plc4x.java.opcua.tag.OpcuaPlcTagHandler;
 import org.apache.plc4x.java.opcua.optimizer.OpcuaOptimizer;
@@ -209,7 +210,7 @@ public class OpcuaPlcDriver extends GeneratedDriverBase<OpcuaAPU> {
             awaitDisconnectComplete = Boolean.parseBoolean(System.getProperty(PROPERTY_PLC4X_FORCE_AWAIT_DISCONNECT_COMPLETE));
         }
 
-        if (configuration.getSecurityPolicy() != null && !(configuration.getSecurityPolicy().equals("None"))) {
+        if (configuration.getSecurityPolicy() != null && (configuration.getSecurityPolicy() != SecurityPolicy.NONE)) {
             try {
                 configuration.openKeyStore();
             } catch (Exception e) {
diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/config/OpcuaConfiguration.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/config/OpcuaConfiguration.java
index fb23044f2a..9132643b29 100644
--- a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/config/OpcuaConfiguration.java
+++ b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/config/OpcuaConfiguration.java
@@ -22,6 +22,7 @@ import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
 import org.apache.plc4x.java.opcua.context.CertificateGenerator;
 import org.apache.plc4x.java.opcua.context.CertificateKeyPair;
 import org.apache.plc4x.java.opcua.readwrite.PascalByteString;
+import org.apache.plc4x.java.opcua.security.SecurityPolicy;
 import org.apache.plc4x.java.spi.configuration.Configuration;
 import org.apache.plc4x.java.spi.configuration.annotations.ConfigurationParameter;
 import org.apache.plc4x.java.spi.configuration.annotations.defaults.BooleanDefaultValue;
@@ -84,9 +85,6 @@ public class OpcuaConfiguration implements Configuration, TcpTransportConfigurat
     @ConfigurationParameter("keyStorePassword")
     private String keyStorePassword;
 
-    @ConfigurationParameter("applicationUri")
-    private String applicationUri;
-
     private CertificateKeyPair ckp;
 
     public boolean isDiscovery() {
@@ -105,8 +103,8 @@ public class OpcuaConfiguration implements Configuration, TcpTransportConfigurat
         return certDirectory;
     }
 
-    public String getSecurityPolicy() {
-        return securityPolicy;
+    public SecurityPolicy getSecurityPolicy() {
+        return SecurityPolicy.findByName(securityPolicy);
     }
 
     public String getKeyStoreFile() {
@@ -125,7 +123,9 @@ public class OpcuaConfiguration implements Configuration, TcpTransportConfigurat
         return ckp;
     }
 
-    public boolean isEncrypted() { return isEncrypted; }
+    public boolean isEncrypted() {
+        return isEncrypted;
+    }
 
     public void setDiscovery(boolean discovery) {
         this.discovery = discovery;
@@ -155,7 +155,9 @@ public class OpcuaConfiguration implements Configuration, TcpTransportConfigurat
         this.keyStorePassword = keyStorePassword;
     }
 
-    public void setThumbprint(PascalByteString thumbprint) { this.thumbprint = thumbprint; }
+    public void setThumbprint(PascalByteString thumbprint) {
+        this.thumbprint = thumbprint;
+    }
 
     public String getTransportCode() {
         return code;
@@ -197,13 +199,15 @@ public class OpcuaConfiguration implements Configuration, TcpTransportConfigurat
         this.endpoint = endpoint;
     }
 
-    public void setTransportEndpoint(String transportEndpoint) { this.transportEndpoint = transportEndpoint; }
+    public void setTransportEndpoint(String transportEndpoint) {
+        this.transportEndpoint = transportEndpoint;
+    }
 
     public void openKeyStore() throws Exception {
         this.isEncrypted = true;
         File securityTempDir = new File(certDirectory, "security");
         if (!securityTempDir.exists() && !securityTempDir.mkdirs()) {
-            throw new PlcConnectionException("Unable to create directory please confirm folder permissions on "  + certDirectory);
+            throw new PlcConnectionException("Unable to create directory please confirm folder permissions on " + certDirectory);
         }
         KeyStore keyStore = KeyStore.getInstance("PKCS12");
         File serverKeyStore = securityTempDir.toPath().resolve(keyStoreFile).toFile();
@@ -213,7 +217,7 @@ public class OpcuaConfiguration implements Configuration, TcpTransportConfigurat
             ckp = CertificateGenerator.generateCertificate();
             LOGGER.info("Creating new KeyStore at {}", serverKeyStore);
             keyStore.load(null, keyStorePassword.toCharArray());
-            keyStore.setKeyEntry("plc4x-certificate-alias", ckp.getKeyPair().getPrivate(), keyStorePassword.toCharArray(), new X509Certificate[] { ckp.getCertificate() });
+            keyStore.setKeyEntry("plc4x-certificate-alias", ckp.getKeyPair().getPrivate(), keyStorePassword.toCharArray(), new X509Certificate[]{ckp.getCertificate()});
             keyStore.store(new FileOutputStream(serverKeyStore), keyStorePassword.toCharArray());
         } else {
             LOGGER.info("Loading KeyStore at {}", serverKeyStore);
@@ -221,7 +225,7 @@ public class OpcuaConfiguration implements Configuration, TcpTransportConfigurat
             String alias = keyStore.aliases().nextElement();
             KeyPair kp = new KeyPair(keyStore.getCertificate(alias).getPublicKey(),
                 (PrivateKey) keyStore.getKey(alias, keyStorePassword.toCharArray()));
-            ckp = new CertificateKeyPair(kp,(X509Certificate) keyStore.getCertificate(alias));
+            ckp = new CertificateKeyPair(kp, (X509Certificate) keyStore.getCertificate(alias));
         }
     }
 
@@ -231,10 +235,13 @@ public class OpcuaConfiguration implements Configuration, TcpTransportConfigurat
             '}';
     }
 
-    public void setSenderCertificate(byte[] certificate) { this.senderCertificate = certificate; }
+    public void setSenderCertificate(byte[] certificate) {
+        this.senderCertificate = certificate;
+    }
 
     public Optional<String> getApplicationUri() {
-        return Optional.ofNullable(applicationUri).or(() -> ckp.getApplicationUri());
+        return Optional.ofNullable(ckp)
+            .flatMap(CertificateKeyPair::getApplicationUri);
     }
 }
 
diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/AsymmetricEncryptionHandler.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/AsymmetricEncryptionHandler.java
index e49802e28b..1dc72f631f 100644
--- a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/AsymmetricEncryptionHandler.java
+++ b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/AsymmetricEncryptionHandler.java
@@ -3,32 +3,34 @@ package org.apache.plc4x.java.opcua.context;
 import org.apache.plc4x.java.opcua.readwrite.MessagePDU;
 import org.apache.plc4x.java.opcua.readwrite.OpcuaAPU;
 import org.apache.plc4x.java.opcua.readwrite.OpcuaOpenResponse;
+import org.apache.plc4x.java.opcua.security.SecurityPolicy;
 import org.apache.plc4x.java.spi.generation.*;
-import org.eclipse.milo.opcua.stack.core.security.SecurityPolicy;
 
-import javax.crypto.*;
+import javax.crypto.Cipher;
 import java.nio.ByteBuffer;
-import java.security.*;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.Signature;
 import java.security.cert.Certificate;
 import java.security.cert.X509Certificate;
 import java.security.interfaces.RSAPublicKey;
 
-
 public class AsymmetricEncryptionHandler {
     private static final int SECURE_MESSAGE_HEADER_SIZE = 12;
     private static final int SEQUENCE_HEADER_SIZE = 8;
 
-    private final SecurityPolicy policy = SecurityPolicy.Basic128Rsa15;
+    private final SecurityPolicy policy;
 
-    private X509Certificate serverCertificate;
-    private X509Certificate clientCertificate;
+    private final X509Certificate serverCertificate;
+    private final X509Certificate clientCertificate;
 
     private final PrivateKey clientPrivateKey;
 
-    public AsymmetricEncryptionHandler(X509Certificate serverCertificate, X509Certificate clientCertificate, PrivateKey clientPrivateKey, PublicKey clientPublicKey) {
+    public AsymmetricEncryptionHandler(X509Certificate serverCertificate, X509Certificate clientCertificate, PrivateKey clientPrivateKey, PublicKey clientPublicKey, SecurityPolicy policy) {
         this.serverCertificate = serverCertificate;
         this.clientCertificate = clientCertificate;
         this.clientPrivateKey = clientPrivateKey;
+        this.policy = policy;
     }
 
     /**
@@ -115,8 +117,7 @@ public class AsymmetricEncryptionHandler {
             WriteBufferByteBased buf = new WriteBufferByteBased(pdu.getLengthInBytes(), ByteOrder.LITTLE_ENDIAN);
             pdu.serialize(buf);
 
-            String transformation = policy.getAsymmetricEncryptionAlgorithm().getTransformation();
-            Cipher cipher = Cipher.getInstance(transformation);
+            Cipher cipher = policy.getAsymmetricEncryptionAlgorithm().getCipher();
             cipher.init(Cipher.DECRYPT_MODE, clientPrivateKey);
 
             ByteBuffer buffer = ByteBuffer.allocate(plainTextBufferSize);
@@ -153,8 +154,7 @@ public class AsymmetricEncryptionHandler {
         ByteBuffer originalMessage = ByteBuffer.wrap(buf.getBytes(SECURE_MESSAGE_HEADER_SIZE + securityHeaderSize, frameSize));
 
 
-        String transformation = policy.getAsymmetricEncryptionAlgorithm().getTransformation();
-        Cipher cipher = Cipher.getInstance(transformation);
+        Cipher cipher = policy.getAsymmetricEncryptionAlgorithm().getCipher();
         cipher.init(Cipher.ENCRYPT_MODE, serverCertificate.getPublicKey());
 
         for (int block = 0; block < blockCount; block++) {
@@ -179,7 +179,7 @@ public class AsymmetricEncryptionHandler {
 
     public byte[] sign(byte[] data) {
         try {
-            Signature signature = Signature.getInstance("SHA1withRSA");
+            Signature signature = policy.getAsymmetricSignatureAlgorithm().getSignature();
             signature.initSign(clientPrivateKey);
             signature.update(data);
             return signature.sign();
diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/EncryptionHandler.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/EncryptionHandler.java
index ad3b7b64a2..394abdb864 100644
--- a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/EncryptionHandler.java
+++ b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/EncryptionHandler.java
@@ -22,6 +22,7 @@ import com.google.common.primitives.Bytes;
 import io.vavr.control.Try;
 import org.apache.plc4x.java.opcua.protocol.OpcuaProtocolLogic;
 import org.apache.plc4x.java.opcua.readwrite.*;
+import org.apache.plc4x.java.opcua.security.SecurityPolicy;
 import org.apache.plc4x.java.spi.generation.*;
 import org.bouncycastle.jce.provider.BouncyCastleProvider;
 import org.slf4j.Logger;
@@ -32,10 +33,11 @@ import java.io.ByteArrayInputStream;
 import java.security.PrivateKey;
 import java.security.PublicKey;
 import java.security.Security;
-import java.security.Signature;
 import java.security.cert.CertificateFactory;
 import java.security.cert.X509Certificate;
 
+import static org.apache.plc4x.java.spi.generation.ByteOrder.LITTLE_ENDIAN;
+
 
 public class EncryptionHandler {
 
@@ -46,18 +48,19 @@ public class EncryptionHandler {
         Security.addProvider(new BouncyCastleProvider());
     }
 
+
     private X509Certificate serverCertificate;
     private X509Certificate clientCertificate;
     private PrivateKey clientPrivateKey;
     private PublicKey clientPublicKey;
-    private final String securitypolicy;
+    private final SecurityPolicy securitypolicy;
 
     private byte[] clientNonce = null;
     private byte[] serverNonce = null;
-    private SymmetricEncryptionHandler symmetricEncryptionHandler = new SymmetricEncryptionHandler();
-
+    private final SymmetricEncryptionHandler symmetricEncryptionHandler;
+    private final AsymmetricEncryptionHandler asymmetricEncryptionHandler;
 
-    public EncryptionHandler(CertificateKeyPair ckp, byte[] senderCertificate, String securityPolicy) {
+    public EncryptionHandler(CertificateKeyPair ckp, byte[] senderCertificate, SecurityPolicy securityPolicy) {
         if (ckp != null) {
             this.clientPrivateKey = ckp.getKeyPair().getPrivate();
             this.clientPublicKey = ckp.getKeyPair().getPublic();
@@ -67,114 +70,55 @@ public class EncryptionHandler {
             this.serverCertificate = getCertificateX509(senderCertificate);
         }
         this.securitypolicy = securityPolicy;
+        this.symmetricEncryptionHandler = new SymmetricEncryptionHandler(securityPolicy);
+        this.asymmetricEncryptionHandler = new AsymmetricEncryptionHandler(serverCertificate, clientCertificate, clientPrivateKey, clientPublicKey, securitypolicy);
     }
 
     public void setServerCertificate(X509Certificate serverCertificate) {
         this.serverCertificate = serverCertificate;
     }
 
-    //https://reference.opcfoundation.org/Core/Part6/v104/docs/6.7
     public ReadBuffer encodeMessage(MessagePDU pdu, byte[] message) {
-        String messageType = pdu.getMessageType();
-        if ("OPN".equals(messageType)) {
-
-            return new AsymmetricEncryptionHandler(serverCertificate, clientCertificate, clientPrivateKey, clientPublicKey)
-                .encodeMessage(pdu, message);
-        } else {
-
-            return symmetricEncryptionHandler
-                .encodeMessage(pdu, message, clientNonce, serverNonce);
+        switch (securitypolicy) {
+            case NONE:
+                return new ReadBufferByteBased(message, LITTLE_ENDIAN);
+            case Basic128Rsa15:
+                if (pdu instanceof OpcuaOpenRequest) {
+                    return asymmetricEncryptionHandler.encodeMessage(pdu, message);
+                } else {
+                    return symmetricEncryptionHandler.encodeMessage(pdu, message, clientNonce, serverNonce);
+                }
+            default:
+                throw new IllegalStateException("Driver doesn't support security policy: " + securitypolicy);
         }
-
     }
 
 
     public SignatureData createClientSignature(byte[] lastServerNonce) {
-        AsymmetricEncryptionHandler handler = new AsymmetricEncryptionHandler(serverCertificate, clientCertificate, clientPrivateKey, clientPublicKey);
-
         byte[] cert = Try.of(() -> serverCertificate.getEncoded()).getOrElse(new byte[0]);
         byte[] bytes = Bytes.concat(cert, lastServerNonce);
-        byte[] signed = handler.sign(bytes);
+        byte[] signed = asymmetricEncryptionHandler.sign(bytes);
         return new SignatureData(new PascalString("http://www.w3.org/2000/09/xmldsig#rsa-sha1"), new PascalByteString(signed.length, signed));
     }
 
-    public OpcuaAPU decodeMessage(OpcuaAPU pdu) {//TODo patrykg
+    public OpcuaAPU decodeMessage(OpcuaAPU pdu) {
         LOGGER.info("Decoding Message with Security policy {}", securitypolicy);
 
         switch (securitypolicy) {
-            case "None":
+            case NONE:
                 return pdu;
-            case "Basic128Rsa15":
-                if (pdu.getMessage().getMessageType().equals("OPN")) {
-                    return new AsymmetricEncryptionHandler(serverCertificate, clientCertificate, clientPrivateKey, clientPublicKey)
-                        .decodeMessage(pdu);
+            case Basic128Rsa15:
+                if (pdu.getMessage() instanceof OpcuaOpenResponse) {
+                    return asymmetricEncryptionHandler.decodeMessage(pdu);
                 } else {
                     return symmetricEncryptionHandler
                         .decodeMessage(pdu, clientNonce, serverNonce);
                 }
-            case "Basic128Sha128":
-                byte[] message;
-                if (pdu.getMessage() instanceof OpcuaOpenResponse) {
-                    message = ((OpcuaOpenResponse) pdu.getMessage()).getMessage();
-                } else if (pdu.getMessage() instanceof OpcuaMessageResponse) {
-                    message = ((OpcuaMessageResponse) pdu.getMessage()).getMessage();
-                } else {
-                    return pdu;
-                }
-                try {
-                    int encryptedLength = pdu.getLengthInBytes();
-                    int encryptedMessageLength = message.length + 8;
-                    int headerLength = encryptedLength - encryptedMessageLength;
-                    int numberOfBlocks = encryptedMessageLength / 256;
-                    WriteBufferByteBased buf = new WriteBufferByteBased(headerLength + numberOfBlocks * 256, ByteOrder.LITTLE_ENDIAN);
-                    pdu.serialize(buf);
-                    byte[] data = getBytes(buf.getBytes(), headerLength, encryptedLength);
-                    buf.setPos(headerLength);
-                    decryptBlock(buf, data);
-                    int tempPos = buf.getPos();
-                    buf.setPos(0);
-                    if (!checkSignature(getBytes(buf.getBytes(), 0, tempPos))) {
-                        LOGGER.info("Signature verification failed: - {}", getBytes(buf.getBytes(), 0, tempPos - 256));
-                    }
-                    buf.setPos(4);
-                    buf.writeInt(32, tempPos - 256);
-                    ReadBuffer readBuffer = new ReadBufferByteBased(getBytes(buf.getBytes(), 0, tempPos - 256), ByteOrder.LITTLE_ENDIAN);
-                    return OpcuaAPU.staticParse(readBuffer, true);
-                } catch (SerializationException | ParseException e) {
-                    LOGGER.error("Unable to Parse encrypted message");
-                }
-        }
-        return pdu;
-    }
-
-    public void decryptBlock(WriteBuffer buf, byte[] data) {
-        try {
-            Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding");
-            cipher.init(Cipher.DECRYPT_MODE, this.clientPrivateKey);
-
-            for (int i = 0; i < data.length; i += 256) {
-                byte[] decrypted = cipher.doFinal(data, i, 256);
-                for (int j = 0; j < 214; j++) {
-                    buf.writeByte(decrypted[j]);
-                }
-            }
-        } catch (Exception e) {
-            LOGGER.error("Unable to decrypt Data", e);
+            default:
+                throw new IllegalStateException("Driver doesn't support security policy: " + securitypolicy);
         }
     }
 
-    public boolean checkSignature(byte[] data) {
-        try {
-            Signature signature = Signature.getInstance("SHA1withRSA", "BC");
-            signature.initVerify(serverCertificate.getPublicKey());
-            signature.update(data);
-            return signature.verify(data, 0, data.length - 256);
-        } catch (Exception e) {
-            e.printStackTrace();
-            LOGGER.error("Unable to sign Data");
-            return false;
-        }
-    }
 
     public byte[] encryptPassword(byte[] data) {
         try {
@@ -187,7 +131,6 @@ public class EncryptionHandler {
         }
     }
 
-
     public static X509Certificate getCertificateX509(byte[] senderCertificate) {
         try {
             CertificateFactory factory = CertificateFactory.getInstance("X.509");
@@ -199,28 +142,6 @@ public class EncryptionHandler {
         }
     }
 
-    public byte[] sign(byte[] data) {
-        try {
-            Signature signature = Signature.getInstance("SHA1withRSA", "BC");
-            signature.initSign(this.clientPrivateKey);
-            signature.update(data);
-            byte[] ss = signature.sign();
-            LOGGER.info("----------------Signature Length{}", ss.length);
-            return ss;
-        } catch (Exception e) {
-            e.printStackTrace();
-            LOGGER.error("Unable to sign Data");
-            return null;
-        }
-    }
-
-    private byte[] getBytes(byte[] bytes, int startPos, int endPos) {
-        int numBytes = endPos - startPos;
-        byte[] data = new byte[numBytes];
-        System.arraycopy(bytes, startPos, data, 0, numBytes);
-        return data;
-    }
-
     public void setClientNonce(byte[] clientNonce) {
         this.clientNonce = clientNonce;
     }
diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/SecureChannel.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/SecureChannel.java
index 0ca1e21e30..87e61032de 100644
--- a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/SecureChannel.java
+++ b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/SecureChannel.java
@@ -25,6 +25,7 @@ import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
 import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
 import org.apache.plc4x.java.opcua.config.OpcuaConfiguration;
 import org.apache.plc4x.java.opcua.readwrite.*;
+import org.apache.plc4x.java.opcua.security.SecurityPolicy;
 import org.apache.plc4x.java.spi.ConversationContext;
 import org.apache.plc4x.java.spi.context.DriverContext;
 import org.apache.plc4x.java.spi.generation.*;
@@ -52,6 +53,8 @@ import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.stream.Stream;
 
+import static org.apache.plc4x.java.opcua.security.SecurityPolicy.NONE;
+
 public class SecureChannel {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(SecureChannel.class);
@@ -100,14 +103,10 @@ public class SecureChannel {
     private final AtomicInteger requestHandleGenerator = new AtomicInteger(1);
     private PascalString policyId;
     private UserTokenType tokenType;
-    private boolean discovery;
-    private String certFile;
-    private final String keyStoreFile;
-    private CertificateKeyPair ckp;
     private final PascalString endpoint;
     private final String username;
     private final String password;
-    private final String securityPolicy;
+    private final SecurityPolicy securityPolicy;
     private final PascalByteString publicCertificate;
     private final PascalByteString thumbprint;
     private final boolean isEncrypted;
@@ -124,8 +123,6 @@ public class SecureChannel {
     private final SecureChannelTransactionManager channelTransactionManager = new SecureChannelTransactionManager();
     private long lifetime = DEFAULT_CONNECTION_LIFETIME;
     private CompletableFuture<Void> keepAlive;
-    private int sendBufferSize;
-    private int maxMessageSize;
     private final List<String> endpoints = new ArrayList<>();
 
     private final AtomicLong senderSequenceNumber = new AtomicLong();
@@ -136,13 +133,14 @@ public class SecureChannel {
         this.endpoint = new PascalString(configuration.getEndpoint());
         this.username = configuration.getUsername();
         this.password = configuration.getPassword();
-        this.securityPolicy = "http://opcfoundation.org/UA/SecurityPolicy#" + configuration.getSecurityPolicy();
+
+        this.securityPolicy = configuration.getSecurityPolicy();
         CertificateKeyPair ckp = configuration.getCertificateKeyPair();
 
-        if (configuration.getSecurityPolicy() != null && SecurityPolicy.byName(configuration.getSecurityPolicy()).isPresent()) {
+        if (securityPolicy != NONE) {
             //Sender Certificate gets populated during the 'discover' phase when encryption is enabled.
             this.senderCertificate = configuration.getSenderCertificate();
-            this.encryptionHandler = new EncryptionHandler(ckp, this.senderCertificate, configuration.getSecurityPolicy());
+            this.encryptionHandler = new EncryptionHandler(ckp, this.senderCertificate, securityPolicy);
 
             try {
                 this.publicCertificate = new PascalByteString(ckp.getCertificate().getEncoded().length, ckp.getCertificate().getEncoded());
@@ -152,13 +150,12 @@ public class SecureChannel {
             }
             this.thumbprint = configuration.getThumbprint();
         } else {
-            this.encryptionHandler = new EncryptionHandler(ckp, this.senderCertificate, configuration.getSecurityPolicy());
+            this.encryptionHandler = new EncryptionHandler(ckp, this.senderCertificate, securityPolicy);
             this.publicCertificate = NULL_BYTE_STRING;
             this.thumbprint = NULL_BYTE_STRING;
             this.isEncrypted = false;
         }
         encryptionHandler.setClientNonce(clientNonce);
-        this.keyStoreFile = configuration.getKeyStoreFile();
 
         // Generate a list of endpoints we can use.
         try {
@@ -311,7 +308,7 @@ public class SecureChannel {
 
             OpcuaOpenRequest openRequest = new OpcuaOpenRequest(FINAL_CHUNK,
                 0,
-                new PascalString(this.securityPolicy),
+                new PascalString(this.securityPolicy.getSecurityPolicyUri()),
                 this.publicCertificate,
                 this.thumbprint,
                 transactionId,
@@ -394,6 +391,7 @@ public class SecureChannel {
             noOfDiscoveryUrls,
             discoveryUrls);
 
+
         CreateSessionRequest createSessionRequest = new CreateSessionRequest(
             requestHeader,
             clientDescription,
@@ -401,7 +399,7 @@ public class SecureChannel {
             this.endpoint,
             new PascalString(sessionName),
             new PascalByteString(clientNonce.length, clientNonce),
-            publicCertificate,//TODO patrykg set only if securityMode != None
+            securityPolicy == NONE ? NULL_BYTE_STRING : publicCertificate,
             120000L,
             0L);
 
@@ -504,17 +502,19 @@ public class SecureChannel {
             REQUEST_TIMEOUT_LONG,
             NULL_EXTENSION_OBJECT);
 
-        SignatureData clientSignature = new SignatureData(NULL_STRING, NULL_BYTE_STRING);
+        SignatureData emptySignature = new SignatureData(NULL_STRING, NULL_BYTE_STRING);
+
+        SignatureData clientSignature = securityPolicy == NONE ? emptySignature : encryptionHandler.createClientSignature(this.senderNonce);
 
         ActivateSessionRequest activateSessionRequest = new ActivateSessionRequest(
             requestHeader,
-            encryptionHandler.createClientSignature(this.senderNonce),
+            clientSignature,
             0,
             null,
             0,
             null,
             userIdentityToken,
-            clientSignature);
+            emptySignature);
 
         ExpandedNodeId expandedNodeId = new ExpandedNodeId(false,           //Namespace Uri Specified
             false,            //Server Index Specified
@@ -874,7 +874,8 @@ public class SecureChannel {
                             List<ExtensionObjectDefinition> endpoints = response.getEndpoints();
                             for (ExtensionObjectDefinition endpoint : endpoints) {
                                 EndpointDescription endpointDescription = (EndpointDescription) endpoint;
-                                if (endpointDescription.getEndpointUrl().getStringValue().equals(this.endpoint.getStringValue()) && endpointDescription.getSecurityPolicyUri().getStringValue().equals(this.securityPolicy)) {
+                                if (endpointDescription.getEndpointUrl().getStringValue().equals(this.endpoint.getStringValue())
+                                    && endpointDescription.getSecurityPolicyUri().getStringValue().equals(this.securityPolicy.getSecurityPolicyUri())) {
                                     LOGGER.info("Found OPC UA endpoint {}", this.endpoint.getStringValue());
                                     this.configuration.setSenderCertificate(endpointDescription.getServerCertificate().getStringValue());
                                 }
@@ -1006,7 +1007,7 @@ public class SecureChannel {
 
                         OpcuaOpenRequest openRequest = new OpcuaOpenRequest(FINAL_CHUNK,
                             0,
-                            new PascalString(this.securityPolicy),
+                            new PascalString(this.securityPolicy.getSecurityPolicyUri()),
                             this.publicCertificate,
                             this.thumbprint,
                             transactionId,
diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/SecurityPolicy.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/SecurityPolicy.java
deleted file mode 100644
index 532197a586..0000000000
--- a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/SecurityPolicy.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package org.apache.plc4x.java.opcua.context;
-
-import java.util.Optional;
-import java.util.stream.Stream;
-
-public enum SecurityPolicy {
-    Basic128Rsa15,
-    Basic256Sha256;
-
-
-    public static Optional<SecurityPolicy> byName(String value) {
-        return Stream.of(values())
-            .filter(policy -> policy.name().equals(value))
-            .findAny();
-    }
-}
diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/SymmetricEncryptionHandler.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/SymmetricEncryptionHandler.java
index bbae72029d..ae5bcc6017 100644
--- a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/SymmetricEncryptionHandler.java
+++ b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/SymmetricEncryptionHandler.java
@@ -3,8 +3,10 @@ package org.apache.plc4x.java.opcua.context;
 import org.apache.plc4x.java.opcua.readwrite.MessagePDU;
 import org.apache.plc4x.java.opcua.readwrite.OpcuaAPU;
 import org.apache.plc4x.java.opcua.readwrite.OpcuaMessageResponse;
+import org.apache.plc4x.java.opcua.security.SecurityPolicy;
+import org.apache.plc4x.java.opcua.security.SecurityPolicy.EncryptionAlgorithm;
+import org.apache.plc4x.java.opcua.security.SymmetricKeys;
 import org.apache.plc4x.java.spi.generation.*;
-import org.eclipse.milo.opcua.stack.core.security.SecurityPolicy;
 
 import javax.crypto.Cipher;
 import javax.crypto.Mac;
@@ -12,7 +14,10 @@ import javax.crypto.NoSuchPaddingException;
 import javax.crypto.spec.IvParameterSpec;
 import javax.crypto.spec.SecretKeySpec;
 import java.nio.ByteBuffer;
-import java.security.*;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.PublicKey;
 import java.security.cert.Certificate;
 import java.security.interfaces.RSAPublicKey;
 
@@ -22,14 +27,13 @@ public class SymmetricEncryptionHandler {
     private static final int SEQUENCE_HEADER_SIZE = 8;
     private static final int SYMMETRIC_SECURITY_HEADER_SIZE = 4;
 
-    private final SecurityPolicy policy = SecurityPolicy.Basic128Rsa15;
+    private final SecurityPolicy policy;
 
 
     private SymmetricKeys keys = null;
 
-    public SymmetricEncryptionHandler() {
-
-
+    public SymmetricEncryptionHandler(SecurityPolicy policy) {
+        this.policy = policy;
     }
 
     /**
@@ -117,7 +121,7 @@ public class SymmetricEncryptionHandler {
             WriteBufferByteBased buf = new WriteBufferByteBased(pdu.getLengthInBytes(), ByteOrder.LITTLE_ENDIAN);
             pdu.serialize(buf);
 
-            String transformation = policy.getSymmetricEncryptionAlgorithm().getTransformation();
+            EncryptionAlgorithm transformation = policy.getSymmetricEncryptionAlgorithm();
             SymmetricKeys symmetricKeys = getSymmetricKeys(clientNonce, serverNonce);
             Cipher cipher = getCipher(symmetricKeys.getServerKeys(), transformation, Cipher.DECRYPT_MODE);
 
@@ -154,7 +158,7 @@ public class SymmetricEncryptionHandler {
         ByteBuffer originalMessage = ByteBuffer.wrap(buf.getBytes(SECURE_MESSAGE_HEADER_SIZE + securityHeaderSize, frameSize));
 
 
-        String transformation = policy.getSymmetricEncryptionAlgorithm().getTransformation();
+        EncryptionAlgorithm transformation = policy.getSymmetricEncryptionAlgorithm();
         Cipher cipher = getCipher(symmetricKeys.getClientKeys(), transformation, Cipher.ENCRYPT_MODE);
 
 
@@ -163,8 +167,8 @@ public class SymmetricEncryptionHandler {
         return buffer.array();
     }
 
-    private static Cipher getCipher(SymmetricKeys.Keys symmetricKeys, String transformation, int mode) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException {
-        Cipher cipher = Cipher.getInstance(transformation);
+    private static Cipher getCipher(SymmetricKeys.Keys symmetricKeys, EncryptionAlgorithm transformation, int mode) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException {
+        Cipher cipher = transformation.getCipher();
 
         SecretKeySpec keySpec = new SecretKeySpec(symmetricKeys.getEncryptionKey(), "AES");
         IvParameterSpec ivSpec = new IvParameterSpec(symmetricKeys.getInitializationVector());
@@ -183,7 +187,7 @@ public class SymmetricEncryptionHandler {
 
     public byte[] sign(byte[] data, SymmetricKeys.Keys symmetricKeys) {
         try {
-            Mac signature = Mac.getInstance("HmacSHA1");
+            Mac signature = policy.getSymmetricSignatureAlgorithm().getSignature();
             signature.init(new SecretKeySpec(symmetricKeys.getSignatureKey(), "HmacSHA1"));
             signature.update(data);
             return signature.doFinal();
@@ -199,18 +203,9 @@ public class SymmetricEncryptionHandler {
         }
     }
 
-
-    static int getAsymmetricKeyLength(Certificate certificate) {
-        PublicKey publicKey = certificate != null ?
-            certificate.getPublicKey() : null;
-
-        return (publicKey instanceof RSAPublicKey) ?
-            ((RSAPublicKey) publicKey).getModulus().bitLength() : 0;
-    }
-
     private SymmetricKeys getSymmetricKeys(byte[] clientNonce, byte[] serverNonce) {
         if (keys == null) {
-            keys = SymmetricKeys.generateKeyPair(clientNonce, serverNonce);
+            keys = SymmetricKeys.generateKeyPair(clientNonce, serverNonce, policy.getSymmetricSignatureAlgorithm());
         }
         return keys;
     }
diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/security/SecurityPolicy.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/security/SecurityPolicy.java
new file mode 100644
index 0000000000..9ddd06e588
--- /dev/null
+++ b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/security/SecurityPolicy.java
@@ -0,0 +1,117 @@
+package org.apache.plc4x.java.opcua.security;
+
+import javax.crypto.Cipher;
+import javax.crypto.Mac;
+import javax.crypto.NoSuchPaddingException;
+import java.security.NoSuchAlgorithmException;
+import java.security.Signature;
+import java.util.Arrays;
+
+public enum SecurityPolicy {
+    NONE("http://opcfoundation.org/UA/SecurityPolicy#None",
+        new MacSignatureAlgorithm(""),
+        new EncryptionAlgorithm(""),
+        new SignatureAlgorithm(""),
+        new EncryptionAlgorithm("")),
+    Basic128Rsa15("http://opcfoundation.org/UA/SecurityPolicy#Basic128Rsa15",
+        new MacSignatureAlgorithm("HmacSHA1"),
+        new EncryptionAlgorithm("AES/CBC/NoPadding"),
+        new SignatureAlgorithm("SHA1withRSA"),
+        new EncryptionAlgorithm("RSA/ECB/PKCS1Padding")
+    );
+
+
+    private final String securityPolicyUri;
+    private final MacSignatureAlgorithm symmetricSignatureAlgorithm;
+
+
+    private final EncryptionAlgorithm symmetricEncryptionAlgorithm;
+    private final SignatureAlgorithm asymmetricSignatureAlgorithm;
+    private final EncryptionAlgorithm asymmetricEncryptionAlgorithm;
+
+
+    SecurityPolicy(String securityPolicyUri,
+                   MacSignatureAlgorithm symmetricSignatureAlgorithm,
+                   EncryptionAlgorithm symmetricEncryptionAlgorithm,
+                   SignatureAlgorithm asymmetricSignatureAlgorithm,
+                   EncryptionAlgorithm asymmetricEncryptionAlgorithm) {
+        this.securityPolicyUri = securityPolicyUri;
+        this.symmetricSignatureAlgorithm = symmetricSignatureAlgorithm;
+        this.symmetricEncryptionAlgorithm = symmetricEncryptionAlgorithm;
+        this.asymmetricSignatureAlgorithm = asymmetricSignatureAlgorithm;
+        this.asymmetricEncryptionAlgorithm = asymmetricEncryptionAlgorithm;
+    }
+
+    public static SecurityPolicy findByName(String securityPolicy) {
+        return Arrays.stream(values())
+            .filter(v -> v.name().equalsIgnoreCase(securityPolicy))
+            .findAny()
+            .orElseThrow();
+    }
+
+    public MacSignatureAlgorithm getSymmetricSignatureAlgorithm() {
+        return symmetricSignatureAlgorithm;
+    }
+
+    public String getSecurityPolicyUri() {
+        return securityPolicyUri;
+    }
+
+    public SignatureAlgorithm getAsymmetricSignatureAlgorithm() {
+        return asymmetricSignatureAlgorithm;
+    }
+
+    public EncryptionAlgorithm getAsymmetricEncryptionAlgorithm() {
+        return asymmetricEncryptionAlgorithm;
+    }
+
+    public EncryptionAlgorithm getSymmetricEncryptionAlgorithm() {
+        return symmetricEncryptionAlgorithm;
+    }
+
+    public static class MacSignatureAlgorithm {
+
+
+        private final String name;
+
+        MacSignatureAlgorithm(String name) {
+            this.name = name;
+        }
+
+        public Mac getSignature() throws NoSuchAlgorithmException {
+            return Mac.getInstance(name);
+        }
+
+        public String getName() {
+            return name;
+        }
+    }
+
+
+    public static class SignatureAlgorithm {
+        private final String name;
+
+        SignatureAlgorithm(String name) {
+            this.name = name;
+        }
+
+        public Signature getSignature() throws NoSuchAlgorithmException {
+            return Signature.getInstance(name);
+        }
+    }
+
+    public static class EncryptionAlgorithm {
+        private final String name;
+
+        EncryptionAlgorithm(String name) {
+            this.name = name;
+        }
+
+        public Cipher getCipher() throws NoSuchPaddingException, NoSuchAlgorithmException {
+            return Cipher.getInstance(name);
+        }
+
+    }
+
+
+}
diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/SymmetricKeys.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/security/SymmetricKeys.java
similarity index 83%
rename from plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/SymmetricKeys.java
rename to plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/security/SymmetricKeys.java
index eb2b1e2dde..1206e46ac7 100644
--- a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/SymmetricKeys.java
+++ b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/security/SymmetricKeys.java
@@ -1,4 +1,6 @@
-package org.apache.plc4x.java.opcua.context;
+package org.apache.plc4x.java.opcua.security;
+
+import org.apache.plc4x.java.opcua.security.SecurityPolicy.MacSignatureAlgorithm;
 
 import javax.crypto.Mac;
 import javax.crypto.spec.SecretKeySpec;
@@ -6,9 +8,6 @@ import javax.crypto.spec.SecretKeySpec;
 public class SymmetricKeys {
 
 
-    private static String KEY_ALGORITHM = "HmacSHA1";
-
-
     private final Keys clientKeys;
     private final Keys serverKeys;
 
@@ -26,20 +25,20 @@ public class SymmetricKeys {
         return serverKeys;
     }
 
-    public static SymmetricKeys generateKeyPair(byte[] clientNonce, byte[] serverNonce) {
+    public static SymmetricKeys generateKeyPair(byte[] clientNonce, byte[] serverNonce, MacSignatureAlgorithm policy) {
         int signatureKeySize = 16;// different for aes
         int encryptionKeySize = 16;
         int cipherTextBlockSize = 16;
 
 
-        byte[] clientSignatureKey = createKey(serverNonce, clientNonce, 0, signatureKeySize);
-        byte[] clientEncryptionKey = createKey(serverNonce, clientNonce, signatureKeySize, encryptionKeySize);
-        byte[] clientInitializationVector = createKey(serverNonce, clientNonce, signatureKeySize + encryptionKeySize, cipherTextBlockSize);
+        byte[] clientSignatureKey = createKey(serverNonce, clientNonce, 0, signatureKeySize, policy);
+        byte[] clientEncryptionKey = createKey(serverNonce, clientNonce, signatureKeySize, encryptionKeySize, policy);
+        byte[] clientInitializationVector = createKey(serverNonce, clientNonce, signatureKeySize + encryptionKeySize, cipherTextBlockSize, policy);
 
 
-        byte[] serverSignatureKey = createKey(clientNonce, serverNonce, 0, signatureKeySize);
-        byte[] serverEncryptionKey = createKey(clientNonce, serverNonce, signatureKeySize, encryptionKeySize);
-        byte[] serverInitializationVector = createKey(clientNonce, serverNonce, signatureKeySize + encryptionKeySize, cipherTextBlockSize);
+        byte[] serverSignatureKey = createKey(clientNonce, serverNonce, 0, signatureKeySize, policy);
+        byte[] serverEncryptionKey = createKey(clientNonce, serverNonce, signatureKeySize, encryptionKeySize, policy);
+        byte[] serverInitializationVector = createKey(clientNonce, serverNonce, signatureKeySize + encryptionKeySize, cipherTextBlockSize, policy);
 
         return new SymmetricKeys(
             new Keys(clientSignatureKey, clientEncryptionKey, clientInitializationVector),
@@ -47,11 +46,11 @@ public class SymmetricKeys {
         );
     }
 
-    private static byte[] createKey(byte[] secret, byte[] seed, int offset, int length) {
+    private static byte[] createKey(byte[] secret, byte[] seed, int offset, int length, MacSignatureAlgorithm macSignatureAlgorithm) {
         try {
-            Mac mac = Mac.getInstance(KEY_ALGORITHM);
+            Mac mac = macSignatureAlgorithm.getSignature();
 
-            byte[] tempBytes = hash(KEY_ALGORITHM, secret, seed, mac, offset + length);
+            byte[] tempBytes = hash(macSignatureAlgorithm.getName(), secret, seed, mac, offset + length);
             byte[] key = new byte[length];
 
             System.arraycopy(tempBytes, offset, key, 0, key.length);
diff --git a/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/OpcuaPlcDriverTest.java b/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/OpcuaPlcDriverTest.java
index 99763e5741..8ad20bb3a8 100644
--- a/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/OpcuaPlcDriverTest.java
+++ b/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/OpcuaPlcDriverTest.java
@@ -28,18 +28,15 @@ import org.apache.plc4x.java.api.messages.PlcReadResponse;
 import org.apache.plc4x.java.api.messages.PlcWriteRequest;
 import org.apache.plc4x.java.api.messages.PlcWriteResponse;
 import org.apache.plc4x.java.api.types.PlcResponseCode;
+import org.apache.plc4x.java.opcua.security.SecurityPolicy;
 import org.assertj.core.api.Condition;
 import org.eclipse.milo.examples.server.ExampleServer;
-import org.junit.jupiter.api.*;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.EnumSource;
 
-
-import static org.apache.plc4x.java.opcua.OpcuaPlcDriver.INET_ADDRESS_PATTERN;
-import static org.apache.plc4x.java.opcua.OpcuaPlcDriver.URI_PATTERN;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.fail;
-import static org.junit.jupiter.api.Assumptions.assumeTrue;
-
-import java.io.File;
 import java.math.BigInteger;
 import java.nio.file.Files;
 import java.nio.file.Path;
@@ -48,6 +45,12 @@ import java.util.concurrent.ExecutionException;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
+import static org.apache.plc4x.java.opcua.OpcuaPlcDriver.INET_ADDRESS_PATTERN;
+import static org.apache.plc4x.java.opcua.OpcuaPlcDriver.URI_PATTERN;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.fail;
+import static org.junit.jupiter.api.Assumptions.assumeTrue;
+
 public class OpcuaPlcDriverTest {
 
     @BeforeAll
@@ -148,7 +151,6 @@ public class OpcuaPlcDriverTest {
         exampleServer = new ExampleServer();
 
 
-
         exampleServer.startup().get();
     }
 
@@ -194,25 +196,14 @@ public class OpcuaPlcDriverTest {
         }));
     }
 
-    @Test
-    public void readVariables() {
+
+    @ParameterizedTest
+    @EnumSource(SecurityPolicy.class)
+    public void readVariables(SecurityPolicy policy) {
         try {
-            Path securityTempDir = Paths.get(System.getProperty("java.io.tmpdir"), "server" );
-            String s1 = securityTempDir.resolve("security").resolve("example-server.pfx").toAbsolutePath().toString();
-
-            String s = securityTempDir.toAbsolutePath().toString();
-            String connectionParams = Stream.of(
-                new Tuple2<>("keyStoreFile", s1),
-                new Tuple2<>("certDirectory", s),
-                new Tuple2<>("keyStorePassword", "password"),
-                new Tuple2<>("securityPolicy", "Basic128Rsa15")
-                )
-                .map(tuple-> tuple._1() + "=" + tuple._2())
-                .collect(Collectors.joining(paramDivider));
-
-
-            String url = tcpConnectionAddress + paramSectionDivider + connectionParams;
-            PlcConnection opcuaConnection = new DefaultPlcDriverManager().getConnection(url);
+            String connectionString = getConnectionString(policy);
+
+            PlcConnection opcuaConnection = new DefaultPlcDriverManager().getConnection(connectionString);
             Condition<PlcConnection> is_connected = new Condition<>(PlcConnection::isConnected, "is connected");
             assertThat(opcuaConnection).is(is_connected);
 
@@ -283,28 +274,16 @@ public class OpcuaPlcDriverTest {
             opcuaConnection.close();
             assert !opcuaConnection.isConnected();
         } catch (Exception e) {
-            fail("Exception during readVariables Test EXCEPTION: " , e);
+            fail("Exception during readVariables Test EXCEPTION: ", e);
         }
     }
 
-    @Test
-    public void writeVariables() throws Exception {
-        Path securityTempDir = Paths.get(System.getProperty("java.io.tmpdir"), "server" );
-        String s1 = securityTempDir.resolve("security").resolve("example-server.pfx").toAbsolutePath().toString();
-
-        String s = securityTempDir.toAbsolutePath().toString();
-        String connectionParams = Stream.of(
-                new Tuple2<>("keyStoreFile", s1),
-                new Tuple2<>("certDirectory", s),
-                new Tuple2<>("keyStorePassword", "password"),
-                new Tuple2<>("securityPolicy", "Basic128Rsa15")
-            )
-            .map(tuple-> tuple._1() + "=" + tuple._2())
-            .collect(Collectors.joining(paramDivider));
-
-
-        String url = tcpConnectionAddress + paramSectionDivider + connectionParams;
-        PlcConnection opcuaConnection = new DefaultPlcDriverManager().getConnection(url);
+    @ParameterizedTest
+    @EnumSource(SecurityPolicy.class)
+    public void writeVariables(SecurityPolicy policy) throws Exception {
+        String connectionString = getConnectionString(policy);
+
+        PlcConnection opcuaConnection = new DefaultPlcDriverManager().getConnection(connectionString);
         Condition<PlcConnection> is_connected = new Condition<>(PlcConnection::isConnected, "is connected");
         assertThat(opcuaConnection).is(is_connected);
 
@@ -483,4 +462,28 @@ public class OpcuaPlcDriverTest {
         }
     }
 
+    private String getConnectionString(SecurityPolicy policy) {
+        switch (policy) {
+            case NONE:
+                return tcpConnectionAddress;
+            case Basic128Rsa15:
+                Path securityTempDir = Paths.get(System.getProperty("java.io.tmpdir"), "server");
+                String keyStoreFile = securityTempDir.resolve("security").resolve("example-server.pfx").toAbsolutePath().toString();
+
+                String certDirectory = securityTempDir.toAbsolutePath().toString();
+                String connectionParams = Stream.of(
+                        new Tuple2<>("keyStoreFile", keyStoreFile),
+                        new Tuple2<>("certDirectory", certDirectory),
+                        new Tuple2<>("keyStorePassword", "password"),
+                        new Tuple2<>("securityPolicy", SecurityPolicy.Basic128Rsa15)
+                    )
+                    .map(tuple -> tuple._1() + "=" + tuple._2())
+                    .collect(Collectors.joining(paramDivider));
+
+
+                return tcpConnectionAddress + paramSectionDivider + connectionParams;
+            default:
+                throw new IllegalStateException();
+        }
+    }
 }


(plc4x) 03/12: Fix signature

Posted by ld...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ldywicki pushed a commit to branch pg/security-policy
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit 8a9c112aacb245714106228984c872b14dcbae80
Author: PatrykGala <pa...@gmail.com>
AuthorDate: Sat Jul 1 18:50:09 2023 +0200

    Fix signature
---
 .../java/opcua/context/AsyncEncryptionHandler.java  | 21 +++++++++------------
 1 file changed, 9 insertions(+), 12 deletions(-)

diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/AsyncEncryptionHandler.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/AsyncEncryptionHandler.java
index 7e8152bba1..0fbbc932bf 100644
--- a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/AsyncEncryptionHandler.java
+++ b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/AsyncEncryptionHandler.java
@@ -17,10 +17,8 @@ public class AsyncEncryptionHandler {
     private static final int SECURE_MESSAGE_HEADER_SIZE = 12;
     private static final int SEQUENCE_HEADER_SIZE = 8;
 
-
     private final SecurityPolicy policy = SecurityPolicy.Basic128Rsa15;
 
-
     private X509Certificate serverCertificate;
     private X509Certificate clientCertificate;
 
@@ -80,19 +78,19 @@ public class AsyncEncryptionHandler {
             opcuaAPU.serialize(buf);
 
             writePadding(paddingSize, buf);
+            updateFrameSize(frameSize, buf);
 
             byte[] sign = sign(buf.getBytes());
             buf.writeByteArray(sign);
 
             buf.setPos(SECURE_MESSAGE_HEADER_SIZE + securityHeaderSize);
 
-
             int blockCount = (frameSize - buf.getPos()) / plainTextBlockSize;
 
             byte[] encrypted = encrypt(plainTextBlockSize, securityHeaderSize, frameSize, buf, blockCount);
             buf.writeByteArray(encrypted);
 
-            updateFrameSize(frameSize, buf);
+
             return new ReadBufferByteBased(buf.getBytes(), ByteOrder.LITTLE_ENDIAN);
         } catch (Exception e) {
             throw new RuntimeException(e);
@@ -120,21 +118,20 @@ public class AsyncEncryptionHandler {
         return buffer.array();
     }
 
-    private static void updateFrameSize(int chunkSize, WriteBufferByteBased buf) throws SerializationException {
+    private static void updateFrameSize(int frameSize, WriteBufferByteBased buf) throws SerializationException {
+        int initPosition = buf.getPos();
         buf.setPos(4);
-        buf.writeInt(32, chunkSize);
-        buf.setPos(chunkSize);
+        buf.writeInt(32, frameSize);
+        buf.setPos(initPosition);
     }
 
 
     public byte[] sign(byte[] data) {
         try {
-            Signature signature = Signature.getInstance(policy.getAsymmetricSignatureAlgorithm().getTransformation());
-            signature.initSign(this.clientPrivateKey);
+            Signature signature = Signature.getInstance("SHA1withRSA");
+            signature.initSign(clientPrivateKey);
             signature.update(data);
-            byte[] ss = signature.sign();
-
-            return ss;
+            return signature.sign();
         } catch (Exception e) {
             throw new RuntimeException(e);
         }


(plc4x) 02/12: Draft v2

Posted by ld...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ldywicki pushed a commit to branch pg/security-policy
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit cc1046bdfe4f60f20cc72e962b0f0ca1e892fd12
Author: PatrykGala <pa...@gmail.com>
AuthorDate: Thu Jun 29 01:26:32 2023 +0200

    Draft v2
---
 plc4j/drivers/opcua/pom.xml                        |  10 +-
 .../java/opcua/context/AsyncEncryptionHandler.java | 159 +++++++++++++++++++++
 .../java/opcua/context/EncryptionHandler.java      |  87 +----------
 .../java/opcua/context/EncryptionHandler2.java     |  16 ---
 .../plc4x/java/opcua/OpcuaPlcDriverTest.java       |   5 +
 .../java/spi/generation/WriteBufferByteBased.java  |   8 +-
 6 files changed, 182 insertions(+), 103 deletions(-)

diff --git a/plc4j/drivers/opcua/pom.xml b/plc4j/drivers/opcua/pom.xml
index 333745bd2e..fbc861ac64 100644
--- a/plc4j/drivers/opcua/pom.xml
+++ b/plc4j/drivers/opcua/pom.xml
@@ -171,28 +171,28 @@
       <groupId>org.apache.plc4x</groupId>
       <artifactId>plc4j-utils-test-utils</artifactId>
       <version>0.11.0-SNAPSHOT</version>
-      <scope>test</scope>
+
     </dependency>
 
     <dependency>
       <groupId>org.eclipse.milo</groupId>
       <artifactId>sdk-client</artifactId>
-      <scope>test</scope>
+
     </dependency>
     <dependency>
       <groupId>org.eclipse.milo</groupId>
       <artifactId>stack-core</artifactId>
-      <scope>test</scope>
+
     </dependency>
     <dependency>
       <groupId>org.eclipse.milo</groupId>
       <artifactId>stack-client</artifactId>
-      <scope>test</scope>
+
     </dependency>
     <dependency>
       <groupId>org.eclipse.milo</groupId>
       <artifactId>server-examples</artifactId>
-      <scope>test</scope>
+
     </dependency>
 
     <dependency>
diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/AsyncEncryptionHandler.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/AsyncEncryptionHandler.java
new file mode 100644
index 0000000000..7e8152bba1
--- /dev/null
+++ b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/AsyncEncryptionHandler.java
@@ -0,0 +1,159 @@
+package org.apache.plc4x.java.opcua.context;
+
+import org.apache.plc4x.java.opcua.readwrite.MessagePDU;
+import org.apache.plc4x.java.opcua.readwrite.OpcuaAPU;
+import org.apache.plc4x.java.spi.generation.*;
+import org.eclipse.milo.opcua.stack.core.security.SecurityPolicy;
+
+import javax.crypto.*;
+import java.nio.ByteBuffer;
+import java.security.*;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+import java.security.interfaces.RSAPublicKey;
+
+
+public class AsyncEncryptionHandler {
+    private static final int SECURE_MESSAGE_HEADER_SIZE = 12;
+    private static final int SEQUENCE_HEADER_SIZE = 8;
+
+
+    private final SecurityPolicy policy = SecurityPolicy.Basic128Rsa15;
+
+
+    private X509Certificate serverCertificate;
+    private X509Certificate clientCertificate;
+
+    private final PrivateKey clientPrivateKey;
+    private final PublicKey clientPublicKey;
+
+    public AsyncEncryptionHandler(X509Certificate serverCertificate, X509Certificate clientCertificate, PrivateKey clientPrivateKey, PublicKey clientPublicKey) {
+        this.serverCertificate = serverCertificate;
+        this.clientCertificate = clientCertificate;
+        this.clientPrivateKey = clientPrivateKey;
+        this.clientPublicKey = clientPublicKey;
+    }
+
+    /**
+     * Docs: https://reference.opcfoundation.org/Core/Part6/v104/docs/6.7
+     *
+     * @param pdu
+     * @param message
+     * @return
+     */
+    public ReadBuffer encodeMessage(MessagePDU pdu, byte[] message) {
+        int unencryptedLength = pdu.getLengthInBytes();
+        int messageLength = message.length;
+
+        int beforeBodyLength = unencryptedLength - messageLength; // message header, security header, sequence header
+
+        int cipherTextBlockSize = (getAsymmetricKeyLength(serverCertificate) + 7) / 8;
+        int plainTextBlockSize = (getAsymmetricKeyLength(serverCertificate) + 7) / 8 - 11;
+        int signatureSize = (getAsymmetricKeyLength(clientCertificate) + 7) / 8;
+
+
+        int maxChunkSize = 8196;
+        int paddingOverhead = 1; // if cipherTextBlockSize > 256 => 2
+
+
+        int securityHeaderSize = beforeBodyLength - SEQUENCE_HEADER_SIZE - SECURE_MESSAGE_HEADER_SIZE;
+        int maxCipherTextSize = maxChunkSize - securityHeaderSize;
+        int maxCipherTextBlocks = maxCipherTextSize / cipherTextBlockSize;
+        int maxPlainTextSize = maxCipherTextBlocks * plainTextBlockSize;
+        int maxBodySize = maxPlainTextSize - SEQUENCE_HEADER_SIZE - paddingOverhead - signatureSize;
+
+        int bodySize = Math.min(message.length, maxBodySize);
+
+        int plainTextSize = SEQUENCE_HEADER_SIZE + bodySize + paddingOverhead + signatureSize;
+        int remaining = plainTextSize % plainTextBlockSize;
+        int paddingSize = remaining > 0 ? plainTextBlockSize - remaining : 0;
+
+        int plainTextContentSize = SEQUENCE_HEADER_SIZE + bodySize +
+            signatureSize + paddingSize + paddingOverhead;
+
+        int frameSize = SECURE_MESSAGE_HEADER_SIZE + securityHeaderSize +
+            (plainTextContentSize / plainTextBlockSize) * cipherTextBlockSize;
+
+        try {
+            WriteBufferByteBased buf = new WriteBufferByteBased(frameSize, ByteOrder.LITTLE_ENDIAN);
+            OpcuaAPU opcuaAPU = new OpcuaAPU(pdu);
+            opcuaAPU.serialize(buf);
+
+            writePadding(paddingSize, buf);
+
+            byte[] sign = sign(buf.getBytes());
+            buf.writeByteArray(sign);
+
+            buf.setPos(SECURE_MESSAGE_HEADER_SIZE + securityHeaderSize);
+
+
+            int blockCount = (frameSize - buf.getPos()) / plainTextBlockSize;
+
+            byte[] encrypted = encrypt(plainTextBlockSize, securityHeaderSize, frameSize, buf, blockCount);
+            buf.writeByteArray(encrypted);
+
+            updateFrameSize(frameSize, buf);
+            return new ReadBufferByteBased(buf.getBytes(), ByteOrder.LITTLE_ENDIAN);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private byte[] encrypt(int plainTextBlockSize, int securityHeaderSize, int frameSize, WriteBufferByteBased buf, int blockCount) throws Exception {
+        ByteBuffer buffer = ByteBuffer.allocate(frameSize - buf.getPos());
+        ByteBuffer originalMessage = ByteBuffer.wrap(buf.getBytes(SECURE_MESSAGE_HEADER_SIZE + securityHeaderSize, frameSize));
+
+
+        String transformation = policy.getAsymmetricEncryptionAlgorithm().getTransformation();
+        Cipher cipher = Cipher.getInstance(transformation);
+        cipher.init(Cipher.ENCRYPT_MODE, serverCertificate.getPublicKey());
+
+        for (int block = 0; block < blockCount; block++) {
+            int position = block * plainTextBlockSize;
+            int limit = (block + 1) * plainTextBlockSize;
+            originalMessage.position(position);
+            originalMessage.limit(limit);
+
+            cipher.doFinal(originalMessage, buffer);
+
+        }
+        return buffer.array();
+    }
+
+    private static void updateFrameSize(int chunkSize, WriteBufferByteBased buf) throws SerializationException {
+        buf.setPos(4);
+        buf.writeInt(32, chunkSize);
+        buf.setPos(chunkSize);
+    }
+
+
+    public byte[] sign(byte[] data) {
+        try {
+            Signature signature = Signature.getInstance(policy.getAsymmetricSignatureAlgorithm().getTransformation());
+            signature.initSign(this.clientPrivateKey);
+            signature.update(data);
+            byte[] ss = signature.sign();
+
+            return ss;
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private void writePadding(int paddingSize, WriteBufferByteBased buffer) throws Exception {
+        buffer.writeByte((byte) paddingSize);
+        for (int i = 0; i < paddingSize; i++) {
+            buffer.writeByte((byte) paddingSize);
+        }
+    }
+
+
+    static int getAsymmetricKeyLength(Certificate certificate) {
+        PublicKey publicKey = certificate != null ?
+            certificate.getPublicKey() : null;
+
+        return (publicKey instanceof RSAPublicKey) ?
+            ((RSAPublicKey) publicKey).getModulus().bitLength() : 0;
+    }
+
+}
diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/EncryptionHandler.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/EncryptionHandler.java
index cbcaab226f..22bd72240e 100644
--- a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/EncryptionHandler.java
+++ b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/EncryptionHandler.java
@@ -18,7 +18,6 @@
  */
 package org.apache.plc4x.java.opcua.context;
 
-import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
 import org.apache.plc4x.java.opcua.protocol.OpcuaProtocolLogic;
 import org.apache.plc4x.java.opcua.readwrite.MessagePDU;
 import org.apache.plc4x.java.opcua.readwrite.OpcuaAPU;
@@ -30,15 +29,13 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import javax.crypto.Cipher;
-import javax.crypto.Mac;
-import javax.crypto.spec.SecretKeySpec;
 import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.security.*;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.Security;
+import java.security.Signature;
 import java.security.cert.CertificateFactory;
 import java.security.cert.X509Certificate;
-import java.util.ArrayList;
-import java.util.List;
 
 
 public class EncryptionHandler {
@@ -72,43 +69,10 @@ public class EncryptionHandler {
         this.serverCertificate = serverCertificate;
     }
 
+    //https://reference.opcfoundation.org/Core/Part6/v104/docs/6.7
     public ReadBuffer encodeMessage(MessagePDU pdu, byte[] message) {
-        int PREENCRYPTED_BLOCK_LENGTH = 190;
-        int unencryptedLength = pdu.getLengthInBytes();
-        int openRequestLength = message.length;
-        int positionFirstBlock = unencryptedLength - openRequestLength - 8;
-        int paddingSize = PREENCRYPTED_BLOCK_LENGTH - ((openRequestLength + 256 + 1 + 8) % PREENCRYPTED_BLOCK_LENGTH);
-        int preEncryptedLength = openRequestLength + 256 + 1 + 8 + paddingSize;
-        if (preEncryptedLength % PREENCRYPTED_BLOCK_LENGTH != 0) {
-            throw new PlcRuntimeException("Pre encrypted block length " + preEncryptedLength + " isn't a multiple of the block size");
-        }
-        int numberOfBlocks = preEncryptedLength / PREENCRYPTED_BLOCK_LENGTH;
-        int encryptedLength = numberOfBlocks * 256 + positionFirstBlock;
-        WriteBufferByteBased buf = new WriteBufferByteBased(encryptedLength, ByteOrder.LITTLE_ENDIAN);
-        try {
-            OpcuaAPU opcuaAPU = new OpcuaAPU(pdu);
-            opcuaAPU.serialize(buf);
-            byte paddingByte = (byte) paddingSize;
-            buf.writeByte(paddingByte);
-            for (int i = 0; i < paddingSize; i++) {
-                buf.writeByte(paddingByte);
-            }
-            //Writing Message Length
-            int tempPos = buf.getPos();
-            buf.setPos(4);
-            buf.writeInt(32, encryptedLength);
-            buf.setPos(tempPos);
-            byte[] signature = sign(getBytes(buf.getBytes(), 0, unencryptedLength + paddingSize + 1));
-            //Write the signature to the end of the buffer
-            for (byte b : signature) {
-                buf.writeByte(b);
-            }
-//            buf.setPos(positionFirstBlock);
-            encryptBlock(buf, getBytes(buf.getBytes(), positionFirstBlock, positionFirstBlock + preEncryptedLength));
-            return new ReadBufferByteBased(buf.getData(), ByteOrder.LITTLE_ENDIAN);
-        } catch (Exception e) {
-            throw new PlcRuntimeException("Unable to parse apu prior to encrypting");
-        }
+        return new AsyncEncryptionHandler(serverCertificate, clientCertificate, clientPrivateKey, clientPublicKey)
+            .encodeMessage(pdu, message);
     }
 
     public OpcuaAPU decodeMessage(OpcuaAPU pdu) {//TODo patrykg
@@ -191,43 +155,6 @@ public class EncryptionHandler {
         }
     }
 
-    public void encryptBlock(WriteBuffer buf, byte[] data) {
-        try {
-            Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
-            cipher.init(Cipher.ENCRYPT_MODE, this.serverCertificate.getPublicKey());
-            List<Byte> b = new ArrayList<>();
-            for (int i = 0; i < data.length; i += 190) {
-                LOGGER.info("Iterate:- {}, Data Length:- {}", i, data.length);
-
-
-                byte[] encrypted = cipher.doFinal(data, i, 190);
-                for (int j = 0; j < 256; j++) {
-                    b.add(encrypted[j]);
-//                    buf.writeByte(encrypted[j]);
-                }
-            }
-
-            byte[] bytes = cipher.doFinal(data);
-            System.out.println(b);
-        } catch (Exception e) {
-            LOGGER.error("Unable to encrypt Data",e);
-            e.printStackTrace();
-        }
-    }
-
-    public void encryptHmacBlock(WriteBuffer buf, byte[] data) {
-        try {
-            Mac cipher = Mac.getInstance("HmacSHA256");
-            SecretKeySpec keySpec = new SecretKeySpec(getSecretKey(), "HmacSHA256");
-            cipher.init(keySpec);
-        } catch (Exception e) {
-            LOGGER.error("Unable to encrypt Data", e);
-        }
-    }
-
-    public byte[] getSecretKey() {
-        return null;
-    }
 
     public static X509Certificate getCertificateX509(byte[] senderCertificate) {
         try {
diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/EncryptionHandler2.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/EncryptionHandler2.java
deleted file mode 100644
index 26b41593bd..0000000000
--- a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/EncryptionHandler2.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package org.apache.plc4x.java.opcua.context;
-
-import org.apache.plc4x.java.opcua.readwrite.MessagePDU;
-import org.apache.plc4x.java.spi.generation.ReadBuffer;
-
-public class EncryptionHandler2 {
-
-    public ReadBuffer encodeMessage(MessagePDU pdu, byte[] message) {
-        int securityHeaderSize = pdu.getLengthInBytes();
-
-
-
-        return null;
-    }
-
-}
diff --git a/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/OpcuaPlcDriverTest.java b/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/OpcuaPlcDriverTest.java
index dd93264988..3dba6eb7f2 100644
--- a/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/OpcuaPlcDriverTest.java
+++ b/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/OpcuaPlcDriverTest.java
@@ -145,6 +145,9 @@ public class OpcuaPlcDriverTest {
         }
 
         exampleServer = new ExampleServer();
+
+
+
         exampleServer.startup().get();
     }
 
@@ -198,6 +201,8 @@ public class OpcuaPlcDriverTest {
 
             String s1 = securityTempDir.resolve("security").resolve("example-server.pfx").toAbsolutePath().toString();
 
+
+
             String s = securityTempDir.toAbsolutePath().toString();
             String connectionParams = Stream.of(
                 new Tuple2<>("keyStoreFile", s1),
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WriteBufferByteBased.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WriteBufferByteBased.java
index 84465b3629..8d4ac22c6c 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WriteBufferByteBased.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WriteBufferByteBased.java
@@ -69,6 +69,10 @@ public class WriteBufferByteBased implements WriteBuffer, BufferCommons {
         return ArrayUtils.subarray(bb.array(), 0, getPos());
     }
 
+    public byte[] getBytes(int start, int end) {
+        return ArrayUtils.subarray(bb.array(), start, end);
+    }
+
     @Override
     public int getPos() {
         return (int) bo.getPos();
@@ -388,8 +392,8 @@ public class WriteBufferByteBased implements WriteBuffer, BufferCommons {
             case "UTF16LE":
             case "UTF16BE": {
                 bytes = value.getBytes(StandardCharsets.UTF_16);
-                if(bytes.length > 2) {
-                    bytes = new byte[] {
+                if (bytes.length > 2) {
+                    bytes = new byte[]{
                         bytes[2], bytes[3]
                     };
                 }


(plc4x) 05/12: Draft - read variable from milo - more tests

Posted by ld...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ldywicki pushed a commit to branch pg/security-policy
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit a1a028028e5322507b695b5182e7fc928dc2122a
Author: PatrykGala <pa...@gmail.com>
AuthorDate: Wed Jul 19 11:52:09 2023 +0200

    Draft - read variable from milo - more tests
---
 .../plc4x/java/opcua/OpcuaPlcDriverTest.java       | 52 +++++++++++-----------
 1 file changed, 26 insertions(+), 26 deletions(-)

diff --git a/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/OpcuaPlcDriverTest.java b/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/OpcuaPlcDriverTest.java
index ea22e1f368..87d0d6e898 100644
--- a/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/OpcuaPlcDriverTest.java
+++ b/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/OpcuaPlcDriverTest.java
@@ -222,19 +222,19 @@ public class OpcuaPlcDriverTest {
 
             PlcReadRequest.Builder builder = opcuaConnection.readRequestBuilder();
             builder.addTagAddress("Bool", BOOL_IDENTIFIER_READ_WRITE);
-//            builder.addTagAddress("Byte", BYTE_IDENTIFIER_READ_WRITE);
-//            builder.addTagAddress("Double", DOUBLE_IDENTIFIER_READ_WRITE);
-//            builder.addTagAddress("Float", FLOAT_IDENTIFIER_READ_WRITE);
-//            builder.addTagAddress("Int16", INT16_IDENTIFIER_READ_WRITE);
-//            builder.addTagAddress("Int32", INT32_IDENTIFIER_READ_WRITE);
-//            builder.addTagAddress("Int64", INT64_IDENTIFIER_READ_WRITE);
-//            builder.addTagAddress("Integer", INTEGER_IDENTIFIER_READ_WRITE);
-//            builder.addTagAddress("SByte", SBYTE_IDENTIFIER_READ_WRITE);
-//            builder.addTagAddress("String", STRING_IDENTIFIER_READ_WRITE);
-//            builder.addTagAddress("UInt16", UINT16_IDENTIFIER_READ_WRITE);
-//            builder.addTagAddress("UInt32", UINT32_IDENTIFIER_READ_WRITE);
-//            builder.addTagAddress("UInt64", UINT64_IDENTIFIER_READ_WRITE);
-//            builder.addTagAddress("UInteger", UINTEGER_IDENTIFIER_READ_WRITE);
+            builder.addTagAddress("Byte", BYTE_IDENTIFIER_READ_WRITE);
+            builder.addTagAddress("Double", DOUBLE_IDENTIFIER_READ_WRITE);
+            builder.addTagAddress("Float", FLOAT_IDENTIFIER_READ_WRITE);
+            builder.addTagAddress("Int16", INT16_IDENTIFIER_READ_WRITE);
+            builder.addTagAddress("Int32", INT32_IDENTIFIER_READ_WRITE);
+            builder.addTagAddress("Int64", INT64_IDENTIFIER_READ_WRITE);
+            builder.addTagAddress("Integer", INTEGER_IDENTIFIER_READ_WRITE);
+            builder.addTagAddress("SByte", SBYTE_IDENTIFIER_READ_WRITE);
+            builder.addTagAddress("String", STRING_IDENTIFIER_READ_WRITE);
+            builder.addTagAddress("UInt16", UINT16_IDENTIFIER_READ_WRITE);
+            builder.addTagAddress("UInt32", UINT32_IDENTIFIER_READ_WRITE);
+            builder.addTagAddress("UInt64", UINT64_IDENTIFIER_READ_WRITE);
+            builder.addTagAddress("UInteger", UINTEGER_IDENTIFIER_READ_WRITE);
 //
 //            builder.addTagAddress("BoolArray", BOOL_ARRAY_IDENTIFIER);
 //            //builder.addTagAddress("ByteStringArray", BYTE_STRING_ARRAY_IDENTIFIER);
@@ -255,19 +255,19 @@ public class OpcuaPlcDriverTest {
             PlcReadRequest request = builder.build();
             PlcReadResponse response = request.execute().get();
             assertThat(response.getResponseCode("Bool")).isEqualTo(PlcResponseCode.OK);
-//            assertThat(response.getResponseCode("Byte")).isEqualTo(PlcResponseCode.OK);
-//            assertThat(response.getResponseCode("Double")).isEqualTo(PlcResponseCode.OK);
-//            assertThat(response.getResponseCode("Float")).isEqualTo(PlcResponseCode.OK);
-//            assertThat(response.getResponseCode("Int16")).isEqualTo(PlcResponseCode.OK);
-//            assertThat(response.getResponseCode("Int32")).isEqualTo(PlcResponseCode.OK);
-//            assertThat(response.getResponseCode("Int64")).isEqualTo(PlcResponseCode.OK);
-//            assertThat(response.getResponseCode("Integer")).isEqualTo(PlcResponseCode.OK);
-//            assertThat(response.getResponseCode("SByte")).isEqualTo(PlcResponseCode.OK);
-//            assertThat(response.getResponseCode("String")).isEqualTo(PlcResponseCode.OK);
-//            assertThat(response.getResponseCode("UInt16")).isEqualTo(PlcResponseCode.OK);
-//            assertThat(response.getResponseCode("UInt32")).isEqualTo(PlcResponseCode.OK);
-//            assertThat(response.getResponseCode("UInt64")).isEqualTo(PlcResponseCode.OK);
-//            assertThat(response.getResponseCode("UInteger")).isEqualTo(PlcResponseCode.OK);
+            assertThat(response.getResponseCode("Byte")).isEqualTo(PlcResponseCode.OK);
+            assertThat(response.getResponseCode("Double")).isEqualTo(PlcResponseCode.OK);
+            assertThat(response.getResponseCode("Float")).isEqualTo(PlcResponseCode.OK);
+            assertThat(response.getResponseCode("Int16")).isEqualTo(PlcResponseCode.OK);
+            assertThat(response.getResponseCode("Int32")).isEqualTo(PlcResponseCode.OK);
+            assertThat(response.getResponseCode("Int64")).isEqualTo(PlcResponseCode.OK);
+            assertThat(response.getResponseCode("Integer")).isEqualTo(PlcResponseCode.OK);
+            assertThat(response.getResponseCode("SByte")).isEqualTo(PlcResponseCode.OK);
+            assertThat(response.getResponseCode("String")).isEqualTo(PlcResponseCode.OK);
+            assertThat(response.getResponseCode("UInt16")).isEqualTo(PlcResponseCode.OK);
+            assertThat(response.getResponseCode("UInt32")).isEqualTo(PlcResponseCode.OK);
+            assertThat(response.getResponseCode("UInt64")).isEqualTo(PlcResponseCode.OK);
+            assertThat(response.getResponseCode("UInteger")).isEqualTo(PlcResponseCode.OK);
 //
 //            assertThat(response.getResponseCode("BoolArray")).isEqualTo(PlcResponseCode.OK);
 //            assertThat(response.getResponseCode("ByteArray")).isEqualTo(PlcResponseCode.OK);


(plc4x) 09/12: Write variables test - add connection conf

Posted by ld...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ldywicki pushed a commit to branch pg/security-policy
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit 0aea62481c1501fa8c1aebd7f2dd0fe6d14030de
Author: PatrykGala <pa...@gmail.com>
AuthorDate: Mon Aug 14 18:33:57 2023 +0200

    Write variables test - add connection conf
---
 .../plc4x/java/opcua/OpcuaPlcDriverTest.java       | 87 ++++++++++++----------
 1 file changed, 49 insertions(+), 38 deletions(-)

diff --git a/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/OpcuaPlcDriverTest.java b/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/OpcuaPlcDriverTest.java
index 87d0d6e898..99763e5741 100644
--- a/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/OpcuaPlcDriverTest.java
+++ b/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/OpcuaPlcDriverTest.java
@@ -32,6 +32,7 @@ import org.assertj.core.api.Condition;
 import org.eclipse.milo.examples.server.ExampleServer;
 import org.junit.jupiter.api.*;
 
+
 import static org.apache.plc4x.java.opcua.OpcuaPlcDriver.INET_ADDRESS_PATTERN;
 import static org.apache.plc4x.java.opcua.OpcuaPlcDriver.URI_PATTERN;
 import static org.assertj.core.api.Assertions.assertThat;
@@ -197,12 +198,8 @@ public class OpcuaPlcDriverTest {
     public void readVariables() {
         try {
             Path securityTempDir = Paths.get(System.getProperty("java.io.tmpdir"), "server" );
-            File pkiDir = securityTempDir.resolve("pki").toFile();
-
             String s1 = securityTempDir.resolve("security").resolve("example-server.pfx").toAbsolutePath().toString();
 
-
-
             String s = securityTempDir.toAbsolutePath().toString();
             String connectionParams = Stream.of(
                 new Tuple2<>("keyStoreFile", s1),
@@ -212,8 +209,7 @@ public class OpcuaPlcDriverTest {
                 )
                 .map(tuple-> tuple._1() + "=" + tuple._2())
                 .collect(Collectors.joining(paramDivider));
-///var/folders/8_/d821tw6d03g856b1k51tvsdw0000gn/T/server/security/example-server.pfx
-///var/folders/8_/d821tw6d03g856b1k51tvsdw0000gn/T/server/security/security
+
 
             String url = tcpConnectionAddress + paramSectionDivider + connectionParams;
             PlcConnection opcuaConnection = new DefaultPlcDriverManager().getConnection(url);
@@ -235,23 +231,23 @@ public class OpcuaPlcDriverTest {
             builder.addTagAddress("UInt32", UINT32_IDENTIFIER_READ_WRITE);
             builder.addTagAddress("UInt64", UINT64_IDENTIFIER_READ_WRITE);
             builder.addTagAddress("UInteger", UINTEGER_IDENTIFIER_READ_WRITE);
-//
-//            builder.addTagAddress("BoolArray", BOOL_ARRAY_IDENTIFIER);
-//            //builder.addTagAddress("ByteStringArray", BYTE_STRING_ARRAY_IDENTIFIER);
-//            builder.addTagAddress("ByteArray", BYTE_ARRAY_IDENTIFIER);
-//            builder.addTagAddress("DoubleArray", DOUBLE_ARRAY_IDENTIFIER);
-//            builder.addTagAddress("FloatArray", FLOAT_ARRAY_IDENTIFIER);
-//            builder.addTagAddress("Int16Array", INT16_ARRAY_IDENTIFIER);
-//            builder.addTagAddress("Int32Array", INT32_ARRAY_IDENTIFIER);
-//            builder.addTagAddress("Int64Array", INT64_ARRAY_IDENTIFIER);
-//            builder.addTagAddress("SByteArray", SBYTE_ARRAY_IDENTIFIER);
-//            builder.addTagAddress("StringArray", STRING_ARRAY_IDENTIFIER);
-//            builder.addTagAddress("UInt16Array", UINT16_ARRAY_IDENTIFIER);
-//            builder.addTagAddress("UInt32Array", UINT32_ARRAY_IDENTIFIER);
-//            builder.addTagAddress("UInt64Array", UINT64_ARRAY_IDENTIFIER);
-//
-//            builder.addTagAddress("DoesNotExists", DOES_NOT_EXIST_IDENTIFIER_READ_WRITE);
-//
+
+            builder.addTagAddress("BoolArray", BOOL_ARRAY_IDENTIFIER);
+//            builder.addTagAddress("ByteStringArray", BYTE_STRING_ARRAY_IDENTIFIER);
+            builder.addTagAddress("ByteArray", BYTE_ARRAY_IDENTIFIER);
+            builder.addTagAddress("DoubleArray", DOUBLE_ARRAY_IDENTIFIER);
+            builder.addTagAddress("FloatArray", FLOAT_ARRAY_IDENTIFIER);
+            builder.addTagAddress("Int16Array", INT16_ARRAY_IDENTIFIER);
+            builder.addTagAddress("Int32Array", INT32_ARRAY_IDENTIFIER);
+            builder.addTagAddress("Int64Array", INT64_ARRAY_IDENTIFIER);
+            builder.addTagAddress("SByteArray", SBYTE_ARRAY_IDENTIFIER);
+            builder.addTagAddress("StringArray", STRING_ARRAY_IDENTIFIER);
+            builder.addTagAddress("UInt16Array", UINT16_ARRAY_IDENTIFIER);
+            builder.addTagAddress("UInt32Array", UINT32_ARRAY_IDENTIFIER);
+            builder.addTagAddress("UInt64Array", UINT64_ARRAY_IDENTIFIER);
+
+            builder.addTagAddress("DoesNotExists", DOES_NOT_EXIST_IDENTIFIER_READ_WRITE);
+
             PlcReadRequest request = builder.build();
             PlcReadResponse response = request.execute().get();
             assertThat(response.getResponseCode("Bool")).isEqualTo(PlcResponseCode.OK);
@@ -268,21 +264,21 @@ public class OpcuaPlcDriverTest {
             assertThat(response.getResponseCode("UInt32")).isEqualTo(PlcResponseCode.OK);
             assertThat(response.getResponseCode("UInt64")).isEqualTo(PlcResponseCode.OK);
             assertThat(response.getResponseCode("UInteger")).isEqualTo(PlcResponseCode.OK);
+
+            assertThat(response.getResponseCode("BoolArray")).isEqualTo(PlcResponseCode.OK);
+            assertThat(response.getResponseCode("ByteArray")).isEqualTo(PlcResponseCode.OK);
+            assertThat(response.getResponseCode("DoubleArray")).isEqualTo(PlcResponseCode.OK);
+            assertThat(response.getResponseCode("FloatArray")).isEqualTo(PlcResponseCode.OK);
+            assertThat(response.getResponseCode("Int16Array")).isEqualTo(PlcResponseCode.OK);
+            assertThat(response.getResponseCode("Int32Array")).isEqualTo(PlcResponseCode.OK);
+            assertThat(response.getResponseCode("Int64Array")).isEqualTo(PlcResponseCode.OK);
+            assertThat(response.getResponseCode("SByteArray")).isEqualTo(PlcResponseCode.OK);
+            assertThat(response.getResponseCode("StringArray")).isEqualTo(PlcResponseCode.OK);
+            assertThat(response.getResponseCode("UInt16Array")).isEqualTo(PlcResponseCode.OK);
+            assertThat(response.getResponseCode("UInt32Array")).isEqualTo(PlcResponseCode.OK);
+            assertThat(response.getResponseCode("UInt64Array")).isEqualTo(PlcResponseCode.OK);
 //
-//            assertThat(response.getResponseCode("BoolArray")).isEqualTo(PlcResponseCode.OK);
-//            assertThat(response.getResponseCode("ByteArray")).isEqualTo(PlcResponseCode.OK);
-//            assertThat(response.getResponseCode("DoubleArray")).isEqualTo(PlcResponseCode.OK);
-//            assertThat(response.getResponseCode("FloatArray")).isEqualTo(PlcResponseCode.OK);
-//            assertThat(response.getResponseCode("Int16Array")).isEqualTo(PlcResponseCode.OK);
-//            assertThat(response.getResponseCode("Int32Array")).isEqualTo(PlcResponseCode.OK);
-//            assertThat(response.getResponseCode("Int64Array")).isEqualTo(PlcResponseCode.OK);
-//            assertThat(response.getResponseCode("SByteArray")).isEqualTo(PlcResponseCode.OK);
-//            assertThat(response.getResponseCode("StringArray")).isEqualTo(PlcResponseCode.OK);
-//            assertThat(response.getResponseCode("UInt16Array")).isEqualTo(PlcResponseCode.OK);
-//            assertThat(response.getResponseCode("UInt32Array")).isEqualTo(PlcResponseCode.OK);
-//            assertThat(response.getResponseCode("UInt64Array")).isEqualTo(PlcResponseCode.OK);
-//
-//            assertThat(response.getResponseCode("DoesNotExists")).isEqualTo(PlcResponseCode.NOT_FOUND);
+            assertThat(response.getResponseCode("DoesNotExists")).isEqualTo(PlcResponseCode.NOT_FOUND);
 
             opcuaConnection.close();
             assert !opcuaConnection.isConnected();
@@ -293,7 +289,22 @@ public class OpcuaPlcDriverTest {
 
     @Test
     public void writeVariables() throws Exception {
-        PlcConnection opcuaConnection = new DefaultPlcDriverManager().getConnection(tcpConnectionAddress);
+        Path securityTempDir = Paths.get(System.getProperty("java.io.tmpdir"), "server" );
+        String s1 = securityTempDir.resolve("security").resolve("example-server.pfx").toAbsolutePath().toString();
+
+        String s = securityTempDir.toAbsolutePath().toString();
+        String connectionParams = Stream.of(
+                new Tuple2<>("keyStoreFile", s1),
+                new Tuple2<>("certDirectory", s),
+                new Tuple2<>("keyStorePassword", "password"),
+                new Tuple2<>("securityPolicy", "Basic128Rsa15")
+            )
+            .map(tuple-> tuple._1() + "=" + tuple._2())
+            .collect(Collectors.joining(paramDivider));
+
+
+        String url = tcpConnectionAddress + paramSectionDivider + connectionParams;
+        PlcConnection opcuaConnection = new DefaultPlcDriverManager().getConnection(url);
         Condition<PlcConnection> is_connected = new Condition<>(PlcConnection::isConnected, "is connected");
         assertThat(opcuaConnection).is(is_connected);
 


(plc4x) 01/12: Draft

Posted by ld...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ldywicki pushed a commit to branch pg/security-policy
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit 9bd9a9437e8b434b0db7d70fe8a9c5f9674ddb59
Author: PatrykGala <pa...@gmail.com>
AuthorDate: Wed Jun 21 09:15:26 2023 +0200

    Draft
---
 .../java/opcua/readwrite/MessageSecurityMode.java  |   8 +-
 .../opcua/readwrite/OpenSecureChannelRequest.java  |   2 +-
 .../apache/plc4x/java/opcua/OpcuaPlcDriver.java    |  36 ++---
 .../java/opcua/context/EncryptionHandler.java      |  33 +++--
 .../java/opcua/context/EncryptionHandler2.java     |  16 +++
 .../plc4x/java/opcua/context/SecureChannel.java    |  19 ++-
 .../plc4x/java/opcua/context/SecurityPolicy.java   |  16 +++
 .../plc4x/java/opcua/OpcuaPlcDriverTest.java       | 148 ++++++++++++---------
 .../opcua/src/test/resources/log4j.properties      |   2 +-
 .../opcua/src/test/resources/logback-test.xml      |   2 +-
 plc4j/pom.xml                                      |   2 +-
 pom.xml                                            |   2 +-
 12 files changed, 179 insertions(+), 107 deletions(-)

diff --git a/plc4j/drivers/opcua/src/main/generated/org/apache/plc4x/java/opcua/readwrite/MessageSecurityMode.java b/plc4j/drivers/opcua/src/main/generated/org/apache/plc4x/java/opcua/readwrite/MessageSecurityMode.java
index 37708cd5a0..5f392b155d 100644
--- a/plc4j/drivers/opcua/src/main/generated/org/apache/plc4x/java/opcua/readwrite/MessageSecurityMode.java
+++ b/plc4j/drivers/opcua/src/main/generated/org/apache/plc4x/java/opcua/readwrite/MessageSecurityMode.java
@@ -24,10 +24,10 @@ import java.util.Map;
 // Code generated by code-generation. DO NOT EDIT.
 
 public enum MessageSecurityMode {
-  messageSecurityModeInvalid((long) 0L),
-  messageSecurityModeNone((long) 1L),
-  messageSecurityModeSign((long) 2L),
-  messageSecurityModeSignAndEncrypt((long) 3L);
+  messageSecurityModeInvalid(0L),
+  messageSecurityModeNone(1L),
+  messageSecurityModeSign(2L),
+  messageSecurityModeSignAndEncrypt(3L);//TODO this
   private static final Map<Long, MessageSecurityMode> map;
 
   static {
diff --git a/plc4j/drivers/opcua/src/main/generated/org/apache/plc4x/java/opcua/readwrite/OpenSecureChannelRequest.java b/plc4j/drivers/opcua/src/main/generated/org/apache/plc4x/java/opcua/readwrite/OpenSecureChannelRequest.java
index 8c5091f53c..0f3f536935 100644
--- a/plc4j/drivers/opcua/src/main/generated/org/apache/plc4x/java/opcua/readwrite/OpenSecureChannelRequest.java
+++ b/plc4j/drivers/opcua/src/main/generated/org/apache/plc4x/java/opcua/readwrite/OpenSecureChannelRequest.java
@@ -118,7 +118,7 @@ public class OpenSecureChannelRequest extends ExtensionObjectDefinition implemen
     writeSimpleEnumField(
         "securityMode",
         "MessageSecurityMode",
-        securityMode,
+        securityMode,//TODO patrykg
         new DataWriterEnumDefault<>(
             MessageSecurityMode::getValue,
             MessageSecurityMode::name,
diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/OpcuaPlcDriver.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/OpcuaPlcDriver.java
index 10cbe9dec1..8df80ecd3b 100644
--- a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/OpcuaPlcDriver.java
+++ b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/OpcuaPlcDriver.java
@@ -45,14 +45,14 @@ import static org.apache.plc4x.java.spi.configuration.ConfigurationFactory.confi
 public class OpcuaPlcDriver extends GeneratedDriverBase<OpcuaAPU> {
 
     public static final Pattern INET_ADDRESS_PATTERN = Pattern.compile("(:(?<transportCode>[a-z0-9]*))?://" +
-                                                                        "(?<transportHost>[\\w.-]+)(:" +
-                                                                        "(?<transportPort>\\d*))?");
+        "(?<transportHost>[\\w.-]+)(:" +
+        "(?<transportPort>\\d*))?");
 
     public static final Pattern URI_PATTERN = Pattern.compile("^(?<protocolCode>opcua)" +
-                                                                    INET_ADDRESS_PATTERN +
-                                                                    "(?<transportEndpoint>[\\w/=]*)[\\?]?" +
-                                                                    "(?<paramString>([^\\=]+\\=[^\\=&]+[&]?)*)"
-                                                                );
+        INET_ADDRESS_PATTERN +
+        "(?<transportEndpoint>[\\w/=]*)[\\?]?" +
+        "(?<paramString>([^\\=]+\\=[^\\=&]+[&]?)*)"
+    );
 
     private boolean isEncrypted;
 
@@ -152,7 +152,7 @@ public class OpcuaPlcDriver extends GeneratedDriverBase<OpcuaAPU> {
         final String paramString = matcher.group("paramString");
 
         // Check if the protocol code matches this driver.
-        if(!protocolCode.equals(getProtocolCode())) {
+        if (!protocolCode.equals(getProtocolCode())) {
             // Actually this shouldn't happen as the DriverManager should have not used this driver in the first place.
             throw new PlcConnectionException(
                 "This driver is not suited to handle this connection string");
@@ -161,7 +161,7 @@ public class OpcuaPlcDriver extends GeneratedDriverBase<OpcuaAPU> {
         // Create the configuration object.
         OpcuaConfiguration configuration = (OpcuaConfiguration) new ConfigurationFactory().createConfiguration(
             getConfigurationType(), paramString);
-        if(configuration == null) {
+        if (configuration == null) {
             throw new PlcConnectionException("Unsupported configuration");
         }
         configuration.setTransportCode(transportCode);
@@ -175,12 +175,12 @@ public class OpcuaPlcDriver extends GeneratedDriverBase<OpcuaAPU> {
         ServiceLoader<Transport> transportLoader = ServiceLoader.load(
             Transport.class, Thread.currentThread().getContextClassLoader());
         for (Transport curTransport : transportLoader) {
-            if(curTransport.getTransportCode().equals(transportCode)) {
+            if (curTransport.getTransportCode().equals(transportCode)) {
                 transport = curTransport;
                 break;
             }
         }
-        if(transport == null) {
+        if (transport == null) {
             throw new PlcConnectionException("Unsupported transport " + transportCode);
         }
 
@@ -189,7 +189,7 @@ public class OpcuaPlcDriver extends GeneratedDriverBase<OpcuaAPU> {
 
         // Create an instance of the communication channel which the driver should use.
         ChannelFactory channelFactory = transport.createChannelFactory(transportHost + ":" + transportPort);
-        if(channelFactory == null) {
+        if (channelFactory == null) {
             throw new PlcConnectionException("Unable to get channel factory from url " + transportHost + ":" + transportPort);
         }
         configure(configuration, channelFactory);
@@ -199,13 +199,13 @@ public class OpcuaPlcDriver extends GeneratedDriverBase<OpcuaAPU> {
 
         // Make the "await setup complete" overridable via system property.
         boolean awaitSetupComplete = awaitSetupComplete();
-        if(System.getProperty(PROPERTY_PLC4X_FORCE_AWAIT_SETUP_COMPLETE) != null) {
+        if (System.getProperty(PROPERTY_PLC4X_FORCE_AWAIT_SETUP_COMPLETE) != null) {
             awaitSetupComplete = Boolean.parseBoolean(System.getProperty(PROPERTY_PLC4X_FORCE_AWAIT_SETUP_COMPLETE));
         }
 
         // Make the "await disconnect complete" overridable via system property.
         boolean awaitDisconnectComplete = awaitDisconnectComplete();
-        if(System.getProperty(PROPERTY_PLC4X_FORCE_AWAIT_DISCONNECT_COMPLETE) != null) {
+        if (System.getProperty(PROPERTY_PLC4X_FORCE_AWAIT_DISCONNECT_COMPLETE) != null) {
             awaitDisconnectComplete = Boolean.parseBoolean(System.getProperty(PROPERTY_PLC4X_FORCE_AWAIT_DISCONNECT_COMPLETE));
         }
 
@@ -213,7 +213,7 @@ public class OpcuaPlcDriver extends GeneratedDriverBase<OpcuaAPU> {
             try {
                 configuration.openKeyStore();
             } catch (Exception e) {
-                throw new PlcConnectionException("Unable to open keystore, please confirm you have the correct permissions");
+                throw new PlcConnectionException("Unable to open keystore, please confirm you have the correct permissions", e);
             }
         }
 
@@ -221,7 +221,7 @@ public class OpcuaPlcDriver extends GeneratedDriverBase<OpcuaAPU> {
 
         // Make the "await disconnect complete" overridable via system property.
         boolean awaitDiscoverComplete = awaitDiscoverComplete();
-        if(System.getProperty(PROPERTY_PLC4X_FORCE_AWAIT_DISCOVER_COMPLETE) != null) {
+        if (System.getProperty(PROPERTY_PLC4X_FORCE_AWAIT_DISCOVER_COMPLETE) != null) {
             awaitDiscoverComplete = Boolean.parseBoolean(System.getProperty(PROPERTY_PLC4X_FORCE_AWAIT_DISCOVER_COMPLETE));
         }
 
@@ -239,7 +239,9 @@ public class OpcuaPlcDriver extends GeneratedDriverBase<OpcuaAPU> {
             null);
     }
 
-    /** Estimate the Length of a Packet */
+    /**
+     * Estimate the Length of a Packet
+     */
     public static class ByteLengthEstimator implements ToIntFunction<ByteBuf> {
         @Override
         public int applyAsInt(ByteBuf byteBuf) {
@@ -251,7 +253,7 @@ public class OpcuaPlcDriver extends GeneratedDriverBase<OpcuaAPU> {
     }
 
     @Override
-    public OpcuaTag prepareTag(String tagAddress){
+    public OpcuaTag prepareTag(String tagAddress) {
         return OpcuaTag.of(tagAddress);
     }
 
diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/EncryptionHandler.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/EncryptionHandler.java
index 2cd34d74ed..cbcaab226f 100644
--- a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/EncryptionHandler.java
+++ b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/EncryptionHandler.java
@@ -33,9 +33,12 @@ import javax.crypto.Cipher;
 import javax.crypto.Mac;
 import javax.crypto.spec.SecretKeySpec;
 import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
 import java.security.*;
 import java.security.cert.CertificateFactory;
 import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.List;
 
 
 public class EncryptionHandler {
@@ -43,7 +46,7 @@ public class EncryptionHandler {
     private static final Logger LOGGER = LoggerFactory.getLogger(OpcuaProtocolLogic.class);
 
     static {
-        // Required for SecurityPolicy.Aes256_Sha256_RsaPss
+        // Required for SecurityPolicy.Aes128_Sha128_RsaPss
         Security.addProvider(new BouncyCastleProvider());
     }
 
@@ -83,7 +86,8 @@ public class EncryptionHandler {
         int encryptedLength = numberOfBlocks * 256 + positionFirstBlock;
         WriteBufferByteBased buf = new WriteBufferByteBased(encryptedLength, ByteOrder.LITTLE_ENDIAN);
         try {
-            new OpcuaAPU(pdu).serialize(buf);
+            OpcuaAPU opcuaAPU = new OpcuaAPU(pdu);
+            opcuaAPU.serialize(buf);
             byte paddingByte = (byte) paddingSize;
             buf.writeByte(paddingByte);
             for (int i = 0; i < paddingSize; i++) {
@@ -99,20 +103,20 @@ public class EncryptionHandler {
             for (byte b : signature) {
                 buf.writeByte(b);
             }
-            buf.setPos(positionFirstBlock);
+//            buf.setPos(positionFirstBlock);
             encryptBlock(buf, getBytes(buf.getBytes(), positionFirstBlock, positionFirstBlock + preEncryptedLength));
             return new ReadBufferByteBased(buf.getData(), ByteOrder.LITTLE_ENDIAN);
-        } catch (SerializationException e) {
+        } catch (Exception e) {
             throw new PlcRuntimeException("Unable to parse apu prior to encrypting");
         }
     }
 
-    public OpcuaAPU decodeMessage(OpcuaAPU pdu) {
+    public OpcuaAPU decodeMessage(OpcuaAPU pdu) {//TODo patrykg
         LOGGER.info("Decoding Message with Security policy {}", securitypolicy);
         switch (securitypolicy) {
             case "None":
                 return pdu;
-            case "Basic256Sha256":
+            case "Basic128Sha128":
                 byte[] message;
                 if (pdu.getMessage() instanceof OpcuaOpenResponse) {
                     message = ((OpcuaOpenResponse) pdu.getMessage()).getMessage();
@@ -165,7 +169,7 @@ public class EncryptionHandler {
 
     public boolean checkSignature(byte[] data) {
         try {
-            Signature signature = Signature.getInstance("SHA256withRSA", "BC");
+            Signature signature = Signature.getInstance("SHA1withRSA", "BC");
             signature.initVerify(serverCertificate.getPublicKey());
             signature.update(data);
             return signature.verify(data, 0, data.length - 256);
@@ -189,17 +193,24 @@ public class EncryptionHandler {
 
     public void encryptBlock(WriteBuffer buf, byte[] data) {
         try {
-            Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding");
+            Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
             cipher.init(Cipher.ENCRYPT_MODE, this.serverCertificate.getPublicKey());
+            List<Byte> b = new ArrayList<>();
             for (int i = 0; i < data.length; i += 190) {
                 LOGGER.info("Iterate:- {}, Data Length:- {}", i, data.length);
+
+
                 byte[] encrypted = cipher.doFinal(data, i, 190);
                 for (int j = 0; j < 256; j++) {
-                    buf.writeByte(encrypted[j]);
+                    b.add(encrypted[j]);
+//                    buf.writeByte(encrypted[j]);
                 }
             }
+
+            byte[] bytes = cipher.doFinal(data);
+            System.out.println(b);
         } catch (Exception e) {
-            LOGGER.error("Unable to encrypt Data");
+            LOGGER.error("Unable to encrypt Data",e);
             e.printStackTrace();
         }
     }
@@ -231,7 +242,7 @@ public class EncryptionHandler {
 
     public byte[] sign(byte[] data) {
         try {
-            Signature signature = Signature.getInstance("SHA256withRSA", "BC");
+            Signature signature = Signature.getInstance("SHA1withRSA", "BC");
             signature.initSign(this.clientPrivateKey);
             signature.update(data);
             byte[] ss = signature.sign();
diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/EncryptionHandler2.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/EncryptionHandler2.java
new file mode 100644
index 0000000000..26b41593bd
--- /dev/null
+++ b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/EncryptionHandler2.java
@@ -0,0 +1,16 @@
+package org.apache.plc4x.java.opcua.context;
+
+import org.apache.plc4x.java.opcua.readwrite.MessagePDU;
+import org.apache.plc4x.java.spi.generation.ReadBuffer;
+
+public class EncryptionHandler2 {
+
+    public ReadBuffer encodeMessage(MessagePDU pdu, byte[] message) {
+        int securityHeaderSize = pdu.getLengthInBytes();
+
+
+
+        return null;
+    }
+
+}
diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/SecureChannel.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/SecureChannel.java
index af2bd152f9..b599eaee8d 100644
--- a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/SecureChannel.java
+++ b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/SecureChannel.java
@@ -18,6 +18,7 @@
  */
 package org.apache.plc4x.java.opcua.context;
 
+import io.vavr.control.Try;
 import org.apache.commons.lang3.RandomStringUtils;
 import org.apache.commons.lang3.RandomUtils;
 import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
@@ -139,7 +140,7 @@ public class SecureChannel {
         this.securityPolicy = "http://opcfoundation.org/UA/SecurityPolicy#" + configuration.getSecurityPolicy();
         CertificateKeyPair ckp = configuration.getCertificateKeyPair();
 
-        if (configuration.getSecurityPolicy() != null && configuration.getSecurityPolicy().equals("Basic256Sha256")) {
+        if (configuration.getSecurityPolicy() != null && SecurityPolicy.byName(configuration.getSecurityPolicy()).isPresent()) {
             //Sender Certificate gets populated during the 'discover' phase when encryption is enabled.
             this.senderCertificate = configuration.getSenderCertificate();
             this.encryptionHandler = new EncryptionHandler(ckp, this.senderCertificate, configuration.getSecurityPolicy());
@@ -312,12 +313,12 @@ public class SecureChannel {
                 this.thumbprint,
                 transactionId,
                 transactionId,
-                buffer.getData());
+                buffer.getBytes());
 
             final OpcuaAPU apu;
 
             if (this.isEncrypted) {
-                apu = OpcuaAPU.staticParse(encryptionHandler.encodeMessage(openRequest, buffer.getData()), false);
+                apu = OpcuaAPU.staticParse(encryptionHandler.encodeMessage(openRequest, buffer.getBytes()), false);
             } else {
                 apu = new OpcuaAPU(openRequest);
             }
@@ -876,15 +877,21 @@ public class SecureChannel {
 
                             try {
                                 MessageDigest messageDigest = MessageDigest.getInstance("SHA-1");
+                                Try<Boolean> of = Try.of(() -> {
+                                    configuration.openKeyStore();
+                                    return true;
+                                });
                                 byte[] digest = messageDigest.digest(this.configuration.getSenderCertificate());
                                 this.configuration.setThumbprint(new PascalByteString(digest.length, digest));
-                            } catch (NoSuchAlgorithmException e) {
+                            } catch (Exception e) {
                                 LOGGER.error("Failed to find hashing algorithm");
+                                throw new RuntimeException(e);
                             }
                             onDiscoverCloseSecureChannel(context, response);
                         }
-                    } catch (ParseException e) {
+                    } catch (Exception e) {
                         LOGGER.error("Error parsing", e);
+                        throw new RuntimeException(e);
                     }
                 });
 
@@ -1092,8 +1099,6 @@ public class SecureChannel {
      * @throws PlcRuntimeException - If no endpoint with a compatible policy is found raise and error.
      */
     private void selectEndpoint(CreateSessionResponse sessionResponse) throws PlcRuntimeException {
-        List<String> returnedEndpoints = new ArrayList<>();
-
         // Get a list of the endpoints which match ours.
         Stream<EndpointDescription> filteredEndpoints = sessionResponse.getServerEndpoints().stream()
             .map(e -> (EndpointDescription) e)
diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/SecurityPolicy.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/SecurityPolicy.java
new file mode 100644
index 0000000000..532197a586
--- /dev/null
+++ b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/SecurityPolicy.java
@@ -0,0 +1,16 @@
+package org.apache.plc4x.java.opcua.context;
+
+import java.util.Optional;
+import java.util.stream.Stream;
+
+public enum SecurityPolicy {
+    Basic128Rsa15,
+    Basic256Sha256;
+
+
+    public static Optional<SecurityPolicy> byName(String value) {
+        return Stream.of(values())
+            .filter(policy -> policy.name().equals(value))
+            .findAny();
+    }
+}
diff --git a/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/OpcuaPlcDriverTest.java b/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/OpcuaPlcDriverTest.java
index c2f9cfcf78..dd93264988 100644
--- a/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/OpcuaPlcDriverTest.java
+++ b/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/OpcuaPlcDriverTest.java
@@ -18,6 +18,7 @@
  */
 package org.apache.plc4x.java.opcua;
 
+import io.vavr.Tuple2;
 import io.vavr.collection.List;
 import org.apache.plc4x.java.DefaultPlcDriverManager;
 import org.apache.plc4x.java.api.PlcConnection;
@@ -37,11 +38,14 @@ import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.fail;
 import static org.junit.jupiter.api.Assumptions.assumeTrue;
 
+import java.io.File;
 import java.math.BigInteger;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.concurrent.ExecutionException;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 public class OpcuaPlcDriverTest {
 
@@ -189,78 +193,96 @@ public class OpcuaPlcDriverTest {
     @Test
     public void readVariables() {
         try {
-            PlcConnection opcuaConnection = new DefaultPlcDriverManager().getConnection(tcpConnectionAddress);
+            Path securityTempDir = Paths.get(System.getProperty("java.io.tmpdir"), "server" );
+            File pkiDir = securityTempDir.resolve("pki").toFile();
+
+            String s1 = securityTempDir.resolve("security").resolve("example-server.pfx").toAbsolutePath().toString();
+
+            String s = securityTempDir.toAbsolutePath().toString();
+            String connectionParams = Stream.of(
+                new Tuple2<>("keyStoreFile", s1),
+                new Tuple2<>("certDirectory", s),
+                new Tuple2<>("keyStorePassword", "password"),
+                new Tuple2<>("securityPolicy", "Basic128Rsa15")
+                )
+                .map(tuple-> tuple._1() + "=" + tuple._2())
+                .collect(Collectors.joining(paramDivider));
+///var/folders/8_/d821tw6d03g856b1k51tvsdw0000gn/T/server/security/example-server.pfx
+///var/folders/8_/d821tw6d03g856b1k51tvsdw0000gn/T/server/security/security
+
+            String url = tcpConnectionAddress + paramSectionDivider + connectionParams;
+            PlcConnection opcuaConnection = new DefaultPlcDriverManager().getConnection(url);
             Condition<PlcConnection> is_connected = new Condition<>(PlcConnection::isConnected, "is connected");
             assertThat(opcuaConnection).is(is_connected);
 
             PlcReadRequest.Builder builder = opcuaConnection.readRequestBuilder();
             builder.addTagAddress("Bool", BOOL_IDENTIFIER_READ_WRITE);
-            builder.addTagAddress("Byte", BYTE_IDENTIFIER_READ_WRITE);
-            builder.addTagAddress("Double", DOUBLE_IDENTIFIER_READ_WRITE);
-            builder.addTagAddress("Float", FLOAT_IDENTIFIER_READ_WRITE);
-            builder.addTagAddress("Int16", INT16_IDENTIFIER_READ_WRITE);
-            builder.addTagAddress("Int32", INT32_IDENTIFIER_READ_WRITE);
-            builder.addTagAddress("Int64", INT64_IDENTIFIER_READ_WRITE);
-            builder.addTagAddress("Integer", INTEGER_IDENTIFIER_READ_WRITE);
-            builder.addTagAddress("SByte", SBYTE_IDENTIFIER_READ_WRITE);
-            builder.addTagAddress("String", STRING_IDENTIFIER_READ_WRITE);
-            builder.addTagAddress("UInt16", UINT16_IDENTIFIER_READ_WRITE);
-            builder.addTagAddress("UInt32", UINT32_IDENTIFIER_READ_WRITE);
-            builder.addTagAddress("UInt64", UINT64_IDENTIFIER_READ_WRITE);
-            builder.addTagAddress("UInteger", UINTEGER_IDENTIFIER_READ_WRITE);
-
-            builder.addTagAddress("BoolArray", BOOL_ARRAY_IDENTIFIER);
-            //builder.addTagAddress("ByteStringArray", BYTE_STRING_ARRAY_IDENTIFIER);
-            builder.addTagAddress("ByteArray", BYTE_ARRAY_IDENTIFIER);
-            builder.addTagAddress("DoubleArray", DOUBLE_ARRAY_IDENTIFIER);
-            builder.addTagAddress("FloatArray", FLOAT_ARRAY_IDENTIFIER);
-            builder.addTagAddress("Int16Array", INT16_ARRAY_IDENTIFIER);
-            builder.addTagAddress("Int32Array", INT32_ARRAY_IDENTIFIER);
-            builder.addTagAddress("Int64Array", INT64_ARRAY_IDENTIFIER);
-            builder.addTagAddress("SByteArray", SBYTE_ARRAY_IDENTIFIER);
-            builder.addTagAddress("StringArray", STRING_ARRAY_IDENTIFIER);
-            builder.addTagAddress("UInt16Array", UINT16_ARRAY_IDENTIFIER);
-            builder.addTagAddress("UInt32Array", UINT32_ARRAY_IDENTIFIER);
-            builder.addTagAddress("UInt64Array", UINT64_ARRAY_IDENTIFIER);
-
-            builder.addTagAddress("DoesNotExists", DOES_NOT_EXIST_IDENTIFIER_READ_WRITE);
-
-            PlcReadRequest request = builder.build();
-            PlcReadResponse response = request.execute().get();
-            assertThat(response.getResponseCode("Bool")).isEqualTo(PlcResponseCode.OK);
-            assertThat(response.getResponseCode("Byte")).isEqualTo(PlcResponseCode.OK);
-            assertThat(response.getResponseCode("Double")).isEqualTo(PlcResponseCode.OK);
-            assertThat(response.getResponseCode("Float")).isEqualTo(PlcResponseCode.OK);
-            assertThat(response.getResponseCode("Int16")).isEqualTo(PlcResponseCode.OK);
-            assertThat(response.getResponseCode("Int32")).isEqualTo(PlcResponseCode.OK);
-            assertThat(response.getResponseCode("Int64")).isEqualTo(PlcResponseCode.OK);
-            assertThat(response.getResponseCode("Integer")).isEqualTo(PlcResponseCode.OK);
-            assertThat(response.getResponseCode("SByte")).isEqualTo(PlcResponseCode.OK);
-            assertThat(response.getResponseCode("String")).isEqualTo(PlcResponseCode.OK);
-            assertThat(response.getResponseCode("UInt16")).isEqualTo(PlcResponseCode.OK);
-            assertThat(response.getResponseCode("UInt32")).isEqualTo(PlcResponseCode.OK);
-            assertThat(response.getResponseCode("UInt64")).isEqualTo(PlcResponseCode.OK);
-            assertThat(response.getResponseCode("UInteger")).isEqualTo(PlcResponseCode.OK);
-
-            assertThat(response.getResponseCode("BoolArray")).isEqualTo(PlcResponseCode.OK);
-            assertThat(response.getResponseCode("ByteArray")).isEqualTo(PlcResponseCode.OK);
-            assertThat(response.getResponseCode("DoubleArray")).isEqualTo(PlcResponseCode.OK);
-            assertThat(response.getResponseCode("FloatArray")).isEqualTo(PlcResponseCode.OK);
-            assertThat(response.getResponseCode("Int16Array")).isEqualTo(PlcResponseCode.OK);
-            assertThat(response.getResponseCode("Int32Array")).isEqualTo(PlcResponseCode.OK);
-            assertThat(response.getResponseCode("Int64Array")).isEqualTo(PlcResponseCode.OK);
-            assertThat(response.getResponseCode("SByteArray")).isEqualTo(PlcResponseCode.OK);
-            assertThat(response.getResponseCode("StringArray")).isEqualTo(PlcResponseCode.OK);
-            assertThat(response.getResponseCode("UInt16Array")).isEqualTo(PlcResponseCode.OK);
-            assertThat(response.getResponseCode("UInt32Array")).isEqualTo(PlcResponseCode.OK);
-            assertThat(response.getResponseCode("UInt64Array")).isEqualTo(PlcResponseCode.OK);
-
-            assertThat(response.getResponseCode("DoesNotExists")).isEqualTo(PlcResponseCode.NOT_FOUND);
+//            builder.addTagAddress("Byte", BYTE_IDENTIFIER_READ_WRITE);
+//            builder.addTagAddress("Double", DOUBLE_IDENTIFIER_READ_WRITE);
+//            builder.addTagAddress("Float", FLOAT_IDENTIFIER_READ_WRITE);
+//            builder.addTagAddress("Int16", INT16_IDENTIFIER_READ_WRITE);
+//            builder.addTagAddress("Int32", INT32_IDENTIFIER_READ_WRITE);
+//            builder.addTagAddress("Int64", INT64_IDENTIFIER_READ_WRITE);
+//            builder.addTagAddress("Integer", INTEGER_IDENTIFIER_READ_WRITE);
+//            builder.addTagAddress("SByte", SBYTE_IDENTIFIER_READ_WRITE);
+//            builder.addTagAddress("String", STRING_IDENTIFIER_READ_WRITE);
+//            builder.addTagAddress("UInt16", UINT16_IDENTIFIER_READ_WRITE);
+//            builder.addTagAddress("UInt32", UINT32_IDENTIFIER_READ_WRITE);
+//            builder.addTagAddress("UInt64", UINT64_IDENTIFIER_READ_WRITE);
+//            builder.addTagAddress("UInteger", UINTEGER_IDENTIFIER_READ_WRITE);
+//
+//            builder.addTagAddress("BoolArray", BOOL_ARRAY_IDENTIFIER);
+//            //builder.addTagAddress("ByteStringArray", BYTE_STRING_ARRAY_IDENTIFIER);
+//            builder.addTagAddress("ByteArray", BYTE_ARRAY_IDENTIFIER);
+//            builder.addTagAddress("DoubleArray", DOUBLE_ARRAY_IDENTIFIER);
+//            builder.addTagAddress("FloatArray", FLOAT_ARRAY_IDENTIFIER);
+//            builder.addTagAddress("Int16Array", INT16_ARRAY_IDENTIFIER);
+//            builder.addTagAddress("Int32Array", INT32_ARRAY_IDENTIFIER);
+//            builder.addTagAddress("Int64Array", INT64_ARRAY_IDENTIFIER);
+//            builder.addTagAddress("SByteArray", SBYTE_ARRAY_IDENTIFIER);
+//            builder.addTagAddress("StringArray", STRING_ARRAY_IDENTIFIER);
+//            builder.addTagAddress("UInt16Array", UINT16_ARRAY_IDENTIFIER);
+//            builder.addTagAddress("UInt32Array", UINT32_ARRAY_IDENTIFIER);
+//            builder.addTagAddress("UInt64Array", UINT64_ARRAY_IDENTIFIER);
+//
+//            builder.addTagAddress("DoesNotExists", DOES_NOT_EXIST_IDENTIFIER_READ_WRITE);
+//
+//            PlcReadRequest request = builder.build();
+//            PlcReadResponse response = request.execute().get();
+//            assertThat(response.getResponseCode("Bool")).isEqualTo(PlcResponseCode.OK);
+//            assertThat(response.getResponseCode("Byte")).isEqualTo(PlcResponseCode.OK);
+//            assertThat(response.getResponseCode("Double")).isEqualTo(PlcResponseCode.OK);
+//            assertThat(response.getResponseCode("Float")).isEqualTo(PlcResponseCode.OK);
+//            assertThat(response.getResponseCode("Int16")).isEqualTo(PlcResponseCode.OK);
+//            assertThat(response.getResponseCode("Int32")).isEqualTo(PlcResponseCode.OK);
+//            assertThat(response.getResponseCode("Int64")).isEqualTo(PlcResponseCode.OK);
+//            assertThat(response.getResponseCode("Integer")).isEqualTo(PlcResponseCode.OK);
+//            assertThat(response.getResponseCode("SByte")).isEqualTo(PlcResponseCode.OK);
+//            assertThat(response.getResponseCode("String")).isEqualTo(PlcResponseCode.OK);
+//            assertThat(response.getResponseCode("UInt16")).isEqualTo(PlcResponseCode.OK);
+//            assertThat(response.getResponseCode("UInt32")).isEqualTo(PlcResponseCode.OK);
+//            assertThat(response.getResponseCode("UInt64")).isEqualTo(PlcResponseCode.OK);
+//            assertThat(response.getResponseCode("UInteger")).isEqualTo(PlcResponseCode.OK);
+//
+//            assertThat(response.getResponseCode("BoolArray")).isEqualTo(PlcResponseCode.OK);
+//            assertThat(response.getResponseCode("ByteArray")).isEqualTo(PlcResponseCode.OK);
+//            assertThat(response.getResponseCode("DoubleArray")).isEqualTo(PlcResponseCode.OK);
+//            assertThat(response.getResponseCode("FloatArray")).isEqualTo(PlcResponseCode.OK);
+//            assertThat(response.getResponseCode("Int16Array")).isEqualTo(PlcResponseCode.OK);
+//            assertThat(response.getResponseCode("Int32Array")).isEqualTo(PlcResponseCode.OK);
+//            assertThat(response.getResponseCode("Int64Array")).isEqualTo(PlcResponseCode.OK);
+//            assertThat(response.getResponseCode("SByteArray")).isEqualTo(PlcResponseCode.OK);
+//            assertThat(response.getResponseCode("StringArray")).isEqualTo(PlcResponseCode.OK);
+//            assertThat(response.getResponseCode("UInt16Array")).isEqualTo(PlcResponseCode.OK);
+//            assertThat(response.getResponseCode("UInt32Array")).isEqualTo(PlcResponseCode.OK);
+//            assertThat(response.getResponseCode("UInt64Array")).isEqualTo(PlcResponseCode.OK);
+//
+//            assertThat(response.getResponseCode("DoesNotExists")).isEqualTo(PlcResponseCode.NOT_FOUND);
 
             opcuaConnection.close();
             assert !opcuaConnection.isConnected();
         } catch (Exception e) {
-            fail("Exception during readVariables Test EXCEPTION: " + e.getMessage());
+            fail("Exception during readVariables Test EXCEPTION: " , e);
         }
     }
 
diff --git a/plc4j/drivers/opcua/src/test/resources/log4j.properties b/plc4j/drivers/opcua/src/test/resources/log4j.properties
index 803afdb15a..d8011c1750 100644
--- a/plc4j/drivers/opcua/src/test/resources/log4j.properties
+++ b/plc4j/drivers/opcua/src/test/resources/log4j.properties
@@ -20,5 +20,5 @@ appender.out.type=Console
 appender.out.name=out
 appender.out.layout.type=PatternLayout
 appender.out.layout.pattern=[%30.30t] %-30.30c{0} %-5p %m%n
-rootLogger.level=ERROR
+rootLogger.level=info
 rootLogger.appenderRef.out.ref=out
diff --git a/plc4j/drivers/opcua/src/test/resources/logback-test.xml b/plc4j/drivers/opcua/src/test/resources/logback-test.xml
index 1d9de10bd8..4833ef946e 100644
--- a/plc4j/drivers/opcua/src/test/resources/logback-test.xml
+++ b/plc4j/drivers/opcua/src/test/resources/logback-test.xml
@@ -27,7 +27,7 @@
     </encoder>
   </appender>
 
-  <root level="error">
+  <root level="debug">
     <appender-ref ref="STDOUT" />
   </root>
 </configuration>
\ No newline at end of file
diff --git a/plc4j/pom.xml b/plc4j/pom.xml
index f348ec0137..26b58b3987 100644
--- a/plc4j/pom.xml
+++ b/plc4j/pom.xml
@@ -221,7 +221,7 @@
             We have to slightly increase the heap-size or some tests will fail.
             Notice the @ instead of the $ as prefix? That's late evaluation.
           -->
-          <argLine>-Xmx256m @{failsafeArgLine}</argLine>
+          <argLine>-Xmx256m</argLine>
           <includes>
             <include>**/*IT.java</include>
           </includes>
diff --git a/pom.xml b/pom.xml
index 3924bbad94..b7d503795a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -146,7 +146,7 @@
     <maven.clean.plugin.version>3.2.0</maven.clean.plugin.version>
     <!-- version 0.6.7 is newer, however the ExampleServer doesn't seem to run with that -->
     <!-- version 0.6.8 is being released, however the milo-examples artifact is not available yet -->
-    <milo.version>0.6.9</milo.version>
+    <milo.version>0.6.10-SNAPSHOT</milo.version>
     <mockito.version>5.3.1</mockito.version>
     <netty.version>4.1.92.Final</netty.version>
     <pcap4j.version>1.8.2</pcap4j.version>


(plc4x) 08/12: Create client signature in ActivateSessionRequest

Posted by ld...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ldywicki pushed a commit to branch pg/security-policy
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit 2472008d2aad789e10d950d01f541a56a531774d
Author: PatrykGala <pa...@gmail.com>
AuthorDate: Wed Jul 26 13:24:16 2023 +0200

    Create client signature in ActivateSessionRequest
---
 .../plc4x/java/opcua/context/EncryptionHandler.java   | 19 ++++++++++++++-----
 .../plc4x/java/opcua/context/SecureChannel.java       |  4 ++--
 2 files changed, 16 insertions(+), 7 deletions(-)

diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/EncryptionHandler.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/EncryptionHandler.java
index e8718c43d0..ad3b7b64a2 100644
--- a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/EncryptionHandler.java
+++ b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/EncryptionHandler.java
@@ -18,11 +18,10 @@
  */
 package org.apache.plc4x.java.opcua.context;
 
+import com.google.common.primitives.Bytes;
+import io.vavr.control.Try;
 import org.apache.plc4x.java.opcua.protocol.OpcuaProtocolLogic;
-import org.apache.plc4x.java.opcua.readwrite.MessagePDU;
-import org.apache.plc4x.java.opcua.readwrite.OpcuaAPU;
-import org.apache.plc4x.java.opcua.readwrite.OpcuaMessageResponse;
-import org.apache.plc4x.java.opcua.readwrite.OpcuaOpenResponse;
+import org.apache.plc4x.java.opcua.readwrite.*;
 import org.apache.plc4x.java.spi.generation.*;
 import org.bouncycastle.jce.provider.BouncyCastleProvider;
 import org.slf4j.Logger;
@@ -55,7 +54,7 @@ public class EncryptionHandler {
 
     private byte[] clientNonce = null;
     private byte[] serverNonce = null;
-    private SymmetricEncryptionHandler symmetricEncryptionHandler= new SymmetricEncryptionHandler();
+    private SymmetricEncryptionHandler symmetricEncryptionHandler = new SymmetricEncryptionHandler();
 
 
     public EncryptionHandler(CertificateKeyPair ckp, byte[] senderCertificate, String securityPolicy) {
@@ -89,6 +88,16 @@ public class EncryptionHandler {
 
     }
 
+
+    public SignatureData createClientSignature(byte[] lastServerNonce) {
+        AsymmetricEncryptionHandler handler = new AsymmetricEncryptionHandler(serverCertificate, clientCertificate, clientPrivateKey, clientPublicKey);
+
+        byte[] cert = Try.of(() -> serverCertificate.getEncoded()).getOrElse(new byte[0]);
+        byte[] bytes = Bytes.concat(cert, lastServerNonce);
+        byte[] signed = handler.sign(bytes);
+        return new SignatureData(new PascalString("http://www.w3.org/2000/09/xmldsig#rsa-sha1"), new PascalByteString(signed.length, signed));
+    }
+
     public OpcuaAPU decodeMessage(OpcuaAPU pdu) {//TODo patrykg
         LOGGER.info("Decoding Message with Security policy {}", securitypolicy);
 
diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/SecureChannel.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/SecureChannel.java
index 7c529c3ce7..0ca1e21e30 100644
--- a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/SecureChannel.java
+++ b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/SecureChannel.java
@@ -504,11 +504,11 @@ public class SecureChannel {
             REQUEST_TIMEOUT_LONG,
             NULL_EXTENSION_OBJECT);
 
-        SignatureData clientSignature = new SignatureData(NULL_STRING, NULL_BYTE_STRING);//todo patrykg add signature - temporary disabled in Milo, sign request
+        SignatureData clientSignature = new SignatureData(NULL_STRING, NULL_BYTE_STRING);
 
         ActivateSessionRequest activateSessionRequest = new ActivateSessionRequest(
             requestHeader,
-            clientSignature,
+            encryptionHandler.createClientSignature(this.senderNonce),
             0,
             null,
             0,


(plc4x) 07/12: Draft - remove todo

Posted by ld...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ldywicki pushed a commit to branch pg/security-policy
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit f312f3ad60267bb79ee89ca2b745bae78ceaeed5
Author: PatrykGala <pa...@gmail.com>
AuthorDate: Wed Jul 19 23:29:11 2023 +0200

    Draft - remove todo
---
 .../main/java/org/apache/plc4x/java/opcua/context/SecureChannel.java    | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/SecureChannel.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/SecureChannel.java
index e40f48befb..7c529c3ce7 100644
--- a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/SecureChannel.java
+++ b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/SecureChannel.java
@@ -91,7 +91,7 @@ public class SecureChannel {
     );
 
     private static final long EPOCH_OFFSET = 116444736000000000L;         //Offset between OPC UA epoch time and linux epoch time.
-    private static final PascalString APPLICATION_URI = new PascalString("urn:apache:plc4x:client"); //todo patrykg change for value from certificate
+    private static final PascalString APPLICATION_URI = new PascalString("urn:apache:plc4x:client");
     private static final PascalString PRODUCT_URI = new PascalString("urn:apache:plc4x:client");
     private static final PascalString APPLICATION_TEXT = new PascalString("OPCUA client for the Apache PLC4X:PLC4J project");
     private static final long DEFAULT_CONNECTION_LIFETIME = 36000000;


(plc4x) 04/12: Draft - read variable from milo

Posted by ld...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ldywicki pushed a commit to branch pg/security-policy
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit e1cb6b40c7a6f3328981df3988aefad8cc1975ff
Author: PatrykGala <pa...@gmail.com>
AuthorDate: Wed Jul 19 11:33:02 2023 +0200

    Draft - read variable from milo
---
 ...ndler.java => AsymmetricEncryptionHandler.java} |  63 +++++-
 .../java/opcua/context/EncryptionHandler.java      |  36 +++-
 .../plc4x/java/opcua/context/SecureChannel.java    |  13 +-
 .../opcua/context/SymmetricEncryptionHandler.java  | 217 +++++++++++++++++++++
 .../plc4x/java/opcua/context/SymmetricKeys.java    | 121 ++++++++++++
 .../plc4x/java/opcua/OpcuaPlcDriverTest.java       |   6 +-
 6 files changed, 441 insertions(+), 15 deletions(-)

diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/AsyncEncryptionHandler.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/AsymmetricEncryptionHandler.java
similarity index 70%
rename from plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/AsyncEncryptionHandler.java
rename to plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/AsymmetricEncryptionHandler.java
index 0fbbc932bf..e49802e28b 100644
--- a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/AsyncEncryptionHandler.java
+++ b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/AsymmetricEncryptionHandler.java
@@ -2,6 +2,7 @@ package org.apache.plc4x.java.opcua.context;
 
 import org.apache.plc4x.java.opcua.readwrite.MessagePDU;
 import org.apache.plc4x.java.opcua.readwrite.OpcuaAPU;
+import org.apache.plc4x.java.opcua.readwrite.OpcuaOpenResponse;
 import org.apache.plc4x.java.spi.generation.*;
 import org.eclipse.milo.opcua.stack.core.security.SecurityPolicy;
 
@@ -13,7 +14,7 @@ import java.security.cert.X509Certificate;
 import java.security.interfaces.RSAPublicKey;
 
 
-public class AsyncEncryptionHandler {
+public class AsymmetricEncryptionHandler {
     private static final int SECURE_MESSAGE_HEADER_SIZE = 12;
     private static final int SEQUENCE_HEADER_SIZE = 8;
 
@@ -23,13 +24,11 @@ public class AsyncEncryptionHandler {
     private X509Certificate clientCertificate;
 
     private final PrivateKey clientPrivateKey;
-    private final PublicKey clientPublicKey;
 
-    public AsyncEncryptionHandler(X509Certificate serverCertificate, X509Certificate clientCertificate, PrivateKey clientPrivateKey, PublicKey clientPublicKey) {
+    public AsymmetricEncryptionHandler(X509Certificate serverCertificate, X509Certificate clientCertificate, PrivateKey clientPrivateKey, PublicKey clientPublicKey) {
         this.serverCertificate = serverCertificate;
         this.clientCertificate = clientCertificate;
         this.clientPrivateKey = clientPrivateKey;
-        this.clientPublicKey = clientPublicKey;
     }
 
     /**
@@ -85,18 +84,70 @@ public class AsyncEncryptionHandler {
 
             buf.setPos(SECURE_MESSAGE_HEADER_SIZE + securityHeaderSize);
 
-            int blockCount = (frameSize - buf.getPos()) / plainTextBlockSize;
+            int blockCount = (frameSize - buf.getPos()) / plainTextBlockSize;// -> plainTextContentSize / plainTextBlockSize
 
             byte[] encrypted = encrypt(plainTextBlockSize, securityHeaderSize, frameSize, buf, blockCount);
             buf.writeByteArray(encrypted);
 
-
             return new ReadBufferByteBased(buf.getBytes(), ByteOrder.LITTLE_ENDIAN);
         } catch (Exception e) {
             throw new RuntimeException(e);
         }
     }
 
+    public OpcuaAPU decodeMessage(OpcuaAPU pdu) {
+        MessagePDU message = pdu.getMessage();
+
+        OpcuaOpenResponse a = (OpcuaOpenResponse) message;
+
+
+        int cipherTextBlockSize = (getAsymmetricKeyLength(serverCertificate) + 7) / 8;
+        int signatureSize = (getAsymmetricKeyLength(clientCertificate) + 7) / 8;
+
+        byte[] textMessage = a.getMessage();
+
+
+        int blockCount = (SEQUENCE_HEADER_SIZE + textMessage.length) / cipherTextBlockSize;
+        int plainTextBufferSize = cipherTextBlockSize * blockCount;
+
+
+        try {
+            WriteBufferByteBased buf = new WriteBufferByteBased(pdu.getLengthInBytes(), ByteOrder.LITTLE_ENDIAN);
+            pdu.serialize(buf);
+
+            String transformation = policy.getAsymmetricEncryptionAlgorithm().getTransformation();
+            Cipher cipher = Cipher.getInstance(transformation);
+            cipher.init(Cipher.DECRYPT_MODE, clientPrivateKey);
+
+            ByteBuffer buffer = ByteBuffer.allocate(plainTextBufferSize);
+            byte[] bytes = buf.getBytes(pdu.getLengthInBytes() - plainTextBufferSize, pdu.getLengthInBytes());
+            ByteBuffer originalMessage = ByteBuffer.wrap(bytes);
+
+            for (int blockNumber = 0; blockNumber < blockCount; blockNumber++) {
+                originalMessage.limit(originalMessage.position() + cipherTextBlockSize);
+                cipher.doFinal(originalMessage, buffer);
+            }
+            buffer.flip();
+
+            buf.setPos(pdu.getLengthInBytes() - plainTextBufferSize);
+            buf.writeByteArray(buffer.array());
+
+
+            int frameSize = pdu.getLengthInBytes() - plainTextBufferSize + buffer.limit();
+
+            updateFrameSize(frameSize, buf);
+
+            byte[] decryptedMessage = buf.getBytes(0, frameSize);
+            ReadBuffer readBuffer = new ReadBufferByteBased(decryptedMessage, ByteOrder.LITTLE_ENDIAN);
+            OpcuaAPU opcuaAPU = OpcuaAPU.staticParse(readBuffer, true);
+            return opcuaAPU;
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+
+
+    }
+
     private byte[] encrypt(int plainTextBlockSize, int securityHeaderSize, int frameSize, WriteBufferByteBased buf, int blockCount) throws Exception {
         ByteBuffer buffer = ByteBuffer.allocate(frameSize - buf.getPos());
         ByteBuffer originalMessage = ByteBuffer.wrap(buf.getBytes(SECURE_MESSAGE_HEADER_SIZE + securityHeaderSize, frameSize));
diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/EncryptionHandler.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/EncryptionHandler.java
index 22bd72240e..e8718c43d0 100644
--- a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/EncryptionHandler.java
+++ b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/EncryptionHandler.java
@@ -53,6 +53,11 @@ public class EncryptionHandler {
     private PublicKey clientPublicKey;
     private final String securitypolicy;
 
+    private byte[] clientNonce = null;
+    private byte[] serverNonce = null;
+    private SymmetricEncryptionHandler symmetricEncryptionHandler= new SymmetricEncryptionHandler();
+
+
     public EncryptionHandler(CertificateKeyPair ckp, byte[] senderCertificate, String securityPolicy) {
         if (ckp != null) {
             this.clientPrivateKey = ckp.getKeyPair().getPrivate();
@@ -71,15 +76,33 @@ public class EncryptionHandler {
 
     //https://reference.opcfoundation.org/Core/Part6/v104/docs/6.7
     public ReadBuffer encodeMessage(MessagePDU pdu, byte[] message) {
-        return new AsyncEncryptionHandler(serverCertificate, clientCertificate, clientPrivateKey, clientPublicKey)
-            .encodeMessage(pdu, message);
+        String messageType = pdu.getMessageType();
+        if ("OPN".equals(messageType)) {
+
+            return new AsymmetricEncryptionHandler(serverCertificate, clientCertificate, clientPrivateKey, clientPublicKey)
+                .encodeMessage(pdu, message);
+        } else {
+
+            return symmetricEncryptionHandler
+                .encodeMessage(pdu, message, clientNonce, serverNonce);
+        }
+
     }
 
     public OpcuaAPU decodeMessage(OpcuaAPU pdu) {//TODo patrykg
         LOGGER.info("Decoding Message with Security policy {}", securitypolicy);
+
         switch (securitypolicy) {
             case "None":
                 return pdu;
+            case "Basic128Rsa15":
+                if (pdu.getMessage().getMessageType().equals("OPN")) {
+                    return new AsymmetricEncryptionHandler(serverCertificate, clientCertificate, clientPrivateKey, clientPublicKey)
+                        .decodeMessage(pdu);
+                } else {
+                    return symmetricEncryptionHandler
+                        .decodeMessage(pdu, clientNonce, serverNonce);
+                }
             case "Basic128Sha128":
                 byte[] message;
                 if (pdu.getMessage() instanceof OpcuaOpenResponse) {
@@ -188,4 +211,13 @@ public class EncryptionHandler {
         System.arraycopy(bytes, startPos, data, 0, numBytes);
         return data;
     }
+
+    public void setClientNonce(byte[] clientNonce) {
+        this.clientNonce = clientNonce;
+    }
+
+
+    public void setServerNonce(byte[] serverNonce) {
+        this.serverNonce = serverNonce;
+    }
 }
diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/SecureChannel.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/SecureChannel.java
index b599eaee8d..798089ea25 100644
--- a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/SecureChannel.java
+++ b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/SecureChannel.java
@@ -38,7 +38,6 @@ import java.net.UnknownHostException;
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
 import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
 import java.security.cert.CertificateEncodingException;
 import java.time.Duration;
 import java.util.ArrayList;
@@ -92,7 +91,7 @@ public class SecureChannel {
     );
 
     private static final long EPOCH_OFFSET = 116444736000000000L;         //Offset between OPC UA epoch time and linux epoch time.
-    private static final PascalString APPLICATION_URI = new PascalString("urn:apache:plc4x:client");
+    private static final PascalString APPLICATION_URI = new PascalString("urn:apache:plc4x:client"); //todo patrykg change for value from certificate
     private static final PascalString PRODUCT_URI = new PascalString("urn:apache:plc4x:client");
     private static final PascalString APPLICATION_TEXT = new PascalString("OPCUA client for the Apache PLC4X:PLC4J project");
     private static final long DEFAULT_CONNECTION_LIFETIME = 36000000;
@@ -144,6 +143,7 @@ public class SecureChannel {
             //Sender Certificate gets populated during the 'discover' phase when encryption is enabled.
             this.senderCertificate = configuration.getSenderCertificate();
             this.encryptionHandler = new EncryptionHandler(ckp, this.senderCertificate, configuration.getSecurityPolicy());
+
             try {
                 this.publicCertificate = new PascalByteString(ckp.getCertificate().getEncoded().length, ckp.getCertificate().getEncoded());
                 this.isEncrypted = true;
@@ -157,6 +157,7 @@ public class SecureChannel {
             this.thumbprint = NULL_BYTE_STRING;
             this.isEncrypted = false;
         }
+        encryptionHandler.setClientNonce(clientNonce);
         this.keyStoreFile = configuration.getKeyStoreFile();
 
         // Generate a list of endpoints we can use.
@@ -187,6 +188,8 @@ public class SecureChannel {
         final OpcuaAPU apu;
         try {
             if (this.isEncrypted) {
+                encryptionHandler.setServerNonce(senderNonce);
+                encryptionHandler.setClientNonce(clientNonce);
                 apu = OpcuaAPU.staticParse(encryptionHandler.encodeMessage(messageRequest, buffer.getData()), false);
             } else {
                 apu = new OpcuaAPU(messageRequest);
@@ -345,6 +348,8 @@ public class SecureChannel {
                                 OpenSecureChannelResponse openSecureChannelResponse = (OpenSecureChannelResponse) message.getBody();
                                 tokenId.set((int) ((ChannelSecurityToken) openSecureChannelResponse.getSecurityToken()).getTokenId());
                                 channelId.set((int) ((ChannelSecurityToken) openSecureChannelResponse.getSecurityToken()).getChannelId());
+                                this.senderNonce = openSecureChannelResponse.getServerNonce().getStringValue();
+                                this.encryptionHandler.setServerNonce(openSecureChannelResponse.getServerNonce().getStringValue());
                                 onConnectCreateSessionRequest(context);
                             } catch (PlcConnectionException e) {
                                 LOGGER.error("Error occurred while connecting to OPC UA server", e);
@@ -396,7 +401,7 @@ public class SecureChannel {
             this.endpoint,
             new PascalString(sessionName),
             new PascalByteString(clientNonce.length, clientNonce),
-            NULL_BYTE_STRING,
+            publicCertificate,//TODO patrykg set only if securityMode != None
             120000L,
             0L);
 
@@ -499,7 +504,7 @@ public class SecureChannel {
             REQUEST_TIMEOUT_LONG,
             NULL_EXTENSION_OBJECT);
 
-        SignatureData clientSignature = new SignatureData(NULL_STRING, NULL_BYTE_STRING);
+        SignatureData clientSignature = new SignatureData(NULL_STRING, NULL_BYTE_STRING);//todo patrykg add signature - temporary disabled in Milo, sign request
 
         ActivateSessionRequest activateSessionRequest = new ActivateSessionRequest(
             requestHeader,
diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/SymmetricEncryptionHandler.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/SymmetricEncryptionHandler.java
new file mode 100644
index 0000000000..bbae72029d
--- /dev/null
+++ b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/SymmetricEncryptionHandler.java
@@ -0,0 +1,217 @@
+package org.apache.plc4x.java.opcua.context;
+
+import org.apache.plc4x.java.opcua.readwrite.MessagePDU;
+import org.apache.plc4x.java.opcua.readwrite.OpcuaAPU;
+import org.apache.plc4x.java.opcua.readwrite.OpcuaMessageResponse;
+import org.apache.plc4x.java.spi.generation.*;
+import org.eclipse.milo.opcua.stack.core.security.SecurityPolicy;
+
+import javax.crypto.Cipher;
+import javax.crypto.Mac;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+import java.nio.ByteBuffer;
+import java.security.*;
+import java.security.cert.Certificate;
+import java.security.interfaces.RSAPublicKey;
+
+
+public class SymmetricEncryptionHandler {
+    private static final int SECURE_MESSAGE_HEADER_SIZE = 12;
+    private static final int SEQUENCE_HEADER_SIZE = 8;
+    private static final int SYMMETRIC_SECURITY_HEADER_SIZE = 4;
+
+    private final SecurityPolicy policy = SecurityPolicy.Basic128Rsa15;
+
+
+    private SymmetricKeys keys = null;
+
+    public SymmetricEncryptionHandler() {
+
+
+    }
+
+    /**
+     * Docs: https://reference.opcfoundation.org/Core/Part6/v104/docs/6.7
+     *
+     * @param pdu
+     * @param message
+     * @param clientNonce
+     * @param serverNonce
+     * @return
+     */
+    public ReadBuffer encodeMessage(MessagePDU pdu, byte[] message, byte[] clientNonce, byte[] serverNonce) {
+        int unencryptedLength = pdu.getLengthInBytes();
+        int messageLength = message.length;
+
+        int beforeBodyLength = unencryptedLength - messageLength; // message header, security header, sequence header
+
+        int cipherTextBlockSize = 16; // different for aes
+        int plainTextBlockSize = 16;
+        int signatureSize = 20;
+
+
+        int maxChunkSize = 8196;
+        int paddingOverhead = 1; // if cipherTextBlockSize > 256 => 2
+
+
+        int securityHeaderSize = SYMMETRIC_SECURITY_HEADER_SIZE;
+        int maxCipherTextSize = maxChunkSize - securityHeaderSize;
+        int maxCipherTextBlocks = maxCipherTextSize / cipherTextBlockSize;
+        int maxPlainTextSize = maxCipherTextBlocks * plainTextBlockSize;
+        int maxBodySize = maxPlainTextSize - SEQUENCE_HEADER_SIZE - paddingOverhead - signatureSize;
+
+        int bodySize = Math.min(message.length, maxBodySize);
+
+        int plainTextSize = SEQUENCE_HEADER_SIZE + bodySize + paddingOverhead + signatureSize;
+        int remaining = plainTextSize % plainTextBlockSize;
+        int paddingSize = remaining > 0 ? plainTextBlockSize - remaining : 0;
+
+        int plainTextContentSize = SEQUENCE_HEADER_SIZE + bodySize +
+            signatureSize + paddingSize + paddingOverhead;
+
+        int frameSize = SECURE_MESSAGE_HEADER_SIZE + securityHeaderSize +
+            (plainTextContentSize / plainTextBlockSize) * cipherTextBlockSize;
+
+        SymmetricKeys symmetricKeys = getSymmetricKeys(clientNonce, serverNonce);
+
+        try {
+            WriteBufferByteBased buf = new WriteBufferByteBased(frameSize, ByteOrder.LITTLE_ENDIAN);
+            OpcuaAPU opcuaAPU = new OpcuaAPU(pdu);
+            opcuaAPU.serialize(buf);
+
+            writePadding(paddingSize, buf);
+            updateFrameSize(frameSize, buf);
+
+            byte[] sign = sign(buf.getBytes(), symmetricKeys.getClientKeys());
+            buf.writeByteArray(sign);
+
+            buf.setPos(SECURE_MESSAGE_HEADER_SIZE + securityHeaderSize);
+
+            byte[] encrypted = encrypt(securityHeaderSize, frameSize, buf, symmetricKeys);
+            buf.writeByteArray(encrypted);
+
+            return new ReadBufferByteBased(buf.getBytes(), ByteOrder.LITTLE_ENDIAN);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public OpcuaAPU decodeMessage(OpcuaAPU pdu, byte[] clientNonce, byte[] serverNonce) {
+        MessagePDU message = pdu.getMessage();
+
+        OpcuaMessageResponse a = (OpcuaMessageResponse) message;
+
+
+        int cipherTextBlockSize = 16; // different for aes256
+
+        byte[] textMessage = a.getMessage();
+
+
+        int blockCount = (SEQUENCE_HEADER_SIZE + textMessage.length) / cipherTextBlockSize;
+        int plainTextBufferSize = cipherTextBlockSize * blockCount;
+
+
+        try {
+            WriteBufferByteBased buf = new WriteBufferByteBased(pdu.getLengthInBytes(), ByteOrder.LITTLE_ENDIAN);
+            pdu.serialize(buf);
+
+            String transformation = policy.getSymmetricEncryptionAlgorithm().getTransformation();
+            SymmetricKeys symmetricKeys = getSymmetricKeys(clientNonce, serverNonce);
+            Cipher cipher = getCipher(symmetricKeys.getServerKeys(), transformation, Cipher.DECRYPT_MODE);
+
+            ByteBuffer buffer = ByteBuffer.allocate(plainTextBufferSize);
+            byte[] bytes = buf.getBytes(pdu.getLengthInBytes() - plainTextBufferSize, pdu.getLengthInBytes());
+            ByteBuffer originalMessage = ByteBuffer.wrap(bytes);
+
+
+            cipher.doFinal(originalMessage, buffer);
+
+            buffer.flip();
+
+            buf.setPos(pdu.getLengthInBytes() - plainTextBufferSize);
+            buf.writeByteArray(buffer.array());
+
+
+            int frameSize = pdu.getLengthInBytes() - plainTextBufferSize + buffer.limit();
+
+            updateFrameSize(frameSize, buf);
+
+            byte[] decryptedMessage = buf.getBytes(0, frameSize);
+            ReadBuffer readBuffer = new ReadBufferByteBased(decryptedMessage, ByteOrder.LITTLE_ENDIAN);
+            OpcuaAPU opcuaAPU = OpcuaAPU.staticParse(readBuffer, true);
+            return opcuaAPU;
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+
+
+    }
+
+    private byte[] encrypt(int securityHeaderSize, int frameSize, WriteBufferByteBased buf, SymmetricKeys symmetricKeys) throws Exception {
+        ByteBuffer buffer = ByteBuffer.allocate(frameSize - buf.getPos());
+        ByteBuffer originalMessage = ByteBuffer.wrap(buf.getBytes(SECURE_MESSAGE_HEADER_SIZE + securityHeaderSize, frameSize));
+
+
+        String transformation = policy.getSymmetricEncryptionAlgorithm().getTransformation();
+        Cipher cipher = getCipher(symmetricKeys.getClientKeys(), transformation, Cipher.ENCRYPT_MODE);
+
+
+        cipher.doFinal(originalMessage, buffer);
+
+        return buffer.array();
+    }
+
+    private static Cipher getCipher(SymmetricKeys.Keys symmetricKeys, String transformation, int mode) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException {
+        Cipher cipher = Cipher.getInstance(transformation);
+
+        SecretKeySpec keySpec = new SecretKeySpec(symmetricKeys.getEncryptionKey(), "AES");
+        IvParameterSpec ivSpec = new IvParameterSpec(symmetricKeys.getInitializationVector());
+
+        cipher.init(mode, keySpec, ivSpec);
+        return cipher;
+    }
+
+    private static void updateFrameSize(int frameSize, WriteBufferByteBased buf) throws SerializationException {
+        int initPosition = buf.getPos();
+        buf.setPos(4);
+        buf.writeInt(32, frameSize);
+        buf.setPos(initPosition);
+    }
+
+
+    public byte[] sign(byte[] data, SymmetricKeys.Keys symmetricKeys) {
+        try {
+            Mac signature = Mac.getInstance("HmacSHA1");
+            signature.init(new SecretKeySpec(symmetricKeys.getSignatureKey(), "HmacSHA1"));
+            signature.update(data);
+            return signature.doFinal();
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private void writePadding(int paddingSize, WriteBufferByteBased buffer) throws Exception {
+        buffer.writeByte((byte) paddingSize);
+        for (int i = 0; i < paddingSize; i++) {
+            buffer.writeByte((byte) paddingSize);
+        }
+    }
+
+
+    static int getAsymmetricKeyLength(Certificate certificate) {
+        PublicKey publicKey = certificate != null ?
+            certificate.getPublicKey() : null;
+
+        return (publicKey instanceof RSAPublicKey) ?
+            ((RSAPublicKey) publicKey).getModulus().bitLength() : 0;
+    }
+
+    private SymmetricKeys getSymmetricKeys(byte[] clientNonce, byte[] serverNonce) {
+        if (keys == null) {
+            keys = SymmetricKeys.generateKeyPair(clientNonce, serverNonce);
+        }
+        return keys;
+    }
+}
diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/SymmetricKeys.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/SymmetricKeys.java
new file mode 100644
index 0000000000..eb2b1e2dde
--- /dev/null
+++ b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/SymmetricKeys.java
@@ -0,0 +1,121 @@
+package org.apache.plc4x.java.opcua.context;
+
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+
+public class SymmetricKeys {
+
+
+    private static String KEY_ALGORITHM = "HmacSHA1";
+
+
+    private final Keys clientKeys;
+    private final Keys serverKeys;
+
+
+    public SymmetricKeys(Keys clientKeys, Keys serverKeys) {
+        this.clientKeys = clientKeys;
+        this.serverKeys = serverKeys;
+    }
+
+    public Keys getClientKeys() {
+        return clientKeys;
+    }
+
+    public Keys getServerKeys() {
+        return serverKeys;
+    }
+
+    public static SymmetricKeys generateKeyPair(byte[] clientNonce, byte[] serverNonce) {
+        int signatureKeySize = 16;// different for aes
+        int encryptionKeySize = 16;
+        int cipherTextBlockSize = 16;
+
+
+        byte[] clientSignatureKey = createKey(serverNonce, clientNonce, 0, signatureKeySize);
+        byte[] clientEncryptionKey = createKey(serverNonce, clientNonce, signatureKeySize, encryptionKeySize);
+        byte[] clientInitializationVector = createKey(serverNonce, clientNonce, signatureKeySize + encryptionKeySize, cipherTextBlockSize);
+
+
+        byte[] serverSignatureKey = createKey(clientNonce, serverNonce, 0, signatureKeySize);
+        byte[] serverEncryptionKey = createKey(clientNonce, serverNonce, signatureKeySize, encryptionKeySize);
+        byte[] serverInitializationVector = createKey(clientNonce, serverNonce, signatureKeySize + encryptionKeySize, cipherTextBlockSize);
+
+        return new SymmetricKeys(
+            new Keys(clientSignatureKey, clientEncryptionKey, clientInitializationVector),
+            new Keys(serverSignatureKey, serverEncryptionKey, serverInitializationVector)
+        );
+    }
+
+    private static byte[] createKey(byte[] secret, byte[] seed, int offset, int length) {
+        try {
+            Mac mac = Mac.getInstance(KEY_ALGORITHM);
+
+            byte[] tempBytes = hash(KEY_ALGORITHM, secret, seed, mac, offset + length);
+            byte[] key = new byte[length];
+
+            System.arraycopy(tempBytes, offset, key, 0, key.length);
+
+            return key;
+
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private static byte[] hash(String transformation,
+                               byte[] secret,
+                               byte[] seed,
+                               Mac mac,
+                               int required) throws Exception {
+
+        byte[] out = new byte[required];
+        int offset = 0;
+        int toCopy;
+        byte[] a = seed;
+        byte[] tmp;
+
+        while (required > 0) {
+            SecretKeySpec key = new SecretKeySpec(secret, transformation);
+            mac.init(key);
+            mac.update(a);
+            a = mac.doFinal();
+            mac.reset();
+            mac.init(key);
+            mac.update(a);
+            mac.update(seed);
+            tmp = mac.doFinal();
+            toCopy = Math.min(required, tmp.length);
+            System.arraycopy(tmp, 0, out, offset, toCopy);
+            offset += toCopy;
+            required -= toCopy;
+        }
+
+        return out;
+    }
+
+
+    public static class Keys {
+        private final byte[] signatureKey;
+        private final byte[] encryptionKey;
+        private final byte[] initializationVector;
+
+        public Keys(byte[] signatureKey, byte[] encryptionKey, byte[] initializationVector) {
+            this.signatureKey = signatureKey;
+            this.encryptionKey = encryptionKey;
+            this.initializationVector = initializationVector;
+        }
+
+        public byte[] getSignatureKey() {
+            return signatureKey;
+        }
+
+        public byte[] getEncryptionKey() {
+            return encryptionKey;
+        }
+
+        public byte[] getInitializationVector() {
+            return initializationVector;
+        }
+    }
+}
diff --git a/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/OpcuaPlcDriverTest.java b/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/OpcuaPlcDriverTest.java
index 3dba6eb7f2..ea22e1f368 100644
--- a/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/OpcuaPlcDriverTest.java
+++ b/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/OpcuaPlcDriverTest.java
@@ -252,9 +252,9 @@ public class OpcuaPlcDriverTest {
 //
 //            builder.addTagAddress("DoesNotExists", DOES_NOT_EXIST_IDENTIFIER_READ_WRITE);
 //
-//            PlcReadRequest request = builder.build();
-//            PlcReadResponse response = request.execute().get();
-//            assertThat(response.getResponseCode("Bool")).isEqualTo(PlcResponseCode.OK);
+            PlcReadRequest request = builder.build();
+            PlcReadResponse response = request.execute().get();
+            assertThat(response.getResponseCode("Bool")).isEqualTo(PlcResponseCode.OK);
 //            assertThat(response.getResponseCode("Byte")).isEqualTo(PlcResponseCode.OK);
 //            assertThat(response.getResponseCode("Double")).isEqualTo(PlcResponseCode.OK);
 //            assertThat(response.getResponseCode("Float")).isEqualTo(PlcResponseCode.OK);


(plc4x) 11/12: Add Basic256Sha256 support

Posted by ld...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ldywicki pushed a commit to branch pg/security-policy
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit e67759379796df99e8f57400407eceeabd551eff
Author: PatrykGala <pa...@gmail.com>
AuthorDate: Sat Sep 16 21:27:20 2023 +0200

    Add Basic256Sha256 support
---
 .../opcua/context/AsymmetricEncryptionHandler.java |  2 +-
 .../java/opcua/context/EncryptionHandler.java      |  4 +-
 .../plc4x/java/opcua/context/SecureChannel.java    |  4 --
 .../opcua/context/SymmetricEncryptionHandler.java  | 13 +++---
 .../plc4x/java/opcua/security/SecurityPolicy.java  | 54 +++++++++++++++++-----
 .../plc4x/java/opcua/security/SymmetricKeys.java   |  4 +-
 .../plc4x/java/opcua/OpcuaPlcDriverTest.java       |  3 +-
 7 files changed, 56 insertions(+), 28 deletions(-)

diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/AsymmetricEncryptionHandler.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/AsymmetricEncryptionHandler.java
index 1dc72f631f..5fea2ab9fe 100644
--- a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/AsymmetricEncryptionHandler.java
+++ b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/AsymmetricEncryptionHandler.java
@@ -47,7 +47,7 @@ public class AsymmetricEncryptionHandler {
         int beforeBodyLength = unencryptedLength - messageLength; // message header, security header, sequence header
 
         int cipherTextBlockSize = (getAsymmetricKeyLength(serverCertificate) + 7) / 8;
-        int plainTextBlockSize = (getAsymmetricKeyLength(serverCertificate) + 7) / 8 - 11;
+        int plainTextBlockSize = (getAsymmetricKeyLength(serverCertificate) + 7) / 8 - policy.getAsymmetricPlainBlock();
         int signatureSize = (getAsymmetricKeyLength(clientCertificate) + 7) / 8;
 
 
diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/EncryptionHandler.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/EncryptionHandler.java
index 394abdb864..1c25f410ca 100644
--- a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/EncryptionHandler.java
+++ b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/EncryptionHandler.java
@@ -82,6 +82,7 @@ public class EncryptionHandler {
         switch (securitypolicy) {
             case NONE:
                 return new ReadBufferByteBased(message, LITTLE_ENDIAN);
+            case Basic256Sha256:
             case Basic128Rsa15:
                 if (pdu instanceof OpcuaOpenRequest) {
                     return asymmetricEncryptionHandler.encodeMessage(pdu, message);
@@ -98,7 +99,7 @@ public class EncryptionHandler {
         byte[] cert = Try.of(() -> serverCertificate.getEncoded()).getOrElse(new byte[0]);
         byte[] bytes = Bytes.concat(cert, lastServerNonce);
         byte[] signed = asymmetricEncryptionHandler.sign(bytes);
-        return new SignatureData(new PascalString("http://www.w3.org/2000/09/xmldsig#rsa-sha1"), new PascalByteString(signed.length, signed));
+        return new SignatureData(new PascalString(securitypolicy.getAsymmetricSignatureAlgorithm().getUri()), new PascalByteString(signed.length, signed));
     }
 
     public OpcuaAPU decodeMessage(OpcuaAPU pdu) {
@@ -108,6 +109,7 @@ public class EncryptionHandler {
             case NONE:
                 return pdu;
             case Basic128Rsa15:
+            case Basic256Sha256:
                 if (pdu.getMessage() instanceof OpcuaOpenResponse) {
                     return asymmetricEncryptionHandler.decodeMessage(pdu);
                 } else {
diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/SecureChannel.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/SecureChannel.java
index 87e61032de..ea208b0b24 100644
--- a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/SecureChannel.java
+++ b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/SecureChannel.java
@@ -883,10 +883,6 @@ public class SecureChannel {
 
                             try {
                                 MessageDigest messageDigest = MessageDigest.getInstance("SHA-1");
-                                Try<Boolean> of = Try.of(() -> {
-                                    configuration.openKeyStore();
-                                    return true;
-                                });
                                 byte[] digest = messageDigest.digest(this.configuration.getSenderCertificate());
                                 this.configuration.setThumbprint(new PascalByteString(digest.length, digest));
                             } catch (Exception e) {
diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/SymmetricEncryptionHandler.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/SymmetricEncryptionHandler.java
index ae5bcc6017..d652eed511 100644
--- a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/SymmetricEncryptionHandler.java
+++ b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/SymmetricEncryptionHandler.java
@@ -5,6 +5,7 @@ import org.apache.plc4x.java.opcua.readwrite.OpcuaAPU;
 import org.apache.plc4x.java.opcua.readwrite.OpcuaMessageResponse;
 import org.apache.plc4x.java.opcua.security.SecurityPolicy;
 import org.apache.plc4x.java.opcua.security.SecurityPolicy.EncryptionAlgorithm;
+import org.apache.plc4x.java.opcua.security.SecurityPolicy.MacSignatureAlgorithm;
 import org.apache.plc4x.java.opcua.security.SymmetricKeys;
 import org.apache.plc4x.java.spi.generation.*;
 
@@ -17,9 +18,6 @@ import java.nio.ByteBuffer;
 import java.security.InvalidAlgorithmParameterException;
 import java.security.InvalidKeyException;
 import java.security.NoSuchAlgorithmException;
-import java.security.PublicKey;
-import java.security.cert.Certificate;
-import java.security.interfaces.RSAPublicKey;
 
 
 public class SymmetricEncryptionHandler {
@@ -51,9 +49,9 @@ public class SymmetricEncryptionHandler {
 
         int beforeBodyLength = unencryptedLength - messageLength; // message header, security header, sequence header
 
-        int cipherTextBlockSize = 16; // different for aes
+        int cipherTextBlockSize = 16;
         int plainTextBlockSize = 16;
-        int signatureSize = 20;
+        int signatureSize = policy.getSymmetricSignatureAlgorithm().getSymmetricSignatureSize();
 
 
         int maxChunkSize = 8196;
@@ -187,8 +185,9 @@ public class SymmetricEncryptionHandler {
 
     public byte[] sign(byte[] data, SymmetricKeys.Keys symmetricKeys) {
         try {
-            Mac signature = policy.getSymmetricSignatureAlgorithm().getSignature();
-            signature.init(new SecretKeySpec(symmetricKeys.getSignatureKey(), "HmacSHA1"));
+            MacSignatureAlgorithm algorithm = policy.getSymmetricSignatureAlgorithm();
+            Mac signature = algorithm.getSignature();
+            signature.init(new SecretKeySpec(symmetricKeys.getSignatureKey(), algorithm.getName()));
             signature.update(data);
             return signature.doFinal();
         } catch (Exception e) {
diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/security/SecurityPolicy.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/security/SecurityPolicy.java
index 9ddd06e588..37aca76ac9 100644
--- a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/security/SecurityPolicy.java
+++ b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/security/SecurityPolicy.java
@@ -9,16 +9,23 @@ import java.util.Arrays;
 
 public enum SecurityPolicy {
     NONE("http://opcfoundation.org/UA/SecurityPolicy#None",
-        new MacSignatureAlgorithm(""),
+        new MacSignatureAlgorithm("", 0, 32),
         new EncryptionAlgorithm(""),
-        new SignatureAlgorithm(""),
-        new EncryptionAlgorithm("")),
+        new SignatureAlgorithm("", "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"),
+        new EncryptionAlgorithm(""), 1),
+
     Basic128Rsa15("http://opcfoundation.org/UA/SecurityPolicy#Basic128Rsa15",
-        new MacSignatureAlgorithm("HmacSHA1"),
+        new MacSignatureAlgorithm("HmacSHA1", 20, 16),
+        new EncryptionAlgorithm("AES/CBC/NoPadding"),
+        new SignatureAlgorithm("SHA1withRSA", "http://www.w3.org/2000/09/xmldsig#rsa-sha1"),
+        new EncryptionAlgorithm("RSA/ECB/PKCS1Padding"),
+        11),
+    Basic256Sha256("http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256",
+        new MacSignatureAlgorithm("HmacSHA256", 32, 32),
         new EncryptionAlgorithm("AES/CBC/NoPadding"),
-        new SignatureAlgorithm("SHA1withRSA"),
-        new EncryptionAlgorithm("RSA/ECB/PKCS1Padding")
-    );
+        new SignatureAlgorithm("SHA256withRSA", "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"),
+        new EncryptionAlgorithm("RSA/ECB/OAEPWithSHA-1AndMGF1Padding"),
+        42);
 
 
     private final String securityPolicyUri;
@@ -28,18 +35,20 @@ public enum SecurityPolicy {
     private final EncryptionAlgorithm symmetricEncryptionAlgorithm;
     private final SignatureAlgorithm asymmetricSignatureAlgorithm;
     private final EncryptionAlgorithm asymmetricEncryptionAlgorithm;
-
+    private final int asymmetricPlainBlock;
 
     SecurityPolicy(String securityPolicyUri,
                    MacSignatureAlgorithm symmetricSignatureAlgorithm,
                    EncryptionAlgorithm symmetricEncryptionAlgorithm,
                    SignatureAlgorithm asymmetricSignatureAlgorithm,
-                   EncryptionAlgorithm asymmetricEncryptionAlgorithm) {
+                   EncryptionAlgorithm asymmetricEncryptionAlgorithm,
+                   int asymmetricPlainBlock) {
         this.securityPolicyUri = securityPolicyUri;
         this.symmetricSignatureAlgorithm = symmetricSignatureAlgorithm;
         this.symmetricEncryptionAlgorithm = symmetricEncryptionAlgorithm;
         this.asymmetricSignatureAlgorithm = asymmetricSignatureAlgorithm;
         this.asymmetricEncryptionAlgorithm = asymmetricEncryptionAlgorithm;
+        this.asymmetricPlainBlock = asymmetricPlainBlock;
     }
 
     public static SecurityPolicy findByName(String securityPolicy) {
@@ -69,13 +78,21 @@ public enum SecurityPolicy {
         return symmetricEncryptionAlgorithm;
     }
 
+    public int getAsymmetricPlainBlock() {
+        return asymmetricPlainBlock;
+    }
+
     public static class MacSignatureAlgorithm {
 
 
         private final String name;
+        private final int symmetricSignatureSize;
+        private final int keySize;
 
-        MacSignatureAlgorithm(String name) {
+        MacSignatureAlgorithm(String name, int symmetricSignatureSize, int keySize) {
             this.name = name;
+            this.symmetricSignatureSize = symmetricSignatureSize;
+            this.keySize = keySize;
         }
 
         public Mac getSignature() throws NoSuchAlgorithmException {
@@ -85,19 +102,33 @@ public enum SecurityPolicy {
         public String getName() {
             return name;
         }
+
+        public int getSymmetricSignatureSize() {
+            return symmetricSignatureSize;
+        }
+
+        public int getKeySize() {
+            return keySize;
+        }
     }
 
 
     public static class SignatureAlgorithm {
         private final String name;
+        private String uri;
 
-        SignatureAlgorithm(String name) {
+        SignatureAlgorithm(String name, String uri) {
             this.name = name;
+            this.uri = uri;
         }
 
         public Signature getSignature() throws NoSuchAlgorithmException {
             return Signature.getInstance(name);
         }
+
+        public String getUri() {
+            return uri;
+        }
     }
 
     public static class EncryptionAlgorithm {
@@ -110,7 +141,6 @@ public enum SecurityPolicy {
         public Cipher getCipher() throws NoSuchPaddingException, NoSuchAlgorithmException {
             return Cipher.getInstance(name);
         }
-
     }
 
 
diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/security/SymmetricKeys.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/security/SymmetricKeys.java
index 1206e46ac7..f0457128b0 100644
--- a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/security/SymmetricKeys.java
+++ b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/security/SymmetricKeys.java
@@ -26,8 +26,8 @@ public class SymmetricKeys {
     }
 
     public static SymmetricKeys generateKeyPair(byte[] clientNonce, byte[] serverNonce, MacSignatureAlgorithm policy) {
-        int signatureKeySize = 16;// different for aes
-        int encryptionKeySize = 16;
+        int signatureKeySize = policy.getKeySize();
+        int encryptionKeySize = policy.getKeySize();
         int cipherTextBlockSize = 16;
 
 
diff --git a/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/OpcuaPlcDriverTest.java b/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/OpcuaPlcDriverTest.java
index 8ad20bb3a8..56ce6b5b1d 100644
--- a/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/OpcuaPlcDriverTest.java
+++ b/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/OpcuaPlcDriverTest.java
@@ -466,6 +466,7 @@ public class OpcuaPlcDriverTest {
         switch (policy) {
             case NONE:
                 return tcpConnectionAddress;
+            case Basic256Sha256:
             case Basic128Rsa15:
                 Path securityTempDir = Paths.get(System.getProperty("java.io.tmpdir"), "server");
                 String keyStoreFile = securityTempDir.resolve("security").resolve("example-server.pfx").toAbsolutePath().toString();
@@ -475,7 +476,7 @@ public class OpcuaPlcDriverTest {
                         new Tuple2<>("keyStoreFile", keyStoreFile),
                         new Tuple2<>("certDirectory", certDirectory),
                         new Tuple2<>("keyStorePassword", "password"),
-                        new Tuple2<>("securityPolicy", SecurityPolicy.Basic128Rsa15)
+                        new Tuple2<>("securityPolicy", policy)
                     )
                     .map(tuple -> tuple._1() + "=" + tuple._2())
                     .collect(Collectors.joining(paramDivider));


(plc4x) 12/12: Calculate padding overhead

Posted by ld...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ldywicki pushed a commit to branch pg/security-policy
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit 2f89cb423fcdc58c8e2494c316ea208ce7090da3
Author: PatrykGala <pa...@gmail.com>
AuthorDate: Sat Sep 16 21:35:44 2023 +0200

    Calculate padding overhead
---
 .../apache/plc4x/java/opcua/context/AsymmetricEncryptionHandler.java    | 2 +-
 .../org/apache/plc4x/java/opcua/context/SymmetricEncryptionHandler.java | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/AsymmetricEncryptionHandler.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/AsymmetricEncryptionHandler.java
index 5fea2ab9fe..e37657f7e0 100644
--- a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/AsymmetricEncryptionHandler.java
+++ b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/AsymmetricEncryptionHandler.java
@@ -52,7 +52,7 @@ public class AsymmetricEncryptionHandler {
 
 
         int maxChunkSize = 8196;
-        int paddingOverhead = 1; // if cipherTextBlockSize > 256 => 2
+        int paddingOverhead = cipherTextBlockSize > 256 ? 2 : 1;
 
 
         int securityHeaderSize = beforeBodyLength - SEQUENCE_HEADER_SIZE - SECURE_MESSAGE_HEADER_SIZE;
diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/SymmetricEncryptionHandler.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/SymmetricEncryptionHandler.java
index d652eed511..52cb14635b 100644
--- a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/SymmetricEncryptionHandler.java
+++ b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/context/SymmetricEncryptionHandler.java
@@ -55,7 +55,7 @@ public class SymmetricEncryptionHandler {
 
 
         int maxChunkSize = 8196;
-        int paddingOverhead = 1; // if cipherTextBlockSize > 256 => 2
+        int paddingOverhead = 1;
 
 
         int securityHeaderSize = SYMMETRIC_SECURITY_HEADER_SIZE;