We know that CV25519 private key has interoperability issue.
Explain the format. Explain possible tips when using X25519 API.
Description
Event Timeline
CV25519 private key secret part:
- Standard MPI (big-endian) of 255-bit
- The value should have zeros for least significant three bits, its most significant bit (255th bit) should be set.
- the value should be the one after decodeScalar25519 function in RFC7748
CV25519 public part from secret part:
- Simply calculated by [secret-part]G
Thus the public key differs on wether the raw secret key or the masked (bit255 set, bit0..2 clear) has been used. And at what point in the code this was done. Shall we collect a list describing the differences of applications and on whether they have some mitigation for compatibility.
Note that for the OpenPGP implementations which use X25519 API, it is not possible to calculate [scalar]G with scalar having least significant three bits != 0.
GnuPG never generates key of scalar with LSBs != 0. But there are a few experimental keys with LSBs != 0, which were generated by experimental version of libgcrypt+GnuPG around 2015-08 (when CV25519 was added).
Those experimental keys are incompatible to OpenPGP implementations with X25519, since public key by GnuPG and public key by that implementation is different.
For some implementation which might generate key of scalar with LSBs != 0, the key is incompatible to GnuPG. Before importing such a key to GnuPG, private key part should be fixed so that LSBs should be cleared, then it can be imported to GnuPG.