From 09057bf1026ecd7509102a1ce02386953b70ffff Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jaroslav=20T=C3=B3th?= Date: Tue, 19 Mar 2019 10:28:18 +0100 Subject: [PATCH] NETCONF-527 Holding of key-pair in memory MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit - Generated key-pair is not saved in file but rather kept only in memory. - Created VirtualKeyPairProvider that allows creation of only one key-pair that is returned in loadKeys(..) method. Change-Id: If51f7ae7205bfa85c95649ce327fc01d276c0e6b Signed-off-by: Jaroslav Tóth --- .../test/tool/NetconfDeviceSimulator.java | 15 +-- .../test/tool/VirtualKeyPairProvider.java | 98 +++++++++++++++++++ 2 files changed, 99 insertions(+), 14 deletions(-) create mode 100644 netconf/tools/netconf-testtool/src/main/java/org/opendaylight/netconf/test/tool/VirtualKeyPairProvider.java diff --git a/netconf/tools/netconf-testtool/src/main/java/org/opendaylight/netconf/test/tool/NetconfDeviceSimulator.java b/netconf/tools/netconf-testtool/src/main/java/org/opendaylight/netconf/test/tool/NetconfDeviceSimulator.java index 321b202604..35625ab30e 100644 --- a/netconf/tools/netconf-testtool/src/main/java/org/opendaylight/netconf/test/tool/NetconfDeviceSimulator.java +++ b/netconf/tools/netconf-testtool/src/main/java/org/opendaylight/netconf/test/tool/NetconfDeviceSimulator.java @@ -29,8 +29,6 @@ import java.net.Inet4Address; import java.net.InetSocketAddress; import java.net.UnknownHostException; import java.nio.channels.AsynchronousChannelGroup; -import java.nio.file.Files; -import java.nio.file.Path; import java.util.List; import java.util.Set; import java.util.concurrent.ExecutionException; @@ -38,7 +36,6 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import org.apache.sshd.common.keyprovider.KeyPairProvider; -import org.apache.sshd.common.util.security.SecurityUtils; import org.apache.sshd.common.util.threads.ThreadUtils; import org.opendaylight.netconf.api.capability.BasicCapability; import org.opendaylight.netconf.api.capability.Capability; @@ -191,7 +188,7 @@ public class NetconfDeviceSimulator implements Closeable { final List openDevices = Lists.newArrayList(); // Generate key to temp folder - final KeyPairProvider keyPairProvider = getPemGeneratorHostKeyProvider(); + final KeyPairProvider keyPairProvider = new VirtualKeyPairProvider(); final AsynchronousChannelGroup group; try { @@ -288,16 +285,6 @@ public class NetconfDeviceSimulator implements Closeable { .createSshProxyServerConfiguration(); } - private static KeyPairProvider getPemGeneratorHostKeyProvider() { - try { - final Path tempFile = Files.createTempFile("tempKeyNetconfTest", "suffix"); - return SecurityUtils.createGeneratorHostKeyProvider(tempFile.toAbsolutePath()); - } catch (final IOException e) { - LOG.error("Unable to generate PEM key", e); - throw new RuntimeException(e); - } - } - private Set parseSchemasToModuleCapabilities(final SharedSchemaRepository consumer) { final Set loadedSources = Sets.newHashSet(); consumer.registerSchemaSourceListener(TextToASTTransformer.create(consumer, consumer)); diff --git a/netconf/tools/netconf-testtool/src/main/java/org/opendaylight/netconf/test/tool/VirtualKeyPairProvider.java b/netconf/tools/netconf-testtool/src/main/java/org/opendaylight/netconf/test/tool/VirtualKeyPairProvider.java new file mode 100644 index 0000000000..d50f536116 --- /dev/null +++ b/netconf/tools/netconf-testtool/src/main/java/org/opendaylight/netconf/test/tool/VirtualKeyPairProvider.java @@ -0,0 +1,98 @@ +/* + * Copyright © 2019 FRINX s.r.o. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.netconf.test.tool; + +import java.security.GeneralSecurityException; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.spec.AlgorithmParameterSpec; +import java.util.Collections; +import java.util.Objects; +import org.apache.sshd.common.cipher.ECCurves; +import org.apache.sshd.common.config.keys.KeyUtils; +import org.apache.sshd.common.keyprovider.KeyPairProvider; +import org.apache.sshd.common.util.security.SecurityUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Key provider that allows to create exactly one key-pair in memory (key-pair is not persisted in memory). + * If the key-pair has already been generated, the existing one is used. + */ +public class VirtualKeyPairProvider implements KeyPairProvider { + + private static final Logger LOG = LoggerFactory.getLogger(VirtualKeyPairProvider.class); + + private KeyPair generatedKeyPair; + private String algorithm = KeyUtils.RSA_ALGORITHM; + private AlgorithmParameterSpec keySpecification; + private Integer keySize; + + /** + * Creation of the key-provider with default settings - RSA algorithm with key length of 2048. + * + * @see VirtualKeyPairProvider#VirtualKeyPairProvider(String, AlgorithmParameterSpec, Integer) + */ + VirtualKeyPairProvider() { + } + + /** + * Creation of the key-provider with explicitly defined algorithmic settings. + * + * @param algorithm Algorithm that is used for generation of a new key-pair. Currently supported algorithms: + * {@link KeyUtils#RSA_ALGORITHM}, {@link KeyUtils#DSS_ALGORITHM}, + * {@link KeyUtils#EC_ALGORITHM}. + * @param keySpecification Algorithm-specific settings. + * @param keySize To be generated key length (must be adjusted against selected algorithm). + */ + @SuppressWarnings({"unused", "WeakerAccess"}) + VirtualKeyPairProvider(final String algorithm, + final AlgorithmParameterSpec keySpecification, + final Integer keySize) { + this.algorithm = algorithm; + this.keySpecification = keySpecification; + this.keySize = keySize; + } + + @Override + public synchronized Iterable loadKeys() { + if (Objects.isNull(generatedKeyPair)) { + try { + generatedKeyPair = generateKeyPair(); + } catch (GeneralSecurityException exception) { + LOG.error("Cannot generate key with algorithm '{}', key specification '{}', and key size '{}'.", + algorithm, keySpecification, keySize, exception); + throw new IllegalArgumentException("An error occurred during generation of a new ke pair.", exception); + } + } else { + return Collections.singleton(generatedKeyPair); + } + return Collections.emptyList(); + } + + /** + * Generating of the new key-pair using specified parameters - algorithm, key length, and key specification. + * + * @return Generated key-pair. + * @throws GeneralSecurityException If the generation process fails because of the wrong input parameters. + */ + private KeyPair generateKeyPair() throws GeneralSecurityException { + final KeyPairGenerator generator = SecurityUtils.getKeyPairGenerator(algorithm); + if (Objects.nonNull(keySpecification)) { + generator.initialize(keySpecification); + } else if (Objects.nonNull(keySize)) { + generator.initialize(keySize); + } else if (KeyUtils.EC_ALGORITHM.equals(algorithm)) { + int numCurves = ECCurves.SORTED_KEY_SIZE.size(); + ECCurves curve = ECCurves.SORTED_KEY_SIZE.get(numCurves - 1); + generator.initialize(curve.getParameters()); + } + return generator.generateKeyPair(); + } +} \ No newline at end of file -- 2.36.6