[curves] Generating nonces for Schnorr signatures

Mike Hamburg mike at shiftleft.org
Sat Jun 28 19:51:09 PDT 2014


On 6/28/2014 1:47 PM, Trevor Perrin wrote:
> On Fri, Jun 27, 2014 at 10:20 PM, Michael Hamburg <mike at shiftleft.org> wrote:
>> On Jun 27, 2014, at 1:08 PM, Trevor Perrin <trevp at trevp.net> wrote:
>>> To modify last suggestion, what about XOR'ing the PRNG contribution,
>>> instead of mixing it into the hash?
>>>
>>> """
>>> nonce_key = either
>>> - random(32) generated as part of private key (preferred), OR
>>> - private_scalar
>>>
>>> sig_nonce = (random(HLEN) XOR HMAC-HASH("sig_nonce" || nonce_key, message)) % q
>> I think I prefer hashing the randomness, which is fine so long as the hash is entropy-preserving and the RNG is not malicious.
> Not sure what you mean by "entropy-preserving" - if an attacker can
> cause collisions or severe biases on a hash with unknown prefix then I
> would guess that property is being violated, which is where XOR with
> good RNG adds more robustness.
That's a good point.  I was thinking that the fresh randomness is 
somehow superior to the key... which it probably is, but probably only 
after the point where you lose anyway.

Keccak is entropy-preserving in that the state cannot lose entropy, 
because the update function is a permutation.  This means that if the 
state is random at some time, it cannot be made less random, though I 
suppose that if it doesn't have the full 1600 bits of entropy an 
attacker might theoretically be able to "herd" the entropy into one part 
of the state or another.

Likewise, one might hope that H(anything||r) would have 
not-too-much-less entropy than r.  So hashing randomly at the end might 
be better than at the beginning.  Maybe.
>>   Because if the hash is truly awful then you’re screwed anyway, but if the RNG is straightforwardly malicious, then it could bias bits through the XOR.  Not that either of these is at all likely.
> If the hash is truly awful you're screwed for forgeries, but XOR with
> good RNG still prevents your key from being revealed.
>
> So when the RNG is good, I think XOR-the-RNG is clearly better.
Sure.
>
> If the RNG is omnisciently bad, like the DJB blog, then it can leak
> your private key either way (by brute-forcing a bias, for example).
> So I'm not sure there's a real difference here, except that XOR makes
> it more obvious to implementors that the RNG can control the nonce -
> which I think is good.
Maybe.  I was thinking of cases where the RNG is malicious but ignorant, 
and can see what it's being XOR'd into but can't do big computations.  
When RDRAND was integrated into /dev/random there was some concern about 
this model.  But pretty much any of these models is really unlikely.
> If the RNG is not omnisciently bad and the hash is good, then things
> are fine - no difference.
>
> The only argument for hash-the-RNG I see is that if the RNG is weak
> *and* the hash is weak, *maybe* the RNG is at least good enough that
> it "salts" the hash and improves it more than XOR would?
>
> I think that's more fussy than even I'd go, but you could do both:
>
> sig_nonce =
> (random(HLEN) XOR HMAC-HASH("sig_nonce" || nonce_key, random(HLEN) ||
> message)) % q
Doing both is almost certainly not better than just XORing, since XORing 
is going to fail only if the hash is bad and the RNG is soso; or if the 
RNG is stupidly malicious.

I dunno.  I'm convinced that a proper PRF should be used (HMAC or SHAKE 
or something) and that the RNG should be used by default, but I think 
the order doesn't matter much -- any issue there is way down the threat 
list.

-- Mike


More information about the Curves mailing list