RFR 8171279: Support X25519 and X448 in TLS 1.3

Xuelei Fan xuelei.fan at oracle.com
Fri Sep 7 15:34:33 UTC 2018


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



More information about the security-dev mailing list