package de.opcua.app.security; import org.eclipse.milo.opcua.sdk.server.util.HostnameUtil; import org.eclipse.milo.opcua.stack.core.util.SelfSignedCertificateBuilder; import org.eclipse.milo.opcua.stack.core.util.SelfSignedCertificateGenerator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.*; import java.nio.file.Path; import java.security.*; import java.security.cert.X509Certificate; import java.util.*; import java.util.regex.Pattern; /** Lädt oder erzeugt ein selbstsigniertes Zertifikat (Milo 1.1.1). */ public class KeyStoreLoader { private static final Pattern IP = Pattern.compile( "^(([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.){3}([01]?\\d\\d?|2[0-4]\\d|25[0-5])$"); private static final String AL = "server-ai"; private static final char[] PWD = "password".toCharArray(); private final Logger log = LoggerFactory.getLogger(getClass()); private X509Certificate[] chain; private X509Certificate cert; private KeyPair kp; public KeyStoreLoader load(Path dir) throws Exception { KeyStore ks = KeyStore.getInstance("PKCS12"); File file = dir.resolve("simulator.pfx").toFile(); if (!file.exists()) { ks.load(null, PWD); KeyPair pair = SelfSignedCertificateGenerator.generateRsaKeyPair(2048); String uri = "urn:opcua-gui:simulator:" + UUID.randomUUID(); SelfSignedCertificateBuilder b = new SelfSignedCertificateBuilder(pair) .setCommonName("OPC UA Simulator").setOrganization("opcua-gui") .setOrganizationalUnit("dev").setLocalityName("Berlin") .setStateName("Berlin").setCountryCode("DE").setApplicationUri(uri); Set hosts = new HashSet<>(); hosts.add(HostnameUtil.getHostname()); hosts.addAll(HostnameUtil.getHostnames("0.0.0.0", false)); for (String h : hosts) { if (IP.matcher(h).matches()) b.addIpAddress(h); else b.addDnsName(h); } X509Certificate c = b.build(); ks.setKeyEntry(AL, pair.getPrivate(), PWD, new X509Certificate[]{c}); ks.store(new FileOutputStream(file), PWD); log.info("Zertifikat erzeugt: {}", uri); } else { ks.load(new FileInputStream(file), PWD); } Key pk = ks.getKey(AL, PWD); if (pk instanceof PrivateKey priv) { cert = (X509Certificate) ks.getCertificate(AL); chain = Arrays.stream(ks.getCertificateChain(AL)) .map(X509Certificate.class::cast).toArray(X509Certificate[]::new); kp = new KeyPair(cert.getPublicKey(), priv); } return this; } public X509Certificate getServerCertificate() { return cert; } public X509Certificate[] getServerCertificateChain() { return chain; } public KeyPair getServerKeyPair() { return kp; } }