keisentraut / age-keygen-deterministic

simple Rust CLI tool to derive an age private key from passphrase
BSD 3-Clause "New" or "Revised" License
26 stars 1 forks source link

This does not (usually) create valid x25519 keys #3

Closed shelvacu closed 3 months ago

shelvacu commented 3 months ago

Not every set of 256 bits is a valid key, you need to (assuming mysecret is a [u8; 32])

mysecret[0] &= 248;
mysecret[31] &= 127;
mysecret[31] |= 64;

source: https://cr.yp.to/ecdh.html

keisentraut commented 3 months ago

First of all, this is already mentioned in the README.md file.

age does not do clamping, too. (as far as I know). Please read the lines around here: https://github.com/FiloSottile/age/blob/faefdc3c81efa89fd41998b77c62234ca56be10b/x25519.go#L117 I think the worst thing which can happen is that your private key is a multiple of another "clamped" key and it does not really matter. But I am not a cryptographer, though.

keisentraut commented 3 months ago

Here some article written by @FiloSottile (age developer) about NaCl: https://words.filippo.io/dispatches/nacl-api/ Relevant Quote:

A nice explainer of 25519 clamping. Note how clamping is actually pointless for signatures, and Ed25519 could have skipped it and there would have been no need for non-standard solutions for hierarchical keys. (But fear not, there's an IETF WG that's standardizing ECDSA-Curve25519, because sure, it's 2020.)

It is not as simple as you think and I will not implement it as long as you prove that age actually clamps the key.

FiloSottile commented 3 months ago

Yes, age keys are just random bytes. The X25519 function from RFC 7748 does clamping internally.

https://github.com/C2SP/C2SP/blob/main/age.md#the-x25519-recipient-type