libsodium vs gnupg curve25519 compatibility

I am trying to create deterministic GPG keys based on cryptosteel. I have implemented a library for (de)serializing PGP packets and am now trying to use keys generated in libsodium for import in GPG.

Libsodium gives me a 32-byte public key and a 32-byte secret key. This is also what PGP seems to use - except PGP prefixes 0x40 to the public key to indicate it isn't using point compression (and thus becomes 33 bytes).

ed25519 keys work fine, but curve25519 keys don't work, when trying to import the generated key GPG asks for a passphrase - despite not specifying a KDF. It seems the points generated by libsodium are not compatible with GPG.

A few random things I don't understand, that may be related to this: - GPG points are 32 bytes, but they are uncompressed. Shouldn't they be 32 + 32 bytes then? From all I can read it seems both X and Y should be 32 bytes. - Libsodium might be using compressed points, but their points don't start with 02 or 03 - which I read is used to indicate which Y was taken for the key. They are also 32 bytes, which would also be too small if you consider an extra byte to indicate the compression.

Does anybody know what exactly is different between these curves and what I could do to fix it?

• Endian swapping a private cv25519 key generated by gpg % echo -n 5486ef03e54ce9cbaf9d88543f286e6517134d694590cfdf56c983732a188fb8 | rev | dd conv=swab b88f182a7383c956dfcf9045694d1317656e283f54889dafcbe94ce503ef8654 will cause libsodium to generate the same cv25519 public key 30b9aa870e4f3cea16f8d8bd4d48704779c416d9a5271c452b263f6f42b28a66. – skaht Jan 20 at 0:45