Giter VIP home page Giter VIP logo

Comments (15)

gmaxwell avatar gmaxwell commented on July 22, 2024 2

(it adds an extra round though)

It shouldn't, it should be possible to have the same number of compression function calls as currently and still have 23 bytes left over for synthetic nonce input. (care should be taken to recommend the synthetic nonce input size to be small enough to avoid gratuitously adding another compression function run)

from bips.

sipa avatar sipa commented on July 22, 2024

After some more discussion on IRC, it seems worthwhile to modify the signing algorithm to use a nonce function that always includes the public key + negation flag.

We don't have a proof, but I think there is a pretty decent informal argument that that is actually secure - there can't be any nonce leakage if the nonce is computed using a superset of all the data that goes into the challenge hash, and a signature with invalid P in the challenge hash should be useless otherwise. An actual proof would be nice, and perhaps a prerequisite before we actually advertise the untrusted-pubkey-input feature.

Still, given that it does not increase the amount of hashing in the nonce derivation to add the pubkey + neg flag makes it kind of an obvious improvement.

from bips.

sipa avatar sipa commented on July 22, 2024

One consideration: if people sign with untrusted public keys (which are fed to nonce derivation), I suspect that whatever protections key-prefixed Schnorr has over non-key-prefixed disappear, as we need to assume the public keys are attacker controlled.

from bips.

sipa avatar sipa commented on July 22, 2024

See also the post by @gmaxwell: https://moderncrypto.org/mail-archive/curves/2020/001012.html

from bips.

sipa avatar sipa commented on July 22, 2024

Note that I think there are two independent questions here:

  • Do we want to switch to including pubkey/neg in the nonce derivation function by default, without exposing/advertizing the untrusted-pubkey feature (or maybe exposing it, but still only intended it to be used with self-computed pubkeys).
  • Specifying/analysing the security properties of untrusted-pubkey input to a signing algorithm that already does the above.

from bips.

real-or-random avatar real-or-random commented on July 22, 2024

I agree, we should add the "full" pubkey to the nonce derivation.

One consideration: if people sign with untrusted public keys (which are fed to nonce derivation), I suspect that whatever protections key-prefixed Schnorr has over non-key-prefixed disappear, as we need to assume the public keys are attacker controlled.

Exactly, I was just typing this post to point this out. And this is a worse concern that noone has brought up so far in the discussion.

We heavily rely on key-prefixing for security with tweaked keys. Schnorr signature with attacker-controlled keys used as the prefix (like without key-prefixing) are not secure when we can tweak keys. Say I can trick you into signing with your correct secret key x but with wrong public key (x+H(xG, data))G . Then I can tweak your signature to be valid for the wrong public key.

This is a different attack, adding the public key to the nonce derivation does not help here.

from bips.

real-or-random avatar real-or-random commented on July 22, 2024

And we're the first to rely on tweaked keys in practice, so the fact that we don't know about any real-world attacks on other signature schemes where the attacker provides the wrong public key (e.g., EdDSA) may not be so useful.

AFAIK EdDSA implementations often store the public key together with the secret key. But that breaks our model that the secret key is simply 256 bits, and it does not work well with tweaked keys again.

What we could do (related/same? as bitcoin-core/secp256k1#558 (comment)) is to define an "auxilliary" key [0] that is the public key, MACed with the secret key, e.g., simply (pk, H(pk || sk)) for a newly tagged hash function H. This way of storing pk has integrity built in, and the signing algorithm can recompute the hash before trusting the pk over which the attacker potentially has control, e.g., because it read stored from an unstrusted cache on disk or the result of a computation in some interactive signing process.

That's not for free but also much cheaper than an EC multiplication.
edit: If you're courageous you can share the H(pk || ... midstate with the challenge hash computation.

[0] Sorry for switching terms again but yes, the term "extended public key" exists already as in xpub.

from bips.

gmaxwell avatar gmaxwell commented on July 22, 2024

AFAIK EdDSA

I have found only a single one that did. The overwhelmingly common ones do not.

I think doing so is not unreasonable, but overall implementations do not.

and it does not work well with tweaked keys again.

It would work fine if there were tweak functions that operated on the same interface.

MACed with the secret key,

I think that might be a little excessive? If there is arbitrary corruption we're already in trouble. So long as the nonce function takes all the input, a corrupted key just risks signing for a related key. But if it's corruption rather than a maliciously generated point, no one will know the DL for the fixup. If the key is malicious and managed to get loaded into our extended secret key, then presumably the loading process is gonna end up setting the right mac too...

nonce derivation function by default, without exposing/advertizing the untrusted-pubkey feature

At a minimum. Even if the interface doesn't take the key and generates it internally, the nonce hash should get it. From a BIP perspective this should be the only question, and I think the answer is unambiguous.

I think just having a schnorr secret key object that has the pubkey and flag in it... and a function to load a regular secret key into that (that ecmults to generate the pubkey and extracts the flag). Callers that don't want to deal with storing the longer key can just always load it, for a performance penalty.

If the pubkey is loaded into a combined seckeypub object by functions that always generate it... then the security issue doesn't arise.

from bips.

jonasnick avatar jonasnick commented on July 22, 2024

Given that untrusted pubkeys break the security of signing (see @real-or-random's related key attack), tying the pubkey to the seckey seems to be the only viable solution. Also, adding the public key to the deterministic nonce function to protect against corruption makes a lot of sense.

MAC'ing the pubkey indeed seems to be excessive. If attackers can write arbitrarily, they can set most bits of the secret key to zero and after signing brute force search x' via (s - H(...)x')G ?= R.

It's clear that if pubkey precomputation is used in libsecp, people will try to implement the same thing regardless of whether it's mentioned or even discouraged in the BIP. Therefore, we should specify how to do it correctly if we find a wording that's not "fragile".

from bips.

real-or-random avatar real-or-random commented on July 22, 2024

I agree MACing is excessive in a simple implementation that stores secret keys in RAM (such as libsecp256k1). I guess I had a different scenario in mind when I mentioned this.

I think it can be interesting when you store your secret keys differently than the precomputed public keys, and you trust one storage more than the other. And I think that's not unrealistic, in particular with HD wallets where the seed is short and thus easier to store. Think of a hardware wallet that stores its HD seed in some (hopefully) very secure trusted storage but then wants to store precomputed public keys on some other drive. Using a MAC it could actually hand the precomputed public keys over to the host and then later query the host for the public key when necessary.

tying the pubkey to the seckey seems to be the only viable solution

Right, and one related issue here is what API will want to use for tweaking. In libsecp256k1, tweaking is an operation on the public key and on the secret key. Alternatively, one could think about this in terms of an API that still is able to tweak public keys but then has a sign_with_tweak function which never output the tweaked secret key, which then becomes an intermediate value. Not sure what is better, I haven't really thought about this so far.

from bips.

gmaxwell avatar gmaxwell commented on July 22, 2024

Interface wise, I think it's nice if the pubkey is optional. Signing is faster if you have it, if you don't care you don't bother with it. Unfortunately, that is incompatible with "pubkey is part of the secret". Pubkey is part of the secret is also incompatible with "you don't need a keygen function, you just need randomness" :(

from bips.

ajtowns avatar ajtowns commented on July 22, 2024

One consideration: if people sign with untrusted public keys (which are fed to nonce derivation), I suspect that whatever protections key-prefixed Schnorr has over non-key-prefixed disappear, as we need to assume the public keys are attacker controlled.

I think that's half right -- with non-key-prefixed schnorr, you get a valid signature for pubkey P on message m, and can then convert that to a valid signature for pubkey P+aG on message m, provided you know a.

With this, I think you can still generate a valid signature for pubkey P+aG on message m but you have to specify P+aG as the pubkey at signing time and the signature can't be made valid for any other pubkey. That's technically not quite as powerful, but it seems like it's just as good in practice?

As written, we already calculate the pubkey P and squareness before generating the nonce, so throwing ext_bytes(P) into Hash_BIPSchnorrDerive seems easy (it adds an extra round though). I think passing in the pubkey can probably be briefly discussed as an Alternative Signing option, like synthetic nonces?

from bips.

jonasnick avatar jonasnick commented on July 22, 2024

Signing is faster if you have it, if you don't care you don't bother with it. Unfortunately, that is incompatible with "pubkey is part of the secret" (@gmaxwell)

I don't see how this is incompatible. In libsecp lingo, if schnorrsig_sign could just be a wrapper for "sign_fast":

/* if you just want the pubkey */
xonly_pubkey_create(xonly_pubkey, seckey)
/* if you want the pubkey and sign */
xonly_keypair_create(keypair, seckey)
xonly_keypair_get_pubkey(xonly_pubkey, keypair)
/* perhaps also add serialize and parse function for keypairs */

schnorrsig_sign_fast(keypair, m)
schnorrsig_sign(seckey, m) {
  xonly_keypair_create(keypair, seckey)
  sign_fast(keypair, m)
}

from bips.

gmaxwell avatar gmaxwell commented on July 22, 2024

That doesn't sound bad.

from bips.

ajtowns avatar ajtowns commented on July 22, 2024

I think this issue is resolved

from bips.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.