http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/config/keys/KeyRandomArt.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/KeyRandomArt.java b/sshd-core/src/main/java/org/apache/sshd/common/config/keys/KeyRandomArt.java deleted file mode 100644 index b59dbd0..0000000 --- a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/KeyRandomArt.java +++ /dev/null @@ -1,310 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.apache.sshd.common.config.keys; - -import java.io.IOException; -import java.io.StreamCorruptedException; -import java.security.KeyPair; -import java.security.PublicKey; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Objects; - -import org.apache.sshd.common.Factory; -import org.apache.sshd.common.digest.Digest; -import org.apache.sshd.common.keyprovider.KeyIdentityProvider; -import org.apache.sshd.common.util.GenericUtils; -import org.apache.sshd.common.util.ValidateUtils; - -/** - * Draw an ASCII-Art representing the fingerprint so human brain can - * profit from its built-in pattern recognition ability. - * This technique is called "random art" and can be found in some - * scientific publications like this original paper: - * - * "Hash Visualization: a New Technique to improve Real-World Security", - * Perrig A. and Song D., 1999, International Workshop on Cryptographic - * Techniques and E-Commerce (CrypTEC '99) - * - * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> - * @see <a href="http://sparrow.ece.cmu.edu/~adrian/projects/validation/validation.pdf">Original article</a> - * @see <a href="http://opensource.apple.com/source/OpenSSH/OpenSSH-175/openssh/key.c">C implementation</a> - */ -public class KeyRandomArt { - public static final int FLDBASE = 8; - public static final int FLDSIZE_Y = FLDBASE + 1; - public static final int FLDSIZE_X = FLDBASE * 2 + 1; - public static final String AUGMENTATION_STRING = " .o+=*BOX@%&#/^SE"; - - private final String algorithm; - private final int keySize; - private final char[][] field = new char[FLDSIZE_X][FLDSIZE_Y]; - - public KeyRandomArt(PublicKey key) throws Exception { - this(key, KeyUtils.getDefaultFingerPrintFactory()); - } - - public KeyRandomArt(PublicKey key, Factory<? extends Digest> f) throws Exception { - this(key, Objects.requireNonNull(f, "No digest factory").create()); - } - - public KeyRandomArt(PublicKey key, Digest d) throws Exception { - this(Objects.requireNonNull(key, "No key provided").getAlgorithm(), - KeyUtils.getKeySize(key), - KeyUtils.getRawFingerprint(Objects.requireNonNull(d, "No key digest"), key)); - } - - /** - * @param algorithm The key algorithm - * @param keySize The key size in bits - * @param digest The key digest - */ - public KeyRandomArt(String algorithm, int keySize, byte[] digest) { - this.algorithm = ValidateUtils.checkNotNullAndNotEmpty(algorithm, "No algorithm provided"); - ValidateUtils.checkTrue(keySize > 0, "Invalid key size: %d", keySize); - this.keySize = keySize; - Objects.requireNonNull(digest, "No key digest provided"); - - int x = FLDSIZE_X / 2; - int y = FLDSIZE_Y / 2; - int len = AUGMENTATION_STRING.length() - 1; - for (int i = 0; i < digest.length; i++) { - /* each byte conveys four 2-bit move commands */ - int input = digest[i] & 0xFF; - for (int b = 0; b < 4; b++) { - /* evaluate 2 bit, rest is shifted later */ - x += ((input & 0x1) != 0) ? 1 : -1; - y += ((input & 0x2) != 0) ? 1 : -1; - - /* assure we are still in bounds */ - x = Math.max(x, 0); - y = Math.max(y, 0); - x = Math.min(x, FLDSIZE_X - 1); - y = Math.min(y, FLDSIZE_Y - 1); - - /* augment the field */ - if (field[x][y] < (len - 2)) { - field[x][y]++; - } - input = input >> 2; - } - } - - /* mark starting point and end point*/ - field[FLDSIZE_X / 2][FLDSIZE_Y / 2] = (char) (len - 1); - field[x][y] = (char) len; - } - - public String getAlgorithm() { - return algorithm; - } - - public int getKeySize() { - return keySize; - } - - /** - * Outputs the generated random art - * - * @param <A> The {@link Appendable} output writer - * @param sb The writer - * @return The updated writer instance - * @throws IOException If failed to write the combined result - */ - public <A extends Appendable> A append(A sb) throws IOException { - // Upper border - String s = String.format("+--[%4s %4d]", getAlgorithm(), getKeySize()); - sb.append(s); - for (int index = s.length(); index <= FLDSIZE_X; index++) { - sb.append('-'); - } - sb.append('+'); - sb.append('\n'); - - // contents - int len = AUGMENTATION_STRING.length() - 1; - for (int y = 0; y < FLDSIZE_Y; y++) { - sb.append('|'); - for (int x = 0; x < FLDSIZE_X; x++) { - char ch = field[x][y]; - sb.append(AUGMENTATION_STRING.charAt(Math.min(ch, len))); - } - sb.append('|'); - sb.append('\n'); - } - - // lower border - sb.append('+'); - for (int index = 0; index < FLDSIZE_X; index++) { - sb.append('-'); - } - - sb.append('+'); - sb.append('\n'); - return sb; - } - - @Override - public String toString() { - try { - return append(new StringBuilder((FLDSIZE_X + 4) * (FLDSIZE_Y + 3))).toString(); - } catch (IOException e) { - return e.getClass().getSimpleName(); // unexpected - } - } - - /** - * Combines the arts in a user-friendly way so they are aligned with each other - * - * @param separator The separator to use between the arts - if empty char - * ('\0') then no separation is done - * @param arts The {@link KeyRandomArt}s to combine - ignored if {@code null}/empty - * @return The combined result - */ - public static String combine(char separator, Collection<? extends KeyRandomArt> arts) { - if (GenericUtils.isEmpty(arts)) { - return ""; - } - - try { - return combine(new StringBuilder(arts.size() * (FLDSIZE_X + 4) * (FLDSIZE_Y + 3)), separator, arts).toString(); - } catch (IOException e) { - return e.getClass().getSimpleName(); // unexpected - } - } - - /** - * Creates the combined representation of the random art entries for the provided keys - * - * @param separator The separator to use between the arts - if empty char - * ('\0') then no separation is done - * @param provider The {@link KeyIdentityProvider} - ignored if {@code null} - * or has no keys to provide - * @return The combined representation - * @throws Exception If failed to extract or combine the entries - * @see #combine(Appendable, char, KeyIdentityProvider) - */ - public static String combine(char separator, KeyIdentityProvider provider) throws Exception { - return combine(new StringBuilder(4 * (FLDSIZE_X + 4) * (FLDSIZE_Y + 3)), separator, provider).toString(); - } - - /** - * Appends the combined random art entries for the provided keys - * - * @param <A> The {@link Appendable} output writer - * @param sb The writer - * @param separator The separator to use between the arts - if empty char - * ('\0') then no separation is done - * @param provider The {@link KeyIdentityProvider} - ignored if {@code null} - * or has no keys to provide - * @return The updated writer instance - * @throws Exception If failed to extract or write the entries - * @see #generate(KeyIdentityProvider) - * @see #combine(Appendable, char, Collection) - */ - public static <A extends Appendable> A combine(A sb, char separator, KeyIdentityProvider provider) throws Exception { - return combine(sb, separator, generate(provider)); - } - - /** - * Extracts and generates random art entries for all key in the provider - * - * @param provider The {@link KeyIdentityProvider} - ignored if {@code null} - * or has no keys to provide - * @return The extracted {@link KeyRandomArt}s - * @throws Exception If failed to extract the entries - * @see KeyIdentityProvider#loadKeys() - */ - public static Collection<KeyRandomArt> generate(KeyIdentityProvider provider) throws Exception { - Iterable<KeyPair> keys = (provider == null) ? null : provider.loadKeys(); - Iterator<KeyPair> iter = (keys == null) ? null : keys.iterator(); - if ((iter == null) || (!iter.hasNext())) { - return Collections.emptyList(); - } - - Collection<KeyRandomArt> arts = new LinkedList<>(); - do { - KeyPair kp = iter.next(); - KeyRandomArt a = new KeyRandomArt(kp.getPublic()); - arts.add(a); - } while (iter.hasNext()); - - return arts; - } - - /** - * Combines the arts in a user-friendly way so they are aligned with each other - * - * @param <A> The {@link Appendable} output writer - * @param sb The writer - * @param separator The separator to use between the arts - if empty char - * ('\0') then no separation is done - * @param arts The {@link KeyRandomArt}s to combine - ignored if {@code null}/empty - * @return The updated writer instance - * @throws IOException If failed to write the combined result - */ - public static <A extends Appendable> A combine(A sb, char separator, Collection<? extends KeyRandomArt> arts) throws IOException { - if (GenericUtils.isEmpty(arts)) { - return sb; - } - - List<String[]> allLines = new ArrayList<>(arts.size()); - int numLines = -1; - for (KeyRandomArt a : arts) { - String s = a.toString(); - String[] lines = GenericUtils.split(s, '\n'); - if (numLines <= 0) { - numLines = lines.length; - } else { - if (numLines != lines.length) { - throw new StreamCorruptedException("Mismatched lines count: expected=" + numLines + ", actual=" + lines.length); - } - } - - for (int index = 0; index < lines.length; index++) { - String l = lines[index]; - if ((l.length() > 0) && (l.charAt(l.length() - 1) == '\r')) { - l = l.substring(0, l.length() - 1); - lines[index] = l; - } - } - - allLines.add(lines); - } - - for (int row = 0; row < numLines; row++) { - for (int index = 0; index < allLines.size(); index++) { - String[] lines = allLines.get(index); - String l = lines[row]; - sb.append(l); - if ((index > 0) && (separator != '\0')) { - sb.append(separator); - } - } - sb.append('\n'); - } - - return sb; - } -}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/config/keys/KeyUtils.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/KeyUtils.java b/sshd-core/src/main/java/org/apache/sshd/common/config/keys/KeyUtils.java deleted file mode 100644 index 84b019f..0000000 --- a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/KeyUtils.java +++ /dev/null @@ -1,937 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.sshd.common.config.keys; - -import java.io.IOException; -import java.math.BigInteger; -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.LinkOption; -import java.nio.file.Path; -import java.nio.file.attribute.PosixFilePermission; -import java.security.GeneralSecurityException; -import java.security.Key; -import java.security.KeyFactory; -import java.security.KeyPair; -import java.security.PrivateKey; -import java.security.PublicKey; -import java.security.interfaces.DSAKey; -import java.security.interfaces.DSAParams; -import java.security.interfaces.DSAPrivateKey; -import java.security.interfaces.DSAPublicKey; -import java.security.interfaces.ECKey; -import java.security.interfaces.ECPrivateKey; -import java.security.interfaces.ECPublicKey; -import java.security.interfaces.RSAKey; -import java.security.interfaces.RSAPrivateCrtKey; -import java.security.interfaces.RSAPrivateKey; -import java.security.interfaces.RSAPublicKey; -import java.security.spec.DSAPublicKeySpec; -import java.security.spec.ECParameterSpec; -import java.security.spec.InvalidKeySpecException; -import java.security.spec.RSAPublicKeySpec; -import java.util.AbstractMap.SimpleImmutableEntry; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.EnumSet; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.TreeMap; -import java.util.concurrent.atomic.AtomicReference; - -import org.apache.sshd.common.Factory; -import org.apache.sshd.common.cipher.ECCurves; -import org.apache.sshd.common.config.keys.impl.DSSPublicKeyEntryDecoder; -import org.apache.sshd.common.config.keys.impl.ECDSAPublicKeyEntryDecoder; -import org.apache.sshd.common.config.keys.impl.RSAPublicKeyDecoder; -import org.apache.sshd.common.digest.BuiltinDigests; -import org.apache.sshd.common.digest.Digest; -import org.apache.sshd.common.digest.DigestFactory; -import org.apache.sshd.common.digest.DigestUtils; -import org.apache.sshd.common.keyprovider.KeyPairProvider; -import org.apache.sshd.common.util.GenericUtils; -import org.apache.sshd.common.util.OsUtils; -import org.apache.sshd.common.util.ValidateUtils; -import org.apache.sshd.common.util.buffer.Buffer; -import org.apache.sshd.common.util.buffer.ByteArrayBuffer; -import org.apache.sshd.common.util.io.IoUtils; -import org.apache.sshd.common.util.security.SecurityUtils; - -/** - * Utility class for keys - * - * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> - */ -public final class KeyUtils { - /** - * Name of algorithm for RSA keys to be used when calling security provider - */ - public static final String RSA_ALGORITHM = "RSA"; - - /** - * The most commonly used RSA public key exponent - */ - public static final BigInteger DEFAULT_RSA_PUBLIC_EXPONENT = new BigInteger("65537"); - - /** - * Name of algorithm for DSS keys to be used when calling security provider - */ - public static final String DSS_ALGORITHM = "DSA"; - - /** - * Name of algorithm for EC keys to be used when calling security provider - */ - public static final String EC_ALGORITHM = "EC"; - - /** - * The {@link Set} of {@link PosixFilePermission} <U>not</U> allowed if strict - * permissions are enforced on key files - */ - public static final Set<PosixFilePermission> STRICTLY_PROHIBITED_FILE_PERMISSION = - Collections.unmodifiableSet( - EnumSet.of(PosixFilePermission.GROUP_READ, PosixFilePermission.GROUP_WRITE, PosixFilePermission.GROUP_EXECUTE, - PosixFilePermission.OTHERS_READ, PosixFilePermission.OTHERS_WRITE, PosixFilePermission.OTHERS_EXECUTE)); - - /** - * System property that can be used to control the default fingerprint factory used for keys. - * If not set the {@link #DEFAULT_FINGERPRINT_DIGEST_FACTORY} is used - */ - public static final String KEY_FINGERPRINT_FACTORY_PROP = "org.apache.sshd.keyFingerprintFactory"; - - /** - * The default {@link Factory} of {@link Digest}s initialized - * as the value of {@link #getDefaultFingerPrintFactory()} if not - * overridden by {@link #KEY_FINGERPRINT_FACTORY_PROP} or - * {@link #setDefaultFingerPrintFactory(DigestFactory)} - */ - public static final DigestFactory DEFAULT_FINGERPRINT_DIGEST_FACTORY = BuiltinDigests.sha256; - - private static final AtomicReference<DigestFactory> DEFAULT_DIGEST_HOLDER = new AtomicReference<>(); - - private static final Map<String, PublicKeyEntryDecoder<?, ?>> BY_KEY_TYPE_DECODERS_MAP = - new TreeMap<>(String.CASE_INSENSITIVE_ORDER); - - private static final Map<Class<?>, PublicKeyEntryDecoder<?, ?>> BY_KEY_CLASS_DECODERS_MAP = - new HashMap<>(); - - static { - registerPublicKeyEntryDecoder(RSAPublicKeyDecoder.INSTANCE); - registerPublicKeyEntryDecoder(DSSPublicKeyEntryDecoder.INSTANCE); - - if (SecurityUtils.isECCSupported()) { - registerPublicKeyEntryDecoder(ECDSAPublicKeyEntryDecoder.INSTANCE); - } - if (SecurityUtils.isEDDSACurveSupported()) { - registerPublicKeyEntryDecoder(SecurityUtils.getEDDSAPublicKeyEntryDecoder()); - } - } - - private KeyUtils() { - throw new UnsupportedOperationException("No instance"); - } - - /** - * <P>Checks if a path has strict permissions</P> - * <UL> - * <LI><P> - * The path may not have {@link PosixFilePermission#OTHERS_EXECUTE} - * permission - * </P></LI> - * - * <LI><P> - * (For {@code Unix}) The path may not have group or others permissions - * </P></LI> - * - * <LI><P> - * (For {@code Unix}) If the path is a file, then its folder may not have - * group or others permissions - * </P></LI> - * - * <LI><P> - * The path must be owned by current user. - * </P></LI> - * - * <LI><P> - * (For {@code Unix}) The path may be owned by root. - * </P></LI> - * - * <LI><P> - * (For {@code Unix}) If the path is a file, then its folder must also - * have valid owner. - * </P></LI> - * - * </UL> - * - * @param path The {@link Path} to be checked - ignored if {@code null} - * or does not exist - * @param options The {@link LinkOption}s to use to query the file's permissions - * @return The violated permission as {@link SimpleImmutableEntry} where key is a message and - * value is the offending object {@link PosixFilePermission} or {@link String} for owner - {@code null} - * if no violations detected - * @throws IOException If failed to retrieve the permissions - * @see #STRICTLY_PROHIBITED_FILE_PERMISSION - */ - public static SimpleImmutableEntry<String, Object> validateStrictKeyFilePermissions(Path path, LinkOption... options) throws IOException { - if ((path == null) || (!Files.exists(path, options))) { - return null; - } - - Collection<PosixFilePermission> perms = IoUtils.getPermissions(path, options); - if (GenericUtils.isEmpty(perms)) { - return null; - } - - if (perms.contains(PosixFilePermission.OTHERS_EXECUTE)) { - PosixFilePermission p = PosixFilePermission.OTHERS_EXECUTE; - return new SimpleImmutableEntry<>(String.format("Permissions violation (%s)", p), p); - } - - if (OsUtils.isUNIX()) { - PosixFilePermission p = IoUtils.validateExcludedPermissions(perms, STRICTLY_PROHIBITED_FILE_PERMISSION); - if (p != null) { - return new SimpleImmutableEntry<>(String.format("Permissions violation (%s)", p), p); - } - - if (Files.isRegularFile(path, options)) { - Path parent = path.getParent(); - p = IoUtils.validateExcludedPermissions(IoUtils.getPermissions(parent, options), STRICTLY_PROHIBITED_FILE_PERMISSION); - if (p != null) { - return new SimpleImmutableEntry<>(String.format("Parent permissions violation (%s)", p), p); - } - } - } - - String owner = IoUtils.getFileOwner(path, options); - if (GenericUtils.isEmpty(owner)) { - // we cannot get owner - // general issue: jvm does not support permissions - // security issue: specific filesystem does not support permissions - return null; - } - - String current = OsUtils.getCurrentUser(); - Set<String> expected = new HashSet<>(); - expected.add(current); - if (OsUtils.isUNIX()) { - // Windows "Administrator" was considered however in Windows most likely a group is used. - expected.add(OsUtils.ROOT_USER); - } - - if (!expected.contains(owner)) { - return new SimpleImmutableEntry<>(String.format("Owner violation (%s)", owner), owner); - } - - if (OsUtils.isUNIX()) { - if (Files.isRegularFile(path, options)) { - String parentOwner = IoUtils.getFileOwner(path.getParent(), options); - if ((!GenericUtils.isEmpty(parentOwner)) && (!expected.contains(parentOwner))) { - return new SimpleImmutableEntry<>(String.format("Parent owner violation (%s)", parentOwner), parentOwner); - } - } - } - - return null; - } - - /** - * @param keyType The key type - {@code OpenSSH} name - e.g., {@code ssh-rsa, ssh-dss} - * @param keySize The key size (in bits) - * @return A {@link KeyPair} of the specified type and size - * @throws GeneralSecurityException If failed to generate the key pair - * @see #getPublicKeyEntryDecoder(String) - * @see PublicKeyEntryDecoder#generateKeyPair(int) - */ - public static KeyPair generateKeyPair(String keyType, int keySize) throws GeneralSecurityException { - PublicKeyEntryDecoder<?, ?> decoder = getPublicKeyEntryDecoder(keyType); - if (decoder == null) { - throw new InvalidKeySpecException("No decoder for key type=" + keyType); - } - - return decoder.generateKeyPair(keySize); - } - - /** - * Performs a deep-clone of the original {@link KeyPair} - i.e., creates - * <U>new</U> public/private keys that are clones of the original one - * - * @param keyType The key type - {@code OpenSSH} name - e.g., {@code ssh-rsa, ssh-dss} - * @param kp The {@link KeyPair} to clone - ignored if {@code null} - * @return The cloned instance - * @throws GeneralSecurityException If failed to clone the pair - */ - public static KeyPair cloneKeyPair(String keyType, KeyPair kp) throws GeneralSecurityException { - PublicKeyEntryDecoder<?, ?> decoder = getPublicKeyEntryDecoder(keyType); - if (decoder == null) { - throw new InvalidKeySpecException("No decoder for key type=" + keyType); - } - - return decoder.cloneKeyPair(kp); - } - - /** - * @param decoder The decoder to register - * @throws IllegalArgumentException if no decoder or not key type or no - * supported names for the decoder - * @see PublicKeyEntryDecoder#getPublicKeyType() - * @see PublicKeyEntryDecoder#getSupportedTypeNames() - */ - public static void registerPublicKeyEntryDecoder(PublicKeyEntryDecoder<?, ?> decoder) { - Objects.requireNonNull(decoder, "No decoder specified"); - - Class<?> pubType = Objects.requireNonNull(decoder.getPublicKeyType(), "No public key type declared"); - Class<?> prvType = Objects.requireNonNull(decoder.getPrivateKeyType(), "No private key type declared"); - synchronized (BY_KEY_CLASS_DECODERS_MAP) { - BY_KEY_CLASS_DECODERS_MAP.put(pubType, decoder); - BY_KEY_CLASS_DECODERS_MAP.put(prvType, decoder); - } - - Collection<String> names = ValidateUtils.checkNotNullAndNotEmpty(decoder.getSupportedTypeNames(), "No supported key type"); - synchronized (BY_KEY_TYPE_DECODERS_MAP) { - for (String n : names) { - PublicKeyEntryDecoder<?, ?> prev = BY_KEY_TYPE_DECODERS_MAP.put(n, decoder); - if (prev != null) { - //noinspection UnnecessaryContinue - continue; // debug breakpoint - } - } - } - } - - /** - * @param keyType The {@code OpenSSH} key type string - e.g., {@code ssh-rsa, ssh-dss} - * - ignored if {@code null}/empty - * @return The registered {@link PublicKeyEntryDecoder} or {code null} if not found - */ - public static PublicKeyEntryDecoder<?, ?> getPublicKeyEntryDecoder(String keyType) { - if (GenericUtils.isEmpty(keyType)) { - return null; - } - - synchronized (BY_KEY_TYPE_DECODERS_MAP) { - return BY_KEY_TYPE_DECODERS_MAP.get(keyType); - } - } - - /** - * @param kp The {@link KeyPair} to examine - ignored if {@code null} - * @return The matching {@link PublicKeyEntryDecoder} provided <U>both</U> - * the public and private keys have the same decoder - {@code null} if no - * match found - * @see #getPublicKeyEntryDecoder(Key) - */ - public static PublicKeyEntryDecoder<?, ?> getPublicKeyEntryDecoder(KeyPair kp) { - if (kp == null) { - return null; - } - - PublicKeyEntryDecoder<?, ?> d1 = getPublicKeyEntryDecoder(kp.getPublic()); - PublicKeyEntryDecoder<?, ?> d2 = getPublicKeyEntryDecoder(kp.getPrivate()); - if (d1 == d2) { - return d1; - } else { - return null; // some kind of mixed keys... - } - } - - /** - * @param key The {@link Key} (public or private) - ignored if {@code null} - * @return The registered {@link PublicKeyEntryDecoder} for this key or {code null} if no match found - * @see #getPublicKeyEntryDecoder(Class) - */ - public static PublicKeyEntryDecoder<?, ?> getPublicKeyEntryDecoder(Key key) { - if (key == null) { - return null; - } else { - return getPublicKeyEntryDecoder(key.getClass()); - } - } - - /** - * @param keyType The key {@link Class} - ignored if {@code null} or not a {@link Key} - * compatible type - * @return The registered {@link PublicKeyEntryDecoder} or {code null} if no match found - */ - public static PublicKeyEntryDecoder<?, ?> getPublicKeyEntryDecoder(Class<?> keyType) { - if ((keyType == null) || (!Key.class.isAssignableFrom(keyType))) { - return null; - } - - synchronized (BY_KEY_TYPE_DECODERS_MAP) { - PublicKeyEntryDecoder<?, ?> decoder = BY_KEY_CLASS_DECODERS_MAP.get(keyType); - if (decoder != null) { - return decoder; - } - - // in case it is a derived class - for (PublicKeyEntryDecoder<?, ?> dec : BY_KEY_CLASS_DECODERS_MAP.values()) { - Class<?> pubType = dec.getPublicKeyType(); - Class<?> prvType = dec.getPrivateKeyType(); - if (pubType.isAssignableFrom(keyType) || prvType.isAssignableFrom(keyType)) { - return dec; - } - } - } - - return null; - } - - /** - * @return The default {@link DigestFactory} - * by the {@link #getFingerPrint(PublicKey)} and {@link #getFingerPrint(String)} - * methods - * @see #KEY_FINGERPRINT_FACTORY_PROP - * @see #setDefaultFingerPrintFactory(DigestFactory) - */ - public static DigestFactory getDefaultFingerPrintFactory() { - DigestFactory factory = null; - synchronized (DEFAULT_DIGEST_HOLDER) { - factory = DEFAULT_DIGEST_HOLDER.get(); - if (factory != null) { - return factory; - } - - String propVal = System.getProperty(KEY_FINGERPRINT_FACTORY_PROP); - if (GenericUtils.isEmpty(propVal)) { - factory = DEFAULT_FINGERPRINT_DIGEST_FACTORY; - } else { - factory = ValidateUtils.checkNotNull(BuiltinDigests.fromFactoryName(propVal), "Unknown digest factory: %s", propVal); - } - - ValidateUtils.checkTrue(factory.isSupported(), "Selected fingerprint digest not supported: %s", factory.getName()); - DEFAULT_DIGEST_HOLDER.set(factory); - } - - return factory; - } - - /** - * @param f The {@link DigestFactory} of {@link Digest}s to be used - may - * not be {@code null} - */ - public static void setDefaultFingerPrintFactory(DigestFactory f) { - synchronized (DEFAULT_DIGEST_HOLDER) { - DEFAULT_DIGEST_HOLDER.set(Objects.requireNonNull(f, "No digest factory")); - } - } - - /** - * @param key the public key - ignored if {@code null} - * @return the fingerprint or {@code null} if no key. - * <B>Note:</B> if exception encountered then returns the exception's simple class name - * @see #getFingerPrint(Factory, PublicKey) - */ - public static String getFingerPrint(PublicKey key) { - return getFingerPrint(getDefaultFingerPrintFactory(), key); - } - - /** - * @param password The {@link String} to digest - ignored if {@code null}/empty, - * otherwise its UTF-8 representation is used as input for the fingerprint - * @return The fingerprint - {@code null} if {@code null}/empty input. - * <B>Note:</B> if exception encountered then returns the exception's simple class name - * @see #getFingerPrint(String, Charset) - */ - public static String getFingerPrint(String password) { - return getFingerPrint(password, StandardCharsets.UTF_8); - } - - /** - * @param password The {@link String} to digest - ignored if {@code null}/empty - * @param charset The {@link Charset} to use in order to convert the - * string to its byte representation to use as input for the fingerprint - * @return The fingerprint - {@code null} if {@code null}/empty input. - * <B>Note:</B> if exception encountered then returns the exception's simple class name - * @see #getFingerPrint(Factory, String, Charset) - * @see #getDefaultFingerPrintFactory() - */ - public static String getFingerPrint(String password, Charset charset) { - return getFingerPrint(getDefaultFingerPrintFactory(), password, charset); - } - - /** - * @param f The {@link Factory} to create the {@link Digest} to use - * @param key the public key - ignored if {@code null} - * @return the fingerprint or {@code null} if no key. - * <B>Note:</B> if exception encountered then returns the exception's simple class name - * @see #getFingerPrint(Digest, PublicKey) - */ - public static String getFingerPrint(Factory<? extends Digest> f, PublicKey key) { - return (key == null) ? null : getFingerPrint(Objects.requireNonNull(f, "No digest factory").create(), key); - } - - /** - * @param d The {@link Digest} to use - * @param key the public key - ignored if {@code null} - * @return the fingerprint or {@code null} if no key. - * <B>Note:</B> if exception encountered then returns the exception's simple class name - * @see DigestUtils#getFingerPrint(Digest, byte[], int, int) - */ - public static String getFingerPrint(Digest d, PublicKey key) { - if (key == null) { - return null; - } - - try { - Buffer buffer = new ByteArrayBuffer(); - buffer.putRawPublicKey(key); - return DigestUtils.getFingerPrint(d, buffer.array(), 0, buffer.wpos()); - } catch (Exception e) { - return e.getClass().getSimpleName(); - } - } - - public static byte[] getRawFingerprint(PublicKey key) throws Exception { - return getRawFingerprint(getDefaultFingerPrintFactory(), key); - } - - public static byte[] getRawFingerprint(Factory<? extends Digest> f, PublicKey key) throws Exception { - return (key == null) ? null : getRawFingerprint(Objects.requireNonNull(f, "No digest factory").create(), key); - } - - public static byte[] getRawFingerprint(Digest d, PublicKey key) throws Exception { - if (key == null) { - return null; - } - - Buffer buffer = new ByteArrayBuffer(); - buffer.putRawPublicKey(key); - return DigestUtils.getRawFingerprint(d, buffer.array(), 0, buffer.wpos()); - } - - /** - * @param f The {@link Factory} to create the {@link Digest} to use - * @param s The {@link String} to digest - ignored if {@code null}/empty, - * otherwise its UTF-8 representation is used as input for the fingerprint - * @return The fingerprint - {@code null} if {@code null}/empty input. - * <B>Note:</B> if exception encountered then returns the exception's simple class name - * @see #getFingerPrint(Digest, String, Charset) - */ - public static String getFingerPrint(Factory<? extends Digest> f, String s) { - return getFingerPrint(f, s, StandardCharsets.UTF_8); - } - - /** - * @param f The {@link Factory} to create the {@link Digest} to use - * @param s The {@link String} to digest - ignored if {@code null}/empty - * @param charset The {@link Charset} to use in order to convert the - * string to its byte representation to use as input for the fingerprint - * @return The fingerprint - {@code null} if {@code null}/empty input - * <B>Note:</B> if exception encountered then returns the exception's simple class name - * @see DigestUtils#getFingerPrint(Digest, String, Charset) - */ - public static String getFingerPrint(Factory<? extends Digest> f, String s, Charset charset) { - return getFingerPrint(f.create(), s, charset); - } - - /** - * @param d The {@link Digest} to use - * @param s The {@link String} to digest - ignored if {@code null}/empty, - * otherwise its UTF-8 representation is used as input for the fingerprint - * @return The fingerprint - {@code null} if {@code null}/empty input. - * <B>Note:</B> if exception encountered then returns the exception's simple class name - * @see DigestUtils#getFingerPrint(Digest, String, Charset) - */ - public static String getFingerPrint(Digest d, String s) { - return getFingerPrint(d, s, StandardCharsets.UTF_8); - } - - /** - * @param d The {@link Digest} to use to calculate the fingerprint - * @param s The string to digest - ignored if {@code null}/empty - * @param charset The {@link Charset} to use in order to convert the - * string to its byte representation to use as input for the fingerprint - * @return The fingerprint - {@code null} if {@code null}/empty input. - * <B>Note:</B> if exception encountered then returns the exception's simple class name - * @see DigestUtils#getFingerPrint(Digest, String, Charset) - */ - public static String getFingerPrint(Digest d, String s, Charset charset) { - if (GenericUtils.isEmpty(s)) { - return null; - } - - try { - return DigestUtils.getFingerPrint(d, s, charset); - } catch (Exception e) { - return e.getClass().getSimpleName(); - } - } - - /** - * @param expected The expected fingerprint if {@code null} or empty then returns a failure - * with the default fingerprint. - * @param key the {@link PublicKey} - if {@code null} then returns null. - * @return SimpleImmutableEntry<Boolean, String> - key is success indicator, value is actual fingerprint, - * {@code null} if no key. - * @see #getDefaultFingerPrintFactory() - * @see #checkFingerPrint(String, Factory, PublicKey) - */ - public static SimpleImmutableEntry<Boolean, String> checkFingerPrint(String expected, PublicKey key) { - return checkFingerPrint(expected, getDefaultFingerPrintFactory(), key); - } - - /** - * @param expected The expected fingerprint if {@code null} or empty then returns a failure - * with the default fingerprint. - * @param f The {@link Factory} to be used to generate the default {@link Digest} for the key - * @param key the {@link PublicKey} - if {@code null} then returns null. - * @return SimpleImmutableEntry<Boolean, String> - key is success indicator, value is actual fingerprint, - * {@code null} if no key. - */ - public static SimpleImmutableEntry<Boolean, String> checkFingerPrint(String expected, Factory<? extends Digest> f, PublicKey key) { - return checkFingerPrint(expected, Objects.requireNonNull(f, "No digest factory").create(), key); - } - - /** - * @param expected The expected fingerprint if {@code null} or empty then returns a failure - * with the default fingerprint. - * @param d The {@link Digest} to be used to generate the default fingerprint for the key - * @param key the {@link PublicKey} - if {@code null} then returns null. - * @return SimpleImmutableEntry<Boolean, String> - key is success indicator, value is actual fingerprint, - * {@code null} if no key. - */ - public static SimpleImmutableEntry<Boolean, String> checkFingerPrint(String expected, Digest d, PublicKey key) { - if (key == null) { - return null; - } - - if (GenericUtils.isEmpty(expected)) { - return new SimpleImmutableEntry<>(false, getFingerPrint(d, key)); - } - - // de-construct fingerprint - int pos = expected.indexOf(':'); - if ((pos < 0) || (pos >= (expected.length() - 1))) { - return new SimpleImmutableEntry<>(false, getFingerPrint(d, key)); - } - - String name = expected.substring(0, pos); - String value = expected.substring(pos + 1); - DigestFactory expectedFactory; - // We know that all digest names have a length > 2 - if 2 (or less) then assume a pure HEX value - if (name.length() > 2) { - expectedFactory = BuiltinDigests.fromFactoryName(name); - if (expectedFactory == null) { - return new SimpleImmutableEntry<>(false, getFingerPrint(d, key)); - } - - expected = name.toUpperCase() + ":" + value; - } else { - expectedFactory = BuiltinDigests.md5; - expected = expectedFactory.getName().toUpperCase() + ":" + expected; - } - - String fingerprint = getFingerPrint(expectedFactory, key); - boolean matches = BuiltinDigests.md5.getName().equals(expectedFactory.getName()) - ? expected.equalsIgnoreCase(fingerprint) // HEX is case insensitive - : expected.equals(fingerprint); - return new SimpleImmutableEntry<>(matches, fingerprint); - } - - /** - * @param kp a key pair - ignored if {@code null}. If the private - * key is non-{@code null} then it is used to determine the type, - * otherwise the public one is used. - * @return the key type or {@code null} if cannot determine it - * @see #getKeyType(Key) - */ - public static String getKeyType(KeyPair kp) { - if (kp == null) { - return null; - } - PrivateKey key = kp.getPrivate(); - if (key != null) { - return getKeyType(key); - } else { - return getKeyType(kp.getPublic()); - } - } - - /** - * @param key a public or private key - * @return the key type or {@code null} if cannot determine it - */ - public static String getKeyType(Key key) { - if (key == null) { - return null; - } else if (key instanceof DSAKey) { - return KeyPairProvider.SSH_DSS; - } else if (key instanceof RSAKey) { - return KeyPairProvider.SSH_RSA; - } else if (key instanceof ECKey) { - ECKey ecKey = (ECKey) key; - ECParameterSpec ecSpec = ecKey.getParams(); - ECCurves curve = ECCurves.fromCurveParameters(ecSpec); - if (curve == null) { - return null; // debug breakpoint - } else { - return curve.getKeyType(); - } - } else if (SecurityUtils.EDDSA.equalsIgnoreCase(key.getAlgorithm())) { - return KeyPairProvider.SSH_ED25519; - } - - return null; - } - - /** - * Determines the key size in bits - * - * @param key The {@link Key} to examine - ignored if {@code null} - * @return The key size - non-positive value if cannot determine it - */ - public static int getKeySize(Key key) { - if (key == null) { - return -1; - } else if (key instanceof RSAKey) { - BigInteger n = ((RSAKey) key).getModulus(); - return n.bitLength(); - } else if (key instanceof DSAKey) { - DSAParams params = ((DSAKey) key).getParams(); - BigInteger p = params.getP(); - return p.bitLength(); - } else if (key instanceof ECKey) { - ECParameterSpec ecSpec = ((ECKey) key).getParams(); - ECCurves curve = ECCurves.fromCurveParameters(ecSpec); - if (curve != null) { - return curve.getKeySize(); - } - } else if (SecurityUtils.EDDSA.equalsIgnoreCase(key.getAlgorithm())) { - return SecurityUtils.getEDDSAKeySize(key); - } - - return -1; - } - - /** - * @param key The {@link PublicKey} to be checked - ignored if {@code null} - * @param keySet The keys to be searched - ignored if {@code null}/empty - * @return The matching {@link PublicKey} from the keys or {@code null} if - * no match found - * @see #compareKeys(PublicKey, PublicKey) - */ - public static PublicKey findMatchingKey(PublicKey key, PublicKey... keySet) { - if (key == null || GenericUtils.isEmpty(keySet)) { - return null; - } else { - return findMatchingKey(key, Arrays.asList(keySet)); - } - } - - /** - * @param key The {@link PublicKey} to be checked - ignored if {@code null} - * @param keySet The keys to be searched - ignored if {@code null}/empty - * @return The matching {@link PublicKey} from the keys or {@code null} if - * no match found - * @see #compareKeys(PublicKey, PublicKey) - */ - public static PublicKey findMatchingKey(PublicKey key, Collection<? extends PublicKey> keySet) { - if (key == null || GenericUtils.isEmpty(keySet)) { - return null; - } - for (PublicKey k : keySet) { - if (compareKeys(key, k)) { - return k; - } - } - return null; - } - - public static boolean compareKeyPairs(KeyPair k1, KeyPair k2) { - if (Objects.equals(k1, k2)) { - return true; - } else if ((k1 == null) || (k2 == null)) { - return false; // both null is covered by Objects#equals - } else { - return compareKeys(k1.getPublic(), k2.getPublic()) - && compareKeys(k1.getPrivate(), k2.getPrivate()); - } - } - - public static boolean compareKeys(PublicKey k1, PublicKey k2) { - if ((k1 instanceof RSAPublicKey) && (k2 instanceof RSAPublicKey)) { - return compareRSAKeys(RSAPublicKey.class.cast(k1), RSAPublicKey.class.cast(k2)); - } else if ((k1 instanceof DSAPublicKey) && (k2 instanceof DSAPublicKey)) { - return compareDSAKeys(DSAPublicKey.class.cast(k1), DSAPublicKey.class.cast(k2)); - } else if ((k1 instanceof ECPublicKey) && (k2 instanceof ECPublicKey)) { - return compareECKeys(ECPublicKey.class.cast(k1), ECPublicKey.class.cast(k2)); - } else if ((k1 != null) && SecurityUtils.EDDSA.equalsIgnoreCase(k1.getAlgorithm()) - && (k2 != null) && SecurityUtils.EDDSA.equalsIgnoreCase(k2.getAlgorithm())) { - return SecurityUtils.compareEDDSAPPublicKeys(k1, k2); - } else { - return false; // either key is null or not of same class - } - } - - public static PublicKey recoverPublicKey(PrivateKey key) throws GeneralSecurityException { - if (key instanceof RSAPrivateKey) { - return recoverRSAPublicKey((RSAPrivateKey) key); - } else if (key instanceof DSAPrivateKey) { - return recoverDSAPublicKey((DSAPrivateKey) key); - } else if ((key != null) && SecurityUtils.EDDSA.equalsIgnoreCase(key.getAlgorithm())) { - return SecurityUtils.recoverEDDSAPublicKey(key); - } else { - return null; - } - } - - public static boolean compareKeys(PrivateKey k1, PrivateKey k2) { - if ((k1 instanceof RSAPrivateKey) && (k2 instanceof RSAPrivateKey)) { - return compareRSAKeys(RSAPrivateKey.class.cast(k1), RSAPrivateKey.class.cast(k2)); - } else if ((k1 instanceof DSAPrivateKey) && (k2 instanceof DSAPrivateKey)) { - return compareDSAKeys(DSAPrivateKey.class.cast(k1), DSAPrivateKey.class.cast(k2)); - } else if ((k1 instanceof ECPrivateKey) && (k2 instanceof ECPrivateKey)) { - return compareECKeys(ECPrivateKey.class.cast(k1), ECPrivateKey.class.cast(k2)); - } else if ((k1 != null) && SecurityUtils.EDDSA.equalsIgnoreCase(k1.getAlgorithm()) - && (k2 != null) && SecurityUtils.EDDSA.equalsIgnoreCase(k2.getAlgorithm())) { - return SecurityUtils.compareEDDSAPrivateKeys(k1, k2); - } else { - return false; // either key is null or not of same class - } - } - - public static boolean compareRSAKeys(RSAPublicKey k1, RSAPublicKey k2) { - if (Objects.equals(k1, k2)) { - return true; - } else if (k1 == null || k2 == null) { - return false; // both null is covered by Objects#equals - } else { - return Objects.equals(k1.getPublicExponent(), k2.getPublicExponent()) - && Objects.equals(k1.getModulus(), k2.getModulus()); - } - } - - public static boolean compareRSAKeys(RSAPrivateKey k1, RSAPrivateKey k2) { - if (Objects.equals(k1, k2)) { - return true; - } else if (k1 == null || k2 == null) { - return false; // both null is covered by Objects#equals - } else { - return Objects.equals(k1.getModulus(), k2.getModulus()) - && Objects.equals(k1.getPrivateExponent(), k2.getPrivateExponent()); - } - } - - public static RSAPublicKey recoverRSAPublicKey(RSAPrivateKey privateKey) throws GeneralSecurityException { - if (privateKey instanceof RSAPrivateCrtKey) { - return recoverFromRSAPrivateCrtKey((RSAPrivateCrtKey) privateKey); - } else { - // Not ideal, but best we can do under the circumstances - return recoverRSAPublicKey(privateKey.getModulus(), DEFAULT_RSA_PUBLIC_EXPONENT); - } - } - - public static RSAPublicKey recoverFromRSAPrivateCrtKey(RSAPrivateCrtKey rsaKey) throws GeneralSecurityException { - return recoverRSAPublicKey(rsaKey.getPrimeP(), rsaKey.getPrimeQ(), rsaKey.getPublicExponent()); - } - - public static RSAPublicKey recoverRSAPublicKey(BigInteger p, BigInteger q, BigInteger publicExponent) throws GeneralSecurityException { - return recoverRSAPublicKey(p.multiply(q), publicExponent); - } - - public static RSAPublicKey recoverRSAPublicKey(BigInteger modulus, BigInteger publicExponent) throws GeneralSecurityException { - KeyFactory kf = SecurityUtils.getKeyFactory(RSA_ALGORITHM); - return (RSAPublicKey) kf.generatePublic(new RSAPublicKeySpec(modulus, publicExponent)); - } - - public static boolean compareDSAKeys(DSAPublicKey k1, DSAPublicKey k2) { - if (Objects.equals(k1, k2)) { - return true; - } else if (k1 == null || k2 == null) { - return false; // both null is covered by Objects#equals - } else { - return Objects.equals(k1.getY(), k2.getY()) - && compareDSAParams(k1.getParams(), k2.getParams()); - } - } - - public static boolean compareDSAKeys(DSAPrivateKey k1, DSAPrivateKey k2) { - if (Objects.equals(k1, k2)) { - return true; - } else if (k1 == null || k2 == null) { - return false; // both null is covered by Objects#equals - } else { - return Objects.equals(k1.getX(), k2.getX()) - && compareDSAParams(k1.getParams(), k2.getParams()); - } - } - - public static boolean compareDSAParams(DSAParams p1, DSAParams p2) { - if (Objects.equals(p1, p2)) { - return true; - } else if (p1 == null || p2 == null) { - return false; // both null is covered by Objects#equals - } else { - return Objects.equals(p1.getG(), p2.getG()) - && Objects.equals(p1.getP(), p2.getP()) - && Objects.equals(p1.getQ(), p2.getQ()); - } - } - - // based on code from https://github.com/alexo/SAML-2.0/blob/master/java-opensaml/opensaml-security-api/src/main/java/org/opensaml/xml/security/SecurityHelper.java - public static DSAPublicKey recoverDSAPublicKey(DSAPrivateKey privateKey) throws GeneralSecurityException { - DSAParams keyParams = privateKey.getParams(); - BigInteger p = keyParams.getP(); - BigInteger x = privateKey.getX(); - BigInteger q = keyParams.getQ(); - BigInteger g = keyParams.getG(); - BigInteger y = g.modPow(x, p); - KeyFactory kf = SecurityUtils.getKeyFactory(DSS_ALGORITHM); - return (DSAPublicKey) kf.generatePublic(new DSAPublicKeySpec(y, p, q, g)); - } - - public static boolean compareECKeys(ECPrivateKey k1, ECPrivateKey k2) { - if (Objects.equals(k1, k2)) { - return true; - } else if (k1 == null || k2 == null) { - return false; // both null is covered by Objects#equals - } else { - return Objects.equals(k1.getS(), k2.getS()) - && compareECParams(k1.getParams(), k2.getParams()); - } - } - - public static boolean compareECKeys(ECPublicKey k1, ECPublicKey k2) { - if (Objects.equals(k1, k2)) { - return true; - } else if (k1 == null || k2 == null) { - return false; // both null is covered by Objects#equals - } else { - return Objects.equals(k1.getW(), k2.getW()) - && compareECParams(k1.getParams(), k2.getParams()); - } - } - - public static boolean compareECParams(ECParameterSpec s1, ECParameterSpec s2) { - if (Objects.equals(s1, s2)) { - return true; - } else if (s1 == null || s2 == null) { - return false; // both null is covered by Objects#equals - } else { - return Objects.equals(s1.getOrder(), s2.getOrder()) - && (s1.getCofactor() == s2.getCofactor()) - && Objects.equals(s1.getGenerator(), s2.getGenerator()) - && Objects.equals(s1.getCurve(), s2.getCurve()); - } - } -} http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/config/keys/PrivateKeyEntryDecoder.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/PrivateKeyEntryDecoder.java b/sshd-core/src/main/java/org/apache/sshd/common/config/keys/PrivateKeyEntryDecoder.java deleted file mode 100644 index 6dbeee9..0000000 --- a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/PrivateKeyEntryDecoder.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.apache.sshd.common.config.keys; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.StreamCorruptedException; -import java.security.GeneralSecurityException; -import java.security.PrivateKey; -import java.security.PublicKey; -import java.security.spec.InvalidKeySpecException; -import java.util.Collection; -import java.util.Objects; - -import org.apache.sshd.common.util.GenericUtils; -import org.apache.sshd.common.util.NumberUtils; -import org.apache.sshd.common.util.ValidateUtils; - -/** - * @param <PUB> Type of {@link PublicKey} - * @param <PRV> Type of {@link PrivateKey} - * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> - */ -public interface PrivateKeyEntryDecoder<PUB extends PublicKey, PRV extends PrivateKey> - extends KeyEntryResolver<PUB, PRV>, PrivateKeyEntryResolver { - - @Override - default PrivateKey resolve(String keyType, byte[] keyData) throws IOException, GeneralSecurityException { - ValidateUtils.checkNotNullAndNotEmpty(keyType, "No key type provided"); - Collection<String> supported = getSupportedTypeNames(); - if ((GenericUtils.size(supported) > 0) && supported.contains(keyType)) { - return decodePrivateKey(FilePasswordProvider.EMPTY, keyData); - } - - throw new InvalidKeySpecException("resolve(" + keyType + ") not in listed supported types: " + supported); - } - - /** - * @param passwordProvider The {@link FilePasswordProvider} to use - * in case the data is encrypted - may be {@code null} if no encrypted - * data is expected - * @param keyData The key data bytes in {@code OpenSSH} format (after - * BASE64 decoding) - ignored if {@code null}/empty - * @return The decoded {@link PrivateKey} - or {@code null} if no data - * @throws IOException If failed to decode the key - * @throws GeneralSecurityException If failed to generate the key - */ - default PRV decodePrivateKey(FilePasswordProvider passwordProvider, byte... keyData) - throws IOException, GeneralSecurityException { - return decodePrivateKey(passwordProvider, keyData, 0, NumberUtils.length(keyData)); - } - - default PRV decodePrivateKey(FilePasswordProvider passwordProvider, byte[] keyData, int offset, int length) - throws IOException, GeneralSecurityException { - if (length <= 0) { - return null; - } - - try (InputStream stream = new ByteArrayInputStream(keyData, offset, length)) { - return decodePrivateKey(passwordProvider, stream); - } - } - - default PRV decodePrivateKey(FilePasswordProvider passwordProvider, InputStream keyData) - throws IOException, GeneralSecurityException { - // the actual data is preceded by a string that repeats the key type - String type = KeyEntryResolver.decodeString(keyData); - if (GenericUtils.isEmpty(type)) { - throw new StreamCorruptedException("Missing key type string"); - } - - Collection<String> supported = getSupportedTypeNames(); - if (GenericUtils.isEmpty(supported) || (!supported.contains(type))) { - throw new InvalidKeySpecException("Reported key type (" + type + ") not in supported list: " + supported); - } - - return decodePrivateKey(type, passwordProvider, keyData); - } - - /** - * @param keyType The reported / encode key type - * @param passwordProvider The {@link FilePasswordProvider} to use - * in case the data is encrypted - may be {@code null} if no encrypted - * data is expected - * @param keyData The key data bytes stream positioned after the key type decoding - * and making sure it is one of the supported types - * @return The decoded {@link PrivateKey} - * @throws IOException If failed to read from the data stream - * @throws GeneralSecurityException If failed to generate the key - */ - PRV decodePrivateKey(String keyType, FilePasswordProvider passwordProvider, InputStream keyData) - throws IOException, GeneralSecurityException; - - /** - * Encodes the {@link PrivateKey} using the {@code OpenSSH} format - same - * one used by the {@code decodePublicKey} method(s) - * - * @param s The {@link OutputStream} to write the data to - * @param key The {@link PrivateKey} - may not be {@code null} - * @return The key type value - one of the {@link #getSupportedTypeNames()} or - * {@code null} if encoding not supported - * @throws IOException If failed to generate the encoding - */ - default String encodePrivateKey(OutputStream s, PRV key) throws IOException { - Objects.requireNonNull(key, "No private key provided"); - return null; - } - - default boolean isPublicKeyRecoverySupported() { - return false; - } - - /** - * Attempts to recover the public key given the private one - * - * @param prvKey The {@link PrivateKey} - * @return The recovered {@link PublicKey} - {@code null} if cannot recover it - * @throws GeneralSecurityException If failed to generate the public key - */ - default PUB recoverPublicKey(PRV prvKey) throws GeneralSecurityException { - return null; - } -} http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/config/keys/PrivateKeyEntryResolver.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/PrivateKeyEntryResolver.java b/sshd-core/src/main/java/org/apache/sshd/common/config/keys/PrivateKeyEntryResolver.java deleted file mode 100644 index 1e4c91e..0000000 --- a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/PrivateKeyEntryResolver.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.apache.sshd.common.config.keys; - -import java.io.IOException; -import java.security.GeneralSecurityException; -import java.security.PrivateKey; -import java.security.spec.InvalidKeySpecException; - -/** - * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> - */ -@FunctionalInterface -public interface PrivateKeyEntryResolver { - /** - * A resolver that ignores all input - */ - PrivateKeyEntryResolver IGNORING = new PrivateKeyEntryResolver() { - @Override - public PrivateKey resolve(String keyType, byte[] keyData) throws IOException, GeneralSecurityException { - return null; - } - - @Override - public String toString() { - return "IGNORING"; - } - }; - - /** - * A resolver that fails on all input - */ - PrivateKeyEntryResolver FAILING = new PrivateKeyEntryResolver() { - @Override - public PrivateKey resolve(String keyType, byte[] keyData) throws IOException, GeneralSecurityException { - throw new InvalidKeySpecException("Failing resolver on key type=" + keyType); - } - - @Override - public String toString() { - return "FAILING"; - } - }; - - /** - * @param keyType The {@code OpenSSH} reported key type - * @param keyData The {@code OpenSSH} encoded key data - * @return The extracted {@link PrivateKey} - ignored if {@code null} - * @throws IOException If failed to parse the key data - * @throws GeneralSecurityException If failed to generate the key - */ - PrivateKey resolve(String keyType, byte[] keyData) throws IOException, GeneralSecurityException; -} http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/config/keys/PublicKeyEntry.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/PublicKeyEntry.java b/sshd-core/src/main/java/org/apache/sshd/common/config/keys/PublicKeyEntry.java deleted file mode 100644 index 1db3d2b..0000000 --- a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/PublicKeyEntry.java +++ /dev/null @@ -1,286 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.apache.sshd.common.config.keys; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.Serializable; -import java.io.StreamCorruptedException; -import java.nio.file.Path; -import java.security.GeneralSecurityException; -import java.security.PublicKey; -import java.security.spec.InvalidKeySpecException; -import java.util.Arrays; -import java.util.Base64; -import java.util.Objects; - -import org.apache.sshd.common.util.GenericUtils; -import org.apache.sshd.common.util.NumberUtils; - -/** - * <P>Represents a {@link PublicKey} whose data is formatted according to - * the <A HREF="http://en.wikibooks.org/wiki/OpenSSH">OpenSSH</A> format:</P> - * - * <PRE> - * <key-type> <base64-encoded-public-key-data> - * </PRE> - * - * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> - */ -public class PublicKeyEntry implements Serializable { - - /** - * Character used to denote a comment line in the keys file - */ - public static final char COMMENT_CHAR = '#'; - - - /** - * Standard folder name used by OpenSSH to hold key files - */ - public static final String STD_KEYFILE_FOLDER_NAME = ".ssh"; - - private static final long serialVersionUID = -585506072687602760L; - - private String keyType; - private byte[] keyData; - - public PublicKeyEntry() { - super(); - } - - public PublicKeyEntry(String keyType, byte... keyData) { - this.keyType = keyType; - this.keyData = keyData; - } - - public String getKeyType() { - return keyType; - } - - public void setKeyType(String value) { - this.keyType = value; - } - - public byte[] getKeyData() { - return keyData; - } - - public void setKeyData(byte[] value) { - this.keyData = value; - } - - /** - * @param fallbackResolver The {@link PublicKeyEntryResolver} to consult if - * none of the built-in ones can be used. If {@code null} and no built-in - * resolver can be used then an {@link InvalidKeySpecException} is thrown. - * @return The resolved {@link PublicKey} - or {@code null} if could not be - * resolved. <B>Note:</B> may be called only after key type and data bytes - * have been set or exception(s) may be thrown - * @throws IOException If failed to decode the key - * @throws GeneralSecurityException If failed to generate the key - */ - public PublicKey resolvePublicKey(PublicKeyEntryResolver fallbackResolver) throws IOException, GeneralSecurityException { - String kt = getKeyType(); - PublicKeyEntryResolver decoder = KeyUtils.getPublicKeyEntryDecoder(kt); - if (decoder == null) { - decoder = fallbackResolver; - } - if (decoder == null) { - throw new InvalidKeySpecException("No decoder available for key type=" + kt); - } - - return decoder.resolve(kt, getKeyData()); - } - - /** - * @param sb The {@link Appendable} instance to encode the data into - * @param fallbackResolver The {@link PublicKeyEntryResolver} to consult if - * none of the built-in ones can be used. If {@code null} and no built-in - * resolver can be used then an {@link InvalidKeySpecException} is thrown. - * @return The {@link PublicKey} or {@code null} if could not resolve it - * @throws IOException If failed to decode/encode the key - * @throws GeneralSecurityException If failed to generate the key - * @see #resolvePublicKey(PublicKeyEntryResolver) - */ - public PublicKey appendPublicKey(Appendable sb, PublicKeyEntryResolver fallbackResolver) throws IOException, GeneralSecurityException { - PublicKey key = resolvePublicKey(fallbackResolver); - if (key != null) { - appendPublicKeyEntry(sb, key); - } - return key; - } - - @Override - public int hashCode() { - return Objects.hashCode(getKeyType()) + Arrays.hashCode(getKeyData()); - } - - /* - * In case some derived class wants to define some "extended" equality - * without having to repeat this code - */ - protected boolean isEquivalent(PublicKeyEntry e) { - if (this == e) { - return true; - } - return Objects.equals(getKeyType(), e.getKeyType()) - && Arrays.equals(getKeyData(), e.getKeyData()); - } - - @Override - public boolean equals(Object obj) { - if (obj == null) { - return false; - } - if (this == obj) { - return true; - } - if (getClass() != obj.getClass()) { - return false; - } - return isEquivalent((PublicKeyEntry) obj); - } - - @Override - public String toString() { - byte[] data = getKeyData(); - Base64.Encoder encoder = Base64.getEncoder(); - return getKeyType() + " " + (NumberUtils.isEmpty(data) ? "<no-key>" : encoder.encodeToString(data)); - } - - /** - * @param encData Assumed to contain at least {@code key-type base64-data} - * (anything beyond the BASE64 data is ignored) - ignored if {@code null}/empty - * @return A {@link PublicKeyEntry} or {@code null} if no data - * @throws IllegalArgumentException if bad format found - * @see #parsePublicKeyEntry(PublicKeyEntry, String) - */ - public static PublicKeyEntry parsePublicKeyEntry(String encData) throws IllegalArgumentException { - String data = GenericUtils.replaceWhitespaceAndTrim(encData); - if (GenericUtils.isEmpty(data)) { - return null; - } else { - return parsePublicKeyEntry(new PublicKeyEntry(), data); - } - } - - /** - * @param <E> The generic entry type - * @param entry The {@link PublicKeyEntry} whose contents are to be - * updated - ignored if {@code null} - * @param encData Assumed to contain at least {@code key-type base64-data} (anything - * beyond the BASE64 data is ignored) - ignored if {@code null}/empty - * @return The updated entry instance - * @throws IllegalArgumentException if bad format found - */ - public static <E extends PublicKeyEntry> E parsePublicKeyEntry(E entry, String encData) throws IllegalArgumentException { - String data = GenericUtils.replaceWhitespaceAndTrim(encData); - if (GenericUtils.isEmpty(data) || (entry == null)) { - return entry; - } - - int startPos = data.indexOf(' '); - if (startPos <= 0) { - throw new IllegalArgumentException("Bad format (no key data delimiter): " + data); - } - - int endPos = data.indexOf(' ', startPos + 1); - if (endPos <= startPos) { // OK if no continuation beyond the BASE64 encoded data - endPos = data.length(); - } - - String keyType = data.substring(0, startPos); - String b64Data = data.substring(startPos + 1, endPos).trim(); - Base64.Decoder decoder = Base64.getDecoder(); - byte[] keyData = decoder.decode(b64Data); - if (NumberUtils.isEmpty(keyData)) { - throw new IllegalArgumentException("Bad format (no BASE64 key data): " + data); - } - - entry.setKeyType(keyType); - entry.setKeyData(keyData); - return entry; - } - - /** - * @param key The {@link PublicKey} - * @return The {@code OpenSSH} encoded data - * @throws IllegalArgumentException If failed to encode - * @see #appendPublicKeyEntry(Appendable, PublicKey) - */ - public static String toString(PublicKey key) throws IllegalArgumentException { - try { - return appendPublicKeyEntry(new StringBuilder(Byte.MAX_VALUE), key).toString(); - } catch (IOException e) { - throw new IllegalArgumentException("Failed (" + e.getClass().getSimpleName() + ") to encode: " + e.getMessage(), e); - } - } - - /** - * Encodes a public key data the same way as the {@link #parsePublicKeyEntry(String)} expects it - * - * @param <A> The generic appendable class - * @param sb The {@link Appendable} instance to encode the data into - * @param key The {@link PublicKey} - ignored if {@code null} - * @return The updated appendable instance - * @throws IOException If failed to append the data - */ - public static <A extends Appendable> A appendPublicKeyEntry(A sb, PublicKey key) throws IOException { - if (key == null) { - return sb; - } - - @SuppressWarnings("unchecked") - PublicKeyEntryDecoder<PublicKey, ?> decoder = - (PublicKeyEntryDecoder<PublicKey, ?>) KeyUtils.getPublicKeyEntryDecoder(key); - if (decoder == null) { - throw new StreamCorruptedException("Cannot retrieve decoder for key=" + key.getAlgorithm()); - } - - try (ByteArrayOutputStream s = new ByteArrayOutputStream(Byte.MAX_VALUE)) { - String keyType = decoder.encodePublicKey(s, key); - byte[] bytes = s.toByteArray(); - Base64.Encoder encoder = Base64.getEncoder(); - String b64Data = encoder.encodeToString(bytes); - sb.append(keyType).append(' ').append(b64Data); - } - - return sb; - } - - private static final class LazyDefaultKeysFolderHolder { - private static final Path PATH = - IdentityUtils.getUserHomeFolder().resolve(STD_KEYFILE_FOLDER_NAME); - - private LazyDefaultKeysFolderHolder() { - throw new UnsupportedOperationException("No instance allowed"); - } - } - - /** - * @return The default OpenSSH folder used to hold key files - e.g., - * {@code known_hosts}, {@code authorized_keys}, etc. - */ - @SuppressWarnings("synthetic-access") - public static Path getDefaultKeysFolderPath() { - return LazyDefaultKeysFolderHolder.PATH; - } -} http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/config/keys/PublicKeyEntryDecoder.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/PublicKeyEntryDecoder.java b/sshd-core/src/main/java/org/apache/sshd/common/config/keys/PublicKeyEntryDecoder.java deleted file mode 100644 index 7462e4a..0000000 --- a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/PublicKeyEntryDecoder.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.apache.sshd.common.config.keys; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.StreamCorruptedException; -import java.security.GeneralSecurityException; -import java.security.PrivateKey; -import java.security.PublicKey; -import java.security.spec.InvalidKeySpecException; -import java.util.Collection; - -import org.apache.sshd.common.util.GenericUtils; -import org.apache.sshd.common.util.NumberUtils; -import org.apache.sshd.common.util.ValidateUtils; - -/** - * Represents a decoder of an {@code OpenSSH} encoded key data - * - * @param <PUB> Type of {@link PublicKey} - * @param <PRV> Type of {@link PrivateKey} - * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> - */ -public interface PublicKeyEntryDecoder<PUB extends PublicKey, PRV extends PrivateKey> - extends KeyEntryResolver<PUB, PRV>, PublicKeyEntryResolver { - - @Override - default PublicKey resolve(String keyType, byte[] keyData) throws IOException, GeneralSecurityException { - ValidateUtils.checkNotNullAndNotEmpty(keyType, "No key type provided"); - Collection<String> supported = getSupportedTypeNames(); - if ((GenericUtils.size(supported) > 0) && supported.contains(keyType)) { - return decodePublicKey(keyData); - } - - throw new InvalidKeySpecException("resolve(" + keyType + ") not in listed supported types: " + supported); - } - - /** - * @param keyData The key data bytes in {@code OpenSSH} format (after - * BASE64 decoding) - ignored if {@code null}/empty - * @return The decoded {@link PublicKey} - or {@code null} if no data - * @throws IOException If failed to decode the key - * @throws GeneralSecurityException If failed to generate the key - */ - default PUB decodePublicKey(byte... keyData) throws IOException, GeneralSecurityException { - return decodePublicKey(keyData, 0, NumberUtils.length(keyData)); - } - - default PUB decodePublicKey(byte[] keyData, int offset, int length) throws IOException, GeneralSecurityException { - if (length <= 0) { - return null; - } - - try (InputStream stream = new ByteArrayInputStream(keyData, offset, length)) { - return decodePublicKey(stream); - } - } - - default PUB decodePublicKey(InputStream keyData) throws IOException, GeneralSecurityException { - // the actual data is preceded by a string that repeats the key type - String type = KeyEntryResolver.decodeString(keyData); - if (GenericUtils.isEmpty(type)) { - throw new StreamCorruptedException("Missing key type string"); - } - - Collection<String> supported = getSupportedTypeNames(); - if (GenericUtils.isEmpty(supported) || (!supported.contains(type))) { - throw new InvalidKeySpecException("Reported key type (" + type + ") not in supported list: " + supported); - } - - return decodePublicKey(type, keyData); - } - - /** - * @param keyType The reported / encode key type - * @param keyData The key data bytes stream positioned after the key type decoding - * and making sure it is one of the supported types - * @return The decoded {@link PublicKey} - * @throws IOException If failed to read from the data stream - * @throws GeneralSecurityException If failed to generate the key - */ - PUB decodePublicKey(String keyType, InputStream keyData) throws IOException, GeneralSecurityException; - - /** - * Encodes the {@link PublicKey} using the {@code OpenSSH} format - same - * one used by the {@code decodePublicKey} method(s) - * - * @param s The {@link OutputStream} to write the data to - * @param key The {@link PublicKey} - may not be {@code null} - * @return The key type value - one of the {@link #getSupportedTypeNames()} - * @throws IOException If failed to generate the encoding - */ - String encodePublicKey(OutputStream s, PUB key) throws IOException; -} http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/config/keys/PublicKeyEntryResolver.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/PublicKeyEntryResolver.java b/sshd-core/src/main/java/org/apache/sshd/common/config/keys/PublicKeyEntryResolver.java deleted file mode 100644 index e5eb0ed..0000000 --- a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/PublicKeyEntryResolver.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.apache.sshd.common.config.keys; - -import java.io.IOException; -import java.security.GeneralSecurityException; -import java.security.PublicKey; -import java.security.spec.InvalidKeySpecException; - -/** - * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> - */ -@FunctionalInterface -public interface PublicKeyEntryResolver { - /** - * A resolver that ignores all input - */ - PublicKeyEntryResolver IGNORING = new PublicKeyEntryResolver() { - @Override - public PublicKey resolve(String keyType, byte[] keyData) throws IOException, GeneralSecurityException { - return null; - } - - @Override - public String toString() { - return "IGNORING"; - } - }; - - /** - * A resolver that fails on all input - */ - PublicKeyEntryResolver FAILING = new PublicKeyEntryResolver() { - @Override - public PublicKey resolve(String keyType, byte[] keyData) throws IOException, GeneralSecurityException { - throw new InvalidKeySpecException("Failing resolver on key type=" + keyType); - } - - @Override - public String toString() { - return "FAILING"; - } - }; - - /** - * @param keyType The {@code OpenSSH} reported key type - * @param keyData The {@code OpenSSH} encoded key data - * @return The extracted {@link PublicKey} - ignored if {@code null} - * @throws IOException If failed to parse the key data - * @throws GeneralSecurityException If failed to generate the key - */ - PublicKey resolve(String keyType, byte[] keyData) throws IOException, GeneralSecurityException; -} http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/config/keys/impl/AbstractIdentityResourceLoader.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/impl/AbstractIdentityResourceLoader.java b/sshd-core/src/main/java/org/apache/sshd/common/config/keys/impl/AbstractIdentityResourceLoader.java deleted file mode 100644 index a2412bd..0000000 --- a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/impl/AbstractIdentityResourceLoader.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.sshd.common.config.keys.impl; - -import java.security.PrivateKey; -import java.security.PublicKey; -import java.util.Collection; -import java.util.Objects; - -import org.apache.sshd.common.config.keys.IdentityResourceLoader; -import org.apache.sshd.common.util.ValidateUtils; -import org.apache.sshd.common.util.logging.AbstractLoggingBean; - -/** - * @param <PUB> Generic public key type - * @param <PRV> Generic private key type - * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> - */ -public abstract class AbstractIdentityResourceLoader<PUB extends PublicKey, PRV extends PrivateKey> - extends AbstractLoggingBean - implements IdentityResourceLoader<PUB, PRV> { - private final Class<PUB> pubType; - private final Class<PRV> prvType; - private final Collection<String> names; - - protected AbstractIdentityResourceLoader(Class<PUB> pubType, Class<PRV> prvType, Collection<String> names) { - this.pubType = Objects.requireNonNull(pubType, "No public key type specified"); - this.prvType = Objects.requireNonNull(prvType, "No private key type specified"); - this.names = ValidateUtils.checkNotNullAndNotEmpty(names, "No type names provided"); - } - - @Override - public final Class<PUB> getPublicKeyType() { - return pubType; - } - - @Override - public final Class<PRV> getPrivateKeyType() { - return prvType; - } - - @Override - public Collection<String> getSupportedTypeNames() { - return names; - } -} http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/config/keys/impl/AbstractKeyEntryResolver.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/impl/AbstractKeyEntryResolver.java b/sshd-core/src/main/java/org/apache/sshd/common/config/keys/impl/AbstractKeyEntryResolver.java deleted file mode 100644 index 7afa3a6..0000000 --- a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/impl/AbstractKeyEntryResolver.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.apache.sshd.common.config.keys.impl; - -import java.security.GeneralSecurityException; -import java.security.KeyFactory; -import java.security.PrivateKey; -import java.security.PublicKey; -import java.security.spec.KeySpec; -import java.util.Collection; - -import org.apache.sshd.common.config.keys.KeyEntryResolver; - -/** - * @param <PUB> Type of {@link PublicKey} - * @param <PRV> Type of {@link PrivateKey} - * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> - */ -public abstract class AbstractKeyEntryResolver<PUB extends PublicKey, PRV extends PrivateKey> - extends AbstractIdentityResourceLoader<PUB, PRV> - implements KeyEntryResolver<PUB, PRV> { - protected AbstractKeyEntryResolver(Class<PUB> pubType, Class<PRV> prvType, Collection<String> names) { - super(pubType, prvType, names); - } - - public PUB generatePublicKey(KeySpec keySpec) throws GeneralSecurityException { - KeyFactory factory = getKeyFactoryInstance(); - Class<PUB> keyType = getPublicKeyType(); - return keyType.cast(factory.generatePublic(keySpec)); - } - - public PRV generatePrivateKey(KeySpec keySpec) throws GeneralSecurityException { - KeyFactory factory = getKeyFactoryInstance(); - Class<PRV> keyType = getPrivateKeyType(); - return keyType.cast(factory.generatePrivate(keySpec)); - } - - @Override - public String toString() { - return getPublicKeyType().getSimpleName() + ": " + getSupportedTypeNames(); - } -}
