JDK-8190219 : Crypto support for the EdDSA Signature Algorithm
  • Type: CSR
  • Component: security-libs
  • Sub-Component: javax.crypto
  • Priority: P3
  • Status: Closed
  • Resolution: Approved
  • Fix Versions: 15
  • Submitted: 2017-10-26
  • Updated: 2020-03-30
  • Resolved: 2020-03-19
Related Reports
CSR :  
Relates :  
Description
Summary
-------

Add support for the EdDSA signature algorithm in the JCA API. 

Problem
-------

EdDSA is a new signature algorithm that we want to support in the JCA API. This algorithm uses elliptic curves, but it represents curves, points, and keys in a way that is different than the existing mechanisms in ECDSA, ECDH, and XDH. So we need to define new API classes and interfaces in order to support this new algorithm and its keys.

Solution
--------
Define a new set of API classes and interfaces that are mostly independent from the existing API for ECDSA and other elliptic curve algorithms. Define standard names for algorithms and curve parameter sets associated with EdDSA.

Example API usage:


    // example: generate a key pair and sign
    KeyPairGenerator kpg = KeyPairGenerator.getInstance("Ed25519");
    KeyPair kp = kpg.generateKeyPair();
    Signature sig = Signature.getInstance("Ed25519");
    // mode is Ed25519ph with a context
    byte[] context = ...
    EdDSAParameterSpec edParamSpec = new EdDSAParameterSpec(true, context);
    sig.setParameter(edParamSpec);
    sig.initSign(kp.getPrivate());
    sig.update(msg);
    byte[] s = sig.sign();

    // example: use KeyFactory to construct a public key
    KeyFactory kf = KeyFactory.getInstance("EdDSA");
    boolean xOdd = ...
    BigInteger y = ...
    NamedParameterSpec paramSpec = new NamedParameterSpec("Ed25519");
    EdECPublicKeySpec pubSpec = new EdECPublicKeySpec(paramSpec,
        new EdPoint(xOdd, y));
    PublicKey pubKey = kf.generatePublic(pubSpec);

The API uses "EdDSA" to refer to the family of signature scheme defined in RFC 8032. "EdEC" refers to the underlying elliptic curve operations and representations in a way that is not specific to any particular cryptosystem. In the API, key interfaces and key spec classes are "EdEC" so they can be reused with other cryptosystems (that may not be signature schemes) based on RFC 8032. This EdEC/EdDSA arrangement mirrors the existing EC/ECDH API classes/interfaces. This API does not standardize "EdEC" algorithm names, so the programmer must use "EdDSA" (or a more specific name like "Ed25519") as the algorithm name to obtain a `KeyPairGenerator` or `KeyFactory`. Requiring information about the intended use of the keys allows the implementation to apply algorithm-specific optimizations and ensure that keys are not misused.  

Specification
-------------

###JCA Identifier Strings###

In the Java Security Standard Algorithm Names Specification, define the following standard algorithm names for `Signature`, `KeyPairGenerator`, `KeyFactory`, and `AlgorithmParameters`:

Algorithm Name  |  Description 
--- | ---
EdDSA | The EdDSA signature scheme family as defined in RFC 8032
Ed25519| The Ed25519 signature scheme family based on Curve25519 as defined in RFC 8032
Ed448 | The Ed448 signature scheme family based on Curve448 as defined in RFC 8032

A correct implementation of these algorithms must adhere to RFC 8032 exactly, and may only take liberty where allowed by that spec through use of language such as "MAY" or "SHOULD." An implementation that supports some curve SHOULD implement the entire family of signature schemes for that curve. For example, an implementation that supports Ed25519 SHOULD support the "pure" mode as well as Ed25519ctx and Ed25519ph. None of these algorithm names are mandatory, and an implementation MAY implement any subset of the curves.     

The EdDSA API provides no way to specify arbitrary curve/field parameters for use with EdDSA. This feature is not commonly implemented/used in ECC, and it is even less desirable due to the nature of EdDSA. The existing `NamedParameterSpec` class will be used to specify curve parameters. The following standard names will be added for use with this class: 

Parameters Name |  Description 
--- | --- 
Ed25519 | Elliptic curve cryptography using Curve25519 in twisted Edwards form as defined in RFC 8032
Ed448 | Elliptic curve cryptography using Curve448 in twisted Edwards form as defined in RFC 8032

###API###

For the most part, the spec classes and interfaces for EdDSA mirror those used by the existing XDH and ECC APIs. 

**Parameter Specs**

The existing `NamedParameterSpec` class is used to specify curve/key parameters. This class holds static members for the standard parameter spec names. Two new static members are added to this class for the standard EdDSA parameter sets:

```
public class NamedParameterSpec implements AlgorithmParameterSpec {

    (existing definitions)

    /**
     * The Ed25519 parameters
     */
    public static final NamedParameterSpec ED25519
        = new NamedParameterSpec("Ed25519");

    /**
     * The Ed448 parameters
     */
    public static final NamedParameterSpec ED448
        = new NamedParameterSpec("Ed448");
  
    (existing definitions)
}
```

In addition to curve parameters, the API needs a way to specify the parameters of the signature mode. These parameters are: (1) whether the message should be "prehashed" and (2) an arbitrary context value that is bound to the signature. Signature parameters are specified with the new class `EdDSAParameterSpec`. This class is supplied to the `Signature` object using the `setParameter` method. If no `EdDSAParameterSpec` is supplied, then the default value is (1) not prehashed, and (2) no context. `EdDSAParameterSpec` does not include curve parameters, because these parameters are supplied in the key during `initSign` or `initVerify`. 

```
package java.security.spec;

import java.util.Objects;
import java.util.Optional;

/**
 * A class used to specify EdDSA signature and verification parameters. All
 * algorithm modes in <a href="https://tools.ietf.org/html/rfc8032">RFC 8032:
 * Edwards-Curve Digital Signature Algorithm (EdDSA)</a> can be specified using
 * combinations of the settings in this class.
 *
 * <ul>
 * <li>If prehash is true, then the mode is Ed25519ph or Ed448ph</li>
 * <li>Otherwise, if a context is present, the mode is Ed25519ctx or Ed448</li>
 * <li>Otherwise, the mode is Ed25519 or Ed448</li>
 * </ul>
 *
 * @since 15
 */

public final class EdDSAParameterSpec implements AlgorithmParameterSpec {

    private final boolean prehash;
    private final byte[] context;

    /**
     * Construct an EdDSAParameterSpec by specifying whether the prehash mode
     * is used. No context is provided so this constructor specifies a mode
     * in which the context is absent. Note that this mode may be different
     * than the mode in which an empty array is used as the context.
     *
     * @param prehash whether the prehash mode is specified
     */
    public EdDSAParameterSpec(boolean prehash) {
        this.prehash = prehash;
        this.context = null;
    }

    /**
     * Construct an EdDSAParameterSpec by specifying a context and whether the
     * prehash mode is used. The context may not be null, but it may be an
     * empty array. The mode used when the context is an empty array may not be
     * the same as the mode used when the context is absent.
     *
     * @param prehash whether the prehash mode is specified
     * @param context the context that is bound to the signature
     *
     * @throws NullPointerException if context is null
     */
    public EdDSAParameterSpec(boolean prehash, byte[] context) {

        Objects.requireNonNull(context, "context may not be null");

        this.prehash = prehash;
        this.context = context.clone();
    }

    /**
     * Get whether the prehash mode is specified.
     *
     * @return whether the prehash mode is specified
     */
    public boolean isPrehash() {
        return prehash;
    }

    /**
     * Get the context that should be used, if any
     *
     * @return the context that is bound to the signature
     */
    public Optional<byte[]> getContext() {
        if (context == null) {
            return Optional.empty();
        } else {
            return Optional.of(context.clone());
        }

    }

}

```

**Key Interfaces**

There are interfaces for public and private keys, along with a superinterface that allows access to algorithm parameters. NamedParameterSpec are returned to identify the defined curves.  Additional or arbitrary curves are not defined with this interface. It is not expected support will be needed beyond defined curves, but if it were to happen, parameters  can be subclassed under NamedParameterSpec.

```
package java.security.interfaces;

import java.security.spec.NamedParameterSpec;

/**
 * An interface for an elliptic curve public/private key as defined by
 * <a href="https://tools.ietf.org/html/rfc8032">RFC 8032: Edwards-Curve
 * Digital Signature Algorithm (EdDSA)</a>. These keys are distinct from the
 * keys represented by {@code ECKey}, and they are intended for use with
 * algorithms based on RFC 8032 such as the EdDSA {@code Signature} algorithm.
 * This interface allows access to the algorithm parameters associated with
 * the key.
 *
 * @since 15
 */
public interface EdECKey {
    /**
     * Returns the algorithm parameters associated
     * with the key.
     *
     * @return the associated algorithm parameters
     */
    NamedParameterSpec getParams();

}
```


Private key interface:

```
package java.security.interfaces;

import java.security.PrivateKey;
import java.util.Optional;

/**
 * An interface for an elliptic curve private key as defined by
 * <a href="https://tools.ietf.org/html/rfc8032">RFC 8032: Edwards-Curve
 * Digital Signature Algorithm (EdDSA)</a>. These keys are distinct from the
 * keys represented by {@code ECPrivateKey}, and they are intended for use
 * with algorithms based on RFC 8032 such as the EdDSA {@code Signature}
 * algorithm.
 *
 * An EdEC private key is a bit string. This interface only supports bit
 * string lengths that are a multiple of 8, and the key is represented using
 * a byte array.
 *
 * @since 15
 */
public interface EdECPrivateKey extends EdECKey, PrivateKey {

    /**
     * Get the byte array representing the private key. This method may return
     * an empty Optional if the implementation is not willing to produce
     * the private key value.
     *
     * @return the private key as a byte array
     */
    Optional<byte[]> getBytes();
}
```

Public key interface and points:

```
package java.security.interfaces;

import java.security.PublicKey;
import java.security.spec.EdECPoint;

/**
 * An interface for an elliptic curve public key as defined by
 * <a href="https://tools.ietf.org/html/rfc8032">RFC 8032: Edwards-Curve
 * Digital Signature Algorithm (EdDSA)</a>. These keys are distinct from the
 * keys represented by {@code ECPublicKey}, and they are intended for use with
 * algorithms based on RFC 8032 such as the EdDSA {@code Signature} algorithm.
 *
 * An EdEC public key is a point on the curve, which is represented using an
 * EdECPoint.
 *
 * @since 15
 */
public interface EdECPublicKey extends EdECKey, PublicKey {

    /**
     * Get the point representing the public key.
     *
     * @return the EdECPoint representing the public key
     */
    EdECPoint getPoint();

}
```

```
package java.security.spec;

import java.math.BigInteger;
import java.util.Objects;

/**
 * An elliptic curve point used to specify keys as defined by
 * <a href="https://tools.ietf.org/html/rfc8032">RFC 8032: Edwards-Curve
 * Digital Signature Algorithm (EdDSA)</a>. These points are distinct from the
 * points represented by {@code ECPoint}, and they are intended for use with
 * algorithms based on RFC 8032 such as the EdDSA {@code Signature} algorithm.
 *
 * An EdEC point is specified by its y-coordinate value and a boolean that
 * indicates whether the x-coordinate is odd. The y-coordinate is an
 * element of the field of integers modulo some value p that is determined by
 * the algorithm parameters. This field element is represented by a BigInteger,
 * and implementations that consume objects of this class may reject integer
 * values which are not in the range [0, p).
 *
 * @since 15
 */

public final class EdECPoint {

    private final boolean xOdd;
    private final BigInteger y;

    /**
     * Construct an EdECPoint
     *
     * @param xOdd whether the x-coordinate is odd
     * @param y the y-coordinate, represented using a BigInteger
     *
     * @throws NullPointerException if {@code y} is null.
     */
    public EdECPoint(boolean xOdd, BigInteger y) {

        Objects.requireNonNull(y, "y must not be null");

        this.xOdd = xOdd;
        this.y = y;
    }

    /**
     * Get whether the x-coordinate of the point is odd
     *
     * @return a boolean indicating whether the x-coordinate is odd
     */
    public boolean isXOdd() {
        return xOdd;
    }

    /**
     * Get the y-coordinate of the point.
     *
     * @return the y-coordinate, represented using a BigInteger
     */
    public BigInteger getY() {
        return y;
    }
}
```

**Key Specs**

The API provides transparent spec classes for public and private keys.

Private key spec:

```
package java.security.spec;

import java.util.Objects;

/**
 * A class representing elliptic curve private keys as defined in
 * <a href="https://tools.ietf.org/html/rfc8032">RFC 8032: Edwards-Curve
 * Digital Signature Algorithm (EdDSA)</a>, including the curve and other
 * algorithm parameters. The private key is a bit string represented using
 * a byte array. This class only supports bit string lengths that are a
 * multiple of 8.
 *
 * @since 15
 */
public final class EdECPrivateKeySpec implements KeySpec {

    private final NamedParameterSpec params;
    private final byte[] bytes;

    /**
     * Construct a private key spec using the supplied parameters and
     * bit string.
     *
     * @param params the algorithm parameters
     * @param bytes the key as a byte array. This array is copied
     *              to protect against subsequent modification.
     *
     * @throws NullPointerException if {@code params} or {@code bytes}
     *                              is null.
     */
    public EdECPrivateKeySpec(NamedParameterSpec params, byte[] bytes) {
        Objects.requireNonNull(params, "params must not be null");
        Objects.requireNonNull(bytes, "bytes must not be null");

        this.params = params;
        this.bytes = bytes.clone();
    }

    /**
     * Get the algorithm parameters that define the curve and other settings.
     *
     * @return the algorithm parameters
     */
    public NamedParameterSpec getParams() {
        return params;
    }

    /**
     * Get the byte array representing the private key. A new copy of the array
     * is returned each time this method is called.
     *
     * @return the private key as a byte array
     */
    public byte[] getBytes() {
        return bytes.clone();
    }
}
``` 

Public key spec:

```
package java.security.spec;

import java.util.Objects;

/**
 * A class representing elliptic curve public keys as defined in
 * <a href="https://tools.ietf.org/html/rfc8032">RFC 8032: Edwards-Curve
 * Digital Signature Algorithm (EdDSA)</a>, including the curve and other
 * algorithm parameters. The public key is a point on the curve, which is
 * represented using an EdECPoint.
 *
 * @since 15
 */
public final class EdECPublicKeySpec implements KeySpec {

    private final AlgorithmParameterSpec params;
    private final EdECPoint point;

    /**
     * Construct a public key spec using the supplied parameters and
     * point.
     *
     * @param params the algorithm parameters
     * @param point the point representing the public key
     *
     * @throws NullPointerException if {@code params} or {@code point}
     *                              is null.
     */
    public EdECPublicKeySpec(AlgorithmParameterSpec params, EdECPoint point) {
        Objects.requireNonNull(params, "params must not be null");
        Objects.requireNonNull(point, "point must not be null");

        this.params = params;
        this.point = point;
    }

    /**
     * Get the algorithm parameters that define the curve and other settings.
     *
     * @return the parameters
     */
    public NamedParameterSpec getParams() {
        return params;
    }

    /**
     * Get the point representing the public key
     *
     * @return the EdECPoint representing the public key
     */
    public EdECPoint getPoint() {
        return point;
    }
}
```

Rejected Alternative Solutions
--------
It is technically possible to use existing classes/interfaces for elliptic curve cryptography for these new mechanisms. In this approach, curve parameters would be interpreted differently when supplied to different elliptic curve crypto services. This approach was not selected because it would make the API confusing and error-prone, and may cause compatibility issues.

For example, consider an ECPrivateKeySpec that describes an ECDSA private key. ECPrivateKeySpec contains an ECParameterSpec that includes all of the curve/field parameters including the curve coefficients a and b. For ECDSA, these are the coefficients of a Weierstrass curve y^2 = x^3 + ax + b. For EdDSA, we could use the same class and interpret a and b as the coefficients of a twisted Edwards curve ax^2 + y^2 = 1 + bx^2y^2. Perhaps we would add a field to the ECParameterSpec to indicate how a and b should be interpreted, so that EdDSA implementations could reject ECDSA keys, and vice-versa.

The above solution is problematic when EdDSA private keys are given to an existing ECDSA implementation that has not been modified to check the new field indicating how coefficients should be interpreted. The ECDSA implementation could interpret the coefficients as Weierstrass curve parameters, and perform the signing operation using that curve, instead of the intended Edwards curve. There is no reason to expect that this misinterpreted Weierstrass curve is secure, and the resulting signature could leak information about the private key. There is no reason why a program should supply an EdDSA key to an ECDSA implementation, but it could easily be done inadvertently if they have the same type.   
Comments
Moving to Approved.
19-03-2020

In a discussion with [~mullan] and [~ascarpino] we discussed the proper return type of `getParams`. We agreed `AlgorithmParameterSpec` was not the best type and either `NamedParameterSpec` nor an elliptic curve specific subtype of `NamedParameterSpec` would be a better choice. Moving this request to Provisional with the expectation the return type will be updated as part of finalizing the request.
19-03-2020

The decision was made to use NamedParameterSpec. After prototyping a subtype of NamedParameterSpec, there was little advantage to adding a new type. I am finalizing this CSR.
18-03-2020

Since I'm taking over the JEP, let me sort out things because this CSR has been around for a long time. The intent of the JEP is to provide crypto access to Ed25519 and Ed448 in RFC 8032, using an implementation that is built to be time-constant and branchless. It is not intended to provide access to arbitrary twisted Edward curves and the implementation was not built that way. This whole design is similar to XDH(1). The original AlgorithmParameterSpec for Elliptic Curve, ECParameterSpec, provided access to arbitrary curves because they were configurable through the SunEC/NSS C library. That decision was made 15-20 years ago when EC was new, changing, and unknown because of patents. As EC matured it moved toward named curves where the parameters are mostly defined and away from arbitrary curves. There is a paragraph in RFC 8032 Section 3(2) points to that when setting up the curves: The generic EdDSA digital signature system with its 11 input parameters is not intended to be implemented directly. Choosing parameters is critical for secure and efficient operation. Instead, you would implement a particular parameter choice for EdDSA (such as Ed25519 or Ed448), sometimes slightly generalized to achieve code reuse to cover Ed25519 and Ed448. EdDSAParameterSpec supports getting and setting prehash and the context that affect two of the 11 parameters during the signature process as the RFC specifies. In the cases of RSA and DSA, those parameters were intended to be more flexible. Your example of a modified NamedParameterSpec and a XEParameterSpec is reasonable if it were necessary to set or get these parameters. The implementation prebuilds the parameters as part of the named curves. That is part of the time-constant branchless implementation we have for the supported curves. At this point, there is no reason to believe parameters access will be needed. The name of the curve tells all that's needed about the curve. If for some reason in the future we have requests or a need to access the parameter data, we can re-visit it at that time. 1. https://openjdk.java.net/jeps/324 2. https://tools.ietf.org/html/rfc8032#section-3
29-10-2019

PS Here is a sketch of the technique I'm recommending, but for the prior round of EC changes: diff -r 8af48416e31f src/java.base/share/classes/java/security/spec/NamedParameterSpec.java --- a/src/java.base/share/classes/java/security/spec/NamedParameterSpec.java Tue Mar 26 18:42:10 2019 +0100 +++ b/src/java.base/share/classes/java/security/spec/NamedParameterSpec.java Thu Mar 28 09:00:12 2019 -0700 @@ -25,6 +25,10 @@ package java.security.spec; import java.util.Objects; +import java.math.BigInteger; + +import static java.math.BigInteger.*; + /** * This class is used to specify any algorithm parameters that are determined @@ -45,12 +49,42 @@ * The X25519 parameters */ public static final NamedParameterSpec X25519 - = new NamedParameterSpec("X25519"); + = new Rfc7748ParameterSpec("X25519", + // 2^255 - 19 + TWO.pow(255).subtract(BigInteger.valueOf(19)), + BigInteger.valueOf(486662)); /** * The X448 parameters */ public static final NamedParameterSpec X448 - = new NamedParameterSpec("X448"); + = new Rfc7748ParameterSpec("X448", + // 2^448 - 2^224 - 1 + TWO.pow(448).subtract(TWO.pow(224)).subtract(ONE), + BigInteger.valueOf(156326)); + + private static class Rfc7748ParameterSpec extends NamedParameterSpec + implements javax.crypto.spec.XEParameterSpec { + private BigInteger prime; + private BigInteger a; + + public Rfc7748ParameterSpec(String stdName, + BigInteger prime, + BigInteger a) { + super(stdName); + this.prime = prime; + this.a = a; + // ... + // Consistency checks omitted + } + + @Override public BigInteger getPrime() { + return prime; + } + + @Override public BigInteger getA() { + return a; + } + } private String name; diff -r 8af48416e31f src/java.base/share/classes/javax/crypto/spec/XEParameterSpec.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/java.base/share/classes/javax/crypto/spec/XEParameterSpec.java Thu Mar 28 09:00:12 2019 -0700 @@ -0,0 +1,23 @@ +package javax.crypto.spec; + +import java.math.BigInteger; + +/** + * Appease the doclint checks. + */ +public interface XEParameterSpec extends java.security.spec.AlgorithmParameterSpec { + // Some subset of information defined RFC 7748 + + /** + * Returns the prime number defining the underlying field. + * @return the prime number defining the underlying field + */ + BigInteger getPrime(); + + /** + * Returns element A. A is an element in the finite field GF(p), + * not equal to -2 or 2. + * @return element A + */ + BigInteger getA(); +}
28-03-2019

Re-returning to this request. For more context, I've looked over the set of Key modeling interfaces in the java.security.interfaces package. The getParams methods in the DSAKey and ECKey families of types do return a family-specific type from getParams, DSAParams and ECParameterSpec, respectively. The RSAKey interface was retrofitted with a getParams() method returning AlgorithmParameterSpec in JDK 11 and the XECKey interfaces added in JDK 11 also use AlgorithmParameterSpec for their getParams() method. From general modeling principles, at least from a user with limited crypto expertise, I would expect somewhere in the API for their to be getter methods that provided information about the 11 parameters discussed in the RFC. This is distinct from providing an ability for end-users to create objects with arbitrary values for those 11 parameters. From example, presumably it would be technically possible for the primary (and initially sole) way for users to get the EdEcKey objects was through a NamedParameterSpec object, but the particular NamedParameterSpec object returned could be a subclass that implemented an interface providing access to some subset of the 11 parameters. For example, something like a nested subclass of NamedParameterSpec that also implemented some to-be-defined EdECParameterSpec interface with the appropriate getter methods. Given the precedents of returning AlgorithmParameterSpec for some key families, I'm also willing to discuss doing so here for the EdEC family. Moving back to Provisional.
22-03-2019

In the proposed API, the only type that can be used to specify EdDSA key parameters is NamedParameterSpec, like this: KeyPairGenerator kpg = KeyPairGenerator.getInstance("EdDSA"); NamedParameterSpec namedParams = new NamedParameterSpec("Ed448"); KeyPair kp = kpg.generateKeyPair(); (or using a NamedParameterSpec with a KeyFactory, like in the example in the description). But we also want the API to allow the addition of new types for specifying key parameters. Both NamedParameterSpec and these hypothetical types should fully specify the curve and its domain parameters---they would just do it in different ways. EdDSAParameterSpec cannot be used to specify parameters for keys---its purpose is to specify parameters for the signature operation. So the problem is that the EdECKey.getParameters() could return a NamedParameterSpec or some other type that specifies the key parameters in a different way. If the programmer wanted to inspect the parameters, then checking and downcasting is not the only option. The programmer could also give it to the EdDSA AlgorithmParameters service to try and convert it to the desired type (using AlgorithmParameters.init() followed by AlgorithmParameters.getParamerSpec()). Though the initial implementation of this feature in the JDK will not have this service, and it may not be present in other providers, too.
07-03-2019

To recap the concerns under discussion, it seems limiting to me if the most specific type returned is AlgorithmParameterSpec as that is a marker interface that doesn't define any methods. Therefore, to get information about the parameters, exploratory downcasting is needed. To check my understanding, is it the case that that keys are expected to be created from either, say, NamedParameterSpec or EdDSAParameterSpec objects so there is no single proposed type that encapsulates the information needed to specify the parameter specs?
07-03-2019

We discussed including an AlgorithmParameterSpec subclass that specifies the actual curve domain parameters. We decided against it because allowing support for arbitrary curves greatly complicates the API and implementation. Though the proposed API is designed to allow the addition of classes like this in the future (or by another library). I don't think we discussed including this class as a way to query parameters only. I don't immediately have a strong opposition to this, but I'm not convinced that it is necessary. I'm not sure how the addition of this new class would help with the current issue. We still need to decide which parameter spec is returned by EdECKey.getParams(). Maybe we make a method for each type (e.g. getNamedParams() getDomainParams())?
06-03-2019

Working to swap this review back in, from my reading of RFC 8032 it defines a space of potential curves over numerous parameters ("EdDSA is a digital signature system with 11 parameters.") and defines two particular curves with specific values for those 11 parameters. In the places in the API where AlgorithmParameterSpec is used to return information, is it sensible to define more or more new interfaces capturing a subset of those 11 parameters to allow more direct querying of information about the algorithm?
06-03-2019

[~darcy]: Please let me know the acceptance criteria for the outcome of this exploration of alternatives. For example, if the current proposed solution is determined to be the best one, then what evidence should I provide that supports this conclusion?
17-09-2018

It is uncommon that an API to requiring downcasting is the best API. Marking this request as pended so that alternatives to returning AlgorithmParameterSpec can be explored in more depth.
17-09-2018

I added a couple of sentences in the "Key Interfaces" section describing why AlgorithmParameterSpec is used instead of a more specific type.
12-09-2018

Can the getParams method in EdECKey return a more specific type than AlgorithmParameterSpec, which defines no methods? Moving to Provisional.
08-09-2018