Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Schnorr signatures #212

Merged
merged 1 commit into from
Aug 3, 2015
Merged

Implement Schnorr signatures #212

merged 1 commit into from
Aug 3, 2015

Conversation

sipa
Copy link
Contributor

@sipa sipa commented Feb 13, 2015

No description provided.

@sipa sipa changed the title Implement Schnorr signatures + batch verification [WIP] Implement Schnorr signatures + batch verification Feb 13, 2015
@sipa
Copy link
Contributor Author

sipa commented Mar 2, 2015

Rebased.

@sipa
Copy link
Contributor Author

sipa commented Apr 23, 2015

Rebased.

@sipa
Copy link
Contributor Author

sipa commented Apr 23, 2015

TODO: use context to store the batch multipliers

@dcousens
Copy link
Contributor

This is awesome, as Schnorr signatures are dead easy to understand.
But, for what purpose have they been added?

(just curious)

@sipa
Copy link
Contributor Author

sipa commented Apr 27, 2015

They have not been added yet :)

@sipa sipa force-pushed the schnorr3 branch 2 times, most recently from a446e0f to 0ab0b47 Compare June 22, 2015 15:26
@sipa sipa changed the title [WIP] Implement Schnorr signatures + batch verification Implement Schnorr signatures Jun 22, 2015
@sipa
Copy link
Contributor Author

sipa commented Jun 22, 2015

Separated batch validation into a separate branch. This pull request should be usable. Question for reviewers:

  • Enable Schnorr code by default, or hide behind a compile flag (and perhaps move to a separate include/.h file)?

@sipa sipa force-pushed the schnorr3 branch 2 times, most recently from af94dbd to 71d3db6 Compare July 1, 2015 14:41
@sipa
Copy link
Contributor Author

sipa commented Jul 1, 2015

@gmaxwell Added multiparty signing API.

@apoelstra
Copy link
Contributor

I'm a bit concerned about using secp256k1_nonce_function_default. If you sign the same message in both ECDSA and Schnorr with the same nonce, it is possible to recover the secret key from the two signatures. So I think by default Schnorr should use a slightly different noncegen function.

Edit: Oh, I'm being stupid, in Schnorr the messagehash has R inside of it while with ECDSA it does not. So you'd have to do this very deliberately.

Edit2: No, I was right the first time :). Regardless of message-hash, two signatures with the same key/nonce represent two equations in two unknowns.

secp256k1_fe_normalize(&Ra.y);
if (secp256k1_fe_is_odd(&Ra.y)) {
secp256k1_scalar_negate(&n, &n);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a comment above this block explaining that forcing the parity of y allows batch verification (and is part of the definition of Schnorr signatures), at the cost of making inversion-free validation impossible?

@sipa
Copy link
Contributor Author

sipa commented Jul 2, 2015

@apoelstra You're not being stupid, I think.

k is the secret nonce, r is R's x coordinate, m is the message, x is the private key, h = H(m || r). x and k are unknown to an attacker.

ECDSA: s_ecdsa * k = m + r * x
Schnorr: s_schnorr = k - h * x

Or:
ECDSA: k = (m + r * x) / s_ecdsa
Schnorr: k = s_schnorr + h * x

So:
(m + r * x) / s_ecdsa = s_schnorr + h * x

So:
x = (s_schnorr - m/s_ecdsa) / (r/s_ecdsa - h)

@sipa
Copy link
Contributor Author

sipa commented Jul 2, 2015

Fixed the problem listed above by xoring the name of the signature algorithm into the message.

Added a rationale for the choice of full R validation and implicit even y.

@sipa
Copy link
Contributor Author

sipa commented Jul 10, 2015

Rebased on top of #269 and passing the signature algorithm name into the PRNG, to avoid the issue @apoelstra found above.

@sipa
Copy link
Contributor Author

sipa commented Jul 24, 2015

Rebased on top of new #269 and #282, and made compilation of Schnorr code optional (with API defined in a separate header).

@theuni Any comments on the module approach here?

@sipa
Copy link
Contributor Author

sipa commented Jul 27, 2015 via email

@sipa
Copy link
Contributor Author

sipa commented Jul 27, 2015 via email

@theuni
Copy link
Contributor

theuni commented Jul 28, 2015

@sipa There's no way to tell if it's installed without preprocessing though, you'd just "#include secp256k1_schnorr.h" and hope for the best.

I took a quick stab at it here: https://github.com/theuni/secp256k1/tree/212

If you decide to go this route, since the config details become part of the api, we'd need to namespace/cleanup their values.

Of course, you could also just take a subset of this and only expose the module details, leaving the rest as it is.

@sipa
Copy link
Contributor Author

sipa commented Jul 28, 2015 via email

@theuni
Copy link
Contributor

theuni commented Jul 28, 2015

@sipa Because when you 'apt-get install libgmp', you know you can "#include <gmp.h>". But if I apt-get install libsecp256k1, I have no idea what it contains. Using the existence of a file is shaky at best, as it'd be very easy to hit the system file in /usr/include when building against another or a cross build.

No problem if you don't want to expose implementation details, but I still think the user needs some explicit way to know what optional apis are available.

@sipa
Copy link
Contributor Author

sipa commented Jul 28, 2015

@theuni What would an application do with the knowledge that an extra API is available? If it needs it, the build will fail (at link time or at compile time), if it doesn't, it doesn't care...

@theuni
Copy link
Contributor

theuni commented Jul 28, 2015

@sipa Just as libsecp256k1 falls back to internal implementations if gmp isn't usable, an application could do the same if libsecp256k1_foo feature isn't available.

But it's really not worth the argument, and certainly not worth holding up this PR.

@sipa
Copy link
Contributor Author

sipa commented Jul 28, 2015

@theuni Right, there may be optional behaviour. But that's something you'd typically check at configure time, which can try to compile.

I guess the fundamental question I have is: why can you trust that the contents of a file on your disk corresponds with the library installed, when you can't trust the presence of the file corresponding to it.

@sipa
Copy link
Contributor Author

sipa commented Jul 28, 2015

@theuni Ok, one other question: when you don't specify --enable-module-schnorr, the schnorr files don't get included in "make dist" I think. Is that something you'd typically want?

@theuni
Copy link
Contributor

theuni commented Jul 28, 2015

@sipa all files needed to build all configs should be included in the dist tarball. From a quick check, that's currently working as expected:

./autogen.sh
./configure
make distdir # same as 'make dist' and extract tarball
cd libsecp256k1-0.1
./configure --enable-module-schnorr
make

@apoelstra
Copy link
Contributor

Before merge can you add bench_schnorr_verify to .gitignore?

@apoelstra
Copy link
Contributor

Also I think you need to change the last line of travis.yml so that the value of $SCHNORR actually affects configure.

@sipa
Copy link
Contributor Author

sipa commented Aug 2, 2015

Rebased.

@sipa
Copy link
Contributor Author

sipa commented Aug 3, 2015

@apoelstra Nits addressed.

@apoelstra
Copy link
Contributor

Thanks! Tested ACK.

@sipa sipa merged commit a5a66c7 into bitcoin-core:master Aug 3, 2015
sipa added a commit that referenced this pull request Aug 3, 2015
a5a66c7 Add support for custom EC-Schnorr-SHA256 signatures (Pieter Wuille)
@sipa sipa mentioned this pull request Aug 28, 2015
@jl777
Copy link

jl777 commented Jun 14, 2016

is there anyway to use schnorr combined pubkey in a standard p2sh script?
I assume the schnorr sigs are different so OP_CHECKSIG wont work, but if we can assume externally coordinated reveal on secret script, I am hoping there is a way to achieve this as a combined pubkey can be created, but I cant see how to get a script verifiable value before the signature. Maybe there is a way to cooperatively construct a combined privkey that can be used to sign?

@voisine
Copy link
Contributor

voisine commented Jun 14, 2016

I believe schnor is planned for the first segwit upgrade. It will require a new checksig opcode and a soft fork.

@jl777
Copy link

jl777 commented Jun 14, 2016

well a new schnorr_sig opcode would make this all too easy :)
that is what I am adding now but would be nice to get this on the bitcoin side too

@sipa
Copy link
Contributor Author

sipa commented Jun 14, 2016

@jl777 Unsure what you mean. Schnorr signatures are not compatible with ECDSA at all, and needs different signing and verification code. Further, Bitcoin scripts that do not use any digital signature are inherently insecure (if there is no secret information being verified, miners can steal all the coins once they see a spend). Thus, indeed, the only way is using a new opcode.

@jl777
Copy link

jl777 commented Jun 14, 2016

it would be combined with a normal signature: OP_HASH160 hash(sharedsecret) OP_EQUALVERIFY (normal_pubkey) OP_CHECKSIG

granted the protection from just the normal_pubkey OP_CHECKSIG isnt as much as full verification, but if there was a way to offchain calculate a schnorr sig based sharedsecret equivalent, then I think it would work.

problem is I dont see a way to know ahead of time any value that a group signature would create. The combined pubkey appears to be a standard pubkey, but without any normal privkey. Maybe there is a way for a set of nodes to create onetime use keypairs and somehow create a combined privkey that can be used with the combined pubkey.

@sipa
Copy link
Contributor Author

sipa commented Jun 14, 2016

You seem to be describing a normal signature with a hashlocked secret. Where does Schnorr come in?

@jl777
Copy link

jl777 commented Jun 14, 2016

the schnorr would come in offchain, so a group can do larger scale MofN between themselves
was hoping there was a way to generate some sort of sharedsecret equivalent among the participants so that if each member of the group validates the schnorr combined sig, they release their portion of the sharedsecret.

using shamir's shared secret that each of the participants have and release only if they are satisfied, comes really close to being the hashlocked secret to use. The problem is we cant have any single node to know the secret that is being shamir'ed.

maybe some sort of oblivious transfer method could be used, but this is getting to where I am not comfortable as I dont know of any C libraries for that.

So the constraints are that each member of the group can directly run the schnorr lib, they can coordinate and precalculate any sort of magic value, but ultimately a hashlocked bitcoin tx needs to be used

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants