Skip to content

BIP340: Variable-length messages / domain separation#221

Merged
sipa merged 4 commits into
sipa:bip-taprootfrom
real-or-random:202207-varlen
Apr 20, 2023
Merged

BIP340: Variable-length messages / domain separation#221
sipa merged 4 commits into
sipa:bip-taprootfrom
real-or-random:202207-varlen

Conversation

@real-or-random
Copy link
Copy Markdown

@real-or-random real-or-random commented Jul 27, 2022

Solves #207.

I tried to avoid going into collision-resistance vs random-prefix resistance. It's hard to explain, and the situation is not entirely clear, e.g., due to https://eprint.iacr.org/2015/509.pdf which claims a flaw in the paper http://www.neven.org/papers/schnorr.pdf which cite in the BIP (we may want to add a footnote to the BIP...).

TODO:

  • Test vectors for varlen messages
  • Do we want a small changelog?

@sipa Can you update the bip-taproot brach to bitcoin/master

Copy link
Copy Markdown

@jonasnick jonasnick left a comment

Choose a reason for hiding this comment

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

Concept ACK. The explanation for domain separation turned out nicely.

Comment thread bip-0340.mediawiki Outdated
Comment thread bip-0340.mediawiki Outdated
Comment thread bip-0340.mediawiki Outdated
Comment thread bip-0340.mediawiki Outdated
@real-or-random
Copy link
Copy Markdown
Author

Forced-push to address @jonasnick's comments.

@real-or-random real-or-random force-pushed the 202207-varlen branch 3 times, most recently from 7d527e7 to 4a1ace6 Compare July 29, 2022 09:59
@real-or-random
Copy link
Copy Markdown
Author

Updated. This also takes the #211 into account now.

@real-or-random
Copy link
Copy Markdown
Author

@jonasnick @sipa Would be nice to have ACKs on the method before I'll generate test vectors.

Copy link
Copy Markdown

@jonasnick jonasnick left a comment

Choose a reason for hiding this comment

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

Method ACK

@sipa
Copy link
Copy Markdown
Owner

sipa commented Jul 29, 2022

You seem to have a bunch of unrelated commits in here?

@real-or-random
Copy link
Copy Markdown
Author

@sipa Can you update the bip-taproot brach to bitcoin/master

@sipa
Copy link
Copy Markdown
Owner

sipa commented Jul 29, 2022

@real-or-random Oops, I didn't realize this was opened against my repo.

@sipa
Copy link
Copy Markdown
Owner

sipa commented Aug 4, 2022

@real-or-random I've updated my bip-taproot branch, in case you want to update.

@real-or-random
Copy link
Copy Markdown
Author

rebased

@sipa
Copy link
Copy Markdown
Owner

sipa commented Aug 4, 2022

Concept ACK

@real-or-random
Copy link
Copy Markdown
Author

cc @LLFourn

@LLFourn
Copy link
Copy Markdown

LLFourn commented Aug 5, 2022

ACK. 33 bytes seems straightforward and easy to explain. It looks like in schnorr_fun I already did the 64 byte pad. I'll probably just leave that as is and document it.

Comment thread bip-0340.mediawiki Outdated

==== Messages of Arbitrary Size ====

The signature scheme specified in this BIP accepts byte strings of arbitrary size as input messages.<ref>In theory, the message size is restricted due to the fact that SHA256 accepts byte strings only up to size of 2^56-1 bytes.</ref>
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Where does the number 2^56-1 come from?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

SHA256 accepts messages of length up to 2^64-1 bits, see https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf Figure 1.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Ah right, tricky.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

2^64 bits is 2^61 bytes

Copy link
Copy Markdown
Author

@real-or-random real-or-random Aug 9, 2022

Choose a reason for hiding this comment

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

Ah right, tricky... Sigh.

edit: I seem to be married to this mistake, I made the same mistake here: bitcoin-core/secp256k1#731 (review)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

fixed

@real-or-random
Copy link
Copy Markdown
Author

@jonasnick suggested in jonasnick#24 (comment) to have an explicit upper limit of message size, e.g., 2^48 (we could also make it 2^60 or even 2^62):

Pros:

  1. This will make the limit explicit. At the moment, the limit is implicitly defined, and at least for signing will depend on concrete nonce function. This could help formal methods.
  2. It will avoid some potential buffer/integer overflows on 64-bit machine. Even if they are just theoretical, this could help formal verification (when applied to implementations).
  3. If you really manage to pass a message of size around 2^61 B (= 2048 PiB), the limit will catch SHA256 implementations that don't check for counter overflow (e.g., the implementation in libsecp256k1 does not check in production).
  4. A limit of 2^48 will also guarantee that a future half-agg spec could concatenate some number of these messages without hitting the 2^61 limit (but see below).

Cons:

  1. Noone will ever sign a message of size 2048 PiB (a least before we can break dlog in secp256k1).
  2. It adds a branch.

My opinion:

I don't think "Pro 4" is helpful in practice: Even if we have an upper bound of 2^48, this does not guarantee that all implementation will accept messages of this size. Many implementations will want reject them, e.g., implementations on 32-bit platforms.

Similarly, I think a limit wouldn't help make verification identical across implementations (again because implementations will have their own upper bounds).

So I tend to think that "Noone will ever sign a message of size 2048 PiB." convinces me. My standpoint is that we're just giving a generic algorithms, any application or protocol using the BIP will need to specify message formats, and this include a maximum message size, which will probably be well below 2^48. If formal methods need a limit, they could still introduce one in their theorems, and then the restricted theorem would still cover any real world protocol.

@real-or-random real-or-random marked this pull request as ready for review August 11, 2022 15:55
@jonasnick
Copy link
Copy Markdown

An upper bound on the message length that's much smaller than 2^61 would allow claiming that BIP-musig can sign any message that BIP-schnorr can or that BIP-half-agg can verify any signature that BIP-schnorr can. With the assumption that "Noone will ever hash an input of size 2048 PiB" (slightly strong than "Noone will ever sign a message of size 2048 PiB") then you can still make this claim (even with formal methods). I'm fine working under this assumption to avoid complexity. If you'd want to make use of an upper bound like 2^48 in a half aggregation spec you'd need to do annoying caclulations to figure out how many signatures you can actually verify and put an upper bound on that as well (the current draft already has an upper bound on it due to potential integer overflows).

Stating the upper bound that stems from SHA256 explicitly (close to 2^61) doesn't seem particularly useful right now. I think the footnote is fine.

Copy link
Copy Markdown

@jonasnick jonasnick left a comment

Choose a reason for hiding this comment

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

ACK mod nit

Comment thread bip-0340/test-vectors.csv Outdated
Comment on lines +17 to +21
15,0340034003400340034003400340034003400340034003400340034003400340,778CAA53B4393AC467774D09497A87224BF9FAB6F6E68B23086497324D6FD117,0000000000000000000000000000000000000000000000000000000000000000,,71535DB165ECD9FBBC046E5FFAEA61186BB6AD436732FCCC25291A55895464CF6069CE26BF03466228F19A3A62DB8A649F2D560FAC652827D1AF0574E427AB63,TRUE,message of size 0 bytes (added 2022-08)
16,0340034003400340034003400340034003400340034003400340034003400340,778CAA53B4393AC467774D09497A87224BF9FAB6F6E68B23086497324D6FD117,0000000000000000000000000000000000000000000000000000000000000000,11,08A20A0AFEF64124649232E0693C583AB1B9934AE63B4C3511F3AE1134C6A303EA3173BFEA6683BD101FA5AA5DBC1996FE7CACFC5A577D33EC14564CEC2BACBF,TRUE,message of size 1 byte (added 2022-08)
17,0340034003400340034003400340034003400340034003400340034003400340,778CAA53B4393AC467774D09497A87224BF9FAB6F6E68B23086497324D6FD117,0000000000000000000000000000000000000000000000000000000000000000,0102030405060708090A0B0C0D0E0F1011,5130F39A4059B43BC7CAC09A19ECE52B5D8699D1A71E3C52DA9AFDB6B50AC370C4A482B77BF960F8681540E25B6771ECE1E5A37FD80E5A51897C5566A97EA5A5,TRUE,message of size 17 bytes (added 2022-08)
18,0340034003400340034003400340034003400340034003400340034003400340,778CAA53B4393AC467774D09497A87224BF9FAB6F6E68B23086497324D6FD117,0000000000000000000000000000000000000000000000000000000000000000,99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999,403B12B0D8555A344175EA7EC746566303321E5DBFA8BE6F091635163ECA79A8585ED3E3170807E7C03B720FC54C7B23897FCBA0E9D0B4A06894CFD249F22367,TRUE,message of size 100 bytes (added 2022-08)
19,0340034003400340034003400340034003400340034003400340034003400340,778CAA53B4393AC467774D09497A87224BF9FAB6F6E68B23086497324D6FD117,0000000000000000000000000000000000000000000000000000000000000000,99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999,F1D320D7DE4D5FF365A8CE6CF0AD580B9358F96F46DFBE141E22128B75919C3E47B4420DB40806AD1CF6BF0FCADE8A2D51634DEDB7E118E9AE896DD4D6A504BB,TRUE,message of size 1000 bytes (added 2022-08)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

nit: is there a particular reason why you chose these test vectors specifically? In BIP-musig we only have tests for 32-byte and 0-byte. I see no particular reason how an implemtnation can pass those two test vectors but not a vector with length 1000.

Copy link
Copy Markdown
Author

@real-or-random real-or-random Aug 19, 2022

Choose a reason for hiding this comment

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

The purpose of the 100 byte and 1000 byte vectors is to catch implementation that that truncate messages (e.g., at 32 bytes because they only reserve 32 bytes internally). I can remove the 1000 bytes vector if you think it's overkill.

And the 17 was just to have another case < 32 which is not a corner case.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The purpose of the 100 byte and 1000 byte vectors is to catch implementation that that truncate messages (e.g., at 32 bytes because they only reserve 32 bytes internally)

Good point. I added a vector with a message > 32 bytes to bip-musig2.

Wrt. the 1000 bytes vector, I'd remove it because I find it desirable to have a minimal set of test vectors, but it's fine with me either way.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

removed the 1000 bytes vector

Copy link
Copy Markdown

@jonasnick jonasnick left a comment

Choose a reason for hiding this comment

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

ACK 05bd175

Comment thread bip-0340.mediawiki Outdated
If large messages are not pre-hashed,
the algorithms of the signature scheme will perform more hashing internally.
In particular, the hashing performed by the signing algorithm will process the message twice,
which leads to performance penalties for large messages.
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Specifically, if the post-padding size of the message exceeds 128/(2-a) bytes, where a is the ratio between the hashing speed in the caller and the hashing speed in libsecp256k1 (a<1 meaning the caller is faster), then pre-hashing in the caller is faster.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Are you suggesting that we add the exact condition?

a is the ratio between the hashing speed in the caller and the hashing speed in libsecp256k1 (a<1 meaning the caller is faster)

Yes, assuming libsecp256k1 is used at all.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

I mostly calculated this because I was curious. But perhaps it's useful to be specific (if you assume a=1), by saying that generally precomputing is faster for messages over 55 bytes?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I can add a footnote but what exactly do you mean by "post-padded"?

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

SHA256 adds between 9 and 72 bytes of padding IIRC (ending with a multiple of 64 bytes). So by post-padded size of the message I mean 64*floor((msglen+72)/64).

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Suggested footnote:

  • Typically, messages of 56 bytes or longer enjoy a performance benefit from pre-hashing, assuming the hashing speed inside the signature scheme matches that of the pre-hashing done inside the calling application.

Comment thread bip-0340.mediawiki
Comment thread bip-0340.mediawiki Outdated
(as for example done in [[bip-0341.mediawiki|BIP341]].)

Since pre-hashing may not always be desirable,
e.g. when actual messages are shorter than 32 bytes,
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Suggested change
e.g. when actual messages are shorter than 32 bytes,
e.g., when actual messages are shorter than 32 bytes,

Comment thread bip-0340.mediawiki Outdated
If large messages are not pre-hashed,
the algorithms of the signature scheme will perform more hashing internally.
In particular, the hashing performed by the signing algorithm will process the message twice,
which leads to performance penalties for large messages.
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I can add a footnote but what exactly do you mean by "post-padded"?

@real-or-random
Copy link
Copy Markdown
Author

real-or-random commented Oct 22, 2022

This could also cite https://ed25519.cr.yp.to/eddsa-20150704.pdf for its last paragraph.

Comment thread bip-0340.mediawiki Outdated

As a best practice, we recommend applications to use exactly one of the following methods to pre-process application messages before passing it to the signature scheme:
* Either, pre-hash the application message using ''hash<sub>name</sub>'', where ''name'' identifies the context uniquely (e.g., "foo-app/signed-bar"),
* or prefix the actual message with a 33-byte string that identifies the context uniquely (e.g. the UTF-8 enconding of "foo-app/signed-bar", padded with null bytes to 33 bytes).
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Typo: enconding

Comment thread bip-0340.mediawiki Outdated

To help implementors understand updates to this BIP, we keep a list of substantial changes.

* 2022-08: Allow messages of arbitrary size
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Update...

Comment thread bip-0340/test-vectors.csv Outdated
12,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F69E89B4C5564D00349106B8497785DD7D1D713A8AE82B32FA79D5F7FC407D39B,FALSE,sig[0:32] is equal to field size
13,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,6CFF5C3BA86C69EA4B7376F31A9BCB4F74C1976089B2D9963DA2E5543E177769FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141,FALSE,sig[32:64] is equal to curve order
14,,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC30,,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,6CFF5C3BA86C69EA4B7376F31A9BCB4F74C1976089B2D9963DA2E5543E17776969E89B4C5564D00349106B8497785DD7D1D713A8AE82B32FA79D5F7FC407D39B,FALSE,public key is not a valid X coordinate because it exceeds the field size
15,0340034003400340034003400340034003400340034003400340034003400340,778CAA53B4393AC467774D09497A87224BF9FAB6F6E68B23086497324D6FD117,0000000000000000000000000000000000000000000000000000000000000000,,71535DB165ECD9FBBC046E5FFAEA61186BB6AD436732FCCC25291A55895464CF6069CE26BF03466228F19A3A62DB8A649F2D560FAC652827D1AF0574E427AB63,TRUE,message of size 0 bytes (added 2022-08)
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Code for generating these should be added to bip-0340/test-vectors.py.

@sipa
Copy link
Copy Markdown
Owner

sipa commented Nov 17, 2022

Concept ACK apart from nits.

@real-or-random
Copy link
Copy Markdown
Author

addressed all nits by @sipa

This could also cite ed25519.cr.yp.to/eddsa-20150704.pdf for its last paragraph.

I made the effort to mention their main arguments instead (reliance on collision-resistance, need to keep the message in memory while signing). And then there's no need to cite this, this is common knowledge...

Copy link
Copy Markdown

@jonasnick jonasnick left a comment

Choose a reason for hiding this comment

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

ACK mod nits

Comment thread bip-0340.mediawiki Outdated
(as for example done in [[bip-0341.mediawiki|BIP341]].)

Since pre-hashing may not always be desirable,
e.g., when actual messages are shorter than 32 bytes,<ref>Another reason to omit pre-hashing is to protect against certain types of cryptanalytic advances against the hash function used for pre-hashing: If pre-hashing is used, an attacker that can find collisions in the pre-hashing function can necessarily forge signatures under chosen-message attacks. If pre-hashing is not used, an attacker that can find collisions in SHA256 (as used inside the signature scheme) may not be able to forge signatures. However, this seeming advantage is mostly moot in the context Bitcoin, which already relies on collision resistance of SHA256 in other places, e.g., for transaction hashes.</ref>
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

nit: s/moot/irrelevant

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

done

Comment thread bip-0340/test-vectors.py
return (None, pubkey, None, msg, sig, "FALSE", "public key is not a valid X coordinate because it exceeds the field size")

def varlen_vector(msg_int):
seckey = bytes_from_int(int(16 * "0340", 16))
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

seckey = default_seckey for consistency?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I think some variance in the vectors won't hurt.

Copy link
Copy Markdown

@jonasnick jonasnick left a comment

Choose a reason for hiding this comment

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

ACK e2ab39a

Comment thread bip-0340.mediawiki Outdated
Comment thread bip-0340.mediawiki Outdated
@real-or-random
Copy link
Copy Markdown
Author

forced-push to address nits by @sipa

Copy link
Copy Markdown

@jonasnick jonasnick left a comment

Choose a reason for hiding this comment

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

ACK 6467520

@sipa
Copy link
Copy Markdown
Owner

sipa commented Apr 18, 2023

Do you want to just PR it to the bips repo now?

@real-or-random
Copy link
Copy Markdown
Author

Do you want to just PR it to the bips repo now?

No, we have more local changes here: bitcoin/bips@master...sipa:bips:bip-taproot

@sipa sipa merged commit 52728c3 into sipa:bip-taproot Apr 20, 2023
@sipa
Copy link
Copy Markdown
Owner

sipa commented Apr 20, 2023

Opened BIPs repo PR: bitcoin#1446

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.

4 participants