NETCONF-527 Holding of key-pair in memory
[netconf.git] / netconf / tools / netconf-testtool / src / main / java / org / opendaylight / netconf / test / tool / VirtualKeyPairProvider.java
1 /*
2  * Copyright © 2019 FRINX s.r.o. All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.netconf.test.tool;
10
11 import java.security.GeneralSecurityException;
12 import java.security.KeyPair;
13 import java.security.KeyPairGenerator;
14 import java.security.spec.AlgorithmParameterSpec;
15 import java.util.Collections;
16 import java.util.Objects;
17 import org.apache.sshd.common.cipher.ECCurves;
18 import org.apache.sshd.common.config.keys.KeyUtils;
19 import org.apache.sshd.common.keyprovider.KeyPairProvider;
20 import org.apache.sshd.common.util.security.SecurityUtils;
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
23
24 /**
25  * Key provider that allows to create exactly one key-pair in memory (key-pair is not persisted in memory).
26  * If the key-pair has already been generated, the existing one is used.
27  */
28 public class VirtualKeyPairProvider implements KeyPairProvider {
29
30     private static final Logger LOG = LoggerFactory.getLogger(VirtualKeyPairProvider.class);
31
32     private KeyPair generatedKeyPair;
33     private String algorithm = KeyUtils.RSA_ALGORITHM;
34     private AlgorithmParameterSpec keySpecification;
35     private Integer keySize;
36
37     /**
38      * Creation of the key-provider with default settings - RSA algorithm with key length of 2048.
39      *
40      * @see VirtualKeyPairProvider#VirtualKeyPairProvider(String, AlgorithmParameterSpec, Integer)
41      */
42     VirtualKeyPairProvider() {
43     }
44
45     /**
46      * Creation of the key-provider with explicitly defined algorithmic settings.
47      *
48      * @param algorithm        Algorithm that is used for generation of a new key-pair. Currently supported algorithms:
49      *                         {@link KeyUtils#RSA_ALGORITHM}, {@link KeyUtils#DSS_ALGORITHM},
50      *                         {@link KeyUtils#EC_ALGORITHM}.
51      * @param keySpecification Algorithm-specific settings.
52      * @param keySize          To be generated key length (must be adjusted against selected algorithm).
53      */
54     @SuppressWarnings({"unused", "WeakerAccess"})
55     VirtualKeyPairProvider(final String algorithm,
56                            final AlgorithmParameterSpec keySpecification,
57                            final Integer keySize) {
58         this.algorithm = algorithm;
59         this.keySpecification = keySpecification;
60         this.keySize = keySize;
61     }
62
63     @Override
64     public synchronized Iterable<KeyPair> loadKeys() {
65         if (Objects.isNull(generatedKeyPair)) {
66             try {
67                 generatedKeyPair = generateKeyPair();
68             } catch (GeneralSecurityException exception) {
69                 LOG.error("Cannot generate key with algorithm '{}', key specification '{}', and key size '{}'.",
70                         algorithm, keySpecification, keySize, exception);
71                 throw new IllegalArgumentException("An error occurred during generation of a new ke pair.", exception);
72             }
73         } else {
74             return Collections.singleton(generatedKeyPair);
75         }
76         return Collections.emptyList();
77     }
78
79     /**
80      * Generating of the new key-pair using specified parameters - algorithm, key length, and key specification.
81      *
82      * @return Generated key-pair.
83      * @throws GeneralSecurityException If the generation process fails because of the wrong input parameters.
84      */
85     private KeyPair generateKeyPair() throws GeneralSecurityException {
86         final KeyPairGenerator generator = SecurityUtils.getKeyPairGenerator(algorithm);
87         if (Objects.nonNull(keySpecification)) {
88             generator.initialize(keySpecification);
89         } else if (Objects.nonNull(keySize)) {
90             generator.initialize(keySize);
91         } else if (KeyUtils.EC_ALGORITHM.equals(algorithm)) {
92             int numCurves = ECCurves.SORTED_KEY_SIZE.size();
93             ECCurves curve = ECCurves.SORTED_KEY_SIZE.get(numCurves - 1);
94             generator.initialize(curve.getParameters());
95         }
96         return generator.generateKeyPair();
97     }
98 }