> Another naming question, should it be dsa_slh_shake128, or maybe
> dsa_slh128_shake ?

We could stick to the spec param names like slh_dsa_shake_128s. Also do you
prefer slh_dsa or dsa_slh prefix?

> Do you think it would be reasonable to drop the sha2 variants in the
> first iteration?

Yes, I think its fine to just have shake variants in the first iteration.

On Wed, Jan 29, 2025 at 10:15 AM Niels Möller <[email protected]> wrote:

> Zoltan Fridrich <[email protected]> writes:
>
> > We want to use SLH-DSA for document signing. I think I will need to add
> the
> > pure and prehash API signing functions. But otherwise whether shake or
> sha2
> > variant is available it does not matter.
>
> Do you think it would be reasonable to drop the sha2 variants in the
> first iteration? Then we wouldn't get the complexities of dealing with
> either "normal" or "compressed" addresses.
>
> >> For the api, I think it should be possible to support "pure" signatures
> >> without requiring all of the message in memory at once, using a
> >> init/update/final-style interface for sign and verify, based on the
> >> update function of the underlying hash. Is that worth while?
> >
> > Sounds like a good idea. I can add it in.
>
> Unfortunately, after a closer look I don't think this is doable. For
> pure signing, the message is hashed twice, once with the secret prf to
> produce the randomizer, and then together with randomizer and public key
> to produce the "digest". It should be possibly to do for the verify
> operation only, but I don't think that's worth the effort.
>
> > It seems to be a typo in the comment. When I checked the logic it is
> indeed
> > pk: [PUB_SEED || root]
>
> That's good.
>
> >> For the Nettle api, I would also consider to not include the pubkey as
> >> part of the secret key, but instead pass both pubkey and secret key to
> >> the secret key functions. Similar to, e.g., ed25519_sha512_sign.
> >
> > That seems redundant to me when the spec defines a secret key to contain
> > the public key too.
> > Did you mean that the secret key shouldnt contain the public key part?
>
> I'm thinking of something analogous to Nettle's ed25519 api,
>
>   void
>   ed25519_sha512_sign (const uint8_t *pub,
>                        const uint8_t *priv,
>                        size_t length, const uint8_t *msg,
>                        uint8_t *signature);
>
>   int
>   ed25519_sha512_verify (const uint8_t *pub,
>                          size_t length, const uint8_t *msg,
>                          const uint8_t *signature);
>
> Here, the pub argument is the same for both functions, and the priv
> argument is the additional private information needed for signing. If we
> do this for dsa-slh, pub would include PK.seed and PK.root, and priv
> would include SK.seed and SK.prf, which seems straightforward to me.
>
> (Signing applications would still be free to store public and private
> parts together whenever convenient).
>
> Nettle isn't totally consistent though, some older signing functions
> take only a private key argument which then needs to include everything,
> others take public key as an additional argument. But I prefer the
> separate style (it's seems more flexible, and it's also more explicit
> about what's public and private), if there's no strong reason to do it
> differently.
>
> >> I think I would prefer separate top-level functions for the different
> >> algorithm variants, rather than the enum slh_dsa_mode. They could all
> >> call the same internal function, passing the appropriate params struct
> >> as argument.
> >
> > What about the pure and pre-hash variants and init, update and final api?
> > Can you describe how you would like the API to look like?
>
> Since it seems we can't have the init/update/final variant, I would suggest
>
>   void
>   dsa_slh_shake128_sign (const uint8_t *pub,
>                          const uint8_t *priv,
>                          size_t length, const uint8_t *msg,
>                          uint8_t *signature);
>   void
>   dsa_slh_shake128_verify (const uint8_t *pub,
>                            size_t length, const uint8_t *msg,
>                            const uint8_t *signature);
>
> for the pure variant, and
>
>   void
>   dsa_slh_shake128_ph_sha256_sign (const uint8_t *pub,
>                                    const uint8_t *priv,
>                                    const uint8_t *digest,
>                                    uint8_t *signature);
>   void
>   dsa_slh_shake128_ph_sha256_verify (const uint8_t *pub,
>                                      const uint8_t *digest,
>                                      const uint8_t *signature);
>
> for the prehash with sha256 variant. There will be lots of functions,
> but they should all be simple wrappers around some internal function
> like
>
>   void
>   _nettle_dsa_slh_sign_internal (const struct dsa_slh_variant *alg,
>                                  const uint8_t *pub,
>                                  const uint8_t *priv,
>                                  size_t prefix_length, const uint8_t
> *prefix,
>                                  size_t length, const uint8_t *msg,
>                                  uint8_t *signature);
>
> (with the prefix, including the extra zero bytes or prehash object id,
> passed as a separate argument to avoid allocation and copying of the
> message).
>
> For link-time dependencies, it's desirable that code specific to one
> slh-dsa variant is referenced indirectly via the struct dsa_slh_variant,
> and that source files are organized so that applications using only a
> single variant don't link-depend on unrelated code.
>
> (The name dsa_slh_variant is a tentative name I made up, feel free to
> use something different).
>
> Another naming question, should it be dsa_slh_shake128, or maybe
> dsa_slh128_shake ? There's a shake128 algorithm, but that's *not* used
> for dsa-slh, it uses shake256. Instead, 128/192/256 refers to the size
> of the values used internally in slh-dsa and in the resulting signature.
>
> >> It's unclear how this differs from _nettle_treehash further above? Or in
> >> general, whats the meaning of "x1" suffix on some functions?
> >
> > I don't exactly know but I think it is some kind of optimization where
> the
> > number determines how many addresses are processed at once.
> > Here is an example of x8 from the reference implementation
> >
> https://github.com/sphincs/sphincsplus/blob/7ec789ace6874d875f4bb84cb61b81155398167e/sha2-avx2/utilsx8.c#L38
>
> I don't get exactly how that 8-way operations works. It would be
> interesting to know what performance improvements they see from that
> (if it's a significant performance boost, we should consider adding
> something like that later).
>
> And it's still unclear to me what's the difference between
> _nettle_treehash and _nettle_treehashx1 in the patch.
>
> >> Not sure I get why wots_k_mask is used? Is it intended to improve
> >> sidechannel-silence or performance?
> >
> > To me it seems to only switch the logic to generate WOTS signatures. I
> > don't know whether it aims to improve either performance or
> > sidechannel-silence.
>
> I think it makes the code harder to understand when signature bytes are
> copied out to the result in a conditional in the middle a loop (both for
> wots and for the merkle inclusion proofs). I like the structure in my
> prototype better, see
> https://git.lysator.liu.se/nisse/poc-slh-dsa/-/blob/main/wots.c?ref_type=heads#L120
>
>   wots_chain (public_seed, addr, 0, msg, sig, sig);
>   sha3_256_update (ctx, _SLH_DSA_128_SIZE,
>                    wots_chain (public_seed, addr, msg, 15 - msg, sig,
> pub));
>
> where first line produces the signature, and second line extends the
> chain to produce the corresponding public key. But you probably don't
> want to do any extensive refactoring now.
>
> To aid later refactoring, it would help with unit tests for the various
> components (even just using the intermadiate values from the top-level
> tests
> is helpful; that's what I did for my prototype).
>
> Another useful addition would be benchmarking in
> examples/hogweed-benchmark.c.
>
> Regards,
> /Niels
>
> --
> Niels Möller. PGP key CB4962D070D77D7FCB8BA36271D8F1FF368C6677.
> Internet email is subject to wholesale government surveillance.
>
>
_______________________________________________
nettle-bugs mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to