JCA design for RFC 7748

Michael StJohns mstjohns at comcast.net
Fri Aug 18 18:57:43 UTC 2017


On 8/17/2017 7:01 PM, Xuelei Fan wrote:
> On 8/17/2017 11:35 AM, Michael StJohns wrote:
>> On 8/17/2017 1:28 PM, Xuelei Fan wrote:
>>>> This is the same for ANY current publicly known curve - different 
>>>> providers may implement all some or none of them.  So extending 
>>>> this model for the curve25519 stuff isn't going to be any different 
>>>> old provider and new provider wise than is currently the case. If 
>>>> you want the new curves, you have to specify the new providers. If 
>>>> the new and old providers don't implement the same curves, you may 
>>>> need to deal with two different providers simultaneously - and 
>>>> that's not something that just happens.
>>>>
>>> I see your points.  Not-binding to a provider cause problems; 
>>> binding to a provider cause other problems.  There are a few 
>>> complains on the problems, and impact the real world applications in 
>>> practice.
>>
>> Basically, this is a failing of imagination when the various 
>> getInstance() methods were defined.  Now its possible to use 
>> Security.getProvider(Map<String,String>)  to good effect (but more 
>> work) to find appropriate providers for appropriate signature/key 
>> agreement algorithms and curves.
>>
> I'm not sure how this applies to the compatibility impact concern.  
> See more in the example bellow.
>
>>
>>>
>>>
>>>> I don't think your concerns are valid.  I may still be missing 
>>>> something here - but would ask for a real-world example that 
>>>> actually shows breakage.
>>>>
>>> I happened to have a real-world example.  See
>>> https://bugs.openjdk.java.net/browse/JDK-8064330
>>
>> I'm not sure how this applies to the current question of whether or 
>> not its possible to integrate new EC curves?
>>
>>>
>>>
>>> This is an interesting bug.  At first it is requested to support 
>>> SHA224 in JSSE implementation. And, SHA224 is added as the supported 
>>> hash algorithm for TLS.  However, because SunMSCAPI does not support 
>>> SHA224 signature, compatibility issues comes.  So we removed SHA224 
>>> if the SunMSCAPI is presented.  Later, one found the code is unusual 
>>> as SHA224 and the related signature algorithms are supported by the 
>>> underlying providers, look like no reason to limit the use of 
>>> SHA224.  So, SHA224 is added back and then the compatibility issues 
>>> come back again.  Then we removed SHA224 again if the SunMSCAPI is 
>>> presented.  However, at the same time, another request is asking to 
>>> support SHA224 on Windows.  The API design itself put me in a 
>>> either-or situation.  I would try to avoid it if possible for new 
>>> design.
>>
>> This appears to be an MSCAPI issue vice a JSSE issue.
> MSCAPI is fine as it does not support SHA224.  JSSE is then in a bad 
> position because it cannot support SHA224 in a general way even one of 
> the underlying provider supports SHA224 but another one not.

No - I don't think both are fine.   MSCAPI could outsource algorithms it 
doesn't have internally to another provider - for a very limited set of 
classes (e.g. MessageDigest and Secure Random), but it would be smarter 
if JSSE just tried to see of the provider it was already using for other 
stuff had the available algorithm (e.g. using the long form of getInstance).

In the above case - MSCAPI should realize that it can't do a 
SHA224with... signature and just throw the appropriate error.  JSSE 
should know which TLS suites MSCAPI can support.  Or at least be able to 
figure out which ones it supports by checking which JCA algorithms are 
supported.

>
>> And the JCA specifically disclaims the guaranteed ability to use 
>> cryptographic objects from one provider in another provider.
> It's not the real problem.  The real problem is that there is a 
> provider support the requested algorithms, why not use it?  We can 
> say, the spec does not guarantee the behavior, but the application 
> still has a problem.  We also can say, we have a design flaw, but the 
> question is still there.

There is no design flaw, there is only incorrect programming. Basically, 
the only non-key related crypto algorithms in the providers are hashing 
and random number generation.    While its possible to use these across 
providers (and you might want to), special casing things to do this 
means (for example) that your FIPS approved signature mechanism might 
end up using a non-fips summary (hash) mechanism.

Every other crypto mechanism has or involves keys.  And there's no 
guarantee that keys are valid across providers.

>
>> Secondary users like the JSSE probably need to stick to a single 
>> provider for a given connection.
>>
> Stick to a single provider will open other windows for different 
> problems.  JCE spec does not grant one provider could implement all 
> services.

An application that needs to use two different cryptographic algorithm 
providers should be doing that explicitly and not having it happen under 
the covers.   For example, I was using the BC provider to deal with 
elliptic curve stuff for a long while.  That meant I was also using BC 
to deal with certificates (because the Sun provider didn't understand 
how to deal with the BC's ECKey implementation).   It was kind of a 
surprise at the time, but made me quite a bit more cautious about making 
sure I didn't leave the selection of the provider up to Java if I was 
doing anything remotely complicated.

Mostly a given provider has to implement all of the concrete classes 
that support a given class of key material - key generation, signatures, 
encryption etc.  Given the internal representation of the concrete 
classes can be anything I wouldn't expect a key generated by provider A 
to work with provider B without some conversion taking place.  In both 
the RSA and EC key spaces, I can convert a key to a spec, then then back 
to a key with minimal problems.  The spec contains ALL of the 
information I need to get a mathematically correct key out the back 
side.  Those keys (mostly the public ones) just work because under the 
covers good providers are running alien keys through a KeyFactory to get 
local keys they can use.


>
>>>
>>>
>>>> Treat these simply as new curves and let's move forward with very 
>>>> minimal changes to the public API.
>>>>
>>> I would like to treat it as two things.  One is to support new 
>>> curves for new forms.  The other one is to support named curves 
>>> [1].  For the support of new forms,  there are still significant 
>>> problems to solve. For the support of named curves (including the 
>>> current EC form), looks like we are in a not-that-bad situation 
>>> right now.  Will the named curves solution impacts the support of 
>>> new curves APIs in the future?  I don't see the impact yet.  I may 
>>> missing something, but I see no reason to option out the named 
>>> curves support.
>>>
>>
>> I'm not sure why you think this (the example in [1]) can't be done?
>>
>> I gave the example elsewhere, but let me expand it with my comment 
>> above (possibly faking the hash key names - sorry):
>>
>>>         HashMap<String,String> neededAlgs = new HashMap<>();
>>>     neededAlgs.put("Signature.EdDSA", "");
>>>          neededAlgs.put("AlgorithmParameters.EC SupportedCurves", 
>>> "ed25519")
>>
>>
>>> Provider[] p = Security.getProviders(neededAlgs);
>>> if (p == null) throw new Exception ("Oops");
>>
>>> AlgorithmParameters parameters = 
>>> AlgorithmParameters.getInstance("EC", p[0]);
>>>          parameters.init(new ECGenParameterSpec("ed25519"));
>>>          ECParameterSpec ecParameters = 
>>> parameters.getParameterSpec(ECParameterSpec.class);
>>>
>>>          return KeyFactory.getInstance("EC", 
>>> p[0]).generatePublic(new ECPublicKeySpec(new ECPoint(x, y), 
>>> ecParameters));
>>
> Hm, good example!
>
> But it is really too weight to use for general application development.

Umm..  right now about 90+% of the EC stuff focuses on one of the NIST 
curves and pretty much all providers implement those.  But  - the set of 
curves that SunEC supports is different than the set of curves that 
BouncyCastle supports and I have to take that in consideration when 
picking the curve and the provider for my application.

I can either know which provider has which curves up front  (or assume 
they all have the most common curves) and pick the right provider and 
hard code it (and that will work mostly), or use something like the 
above and just have it work going forward.

>
> In the example, two crypto operations ("EC" AlgorithmParameters and 
> "EC" KeyFactory) are supported in the same provider.   In practice, 
> two crypto operations may be supported in different providers.

Actually, in this specific case you COULD use different providers - but 
they'd both have to understand what was in the ECParameterSpec in a 
non-proprietary way.   The first (AlgorithmParameter) provider would 
generate an ECParameterSpec which the second provider (the KeyFactory 
provider) would convert into a concrete public key (along with the other 
data).  Sort of the definition of the use of 'Spec classes.

In the above example, I know this works with the SunEC provider for the 
AlgorithmParameter side - but I'm pretty sure it doesn't work for the 
BouncyCastle side.

>
>> If you're talking more generally, NamedCurves should be a form of 
>> ECParameterSpec so you can read the name from the key, but there's no 
>> support for adding names to that spec.  Maybe extend it?  E.g.:
>>
>> package java.security.spec;
>> public class NamedECParameterSpec extends ECParameterSpec {
>>
>>     private Collection<String> names;
>>     private Collection<Oid> oids;
>>     public NamedECParameterSpec (EllipticCurve curve, ECPoint g, 
>> BigInteger n, int h, Collection<String> names, Collection<Oid> oids) {
>>          super (curve, g, n, h);
>>          if (names != null) {
>>              this.names = new ArrayList<String>(names);
>>          }
>>          if (oids != null) {
>>              this.oids = new ArrayList<Oid>(oids);
>>         }
>>    }
>>
>>     public Collection<String> getNames() {
>>          if (names == null)
>>               return (Collection<String>)Collections.EMPTY_LIST;
>>           else
>>              return Collections.unmodifiableList(names);
>>      }
>>
>>      etc....
>>
>>     This makes it easier to get exactly what you want from a key. 
>> Assuming the provider implements it.
>>
> I see your points.  But my concerns are not really about it. Except 
> the confusing and possibility to map/convert Montgomery curve or 
> Edwards curve or other forms [3][4] to Weierstrass form, I did not see 
> how the new proposal solve the problems I described in the previous 
> mails [1][2].
If by [1] you mean "There is no public api for named curves" - I would 
say that the above actually does provide part of that solution.  There 
are a number of times when I'm trying to convert a public key from Java 
to a smart card where I need to know the curve.  Being able to grab the 
curve name directly from the ECKey->ECParameterSpec would be useful.  If 
you mean there is no lookup by name to get direct to an ECParameterSpec 
- sure, but there are two work arounds.  The one in [1] and the other 
involving generating a key pair using ECGenParameterSpec with the curve 
name and then grabbing the ECParameterSpec from it.  The latter works 
with all providers, but seems clumsy.

I actually think the above solves a bunch of what you want for [2].   
((NamedECParameterSpec)pubKey.getParameterSpec()).getNames()

Your idea in section 4 of [2] makes me uncomfortable as it *really* 
changes the model for parameter based keys (EC, DSA and the new stuff).  
Would you move all of the old key and curves over to a new key type?  
(E.g. the OKPKey stuff).  Would you carry over all the backwards 
compatibility stuff (e.g. the complete set of curve parameters needed 
for the math) in those keys?  If not would you require additional curves 
to be accessible both the old and new ways?

The current stuff for Security.getProviders(Map<String,String> filters) 
does what you want in section 4 - just in a few more lines.


Later, Mike

>
> Xuelei
>
>>> [1]: 
>>> http://mail.openjdk.java.net/pipermail/security-dev/2013-October/009105.html 
>>
> [2]: 
> http://mail.openjdk.java.net/pipermail/security-dev/2017-August/016194.html
> [3]: https://crypto.stanford.edu/pbc/notes/elliptic/explicit.html
> [4]: http://mathworld.wolfram.com/EllipticCurve.html





More information about the security-dev mailing list