View Javadoc
1   /*
2    * Copyright (c) 2019 the Eclipse Milo Authors
3    *
4    * This program and the accompanying materials are made
5    * available under the terms of the Eclipse Public License 2.0
6    * which is available at https://www.eclipse.org/legal/epl-2.0/
7    *
8    * SPDX-License-Identifier: EPL-2.0
9    */
10  
11  package de.dlr.bt.stc.source.opcua;
12  
13  import java.io.File;
14  import java.io.InputStream;
15  import java.io.OutputStream;
16  import java.nio.file.Files;
17  import java.security.Key;
18  import java.security.KeyPair;
19  import java.security.KeyStore;
20  import java.security.PrivateKey;
21  import java.security.PublicKey;
22  import java.security.cert.X509Certificate;
23  
24  import org.eclipse.milo.opcua.stack.core.util.SelfSignedCertificateBuilder;
25  import org.eclipse.milo.opcua.stack.core.util.SelfSignedCertificateGenerator;
26  
27  import de.dlr.bt.stc.exceptions.SourceConfigurationException;
28  import lombok.extern.slf4j.Slf4j;
29  
30  @Slf4j
31  class KeyStoreLoader {
32  
33  //	private static final Pattern IP_ADDR_PATTERN = Pattern
34  //			.compile("^(([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.){3}([01]?\\d\\d?|2[0-4]\\d|25[0-5])$");
35  
36  	private static final String CLIENT_ALIAS = "client-ai";
37  	private static final char[] PASSWORD = "password".toCharArray();
38  
39  	private X509Certificate clientCertificate;
40  	private KeyPair clientKeyPair;
41  
42  	KeyStoreLoader load(File keyStoreFile, boolean createIfNotExisting) throws SourceConfigurationException {
43  		try {
44  			KeyStore keyStore = KeyStore.getInstance("PKCS12");
45  
46  			log.info("Loading KeyStore at {}", keyStoreFile);
47  
48  			if (!keyStoreFile.exists()) {
49  				if (!createIfNotExisting)
50  					throw new SourceConfigurationException(
51  							"Keystore " + keyStoreFile + " not found and automatic creation is disabled!");
52  				keyStore.load(null, PASSWORD);
53  
54  				KeyPair keyPair = SelfSignedCertificateGenerator.generateRsaKeyPair(2048);
55  
56  				SelfSignedCertificateBuilder builder = new SelfSignedCertificateBuilder(keyPair)
57  						.setCommonName("Shepard Timeseries Connector").setOrganization("DLR e.V.")
58  						.setOrganizationalUnit("BT").setLocalityName("Augsburg").setStateName("BY").setCountryCode("DE")
59  						.setApplicationUri("urn:idms:stc").addDnsName("localhost").addIpAddress("127.0.0.1");
60  
61  				// Get as many hostnames and IP addresses as we can listed in the certificate.
62  //			for (String hostname : HostnameUtil.getHostnames("0.0.0.0")) {
63  //				if (IP_ADDR_PATTERN.matcher(hostname)
64  //						.matches()) {
65  //					builder.addIpAddress(hostname);
66  //				} else {
67  //					builder.addDnsName(hostname);
68  //				}
69  //			}
70  
71  				X509Certificate certificate = builder.build();
72  
73  				keyStore.setKeyEntry(CLIENT_ALIAS, keyPair.getPrivate(), PASSWORD,
74  						new X509Certificate[] { certificate });
75  				try (OutputStream out = Files.newOutputStream(keyStoreFile.toPath())) {
76  					keyStore.store(out, PASSWORD);
77  				}
78  			} else {
79  				try (InputStream in = Files.newInputStream(keyStoreFile.toPath())) {
80  					keyStore.load(in, PASSWORD);
81  				}
82  			}
83  
84  			Key serverPrivateKey = keyStore.getKey(CLIENT_ALIAS, PASSWORD);
85  			if (serverPrivateKey instanceof PrivateKey) {
86  				clientCertificate = (X509Certificate) keyStore.getCertificate(CLIENT_ALIAS);
87  				PublicKey serverPublicKey = clientCertificate.getPublicKey();
88  				clientKeyPair = new KeyPair(serverPublicKey, (PrivateKey) serverPrivateKey);
89  			}
90  
91  			return this;
92  		} catch (Exception ex) {
93  			// This is ugly, but builder throws a generic Exception ...
94  			throw new SourceConfigurationException("Keystore operation failed", ex);
95  		}
96  	}
97  
98  	X509Certificate getClientCertificate() {
99  		return clientCertificate;
100 	}
101 
102 	KeyPair getClientKeyPair() {
103 		return clientKeyPair;
104 	}
105 
106 }