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?


Found the solution. All that was needed was to reverse the bytes in the curve25519 secret point. Apparantly PGP uses little-endian for this, while ed25519 uses big-endian.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.