JCA design for RFC 7748

Michael StJohns mstjohns at comcast.net
Tue Aug 15 23:05:13 UTC 2017


On 8/15/2017 1:43 PM, Xuelei Fan wrote:
> On 8/11/2017 7:57 AM, Adam Petcher wrote:
>> On 8/10/2017 9:46 PM, Michael StJohns wrote:
>>
>>> On 8/10/2017 7:36 PM, Xuelei Fan wrote:
>>>>> Right now there are 3 major APIs (JCA, PKCS11 and Microsoft CSP) 
>>>>> and at least 4 major representational domains (Raw, PKIX, XML and 
>>>>> JSON).  In the current situation, I can take a JCA EC Public key 
>>>>> and convert it to pretty much any of the other APIs or 
>>>>> representations. For much of the hardware based stuff (ie, smart 
>>>>> cards), I go straight from JCA into raw and vice versa. Assuming 
>>>>> you left the "getEncoded()" stuff in the API and the encoding was 
>>>>> PKIX, I'd have to encode to PKIX, decode the PKIX to extract the 
>>>>> actual raw key or encode a PKIX blob and hope that the KeyFactory 
>>>>> stuff actually worked.
>>>>>
>>>>> It's not just support of arbitrary keys, but the ability to 
>>>>> convert things without having to do multiple steps or stages.
>>>>>
>>>> Good point!  It would be nice if transaction between two formats 
>>>> could be done simply.  Using X.509 encoding is doable as you said 
>>>> above, but maybe there are spaces to get improvements.
>>>>
>>>> I need more time to think about it.  Please let me know if any one 
>>>> have a solution to simplify the transaction if keeping use the 
>>>> proposed named curves solution.
>>>>
>>
>> I'm also coming to the conclusion that using X.509 encoding for this 
>> sort of interoperability is too onerous, and we should come up with 
>> something better. Maybe we should add a new general-purpose interface 
>> that exposes some structure in an algorithm-independent way. 
>> Something like this:
>>
>> package java.security.interfaces;
>> public interface ByteArrayValue {
>>
>>      String getAlgorithm();
>>      AlgorithmParameterSpec getParams();
>>      byte[] getValue();
>> }
>>
> I'm not sure how to use the above interface in an application.

This is sort of the moral equivalent of using the TXT RR record in DNS 
and the arguments are similar.

This is a bad idea.

>
> I don't worry about this issue any more.  At present, each 
> java.security.Key has three characters (see the API Java doc):
> . an algorithm
> . an encoded form
> . a format
>
> The format could be "X.509", and could be "RAW" (like 
> ByteArrayValue.getValue()).  I would suggest have the named curve in 
> the algorithm characters, and use "RAW" as the encode format.
> If X.509 encoding is required, KeyFactory.getKeySpec​() could do it.
Um... I think that doesn't make a lot of sense.  The default contract 
for public keys is X.509 and the default for private keys is PKCS#8.  
Almost all uses of the encoded formats are related to PKIX related 
functions.   (See for info the javadoc for PublicKey).

Raw formats are used pretty much exclusively for symmetric keys.

The KeyFactory.getKeySpec() requires an actual KeySpec definition which 
is different than the ByteArrayValue stuff being proposed above.

To be JCA compliant you need all of:

1) A master interface (e.g. ECKey) that's a marker interface for key 
material
2) A public key interface that extends PublicKey and the master interface
3) A private key interface that extends PrivateKey and the master interface
4) A public key specification that implements KeySpec
5) A private key specification that implements KeySpec
6) A generation parameter specification that implements 
AlgorithmParameterSpec
7) A key parameter specification (if required by the master interface)
8) A factory class that implements KeyFactoryImpl taht implements 
AlgorithmParameterSpec
9) A common encoding for each of the public and private keys
10) A transform to/from the public and private key specs


Here's what I think should happen:

1) ECPoint gets a document modification to handle compressed points.  
The X is the X value, the Y is -1, 0 or 1 depending on positive negative 
or don't care for the sign of the Y value.   (This means that the byte 
array public key gets handled as a BigInteger). Any value other than 0, 
-1 or 1 for Y indicates a normal X Y point.

2) EllipticCurve gets a document modification to describe the mappings 
for Edwards and Montgomery curves as discussed previously.

3) Two classes are added to java.security.spec: 
java.security.spec.ECFieldEdwards and 
java.security.spec.ECFieldMontgomery - both of which implement ECField.

4) The ECFieldEdwards/Montgomery classes contain an indication of 
whether the curve is signature only, key agreement only or both. They 
also contain any parameters that can't be mapped in EllipticCurve

5) Using the above, someone specifies the curve sets for the four new 
curves as ECParameterSpec's and we iterate until we're satisfied we've 
got a standard public representation that can be used for other than the 
4 curves.

6) Until the JCA is updated, a provider for the new curves can use its 
own concrete ECField classes and later make them be subclasses of the 
java.security.spec.ECFieldMontgomery etc.  It's not ideal, but it does 
let the guys who are chomping at the bit do an implementation while 
waiting for the JCA to be updated.

7) No other changes to the JCA are made.  The providers implement 
SubjectPublicKeyInfo and PKCS8 as the standard encodings  using the 
definitions in 
https://tools.ietf.org/html/draft-ietf-curdle-pkix-newcurves-00 and RFC5480.

The new keys remain tagged as ECKeys.  Old code won't notice (because 
old code is using old curves).  New code (new providers) will have to 
pay attention to EllipticCurve and ECField information if its handling 
both types of curves.  As is the case now, no provider need support 
every curve or even every field type.

Mike

>
> Xuelei
>
>> The actual value is encoded, but the parameters are exposed, so this 
>> interface would work well for any value that is generally represented 
>> using a single encoded value (like public/private keys in RFC 7748, 
>> and 8032). This could be used with the new NamedParameterSpec class 
>> to identify the parameters by name. It could also be used with other 
>> parameter specs to specify curve coefficients.
>>
>> Of course, you may still need to look up curve name/OID/coefficients 
>> based on the parameters, but at least this solution provides direct 
>> access to the parameters and raw value, and you wouldn't need to go 
>> through X.509. Though perhaps this is less appropriate for SEC1 types 
>> and XML/JSON, because you would need to parse the value to extract 
>> the x and y coordinates. So using the existing ECKey for those types 
>> may make more sense.
>>
>>
>>
>>




More information about the security-dev mailing list