The current PK11ECPublicKey and PK11ECPrivateKey classes do not implement the standard ECPublicKey and ECPrivateKey interfaces. This is required in order to provide an SSL connector for Tomcat that supports EC keys.
See also:
We face a few challenges in implementing this because of the mismatch between Java and NSS. Besides the obvious (supporting getS() likely won't happen for similar reasons as to why getPrivateExponent() isn't supported in the RSA equivalents), some of the other problems are discussed below.
getS()
getPrivateExponent()
References to SECKEYPrivateKey and SECKEYPublicKey. The Public Key does have the publicValue member, which is an "encoded point", though it appears to lack documentation of how it is encoded, other than DER encoding. I'm guessing it is uncompressed.
SECKEYPrivateKey
SECKEYPublicKey
publicValue
The SECEYECParams structure is opaque (well, it appears to be DER encoded... Lovely!). From here we can call SECKEY_GetECCOid(...) to get the curve's OID, but we still need a way to go from SECKEYECPublicKey (or the Private key!) to SECKEYECParams....
SECEYECParams
SECKEY_GetECCOid(...)
SECKEYECPublicKey
SECKEYECParams
Also missing is the generator of the curve and any way to identify the OID of the public key...
The Java interfaces want us to provide an implementation of getParams(). This returns an ECParameterSpec, which in turn requires describing the EllipticCurve and the ECPoint of the curve's generator.
getParams()
ECParameterSpec
EllipticCurve
ECPoint
The most common usages of getGenerator() seem to be with equals() to see if it is in the CurveDB and is a known curve. In KeyUtil, getOrder is called.
getGenerator()
equals()
CurveDB
KeyUtil
getOrder
We also need an implementation of getW() for public keys. This is utilized in ECDHKeyAgreement, among other places. However, it is an ECPoint again, which only seems to support a constructor with a pair of BigIntegers, and no other encodings.
getW()
ECDHKeyAgreement
BigInteger
There are two potential solutions that I can see:
What remains unclear is if we can use AlgorithmParameters to accomplish what we want. The pseudo-code would look like this:
AlgorithmParameters
public ECParameterSpec getParams() { byte[] encoded_params = getParamsNative(); AlgorithmParameters params = ??? params.init(encoded_params); return params.getParameterSpec(ECParameterSpec); }
The problem with the above approach is generating a AlgorithmParameters instance and whether or not the getParamsNative() call can return stuff in the correct format.
getParamsNative()
A lot of the material here is dependent on the curve, not the underlying algorithm. We'd want to provide a Curve-lookup mechanism and return parameters common to that curve, probably based on OID. We can sync it by a lookup table in Java/C similar to the (new) TLS Algorithm list. We can then augment the data returned by the Curve lookup (generator, curve, order, etc.) by the information in the Public/Private key as necessary.
Some of the code in the JDK requires the curve to be a Named Curve (for some reason), however, X25519 isn't a known curve, which is well, a problem. I'm not sure if we can ask them to standardize this curve, but to my knowledge it is neither in JDK8 nor JDK11, so perhaps unlikely for inclusion, especially before it is standardized by NIST for inclusion in FIPS. I'm also not sure if this means JSSE doesn't support x25519 at all for either handshakes or for CA keys.
X25519
x25519
Getting the public key from the private key might be a touch hard. Though, there is SECKEY_ConvertToPublicKey(...).
SECKEY_ConvertToPublicKey(...)
Metadata Update from @cipherboy: - Custom field component adjusted to None - Custom field feature adjusted to None - Custom field origin adjusted to None - Custom field proposedmilestone adjusted to None - Custom field proposedpriority adjusted to None - Custom field reviewer adjusted to None - Custom field type adjusted to None - Custom field version adjusted to None
Ok, so I've gotten the following to work on my add-ecpoint branch:
add-ecpoint
PK11PublicKey
ECPublicKey
getW
ECCurve
PK11KeyGenerator
PK11PrivateKey
SECKEY_ConvertToPublicKey
null
PK11RSAPrivateKey
If the API is not going to be backward compatible we should consider using a new JSS minor version number (i.e. 4.7.x).
Right, but check the version history on this:
@kaie
@emaldonado
@cfu
Note though that "standard interface" is in quotes -- it never implemented ECPublicKey fully -- the return type of getW() was always wrong. IMO, the current return type is useless and misleading: it was never a BigInteger, it was a BigInteger which stored a byte[], which in turn was the ANSI X9.62 ECPoint value Q (a pair, (x, y) of values on a finite field), in something that vaguely looks like DER encoding.
byte[]
(x, y)
In our code base and in Candlepin, nobody uses getW() for that reason. We don't need to worry about most other usages of getW() because nobody's trying to use it via the standard interface (ECPublicKey) yet, because it isn't an interface we implement yet. Nbody can rely on this, as-is.
I'm fine bumping to v4.7 on master, but I'd prefer to backport this to older branches if we can, and we can't cut a new major release out of the v4.4.x series. If we do that, there's no point in bumping to v4.7 on master.
Ah OK, if it never worked properly before it's not necessary to introduce JSS 4.7. Thanks for looking into this!
This is fixed by JSS gh-pr#230. \o/ Wheee!
Metadata Update from @cipherboy: - Issue close_status updated to: fixed - Issue status updated to: Closed (was: Open)
Login to comment on this ticket.