Re: JCA design for RFC 7748

2017-08-10 Thread Xuelei Fan

On 8/10/2017 6:46 PM, Michael StJohns wrote:

On 8/10/2017 7:36 PM, Xuelei Fan wrote:

Hi Michael,

Good points!  See comments inlines.

On 8/10/2017 3:20 PM, Michael StJohns wrote:


Instead of converting, I was thinking about mapping.  E.g. Montgomery 
A and B matches the A and B of the curve.  But the "x" of the 
Montgomery point is just the "x" of the ECPoint with the "y" left as 
null.  For Edwards, it looks like you would map "d" to A. For [3] I'd 
map "r" to A.  I'd leave B as null for both- no reason to throw an 
unsupported exception as the code generally has a clue about what 
types of keys they're dealing with (or we provide a marker so they 
can figure it out).


The conversion in and out for points is a conversion from little 
endian to big endian and vice versa, but that only has to be done if 
you're importing or exporting a parameter set and that's an 
implementation issue not an API issue.


Basically, all the math is BigIntegers under the hood.  The 
curve25519 RFC specifies an implementation that's little endian, but 
the actual math is just math and things like the public key is really 
just a BigInteger.


Old code would just continue to work - since it would not be using 
the new curves.  New code would have to look for the curve type 
marker (e.g. the ECField) if there was the possibility of confusion.


I understand your points.  The mapping may be confusing to application 
developers, but no problem for new codes if following the new coding 
guideline.  I'm not very sure of the old code, for similar reason to 
use the converting solution.


For example, an Edwards curve form of the SubjectPublicKeyInfo field 
in a X.509 cert is parsed as X509EncodedKeySpec, and "EC" KeyFactory 
is used to generate the ECPublicKey.  The algorithm name of the 
ECPublicKey instance is "EC", and the parameter is an instance of 
ECParameterSpec. Somehow, the ECPublicKey leave the key generation 
environment, and the curve OID is unknown in the new environment. Then 
the public could be used improperly.  In the past, it's fine as the 
only supported form is Weierstrass form, there is no need to tell the 
curve forms in a crypto implementation.  However, when a new form is 
introduces, identify the EC form of a key is an essential part for the 
following crypto operations. Old providers or codes may not be able to 
tell the form, as may result in compatibility issues.


I don't think any of this is an issue.   An X509EncodedKeySpec for 
either type of key has a id-ecPublicKey OID identifying it (embedded in 
the SubjectPublicKeyInfo encoding).  In the key body, there's the 
EcpkParameters structure which is a 'namedCurve' which consists of an 
OID.  The curve OIDs for 25519 and 447 are different than any of the 
Weiserstrass keys.   When the KeyFactory factory implementation reads 
the byte stream its going to build a JCA ECPublicKey that matches the 
OID AND that's a concrete ECPublicKey class of the key factory provider.


If the factory implementation doesn't understand the oid, then the 
provider throws an error.  I forget which one.

> The concrete class for the ECPublic key is specific to the provider.
Some providers may support the new key forms, some may not.  There's no 
guarantee (and there never has been a guarantee) that an ECPublic key 
from one provider can be used with another provider (e.g. PKCS11 
provider vs a software provider) - you have to convert the key into a 
keyspec and then run the factory method on it.


I'm not sure of it.  JDK is a multiple providers framework.  A key 
generated in one provider may work in another provider, as if the 
conversion of the key works.  It's not rare that the public key is 
parsed by one provider, and used in another provider.  For some cases, 
we don't have conversion problem in the past as the key spec is clear. 
But for some other cases, we do have problems.  But if a case works in 
the past, we don't want to break it; otherwise, it might be a kind of 
compatibility issues.


As we discussed, there are multiple forms of EC curves.  EC curves form 
is an essential part of a EC key for following operation.  As if the EC 
curves form is unknown, there are potential problems.  When a old 
provider try to use a new provider generated keys for a new forms, 
problems happens.  This actually can be avoid if the old provider does 
not support this algorithm.  The "EC" name is too general to accept new 
forms.


So I don't think there's anything we have to worry about here - no 
violation of the API contract as far as I can tell.


(As a more complete example - consider what happens when you have an F2M 
EC provider and an Fp EC provider both generating public keys and 
encoding them.  Neither provider can decode the other's encoded key 
because they don't have the OIDs and the parameter sets).


If we define all of the forms at the same time, a provider would follow 
the specs, and no compatibility issues.  However, if we add something 
new later, and 

Re: JCA design for RFC 7748

2017-08-10 Thread Michael StJohns

On 8/10/2017 7:36 PM, Xuelei Fan wrote:

Hi Michael,

Good points!  See comments inlines.

On 8/10/2017 3:20 PM, Michael StJohns wrote:


Instead of converting, I was thinking about mapping.  E.g. Montgomery 
A and B matches the A and B of the curve.  But the "x" of the 
Montgomery point is just the "x" of the ECPoint with the "y" left as 
null.  For Edwards, it looks like you would map "d" to A. For [3] I'd 
map "r" to A.  I'd leave B as null for both- no reason to throw an 
unsupported exception as the code generally has a clue about what 
types of keys they're dealing with (or we provide a marker so they 
can figure it out).


The conversion in and out for points is a conversion from little 
endian to big endian and vice versa, but that only has to be done if 
you're importing or exporting a parameter set and that's an 
implementation issue not an API issue.


Basically, all the math is BigIntegers under the hood.  The 
curve25519 RFC specifies an implementation that's little endian, but 
the actual math is just math and things like the public key is really 
just a BigInteger.


Old code would just continue to work - since it would not be using 
the new curves.  New code would have to look for the curve type 
marker (e.g. the ECField) if there was the possibility of confusion.


I understand your points.  The mapping may be confusing to application 
developers, but no problem for new codes if following the new coding 
guideline.  I'm not very sure of the old code, for similar reason to 
use the converting solution.


For example, an Edwards curve form of the SubjectPublicKeyInfo field 
in a X.509 cert is parsed as X509EncodedKeySpec, and "EC" KeyFactory 
is used to generate the ECPublicKey.  The algorithm name of the 
ECPublicKey instance is "EC", and the parameter is an instance of 
ECParameterSpec. Somehow, the ECPublicKey leave the key generation 
environment, and the curve OID is unknown in the new environment.  
Then the public could be used improperly.  In the past, it's fine as 
the only supported form is Weierstrass form, there is no need to tell 
the curve forms in a crypto implementation.  However, when a new form 
is introduces, identify the EC form of a key is an essential part for 
the following crypto operations. Old providers or codes may not be 
able to tell the form, as may result in compatibility issues.


I don't think any of this is an issue.   An X509EncodedKeySpec for 
either type of key has a id-ecPublicKey OID identifying it (embedded in 
the SubjectPublicKeyInfo encoding).  In the key body, there's the 
EcpkParameters structure which is a 'namedCurve' which consists of an 
OID.  The curve OIDs for 25519 and 447 are different than any of the 
Weiserstrass keys.   When the KeyFactory factory implementation reads 
the byte stream its going to build a JCA ECPublicKey that matches the 
OID AND that's a concrete ECPublicKey class of the key factory provider.


If the factory implementation doesn't understand the oid, then the 
provider throws an error.  I forget which one.


The concrete class for the ECPublic key is specific to the provider.  
Some providers may support the new key forms, some may not.  There's no 
guarantee (and there never has been a guarantee) that an ECPublic key 
from one provider can be used with another provider (e.g. PKCS11 
provider vs a software provider) - you have to convert the key into a 
keyspec and then run the factory method on it.


So I don't think there's anything we have to worry about here - no 
violation of the API contract as far as I can tell.


(As a more complete example - consider what happens when you have an F2M 
EC provider and an Fp EC provider both generating public keys and 
encoding them.  Neither provider can decode the other's encoded key 
because they don't have the OIDs and the parameter sets).









However, I'm not very sure of the compatibility impact (see above).

3. Where we are not now?
Using named curves is popular.  There is a ECGenParameterSpec class 
using named curves:

 ECGenParameterSpec​ ecgp =
 new ECGenParameterSpec​(secp256r1);
 KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC");
 kpg.initialize(ecpg);
 KeyPair kp = kpg.generateKeyPair​();

 ECPublicKey pubKey = (ECPublicKey)kp.getPublic();
 String keyAlgorithm = pubKey.getAlgorithm​();  // "EC"

However, it is used for key generation only.  Once the keys are 
generated, there is no public API to know the name of the curve in 
ECKey.  ECKey.getAlgorithm() will return "EC" only. If it is 
required to known whether a key is of a named curve, the solution is 
not straightforward.


This ties back to "getEncoded()" representations.  Under the hood, if 
you do a getEncoded() there's a "which name does this parameter set 
match up to" search which checks various tables for an OID and uses 
that in an X.509 SPKI output object.  On input, the table lookup has 
to see whether or not it understands the curve OID (or the key type 

Re: CSR Review for 8159544: Remove deprecated classes in com.sun.security.auth.**

2017-08-10 Thread Weijun Wang
Done.

Thanks
Max

> On Aug 10, 2017, at 11:36 PM, Sean Mullan  wrote:
> 
> On 8/9/17 8:02 PM, Weijun Wang wrote:
>> Looks fine. Should the specification part be formatted with  and fixed 
>> fonts?
> 
> Fixed. Can you add your name as Reviewer (you need to edit the CSR and add 
> your name to the "Reviewed By" box).
> 
> Thanks,
> Sean
> 
>> Thanks
>> Max
>>> On Aug 10, 2017, at 3:15 AM, Sean Mullan  wrote:
>>> 
>>> Max,
>>> 
>>> Could you please review the following CSR:
>>> 
>>> https://bugs.openjdk.java.net/browse/JDK-8186047
>>> 
>>> Thanks,
>>> Sean



Re: JCA design for RFC 7748

2017-08-10 Thread Xuelei Fan

Hi Michael,

Good points!  See comments inlines.

On 8/10/2017 3:20 PM, Michael StJohns wrote:

Hi Xuelei -

Great analysis.

Some comments in line.

On 8/10/2017 3:10 PM, Xuelei Fan wrote:

Hi,

I want to extend the comment a little bit.

1. The background
A elliptic curve is determined by either an equation of form
 y^2 = x^3 + ax + b(1) [Weierstrass form]
or
 y^2 + xy = x^3 + ax^2 + b.(2)

However, some other forms may also be used.  For example:
 y^2 = x(x-1)(x-r) (3)
or
 By^2 = x^3 + Ax^2 + x (4) [RFC 7748, Montgomery curve]
 x^2 + y^2 = 1 + dx^2y^2   (5) [RFC 7748, Edwards curve]

In general, any elliptic curve can be written in Weierstrass form (1) 
or (2).  That's, Montgomery curve and Edwards curve can be expressed 
in Weierstrass form.


2. Where we are now?
In JDK, an elliptic curve is defined in the Weierstrass form 
((1)/(2)). See java.security.spec.EllipticCurve:


EllipticCurve​(ECField field, BigInteger a, BigInteger b)

In theory, the existing APIs can be used for RFC 7748, by converting 
the Montgomery curve and Edwards curve to the Weierstrass form. 
However, the conversion can be misleading and complicate the 
implementation significantly.  For example, before using a point 
Weierstrass form (x, y), the implementation need to convert it to 
Montgomery curve (x', -) so as to use the fully potential of RFC 
7748.   The curves returned in public APIs need to use (x, y), while 
the implementation need to use (x', y'). It's very confusing and the 
compatibility impact could be significant.  For example:


public something(ECPublicKey ecPublicKey)  {
   // Problem: If no other information, it is unclear
   // whether the ecPublicKey can be used for a particular
   // signature verification or not when the RFC 7748/8032
   // get supported.

   // Problem: an old application may use ecPublicKey for
   // the old style operation, even the ecPublicKey is supposed
   // to be x25519.  It's not easy to control the behavior in
   // legacy application code, and may introduce unexpected
   // security issues.
}

public KeyAgreement getKeyAgreement(AlgorithmParameterSpec aps) {
   // Problem: the code bellow should be comment in the current
   // code.  However, the ECParameterSpec may not be able to use
   // for the old style "EC" key agreement.
   //
   // JDK crypto provider can take special action to avoid this
   // issue in the JCA/JCE implementation.  But it cannot be
   // granted other provider can do this as well, and old
   // provider may run into problems as well.
   if (aps instance of ECParameterSpec) {
   return KeyAgreement.getInstance("EC");
   }
}

What's the problem with ECPublicKey/ECPrivateKey/ECKey? It's mainly 
about the ECParameterSpec:


 ECParameterSpec ECKey.getParams​()

and ECParameterSpec is using java.security.spec.EllipticCurve. This 
design makes it pretty confusing to use ECPublicKey/ECPrivateKey/ECKey 
for RFC 7748 (Edwards curve form and Montgomery curve form).


Can EllipticCurve be extended to support more forms? The 
java.security.spec.EllipticCurve defines two methods to get the 
coefficients of Weierstrass form.

 public BigInteger getA()
 public BigInteger getB()

The 'A' and 'B' may not exist in other forms, for example the 
(3)(4)(5) forms above.  While, the spec might be able to be updated by 
throwing UnsupportedOperationException for getA() and getB() for the 
(3)(4)(5) forms, and define new extended classes for new forms, like:

 public MCEllipticCurve extends EllipticCurve   // Montgomery curve
 public EDEllipticCurve extends EllipticCurve   // Edwards curve


Instead of converting, I was thinking about mapping.  E.g. Montgomery A 
and B matches the A and B of the curve.  But the "x" of the Montgomery 
point is just the "x" of the ECPoint with the "y" left as null.  For 
Edwards, it looks like you would map "d" to A. For [3] I'd map "r" to 
A.  I'd leave B as null for both- no reason to throw an unsupported 
exception as the code generally has a clue about what types of keys 
they're dealing with (or we provide a marker so they can figure it out).


The conversion in and out for points is a conversion from little endian 
to big endian and vice versa, but that only has to be done if you're 
importing or exporting a parameter set and that's an implementation 
issue not an API issue.


Basically, all the math is BigIntegers under the hood.  The curve25519 
RFC specifies an implementation that's little endian, but the actual 
math is just math and things like the public key is really just a 
BigInteger.


Old code would just continue to work - since it would not be using the 
new curves.  New code would have to look for the curve type marker (e.g. 
the ECField) if there was the possibility of confusion.


I understand your points.  The mapping may be confusing to 

Re: JCA design for RFC 7748

2017-08-10 Thread Xuelei Fan

Hi,

I want to extend the comment a little bit.

1. The background
A elliptic curve is determined by either an equation of form
 y^2 = x^3 + ax + b(1) [Weierstrass form]
or
 y^2 + xy = x^3 + ax^2 + b.(2)

However, some other forms may also be used.  For example:
 y^2 = x(x-1)(x-r) (3)
or
 By^2 = x^3 + Ax^2 + x (4) [RFC 7748, Montgomery curve]
 x^2 + y^2 = 1 + dx^2y^2   (5) [RFC 7748, Edwards curve]

In general, any elliptic curve can be written in Weierstrass form (1) or 
(2).  That's, Montgomery curve and Edwards curve can be expressed in 
Weierstrass form.


2. Where we are now?
In JDK, an elliptic curve is defined in the Weierstrass form ((1)/(2)). 
See java.security.spec.EllipticCurve:


EllipticCurve​(ECField field, BigInteger a, BigInteger b)

In theory, the existing APIs can be used for RFC 7748, by converting the 
Montgomery curve and Edwards curve to the Weierstrass form.  However, 
the conversion can be misleading and complicate the implementation 
significantly.  For example, before using a point Weierstrass form (x, 
y), the implementation need to convert it to Montgomery curve (x', -) so 
as to use the fully potential of RFC 7748.   The curves returned in 
public APIs need to use (x, y), while the implementation need to use 
(x', y').  It's very confusing and the compatibility impact could be 
significant.  For example:


public something(ECPublicKey ecPublicKey)  {
   // Problem: If no other information, it is unclear
   // whether the ecPublicKey can be used for a particular
   // signature verification or not when the RFC 7748/8032
   // get supported.

   // Problem: an old application may use ecPublicKey for
   // the old style operation, even the ecPublicKey is supposed
   // to be x25519.  It's not easy to control the behavior in
   // legacy application code, and may introduce unexpected
   // security issues.
}

public KeyAgreement getKeyAgreement(AlgorithmParameterSpec aps) {
   // Problem: the code bellow should be comment in the current
   // code.  However, the ECParameterSpec may not be able to use
   // for the old style "EC" key agreement.
   //
   // JDK crypto provider can take special action to avoid this
   // issue in the JCA/JCE implementation.  But it cannot be
   // granted other provider can do this as well, and old
   // provider may run into problems as well.
   if (aps instance of ECParameterSpec) {
   return KeyAgreement.getInstance("EC");
   }
}

What's the problem with ECPublicKey/ECPrivateKey/ECKey? It's mainly 
about the ECParameterSpec:


 ECParameterSpec ECKey.getParams​()

and ECParameterSpec is using java.security.spec.EllipticCurve.  This 
design makes it pretty confusing to use ECPublicKey/ECPrivateKey/ECKey 
for RFC 7748 (Edwards curve form and Montgomery curve form).


Can EllipticCurve be extended to support more forms? The 
java.security.spec.EllipticCurve defines two methods to get the 
coefficients of Weierstrass form.

 public BigInteger getA()
 public BigInteger getB()

The 'A' and 'B' may not exist in other forms, for example the (3)(4)(5) 
forms above.  While, the spec might be able to be updated by throwing 
UnsupportedOperationException for getA() and getB() for the (3)(4)(5) 
forms, and define new extended classes for new forms, like:

 public MCEllipticCurve extends EllipticCurve   // Montgomery curve
 public EDEllipticCurve extends EllipticCurve   // Edwards curve

However, I'm not very sure of the compatibility impact (see above).

3. Where we are not now?
Using named curves is popular.  There is a ECGenParameterSpec class 
using named curves:

 ECGenParameterSpec​ ecgp =
 new ECGenParameterSpec​(secp256r1);
 KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC");
 kpg.initialize(ecpg);
 KeyPair kp = kpg.generateKeyPair​();

 ECPublicKey pubKey = (ECPublicKey)kp.getPublic();
 String keyAlgorithm = pubKey.getAlgorithm​();  // "EC"

However, it is used for key generation only.  Once the keys are 
generated, there is no public API to know the name of the curve in 
ECKey.  ECKey.getAlgorithm() will return "EC" only.  If it is required 
to known whether a key is of a named curve, the solution is not 
straightforward.


4. A general proposal
Support named curves could be a solution for #2 and #3 concerns above. 
For named curves, the parameters are defined explicitly.  So, it is 
REQUIRED to have the public APIs for named curves' parameters any more. 
It can be something hidden in the implementation layer.  The key pair 
generation may looks like:


KeyPairGenerator kpg =
KeyPairGenerator.getInstance("ECWithSecp256k1");
KeyPair kp = kpg.generateKeyPair​();

PublicKey pubKey = kp.getPublic();
String keyAlgorithm = pubKey.getAlgorithm​();  // "ECWithSecp256k1"

As no explicit parameters is required, the 

Re: JCA design for RFC 7748

2017-08-10 Thread Michael StJohns

On 8/10/2017 9:44 AM, Adam Petcher wrote:
Does anyone know of a particular use case (that we haven't discuss 
already) that would require a provider to support arbitrary curves? 
Any other arguments for or against this feature? 


There are uses for changing out the base point.  PAKE and SPAKE use 
similar math (e.g. G^s*sharedSecret is the equivalent of a new base point).


There are uses for private curves - e.g. when you want to actually be 
sure that the curve was randomly generated (sort of the same argument 
that got us to Curve25519 in the first place).


There are the whole set of Edwards curves that are mostly not included 
in any provider (except possible Microsoft's) as of yet.


Basically, you're trying to argue that there are no better curves (for 
the 'new' math) than have already been specified and there never will 
be.  I think that's a very shortsighted argument.


Later, Mike




Re: CSR Review for 8159544: Remove deprecated classes in com.sun.security.auth.**

2017-08-10 Thread Sean Mullan

On 8/9/17 8:02 PM, Weijun Wang wrote:

Looks fine. Should the specification part be formatted with  and fixed 
fonts?


Fixed. Can you add your name as Reviewer (you need to edit the CSR and 
add your name to the "Reviewed By" box).


Thanks,
Sean



Thanks
Max


On Aug 10, 2017, at 3:15 AM, Sean Mullan  wrote:

Max,

Could you please review the following CSR:

https://bugs.openjdk.java.net/browse/JDK-8186047

Thanks,
Sean




Re: JCA design for RFC 7748

2017-08-10 Thread Adam Petcher

Anyone have any additional thoughts on this?

I think the most significant item we need to discuss is the extent to 
which JCA should allow curve parameters for RFC 7748/8032 to be 
specified over the API. Does anyone know of a particular use case (that 
we haven't discuss already) that would require a provider to support 
arbitrary curves? Any other arguments for or against this feature?



On 8/7/2017 4:37 PM, Adam Petcher wrote:
I'm working on the Java implementation of RFC 7748 (Diffie-Hellman 
with X25519 and X448). I know some of you have been anxious to talk 
about how this would fit into JCA, and I appreciate your patience 
while I learned enough about JCA and existing crypto implementations 
to develop this API proposal. This API/design proposal is for RFC 7748 
only, and it does not include the API for RFC 8032 (EdDSA). Of course, 
I expect many of the decisions that we make for RFC 7748 will also 
impact RFC 8032.


First off, I think it is important to separate RFC 7748 from the 
existing ECDH API and implementation. RFC 7748 is a different 
standard, it uses different encodings and algorithms, and it has 
different properties. Further, this separation will reduce the 
probability of programming errors (e.g. accidentally interpreting a 
Weierstrass point as an RFC 7748 point). So I propose that we use 
distinct algorithm names for RFC 7748, and that we don't use any of 
the existing EC classes like EllipticCurve and ECPoint with RFC 7748.


We can achieve this separation without duplicating a lot of code if we 
start with some simplifying assumptions. My goal is to remove 
functionality that nobody needs in order to simplify the design and 
API. If I am simplifying away something that you think you will need, 
please let me know.


A) We don't need to expose actual curve parameters over the API. 
Curves can be specified using names (e.g. "X25519") or OIDs. The 
underlying implementation will likely support arbitrary Montgomery 
curves, but the JCA application will only be able to use the supported 
named curves.
B) We don't need direct interoperability between different providers 
using opaque key representations. We can communicate with other 
providers using X509/PKCS8 encoding, or by using KeyFactory and key 
specs.


These two assumptions greatly simplify the API. We won't need classes 
that mirror ECParameterSpec, EllipticCurve, ECPoint, ECField, 
ECPublicKey, etc. for X25519/X448.


Now that the motivation and assumptions are out of the way, here is a 
description of the proposed JCA API:


1) The string "XDH" will be used in getInstance() to refer to all 
services related to RFC 7748 (KeyAgreement, KeyFactory, 
KeyPairGenerator, etc). This is a departure from the ECDH API that 
used "EC" for key generation (shared with ECDSA) and "ECDH" for 
KeyAgreement, and makes the RFC 7748 API more like "DiffieHellman" and 
other algorithms that use the same name for all services.
2) The new class java.security.spec.NamedParameterSpec (which 
implements AlgorithmParameterSpec) will be used to specify curves for 
RFC 7748. This class has a single String member which holds the name 
of the curve ("X25519" or "X448"). This parameter spec class can be 
reused by other crypto algorithms that similarly identify parameter 
sets using names (e.g. FFDHE3072 in DiffieHellman). This new class can 
be inserted into the hierarchy above ECGenParameterSpec.
3) There will be no classes in java.security.spec for EC public keys 
and private keys. An RFC 7748 implementation can use the existing 
classes X509EncodedKeySpec and PKCS8EncodedKeySpec for public and 
private key specs, respectively.
4) There will be no interfaces in java.security.interfaces for RFC 
7748 public/private keys. Public/private key implementation classes 
will implement java.security.PublicKey and java.security.PrivateKey, 
which allows access to their encoded representations.


Here is how the API will be implemented in the SunEC provider:

1) The public key and private key implementation classes will extend 
sun.security.ec.X509Key and sun.security.ec.PKCS8Key, respectively. 
This is similar to ECPublicKeyImpl and ECPrivateKeyImpl.
2) The KeyFactory for RFC 7748 will support translation to/from opaque 
keys and X509EncodedKeySpec/PKCS8EncodedKeySpec.


Example code:

KeyPairGenerator kpg = KeyPairGenerator.getInstance("XDH");
NamedParameterSpec paramSpec = new NamedParameterSpec("X25519");
kpg.initialize(paramSpec); // equivalent to kpg.initialize(255)
KeyPair kp = kpg.generateKeyPair();

KeyFactory kf = KeyFactory.getInstance("XDH");
X509EncodedKeySpec pubSpec = ...
PublicKey pubKey = kf.generatePublic(pubSpec);

KeyAgreement ka = KeyAgreement.getInstance("XDH");
ka.init(kp.getPrivate());
ka.doPhase(pubKey, true);
byte[] secret = ka.generateSecret();


One thing that is missing from the "core" API proposal is a way to 
easily produce a public/private key from an encoded numeric value. Of 
course, it's possible to put this value into a