Greetings!
I'm having trouble verifying what exactly an OpenPGP secret key packet
for Ed25519 keys is supposed to contain, i.e. what the fields in the
secret key packet actually represent. I think that the spec [1] (and its
later version [2]), if implemented literally, would cause part of the
information necessary for signing to be lost.
My understanding of Ed25519 is based on Brian Warner's presentation [3]:
* Ed25519 keys start as a 32-byte seed `k`, which is hashed and
divided into a left half `LH` and a right half `RH`.
* `LH` is massaged into a secret scalar `a`, from which the public key
`A` is derived via EC point multiplication.
* Ed25519 signatures consist of two encoded EC points `R` and `S`. `R`
depends solely on `r`, the DSA secret "random" integer (which in
Ed25519 is deterministically computed from the message `M` and from
`RH`). `S` is computed from `A`, `a`, `M`, `R` and `r`.
In particular, from my understanding, Ed25519 signatures are
deterministic, and require calculating or storing `RH` to achieve that
goal; consequently, `k` or `RH` must be part of the secret key's wire
format, because calculating `RH` without knowing `k` involves a large
partial hash inversion and is thus cryptographically infeasible. The
bit-fiddling on `LH` also guarantees that `a` is always divisible by 8.
The EdDSA for OpenPGP spec [1] defines the wire format to only contain
"an MPI of an integer representing the secret key, which is a scalar of
the public EC point". This appears to describe the secret scalar `a`.
In contrast, SSH, or more specifically the SSH agent protocol [4],
defines the wire format of Ed25519 keys to contain the seed `k`. It is
unclear to me how OpenPGP would ensure that Ed25519 signatures remain
deterministic -- which I verified that they are -- if neither `k` nor
`RH` is stored in the secret key material. Some testing with sample
Ed25519 keys and GnuPG's `--list-packets` indicates that the range of
possible values for the secret MPI value is actually consistent with
`k`, but not with `a`, because not all sample MPI values were divisible
by 8.
Thus, my question: What exactly does the scalar in an OpenPGP Ed25519
secret key denote? The Ed25519 multiplicative scalar `a` such that the
public key `A` is `a` times the Ed25519 base point? Or the seed `k` such
that `a` and `RH` are derived from `SHA512(k)`?
Thanks, and cheers,
Marco
[1]: https://tools.ietf.org/html/draft-koch-eddsa-for-openpgp-04#section-4
[2]: https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-10#section-5.6.5
[3]: https://blog.mozilla.org/warner/2011/11/29/ed25519-keys/
[4]: https://tools.ietf.org/html/draft-miller-ssh-agent-04#section-4.2.3
I'm having trouble verifying what exactly an OpenPGP secret key packet
for Ed25519 keys is supposed to contain, i.e. what the fields in the
secret key packet actually represent. I think that the spec [1] (and its
later version [2]), if implemented literally, would cause part of the
information necessary for signing to be lost.
My understanding of Ed25519 is based on Brian Warner's presentation [3]:
* Ed25519 keys start as a 32-byte seed `k`, which is hashed and
divided into a left half `LH` and a right half `RH`.
* `LH` is massaged into a secret scalar `a`, from which the public key
`A` is derived via EC point multiplication.
* Ed25519 signatures consist of two encoded EC points `R` and `S`. `R`
depends solely on `r`, the DSA secret "random" integer (which in
Ed25519 is deterministically computed from the message `M` and from
`RH`). `S` is computed from `A`, `a`, `M`, `R` and `r`.
In particular, from my understanding, Ed25519 signatures are
deterministic, and require calculating or storing `RH` to achieve that
goal; consequently, `k` or `RH` must be part of the secret key's wire
format, because calculating `RH` without knowing `k` involves a large
partial hash inversion and is thus cryptographically infeasible. The
bit-fiddling on `LH` also guarantees that `a` is always divisible by 8.
The EdDSA for OpenPGP spec [1] defines the wire format to only contain
"an MPI of an integer representing the secret key, which is a scalar of
the public EC point". This appears to describe the secret scalar `a`.
In contrast, SSH, or more specifically the SSH agent protocol [4],
defines the wire format of Ed25519 keys to contain the seed `k`. It is
unclear to me how OpenPGP would ensure that Ed25519 signatures remain
deterministic -- which I verified that they are -- if neither `k` nor
`RH` is stored in the secret key material. Some testing with sample
Ed25519 keys and GnuPG's `--list-packets` indicates that the range of
possible values for the secret MPI value is actually consistent with
`k`, but not with `a`, because not all sample MPI values were divisible
by 8.
Thus, my question: What exactly does the scalar in an OpenPGP Ed25519
secret key denote? The Ed25519 multiplicative scalar `a` such that the
public key `A` is `a` times the Ed25519 base point? Or the seed `k` such
that `a` and `RH` are derived from `SHA512(k)`?
Thanks, and cheers,
Marco
[1]: https://tools.ietf.org/html/draft-koch-eddsa-for-openpgp-04#section-4
[2]: https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-10#section-5.6.5
[3]: https://blog.mozilla.org/warner/2011/11/29/ed25519-keys/
[4]: https://tools.ietf.org/html/draft-miller-ssh-agent-04#section-4.2.3