You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by lg...@apache.org on 2015/06/21 09:24:44 UTC

mina-sshd git commit: [SSHD-494] Convert ECCurves class into an enum

Repository: mina-sshd
Updated Branches:
  refs/heads/master 8c8541e32 -> 189d8cb90


[SSHD-494] Convert ECCurves class into an enum


Project: http://git-wip-us.apache.org/repos/asf/mina-sshd/repo
Commit: http://git-wip-us.apache.org/repos/asf/mina-sshd/commit/189d8cb9
Tree: http://git-wip-us.apache.org/repos/asf/mina-sshd/tree/189d8cb9
Diff: http://git-wip-us.apache.org/repos/asf/mina-sshd/diff/189d8cb9

Branch: refs/heads/master
Commit: 189d8cb90464f41662d6c7018b1c106296f7fe39
Parents: 8c8541e
Author: Lyor Goldstein <lg...@vmware.com>
Authored: Sun Jun 21 10:24:33 2015 +0300
Committer: Lyor Goldstein <lg...@vmware.com>
Committed: Sun Jun 21 10:24:33 2015 +0300

----------------------------------------------------------------------
 .../java/org/apache/sshd/client/SshKeyScan.java |  11 +-
 .../org/apache/sshd/common/NamedResource.java   |  24 ++
 .../sshd/common/cipher/BuiltinCiphers.java      |  16 +-
 .../org/apache/sshd/common/cipher/ECCurves.java | 348 ++++++++++---------
 .../common/compression/BuiltinCompressions.java |  13 +-
 .../config/keys/ECDSAPublicKeyEntryDecoder.java |  34 +-
 .../sshd/common/config/keys/KeyUtils.java       |   8 +-
 .../sshd/common/digest/BuiltinDigests.java      |  17 +-
 .../io/BuiltinIoServiceFactoryFactories.java    |  15 +-
 .../sshd/common/kex/BuiltinDHFactories.java     |  18 +-
 .../java/org/apache/sshd/common/kex/ECDH.java   |   9 +-
 .../common/keyprovider/KeyPairProvider.java     |   6 +-
 .../org/apache/sshd/common/mac/BuiltinMacs.java |  18 +-
 .../common/signature/BuiltinSignatures.java     |  18 +-
 .../sshd/common/signature/SignatureECDSA.java   |   3 +-
 .../apache/sshd/common/util/buffer/Buffer.java  |  57 +--
 .../sshd/server/forward/ForwardingFilter.java   |  12 +-
 .../apache/sshd/common/cipher/ECCurvesTest.java | 105 ++++++
 .../sshd/common/config/keys/KeyUtilsTest.java   |  10 +-
 .../signature/SignatureECDSAFactoryTest.java    |   6 +-
 20 files changed, 411 insertions(+), 337 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/189d8cb9/sshd-core/src/main/java/org/apache/sshd/client/SshKeyScan.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/SshKeyScan.java b/sshd-core/src/main/java/org/apache/sshd/client/SshKeyScan.java
index 8e8baa3..2d0d278 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/SshKeyScan.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/SshKeyScan.java
@@ -474,18 +474,13 @@ public class SshKeyScan extends AbstractSimplifiedLog
             }
 
             List<KeyPair> kps = new ArrayList<KeyPair>(ECCurves.NAMES.size());
-            for (String curveName : ECCurves.NAMES) {
-                Integer keySize = ECCurves.getCurveSize(curveName);
-                if (keySize == null) {
-                    throw new InvalidKeySpecException("Unknown curve: " + curveName);
-                }
-
+            for (ECCurves curve : ECCurves.VALUES) {
+                String curveName = curve.getName();
                 if (isEnabled(Level.FINER)) {
                     log(Level.FINER, "Generate key pair for curve=" + curveName);
                 }
 
-                String keyName = ECCurves.ECDSA_SHA2_PREFIX + curveName;
-                kps.add(KeyUtils.generateKeyPair(keyName, keySize.intValue()));
+                kps.add(KeyUtils.generateKeyPair(curve.getKeyType(), curve.getKeySize()));
             }
             
             return kps;

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/189d8cb9/sshd-core/src/main/java/org/apache/sshd/common/NamedResource.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/NamedResource.java b/sshd-core/src/main/java/org/apache/sshd/common/NamedResource.java
index b38670f..e1c2287 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/NamedResource.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/NamedResource.java
@@ -92,5 +92,29 @@ public interface NamedResource {
         public static String getNames(Collection<? extends NamedResource> resources) {
             return GenericUtils.join(getNameList(resources), ',');
         }
+        
+        /**
+         * @param name Name of the resource - ignored if {@code null}/empty
+         * @param c The {@link Comparator} to decide whether the {@link NamedResource#getName()}
+         * matches the <tt>name</tt> parameter
+         * @param resources The {@link NamedResource} to check - ignored if {@code null}/empty
+         * @return The <U>first</U> resource whose name matches the parameter - {@code null}
+         * if no match found
+         */
+        public static <R extends NamedResource> R findByName(String name, Comparator<? super String> c, Collection<? extends R> resources) {
+            if (GenericUtils.isEmpty(name) || GenericUtils.isEmpty(resources)) {
+                return null;
+            }
+            
+            for (R r : resources) {
+                String n = r.getName();
+                int nRes = c.compare(name, n);
+                if (nRes == 0) {
+                    return r;
+                }
+            }
+            
+            return null;
+        }
     }
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/189d8cb9/sshd-core/src/main/java/org/apache/sshd/common/cipher/BuiltinCiphers.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/cipher/BuiltinCiphers.java b/sshd-core/src/main/java/org/apache/sshd/common/cipher/BuiltinCiphers.java
index 810b2b2..991c74f 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/cipher/BuiltinCiphers.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/cipher/BuiltinCiphers.java
@@ -250,22 +250,12 @@ public enum BuiltinCiphers implements CipherFactory {
     }
 
     /**
-     * @param n The factory name - ignored if {@code null}/empty
+     * @param name The factory name - ignored if {@code null}/empty
      * @return The matching {@link BuiltinCiphers} whose factory name matches
      * (case <U>insensitive</U>) the provided name - {@code null} if no match
      */
-    public static BuiltinCiphers fromFactoryName(String n) {
-        if (GenericUtils.isEmpty(n)) {
-            return null;
-        }
-
-        for (BuiltinCiphers c : VALUES) {
-            if (n.equalsIgnoreCase(c.getName())) {
-                return c;
-            }
-        }
-
-        return null;
+    public static BuiltinCiphers fromFactoryName(String name) {
+        return NamedResource.Utils.findByName(name, String.CASE_INSENSITIVE_ORDER, VALUES);
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/189d8cb9/sshd-core/src/main/java/org/apache/sshd/common/cipher/ECCurves.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/cipher/ECCurves.java b/sshd-core/src/main/java/org/apache/sshd/common/cipher/ECCurves.java
index 6f0c46e..0812eaf 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/cipher/ECCurves.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/cipher/ECCurves.java
@@ -24,15 +24,17 @@ import java.security.spec.ECFieldFp;
 import java.security.spec.ECParameterSpec;
 import java.security.spec.ECPoint;
 import java.security.spec.EllipticCurve;
-import java.util.ArrayList;
 import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.TreeMap;
+import java.util.EnumSet;
+import java.util.Set;
+import java.util.TreeSet;
 
+import org.apache.sshd.common.NamedResource;
+import org.apache.sshd.common.OptionalFeature;
 import org.apache.sshd.common.digest.BuiltinDigests;
 import org.apache.sshd.common.digest.Digest;
 import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.common.util.SecurityUtils;
 import org.apache.sshd.common.util.ValidateUtils;
 
 /**
@@ -40,165 +42,219 @@ import org.apache.sshd.common.util.ValidateUtils;
  *
  * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
  */
-public class ECCurves {
+public enum ECCurves implements NamedResource, OptionalFeature {
+    nistp256(Constants.NISTP256,
+             new ECParameterSpec(
+                 new EllipticCurve(
+                     new ECFieldFp(new BigInteger("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF", 16)),
+                     new BigInteger("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC", 16),
+                     new BigInteger("5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", 16)),
+                 new ECPoint(
+                     new BigInteger("6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296", 16),
+                     new BigInteger("4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5", 16)),
+                  new BigInteger("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551", 16),
+                  1),
+             32) {
+            @Override
+            public Digest getDigestForParams() {
+                return BuiltinDigests.sha256.create();
+            }
+        },
+    nistp384(Constants.NISTP384,
+             new ECParameterSpec(
+                 new EllipticCurve(
+                     new ECFieldFp(new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF", 16)),
+                     new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC", 16),
+                     new BigInteger("B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF", 16)),
+                 new ECPoint(
+                     new BigInteger("AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7", 16),
+                     new BigInteger("3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F", 16)),
+                     new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973", 16),
+                    1),
+             48) {
+            @Override
+            public Digest getDigestForParams() {
+                return BuiltinDigests.sha384.create();
+            }
+        },
+    nistp521(Constants.NISTP521,
+             new ECParameterSpec(
+                 new EllipticCurve(
+                     new ECFieldFp(new BigInteger("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 16)),
+                     new BigInteger("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC", 16),
+                     new BigInteger("0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00", 16)),
+                 new ECPoint(
+                     new BigInteger("00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66", 16),
+                     new BigInteger("011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650", 16)),
+                     new BigInteger("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409", 16),
+                    1),
+             66) {
+            @Override
+            public Digest getDigestForParams() {
+                return BuiltinDigests.sha512.create();
+            }
+        };
+
+    private final String    name, keyType;
+
+    @Override   // The curve name
+    public final String getName() {
+        return name;
+    }
+
     /**
-     * Standard prefix of NISTP key types when encoded
+     * @return The standard key type used to represent this curve
      */
-    public static final String ECDSA_SHA2_PREFIX = "ecdsa-sha2-";
+    public final String getKeyType() {
+        return keyType;
+    }
+
+    @Override
+    public final boolean isSupported() {
+        return SecurityUtils.hasEcc();
+    }
 
-    public static final String NISTP256 = "nistp256";
-    public static final String NISTP384 = "nistp384";
-    public static final String NISTP521 = "nistp521";
+    private final ECParameterSpec params;
+    public final ECParameterSpec getParameters() {
+        return params;
+    }
 
+    private final int keySize, numOctets;
 
-    public static String getCurveName(ECParameterSpec params) {
-        int fieldSize = getCurveSize(params);
-        final String curveName = getCurveName(fieldSize);
-        if (GenericUtils.isEmpty(curveName)) {
-            throw new RuntimeException("invalid curve size " + fieldSize);
-        }
-        return curveName;
+    /**
+     * @return The size (in bits) of the key
+     */
+    public final int getKeySize() {
+        return keySize;
     }
 
     /**
-     * Key=curve name, value=num. of bits
+     * @return The number of octets used to represent the point(s) for the curve
      */
-    private static final Map<String,Integer> CURVENAME2SIZE =
-            Collections.unmodifiableMap(new TreeMap<String,Integer>(String.CASE_INSENSITIVE_ORDER) {
-                private static final long serialVersionUID = 1L;    // we're not serializing it
-                
-                {
-                    put(NISTP256, Integer.valueOf(256));
-                    put(NISTP384, Integer.valueOf(384));
-                    put(NISTP521, Integer.valueOf(521));
-                }
-        
-            });
+    public final int getNumPointOctets() {
+        return numOctets;
+    }
 
     /**
-     * An un-modifiable {@link List} of all the known curve names
+     * @return The {@link Digest} to use when hashing the curve's parameters
      */
-    @SuppressWarnings("synthetic-access")
-    public static final List<String> NAMES =
-            Collections.unmodifiableList(new ArrayList<String>(CURVENAME2SIZE.size()) {
-                private static final long serialVersionUID = 1L;    // we're not serializing it
-                
-                {
-                    addAll(CURVENAME2SIZE.keySet());
-                    Collections.sort(this); // as a courtesy
-                }
-            });
+    public abstract Digest getDigestForParams();
+
+    ECCurves(String name, ECParameterSpec params, int numOctets) {
+        this.name = ValidateUtils.checkNotNullAndNotEmpty(name, "No curve name", GenericUtils.EMPTY_OBJECT_ARRAY);
+        this.keyType = Constants.ECDSA_SHA2_PREFIX + name;
+        this.params = ValidateUtils.checkNotNull(params, "No EC params for %s", name);
+        this.keySize = getCurveSize(params);
+        this.numOctets = numOctets;
+    }
+    
+    /**
+     * A {@link Set} of all the known curves
+     */
+    public static final Set<ECCurves> VALUES =
+            Collections.unmodifiableSet(EnumSet.allOf(ECCurves.class));
 
     /**
-     * An un-modifiable {@link List} of all the known curve types according to {@code OpenSSH}
+     * A {@link Set} of all the known curves names 
      */
-    public static final List<String> TYPES =
-            Collections.unmodifiableList(new ArrayList<String>(CURVENAME2SIZE.size()) {
+    public static final Set<String> NAMES =
+            Collections.unmodifiableSet(new TreeSet<String>(String.CASE_INSENSITIVE_ORDER) {
                 private static final long serialVersionUID = 1L;    // we're not serializing it
                 
                 {
-                    for (String n : NAMES) {
-                        add(ECDSA_SHA2_PREFIX + n);
+                    for (ECCurves c : VALUES) {
+                        add(c.getName());
                     }
-
-                    Collections.sort(this); // as a courtesy
                 }
             });
+
     /**
-     * An un-modifiable {@link List} of all the known curve sizes
+     * A {@link Set} of all the known curves key types 
      */
-    @SuppressWarnings("synthetic-access")
-    public static final List<Integer> SIZES =
-            Collections.unmodifiableList(new ArrayList<Integer>(CURVENAME2SIZE.size()) {
-                    private static final long serialVersionUID = 1L;    // we're not serializing it
+    public static final Set<String> KEY_TYPES =
+            Collections.unmodifiableSet(new TreeSet<String>(String.CASE_INSENSITIVE_ORDER) {
+                private static final long serialVersionUID = 1L;    // we're not serializing it
                 
-                    {
-                        addAll(CURVENAME2SIZE.values());
-                        Collections.sort(this); // as a courtesy
+                {
+                    for (ECCurves c : VALUES) {
+                        add(c.getKeyType());
                     }
+                }
             });
-    
+
     /**
-     * @param name The curve name - ignored if {@code null}/empty
-     * @return The curve size - {@code null} if unknown curve
+     * @param type The key type value - ignored if {@code null}/empty
+     * @return The matching {@link ECCurves} constant - {@code null} if
+     * no match found case <U>insensitive</U>
      */
-    public static Integer getCurveSize(String name) {
-        if (GenericUtils.isEmpty(name)) {
+    public static ECCurves fromKeyType(String type) {
+        if (GenericUtils.isEmpty(type)) {
             return null;
-        } else {
-            return CURVENAME2SIZE.get(name);
         }
+        
+        for (ECCurves c : VALUES) {
+            if (type.equalsIgnoreCase(c.getKeyType())) {
+                return c;
+            }
+        }
+        
+        return null;
     }
 
     /**
-     * Key=num. of bits, value=curve name
+     * @param name The curve name (case <U>insensitive</U> - ignored if
+     * {@code null}/empty
+     * @return The matching {@link ECCurves} instance - {@code null} if no
+     * match found
      */
-    @SuppressWarnings("synthetic-access")
-    private static final Map<Integer, String> SIZE2CURVENAME = 
-            Collections.unmodifiableMap(new TreeMap<Integer, String>() {
-                private static final long serialVersionUID = 1L;    // we're not serializing it
-        
-                {
-                    for (Map.Entry<String,Integer> e : CURVENAME2SIZE.entrySet()) {
-                        String name = e.getKey();
-                        Integer size = e.getValue();
-                        put(size, name);
-                    }
-                }
-            });
-
+    public static ECCurves fromCurveName(String name) {
+        return NamedResource.Utils.findByName(name, String.CASE_INSENSITIVE_ORDER, VALUES);
+    }
+    
     /**
-     * @param fieldSize The key size in bits
-     * @return The name of the curve - {@code null/empty} if no match found
+     * @param params The curve's {@link ECParameterSpec} - ignored if {@code null}
+     * @return The matching {@link ECCurves} value - {@code null} if no match found
+     * @see #getCurveSize(ECParameterSpec)
+     * @see #fromCurveSize(int)
      */
-    public static String getCurveName(int fieldSize) {
-        return SIZE2CURVENAME.get(Integer.valueOf(fieldSize));
+    public static ECCurves fromCurveParameters(ECParameterSpec params) {
+        if (params == null) {
+            return null;
+        } else {
+            return fromCurveSize(getCurveSize(params));
+        }
     }
-
-    private static final Map<String, Integer> CURVENAME2OCTECTCOUNT = 
-            Collections.unmodifiableMap(new TreeMap<String, Integer>(String.CASE_INSENSITIVE_ORDER) {
-                private static final long serialVersionUID = 1L;    // we're not serializing it
-        
-                {
-                    put(NISTP256, Integer.valueOf(32));
-                    put(NISTP384, Integer.valueOf(48));
-                    put(NISTP521, Integer.valueOf(66));
-                }
-            });
-
+    
     /**
-     * @param curveName Curve name - case <U>insensitive</U> - ignored
-     * if {@code null}/empty
-     * @return The number of octets used to represent the point(s) for
-     * the curve - {@code null} if no match found
+     * @param keySize The key size (in bits)
+     * @return The matching {@link ECCurves} value - {@code null} if no
+     * match found
      */
-    public static Integer getNumPointOctets(String curveName) {
-        if (GenericUtils.isEmpty(curveName)) {
+    public static ECCurves fromCurveSize(int keySize) {
+        if (keySize <= 0) {
             return null;
-        } else {
-            return CURVENAME2OCTECTCOUNT.get(curveName);
         }
+        
+        for (ECCurves c : VALUES) {
+            if (keySize == c.getKeySize()) {
+                return c;
+            }
+        }
+        
+        return null;
     }
 
+    /**
+     * @param params The curve's {@link ECParameterSpec}
+     * @return The curve's key size in bits
+     * @throws IllegalArgumentException if invalid parameters provided
+     */
     public static int getCurveSize(ECParameterSpec params) {
         EllipticCurve   curve = ValidateUtils.checkNotNull(params, "No EC params", GenericUtils.EMPTY_OBJECT_ARRAY).getCurve();
         ECField field = ValidateUtils.checkNotNull(curve, "No EC curve", GenericUtils.EMPTY_OBJECT_ARRAY).getField();
         return ValidateUtils.checkNotNull(field, "No EC field", GenericUtils.EMPTY_OBJECT_ARRAY).getFieldSize();
     }
 
-    public static Digest getDigestForParams(ECParameterSpec params) {
-        int size = getCurveSize(params);
-        if (size <= 256) {
-            return BuiltinDigests.sha256.create();
-        } else if (size <= 384) {
-            return BuiltinDigests.sha384.create();
-        } else if (size <= 521) {
-            return BuiltinDigests.sha512.create();
-        } else {
-            throw new UnsupportedOperationException("Unsupported curve size for digest: " + size);
-        }
-    }
-
     /**
      * Decode an OctetString to EllipticCurvePoint according to SECG 2.3.4
      */
@@ -272,61 +328,15 @@ public class ECCurves {
         System.arraycopy(input, pos, output, 0, output.length);
         return output;
     }
-
-    public static class EllipticCurves {
-        public static ECParameterSpec nistp256 = new ECParameterSpec(
-                new EllipticCurve(
-                        new ECFieldFp(new BigInteger("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF", 16)),
-                        new BigInteger("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC", 16),
-                        new BigInteger("5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", 16)),
-                new ECPoint(
-                        new BigInteger("6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296", 16),
-                        new BigInteger("4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5", 16)),
-                new BigInteger("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551", 16),
-                1);
-
-        public static ECParameterSpec nistp384 = new ECParameterSpec(
-                new EllipticCurve(
-                        new ECFieldFp(new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF", 16)),
-                        new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC", 16),
-                        new BigInteger("B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF", 16)),
-                new ECPoint(
-                        new BigInteger("AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7", 16),
-                        new BigInteger("3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F", 16)),
-                new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973", 16),
-                1);
-
-        public static ECParameterSpec nistp521 = new ECParameterSpec(
-                new EllipticCurve(
-                        new ECFieldFp(new BigInteger("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 16)),
-                        new BigInteger("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC", 16),
-                        new BigInteger("0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00", 16)),
-                new ECPoint(
-                        new BigInteger("00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66", 16),
-                        new BigInteger("011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650", 16)),
-                new BigInteger("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409", 16),
-                1);
-    }
     
-    private static final class LazySpecsMapHolder {
-        private static final Map<String,ECParameterSpec> specsMap =
-                Collections.unmodifiableMap(new TreeMap<String,ECParameterSpec>(String.CASE_INSENSITIVE_ORDER) {
-                        private static final long serialVersionUID = 1L;    // we're not serializing it
-                    
-                        {
-                            put(NISTP256, EllipticCurves.nistp256);
-                            put(NISTP384, EllipticCurves.nistp384);
-                            put(NISTP521, EllipticCurves.nistp521);
-                        }
-                });
-    }
-
-    @SuppressWarnings("synthetic-access")
-    public static ECParameterSpec getECParameterSpec(String curveName) {
-        if (GenericUtils.isEmpty(curveName)) {
-            return null;
-        } else {
-            return LazySpecsMapHolder.specsMap.get(curveName);
-        }
+    public static final class Constants {
+        /**
+         * Standard prefix of NISTP key types when encoded
+         */
+        public static final String ECDSA_SHA2_PREFIX = "ecdsa-sha2-";
+
+        public static final String NISTP256 = "nistp256";
+        public static final String NISTP384 = "nistp384";
+        public static final String NISTP521 = "nistp521";
     }
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/189d8cb9/sshd-core/src/main/java/org/apache/sshd/common/compression/BuiltinCompressions.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/compression/BuiltinCompressions.java b/sshd-core/src/main/java/org/apache/sshd/common/compression/BuiltinCompressions.java
index 95128b8..0d9e38f 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/compression/BuiltinCompressions.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/compression/BuiltinCompressions.java
@@ -130,18 +130,9 @@ public enum BuiltinCompressions implements CompressionFactory {
     }
 
     public static final BuiltinCompressions fromFactoryName(String name) {
-        if (GenericUtils.isEmpty(name)) {
-            return null;
-        }
-        
-        for (BuiltinCompressions c : VALUES) {
-            if (name.equalsIgnoreCase(c.getName())) {
-                return c;
-            }
-        }
-        
-        return null;
+        return NamedResource.Utils.findByName(name, String.CASE_INSENSITIVE_ORDER, VALUES);
     }
+
     /**
      * @param Compressions A comma-separated list of Compressions' names - ignored
      * if {@code null}/empty

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/189d8cb9/sshd-core/src/main/java/org/apache/sshd/common/config/keys/ECDSAPublicKeyEntryDecoder.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/ECDSAPublicKeyEntryDecoder.java b/sshd-core/src/main/java/org/apache/sshd/common/config/keys/ECDSAPublicKeyEntryDecoder.java
index feba09c..e598f56 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/ECDSAPublicKeyEntryDecoder.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/config/keys/ECDSAPublicKeyEntryDecoder.java
@@ -55,12 +55,13 @@ public class ECDSAPublicKeyEntryDecoder extends AbstractPublicKeyEntryDecoder<EC
     public static final ECDSAPublicKeyEntryDecoder INSTANCE = new ECDSAPublicKeyEntryDecoder();
 
     public ECDSAPublicKeyEntryDecoder() {
-        super(ECPublicKey.class, ECPrivateKey.class, ECCurves.TYPES);
+        super(ECPublicKey.class, ECPrivateKey.class, ECCurves.KEY_TYPES);
     }
 
     @Override
     public ECPublicKey decodePublicKey(String keyType, InputStream keyData) throws IOException, GeneralSecurityException {
-        if (GenericUtils.isEmpty(keyType) || (!keyType.startsWith(ECCurves.ECDSA_SHA2_PREFIX))) {
+        ECCurves curve = ECCurves.fromKeyType(keyType);
+        if (curve == null) {
             throw new InvalidKeySpecException("Not an EC curve name: " + keyType);
         }
         
@@ -68,12 +69,8 @@ public class ECDSAPublicKeyEntryDecoder extends AbstractPublicKeyEntryDecoder<EC
             throw new NoSuchProviderException("ECC not supported");
         }
 
-        String keyCurveName = keyType.substring(ECCurves.ECDSA_SHA2_PREFIX.length());
-        ECParameterSpec paramSpec = ECCurves.getECParameterSpec(keyCurveName);
-        if (paramSpec == null) {
-            throw new InvalidKeySpecException("Unknown EC key curve name: " + keyCurveName);
-        }
-        
+        String keyCurveName = curve.getName();
+        ECParameterSpec paramSpec = curve.getParameters();
         // see rfc5656 section 3.1
         String encCurveName = decodeString(keyData);
         if (!keyCurveName.equals(encCurveName)) {
@@ -137,8 +134,8 @@ public class ECDSAPublicKeyEntryDecoder extends AbstractPublicKeyEntryDecoder<EC
         ValidateUtils.checkNotNull(key, "No public key provided", GenericUtils.EMPTY_OBJECT_ARRAY);
         
         ECParameterSpec params = ValidateUtils.checkNotNull(key.getParams(), "No EC parameters available", GenericUtils.EMPTY_OBJECT_ARRAY);
-        String curveName = ValidateUtils.checkNotNullAndNotEmpty(ECCurves.getCurveName(params), "Cannot determine curve name", GenericUtils.EMPTY_OBJECT_ARRAY);
-        String keyType = ECCurves.ECDSA_SHA2_PREFIX + curveName;
+        ECCurves curve = ValidateUtils.checkNotNull(ECCurves.fromCurveParameters(params), "Cannot determine curve", GenericUtils.EMPTY_OBJECT_ARRAY);
+        String keyType = curve.getKeyType(), curveName = curve.getName();
         encodeString(s, keyType);
         // see rfc5656 section 3.1
         encodeString(s, curveName);
@@ -157,18 +154,13 @@ public class ECDSAPublicKeyEntryDecoder extends AbstractPublicKeyEntryDecoder<EC
 
     @Override
     public KeyPair generateKeyPair(int keySize) throws GeneralSecurityException {
-        String curveName = ECCurves.getCurveName(keySize);
-        if (GenericUtils.isEmpty(curveName)) {
+        ECCurves curve = ECCurves.fromCurveSize(keySize);
+        if (curve == null) {
             throw new InvalidKeySpecException("Unknown curve for key size=" + keySize);
         }
         
-        ECParameterSpec params = ECCurves.getECParameterSpec(curveName);
-        if (params == null) {
-            throw new InvalidKeySpecException("No curve parameters available for " + curveName);
-        }
-
         KeyPairGenerator gen = getKeyPairGenerator();
-        gen.initialize(params);
+        gen.initialize(curve.getParameters());
         return gen.generateKeyPair();
     }
 
@@ -270,12 +262,12 @@ public class ECDSAPublicKeyEntryDecoder extends AbstractPublicKeyEntryDecoder<EC
                 
                 @Override
                 public void writeECPoint(OutputStream s, String curveName, ECPoint p) throws IOException {
-                    Integer elems = ECCurves.getNumPointOctets(curveName);
-                    if (elems == null) {
+                    ECCurves curve = ECCurves.fromCurveName(curveName);
+                    if (curve == null) {
                         throw new StreamCorruptedException("writeECPoint(" + name() + ")[" + curveName + "] cannot determine octets count");
                     }
                     
-                    int numElements = elems.intValue();
+                    int numElements = curve.getNumPointOctets();
                     AbstractPublicKeyEntryDecoder.encodeInt(s, 1 /* the indicator */ + 2 * numElements);
                     s.write(getIndicatorValue());
                     writeCoordinate(s, "X", p.getAffineX(), numElements);

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/189d8cb9/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
index c72e5f5..2c37278 100644
--- 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
@@ -380,8 +380,14 @@ public final class KeyUtils {
         } else if (key instanceof ECKey) {
             ECKey ecKey = (ECKey) key;
             ECParameterSpec ecSpec = ecKey.getParams();
-            return ECCurves.ECDSA_SHA2_PREFIX + ECCurves.getCurveName(ecSpec);
+            ECCurves curve = ECCurves.fromCurveParameters(ecSpec);
+            if (curve == null) {
+                return null;    // debug breakpoint
+            } else {
+                return curve.getKeyType();
+            }
         }
+
         return null;
     }
 

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/189d8cb9/sshd-core/src/main/java/org/apache/sshd/common/digest/BuiltinDigests.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/digest/BuiltinDigests.java b/sshd-core/src/main/java/org/apache/sshd/common/digest/BuiltinDigests.java
index 131fbe7..679aa95 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/digest/BuiltinDigests.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/digest/BuiltinDigests.java
@@ -24,6 +24,7 @@ import java.util.EnumSet;
 import java.util.Set;
 
 import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.common.NamedResource;
 import org.apache.sshd.common.util.GenericUtils;
 
 /**
@@ -110,22 +111,12 @@ public enum BuiltinDigests implements DigestInformation, NamedFactory<Digest> {
     }
 
     /**
-     * @param n The factory name - ignored if {@code null}/empty
+     * @param name The factory name - ignored if {@code null}/empty
      * @return The matching {@link org.apache.sshd.common.digest.BuiltinDigests} whose factory name matches
      * (case <U>insensitive</U>) the provided name - {@code null} if no match
      */
-    public static BuiltinDigests fromFactoryName(String n) {
-        if (GenericUtils.isEmpty(n)) {
-            return null;
-        }
-
-        for (BuiltinDigests c : VALUES) {
-            if (n.equalsIgnoreCase(c.getName())) {
-                return c;
-            }
-        }
-
-        return null;
+    public static BuiltinDigests fromFactoryName(String name) {
+        return NamedResource.Utils.findByName(name, String.CASE_INSENSITIVE_ORDER, VALUES);
     }
 
     public static final class Constants {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/189d8cb9/sshd-core/src/main/java/org/apache/sshd/common/io/BuiltinIoServiceFactoryFactories.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/io/BuiltinIoServiceFactoryFactories.java b/sshd-core/src/main/java/org/apache/sshd/common/io/BuiltinIoServiceFactoryFactories.java
index 7d60b0e..f5c558e 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/io/BuiltinIoServiceFactoryFactories.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/io/BuiltinIoServiceFactoryFactories.java
@@ -24,9 +24,9 @@ import java.util.EnumSet;
 import java.util.Set;
 
 import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.common.NamedResource;
 import org.apache.sshd.common.io.mina.MinaServiceFactoryFactory;
 import org.apache.sshd.common.io.nio2.Nio2ServiceFactoryFactory;
-import org.apache.sshd.common.util.GenericUtils;
 
 /**
  * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
@@ -65,18 +65,9 @@ public enum BuiltinIoServiceFactoryFactories implements NamedFactory<IoServiceFa
     
     public static final Set<BuiltinIoServiceFactoryFactories> VALUES = 
             Collections.unmodifiableSet(EnumSet.allOf(BuiltinIoServiceFactoryFactories.class));
+
     public static final BuiltinIoServiceFactoryFactories fromFactoryName(String name) {
-        if (GenericUtils.isEmpty(name)) {
-            return null;
-        }
-        
-        for (BuiltinIoServiceFactoryFactories f : VALUES) {
-            if (name.equalsIgnoreCase(f.getName())) {
-                return f;
-            }
-        }
-        
-        return null;
+        return NamedResource.Utils.findByName(name, String.CASE_INSENSITIVE_ORDER, VALUES);
     }
     
     public static final BuiltinIoServiceFactoryFactories fromFactoryClass(Class<?> clazz) {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/189d8cb9/sshd-core/src/main/java/org/apache/sshd/common/kex/BuiltinDHFactories.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/kex/BuiltinDHFactories.java b/sshd-core/src/main/java/org/apache/sshd/common/kex/BuiltinDHFactories.java
index 0d4b5ef..e5c930d 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/kex/BuiltinDHFactories.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/kex/BuiltinDHFactories.java
@@ -110,7 +110,7 @@ public enum BuiltinDHFactories implements DHFactory {
             if (!GenericUtils.isEmpty(params)) {
                 throw new IllegalArgumentException("No accepted parameters for " + getName());
             }
-            return new ECDH(ECCurves.NISTP256);
+            return new ECDH(ECCurves.nistp256);
         }
 
         @Override
@@ -124,7 +124,7 @@ public enum BuiltinDHFactories implements DHFactory {
             if (!GenericUtils.isEmpty(params)) {
                 throw new IllegalArgumentException("No accepted parameters for " + getName());
             }
-            return new ECDH(ECCurves.NISTP384);
+            return new ECDH(ECCurves.nistp384);
         }
 
         @Override
@@ -138,7 +138,7 @@ public enum BuiltinDHFactories implements DHFactory {
             if (!GenericUtils.isEmpty(params)) {
                 throw new IllegalArgumentException("No accepted parameters for " + getName());
             }
-            return new ECDH(ECCurves.NISTP521);
+            return new ECDH(ECCurves.nistp521);
         }
 
         @Override
@@ -223,17 +223,7 @@ public enum BuiltinDHFactories implements DHFactory {
      * or {@code null} if no match found
      */
     public static final BuiltinDHFactories fromFactoryName(String name) {
-        if (GenericUtils.isEmpty(name)) {
-            return null;
-        }
-
-        for (BuiltinDHFactories f : VALUES) {
-            if (name.equalsIgnoreCase(f.getName())) {
-                return f;
-            }
-        }
-
-        return null;
+        return NamedResource.Utils.findByName(name, String.CASE_INSENSITIVE_ORDER, VALUES);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/189d8cb9/sshd-core/src/main/java/org/apache/sshd/common/kex/ECDH.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/kex/ECDH.java b/sshd-core/src/main/java/org/apache/sshd/common/kex/ECDH.java
index 5c84369..6e55ee0 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/kex/ECDH.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/kex/ECDH.java
@@ -55,7 +55,11 @@ public class ECDH extends AbstractDH {
     }
 
     public ECDH(String curveName) throws Exception {
-        this(ValidateUtils.checkNotNull(ECCurves.getECParameterSpec(curveName), "Unknown curve name: %s", curveName));
+        this(ValidateUtils.checkNotNull(ECCurves.fromCurveName(curveName), "Unknown curve name: %s", curveName));
+    }
+
+    public ECDH(ECCurves curve) throws Exception {
+        this(ValidateUtils.checkNotNull(curve, "No known curve instance provided", GenericUtils.EMPTY_OBJECT_ARRAY).getParameters());
     }
 
     public ECDH(ECParameterSpec paramSpec) throws Exception {
@@ -102,6 +106,7 @@ public class ECDH extends AbstractDH {
     @Override
     public Digest getHash() throws Exception {
         ValidateUtils.checkNotNull(params, "No ECParameterSpec(s)", GenericUtils.EMPTY_OBJECT_ARRAY);
-        return ECCurves.getDigestForParams(params);
+        ECCurves curve = ValidateUtils.checkNotNull(ECCurves.fromCurveParameters(params), "Unknown curve parameters", GenericUtils.EMPTY_OBJECT_ARRAY);
+        return curve.getDigestForParams();
     }
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/189d8cb9/sshd-core/src/main/java/org/apache/sshd/common/keyprovider/KeyPairProvider.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/keyprovider/KeyPairProvider.java b/sshd-core/src/main/java/org/apache/sshd/common/keyprovider/KeyPairProvider.java
index 37af11c..699ee8c 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/keyprovider/KeyPairProvider.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/keyprovider/KeyPairProvider.java
@@ -44,17 +44,17 @@ public interface KeyPairProvider {
     /**
      * SSH identifier for EC keys in NIST curve P-256
      */
-    String ECDSA_SHA2_NISTP256 = ECCurves.ECDSA_SHA2_PREFIX + ECCurves.NISTP256;
+    String ECDSA_SHA2_NISTP256 = ECCurves.nistp256.getKeyType();
 
     /**
      * SSH identifier for EC keys in NIST curve P-384
      */
-    String ECDSA_SHA2_NISTP384 = ECCurves.ECDSA_SHA2_PREFIX + ECCurves.NISTP384;
+    String ECDSA_SHA2_NISTP384 = ECCurves.nistp384.getKeyType();
 
     /**
      * SSH identifier for EC keys in NIST curve P-521
      */
-    String ECDSA_SHA2_NISTP521 = ECCurves.ECDSA_SHA2_PREFIX + ECCurves.NISTP521;
+    String ECDSA_SHA2_NISTP521 = ECCurves.nistp521.getKeyType();
 
     /**
      * Load available keys.

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/189d8cb9/sshd-core/src/main/java/org/apache/sshd/common/mac/BuiltinMacs.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/mac/BuiltinMacs.java b/sshd-core/src/main/java/org/apache/sshd/common/mac/BuiltinMacs.java
index db50964..d48622b 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/mac/BuiltinMacs.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/mac/BuiltinMacs.java
@@ -184,22 +184,12 @@ public enum BuiltinMacs implements MacFactory {
     }
 
     /**
-     * @param n The factory name - ignored if {@code null}/empty
-     * @return The matching {@link org.apache.sshd.common.mac.BuiltinMacs} whose factory name matches
+     * @param name The factory name - ignored if {@code null}/empty
+     * @return The matching {@link BuiltinMacs} whose factory name matches
      * (case <U>insensitive</U>) the provided name - {@code null} if no match
      */
-    public static BuiltinMacs fromFactoryName(String n) {
-        if (GenericUtils.isEmpty(n)) {
-            return null;
-        }
-
-        for (BuiltinMacs c : VALUES) {
-            if (n.equalsIgnoreCase(c.getName())) {
-                return c;
-            }
-        }
-
-        return null;
+    public static BuiltinMacs fromFactoryName(String name) {
+        return NamedResource.Utils.findByName(name, String.CASE_INSENSITIVE_ORDER, VALUES);
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/189d8cb9/sshd-core/src/main/java/org/apache/sshd/common/signature/BuiltinSignatures.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/signature/BuiltinSignatures.java b/sshd-core/src/main/java/org/apache/sshd/common/signature/BuiltinSignatures.java
index c79f56a..f9bd7df 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/signature/BuiltinSignatures.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/signature/BuiltinSignatures.java
@@ -207,22 +207,12 @@ public enum BuiltinSignatures implements SignatureFactory {
     }
 
     /**
-     * @param n The factory name - ignored if {@code null}/empty
-     * @return The matching {@link org.apache.sshd.common.signature.BuiltinSignatures} whose factory name matches
+     * @param name The factory name - ignored if {@code null}/empty
+     * @return The matching {@link BuiltinSignatures} whose factory name matches
      * (case <U>insensitive</U>) the provided name - {@code null} if no match
      */
-    public static BuiltinSignatures fromFactoryName(String n) {
-        if (GenericUtils.isEmpty(n)) {
-            return null;
-        }
-
-        for (BuiltinSignatures c : VALUES) {
-            if (n.equalsIgnoreCase(c.getName())) {
-                return c;
-            }
-        }
-
-        return null;
+    public static BuiltinSignatures fromFactoryName(String name) {
+        return NamedResource.Utils.findByName(name, String.CASE_INSENSITIVE_ORDER, VALUES);
     }
     
     /**

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/189d8cb9/sshd-core/src/main/java/org/apache/sshd/common/signature/SignatureECDSA.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/signature/SignatureECDSA.java b/sshd-core/src/main/java/org/apache/sshd/common/signature/SignatureECDSA.java
index 67c01d1..254069c 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/signature/SignatureECDSA.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/signature/SignatureECDSA.java
@@ -80,7 +80,8 @@ public class SignatureECDSA extends AbstractSignature {
         Pair<String,byte[]> encoding = extractEncodedSignature(data);
         if (encoding != null) {
             String keyType = encoding.getFirst();
-            ValidateUtils.checkTrue(ECCurves.TYPES.contains(keyType), "Unknown curve type: %s", keyType);
+            ECCurves curve = ECCurves.fromKeyType(keyType);
+            ValidateUtils.checkNotNull(curve, "Unknown curve type: %s", keyType);
             data = encoding.getSecond();
         }
 

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/189d8cb9/sshd-core/src/main/java/org/apache/sshd/common/util/buffer/Buffer.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/buffer/Buffer.java b/sshd-core/src/main/java/org/apache/sshd/common/util/buffer/Buffer.java
index fe3c0e3..3984513 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/util/buffer/Buffer.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/util/buffer/Buffer.java
@@ -194,13 +194,16 @@ public abstract class Buffer implements Readable {
                 BigInteger y = getMPInt();
                 KeyFactory keyFactory = SecurityUtils.getKeyFactory("DSA");
                 return keyFactory.generatePublic(new DSAPublicKeySpec(y, p, q, g));
-            } else if (keyAlg.startsWith(ECCurves.ECDSA_SHA2_PREFIX)) {
-                String curveName = keyAlg.substring(ECCurves.ECDSA_SHA2_PREFIX.length());
-                ECParameterSpec params = ECCurves.getECParameterSpec(curveName);
-                return getRawECKey(curveName, params);
-            } else {
+            }
+            
+            ECCurves curve = ECCurves.fromKeyType(keyAlg);
+            if (curve == null) {
                 throw new NoSuchAlgorithmException("Unsupported raw public algorithm: " + keyAlg);
             }
+
+            String curveName = curve.getName();
+            ECParameterSpec params = curve.getParameters();
+            return getRawECKey(curveName, params);
         } catch (GeneralSecurityException e) {
             throw new SshException(e);
         }
@@ -228,9 +231,9 @@ public abstract class Buffer implements Readable {
 
     public KeyPair getKeyPair() throws SshException {
         try {
-            PublicKey pub;
-            PrivateKey prv;
-            String keyAlg = getString();
+            final PublicKey pub;
+            final PrivateKey prv;
+            final String keyAlg = getString();
             if (KeyPairProvider.SSH_RSA.equals(keyAlg)) {
                 BigInteger e = getMPInt();
                 BigInteger n = getMPInt();
@@ -252,13 +255,16 @@ public abstract class Buffer implements Readable {
                 KeyFactory keyFactory = SecurityUtils.getKeyFactory("DSA");
                 pub = keyFactory.generatePublic(new DSAPublicKeySpec(y, p, q, g));
                 prv = keyFactory.generatePrivate(new DSAPrivateKeySpec(x, p, q, g));
-            } else if (keyAlg.startsWith(ECCurves.ECDSA_SHA2_PREFIX)) {
-                String curveName = keyAlg.substring(ECCurves.ECDSA_SHA2_PREFIX.length());
-                ECParameterSpec params = ECCurves.getECParameterSpec(curveName);
-                return extractEC(curveName, params);
             } else {
-                throw new NoSuchAlgorithmException("Unsupported key pair algorithm: " + keyAlg);
+                ECCurves    curve = ECCurves.fromKeyType(keyAlg);
+                if (curve == null) {
+                    throw new NoSuchAlgorithmException("Unsupported key pair algorithm: " + keyAlg);
+                }
+                String curveName = curve.getName();
+                ECParameterSpec params = curve.getParameters();
+                return extractEC(curveName, params);
             }
+
             return new KeyPair(pub, prv);
         } catch (GeneralSecurityException e) {
             throw new SshException(e);
@@ -422,11 +428,15 @@ public abstract class Buffer implements Readable {
             putMPInt(dsaParams.getG());
             putMPInt(dsaPub.getY());
         } else if (key instanceof ECPublicKey) {
-            ECPublicKey     ecKey = (ECPublicKey) key;
+            ECPublicKey ecKey = (ECPublicKey) key;
             ECParameterSpec ecParams = ecKey.getParams();
-            String          curveName = ECCurves.getCurveName(ecParams);
-            putString(ECCurves.ECDSA_SHA2_PREFIX + curveName);
-            putString(curveName);
+            ECCurves curve = ECCurves.fromCurveParameters(ecParams);
+            if (curve == null) {
+                throw new BufferException("Unsupported EC curve parameters");
+            }
+
+            putString(curve.getKeyType());
+            putString(curve.getName());
             putBytes(ECCurves.encodeECPoint(ecKey.getW(), ecParams.getCurve()));
         } else {
             throw new BufferException("Unsupported raw public key algorithm: " + key.getAlgorithm());
@@ -459,13 +469,16 @@ public abstract class Buffer implements Readable {
             putMPInt(dsaPub.getY());
             putMPInt(dsaPrv.getX());
         } else if (pubKey instanceof ECPublicKey) {
-            ECPublicKey     ecPub = (ECPublicKey) pubKey;
-            ECPrivateKey    ecPriv = (ECPrivateKey) prvKey;
+            ECPublicKey ecPub = (ECPublicKey) pubKey;
+            ECPrivateKey ecPriv = (ECPrivateKey) prvKey;
             ECParameterSpec ecParams = ecPub.getParams();
-            String          curveName = ECCurves.getCurveName(ecParams);
+            ECCurves curve = ECCurves.fromCurveParameters(ecParams);
+            if (curve == null) {
+                throw new BufferException("Unsupported EC curve parameters");    
+            }
 
-            putString(ECCurves.ECDSA_SHA2_PREFIX + curveName);
-            putString(curveName);
+            putString(curve.getKeyType());
+            putString(curve.getName());
             putBytes(ECCurves.encodeECPoint(ecPub.getW(), ecParams.getCurve()));
             putMPInt(ecPriv.getS());
         } else {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/189d8cb9/sshd-core/src/main/java/org/apache/sshd/server/forward/ForwardingFilter.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/forward/ForwardingFilter.java b/sshd-core/src/main/java/org/apache/sshd/server/forward/ForwardingFilter.java
index 0e0fcc3..23ada9d 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/forward/ForwardingFilter.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/forward/ForwardingFilter.java
@@ -123,17 +123,7 @@ public interface ForwardingFilter {
          * or {@code null} if no match found
          */
         public static final Type fromName(String name) {
-            if (GenericUtils.isEmpty(name)) {
-                return null;
-            }
-            
-            for (Type t : VALUES) {
-                if (name.equalsIgnoreCase(t.getName())) {
-                    return t;
-                }
-            }
-            
-            return null;
+            return NamedResource.Utils.findByName(name, String.CASE_INSENSITIVE_ORDER, VALUES);
         }
         
         /**

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/189d8cb9/sshd-core/src/test/java/org/apache/sshd/common/cipher/ECCurvesTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/common/cipher/ECCurvesTest.java b/sshd-core/src/test/java/org/apache/sshd/common/cipher/ECCurvesTest.java
new file mode 100644
index 0000000..eca1ce6
--- /dev/null
+++ b/sshd-core/src/test/java/org/apache/sshd/common/cipher/ECCurvesTest.java
@@ -0,0 +1,105 @@
+/*
+ * 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.cipher;
+
+import java.util.EnumSet;
+import java.util.Set;
+
+import org.apache.sshd.util.BaseTestSupport;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class ECCurvesTest extends BaseTestSupport {
+    public ECCurvesTest() {
+        super();
+    }
+
+    @Test
+    public void testFromName() {
+        for (ECCurves expected : ECCurves.VALUES) {
+            String name = expected.getName();
+            for (int index=0; index < name.length(); index++) {
+                ECCurves actual = ECCurves.fromCurveName(name);
+                assertSame(name, expected, actual);
+                name = shuffleCase(name);
+            }
+        }
+    }
+
+    @Test
+    public void testAllNamesListed() {
+        Set<ECCurves> listed = EnumSet.noneOf(ECCurves.class);
+        for (String name : ECCurves.NAMES) {
+            ECCurves c = ECCurves.fromCurveName(name);
+            assertNotNull("No curve for listed name=" + name, c);
+            assertTrue("Duplicated listed name: " + name, listed.add(c));
+        }
+        
+        assertEquals("Mismatched listed vs. values", ECCurves.VALUES, listed);
+    }
+
+    @Test
+    public void testFromKeySize() {
+        for (ECCurves expected : ECCurves.VALUES) {
+            String name = expected.getName();
+            ECCurves actual = ECCurves.fromCurveSize(expected.getKeySize());
+            assertSame(name, expected, actual);
+        }
+    }
+
+    @Test
+    public void testFromCurveParameters() {
+        for (ECCurves expected : ECCurves.VALUES) {
+            String name = expected.getName();
+            ECCurves actual = ECCurves.fromCurveParameters(expected.getParameters());
+            assertSame(name, expected, actual);
+        }
+    }
+
+    @Test
+    public void testFromKeyType() {
+        for (ECCurves expected : ECCurves.VALUES) {
+            String keyType = expected.getKeyType();
+            for (int index=0; index < keyType.length(); index++) {
+                ECCurves actual = ECCurves.fromKeyType(keyType);
+                assertSame(keyType, expected, actual);
+                keyType = shuffleCase(keyType);
+            }
+        }
+    }
+    
+    @Test
+    public void testAllKeyTypesListed() {
+        Set<ECCurves> listed = EnumSet.noneOf(ECCurves.class);
+        for (String name : ECCurves.KEY_TYPES) {
+            ECCurves c = ECCurves.fromKeyType(name);
+            assertNotNull("No curve for listed key type=" + name, c);
+            assertTrue("Duplicated listed key type: " + name, listed.add(c));
+        }
+        
+        assertEquals("Mismatched listed vs. values", ECCurves.VALUES, listed);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/189d8cb9/sshd-core/src/test/java/org/apache/sshd/common/config/keys/KeyUtilsTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/common/config/keys/KeyUtilsTest.java b/sshd-core/src/test/java/org/apache/sshd/common/config/keys/KeyUtilsTest.java
index dd0d9f2..05e62c2 100644
--- a/sshd-core/src/test/java/org/apache/sshd/common/config/keys/KeyUtilsTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/common/config/keys/KeyUtilsTest.java
@@ -91,12 +91,12 @@ public class KeyUtilsTest extends BaseTestSupport {
         Assume.assumeTrue("No ECC support", SecurityUtils.hasEcc());
 
         GeneralSecurityException err = null;
-        for (String curveName : ECCurves.NAMES) {
-            Integer keySize = ECCurves.getCurveSize(curveName);
+        for (ECCurves curve : ECCurves.VALUES) {
+            String keyType = curve.getKeyType();
+            int keySize = curve.getKeySize();
             try {
-                String keyType = ECCurves.ECDSA_SHA2_PREFIX + curveName;
-                KeyPair kp = generateKeyPair(keyType, keySize.intValue());
-                testKeyPairCloning(keyType, keySize.intValue(), kp);
+                KeyPair kp = generateKeyPair(keyType, keySize);
+                testKeyPairCloning(keyType, keySize, kp);
             } catch(GeneralSecurityException e) {
                 err = GenericUtils.accumulateException(err, e);
             }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/189d8cb9/sshd-core/src/test/java/org/apache/sshd/common/signature/SignatureECDSAFactoryTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/common/signature/SignatureECDSAFactoryTest.java b/sshd-core/src/test/java/org/apache/sshd/common/signature/SignatureECDSAFactoryTest.java
index abbdf8d..3c004df 100644
--- a/sshd-core/src/test/java/org/apache/sshd/common/signature/SignatureECDSAFactoryTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/common/signature/SignatureECDSAFactoryTest.java
@@ -52,11 +52,11 @@ public class SignatureECDSAFactoryTest extends AbstractSignatureFactoryTestSuppo
 
     @Parameters(name = "keySize={0}")
     public static Collection<Object[]> parameters() {
-        return parameterize(ECCurves.SIZES);
+        return parameterize(ECCurves.VALUES);
     }
     
-    public SignatureECDSAFactoryTest(int keySize) {
-        super(ECCurves.getCurveName(keySize), keySize);
+    public SignatureECDSAFactoryTest(ECCurves curve) {
+        super(curve.getName(), curve.getKeySize());
     }
 
     @Test