2 * Copyright © 2019 FRINX s.r.o. All rights reserved.
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
9 package org.opendaylight.netconf.test.tool;
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.session.SessionContext;
21 import org.apache.sshd.common.util.security.SecurityUtils;
22 import org.slf4j.Logger;
23 import org.slf4j.LoggerFactory;
26 * Key provider that allows to create exactly one key-pair in memory (key-pair is not persisted in memory).
27 * If the key-pair has already been generated, the existing one is used.
29 public class VirtualKeyPairProvider implements KeyPairProvider {
31 private static final Logger LOG = LoggerFactory.getLogger(VirtualKeyPairProvider.class);
33 private KeyPair generatedKeyPair;
34 private String algorithm = KeyUtils.RSA_ALGORITHM;
35 private AlgorithmParameterSpec keySpecification;
36 private Integer keySize;
39 * Creation of the key-provider with default settings - RSA algorithm with key length of 2048.
41 * @see VirtualKeyPairProvider#VirtualKeyPairProvider(String, AlgorithmParameterSpec, Integer)
43 VirtualKeyPairProvider() {
47 * Creation of the key-provider with explicitly defined algorithmic settings.
49 * @param algorithm Algorithm that is used for generation of a new key-pair. Currently supported algorithms:
50 * {@link KeyUtils#RSA_ALGORITHM}, {@link KeyUtils#DSS_ALGORITHM},
51 * {@link KeyUtils#EC_ALGORITHM}.
52 * @param keySpecification Algorithm-specific settings.
53 * @param keySize To be generated key length (must be adjusted against selected algorithm).
55 @SuppressWarnings({"unused", "WeakerAccess"})
56 VirtualKeyPairProvider(final String algorithm,
57 final AlgorithmParameterSpec keySpecification,
58 final Integer keySize) {
59 this.algorithm = algorithm;
60 this.keySpecification = keySpecification;
61 this.keySize = keySize;
65 public synchronized Iterable<KeyPair> loadKeys(final SessionContext session) {
66 if (Objects.isNull(generatedKeyPair)) {
68 generatedKeyPair = generateKeyPair();
69 } catch (GeneralSecurityException exception) {
70 LOG.error("Cannot generate key with algorithm '{}', key specification '{}', and key size '{}'.",
71 algorithm, keySpecification, keySize, exception);
72 throw new IllegalArgumentException("An error occurred during generation of a new ke pair.", exception);
75 return Collections.singleton(generatedKeyPair);
77 return Collections.emptyList();
81 * Generating of the new key-pair using specified parameters - algorithm, key length, and key specification.
83 * @return Generated key-pair.
84 * @throws GeneralSecurityException If the generation process fails because of the wrong input parameters.
86 private KeyPair generateKeyPair() throws GeneralSecurityException {
87 final KeyPairGenerator generator = SecurityUtils.getKeyPairGenerator(algorithm);
88 if (Objects.nonNull(keySpecification)) {
89 generator.initialize(keySpecification);
90 } else if (Objects.nonNull(keySize)) {
91 generator.initialize(keySize);
92 } else if (KeyUtils.EC_ALGORITHM.equals(algorithm)) {
93 int numCurves = ECCurves.SORTED_KEY_SIZE.size();
94 ECCurves curve = ECCurves.SORTED_KEY_SIZE.get(numCurves - 1);
95 generator.initialize(curve.getParameters());
97 return generator.generateKeyPair();