Please let me know if you understand the following logic. Otherwise, I
will see if I could do something for you, maybe a prototype, maybe a
more detailed description. However, I may need more time for a
prototype/detailed description.
Per RFC 8446/7748, the X25519 key size is 32 bytes. Here we know the
key size. [1]
Per RFC 8446, the X25519 public key is encoded as byte string inputs and
outputs, as defined in RFC 7748. Her we know the encoding of the key. [2]
Suppose x25519 is used [3], then we know that the key sized per [1] and
the encoded key per [2]. Next step, let convert the encoded key bytes
to PublicKey.
EncodedKeySpec keySpec = ... // find a way to construct the keySpec
// at least, we can use:
// new EncodedKeySpec(byte[]);
// But please check if there's a better one
KeyFactory kFac = KeyFactory.getInstance("x25519");
// we know the name in [3]
PublicKey pubKey = kFac.generatePublic(keySpec);
Here you got the public key.
We may also need to generate the key pair.
KeyPairGenerator kpg = KeyPairGenerator.getInstance("x25519");
// we know the name in [3]
// may be optional, we know the name in [3].
NamedParameterSpec nps = new NamedParameterSpec("x25519");
kpg.initialize(nps);
KeyPair kp = kpg.generateKeyPair();
How you get the private key.
That's it. I know you may need to adjust the crypto implementation if
the provider does not support the above scenarios yet.
Xuelei
On 9/7/2018 7:30 AM, Adam Petcher wrote:
On 9/7/2018 9:34 AM, Xuelei Fan wrote:
JSSE should use the 'x25519' name (via NamedParameterSpec object) only.
This is the part that I don't know how to do. In JSSE, we convert
between the array containing the encoded public key and the BigInteger
representation of the public key used in XECPublicKeySpec. To do this,
you need to know the length of the key, in bits. That means that JSSE
needs to know the length of the key, in addition to the name, in order
to do this conversion. I understand that there are lots of ways to get
this information in JSSE, but I don't know which ways you would find
acceptable.
We keep going back and forth, saying the exact same things, and we don't
seem to be making any progress. Can you please provide some code to
illustrate what you want me to do? All I need is an acceptable
implementation of the following method, that is used by JSSE to decode
public keys:
public static XECPublicKeySpec decodeXecPublicKey(byte[] key,
NamedParameterSpec spec)
throws InvalidParameterSpecException {
XECParameters params = XECParameters.get(
InvalidParameterSpecException::new, spec);
BigInteger u = decodeXecPublicKey(key, params.getBits());
return new XECPublicKeySpec(spec, u);
}
For reference, here is the implementation of the helper method that does
the actual decoding, using the length.
public static BigInteger decodeXecPublicKey(byte[] key,
int bits) {
ArrayUtil.reverse(key);
// clear the extra bits
int bitsMod8 = bits % 8;
if (bitsMod8 != 0) {
int mask = (1 << bitsMod8) - 1;
key[0] &= mask;
}
return new BigInteger(1, key);
}