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);
}


Reply via email to