From aeffa075271912f506ed06b860d271461fe99c8d Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Thu, 5 Jul 2018 18:45:34 -0700 Subject: Add draft for Schnorr BIP Includes squashed contributions by GitHub users jonasnick, real-or-random, AustinWilliams, JustinTArthur, ysangkok, RCassatta, Sjors, tnakagawa, and guggero. --- bip-schnorr.mediawiki | 216 ++++++++++++++++++++++++++++++++++++++++++ bip-schnorr/reference.py | 136 ++++++++++++++++++++++++++ bip-schnorr/speedup-batch.png | Bin 0 -> 11914 bytes bip-schnorr/test-vectors.csv | 17 ++++ 4 files changed, 369 insertions(+) create mode 100644 bip-schnorr.mediawiki create mode 100644 bip-schnorr/reference.py create mode 100644 bip-schnorr/speedup-batch.png create mode 100644 bip-schnorr/test-vectors.csv diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki new file mode 100644 index 0000000..d4e4ff1 --- /dev/null +++ b/bip-schnorr.mediawiki @@ -0,0 +1,216 @@ +
+  BIP: ?
+  Title: Schnorr Signatures for secp256k1
+  Author: Pieter Wuille 
+  Status: Draft
+  Type: Informational
+  License: BSD-2-Clause
+  Post-History: 2018-07-06: https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-July/016203.html [bitcoin-dev] Schnorr signatures BIP
+
+ +==Introduction== + +===Abstract=== + +This document proposes a standard for 64-byte Schnorr signatures over the elliptic curve ''secp256k1''. + +===Copyright=== + +This document is licensed under the 2-clause BSD license. + +===Motivation=== + +Bitcoin has traditionally used +[https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm ECDSA] signatures over the [http://www.secg.org/sec2-v2.pdf secp256k1 curve] for authenticating +transactions. These are [http://www.secg.org/sec1-v2.pdf standardized], but have a number of downsides +compared to [https://en.wikipedia.org/wiki/Schnorr_signature Schnorr signatures] over the same curve: + +* '''Security proof''': The security of Schnorr signatures is easily [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf provable] in the random oracle model assuming the elliptic curve discrete logarithm problem (ECDLP) is hard. Such a proof does not exist for ECDSA. +* '''Non-malleability''': ECDSA signatures are inherently malleable; a third party without access to the private key can alter an existing valid signature for a given public key and message into another signature that is valid for the same key and message. This issue is discussed in [https://github.com/bitcoin/bips/blob/master/bip-0062.mediawiki BIP62] and [https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki BIP66]. On the other hand, Schnorr signatures are provably non-malleableMore precisely they are '' '''strongly''' unforgeable under chosen message attacks '' (SUF-CMA), which informally means that without knowledge of the secret key but given a valid signature of a message, it is not possible to come up with a second valid signature for the same message. A security proof in the random oracle model can be found for example in [https://eprint.iacr.org/2016/191 a paper by Kiltz, Masny and Pan], which essentially restates [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf the original security proof of Schnorr signatures by Pointcheval and Stern] more explicitly. These proofs are for the Schnorr signature variant using ''(e,s)'' instead of ''(R,s)'' (see Design above). Since we use a unique encoding of ''R'', there is an efficiently computable bijection that maps ''(R, s)'' to ''(e, s)'', which allows to convert a successful SUF-CMA attacker for the ''(e, s)'' variant to a successful SUF-CMA attacker for the ''(r, s)'' variant (and vice-versa). Furthermore, the aforementioned proofs consider a variant of Schnorr signatures without key prefixing (see Design above), but it can be verified that the proofs are also correct for the variant with key prefixing. As a result, the aforementioned security proofs apply to the variant of Schnorr signatures proposed in this document.. +* '''Linearity''': Schnorr signatures have the remarkable property that multiple parties can collaborate to produce a signature that is valid for the sum of their public keys. This is the building block for various higher-level constructions that improve efficiency and privacy, such as multisignatures and others (see Applications below). + +For all these advantages, there are virtually no disadvantages, apart +from not being standardized. This document seeks to change that. As we +propose a new standard, a number of improvements not specific to Schnorr signatures can be +made: + +* '''Signature encoding''': Instead of [https://en.wikipedia.org/wiki/X.690#DER_encoding DER]-encoding for signatures (which are variable size, and up to 72 bytes), we can use a simple fixed 64-byte format. +* '''Batch verification''': The specific formulation of ECDSA signatures that is standardized cannot be verified more efficiently in batch compared to individually, unless additional witness data is added. Changing the signature scheme offers an opportunity to avoid this. + +[[File:bip-schnorr/speedup-batch.png|frame|This graph shows the ratio between the time it takes to verify ''n'' signatures individually and to verify a batch of ''n'' signatures. This ratio goes up logarithmically with the number of signatures, or in other words: the total time to verify ''n'' signatures grows with ''O(n / log n)''.]] + +By reusing the same curve as Bitcoin has used for ECDSA, private and public keys remain identical for Schnorr signatures, and we avoid introducing new assumptions about elliptic curve group security. + +== Description == + +We first build up the algebraic formulation of the signature scheme by +going through the design choices. Afterwards, we specify the exact +encodings and operations. + +=== Design === + +'''Schnorr signature variant''' Elliptic Curve Schnorr signatures for message ''m'' and public key ''P'' generally involve a point ''R'', integers ''e'' and ''s'' picked by the signer, and generator ''G'' which satisfy ''e = H(R || m)'' and ''sG = R + eP''. Two formulations exist, depending on whether the signer reveals ''e'' or ''R'': +# Signatures are ''(e,s)'' that satisfy ''e = H(sG - eP || m)''. This avoids minor complexity introduced by the encoding of the point ''R'' in the signature (see paragraphs "Encoding the sign of R" and "Implicit Y coordinate" further below in this subsection). +# Signatures are ''(R,s)'' that satisfy ''sG = R + H(R || m)P''. This supports batch verification, as there are no elliptic curve operations inside the hashes. + +We choose the ''R''-option to support batch verification. + +'''Key prefixing''' When using the verification rule above directly, it is possible for a third party to convert a signature ''(R,s)'' for key ''P'' into a signature ''(R,s + aH(R || m))'' for key ''P + aG'' and the same message, for any integer ''a''. This is not a concern for Bitcoin currently, as all signature hashes indirectly commit to the public keys. However, this may change with proposals such as SIGHASH_NOINPUT ([https://github.com/bitcoin/bips/blob/master/bip-0118.mediawiki BIP 118]), or when the signature scheme is used for other purposes—especially in combination with schemes like [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki BIP32]'s unhardened derivation. To combat this, we choose ''key prefixed''A limitation of committing to the public key (rather than to a short hash of it, or not at all) is that it removes the ability for public key recovery or verifying signatures against a short public key hash. These constructions are generally incompatible with batch verification. Schnorr signatures; changing the equation to ''sG = R + H(R || P || m)P''. + +'''Encoding the sign of R''' As we chose the ''R''-option above, we're required to encode the point ''R'' into the signature. Several possibilities exist: +# Encoding the full X and Y coordinate of R, resulting in a 96-byte signature. +# Encoding the full X coordinate, but only whether Y is even or odd (like compressed public keys). This would result in 65-byte signatures. +# Encoding only the X coordinate, leaving us with 64-byte signature. + +Using the first option would be slightly more efficient for verification (around 5%), but we prioritize compactness, and therefore choose option 3. + +'''Implicit Y coordinate''' In order to support batch verification, the Y coordinate of ''R'' cannot be ambiguous (every valid X coordinate has two possible Y coordinates). We have a choice between several options for symmetry breaking: +# Implicitly choosing the Y coordinate that is in the lower half. +# Implicitly choosing the Y coordinate that is evenSince ''p'' is odd, negation modulo ''p'' will map even numbers to odd numbers and the other way around. This means that for a valid X coordinate, one of the corresponding Y coordinates will be even, and the other will be odd.. +# Implicitly choosing the Y coordinate that is a quadratic residue (has a square root modulo the field size)A product of two numbers is a quadratic residue when either both or none of the factors are quadratic residues. As ''-1'' is not a quadratic residue, and the two Y coordinates corresponding to a given X coordinate are each other's negation, this means exactly one of the two must be a quadratic residue.. + +The third option is slower at signing time but a bit faster to verify, as the quadratic residue of the Y coordinate can be computed directly for points represented in +[https://en.wikibooks.org/wiki/Cryptography/Prime_Curve/Jacobian_Coordinates Jacobian coordinates] (a common optimization to avoid modular inverses +for elliptic curve operations). The two other options require a possibly +expensive conversion to affine coordinates first. This would even be the case if the sign or oddness were explicitly coded (option 2 in the previous design choice). We therefore choose option 3. + +'''Final scheme''' As a result, our final scheme ends up using signatures ''(r,s)'' where ''r'' is the X coordinate of a point ''R'' on the curve whose Y coordinate is a quadratic residue, and which satisfies ''sG = R + H(r || P || m)P''. + +=== Specification === + +We first describe the verification algorithm, and then the signature algorithm. + +The following convention is used, with constants as defined for secp256k1: +* Lowercase variables represent integers or byte arrays. +** The constant ''p'' refers to the field size, ''0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F''. +** The constant ''n'' refers to the curve order, ''0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141''. +* Uppercase variables refer to points on the curve with equation ''y2 = x3 + 7'' over the integers modulo ''p''. +** ''infinite(P)'' returns whether or not ''P'' is the point at infinity. +** ''x(P)'' and ''y(P)'' are integers in the range ''0..p-1'' and refer to the X and Y coordinates of a point ''P'' (assuming it is not infinity). +** The constant ''G'' refers to the generator, for which ''x(G) = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798'' and ''y(G) = 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8''. +** Addition of points refers to the usual [https://en.wikipedia.org/wiki/Elliptic_curve#The_group_law elliptic curve group operation]. +** [https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication Multiplication of an integer and a point] refers to the repeated application of the group operation. +* Functions and operations: +** ''||'' refers to byte array concatenation. +** The function ''x[i:j]'', where ''x'' is a byte array, returns a ''(j - i)''-byte array with a copy of the ''i''-th byte (inclusive) to the ''j''-th byte (exclusive) of ''x''. +** The function ''bytes(x)'', where ''x'' is an integer, returns the 32-byte encoding of ''x'', most significant byte first. +** The function ''bytes(P)'', where ''P'' is a point, returns ''bytes(0x02 + (y(P) & 1)) || bytes(x(P))''This matches the ''compressed'' encoding for elliptic curve points used in Bitcoin already, following section 2.3.3 of the [http://www.secg.org/sec1-v2.pdf SEC 1] standard.. +** The function ''int(x)'', where ''x'' is a 32-byte array, returns the 256-bit unsigned integer whose most significant byte encoding is ''x''. +** The function ''lift_x(x)'', where ''x'' is an integer in range ''0..p-1'', returns the point ''P'' for which ''x(P) = x'' and ''y(P)'' is a quadratic residue modulo ''p'', or fails if no such point existsGiven an candidate X coordinate ''x'' in the range ''0..p-1'', there exist either exactly two or exactly zero valid Y coordinates. If no valid Y coordinate exists, then ''x'' is not a valid X coordinate either, i.e., no point ''P'' exists for which ''x(P) = x''. Given a candidate ''x'', the valid Y coordinates are the square roots of ''c = x3 + 7 mod p'' and they can be computed as ''y = ±c(p+1)/4 mod p'' (see [https://en.wikipedia.org/wiki/Quadratic_residue#Prime_or_prime_power_modulus Quadratic residue]) if they exist, which can be checked by squaring and comparing with ''c''. Due to [https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion] it then holds that ''c(p-1)/2 = 1 mod p''. The same criterion applied to ''y'' results in ''y(p-1)/2 mod p = ±c((p+1)/4)((p-1)/2) mod p = ±1 mod p''. Therefore ''y = +c(p+1)/4 mod p'' is a quadratic residue and ''-y mod p'' is not.. The function ''lift_x(x)'' is equivalent to the following pseudocode: +*** Let ''y = c(p+1)/4 mod p''. +*** Fail if ''c ≠ y2 mod p''. +*** Return ''(r, y)''. +** The function ''point(x)'', where ''x'' is a 33-byte array, returns the point ''P'' for which ''x(P) = int(x[1:33])'' and ''y(P) & 1 = int(x[0:1]) - 0x02)'', or fails if no such point exists. The function ''point(x)'' is equivalent to the following pseudocode: +*** Fail if (''x[0:1] ≠ 0x02'' and ''x[0:1] ≠ 0x03''). +*** Set flag ''odd'' if ''x[0:1] = 0x03''. +*** Let ''(r, y) = lift_x(x)''; fail if ''lift_x(x)'' fails. +*** If (flag ''odd'' is set and ''y'' is an even integer) or (flag ''odd'' is not set and ''y'' is an odd integer): +**** Let ''y = p - y''. +*** Return ''(r, y)''. +** The function ''hash(x)'', where ''x'' is a byte array, returns the 32-byte SHA256 hash of ''x''. +** The function ''jacobi(x)'', where ''x'' is an integer, returns the [https://en.wikipedia.org/wiki/Jacobi_symbol Jacobi symbol] of ''x / p''. It is equal to ''x(p-1)/2 mod p'' ([https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion])For points ''P'' on the secp256k1 curve it holds that ''jacobi(y(P)) ≠ 0''.. + +==== Verification ==== + +Input: +* The public key ''pk'': a 33-byte array +* The message ''m'': a 32-byte array +* A signature ''sig'': a 64-byte array + +The signature is valid if and only if the algorithm below does not fail. +* Let ''P = point(pk)''; fail if ''point(pk)'' fails. +* Let ''r = int(sig[0:32])''; fail if ''r ≥ p''. +* Let ''s = int(sig[32:64])''; fail if ''s ≥ n''. +* Let ''e = int(hash(bytes(r) || bytes(P) || m)) mod n''. +* Let ''R = sG - eP''. +* Fail if ''infinite(R)''. +* Fail if ''jacobi(y(R)) ≠ 1'' or ''x(R) ≠ r''. + +==== Batch Verification ==== + +Input: +* The number ''u'' of signatures +* The public keys ''pk1..u'': ''u'' 33-byte arrays +* The messages ''m1..u'': ''u'' 32-byte arrays +* The signatures ''sig1..u'': ''u'' 64-byte arrays + +All provided signatures are valid with overwhelming probability if and only if the algorithm below does not fail. +* Generate ''u-1'' random integers ''a2...u'' in the range ''1...n-1''. They are generated deterministically using a [https://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator CSPRNG] seeded by a cryptographic hash of all inputs of the algorithm, i.e. ''seed = seed_hash(pk1..pku || m1..mu || sig1..sigu )''. A safe choice is to instantiate ''seed_hash'' with SHA256 and use [https://tools.ietf.org/html/rfc8439 ChaCha20] with key ''seed'' as a CSPRNG to generate 256-bit integers, skipping integers not in the range ''1...n-1''. +* For ''i = 1 .. u'': +** Let ''Pi = point(pki)''; fail if ''point(pki)'' fails. +** Let ''r = int(sigi[0:32])''; fail if ''r ≥ p''. +** Let ''si = int(sigi[32:64])''; fail if ''si ≥ n''. +** Let ''ei = int(hash(bytes(r) || bytes(Pi) || mi)) mod n''. +** Let ''Ri = lift_x(r)''; fail if ''lift_x(r)'' fails. +* Fail if ''(s1 + a2s2 + ... + ausu)G ≠ R1 + a2R2 + ... + auRu + e1P1 + (a2e2)P2 + ... + (aueu)Pu''. + +==== Signing ==== + +Input: +* The secret key ''d'': an integer in the range ''1..n-1''. +* The message ''m'': a 32-byte array + +To sign ''m'' for public key ''dG'': +* Let ''k' = int(hash(bytes(d) || m)) mod n''Note that in general, taking the output of a hash function modulo the curve order will produce an unacceptably biased result. However, for the secp256k1 curve, the order is sufficiently close to ''2256'' that this bias is not observable (''1 - n / 2256'' is around ''1.27 * 2-128'').. +* Fail if ''k' = 0''. +* Let ''R = k'G''. +* Let ''k = k' '' if ''jacobi(y(R)) = 1'', otherwise let ''k = n - k' ''. +* Let ''e = int(hash(bytes(x(R)) || bytes(dG) || m)) mod n''. +* The signature is ''bytes(x(R)) || bytes((k + ed) mod n)''. + +'''Above deterministic derivation of ''R'' is designed specifically for this signing algorithm and may not be secure when used in other signature schemes.''' +For example, using the same derivation in the MuSig multi-signature scheme leaks the secret key (see the [https://eprint.iacr.org/2018/068 MuSig paper] for details). + +'''Above deterministic derivation of ''R'' is designed specifically for this signing algorithm and may not be secure when used in other signature schemes.''' +For example, using the same derivation in the MuSig multi-signature scheme leaks the secret key (see the [https://eprint.iacr.org/2018/068 MuSig paper] for details). + +Note that this is not a ''unique signature'' scheme: while this algorithm will always produce the same signature for a given message and public key, ''k'' (and hence ''R'') may be generated in other ways (such as by a CSPRNG) producing a different, but still valid, signature. + +=== Optimizations === + +Many techniques are known for optimizing elliptic curve implementations. Several of them apply here, but are out of scope for this document. Two are listed below however, as they are relevant to the design decisions: + +'''Jacobi symbol''' The function ''jacobi(x)'' is defined as above, but can be computed more efficiently using an [https://en.wikipedia.org/wiki/Jacobi_symbol#Calculating_the_Jacobi_symbol extended GCD algorithm]. + +'''Jacobian coordinates''' Elliptic Curve operations can be implemented more efficiently by using [https://en.wikibooks.org/wiki/Cryptography/Prime_Curve/Jacobian_Coordinates Jacobian coordinates]. Elliptic Curve operations implemented this way avoid many intermediate modular inverses (which are computationally expensive), and the scheme proposed in this document is in fact designed to not need any inversions at all for verification. When operating on a point ''P'' with Jacobian coordinates ''(x,y,z)'' which is not the point at infinity and for which ''x(P)'' is defined as ''x / z2'' and ''y(P)'' is defined as ''y / z3'': +* ''jacobi(y(P))'' can be implemented as ''jacobi(yz mod p)''. +* ''x(P) ≠ r'' can be implemented as ''x ≠ z2r mod p''. + +== Applications == + +There are several interesting applications beyond simple signatures. +While recent academic papers claim that they are also possible with ECDSA, consensus support for Schnorr signature verification would significantly simplify the constructions. + +===Multisignatures and Threshold Signatures=== + +By means of an interactive scheme such as [https://eprint.iacr.org/2018/068 MuSig], participants can produce a combined public key which they can jointly sign for. This allows n-of-n multisignatures which, from a verifier's perspective, are no different from ordinary signatures, giving improved privacy and efficiency versus ''CHECKMULTISIG'' or other means. + +Further, by combining Schnorr signatures with [https://link.springer.com/content/pdf/10.1007/3-540-46766-1_9.pdf Pedersen Secret Sharing], it is possible to obtain [http://cacr.uwaterloo.ca/techreports/2001/corr2001-13.ps an interactive threshold signature scheme] that ensures that signatures can only be produced by arbitrary but predetermined sets of signers. For example, k-of-n threshold signatures can be realized this way. Furthermore, it is possible to replace the combination of participant keys in this scheme with MuSig, though the security of that combination still needs analysis. + +===Adaptor Signatures=== + +[https://download.wpsoftware.net/bitcoin/wizardry/mw-slides/2018-05-18-l2/slides.pdf Adaptor signatures] can be produced by a signer by offsetting his public nonce with a known point ''T = tG'', but not offsetting his secret nonce. +A correct signature (or partial signature, as individual signers' contributions to a multisignature are called) on the same message with same nonce will then be equal to the adaptor signature offset by ''t'', meaning that learning ''t'' is equivalent to learning a correct signature. +This can be used to enable atomic swaps or even [https://eprint.iacr.org/2018/472 general payment channels] in which the atomicity of disjoint transactions is ensured using the signatures themselves, rather than Bitcoin script support. The resulting transactions will appear to verifiers to be no different from ordinary single-signer transactions, except perhaps for the inclusion of locktime refund logic. + +Adaptor signatures, beyond the efficiency and privacy benefits of encoding script semantics into constant-sized signatures, have additional benefits over traditional hash-based payment channels. Specifically, the secret values ''t'' may be reblinded between hops, allowing long chains of transactions to be made atomic while even the participants cannot identify which transactions are part of the chain. Also, because the secret values are chosen at signing time, rather than key generation time, existing outputs may be repurposed for different applications without recourse to the blockchain, even multiple times. + +===Blind Signatures=== + +Schnorr signatures admit a very [https://www.math.uni-frankfurt.de/~dmst/research/papers/schnorr.blind_sigs_attack.2001.pdf simple '''blind signature''' construction] which is a signature that a signer produces at the behest of another party without learning what he has signed. +These can for example be used in [https://github.com/jonasnick/scriptless-scripts/blob/blind-swaps/md/partially-blind-swap.md Partially Blind Atomic Swaps], a construction to enable transferring of coins, mediated by an untrusted escrow agent, without connecting the transactors in the public blockchain transaction graph. + +While the traditional Schnorr blind signatures are vulnerable to [https://www.iacr.org/archive/crypto2002/24420288/24420288.pdf Wagner's attack], there are [https://www.math.uni-frankfurt.de/~dmst/teaching/SS2012/Vorlesung/EBS5.pdf a number of mitigations] which allow them to be usable in practice without any known attacks. Nevertheless, more analysis is required to be confident about the security of the blind signature scheme. + +== Test Vectors and Reference Code == + +For development and testing purposes, we provide a [[bip-schnorr/test-vectors.csv|collection of test vectors in CSV format]] and a naive but highly inefficient and non-constant time [[bip-schnorr/reference.py|pure Python 3.7 reference implementation of the signing and verification algorithm]]. +The reference implementation is for demonstration purposes only and not to be used in production environments. + +== Footnotes == + + + +== Acknowledgements == + +This document is the result of many discussions around Schnorr based signatures over the years, and had input from Johnson Lau, Greg Maxwell, Jonas Nick, Andrew Poelstra, Tim Ruffing, Rusty Russell, and Anthony Towns. diff --git a/bip-schnorr/reference.py b/bip-schnorr/reference.py new file mode 100644 index 0000000..48a36a6 --- /dev/null +++ b/bip-schnorr/reference.py @@ -0,0 +1,136 @@ +import hashlib +import binascii + +p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F +n = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 +G = (0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798, 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8) + +def point_add(P1, P2): + if (P1 is None): + return P2 + if (P2 is None): + return P1 + if (P1[0] == P2[0] and P1[1] != P2[1]): + return None + if (P1 == P2): + lam = (3 * P1[0] * P1[0] * pow(2 * P1[1], p - 2, p)) % p + else: + lam = ((P2[1] - P1[1]) * pow(P2[0] - P1[0], p - 2, p)) % p + x3 = (lam * lam - P1[0] - P2[0]) % p + return (x3, (lam * (P1[0] - x3) - P1[1]) % p) + +def point_mul(P, n): + R = None + for i in range(256): + if ((n >> i) & 1): + R = point_add(R, P) + P = point_add(P, P) + return R + +def bytes_from_int(x): + return x.to_bytes(32, byteorder="big") + +def bytes_from_point(P): + return (b'\x03' if P[1] & 1 else b'\x02') + bytes_from_int(P[0]) + +def point_from_bytes(b): + if b[0] in [b'\x02', b'\x03']: + odd = b[0] - 0x02 + else: + return None + x = int_from_bytes(b[1:33]) + y_sq = (pow(x, 3, p) + 7) % p + y0 = pow(y_sq, (p + 1) // 4, p) + if pow(y0, 2, p) != y_sq: + return None + y = p - y0 if y0 & 1 != odd else y0 + return [x, y] + +def int_from_bytes(b): + return int.from_bytes(b, byteorder="big") + +def hash_sha256(b): + return hashlib.sha256(b).digest() + +def jacobi(x): + return pow(x, (p - 1) // 2, p) + +def schnorr_sign(msg, seckey): + if len(msg) != 32: + raise ValueError('The message must be a 32-byte array.') + if not (1 <= seckey <= n - 1): + raise ValueError('The secret key must be an integer in the range 1..n-1.') + k0 = int_from_bytes(hash_sha256(bytes_from_int(seckey) + msg)) % n + if k0 == 0: + raise RuntimeError('Failure. This happens only with negligible probability.') + R = point_mul(G, k0) + k = n - k0 if (jacobi(R[1]) != 1) else k0 + e = int_from_bytes(hash_sha256(bytes_from_int(R[0]) + bytes_from_point(point_mul(G, seckey)) + msg)) % n + return bytes_from_int(R[0]) + bytes_from_int((k + e * seckey) % n) + +def schnorr_verify(msg, pubkey, sig): + if len(msg) != 32: + raise ValueError('The message must be a 32-byte array.') + if len(pubkey) != 33: + raise ValueError('The public key must be a 33-byte array.') + if len(sig) != 64: + raise ValueError('The signature must be a 64-byte array.') + P = point_from_bytes(pubkey) + if (P is None): + return False + r = int_from_bytes(sig[0:32]) + s = int_from_bytes(sig[32:64]) + if (r >= p or s >= n): + return False + e = int_from_bytes(hash_sha256(sig[0:32] + bytes_from_point(P) + msg)) % n + R = point_add(point_mul(G, s), point_mul(P, n - e)) + if R is None or jacobi(R[1]) != 1 or R[0] != r: + return False + return True + +# +# The following code is only used to verify the test vectors. +# +import csv + +def test_vectors(): + all_passed = True + with open('test-vectors.csv', newline='') as csvfile: + reader = csv.reader(csvfile) + reader.__next__() + for row in reader: + (index, seckey, pubkey, msg, sig, result, comment) = row + pubkey = bytes.fromhex(pubkey) + msg = bytes.fromhex(msg) + sig = bytes.fromhex(sig) + result = result == 'TRUE' + print('\nTest vector #%-3i: ' % int(index)) + if seckey != '': + seckey = int(seckey, 16) + sig_actual = schnorr_sign(msg, seckey) + if sig == sig_actual: + print(' * Passed signing test.') + else: + print(' * Failed signing test.') + print(' Excepted signature:', sig.hex()) + print(' Actual signature:', sig_actual.hex()) + all_passed = False + result_actual = schnorr_verify(msg, pubkey, sig) + if result == result_actual: + print(' * Passed verification test.') + else: + print(' * Failed verification test.') + print(' Excepted verification result:', result) + print(' Actual verification result:', result_actual) + if comment: + print(' Comment:', comment) + all_passed = False + print() + if all_passed: + print('All test vectors passed.') + else: + print('Some test vectors failed.') + return all_passed + +if __name__ == '__main__': + test_vectors() diff --git a/bip-schnorr/speedup-batch.png b/bip-schnorr/speedup-batch.png new file mode 100644 index 0000000..fe672d4 Binary files /dev/null and b/bip-schnorr/speedup-batch.png differ diff --git a/bip-schnorr/test-vectors.csv b/bip-schnorr/test-vectors.csv new file mode 100644 index 0000000..9b89a7b --- /dev/null +++ b/bip-schnorr/test-vectors.csv @@ -0,0 +1,17 @@ +index,secret key,public key,message,signature,verification result,comment +1,0000000000000000000000000000000000000000000000000000000000000001,0279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798,0000000000000000000000000000000000000000000000000000000000000000,787A848E71043D280C50470E8E1532B2DD5D20EE912A45DBDD2BD1DFBF187EF67031A98831859DC34DFFEEDDA86831842CCD0079E1F92AF177F7F22CC1DCED05,TRUE, +2,B7E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEF,02DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,2A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1D1E51A22CCEC35599B8F266912281F8365FFC2D035A230434A1A64DC59F7013FD,TRUE, +3,C90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B14E5C7,03FAC2114C2FBB091527EB7C64ECB11F8021CB45E8E7809D3C0938E4B8C0E5F84B,5E2D58D8B3BCDF1ABADEC7829054F90DDA9805AAB56C77333024B9D0A508B75C,00DA9B08172A9B6F0466A2DEFD817F2D7AB437E0D253CB5395A963866B3574BE00880371D01766935B92D2AB4CD5C8A2A5837EC57FED7660773A05F0DE142380,TRUE, +4,,03DEFDEA4CDB677750A420FEE807EACF21EB9898AE79B9768766E4FAA04A2D4A34,4DF3C3F68FCC83B27E9D42C90431A72499F17875C81A599B566C9889B9696703,00000000000000000000003B78CE563F89A0ED9414F5AA28AD0D96D6795F9C6302A8DC32E64E86A333F20EF56EAC9BA30B7246D6D25E22ADB8C6BE1AEB08D49D,TRUE, +5,,031B84C5567B126440995D3ED5AABA0565D71E1834604819FF9C17F5E9D5DD078F,0000000000000000000000000000000000000000000000000000000000000000,52818579ACA59767E3291D91B76B637BEF062083284992F2D95F564CA6CB4E3530B1DA849C8E8304ADC0CFE870660334B3CFC18E825EF1DB34CFAE3DFC5D8187,TRUE,"test fails if jacobi symbol of x(R) instead of y(R) is used" +6,,03FAC2114C2FBB091527EB7C64ECB11F8021CB45E8E7809D3C0938E4B8C0E5F84B,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,570DD4CA83D4E6317B8EE6BAE83467A1BF419D0767122DE409394414B05080DCE9EE5F237CBD108EABAE1E37759AE47F8E4203DA3532EB28DB860F33D62D49BD,TRUE,"test fails if msg is reduced" +7,,03EEFDEA4CDB677750A420FEE807EACF21EB9898AE79B9768766E4FAA04A2D4A34,4DF3C3F68FCC83B27E9D42C90431A72499F17875C81A599B566C9889B9696703,00000000000000000000003B78CE563F89A0ED9414F5AA28AD0D96D6795F9C6302A8DC32E64E86A333F20EF56EAC9BA30B7246D6D25E22ADB8C6BE1AEB08D49D,FALSE,"public key not on the curve" +8,,02DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,2A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1DFA16AEE06609280A19B67A24E1977E4697712B5FD2943914ECD5F730901B4AB7,FALSE,"incorrect R residuosity" +9,,03FAC2114C2FBB091527EB7C64ECB11F8021CB45E8E7809D3C0938E4B8C0E5F84B,5E2D58D8B3BCDF1ABADEC7829054F90DDA9805AAB56C77333024B9D0A508B75C, 00DA9B08172A9B6F0466A2DEFD817F2D7AB437E0D253CB5395A963866B3574BED092F9D860F1776A1F7412AD8A1EB50DACCC222BC8C0E26B2056DF2F273EFDEC,FALSE,"negated message hash" +10,,0279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798,0000000000000000000000000000000000000000000000000000000000000000,787A848E71043D280C50470E8E1532B2DD5D20EE912A45DBDD2BD1DFBF187EF68FCE5677CE7A623CB20011225797CE7A8DE1DC6CCD4F754A47DA6C600E59543C,FALSE,"negated s value" +11,,03DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,2A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1D1E51A22CCEC35599B8F266912281F8365FFC2D035A230434A1A64DC59F7013FD,FALSE,"negated public key" +12,,02DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,00000000000000000000000000000000000000000000000000000000000000009E9D01AF988B5CEDCE47221BFA9B222721F3FA408915444A4B489021DB55775F,FALSE,"sG - eP is infinite. Test fails in single verification if jacobi(y(inf)) is defined as 1 and x(inf) as 0" +13,,02DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,0000000000000000000000000000000000000000000000000000000000000001D37DDF0254351836D84B1BD6A795FD5D523048F298C4214D187FE4892947F728,FALSE,"sG - eP is infinite. Test fails in single verification if jacobi(y(inf)) is defined as 1 and x(inf) as 1" +14,,02DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,4A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1D1E51A22CCEC35599B8F266912281F8365FFC2D035A230434A1A64DC59F7013FD,FALSE,"sig[0:32] is not an X coordinate on the curve" +15,,02DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC2F1E51A22CCEC35599B8F266912281F8365FFC2D035A230434A1A64DC59F7013FD,FALSE,"sig[0:32] is equal to field size" +16,,02DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,2A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141,FALSE,"sig[32:64] is equal to curve order" -- cgit v1.2.3 From 6733024595ee2affa0977008e020724ddf8903e0 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 6 May 2019 10:46:09 -0700 Subject: Add taproot/tapscript bips drafts --- bip-taproot.mediawiki | 285 ++++++++++++++++++++++++++++++++++++++++++++++++ bip-taproot/tree.png | Bin 0 -> 78937 bytes bip-tapscript.mediawiki | 147 +++++++++++++++++++++++++ 3 files changed, 432 insertions(+) create mode 100644 bip-taproot.mediawiki create mode 100644 bip-taproot/tree.png create mode 100644 bip-tapscript.mediawiki diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki new file mode 100644 index 0000000..2e8b43b --- /dev/null +++ b/bip-taproot.mediawiki @@ -0,0 +1,285 @@ +
+  BIP: bip-taproot
+  Layer: Consensus (soft fork)
+  Title: Taproot: SegWit version 1 output spending rules
+  Author: Pieter Wuille 
+  Comments-Summary: No comments yet.
+  Comments-URI:
+  Status: Draft
+  Type: Standards Track
+  Created:
+  License: BSD-3-Clause
+
+ +==Introduction== + +===Abstract=== + +This document proposes a new SegWit version 1 output type, with spending rules based on Taproot, Schnorr signatures, and Merkle branches. + +===Copyright=== + +This document is licensed under the 3-clause BSD license. + +===Motivation=== + +A number of related ideas for improving Bitcoin's scripting capabilities have been previously proposed: Schnorr signatures (bip-schnorr), Merkle branches ("MAST", [https://github.com/bitcoin/bips/blob/master/bip-0114.mediawiki BIP114], [https://github.com/bitcoin/bips/blob/master/bip-0117.mediawiki BIP117]), new sighash modes ([https://github.com/bitcoin/bips/blob/master/bip-0118.mediawiki BIP118]), new opcodes like CHECKSIGFROMSTACK, [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-January/015614.html Taproot], [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-February/015700.html Graftroot], [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-July/016249.html G'root], and [https://bitcointalk.org/index.php?topic=1377298.0 cross-input aggregation]. + +Combining all these ideas in a single proposal would be an extensive change, be hard to review, and likely miss new discoveries that otherwise could have been made along the way. Some of these ideas are also less mature than others. On the other hand, separating them all into independent proposals would reduce the efficiency and privacy gains to be had, and complicate analysis of their interactions. It seems preferable to focus on one goal set at a time, and combine interacting technologies to achieve them. + +==Design== + +This proposal focuses on improvements to privacy, efficiency, and flexibility of Bitcoin's smart contracts, subject to two restrictions: +* Not adding any new strong security assumptions +* Not combining into the proposal any functionality which could be simply implemented independently. + +Specifically, it seeks to minimize how much information about the spendability conditions of a transaction output is revealed on chain at creation or spending time. To avoid reducing the effectiveness of future improvements a number of upgrade mechanisms are also included, as well as fixes for minor but long-standing issues. + +As a result we choose this combination of technologies: +* '''Merkle branches''' let us only reveal the actually executed part of the script to the blockchain, as opposed to all possible ways a script can be executed. Among the various known mechanisms for implementing this, one where the Merkle tree becomes part of the script's structure directly maximizes the space savings, so that approach is chosen. +* '''Taproot''' on top of that lets us merge the traditionally separate pay-to-pubkey and pay-to-scripthash policies, making all outputs spendable by either a key or (optionally) a script, and indistinguishable from each other. As long as the key-based spending path is used for spending, it is not revealed whether a script path was permitted as well, resulting in space savings and an increase in scripting privacy at spending time. +* Taproot's advantages become apparent under the assumption that most applications involve outputs that could be spent by all parties agreeing. That's where '''Schnorr''' signatures come in, as they permit [https://eprint.iacr.org/2018/068 key aggregation]: a public key can be constructed from multiple participant public keys, and which requires cooperation between all participants to sign for. Such multi-party public keys and signatures are indistinguishable from their single-party equivalents. This means that under this Taproot assumption, the all-parties-agree case can be handled using the key-based spending path, which is both private and efficient using Taproot. This can be generalized to arbitrary M-of-N policies, as Schnorr signatures support threshold signing, at the cost of more complex setup protocols. +* As Schnorr signatures also permit '''batch validation''', allowing multiple signatures to be validated together more efficiently than validating each one independently, we make sure all parts of the design are compatible with this. +* Where unused bits appear as a result of the above changes, they are reserved for mechanisms for '''future extensions'''. As a result, every script in the Merkle tree has an associated version such that new script versions can be introduced with a soft fork while remaining compatible with bip-taproot. Additionally, future soft forks can make use of the currently unused annex in the witness (see [[#Rationale]]). +* While the core semantics of the '''signature hashing algorithm''' are not changed, a number of improvements are included in this proposal. The new signature hashing algorithm fixes the verification capabilities of offline signing devices by including amount and scriptPubKey in the digest, avoids unnecessary hashing, introduces '''tagged hashes''' and defines a default sighash byte. + +Not included in this proposal are additional features like new sighash modes or opcodes that can be included with no loss in effectiveness as a future extension. Also not included is cross-input aggregation, as it [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-March/015838.html interacts] in complex ways with upgrade mechanisms and solutions to that are still [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-October/016461.html in flux]. + +== Specification == + +This section specifies the Taproot consensus rules. Validity is defined by exclusion: a block or transaction is valid if no condition exists that marks it failed. + +The notation below follows that of bip-schnorr. + +=== Tagged hashes === + +Cryptographic hash functions are used for multiple purposes in the specification below and in Bitcoin in general. To make sure hashes used in one context can't be reinterpreted in another one, all hash functions are tweaked with a context-dependent tag name, in such a way that collisions across contexts can be assumed to be infeasible. + +In the text below, ''hashtag(m)'' is a shorthand for ''SHA256(SHA256(tag) || SHA256(tag) || m)'', where ''tag'' is a UTF-8 encoded tag name. +* So far, nowhere in the Bitcoin protocol are hashes used where the input of SHA256 starts with two (non-double) SHA256 hashes, making collisions with existing uses of hash functions infeasible. +* Because the prefix ''SHA256(tag) || SHA256(tag)'' is a 64-byte long context-specific constant, optimized implementations are possible (identical to SHA256 itself, but with a modified initial state). +* Using SHA256 of the tag name itself is reasonably simple and efficient for implementations that don't choose to use the optimization above. + +=== Script validation rules === + +A Taproot output is a SegWit output (native or P2SH-nested, see [https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki BIP141]) with version number 1, and a 33-byte witness program whose first byte is 0 or 1. +The following rules only apply when such an output is being spent. Any other outputs, including version 1 outputs with lengths other than 33 bytes, or with a first byte different from 0 or 1, remain unencumbered. + +* Let ''u'' be the 33-byte array containing the witness program (second push in scriptPubKey or P2SH redeemScript). +* Let ''Q = point(byte(2 + u[0]) || u[1:33])'''''Why is the public key directly included in the output?''' While typical earlier constructions store a hash of a script or a public key in the output, this is rather wasteful when a public key is always involved. To guarantee batch verifiability, ''Q'' must be known to every verifier, and thus only revealing its hash as an output would imply adding an additional 33 bytes to the witness. Furthermore, to maintain [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2016-January/012198.html 128-bit collision security] for outputs, a 256-bit hash would be required anyway, which is comparable in size (and thus in cost for senders) to revealing the public key directly. While the usage of public key hashes is often said to protect against ECDLP breaks or quantum computers, this protection is very weak at best: transactions are not protected while being confirmed, and a very [https://twitter.com/pwuille/status/1108097835365339136 large portion] of the currency's supply is not under such protection regardless. Actual resistance to such systems can be introduced by relying on different cryptographic assumptions, but this proposal focuses on improvements that do not change the security model. Note that using P2SH-wrapped outputs only have 80-bit collision security. This is considered low, and is relevant whenever the output includes data from more than a single party (public keys, hashes, ...). If this is not a valid point on the curve, fail. +* Fail if the witness stack has 0 elements. +* If there are at least two witness elements, and the first byte of the last element is 0x50'''Why is the first byte of the annex 0x50?''' Like the 0xc0-0xc1 constants, 0x50 is chosen as it could not be confused with a valid P2WPKH or P2WSH spending. As the control block's initial byte's lowest bit is used to indicate the public key's Y oddness, each script version needs two subsequence byte values that are both not yet used in P2WPKH or P2WSH spending. To indicate the annex, only an "unpaired" available byte is necessary like 0x50. This choice maximizes the available options for future script versions., this last element is called ''annex'' ''a'''''What is the purpose of the annex?''' The annex is a reserved space for future extensions, such as indicating the validation costs of computationally expensive new opcodes in a way that is recognizable without knowing the outputs being spent. Until the meaning of this field is defined by another softfork, users SHOULD NOT include annex in transactions, or it may lead to PERMANENT FUND LOSS. and is removed from the witness stack. The annex (or the lack of thereof) is always covered by the transaction digest and contributes to transaction weight, but is otherwise ignored during taproot validation. +* If there is exactly one element left in the witness stack, key path spending is used: +** The single witness stack element is interpreted as the signature and must be valid (see the next section) for the public key ''Q'' and taproot transaction digest (to be defined hereinafter) as message. Fail if it is not. Otherwise pass. +* If there are at least two witness elements left, script path spending is used: +** Call the second-to-last stack element ''s'', the script. +** The last stack element is called the control block ''c'', and must have length ''33 + 32m'', for a value of ''m'' that is an integer between 0 and 32, inclusive. Fail if it does not have such a length. +** Let ''P = point(byte(2 + (c[0] & 1)) || c[1:33])'''''What is the purpose of the first byte of the control block?''' The first byte of the control block has three distinct functions: +* The low bit is used to denote the oddness of the Y coordinate of the ''P'' point. +* By keeping the top two bits set to true, it can be guaranteed that scripts can be recognized without knowledge of the UTXO being spent, simplifying analysis. This is because such values cannot occur as first byte of the final stack element in either P2WPKH or P2WSH spends. +* The remaining five bits are used for introducing new script versions that are not observable unless actually executed. +. Fail if this point is not on the curve. +** Let ''l = c[0] & 0xfe'', the leaf version. +** Let ''k0 = hashTapLeaf(l || compact_size(size of s) || s)''; also call it the ''tapleaf hash''. +** For ''j'' in ''[0,1,...,m-1]'': +*** Let ''ej = c[33+32j:65+32j]''. +*** Let ''kj+1 depend on whether ''kj < ej'' (lexicographically)'''Why are child elements sorted before hashing in the Merkle tree?''' By doing so, it is not necessary to reveal the left/right directions along with the hashes in revealed Merkle branches. This is possible because we do not actually care about the position of specific scripts in the tree; only that they are actually committed to.: +**** If ''kj < ej'': ''kj+1 = hashTapBranch(kj || ej)'''''Why not use a more efficient hash construction for inner Merkle nodes?''' The chosen construction does require two invocations of the SHA256 compression functions, one of which can be avoided in theory (see BIP98). However, it seems preferable to stick to constructions that can be implemented using standard cryptographic primitives, both for implementation simplicity and analyzability. If necessary, a significant part of the second compression function can be optimized out by [https://github.com/bitcoin/bitcoin/pull/13191 specialization] for 64-byte inputs.. +**** If ''kj ≥ ej'': ''kj+1 = hashTapBranch(ej || kj)''. +** Let ''t = hashTapTweak(bytes(P) || km) = hashTapTweak(2 + (c[0] & 1) || c[1:33] || km)''. +** If ''t ≥ 0xFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141'' (order of secp256k1), fail. +** If ''Q ≠ P + int(t)G'', fail. +** Execute the script, according to the applicable script rules'''What are the applicable script rules in script path spends?''' Bip-tapscript specifies validity rules that apply if the leaf version is ''0xc0'', but future proposals can introduce rules for other leaf versions., using the witness stack elements excluding the script ''s'', the control block ''c'', and the annex ''a'' if present, as initial stack. + +''Q'' is referred to as ''taproot output key'' and ''P'' as ''taproot internal key''. + +=== Signature validation rules === + +The following rules apply: + +* If the signature is not 64'''Why permit two signature lengths?''' By making the most common type of hash_type implicit, a byte can often be saved. or 65 bytes, fail. +* If the signature size is 65 bytes: +** If the final byte is not a valid hash_type (defined hereinafter), fail. +** If the final byte is 0x00, fail'''Why can the hash_type not be 0x00 in 65-byte signatures?''' Permitting that would enable malleating 64-byte signatures into 65-byte ones, resulting a different fee rate than the creator intended. +** If the first 64 bytes are not a valid signature according to bip-schnorr for the public key and message set to the transaction digest with hash_type set as the final byte, fail. +* If the signature size is 64 bytes: +** If it is not a valid signature according to bip-schnorr for the public key and the hash_type = 0x00 transaction digest as message, fail. +* Otherwise the signature is valid. + +==== hash_type ==== + +hash_type is an 8-bit unsigned value. The SIGHASH encodings from the legacy script system are used, including SIGHASH_ALL, SIGHASH_NONE, SIGHASH_SINGLE, and SIGHASH_ANYONECANPAY + +The following use of hash_type are invalid, and fail execution: + +* Using SIGHASH_SINGLE without a "corresponding output" (an output with the same index as the input being verified). +* Using any hash_type value that is not 0x00, 0x01, 0x02, 0x03, 0x81, 0x82, or 0x83'''Why reject unknown hash_type values?''' By doing so, it is easier to reason about the worst case amount of signature hashing an implementation with adequate caching must perform.. +* The signature has 65 bytes, and hash_type is 0x00. + +==== Transaction digest ==== + +As the message for signature verification, transaction digest is ''hashTapSighash'' of the following values (size in byte) serialized. Numerical values in 2, 4, or 8-byte are encoded in little-endian. + +* Control: +** epoch (1): always 0. '''What's the purpose of the epoch?''' The epoch can be increased to allow securely creating a new transaction digest algorithms with large changes to the structure or interpretation of hash_type if needed. +** hash_type (1). +* Transaction data: +** nVersion (4): the nVersion of the transaction. +** nLockTime (4): the nLockTime of the transaction. +** If the SIGHASH_ANYONECANPAY flag is not set: +*** sha_prevouts (32): the SHA256 of the serialization of all input outpoints. +*** sha_amounts (32): the SHA256 of the serialization of all input amounts. +*** sha_sequences (32): the SHA256 of the serialization of all input nSequence. +** If both the SIGHASH_NONE and SIGHASH_SINGLE flags are not set: +*** sha_outputs (32): the SHA256 of the serialization of all outputs in CTxOut format. +* Data about this input: +** spend_type (1): +*** Bit-0 is set if the scriptPubKey being spent is P2SH (opposed to "native segwit"). +*** Bit-1 is set if an annex is present (the original witness stack has two or more witness elements, and the first byte of the last element is 0x50). +*** The other bits are unset. +** scriptPubKey (24 or 36): scriptPubKey of the previous output spent by this input, serialized as script inside CTxOut. The size is 24-byte for P2SH-embedded segwit, or 36-byte for native segwit. +** If the SIGHASH_ANYONECANPAY flag is set: +*** outpoint (36): the COutPoint of this input (32-byte hash + 4-byte little-endian). +*** amount (8): value of the previous output spent by this input. +*** nSequence (4): nSequence of this input. +** If the SIGHASH_ANYONECANPAY flag is not set: +*** input_index (2): index of this input in the transaction input vector. Index of the first input is 0. +** If the bit-1 of spend_type is set: +*** sha_annex (32): the SHA256 of (compact_size(size of annex) || annex). +* Data about this output: +** If the SIGHASH_SINGLE flag is set: +*** sha_single_output (32): the SHA256 of the corresponding output in CTxOut format. + +The total number of bytes hashed is at most ''209'''''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''177 - is_anyonecanpay * 50 - is_none * 32 - is_p2sh_spending * 12 + has_annex * 32''.. + +In summary, the semantics of the BIP143 sighash types remain unchanged, except the following: +# The way and order of serialization is changed.'''Why is the serialization in the transaction digest changed?''' Hashes that go into the digest and the digest itself are now computed with a single SHA256 invocation instead of double SHA256. There is no expected security improvement by doubling SHA256 because this only protects against length-extension attacks against SHA256 which are not a concern for transaction digests because there is no secret data. Therefore doubling SHA256 is a waste of resources. The digest computation now follows a logical order with transaction level data first, then input data and output data. This allows to efficiently cache the transaction part of the digest across different inputs using the SHA256 midstate. Additionally, digest computation avoids unnecessary hashing as opposed to BIP143 digests in which parts may be set zero and before hashing them. Despite that, collisions are made impossible by committing to the length of the data (implicit in hash_type and spend_type) before the variable length data. +# The digest commits to the scriptPubKey'''Why does the transaction digest commit to the scriptPubKey?''' This prevents lying to offline signing devices about the type of output being spent, even when the actually executed script (scriptCode in BIP143) is correct. Without committing to the scriptPubKey an attacker can fool the device into overpaying fees by asking it to sign for a P2SH wrapped segwit output but actually using it to spend a native segwit output.. +# If the SIGHASH_ANYONECANPAY flag is not set, the digest commits to the amounts of ''all'' transaction inputs.'''Why does the transaction digest commit to the amounts of all transaction inputs?''' This eliminates the possibility to lie to offline signing devices about the fee of a transaction. +# The digest commits to all input nSequence if SIGHASH_NONE or SIGHASH_SINGLE are set (unless SIGHASH_ANYONECANPAY is set as well).'''Why does the transaction digest commit to all input nSequence if SIGHASH_SINGLE or SIGHASH_NONE are set?''' Because setting them already makes the digest commit to the prevouts part of all transaction inputs, it is not useful to treat the nSequence any different. Moreover, this change makes nSequence consistent with the view that SIGHASH_SINGLE and SIGHASH_NONE only modify the digest with respect to transaction outputs and not inputs. +# The digest commits to taproot-specific data epoch, spend_type and annex (if present). + +== Constructing and spending Taproot outputs == + +This section discusses how to construct and spend Taproot outputs. It only affects wallet software that chooses to implement receiving and spending, +and is not consensus critical in any way. + +Conceptually, every Taproot output corresponds to a combination of a single public key condition (the internal key), and zero or more general conditions encoded in scripts organized in a tree. +Satisfying any of these conditions is sufficient to spend the output. + +'''Initial steps''' The first step is determining what the internal key and the organization of the rest of the scripts should be. The specifics are likely application dependent, but here are some general guidelines: +* When deciding between scripts with conditionals (OP_IF etc.) and splitting them up into multiple scripts (each corresponding to one execution path through the original script), it is generally preferable to pick the latter. +* When a single condition requires signatures with multiple keys, key aggregation techniques like MuSig can be used to combine them into a single key. The details are out of scope for this document, but note that this may complicate the signing procedure. +* If one or more of the spending conditions consist of just a single key (after aggregation), the most likely one should be made the internal key. If no such condition exists, it may be worthwhile adding one that consists of an aggregation of all keys participating in all scripts combined; effectively adding an "everyone agrees" branch. If that is inacceptable, pick as internal key a point with unknown discrete logarithm (TODO). +* The remaining scripts should be organized into the leaves of a binary tree. This can be a balanced tree if each of the conditions these scripts correspond to are equally likely. If probabilities for each condition are known, consider constructing the tree as a Huffman tree. + +'''Computing the output script''' Once the spending conditions are split into an internal key internal_pubkey and a binary tree whose leaves are (leaf_version, script) tuples, the following Python3 algorithm can be used to compute the output script. In the code below, ser_script prefixes its input with a CCompactSize-encoded length, and public key objects have methods get_bytes to get their compressed encoding (see bip-schnorr) and tweak_add to add a multiple of the secp256k1 generator to it (similar to BIP32's derivation). + + +import hashlib + +def tagged_hash(tag, msg): + tag_hash = hashlib.sha256(tag.encode()).digest() + return hashlib.sha256(tag_hash + tag_hash + msg).digest() + +def taproot_tree_helper(script_tree): + if isinstance(script_tree, tuple): + leaf_version, script = script_tree + h = tagged_hash("TapLeaf", bytes([leaf_version]) + ser_script(script)) + return ([((leaf_version, script), bytes())], h) + left, left_h = taproot_tree_helper(script_tree[0]) + right, right_h = taproot_tree_helper(script_tree[1]) + ret = [(l, c + right_h) for l, c in left] + [(l, c + left_h) for l, c in right] + if right_h < left_h: + left_h, right_h = right_h, left_h + return (ret, tagged_hash("TapBranch", left_h + right_h)) + +def taproot_output_script(internal_pubkey, script_tree): + """Given a internal public key and a tree of scripts, compute the output script. + script_tree is either: + - a (leaf_version, script) tuple (leaf_version is 0xc0 for bip-tapscript scripts) + - a list of two elements, each with the same structure as script_tree itself""" + _, h = taproot_tree_helper(script_tree) + t = tagged_hash("TapTweak", internal_pubkey.get_bytes() + h) + assert int.from_bytes(t, 'big') < SECP256K1_ORDER + output_pubkey = internal_pubkey.tweak_add(t).get_bytes() + return bytes([0x01, 0x21, output_pubkey[0] & 1]) + output_pubkey[1:] + + +The function taproot_output_script returns a byte array with the scriptPubKey. It can be P2SH wrapped if desired (see BIP141). + +[[File:bip-taproot/tree.png|frame|This diagram shows the hashing structure to obtain the tweak from an internal key ''P'' and a Merkle tree consisting of 3 script leaves.]] + +'''Spending using the internal key''' A Taproot output can be spent with the private key corresponding to the internal_pubkey. To do so, a witness stack consisting of a single element, a bip-schnorr signature on the signature hash as defined above, with the private key tweaked by the same t in the above snippet. See the code below: + + +def taproot_sign_internal_key(internal_pubkey, script_tree, internal_privkey, hash_type): + _, h = taproot_tree_helper(script_tree) + t = tagged_hash("TapTweak", internal_pubkey.get_bytes() + h) + output_privkey = internal_privkey.tweak_add(t) + sig = output_privkey.sign_schnorr(sighash(hash_type)) + if hash_type != 0: + sig += bytes([hash_type]) + return [sig] + + +This function returns the witness stack necessary, and assumes a tweak_add method on private keys, and a sighash function to compute the signature hash as defined above (for simplicity, the snippet above ignores passing information like the transaction, the input position, P2SH or not, ... to the sighashing code). + +'''Spending using one of the scripts''' A Taproot output can be spent by satisfying any of the scripts used in its construction. To do so, a witness stack consisting of the script's inputs, plus the script itself and the control block are necessary. See the code below: + + +def taproot_sign_script(internal_pubkey, script_tree, script_num, inputs): + info, _ = taproot_tree_helper(script_tree) + (leaf_version, script), path = info[script_num] + pubkey_bytes = internal_pubkey.get_bytes() + pubkey_data = bytes([(pubkey_bytes[0] & 1) + leaf_version]) + pubkey_bytes[1:] + return inputs + [script, pubkey_data + path] + + +== Security == + +Taproot improves the privacy of Bitcoin because instead of revealing all possible conditions for spending an output, only the satisfied spending condition has to be published. +Ideally, outputs are spent using the key path which prevents observers from learning the spending conditions of a coin. +A key path spend could be a "normal" payment from a single- or multi-signature wallet or the cooperative settlement of hidden multiparty contract. + +A script path spend leaks that there is a script path and that the key path was not applicable - for example because the involved parties failed to reach agreement. +Moreover, the depth of a script in the Merkle root leaks information including the minimum depth of the tree, which suggests specific wallet software that created the output and helps clustering. +Therefore, the privacy of key spends can be improved by deviating from the optimal tree determined by the probability distribution over the leaves. + +Just like other existing output types, taproot outputs should never reuse keys. +This does not only apply to the particular leaf that was used to spend an output but to all leaves committed to in the output. +If leaves were reused, it could happen that spending a different output would reuse the same Merkle branches in the Merkle proof. +Using fresh keys implies that taproot output construction does not need to take special measures to randomizing leaf positions because they are already randomized due to the branch-sorting Merkle tree construction used in taproot. +This does not avoid leaking information through the leaf depth and therefore only applies to balanced (sub-) trees. +In addition, every leaf should have a set of keys distinct from every other leaf. +The reason for this is to increase leaf entropy and prevent an observer from learning an undisclosed script using brute-force search. + +== Test vectors == + +Examples with creation transaction and spending transaction pairs, valid and invalid. + +Examples of preimage for sighashing for each of the sighash modes. + +== Rationale == + + + +== Deployment == + +TODO + +== Backwards compatibility == +As a soft fork, older software will continue to operate without modification. +Non-upgraded nodes, however, will consider all SegWit version 1 witness programs as anyone-can-spend scripts. +They are strongly encouraged to upgrade in order to fully validate the new programs. + +Non-upgraded wallets can receive and send bitcoin from non-upgraded and upgraded wallets using SegWit version 0 programs, traditional pay-to-pubkey-hash, etc. +Depending on the implementation non-upgraded wallets may be able to send to Segwit version 1 programs if they support sending to BIP173 Bech32 addresses and non-standardness of these outputs does not prevent transaction broadcasting. +Non-upgraded wallets can send bitcoin to upgraded wallets using Segwit version 1 programs nested in BIP16 P2SH. + +== Acknowledgements == + +This document is the result of discussions around script and signature improvements with many people, and had direct constributions from Jonas Nick, Anthony Towns, Greg Maxwell, and others. It further builds on top of earlier published proposals such as Taproot by Greg Maxwell, and Merkle branch constructions by Russell O'Connor, Johnson Lau, and Mark Friedenbach. + +Thanks to Arik Sosman for suggesting to sort Merkle node children before hashes, removing the need to transfer the position in the tree. + diff --git a/bip-taproot/tree.png b/bip-taproot/tree.png new file mode 100644 index 0000000..af56eda Binary files /dev/null and b/bip-taproot/tree.png differ diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki new file mode 100644 index 0000000..ce42098 --- /dev/null +++ b/bip-tapscript.mediawiki @@ -0,0 +1,147 @@ +
+  BIP: bip-tapscript
+  Layer: Consensus (soft fork)
+  Title: Validation of Taproot Scripts
+  Author: Pieter Wuille 
+  Comments-Summary: No comments yet.
+  Comments-URI:
+  Status: Draft
+  Type: Standards Track
+  Created:
+  License: BSD-3-Clause
+
+ +==Introduction== + +===Abstract=== + +This document specifies the semantics of the initial scripting system under bip-taproot. + +===Copyright=== + +This document is licensed under the 3-clause BSD license. + +===Motivation=== + +Bip-taproot proposes improvements to just the script structure, but some of its goals are incompatible with the semantics of certain opcodes within the scripting language itself. +While it is possible to deal with these in separate optional improvements, their impact is not guaranteed unless they are addressed simultaneously with bip-taproot itself. + +Specifically, the goal is making '''Schnorr signatures''', '''batch validation''', and '''signature hash''' improvements available to spends that use the script system as well. + +==Design== + +In order to achieve these goals, signature opcodes OP_CHECKSIG and OP_CHECKSIGVERIFY are modified to verify Schnorr signatures as specified in bip-schnorr and to use a new transaction digest based on the taproot transaction digest. +The tapscript transaction digest also simplifies OP_CODESEPARATOR handling and makes it more efficient. + +The inefficient OP_CHECKMULTISIG and OP_CHECKMULTISIGVERIFY opcodes are disabled. +Instead, a new opcode OP_CHECKSIGADD is introduced to allow creating the same multisignature policies in a batch-verifiable way. +Tapscript uses a new, simpler signature opcode limit fixing complicated interactions with transaction weight. +Furthermore, a potential malleability vector is eliminated by requiring MINIMALIF. + +Tapscript can be upgraded through soft forks by defining unknown key types, for example to add new hash_types or signature algorithms. +Additionally, the new tapscript OP_SUCCESS opcodes allow introducing new opcodes more cleanly than through OP_NOP. + +==Specification== + +The rules below only apply when validating a transaction input for which all of the conditions below are true: +* The transaction output is a '''segregated witness spend''' (i.e., either the scriptPubKey or BIP16 redeemScript is a witness program as defined in BIP141). +* It is a '''taproot spend''' as defined in bip-taproot (i.e., the witness version is 1, the witness program is 33 bytes, and the first of those is 0x00 or 0x01). +* It is a '''script path spend''' as defined in bip-taproot (i.e., after removing the optional annex from the witness stack, two or more stack elements remain). +* The leaf version is ''0xc0'' (i.e. the first byte of the last witness element after removing the optional annex is ''0xc0'' or ''0xc1'')'''How is the ''0xc0'' constant chosen?''' Following the guidelines in bip-taproot, by choosing a value having the two top bits set, tapscript spends are identifiable even without access to the UTXO being spent., marking it as a '''tapscript spend'''. + +Validation of such inputs must be equivalent to performing the following steps in the specified order. +# If the input is invalid due to BIP16, BIP141, or bip-taproot, fail. +# The script as defined in bip-taproot (i.e., the penultimate witness stack element after removing the optional annex) is called the '''tapscript''' and is decoded into opcodes, one by one: +## If any opcode numbered ''80, 98, 126-129, 131-134, 137-138, 141-142, 149-153, 187-254'' is encountered, validation succeeds (none of the rules below apply). This is true even if later bytes in the tapscript would fail to decode otherwise. These opcodes are renamed to OP_SUCCESS80, ..., OP_SUCCESS254, and collectively known as OP_SUCCESSx'''OP_SUCCESSx''' OP_SUCCESSx is a mechanism to upgrade the Script system. Using an OP_SUCCESSx before its meaning is defined by a softfork is insecure and leads to fund loss. The inclusion of OP_SUCCESSx in a script will pass it unconditionally. It precedes any script execution rules to avoid the difficulties in specifying various edge cases, for example: OP_SUCCESSx being the 202nd opcode, OP_SUCCESSx after too many signature opcodes, or even scripts with conditionals lacking OP_ENDIF. The mere existence of an OP_SUCCESSx anywhere in the script will guarantee a pass for all such cases. OP_SUCCESSx are similar to the OP_RETURN in very early bitcoin versions (v0.1 up to and including v0.3.5). The original OP_RETURN terminates script execution immediately, and return pass or fail based on the top stack element at the moment of termination. This was one of a major design flaws in the original bitcoin protocol as it permitted unconditional third party theft by placing an OP_RETURN in scriptSig. This is not a concern in the present proposal since it is not possible for a third party to inject an OP_SUCCESSx to the validation process, as the OP_SUCCESSx is part of the script (and thus committed to be the taproot output), implying the consent of the coin owner. OP_SUCCESSx can be used for a variety of upgrade possibilities: +* An OP_SUCCESSx could be turned into a functional opcode through a softfork. Unlike OP_NOPx-derived opcodes which only have read-only access to the stack, OP_SUCCESSx may also write to the stack. Any rule changes to an OP_SUCCESSx-containing script may only turn a valid script into an invalid one, and this is always achievable with softforks. +* Since OP_SUCCESSx precedes size check of initial stack and push opcodes, an OP_SUCCESSx-derived opcode requiring stack elements bigger than 520 bytes may uplift the limit in a softfork. +* OP_SUCCESSx may also redefine the behavior of existing opcodes so they could work together with the new opcode. For example, if an OP_SUCCESSx-derived opcode works with 64-bit integers, it may also allow the existing arithmetic opcodes in the ''same script'' to do the same. +* Given that OP_SUCCESSx even causes potentially unparseable scripts to pass, it can be used to introduce multi-byte opcodes, or even a completely new scripting language when prefixed with a specific OP_SUCCESSx opcode.. +## If any push opcode fails to decode because it would extend past the end of the tapscript, fail. +# If the size of any element in the '''initial stack''' as defined in bip-taproot (i.e., the witness stack after removing both the optional annex and the two last stack elements after that) is bigger than 520 bytes, fail. +# If the tapscript is bigger than 10000 bytes, fail. +# The tapscript is executed according to the rules in the following section, with the initial stack as input. +## If execution fails for any reason (including the 201 non-push opcode limit), fail. +## If the execution results in anything but exactly one element on the stack which evaluates to true with CastToBool(), fail. +# If this step is reached without encountering a failure, validation succeeds. + +===Script execution=== + +The execution rules for tapscript are based on those for P2WSH according to BIP141, including the OP_CHECKLOCKTIMEVERIFY and OP_CHECKSEQUENCEVERIFY opcodes defined in BIP65 and BIP112, but with the following modifications: +* '''Disabled script opcodes''' The following script opcodes are disabled in tapscript: OP_CHECKMULTISIG and OP_CHECKMULTISIGVERIFY. The disabled opcodes behave in the same way as OP_RETURN, by failing and terminating the script immediately when executed, and being ignored when found in unexecuted branch. While being ignored, they are still counted towards the 201 non-push opcodes limit. +* '''Consensus-enforced MINIMALIF''' The MINIMALIF rules, which are only a standardness rule in P2WSH, are consensus enforced in tapscript. This means that the input argument to the OP_IF and OP_NOTIF opcodes must be either exactly 0 (the empty vector) or exactly 1 (the one-byte vector with value 1)'''Why make MINIMALIF consensus?''' This makes it considerably easier to write non-malleable scripts that take branch information from the stack.. +* '''OP_SUCCESSx opcodes''' As listed above, some opcodes are renamed to OP_SUCCESSx, and make the script unconditionally valid. +* '''Signature opcodes'''. The OP_CHECKSIG and OP_CHECKSIGVERIFY are modified to operate on Schnorr signatures (see bip-schnorr) instead of ECDSA, and a new opcode OP_CHECKSIGADD is added. +** The opcode 186 (0xba) is named as OP_CHECKSIGADD. '''OP_CHECKSIGADD''' This opcode is added to compensate for the loss of OP_CHECKMULTISIG-like opcodes, which are incompatible with batch verification. OP_CHECKSIGADD is functionally equivalent to OP_ROT OP_SWAP OP_CHECKSIG OP_ADD, but is only counted as one opcode towards the 201 non-push opcodes limit. All CScriptNum-related behaviours of OP_ADD are also applicable to OP_CHECKSIGADD.'''Comparison of CHECKMULTISIG and CHECKSIG''' A CHECKMULTISIG script m ... n CHECKMULTISIG with witness 0 ... can be rewritten as script CHECKSIG ... CHECKSIGADD m NUMEQUAL with witness ... . Every witness element w_i is either a signature corresponding to the public key with the same index or an empty vector. A similar CHECKMULTISIGVERIFY script can be translated to bip-tapscript by replacing NUMEQUAL with NUMEQUALVERIFY. Alternatively, an m-of-n multisig policy can be implemented by splitting the script into several leaves of the Merkle tree, each implementing an m-of-m policy using CHECKSIGVERIFY ... CHECKSIGVERIFY CHECKSIG. If the setting allows the participants to interactively collaborate while signing, multisig policies can be realized with [https://eprint.iacr.org/2018/068 MuSig] for m-of-m and with [http://cacr.uwaterloo.ca/techreports/2001/corr2001-13.ps threshold signatures] using verifiable secret sharing for m-of-n. + +===Rules for signature opcodes=== + +The following rules apply to OP_CHECKSIG, OP_CHECKSIGVERIFY, and OP_CHECKSIGADD. + +* For OP_CHECKSIGVERIFY and OP_CHECKSIG, the public key (top element) and a signature (second to top element) are popped from the stack. +** If fewer than 2 elements are on the stack, the script MUST fail and terminate immediately. +* For OP_CHECKSIGADD, the public key (top element), a CScriptNum n (second to top element), and a signature (third to top element) are popped from the stack. +** If fewer than 3 elements are on the stack, the script MUST fail and terminate immediately. +** If n is larger than 4 bytes, the script MUST fail and terminate immediately. +* If the public key size is zero, the script MUST fail and terminate immediately. +* If the first byte of the public key is 0x04, 0x06, or 0x07, the script MUST fail and terminate immediately regardless of the public key size. +* If the first byte of the public key is 0x02 or 0x03, it is considered to be a public key as described in bip-schnorr: +** If the public key is not 33 bytes, the script MUST fail and terminate immediately. +** If the signature is not the empty vector, the signature is validated according to the bip-taproot signing validation rules against the public key and the tapscript transaction digest (to be defined hereinafter) as message. Validation failure MUST cause the script to fail and terminate immediately. +* If the first byte of the public key is not 0x02, 0x03, 0x04, 0x06, or 0x07, the public key is of an ''unknown public key type'''''Unknown public key types''' allow adding new signature validation rules through softforks. A softfork could add actual signature validation which either passes or makes the script fail and terminate immediately. This way, new SIGHASH modes can be added, as well as [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-December/016549.html NOINPUT-tagged public keys] and a public key constant which is replaced by the taproot internal key for signature validation. and no actual signature verification is applied. During script execution of signature opcodes they behave exactly as known public key types except that signature validation is considered to be successful. +* If the script did not fail and terminate before this step, regardless of the public key type: +** If the signature is the empty vector: +*** For OP_CHECKSIGVERIFY, the script MUST fail and terminate immediately. +*** For OP_CHECKSIG, an empty vector is pushed onto the stack, and execution continues with the next opcode. +*** For OP_CHECKSIGADD, a CScriptNum with value n is pushed onto the stack, and execution continues with the next opcode. +** If the signature is not the empty vector, the sigops_passed counter is incremented (see further) +*** For OP_CHECKSIGVERIFY, execution continues without any further changes to the stack. +*** For OP_CHECKSIG, a 1-byte value 0x01 is pushed onto the stack. +*** For OP_CHECKSIGADD, a CScriptNum with value of n + 1 is pushed onto the stack. + +These opcodes count toward the 201 non-push opcodes limit. + +===Transaction digest=== + +As the message for signature opcodes signature verification, transaction digest has the same definition as in bip-taproot, except the following: + +The one-byte spend_type has a different value, specificially at bit-2: +* Bit-0 is set if the scriptPubKey being spent is P2SH (opposed to "native segwit"). +* Bit-1 is set if an annex is present (the original witness stack has at least two witness elements, and the first byte of the last element is 0x50). +* Bit-2 is set. +* The other bits are unset. + +As additional pieces of data, added at the end of the input to the ''hashTapSighash'' function: +* tapleaf_hash (32): the tapleaf hash as defined in bip-taproot +* key_version (1): a constant value 0x02 representing the current version of public keys in the tapscript signature opcode execution. +* codeseparator_position (2): the opcode position of the last executed OP_CODESEPARATOR before the currently executed signature opcode, with the value in little endian (or 0xffff if none executed). The first opcode in a script has a position of 0. A multi-byte push opcode is counted as one opcode, regardless of the size of data being pushed. + +The total number of bytes hashed is at most ''244'''''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''212 - is_anyonecanpay * 50 - is_none * 32 - is_p2sh_spending * 12 + has_annex * 32''.. + +In summary, the semantics of the BIP143 sighash types remain unchanged, except the following: +# The exceptions mentioned in bip-taproot. +# The digest commits to taproot-specific data key_version.'''Why does the transaction digest commit to the key_version?''' This is for future extensions that define unknown public key types, making sure signatures can't be moved from one key type to another. This value is intended to be set equal to the first byte of the public key, after masking out flags like the oddness of the Y coordinate. +# The digest commits to the executed script through the tapleaf_hash which includes the leaf version and script instead of scriptCode. This implies that this commitment is unaffected by OP_CODESEPARATOR. +# The digest commits to the opcode position of the last executed OP_CODESEPARATOR.'''Why does the transaction digest commit to the position of the last executed OP_CODESEPARATOR?''' This allows continuing to use OP_CODESEPARATOR to sign the executed path of the script. Because the codeseparator_position is the last input to the digest, the SHA256 midstate can be efficiently cached for multiple OP_CODESEPARATORs in a single script. In contrast, the BIP143 handling of OP_CODESEPARATOR is to commit to the executed script only from the last executed OP_CODESEPARATOR onwards which requires unnecessary rehashing of the script. It should be noted that the one known OP_CODESEPARATOR use case of saving a second public key push in a script by sharing the first one between two code branches can be most likely expressed even cheaper by moving each branch into a separate taproot leaf. + +===Signature opcodes limitation=== + +In addition to the 201 non-push opcodes limit, the use of signature opcodes is subject to further limitations. + +* input_witness_weight is defined as the size of the serialized input witness associated to a particular transaction input. As defined in BIP141, a serialized input witness includes CCompactSize tags indicating the number of elements and size of each element, and contents of each element. input_witness_weight is the total size of the said CCompactSize tags and element contents. +* sigops_passed is defined as the total number of successfully executed signature opcodes, which have non-zero signature size and do not fail and terminate the script. For the avoidance of doubt, passing signature opcodes with unknown type public key and non-zero size signature are also counted towards sigops_passed. +* If 50 * (sigops_passed - 1) is greater than input_witness_weight, the script MUST fail and terminate immediately. + +This rule limits worst-case validation costs in tapscript similar to the ''sigops limit'' that only applies to legacy and P2WSH scripts'''The tapscript sigop limit''' The signature opcode limit protects against scripts which are slow to verify due to excessively many signature operations. In tapscript the number of signature opcodes does not count towards the BIP141 or legacy sigop limit. The old sigop limit makes transaction selection in block construction unnecessarily difficult because it is a second constraint in addition to weight. Instead, the number of tapscript signature opcodes is limited by witness weight. Additionally, the limit applies to the transaction input instead of the block and only actually executed signature opcodes are counted. Tapscript execution allows one signature opcode per 50 witness weight units plus one free signature opcode. The tapscript signature opcode limit allows to add new signature opcodes like CHECKSIGFROMSTACK to count towards the limit through a soft fork. Even if in the future new opcodes are introduced which change normal script cost there is need to stuff the witness with meaningless data. In that case the taproot annex can be used to add weight to the witness without increasing the actual witness size. +'''Parameter choice of the sigop limit''' Regular witnesses are unaffected by the limit as their weight is composed of public key and (SIGHASH_ALL) signature pairs with ''34 + 65'' weight units each (which includes a 1 weight unit CCompactSize tag). This is also the case if public keys are reused in the script because a signature's weight alone is 65 or 66 weight units. However, the limit increases the fees of abnormal scripts with duplicate signatures (and public keys) by requiring additional weight. The weight per sigop factor 50 corresponds to the ratio of BIP141 block limits: 4 mega weight units divided by 80,000 sigops. The "free" signature opcode permitted by the limit exists to account for the weight of the non-witness parts of the transaction input.. + +==Rationale== + + + +==Examples== + +==Acknowledgements== + +This document is the result of many discussions and contains contributions by Jonas Nick, Anthony Towns, and others. + -- cgit v1.2.3 From e9ea1710ef735c98a6089f869f84e77fb618b547 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Mon, 14 Jan 2019 15:54:24 +0000 Subject: Clarify what 'reduced' means in tests and use word 'message' instead of 'message hash' --- bip-schnorr/test-vectors.csv | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bip-schnorr/test-vectors.csv b/bip-schnorr/test-vectors.csv index 9b89a7b..a4218f7 100644 --- a/bip-schnorr/test-vectors.csv +++ b/bip-schnorr/test-vectors.csv @@ -4,10 +4,10 @@ index,secret key,public key,message,signature,verification result,comment 3,C90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B14E5C7,03FAC2114C2FBB091527EB7C64ECB11F8021CB45E8E7809D3C0938E4B8C0E5F84B,5E2D58D8B3BCDF1ABADEC7829054F90DDA9805AAB56C77333024B9D0A508B75C,00DA9B08172A9B6F0466A2DEFD817F2D7AB437E0D253CB5395A963866B3574BE00880371D01766935B92D2AB4CD5C8A2A5837EC57FED7660773A05F0DE142380,TRUE, 4,,03DEFDEA4CDB677750A420FEE807EACF21EB9898AE79B9768766E4FAA04A2D4A34,4DF3C3F68FCC83B27E9D42C90431A72499F17875C81A599B566C9889B9696703,00000000000000000000003B78CE563F89A0ED9414F5AA28AD0D96D6795F9C6302A8DC32E64E86A333F20EF56EAC9BA30B7246D6D25E22ADB8C6BE1AEB08D49D,TRUE, 5,,031B84C5567B126440995D3ED5AABA0565D71E1834604819FF9C17F5E9D5DD078F,0000000000000000000000000000000000000000000000000000000000000000,52818579ACA59767E3291D91B76B637BEF062083284992F2D95F564CA6CB4E3530B1DA849C8E8304ADC0CFE870660334B3CFC18E825EF1DB34CFAE3DFC5D8187,TRUE,"test fails if jacobi symbol of x(R) instead of y(R) is used" -6,,03FAC2114C2FBB091527EB7C64ECB11F8021CB45E8E7809D3C0938E4B8C0E5F84B,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,570DD4CA83D4E6317B8EE6BAE83467A1BF419D0767122DE409394414B05080DCE9EE5F237CBD108EABAE1E37759AE47F8E4203DA3532EB28DB860F33D62D49BD,TRUE,"test fails if msg is reduced" +6,,03FAC2114C2FBB091527EB7C64ECB11F8021CB45E8E7809D3C0938E4B8C0E5F84B,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,570DD4CA83D4E6317B8EE6BAE83467A1BF419D0767122DE409394414B05080DCE9EE5F237CBD108EABAE1E37759AE47F8E4203DA3532EB28DB860F33D62D49BD,TRUE,"test fails if msg is reduced modulo p or n" 7,,03EEFDEA4CDB677750A420FEE807EACF21EB9898AE79B9768766E4FAA04A2D4A34,4DF3C3F68FCC83B27E9D42C90431A72499F17875C81A599B566C9889B9696703,00000000000000000000003B78CE563F89A0ED9414F5AA28AD0D96D6795F9C6302A8DC32E64E86A333F20EF56EAC9BA30B7246D6D25E22ADB8C6BE1AEB08D49D,FALSE,"public key not on the curve" 8,,02DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,2A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1DFA16AEE06609280A19B67A24E1977E4697712B5FD2943914ECD5F730901B4AB7,FALSE,"incorrect R residuosity" -9,,03FAC2114C2FBB091527EB7C64ECB11F8021CB45E8E7809D3C0938E4B8C0E5F84B,5E2D58D8B3BCDF1ABADEC7829054F90DDA9805AAB56C77333024B9D0A508B75C, 00DA9B08172A9B6F0466A2DEFD817F2D7AB437E0D253CB5395A963866B3574BED092F9D860F1776A1F7412AD8A1EB50DACCC222BC8C0E26B2056DF2F273EFDEC,FALSE,"negated message hash" +9,,03FAC2114C2FBB091527EB7C64ECB11F8021CB45E8E7809D3C0938E4B8C0E5F84B,5E2D58D8B3BCDF1ABADEC7829054F90DDA9805AAB56C77333024B9D0A508B75C, 00DA9B08172A9B6F0466A2DEFD817F2D7AB437E0D253CB5395A963866B3574BED092F9D860F1776A1F7412AD8A1EB50DACCC222BC8C0E26B2056DF2F273EFDEC,FALSE,"negated message" 10,,0279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798,0000000000000000000000000000000000000000000000000000000000000000,787A848E71043D280C50470E8E1532B2DD5D20EE912A45DBDD2BD1DFBF187EF68FCE5677CE7A623CB20011225797CE7A8DE1DC6CCD4F754A47DA6C600E59543C,FALSE,"negated s value" 11,,03DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,2A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1D1E51A22CCEC35599B8F266912281F8365FFC2D035A230434A1A64DC59F7013FD,FALSE,"negated public key" 12,,02DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,00000000000000000000000000000000000000000000000000000000000000009E9D01AF988B5CEDCE47221BFA9B222721F3FA408915444A4B489021DB55775F,FALSE,"sG - eP is infinite. Test fails in single verification if jacobi(y(inf)) is defined as 1 and x(inf) as 0" -- cgit v1.2.3 From d194620af92f085ed67b9d1b0c0cad300350268f Mon Sep 17 00:00:00 2001 From: Mark B Lundeberg <36528214+markblundeberg@users.noreply.github.com> Date: Mon, 6 May 2019 13:13:20 -0700 Subject: remove duplicate warning Though perhaps, the emphasis is warranted given its importance. :-) --- bip-schnorr.mediawiki | 3 --- 1 file changed, 3 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index d4e4ff1..f3df71e 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -161,9 +161,6 @@ To sign ''m'' for public key ''dG'': '''Above deterministic derivation of ''R'' is designed specifically for this signing algorithm and may not be secure when used in other signature schemes.''' For example, using the same derivation in the MuSig multi-signature scheme leaks the secret key (see the [https://eprint.iacr.org/2018/068 MuSig paper] for details). -'''Above deterministic derivation of ''R'' is designed specifically for this signing algorithm and may not be secure when used in other signature schemes.''' -For example, using the same derivation in the MuSig multi-signature scheme leaks the secret key (see the [https://eprint.iacr.org/2018/068 MuSig paper] for details). - Note that this is not a ''unique signature'' scheme: while this algorithm will always produce the same signature for a given message and public key, ''k'' (and hence ''R'') may be generated in other ways (such as by a CSPRNG) producing a different, but still valid, signature. === Optimizations === -- cgit v1.2.3 From 0c49346c874212014af8338f1d433020199ff439 Mon Sep 17 00:00:00 2001 From: Dmitry Petukhov Date: Fri, 10 May 2019 03:09:54 +0500 Subject: taproot_output_script: first returned byte should be OP_1 (0x51) If we look at def IsPayToTaproot(script): return len(script) == 35 and script[0] == OP_1 and script[1] == 33 and script[2] >= 0 and script[2] <= 1 First byte is is checked for OP_1. OP_1 is 0x51 But the example code in this BIP returns `bytes([0x01, 0x21, output_pubkey[0] & 1]) + output_pubkey[1:]` First byte 0x01, but it should be 0x51 --- bip-taproot.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 2e8b43b..0b6c04a 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -203,7 +203,7 @@ def taproot_output_script(internal_pubkey, script_tree): t = tagged_hash("TapTweak", internal_pubkey.get_bytes() + h) assert int.from_bytes(t, 'big') < SECP256K1_ORDER output_pubkey = internal_pubkey.tweak_add(t).get_bytes() - return bytes([0x01, 0x21, output_pubkey[0] & 1]) + output_pubkey[1:] + return bytes([0x51, 0x21, output_pubkey[0] & 1]) + output_pubkey[1:] The function taproot_output_script returns a byte array with the scriptPubKey. It can be P2SH wrapped if desired (see BIP141). -- cgit v1.2.3 From 04b844540e6405e5fd818b273a65c02c96dd5825 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Fri, 10 May 2019 13:57:12 +0000 Subject: Clarify diagram --- bip-taproot.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 0b6c04a..f100e6e 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -208,7 +208,7 @@ def taproot_output_script(internal_pubkey, script_tree): The function taproot_output_script returns a byte array with the scriptPubKey. It can be P2SH wrapped if desired (see BIP141). -[[File:bip-taproot/tree.png|frame|This diagram shows the hashing structure to obtain the tweak from an internal key ''P'' and a Merkle tree consisting of 3 script leaves.]] +[[File:bip-taproot/tree.png|frame|This diagram shows the hashing structure to obtain the tweak from an internal key ''P'' and a Merkle tree consisting of 5 script leaves. ''A'', ''B'', ''C'' and ''E'' are ''TapLeaf'' hashes similar to ''D'' and ''AB'' is a ''TapBranch'' hash. Note that when ''CDE'' is computed ''E'' is hashed first because ''E'' is less than ''CD''.]] '''Spending using the internal key''' A Taproot output can be spent with the private key corresponding to the internal_pubkey. To do so, a witness stack consisting of a single element, a bip-schnorr signature on the signature hash as defined above, with the private key tweaked by the same t in the above snippet. See the code below: -- cgit v1.2.3 From 1faf7053885aaa6890e7d59ce90ede9b43ab0421 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Sat, 6 Jul 2019 14:11:52 +0000 Subject: Fix point_from_bytes in bip-schnorr reference implementation --- bip-schnorr/reference.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-schnorr/reference.py b/bip-schnorr/reference.py index 48a36a6..d3efb52 100644 --- a/bip-schnorr/reference.py +++ b/bip-schnorr/reference.py @@ -34,7 +34,7 @@ def bytes_from_point(P): return (b'\x03' if P[1] & 1 else b'\x02') + bytes_from_int(P[0]) def point_from_bytes(b): - if b[0] in [b'\x02', b'\x03']: + if b[0:1] in [b'\x02', b'\x03']: odd = b[0] - 0x02 else: return None -- cgit v1.2.3 From ed01c1a7761570db6dd788a3d012d10fe7dbf93a Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Sat, 6 Jul 2019 16:32:41 +0000 Subject: Switch to 32 byte public keys in bip-schnorr --- bip-schnorr.mediawiki | 53 +++++++---- bip-schnorr/reference.py | 44 +++++---- bip-schnorr/test-vectors.csv | 30 +++--- bip-schnorr/test-vectors.py | 215 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 288 insertions(+), 54 deletions(-) create mode 100644 bip-schnorr/test-vectors.py diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index f3df71e..fa8faa5 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -35,6 +35,7 @@ propose a new standard, a number of improvements not specific to Schnorr signatu made: * '''Signature encoding''': Instead of [https://en.wikipedia.org/wiki/X.690#DER_encoding DER]-encoding for signatures (which are variable size, and up to 72 bytes), we can use a simple fixed 64-byte format. +* '''Public key encoding''': Instead of ''compressed'' 33-byte encoding of elliptic curve points which are common in Bitcoin, public keys in this proposal are encoded as 32 bytes. * '''Batch verification''': The specific formulation of ECDSA signatures that is standardized cannot be verified more efficiently in batch compared to individually, unless additional witness data is added. Changing the signature scheme offers an opportunity to avoid this. [[File:bip-schnorr/speedup-batch.png|frame|This graph shows the ratio between the time it takes to verify ''n'' signatures individually and to verify a batch of ''n'' signatures. This ratio goes up logarithmically with the number of signatures, or in other words: the total time to verify ''n'' signatures grows with ''O(n / log n)''.]] @@ -57,24 +58,35 @@ We choose the ''R''-option to support batch verification. '''Key prefixing''' When using the verification rule above directly, it is possible for a third party to convert a signature ''(R,s)'' for key ''P'' into a signature ''(R,s + aH(R || m))'' for key ''P + aG'' and the same message, for any integer ''a''. This is not a concern for Bitcoin currently, as all signature hashes indirectly commit to the public keys. However, this may change with proposals such as SIGHASH_NOINPUT ([https://github.com/bitcoin/bips/blob/master/bip-0118.mediawiki BIP 118]), or when the signature scheme is used for other purposes—especially in combination with schemes like [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki BIP32]'s unhardened derivation. To combat this, we choose ''key prefixed''A limitation of committing to the public key (rather than to a short hash of it, or not at all) is that it removes the ability for public key recovery or verifying signatures against a short public key hash. These constructions are generally incompatible with batch verification. Schnorr signatures; changing the equation to ''sG = R + H(R || P || m)P''. -'''Encoding the sign of R''' As we chose the ''R''-option above, we're required to encode the point ''R'' into the signature. Several possibilities exist: +'''Encoding the sign of P and the sign of R''' There exist several possibilities for encoding the sign of the public key point: +# Encoding the full X and Y coordinate of P, resulting in a 64-byte public key. +# Encoding the full X coordinate, but only whether Y is even or odd (like compressed public keys). This would result in 33-byte public keys. +# Encoding only the X coordinate, resulting in 32-byte public keys. + +As we chose the ''R''-option above, we're required to encode the point ''R'' into the signature. The possibilities are similar to the encoding of ''P'': # Encoding the full X and Y coordinate of R, resulting in a 96-byte signature. # Encoding the full X coordinate, but only whether Y is even or odd (like compressed public keys). This would result in 65-byte signatures. # Encoding only the X coordinate, leaving us with 64-byte signature. -Using the first option would be slightly more efficient for verification (around 5%), but we prioritize compactness, and therefore choose option 3. +Using the first option for both ''P'' and ''R'' would be slightly more efficient for verification (around 5%), but we prioritize compactness, and therefore choose option 3. -'''Implicit Y coordinate''' In order to support batch verification, the Y coordinate of ''R'' cannot be ambiguous (every valid X coordinate has two possible Y coordinates). We have a choice between several options for symmetry breaking: +'''Implicit Y coordinates''' In order to support batch verification, the Y coordinate of ''P'' and of ''R'' cannot be ambiguous (every valid X coordinate has two possible Y coordinates). We have a choice between several options for symmetry breaking: # Implicitly choosing the Y coordinate that is in the lower half. # Implicitly choosing the Y coordinate that is evenSince ''p'' is odd, negation modulo ''p'' will map even numbers to odd numbers and the other way around. This means that for a valid X coordinate, one of the corresponding Y coordinates will be even, and the other will be odd.. # Implicitly choosing the Y coordinate that is a quadratic residue (has a square root modulo the field size)A product of two numbers is a quadratic residue when either both or none of the factors are quadratic residues. As ''-1'' is not a quadratic residue, and the two Y coordinates corresponding to a given X coordinate are each other's negation, this means exactly one of the two must be a quadratic residue.. -The third option is slower at signing time but a bit faster to verify, as the quadratic residue of the Y coordinate can be computed directly for points represented in +In the case of ''R'' the third option is slower at signing time but a bit faster to verify, as the quadratic residue of the Y coordinate can be computed directly for points represented in [https://en.wikibooks.org/wiki/Cryptography/Prime_Curve/Jacobian_Coordinates Jacobian coordinates] (a common optimization to avoid modular inverses for elliptic curve operations). The two other options require a possibly expensive conversion to affine coordinates first. This would even be the case if the sign or oddness were explicitly coded (option 2 in the previous design choice). We therefore choose option 3. -'''Final scheme''' As a result, our final scheme ends up using signatures ''(r,s)'' where ''r'' is the X coordinate of a point ''R'' on the curve whose Y coordinate is a quadratic residue, and which satisfies ''sG = R + H(r || P || m)P''. +For ''P'' the speed of signing and verification is not significantly different between any of the three options because affine coordinates of the point have to computed anyway. We therefore choose the same option as for ''R''. The signing algorithm ensures that the signature is valid under the correct public key by negating the secret key if necessary. + +It is important to not mix up the 32 byte public key format and other existing public key formats. Concretely, a verifier should only accept 32 byte public keys and not, for example, convert a 33 byte public key by throwing away the first byte. Otherwise, two public keys would be valid for a single signature which can result in subtle malleability issues. + +Implicit Y coordinates are not a reduction in security when expressed as the number of elliptic curve operations an attacker is expected to perform to compute the secret key. An attacker can normalize any given public key to a point whose Y coordinate is a quadratic residue by negating the point if necessary. This is just a subtraction of field elements and not an elliptic curve operation. + +'''Final scheme''' As a result, our final scheme ends up using public keys ''p'' where ''p'' is the X coordinate of a point ''P'' on the curve whose Y coordinate is a quadratic residue and signatures ''(r,s)'' where ''r'' is the X coordinate of a point ''R'' whose Y coordinate is a quadratic residue. The signature satisfies ''sG = R + H(r || p || m)P''. === Specification === @@ -94,26 +106,27 @@ The following convention is used, with constants as defined for secp256k1: ** ''||'' refers to byte array concatenation. ** The function ''x[i:j]'', where ''x'' is a byte array, returns a ''(j - i)''-byte array with a copy of the ''i''-th byte (inclusive) to the ''j''-th byte (exclusive) of ''x''. ** The function ''bytes(x)'', where ''x'' is an integer, returns the 32-byte encoding of ''x'', most significant byte first. -** The function ''bytes(P)'', where ''P'' is a point, returns ''bytes(0x02 + (y(P) & 1)) || bytes(x(P))''This matches the ''compressed'' encoding for elliptic curve points used in Bitcoin already, following section 2.3.3 of the [http://www.secg.org/sec1-v2.pdf SEC 1] standard.. +** The function ''bytes(P)'', where ''P'' is a point, returns ''bytes(x(P))'. ** The function ''int(x)'', where ''x'' is a 32-byte array, returns the 256-bit unsigned integer whose most significant byte encoding is ''x''. ** The function ''lift_x(x)'', where ''x'' is an integer in range ''0..p-1'', returns the point ''P'' for which ''x(P) = x'' and ''y(P)'' is a quadratic residue modulo ''p'', or fails if no such point existsGiven an candidate X coordinate ''x'' in the range ''0..p-1'', there exist either exactly two or exactly zero valid Y coordinates. If no valid Y coordinate exists, then ''x'' is not a valid X coordinate either, i.e., no point ''P'' exists for which ''x(P) = x''. Given a candidate ''x'', the valid Y coordinates are the square roots of ''c = x3 + 7 mod p'' and they can be computed as ''y = ±c(p+1)/4 mod p'' (see [https://en.wikipedia.org/wiki/Quadratic_residue#Prime_or_prime_power_modulus Quadratic residue]) if they exist, which can be checked by squaring and comparing with ''c''. Due to [https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion] it then holds that ''c(p-1)/2 = 1 mod p''. The same criterion applied to ''y'' results in ''y(p-1)/2 mod p = ±c((p+1)/4)((p-1)/2) mod p = ±1 mod p''. Therefore ''y = +c(p+1)/4 mod p'' is a quadratic residue and ''-y mod p'' is not.. The function ''lift_x(x)'' is equivalent to the following pseudocode: *** Let ''y = c(p+1)/4 mod p''. *** Fail if ''c ≠ y2 mod p''. *** Return ''(r, y)''. -** The function ''point(x)'', where ''x'' is a 33-byte array, returns the point ''P'' for which ''x(P) = int(x[1:33])'' and ''y(P) & 1 = int(x[0:1]) - 0x02)'', or fails if no such point exists. The function ''point(x)'' is equivalent to the following pseudocode: -*** Fail if (''x[0:1] ≠ 0x02'' and ''x[0:1] ≠ 0x03''). -*** Set flag ''odd'' if ''x[0:1] = 0x03''. -*** Let ''(r, y) = lift_x(x)''; fail if ''lift_x(x)'' fails. -*** If (flag ''odd'' is set and ''y'' is an even integer) or (flag ''odd'' is not set and ''y'' is an odd integer): -**** Let ''y = p - y''. -*** Return ''(r, y)''. +** The function ''point(x)'', where ''x'' is a 32-byte array, returns the point ''P = lift_x(int(x))''. ** The function ''hash(x)'', where ''x'' is a byte array, returns the 32-byte SHA256 hash of ''x''. ** The function ''jacobi(x)'', where ''x'' is an integer, returns the [https://en.wikipedia.org/wiki/Jacobi_symbol Jacobi symbol] of ''x / p''. It is equal to ''x(p-1)/2 mod p'' ([https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion])For points ''P'' on the secp256k1 curve it holds that ''jacobi(y(P)) ≠ 0''.. +=== Public Key Generation === + +Input: +* The secret key ''d'': an integer in the range ''1..n-1'' chosen uniformly at random. + +The public key corresponding to secret key ''d'' is ''bytes(dG)''. + ==== Verification ==== Input: -* The public key ''pk'': a 33-byte array +* The public key ''pk'': a 32-byte array * The message ''m'': a 32-byte array * A signature ''sig'': a 64-byte array @@ -130,7 +143,7 @@ The signature is valid if and only if the algorithm below does not fail. Input: * The number ''u'' of signatures -* The public keys ''pk1..u'': ''u'' 33-byte arrays +* The public keys ''pk1..u'': ''u'' 32-byte arrays * The messages ''m1..u'': ''u'' 32-byte arrays * The signatures ''sig1..u'': ''u'' 64-byte arrays @@ -147,16 +160,18 @@ All provided signatures are valid with overwhelming probability if and only if t ==== Signing ==== Input: -* The secret key ''d'': an integer in the range ''1..n-1''. +* The secret key ''d' '': an integer in the range ''1..n-1'' chosen uniformly at random. * The message ''m'': a 32-byte array -To sign ''m'' for public key ''dG'': +To sign ''m'' for public key ''bytes(dG)'': +* Let ''P = dG'' +* Let ''d = d' '' if ''jacobi(y(P)) = 1'', otherwise let ''d = n - d' ''. * Let ''k' = int(hash(bytes(d) || m)) mod n''Note that in general, taking the output of a hash function modulo the curve order will produce an unacceptably biased result. However, for the secp256k1 curve, the order is sufficiently close to ''2256'' that this bias is not observable (''1 - n / 2256'' is around ''1.27 * 2-128'').. * Fail if ''k' = 0''. * Let ''R = k'G''. * Let ''k = k' '' if ''jacobi(y(R)) = 1'', otherwise let ''k = n - k' ''. -* Let ''e = int(hash(bytes(x(R)) || bytes(dG) || m)) mod n''. -* The signature is ''bytes(x(R)) || bytes((k + ed) mod n)''. +* Let ''e = int(hash(bytes(R) || bytes(P) || m)) mod n''. +* The signature is ''bytes(R) || bytes((k + ed) mod n)''. '''Above deterministic derivation of ''R'' is designed specifically for this signing algorithm and may not be secure when used in other signature schemes.''' For example, using the same derivation in the MuSig multi-signature scheme leaks the secret key (see the [https://eprint.iacr.org/2018/068 MuSig paper] for details). diff --git a/bip-schnorr/reference.py b/bip-schnorr/reference.py index d3efb52..f89b3c4 100644 --- a/bip-schnorr/reference.py +++ b/bip-schnorr/reference.py @@ -31,19 +31,14 @@ def bytes_from_int(x): return x.to_bytes(32, byteorder="big") def bytes_from_point(P): - return (b'\x03' if P[1] & 1 else b'\x02') + bytes_from_int(P[0]) + return bytes_from_int(P[0]) def point_from_bytes(b): - if b[0:1] in [b'\x02', b'\x03']: - odd = b[0] - 0x02 - else: - return None - x = int_from_bytes(b[1:33]) + x = int_from_bytes(b) y_sq = (pow(x, 3, p) + 7) % p - y0 = pow(y_sq, (p + 1) // 4, p) - if pow(y0, 2, p) != y_sq: + y = pow(y_sq, (p + 1) // 4, p) + if pow(y, 2, p) != y_sq: return None - y = p - y0 if y0 & 1 != odd else y0 return [x, y] def int_from_bytes(b): @@ -55,24 +50,30 @@ def hash_sha256(b): def jacobi(x): return pow(x, (p - 1) // 2, p) -def schnorr_sign(msg, seckey): +def pubkey_gen(seckey): + P = point_mul(G, seckey) + return bytes_from_point(P) + +def schnorr_sign(msg, seckey0): if len(msg) != 32: raise ValueError('The message must be a 32-byte array.') - if not (1 <= seckey <= n - 1): + if not (1 <= seckey0 <= n - 1): raise ValueError('The secret key must be an integer in the range 1..n-1.') + P = point_mul(G, seckey0) + seckey = seckey0 if (jacobi(P[1]) == 1) else n - seckey0 k0 = int_from_bytes(hash_sha256(bytes_from_int(seckey) + msg)) % n if k0 == 0: raise RuntimeError('Failure. This happens only with negligible probability.') R = point_mul(G, k0) k = n - k0 if (jacobi(R[1]) != 1) else k0 - e = int_from_bytes(hash_sha256(bytes_from_int(R[0]) + bytes_from_point(point_mul(G, seckey)) + msg)) % n - return bytes_from_int(R[0]) + bytes_from_int((k + e * seckey) % n) + e = int_from_bytes(hash_sha256(bytes_from_point(R) + bytes_from_point(P) + msg)) % n + return bytes_from_point(R) + bytes_from_int((k + e * seckey) % n) def schnorr_verify(msg, pubkey, sig): if len(msg) != 32: raise ValueError('The message must be a 32-byte array.') - if len(pubkey) != 33: - raise ValueError('The public key must be a 33-byte array.') + if len(pubkey) != 32: + raise ValueError('The public key must be a 32-byte array.') if len(sig) != 64: raise ValueError('The signature must be a 64-byte array.') P = point_from_bytes(pubkey) @@ -82,7 +83,7 @@ def schnorr_verify(msg, pubkey, sig): s = int_from_bytes(sig[32:64]) if (r >= p or s >= n): return False - e = int_from_bytes(hash_sha256(sig[0:32] + bytes_from_point(P) + msg)) % n + e = int_from_bytes(hash_sha256(sig[0:32] + pubkey + msg)) % n R = point_add(point_mul(G, s), point_mul(P, n - e)) if R is None or jacobi(R[1]) != 1 or R[0] != r: return False @@ -107,20 +108,25 @@ def test_vectors(): print('\nTest vector #%-3i: ' % int(index)) if seckey != '': seckey = int(seckey, 16) + pubkey_actual = pubkey_gen(seckey) + if pubkey != pubkey_actual: + print(' * Failed key generation.') + print(' Expected key:', pubkey.hex().upper()) + print(' Actual key:', pubkey_actual.hex().upper()) sig_actual = schnorr_sign(msg, seckey) if sig == sig_actual: print(' * Passed signing test.') else: print(' * Failed signing test.') - print(' Excepted signature:', sig.hex()) - print(' Actual signature:', sig_actual.hex()) + print(' Expected signature:', sig.hex().upper()) + print(' Actual signature:', sig_actual.hex().upper()) all_passed = False result_actual = schnorr_verify(msg, pubkey, sig) if result == result_actual: print(' * Passed verification test.') else: print(' * Failed verification test.') - print(' Excepted verification result:', result) + print(' Expected verification result:', result) print(' Actual verification result:', result_actual) if comment: print(' Comment:', comment) diff --git a/bip-schnorr/test-vectors.csv b/bip-schnorr/test-vectors.csv index a4218f7..3e17669 100644 --- a/bip-schnorr/test-vectors.csv +++ b/bip-schnorr/test-vectors.csv @@ -1,17 +1,15 @@ index,secret key,public key,message,signature,verification result,comment -1,0000000000000000000000000000000000000000000000000000000000000001,0279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798,0000000000000000000000000000000000000000000000000000000000000000,787A848E71043D280C50470E8E1532B2DD5D20EE912A45DBDD2BD1DFBF187EF67031A98831859DC34DFFEEDDA86831842CCD0079E1F92AF177F7F22CC1DCED05,TRUE, -2,B7E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEF,02DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,2A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1D1E51A22CCEC35599B8F266912281F8365FFC2D035A230434A1A64DC59F7013FD,TRUE, -3,C90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B14E5C7,03FAC2114C2FBB091527EB7C64ECB11F8021CB45E8E7809D3C0938E4B8C0E5F84B,5E2D58D8B3BCDF1ABADEC7829054F90DDA9805AAB56C77333024B9D0A508B75C,00DA9B08172A9B6F0466A2DEFD817F2D7AB437E0D253CB5395A963866B3574BE00880371D01766935B92D2AB4CD5C8A2A5837EC57FED7660773A05F0DE142380,TRUE, -4,,03DEFDEA4CDB677750A420FEE807EACF21EB9898AE79B9768766E4FAA04A2D4A34,4DF3C3F68FCC83B27E9D42C90431A72499F17875C81A599B566C9889B9696703,00000000000000000000003B78CE563F89A0ED9414F5AA28AD0D96D6795F9C6302A8DC32E64E86A333F20EF56EAC9BA30B7246D6D25E22ADB8C6BE1AEB08D49D,TRUE, -5,,031B84C5567B126440995D3ED5AABA0565D71E1834604819FF9C17F5E9D5DD078F,0000000000000000000000000000000000000000000000000000000000000000,52818579ACA59767E3291D91B76B637BEF062083284992F2D95F564CA6CB4E3530B1DA849C8E8304ADC0CFE870660334B3CFC18E825EF1DB34CFAE3DFC5D8187,TRUE,"test fails if jacobi symbol of x(R) instead of y(R) is used" -6,,03FAC2114C2FBB091527EB7C64ECB11F8021CB45E8E7809D3C0938E4B8C0E5F84B,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,570DD4CA83D4E6317B8EE6BAE83467A1BF419D0767122DE409394414B05080DCE9EE5F237CBD108EABAE1E37759AE47F8E4203DA3532EB28DB860F33D62D49BD,TRUE,"test fails if msg is reduced modulo p or n" -7,,03EEFDEA4CDB677750A420FEE807EACF21EB9898AE79B9768766E4FAA04A2D4A34,4DF3C3F68FCC83B27E9D42C90431A72499F17875C81A599B566C9889B9696703,00000000000000000000003B78CE563F89A0ED9414F5AA28AD0D96D6795F9C6302A8DC32E64E86A333F20EF56EAC9BA30B7246D6D25E22ADB8C6BE1AEB08D49D,FALSE,"public key not on the curve" -8,,02DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,2A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1DFA16AEE06609280A19B67A24E1977E4697712B5FD2943914ECD5F730901B4AB7,FALSE,"incorrect R residuosity" -9,,03FAC2114C2FBB091527EB7C64ECB11F8021CB45E8E7809D3C0938E4B8C0E5F84B,5E2D58D8B3BCDF1ABADEC7829054F90DDA9805AAB56C77333024B9D0A508B75C, 00DA9B08172A9B6F0466A2DEFD817F2D7AB437E0D253CB5395A963866B3574BED092F9D860F1776A1F7412AD8A1EB50DACCC222BC8C0E26B2056DF2F273EFDEC,FALSE,"negated message" -10,,0279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798,0000000000000000000000000000000000000000000000000000000000000000,787A848E71043D280C50470E8E1532B2DD5D20EE912A45DBDD2BD1DFBF187EF68FCE5677CE7A623CB20011225797CE7A8DE1DC6CCD4F754A47DA6C600E59543C,FALSE,"negated s value" -11,,03DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,2A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1D1E51A22CCEC35599B8F266912281F8365FFC2D035A230434A1A64DC59F7013FD,FALSE,"negated public key" -12,,02DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,00000000000000000000000000000000000000000000000000000000000000009E9D01AF988B5CEDCE47221BFA9B222721F3FA408915444A4B489021DB55775F,FALSE,"sG - eP is infinite. Test fails in single verification if jacobi(y(inf)) is defined as 1 and x(inf) as 0" -13,,02DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,0000000000000000000000000000000000000000000000000000000000000001D37DDF0254351836D84B1BD6A795FD5D523048F298C4214D187FE4892947F728,FALSE,"sG - eP is infinite. Test fails in single verification if jacobi(y(inf)) is defined as 1 and x(inf) as 1" -14,,02DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,4A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1D1E51A22CCEC35599B8F266912281F8365FFC2D035A230434A1A64DC59F7013FD,FALSE,"sig[0:32] is not an X coordinate on the curve" -15,,02DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC2F1E51A22CCEC35599B8F266912281F8365FFC2D035A230434A1A64DC59F7013FD,FALSE,"sig[0:32] is equal to field size" -16,,02DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,2A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141,FALSE,"sig[32:64] is equal to curve order" +0,0000000000000000000000000000000000000000000000000000000000000001,79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798,0000000000000000000000000000000000000000000000000000000000000000,787A848E71043D280C50470E8E1532B2DD5D20EE912A45DBDD2BD1DFBF187EF6166FCCEE14F021B31AF22A90D0639CC010C2B764C304A8FFF266ABBC01A0A880,TRUE, +1,B7E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEF,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,3C4D3ADB1F05C3E948216ECB6007D1534D97D35D5589EDB226AD0370C0293C780AEA9BA361509DA2FDF7BC6E5E38926E40B6ACCD24EA9E06B9DA8244A1D0B691,TRUE, +2,C90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B14E5C7,FAC2114C2FBB091527EB7C64ECB11F8021CB45E8E7809D3C0938E4B8C0E5F84B,5E2D58D8B3BCDF1ABADEC7829054F90DDA9805AAB56C77333024B9D0A508B75C,33380A613013115518CD6030ABC8220B2DED273FD3ABD13DF0882DC6A928E5AFAC72DF3248F8FAC522EF1A819EE5EE5BEA81D92D0E19A6FAB228E5D1D61BF833,TRUE, +3,0B432B2677937381AEF05BB02A66ECD012773062CF3FA2549E44F58ED2401710,25D1DFF95105F5253C4022F628A996AD3A0D95FBF21D468A1B33F8C160D8F517,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,7C4E8B0C2575A77A01AF41EE6678EF9C41F97CC4D15FF6D6CA45D73BC6FF7FF4919D246589AF2FA6306F4B7A392857E9C4A17CB21DBE72C38A48C99979EEDCB8,TRUE,test fails if msg is reduced modulo p or n +4,,D69C3509BB99E412E68B0FE8544E72837DFA30746D8BE2AA65975F29D22DC7B9,4DF3C3F68FCC83B27E9D42C90431A72499F17875C81A599B566C9889B9696703,00000000000000000000003B78CE563F89A0ED9414F5AA28AD0D96D6795F9C63F84A709CFFD89AD94FCBD808D41BD26BF62F263AA253527134DDC4A4715BF491,TRUE, +5,,EEFDEA4CDB677750A420FEE807EACF21EB9898AE79B9768766E4FAA04A2D4A34,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,3C4D3ADB1F05C3E948216ECB6007D1534D97D35D5589EDB226AD0370C0293C780AEA9BA361509DA2FDF7BC6E5E38926E40B6ACCD24EA9E06B9DA8244A1D0B691,FALSE,public key not on the curve +6,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F98631F4EF21D5F231A1000ED069E0348ED057EDF4FB1B6672009EDE9DBB2DEE14,FALSE,incorrect R residuosity +7,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,07636CBE3092D11AFCA4DD1D32E50F039EB5FF5FB2AB72A7DC2BA0F3A4E7ED418C312ED6ABF6A41446D28789DF4AA43A15E166F001D072536ADC6E49C21DC419,FALSE,negated message +8,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,3C4D3ADB1F05C3E948216ECB6007D1534D97D35D5589EDB226AD0370C0293C78F515645C9EAF625D02084391A1C76D9079F830198A5E023505F7DC482E658AB0,FALSE,negated s value +9,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,0000000000000000000000000000000000000000000000000000000000000000221A96FEEBA7AD29F11B675DB394948A83A220FD8FE181A7667BDBEE178011B1,FALSE,sG - eP is infinite. Test fails in single verification if jacobi(y(inf)) is defined as 1 and x(inf) as 0 +10,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,00000000000000000000000000000000000000000000000000000000000000011A39648F31350D8E591106B43B9EB364F8617BCD52DC96A3FA8C4E50347F31DE,FALSE,sG - eP is infinite. Test fails in single verification if jacobi(y(inf)) is defined as 1 and x(inf) as 1 +11,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,4A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1D0AEA9BA361509DA2FDF7BC6E5E38926E40B6ACCD24EA9E06B9DA8244A1D0B691,FALSE,sig[0:32] is not an X coordinate on the curve +12,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F0AEA9BA361509DA2FDF7BC6E5E38926E40B6ACCD24EA9E06B9DA8244A1D0B691,FALSE,sig[0:32] is equal to field size +13,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,3C4D3ADB1F05C3E948216ECB6007D1534D97D35D5589EDB226AD0370C0293C78FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141,FALSE,sig[32:64] is equal to curve order diff --git a/bip-schnorr/test-vectors.py b/bip-schnorr/test-vectors.py new file mode 100644 index 0000000..5088400 --- /dev/null +++ b/bip-schnorr/test-vectors.py @@ -0,0 +1,215 @@ +import sys +from reference import * + +def vector0(): + seckey = 1 + msg = bytes_from_int(0) + sig = schnorr_sign(msg, seckey) + pubkey = pubkey_gen(seckey) + + # The point reconstructed from the public key has an even Y coordinate. + pubkey_point = point_from_bytes(pubkey) + assert(pubkey_point[1] & 1 == 0) + + return (bytes_from_int(seckey), pubkey, msg, sig, "TRUE", None) + +def vector1(): + seckey = 0xB7E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEF + msg = bytes_from_int(0x243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89) + sig = schnorr_sign(msg, seckey) + pubkey = pubkey_gen(seckey) + + # The point reconstructed from the public key has an odd Y coordinate. + pubkey_point = point_from_bytes(pubkey) + assert(pubkey_point[1] & 1 == 1) + + return (bytes_from_int(seckey), pubkey, msg, sig, "TRUE", None) + +def vector2(): + seckey = 0xC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B14E5C7 + msg = bytes_from_int(0x5E2D58D8B3BCDF1ABADEC7829054F90DDA9805AAB56C77333024B9D0A508B75C) + sig = schnorr_sign(msg, seckey) + + # This signature does not verify vector if the implementer would check the + # jacobi symbol of the X coordinate of R instead of the Y coordinate. + R = point_from_bytes(sig[0:32]) + assert(jacobi(R[0]) != 1) + + return (bytes_from_int(seckey), pubkey_gen(seckey), msg, sig, "TRUE", None) + +def vector3(): + seckey = 0x0B432B2677937381AEF05BB02A66ECD012773062CF3FA2549E44F58ED2401710 + msg = bytes_from_int(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) + sig = schnorr_sign(msg, seckey) + return (bytes_from_int(seckey), pubkey_gen(seckey), msg, sig, "TRUE", "test fails if msg is reduced modulo p or n") + +# Signs with a given nonce. Results in an invalid signature if y(kG) is not a +# quadratic residue. +def schnorr_sign_fixed_nonce(msg, seckey0, k): + if len(msg) != 32: + raise ValueError('The message must be a 32-byte array.') + if not (1 <= seckey0 <= n - 1): + raise ValueError('The secret key must be an integer in the range 1..n-1.') + P = point_mul(G, seckey0) + seckey = seckey0 if (jacobi(P[1]) == 1) else n - seckey0 + R = point_mul(G, k) + e = int_from_bytes(hash_sha256(bytes_from_point(R) + bytes_from_point(P) + msg)) % n + return bytes_from_point(R) + bytes_from_int((k + e * seckey) % n) + +# Creates a singature with a small x(R) by using k = 1/2 +def vector4(): + one_half = 0x7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0 + seckey = 0x763758E5CBEEDEE4F7D3FC86F531C36578933228998226672F13C4F0EBE855EB + msg = bytes_from_int(0x4DF3C3F68FCC83B27E9D42C90431A72499F17875C81A599B566C9889B9696703) + sig = schnorr_sign_fixed_nonce(msg, seckey, one_half) + return (None, pubkey_gen(seckey), msg, sig, "TRUE", None) + +default_seckey = 0xB7E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEF +default_msg = bytes_from_int(0x243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89) + +def vector5(): + seckey = default_seckey + msg = default_msg + sig = schnorr_sign(msg, seckey) + + # Public key is not on the curve + pubkey = bytes_from_int(0xEEFDEA4CDB677750A420FEE807EACF21EB9898AE79B9768766E4FAA04A2D4A34) + assert(point_from_bytes(pubkey) is None) + + return (None, pubkey, msg, sig, "FALSE", "public key not on the curve") + +def vector6(): + seckey = default_seckey + msg = default_msg + k = 3 + sig = schnorr_sign_fixed_nonce(msg, seckey, k) + + # Y coordinate of R is not a quadratic residue + R = point_mul(G, k) + assert(jacobi(R[1]) != 1) + + return (None, pubkey_gen(seckey), msg, sig, "FALSE", "incorrect R residuosity") + +def vector7(): + seckey = default_seckey + msg = int_from_bytes(default_msg) + neg_msg = bytes_from_int(n - msg) + sig = schnorr_sign(neg_msg, seckey) + return (None, pubkey_gen(seckey), bytes_from_int(msg), sig, "FALSE", "negated message") + +def vector8(): + seckey = default_seckey + msg = default_msg + sig = schnorr_sign(msg, seckey) + sig = sig[0:32] + bytes_from_int(n - int_from_bytes(sig[32:64])) + return (None, pubkey_gen(seckey), msg, sig, "FALSE", "negated s value") + +def bytes_from_point_inf0(P): + if P == None: + return bytes_from_int(0) + return bytes_from_int(P[0]) + +def vector9(): + seckey = default_seckey + msg = default_msg + + # Override bytes_from_point in schnorr_sign to allow creating a signature + # with k = 0. + k = 0 + bytes_from_point_tmp = bytes_from_point.__code__ + bytes_from_point.__code__ = bytes_from_point_inf0.__code__ + sig = schnorr_sign_fixed_nonce(msg, seckey, k) + bytes_from_point.__code__ = bytes_from_point_tmp + + return (None, pubkey_gen(seckey), msg, sig, "FALSE", "sG - eP is infinite. Test fails in single verification if jacobi(y(inf)) is defined as 1 and x(inf) as 0") + +def bytes_from_point_inf1(P): + if P == None: + return bytes_from_int(1) + return bytes_from_int(P[0]) + +def vector10(): + seckey = default_seckey + msg = default_msg + + # Override bytes_from_point in schnorr_sign to allow creating a signature + # with k = 0. + k = 0 + bytes_from_point_tmp = bytes_from_point.__code__ + bytes_from_point.__code__ = bytes_from_point_inf1.__code__ + sig = schnorr_sign_fixed_nonce(msg, seckey, k) + bytes_from_point.__code__ = bytes_from_point_tmp + + return (None, pubkey_gen(seckey), msg, sig, "FALSE", "sG - eP is infinite. Test fails in single verification if jacobi(y(inf)) is defined as 1 and x(inf) as 1") + +# It's cryptographically impossible to create a test vector that fails if run +# in an implementation which merely misses the check that sig[0:32] is an X +# coordinate on the curve. This test vector just increases test coverage. +def vector11(): + seckey = default_seckey + msg = default_msg + sig = schnorr_sign(msg, seckey) + + # Replace R's X coordinate with an X coordinate that's not on the curve + x_not_on_curve = bytes_from_int(0x4A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1D) + assert(point_from_bytes(x_not_on_curve) is None) + sig = x_not_on_curve + sig[32:64] + + return (None, pubkey_gen(seckey), msg, sig, "FALSE", "sig[0:32] is not an X coordinate on the curve") + +# It's cryptographically impossible to create a test vector that fails if run +# in an implementation which merely misses the check that sig[0:32] is smaller +# than the field size. This test vector just increases test coverage. +def vector12(): + seckey = default_seckey + msg = default_msg + sig = schnorr_sign(msg, seckey) + + # Replace R's X coordinate with an X coordinate that's equal to field size + sig = bytes_from_int(p) + sig[32:64] + + return (None, pubkey_gen(seckey), msg, sig, "FALSE", "sig[0:32] is equal to field size") + +# It's cryptographically impossible to create a test vector that fails if run +# in an implementation which merely misses the check that sig[32:64] is smaller +# than the curve order. This test vector just increases test coverage. +def vector13(): + seckey = default_seckey + msg = default_msg + sig = schnorr_sign(msg, seckey) + + # Replace s with a number that's equal to the curve order + sig = sig[0:32] + bytes_from_int(n) + + return (None, pubkey_gen(seckey), msg, sig, "FALSE", "sig[32:64] is equal to curve order") + +vectors = [ + vector0(), + vector1(), + vector2(), + vector3(), + vector4(), + vector5(), + vector6(), + vector7(), + vector8(), + vector9(), + vector10(), + vector11(), + vector12(), + vector13(), + ] + +# Converts the byte strings of a test vector into hex strings +def bytes_to_hex(seckey, pubkey, msg, sig, result, comment): + return (seckey.hex().upper() if seckey is not None else None, pubkey.hex().upper(), msg.hex().upper(), sig.hex().upper(), result, comment) + +vectors = list(map(lambda vector: bytes_to_hex(vector[0], vector[1], vector[2], vector[3], vector[4], vector[5]), vectors)) + +def print_csv(vectors): + writer = csv.writer(sys.stdout) + writer.writerow(("index", "secret key", "public key", "message", "signature", "verification result", "comment")) + for (i,v) in enumerate(vectors): + writer.writerow((i,)+v) + +print_csv(vectors) -- cgit v1.2.3 From 5793d3d73561a94230b486cfe0ca88ea346568de Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Fri, 2 Aug 2019 13:52:29 +0000 Subject: Use short public keys for taproot output keys --- bip-taproot.mediawiki | 52 +++++++++++++++++++++++++++---------------------- bip-tapscript.mediawiki | 18 ++++++++--------- 2 files changed, 37 insertions(+), 33 deletions(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index f100e6e..a553791 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -62,24 +62,23 @@ In the text below, ''hashtag(m)'' is a shorthand for ''SHA256(SHA256( === Script validation rules === -A Taproot output is a SegWit output (native or P2SH-nested, see [https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki BIP141]) with version number 1, and a 33-byte witness program whose first byte is 0 or 1. -The following rules only apply when such an output is being spent. Any other outputs, including version 1 outputs with lengths other than 33 bytes, or with a first byte different from 0 or 1, remain unencumbered. +A Taproot output is a SegWit output (native or P2SH-nested, see [https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki BIP141]) with version number 1, and a 32-byte witness program. +The following rules only apply when such an output is being spent. Any other outputs, including version 1 outputs with lengths other than 32 bytes, remain unencumbered. -* Let ''u'' be the 33-byte array containing the witness program (second push in scriptPubKey or P2SH redeemScript). -* Let ''Q = point(byte(2 + u[0]) || u[1:33])'''''Why is the public key directly included in the output?''' While typical earlier constructions store a hash of a script or a public key in the output, this is rather wasteful when a public key is always involved. To guarantee batch verifiability, ''Q'' must be known to every verifier, and thus only revealing its hash as an output would imply adding an additional 33 bytes to the witness. Furthermore, to maintain [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2016-January/012198.html 128-bit collision security] for outputs, a 256-bit hash would be required anyway, which is comparable in size (and thus in cost for senders) to revealing the public key directly. While the usage of public key hashes is often said to protect against ECDLP breaks or quantum computers, this protection is very weak at best: transactions are not protected while being confirmed, and a very [https://twitter.com/pwuille/status/1108097835365339136 large portion] of the currency's supply is not under such protection regardless. Actual resistance to such systems can be introduced by relying on different cryptographic assumptions, but this proposal focuses on improvements that do not change the security model. Note that using P2SH-wrapped outputs only have 80-bit collision security. This is considered low, and is relevant whenever the output includes data from more than a single party (public keys, hashes, ...). If this is not a valid point on the curve, fail. +* Let ''q'' be the 32-byte array containing the witness program (second push in scriptPubKey or P2SH redeemScript) which represents a public key according to bip-schnorr.'''Why is the public key directly included in the output?''' While typical earlier constructions store a hash of a script or a public key in the output, this is rather wasteful when a public key is always involved. To guarantee batch verifiability, ''q'' must be known to every verifier, and thus only revealing its hash as an output would imply adding an additional 32 bytes to the witness. Furthermore, to maintain [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2016-January/012198.html 128-bit collision security] for outputs, a 256-bit hash would be required anyway, which is comparable in size (and thus in cost for senders) to revealing the public key directly. While the usage of public key hashes is often said to protect against ECDLP breaks or quantum computers, this protection is very weak at best: transactions are not protected while being confirmed, and a very [https://twitter.com/pwuille/status/1108097835365339136 large portion] of the currency's supply is not under such protection regardless. Actual resistance to such systems can be introduced by relying on different cryptographic assumptions, but this proposal focuses on improvements that do not change the security model. Note that using P2SH-wrapped outputs only have 80-bit collision security. This is considered low, and is relevant whenever the output includes data from more than a single party (public keys, hashes, ...). . * Fail if the witness stack has 0 elements. -* If there are at least two witness elements, and the first byte of the last element is 0x50'''Why is the first byte of the annex 0x50?''' Like the 0xc0-0xc1 constants, 0x50 is chosen as it could not be confused with a valid P2WPKH or P2WSH spending. As the control block's initial byte's lowest bit is used to indicate the public key's Y oddness, each script version needs two subsequence byte values that are both not yet used in P2WPKH or P2WSH spending. To indicate the annex, only an "unpaired" available byte is necessary like 0x50. This choice maximizes the available options for future script versions., this last element is called ''annex'' ''a'''''What is the purpose of the annex?''' The annex is a reserved space for future extensions, such as indicating the validation costs of computationally expensive new opcodes in a way that is recognizable without knowing the outputs being spent. Until the meaning of this field is defined by another softfork, users SHOULD NOT include annex in transactions, or it may lead to PERMANENT FUND LOSS. and is removed from the witness stack. The annex (or the lack of thereof) is always covered by the transaction digest and contributes to transaction weight, but is otherwise ignored during taproot validation. +* If there are at least two witness elements, and the first byte of the last element is 0x50'''Why is the first byte of the annex 0x50?''' Like the 0xc0-0xc1 constants, 0x50 is chosen as it could not be confused with a valid P2WPKH or P2WSH spending. As the control block's initial byte's lowest bit is used to indicate the public key's Y quadratic residuosity, each script version needs two subsequence byte values that are both not yet used in P2WPKH or P2WSH spending. To indicate the annex, only an "unpaired" available byte is necessary like 0x50. This choice maximizes the available options for future script versions., this last element is called ''annex'' ''a'''''What is the purpose of the annex?''' The annex is a reserved space for future extensions, such as indicating the validation costs of computationally expensive new opcodes in a way that is recognizable without knowing the outputs being spent. Until the meaning of this field is defined by another softfork, users SHOULD NOT include annex in transactions, or it may lead to PERMANENT FUND LOSS. and is removed from the witness stack. The annex (or the lack of thereof) is always covered by the transaction digest and contributes to transaction weight, but is otherwise ignored during taproot validation. * If there is exactly one element left in the witness stack, key path spending is used: -** The single witness stack element is interpreted as the signature and must be valid (see the next section) for the public key ''Q'' and taproot transaction digest (to be defined hereinafter) as message. Fail if it is not. Otherwise pass. +** The single witness stack element is interpreted as the signature and must be valid (see the next section) for the public key ''q'' and taproot transaction digest (to be defined hereinafter) as message. Fail if it is not. Otherwise pass. * If there are at least two witness elements left, script path spending is used: ** Call the second-to-last stack element ''s'', the script. ** The last stack element is called the control block ''c'', and must have length ''33 + 32m'', for a value of ''m'' that is an integer between 0 and 32, inclusive. Fail if it does not have such a length. -** Let ''P = point(byte(2 + (c[0] & 1)) || c[1:33])'''''What is the purpose of the first byte of the control block?''' The first byte of the control block has three distinct functions: -* The low bit is used to denote the oddness of the Y coordinate of the ''P'' point. +** Let ''P = point(c[1:33])'' where ''point'' is defined as in bip-schnorr. Fail if this point is not on the curve. +** Let ''l = c[0] & 0xfe'', the leaf version'''What is the purpose of the first byte of the control block?''' The first byte of the control block has three distinct functions: +* The low bit is used to denote whether the ''Q'' point's Y coordinate is a quadratic residue.'''Why is the quadratic residuosity of the output public key's Y coordinate required in a script path spend?''' The ''point'' function always constructs a point with Y coordinate having that property, but because ''Q'' is constructed by adding the taproot tweak to the internal public key ''P'', it cannot easily be guaranteed that ''Q'' in fact has such a Y coordinate. We can not ignore the Y coordinate because it would prevent batch verification. Trying out multiple internal keys until there's such a ''Q'' is possible but undesirable and unnecessary since this information about the Y coordinate only consumes an unused bit. * By keeping the top two bits set to true, it can be guaranteed that scripts can be recognized without knowledge of the UTXO being spent, simplifying analysis. This is because such values cannot occur as first byte of the final stack element in either P2WPKH or P2WSH spends. * The remaining five bits are used for introducing new script versions that are not observable unless actually executed. -. Fail if this point is not on the curve. -** Let ''l = c[0] & 0xfe'', the leaf version. +. ** Let ''k0 = hashTapLeaf(l || compact_size(size of s) || s)''; also call it the ''tapleaf hash''. ** For ''j'' in ''[0,1,...,m-1]'': *** Let ''ej = c[33+32j:65+32j]''. @@ -88,10 +87,11 @@ The following rules only apply when such an output is being spent. Any other out **** If ''kj ≥ ej'': ''kj+1 = hashTapBranch(ej || kj)''. ** Let ''t = hashTapTweak(bytes(P) || km) = hashTapTweak(2 + (c[0] & 1) || c[1:33] || km)''. ** If ''t ≥ 0xFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141'' (order of secp256k1), fail. +** Let ''Q = point(q) if (c[0] & 1) = 1 and -point(q) otherwise'' ** If ''Q ≠ P + int(t)G'', fail. ** Execute the script, according to the applicable script rules'''What are the applicable script rules in script path spends?''' Bip-tapscript specifies validity rules that apply if the leaf version is ''0xc0'', but future proposals can introduce rules for other leaf versions., using the witness stack elements excluding the script ''s'', the control block ''c'', and the annex ''a'' if present, as initial stack. -''Q'' is referred to as ''taproot output key'' and ''P'' as ''taproot internal key''. +''q'' is referred to as ''taproot output key'' and ''c[1:33]'' as ''taproot internal key''. === Signature validation rules === @@ -137,7 +137,7 @@ As the message for signature verification, transaction digest is ''hashTapS *** Bit-0 is set if the scriptPubKey being spent is P2SH (opposed to "native segwit"). *** Bit-1 is set if an annex is present (the original witness stack has two or more witness elements, and the first byte of the last element is 0x50). *** The other bits are unset. -** scriptPubKey (24 or 36): scriptPubKey of the previous output spent by this input, serialized as script inside CTxOut. The size is 24-byte for P2SH-embedded segwit, or 36-byte for native segwit. +** scriptPubKey (24 or 35): scriptPubKey of the previous output spent by this input, serialized as script inside CTxOut. The size is 24-byte for P2SH-embedded segwit, or 35-byte for native segwit. ** If the SIGHASH_ANYONECANPAY flag is set: *** outpoint (36): the COutPoint of this input (32-byte hash + 4-byte little-endian). *** amount (8): value of the previous output spent by this input. @@ -150,7 +150,7 @@ As the message for signature verification, transaction digest is ''hashTapS ** If the SIGHASH_SINGLE flag is set: *** sha_single_output (32): the SHA256 of the corresponding output in CTxOut format. -The total number of bytes hashed is at most ''209'''''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''177 - is_anyonecanpay * 50 - is_none * 32 - is_p2sh_spending * 12 + has_annex * 32''.. +The total number of bytes hashed is at most ''209'''''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''176 - is_anyonecanpay * 50 - is_none * 32 - is_p2sh_spending * 11 + has_annex * 32''.. In summary, the semantics of the BIP143 sighash types remain unchanged, except the following: # The way and order of serialization is changed.'''Why is the serialization in the transaction digest changed?''' Hashes that go into the digest and the digest itself are now computed with a single SHA256 invocation instead of double SHA256. There is no expected security improvement by doubling SHA256 because this only protects against length-extension attacks against SHA256 which are not a concern for transaction digests because there is no secret data. Therefore doubling SHA256 is a waste of resources. The digest computation now follows a logical order with transaction level data first, then input data and output data. This allows to efficiently cache the transaction part of the digest across different inputs using the SHA256 midstate. Additionally, digest computation avoids unnecessary hashing as opposed to BIP143 digests in which parts may be set zero and before hashing them. Despite that, collisions are made impossible by committing to the length of the data (implicit in hash_type and spend_type) before the variable length data. @@ -165,7 +165,7 @@ This section discusses how to construct and spend Taproot outputs. It only affec and is not consensus critical in any way. Conceptually, every Taproot output corresponds to a combination of a single public key condition (the internal key), and zero or more general conditions encoded in scripts organized in a tree. -Satisfying any of these conditions is sufficient to spend the output. +Satisfying any of these conditions is sufficient to spend the output. '''Initial steps''' The first step is determining what the internal key and the organization of the rest of the scripts should be. The specifics are likely application dependent, but here are some general guidelines: * When deciding between scripts with conditionals (OP_IF etc.) and splitting them up into multiple scripts (each corresponding to one execution path through the original script), it is generally preferable to pick the latter. @@ -173,7 +173,7 @@ Satisfying any of these conditions is sufficient to spend the output. * If one or more of the spending conditions consist of just a single key (after aggregation), the most likely one should be made the internal key. If no such condition exists, it may be worthwhile adding one that consists of an aggregation of all keys participating in all scripts combined; effectively adding an "everyone agrees" branch. If that is inacceptable, pick as internal key a point with unknown discrete logarithm (TODO). * The remaining scripts should be organized into the leaves of a binary tree. This can be a balanced tree if each of the conditions these scripts correspond to are equally likely. If probabilities for each condition are known, consider constructing the tree as a Huffman tree. -'''Computing the output script''' Once the spending conditions are split into an internal key internal_pubkey and a binary tree whose leaves are (leaf_version, script) tuples, the following Python3 algorithm can be used to compute the output script. In the code below, ser_script prefixes its input with a CCompactSize-encoded length, and public key objects have methods get_bytes to get their compressed encoding (see bip-schnorr) and tweak_add to add a multiple of the secp256k1 generator to it (similar to BIP32's derivation). +'''Computing the output script''' Once the spending conditions are split into an internal key internal_pubkey and a binary tree whose leaves are (leaf_version, script) tuples, the following Python3 algorithm can be used to compute the output script. In the code below, ser_script prefixes its input with a CCompactSize-encoded length. Public key objects hold 32-byte public keys according to bip-schnorr, have a method get_bytes to get the byte array and a method tweak_add which returns a new public key corresponding to the sum of the public key point and a multiple of the secp256k1 generator (similar to BIP32's derivation). The second return value of tweak_add is a boolean indicating the quadratic residuosity of the Y coordinate of the resulting point. import hashlib @@ -202,22 +202,26 @@ def taproot_output_script(internal_pubkey, script_tree): _, h = taproot_tree_helper(script_tree) t = tagged_hash("TapTweak", internal_pubkey.get_bytes() + h) assert int.from_bytes(t, 'big') < SECP256K1_ORDER - output_pubkey = internal_pubkey.tweak_add(t).get_bytes() - return bytes([0x51, 0x21, output_pubkey[0] & 1]) + output_pubkey[1:] + output_pubkey, _ = internal_pubkey.tweak_add(t) + return bytes([0x51, 0x20]) + output_pubkey.get_bytes() The function taproot_output_script returns a byte array with the scriptPubKey. It can be P2SH wrapped if desired (see BIP141). [[File:bip-taproot/tree.png|frame|This diagram shows the hashing structure to obtain the tweak from an internal key ''P'' and a Merkle tree consisting of 5 script leaves. ''A'', ''B'', ''C'' and ''E'' are ''TapLeaf'' hashes similar to ''D'' and ''AB'' is a ''TapBranch'' hash. Note that when ''CDE'' is computed ''E'' is hashed first because ''E'' is less than ''CD''.]] -'''Spending using the internal key''' A Taproot output can be spent with the private key corresponding to the internal_pubkey. To do so, a witness stack consisting of a single element, a bip-schnorr signature on the signature hash as defined above, with the private key tweaked by the same t in the above snippet. See the code below: +'''Spending using the internal key''' A Taproot output can be spent with the private key corresponding to the internal_pubkey. To do so, a witness stack consists of a single element: a bip-schnorr signature on the signature hash as defined above, with the private key tweaked by the same t in the above snippet. In the code below, internal_privkey has a method pubkey_gen that returns a public key according to bip-schnorr and a boolean indicating the quadratic residuosity of the Y coordinate of the underlying point. +See the code below: -def taproot_sign_internal_key(internal_pubkey, script_tree, internal_privkey, hash_type): +def taproot_sign_internal_key(script_tree, internal_privkey, hash_type): + internal_pubkey, is_y_qresidue = internal_privkey.pubkey_gen() + if is_y_qresidue: + internal_privkey = internal_privkey.negate() _, h = taproot_tree_helper(script_tree) t = tagged_hash("TapTweak", internal_pubkey.get_bytes() + h) output_privkey = internal_privkey.tweak_add(t) - sig = output_privkey.sign_schnorr(sighash(hash_type)) + sig = output_privkey.schnorr_sign(sighash(hash_type)) if hash_type != 0: sig += bytes([hash_type]) return [sig] @@ -229,10 +233,12 @@ This function returns the witness stack necessary, and assumes a tweak_add def taproot_sign_script(internal_pubkey, script_tree, script_num, inputs): - info, _ = taproot_tree_helper(script_tree) + info, h = taproot_tree_helper(script_tree) (leaf_version, script), path = info[script_num] - pubkey_bytes = internal_pubkey.get_bytes() - pubkey_data = bytes([(pubkey_bytes[0] & 1) + leaf_version]) + pubkey_bytes[1:] + t = tagged_hash("TapTweak", internal_pubkey.get_bytes() + h) + _, is_y_qresidue = internal_pubkey.tweak_add(t) + output_pubkey_tag = 0 if is_y_qresidue else 1 + pubkey_data = bytes([output_pubkey_tag + leaf_version]) + internal_pubkey.get_bytes() return inputs + [script, pubkey_data + path] diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index ce42098..af46afd 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -45,7 +45,7 @@ Additionally, the new tapscript OP_SUCCESS opcodes allow introducin The rules below only apply when validating a transaction input for which all of the conditions below are true: * The transaction output is a '''segregated witness spend''' (i.e., either the scriptPubKey or BIP16 redeemScript is a witness program as defined in BIP141). -* It is a '''taproot spend''' as defined in bip-taproot (i.e., the witness version is 1, the witness program is 33 bytes, and the first of those is 0x00 or 0x01). +* It is a '''taproot spend''' as defined in bip-taproot (i.e., the witness version is 1, the witness program is 32 bytes). * It is a '''script path spend''' as defined in bip-taproot (i.e., after removing the optional annex from the witness stack, two or more stack elements remain). * The leaf version is ''0xc0'' (i.e. the first byte of the last witness element after removing the optional annex is ''0xc0'' or ''0xc1'')'''How is the ''0xc0'' constant chosen?''' Following the guidelines in bip-taproot, by choosing a value having the two top bits set, tapscript spends are identifiable even without access to the UTXO being spent., marking it as a '''tapscript spend'''. @@ -71,7 +71,7 @@ The execution rules for tapscript are based on those for P2WSH according to BIP1 * '''Disabled script opcodes''' The following script opcodes are disabled in tapscript: OP_CHECKMULTISIG and OP_CHECKMULTISIGVERIFY. The disabled opcodes behave in the same way as OP_RETURN, by failing and terminating the script immediately when executed, and being ignored when found in unexecuted branch. While being ignored, they are still counted towards the 201 non-push opcodes limit. * '''Consensus-enforced MINIMALIF''' The MINIMALIF rules, which are only a standardness rule in P2WSH, are consensus enforced in tapscript. This means that the input argument to the OP_IF and OP_NOTIF opcodes must be either exactly 0 (the empty vector) or exactly 1 (the one-byte vector with value 1)'''Why make MINIMALIF consensus?''' This makes it considerably easier to write non-malleable scripts that take branch information from the stack.. * '''OP_SUCCESSx opcodes''' As listed above, some opcodes are renamed to OP_SUCCESSx, and make the script unconditionally valid. -* '''Signature opcodes'''. The OP_CHECKSIG and OP_CHECKSIGVERIFY are modified to operate on Schnorr signatures (see bip-schnorr) instead of ECDSA, and a new opcode OP_CHECKSIGADD is added. +* '''Signature opcodes'''. The OP_CHECKSIG and OP_CHECKSIGVERIFY are modified to operate on Schnorr public keys and signatures (see bip-schnorr) instead of ECDSA, and a new opcode OP_CHECKSIGADD is added. ** The opcode 186 (0xba) is named as OP_CHECKSIGADD. '''OP_CHECKSIGADD''' This opcode is added to compensate for the loss of OP_CHECKMULTISIG-like opcodes, which are incompatible with batch verification. OP_CHECKSIGADD is functionally equivalent to OP_ROT OP_SWAP OP_CHECKSIG OP_ADD, but is only counted as one opcode towards the 201 non-push opcodes limit. All CScriptNum-related behaviours of OP_ADD are also applicable to OP_CHECKSIGADD.'''Comparison of CHECKMULTISIG and CHECKSIG''' A CHECKMULTISIG script m ... n CHECKMULTISIG with witness 0 ... can be rewritten as script CHECKSIG ... CHECKSIGADD m NUMEQUAL with witness ... . Every witness element w_i is either a signature corresponding to the public key with the same index or an empty vector. A similar CHECKMULTISIGVERIFY script can be translated to bip-tapscript by replacing NUMEQUAL with NUMEQUALVERIFY. Alternatively, an m-of-n multisig policy can be implemented by splitting the script into several leaves of the Merkle tree, each implementing an m-of-m policy using CHECKSIGVERIFY ... CHECKSIGVERIFY CHECKSIG. If the setting allows the participants to interactively collaborate while signing, multisig policies can be realized with [https://eprint.iacr.org/2018/068 MuSig] for m-of-m and with [http://cacr.uwaterloo.ca/techreports/2001/corr2001-13.ps threshold signatures] using verifiable secret sharing for m-of-n. ===Rules for signature opcodes=== @@ -84,11 +84,9 @@ The following rules apply to OP_CHECKSIG, OP_CHECKSIGVERIFYn is larger than 4 bytes, the script MUST fail and terminate immediately. * If the public key size is zero, the script MUST fail and terminate immediately. -* If the first byte of the public key is 0x04, 0x06, or 0x07, the script MUST fail and terminate immediately regardless of the public key size. -* If the first byte of the public key is 0x02 or 0x03, it is considered to be a public key as described in bip-schnorr: -** If the public key is not 33 bytes, the script MUST fail and terminate immediately. +* If the public key size is 32 bytes, it is considered to be a public key as described in bip-schnorr: ** If the signature is not the empty vector, the signature is validated according to the bip-taproot signing validation rules against the public key and the tapscript transaction digest (to be defined hereinafter) as message. Validation failure MUST cause the script to fail and terminate immediately. -* If the first byte of the public key is not 0x02, 0x03, 0x04, 0x06, or 0x07, the public key is of an ''unknown public key type'''''Unknown public key types''' allow adding new signature validation rules through softforks. A softfork could add actual signature validation which either passes or makes the script fail and terminate immediately. This way, new SIGHASH modes can be added, as well as [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-December/016549.html NOINPUT-tagged public keys] and a public key constant which is replaced by the taproot internal key for signature validation. and no actual signature verification is applied. During script execution of signature opcodes they behave exactly as known public key types except that signature validation is considered to be successful. +* If the public key size is not zero and not 32 bytes, the public key is of an ''unknown public key type'''''Unknown public key types''' allow adding new signature validation rules through softforks. A softfork could add actual signature validation which either passes or makes the script fail and terminate immediately. This way, new SIGHASH modes can be added, as well as [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-December/016549.html NOINPUT-tagged public keys] and a public key constant which is replaced by the taproot internal key for signature validation. and no actual signature verification is applied. During script execution of signature opcodes they behave exactly as known public key types except that signature validation is considered to be successful. * If the script did not fail and terminate before this step, regardless of the public key type: ** If the signature is the empty vector: *** For OP_CHECKSIGVERIFY, the script MUST fail and terminate immediately. @@ -113,14 +111,14 @@ The one-byte spend_type has a different value, specificially at bit As additional pieces of data, added at the end of the input to the ''hashTapSighash'' function: * tapleaf_hash (32): the tapleaf hash as defined in bip-taproot -* key_version (1): a constant value 0x02 representing the current version of public keys in the tapscript signature opcode execution. +* key_version (1): a constant value 0x00 representing the current version of public keys in the tapscript signature opcode execution. * codeseparator_position (2): the opcode position of the last executed OP_CODESEPARATOR before the currently executed signature opcode, with the value in little endian (or 0xffff if none executed). The first opcode in a script has a position of 0. A multi-byte push opcode is counted as one opcode, regardless of the size of data being pushed. -The total number of bytes hashed is at most ''244'''''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''212 - is_anyonecanpay * 50 - is_none * 32 - is_p2sh_spending * 12 + has_annex * 32''.. +The total number of bytes hashed is at most ''244'''''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''211 - is_anyonecanpay * 50 - is_none * 32 - is_p2sh_spending * 11 + has_annex * 32''.. In summary, the semantics of the BIP143 sighash types remain unchanged, except the following: # The exceptions mentioned in bip-taproot. -# The digest commits to taproot-specific data key_version.'''Why does the transaction digest commit to the key_version?''' This is for future extensions that define unknown public key types, making sure signatures can't be moved from one key type to another. This value is intended to be set equal to the first byte of the public key, after masking out flags like the oddness of the Y coordinate. +# The digest commits to taproot-specific data key_version.'''Why does the transaction digest commit to the key_version?''' This is for future extensions that define unknown public key types, making sure signatures can't be moved from one key type to another. # The digest commits to the executed script through the tapleaf_hash which includes the leaf version and script instead of scriptCode. This implies that this commitment is unaffected by OP_CODESEPARATOR. # The digest commits to the opcode position of the last executed OP_CODESEPARATOR.'''Why does the transaction digest commit to the position of the last executed OP_CODESEPARATOR?''' This allows continuing to use OP_CODESEPARATOR to sign the executed path of the script. Because the codeseparator_position is the last input to the digest, the SHA256 midstate can be efficiently cached for multiple OP_CODESEPARATORs in a single script. In contrast, the BIP143 handling of OP_CODESEPARATOR is to commit to the executed script only from the last executed OP_CODESEPARATOR onwards which requires unnecessary rehashing of the script. It should be noted that the one known OP_CODESEPARATOR use case of saving a second public key push in a script by sharing the first one between two code branches can be most likely expressed even cheaper by moving each branch into a separate taproot leaf. @@ -133,7 +131,7 @@ In addition to the 201 non-push opcodes limit, the use of signature opcodes is s * If 50 * (sigops_passed - 1) is greater than input_witness_weight, the script MUST fail and terminate immediately. This rule limits worst-case validation costs in tapscript similar to the ''sigops limit'' that only applies to legacy and P2WSH scripts'''The tapscript sigop limit''' The signature opcode limit protects against scripts which are slow to verify due to excessively many signature operations. In tapscript the number of signature opcodes does not count towards the BIP141 or legacy sigop limit. The old sigop limit makes transaction selection in block construction unnecessarily difficult because it is a second constraint in addition to weight. Instead, the number of tapscript signature opcodes is limited by witness weight. Additionally, the limit applies to the transaction input instead of the block and only actually executed signature opcodes are counted. Tapscript execution allows one signature opcode per 50 witness weight units plus one free signature opcode. The tapscript signature opcode limit allows to add new signature opcodes like CHECKSIGFROMSTACK to count towards the limit through a soft fork. Even if in the future new opcodes are introduced which change normal script cost there is need to stuff the witness with meaningless data. In that case the taproot annex can be used to add weight to the witness without increasing the actual witness size. -'''Parameter choice of the sigop limit''' Regular witnesses are unaffected by the limit as their weight is composed of public key and (SIGHASH_ALL) signature pairs with ''34 + 65'' weight units each (which includes a 1 weight unit CCompactSize tag). This is also the case if public keys are reused in the script because a signature's weight alone is 65 or 66 weight units. However, the limit increases the fees of abnormal scripts with duplicate signatures (and public keys) by requiring additional weight. The weight per sigop factor 50 corresponds to the ratio of BIP141 block limits: 4 mega weight units divided by 80,000 sigops. The "free" signature opcode permitted by the limit exists to account for the weight of the non-witness parts of the transaction input.. +'''Parameter choice of the sigop limit''' Regular witnesses are unaffected by the limit as their weight is composed of public key and (SIGHASH_ALL) signature pairs with ''33 + 65'' weight units each (which includes a 1 weight unit CCompactSize tag). This is also the case if public keys are reused in the script because a signature's weight alone is 65 or 66 weight units. However, the limit increases the fees of abnormal scripts with duplicate signatures (and public keys) by requiring additional weight. The weight per sigop factor 50 corresponds to the ratio of BIP141 block limits: 4 mega weight units divided by 80,000 sigops. The "free" signature opcode permitted by the limit exists to account for the weight of the non-witness parts of the transaction input.. ==Rationale== -- cgit v1.2.3 From 9795b7081a39ee8f109cafeb91a4460fa81056e6 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Fri, 10 May 2019 13:29:21 +0000 Subject: Clarify how to disable key path spending --- bip-taproot.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 0b6c04a..038f088 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -170,7 +170,7 @@ Satisfying any of these conditions is sufficient to spend the output. '''Initial steps''' The first step is determining what the internal key and the organization of the rest of the scripts should be. The specifics are likely application dependent, but here are some general guidelines: * When deciding between scripts with conditionals (OP_IF etc.) and splitting them up into multiple scripts (each corresponding to one execution path through the original script), it is generally preferable to pick the latter. * When a single condition requires signatures with multiple keys, key aggregation techniques like MuSig can be used to combine them into a single key. The details are out of scope for this document, but note that this may complicate the signing procedure. -* If one or more of the spending conditions consist of just a single key (after aggregation), the most likely one should be made the internal key. If no such condition exists, it may be worthwhile adding one that consists of an aggregation of all keys participating in all scripts combined; effectively adding an "everyone agrees" branch. If that is inacceptable, pick as internal key a point with unknown discrete logarithm (TODO). +* If one or more of the spending conditions consist of just a single key (after aggregation), the most likely one should be made the internal key. If no such condition exists, it may be worthwhile adding one that consists of an aggregation of all keys participating in all scripts combined; effectively adding an "everyone agrees" branch. If that is inacceptable, pick as internal key a point with unknown discrete logarithm. One example of such a point is ''H = point(0x0250929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0)'' which is [https://github.com/ElementsProject/secp256k1-zkp/blob/11af7015de624b010424273be3d91f117f172c82/src/modules/rangeproof/main_impl.h#L16 constructed] by taking the hash of the standard uncompressed encoding of secp256k1 generator ''G'' as X coordinate. In order to avoid leaking the information that key path spending is not possible it is recommended to pick a fresh integer ''r'' in the range ''0...n-1'' uniformly at random and use ''H + rG'' as internal key. It is possible to prove that this internal key is does not have a known discrete logarithm with respect to ''G'' by revealing ''r'' to a verifier who can then reconstruct how the internal key was created. * The remaining scripts should be organized into the leaves of a binary tree. This can be a balanced tree if each of the conditions these scripts correspond to are equally likely. If probabilities for each condition are known, consider constructing the tree as a Huffman tree. '''Computing the output script''' Once the spending conditions are split into an internal key internal_pubkey and a binary tree whose leaves are (leaf_version, script) tuples, the following Python3 algorithm can be used to compute the output script. In the code below, ser_script prefixes its input with a CCompactSize-encoded length, and public key objects have methods get_bytes to get their compressed encoding (see bip-schnorr) and tweak_add to add a multiple of the secp256k1 generator to it (similar to BIP32's derivation). -- cgit v1.2.3 From 112d9c150ab16d3e536e5f29b91776f4f68d46a3 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Mon, 19 Aug 2019 14:37:55 +0000 Subject: Address Tim's comments --- bip-schnorr.mediawiki | 27 +++++++++++---------------- bip-taproot.mediawiki | 6 +++--- 2 files changed, 14 insertions(+), 19 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index fa8faa5..0eb79c4 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -34,8 +34,8 @@ from not being standardized. This document seeks to change that. As we propose a new standard, a number of improvements not specific to Schnorr signatures can be made: -* '''Signature encoding''': Instead of [https://en.wikipedia.org/wiki/X.690#DER_encoding DER]-encoding for signatures (which are variable size, and up to 72 bytes), we can use a simple fixed 64-byte format. -* '''Public key encoding''': Instead of ''compressed'' 33-byte encoding of elliptic curve points which are common in Bitcoin, public keys in this proposal are encoded as 32 bytes. +* '''Signature encoding''': Instead of using [https://en.wikipedia.org/wiki/X.690#DER_encoding DER]-encoding for signatures (which are variable size, and up to 72 bytes), we can use a simple fixed 64-byte format. +* '''Public key encoding''': Instead of using ''compressed'' 33-byte encodings of elliptic curve points which are common in Bitcoin today, public keys in this proposal are encoded as 32 bytes. * '''Batch verification''': The specific formulation of ECDSA signatures that is standardized cannot be verified more efficiently in batch compared to individually, unless additional witness data is added. Changing the signature scheme offers an opportunity to avoid this. [[File:bip-schnorr/speedup-batch.png|frame|This graph shows the ratio between the time it takes to verify ''n'' signatures individually and to verify a batch of ''n'' signatures. This ratio goes up logarithmically with the number of signatures, or in other words: the total time to verify ''n'' signatures grows with ''O(n / log n)''.]] @@ -58,19 +58,14 @@ We choose the ''R''-option to support batch verification. '''Key prefixing''' When using the verification rule above directly, it is possible for a third party to convert a signature ''(R,s)'' for key ''P'' into a signature ''(R,s + aH(R || m))'' for key ''P + aG'' and the same message, for any integer ''a''. This is not a concern for Bitcoin currently, as all signature hashes indirectly commit to the public keys. However, this may change with proposals such as SIGHASH_NOINPUT ([https://github.com/bitcoin/bips/blob/master/bip-0118.mediawiki BIP 118]), or when the signature scheme is used for other purposes—especially in combination with schemes like [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki BIP32]'s unhardened derivation. To combat this, we choose ''key prefixed''A limitation of committing to the public key (rather than to a short hash of it, or not at all) is that it removes the ability for public key recovery or verifying signatures against a short public key hash. These constructions are generally incompatible with batch verification. Schnorr signatures; changing the equation to ''sG = R + H(R || P || m)P''. -'''Encoding the sign of P and the sign of R''' There exist several possibilities for encoding the sign of the public key point: -# Encoding the full X and Y coordinate of P, resulting in a 64-byte public key. -# Encoding the full X coordinate, but only whether Y is even or odd (like compressed public keys). This would result in 33-byte public keys. -# Encoding only the X coordinate, resulting in 32-byte public keys. +'''Encoding R and public key point P''' There exist several possibilities for encoding elliptic curve points: +# Encoding the full X and Y coordinates of ''P'' and ''R'', resulting in a 64-byte public key and a 96-byte signature. +# Encoding the full X coordinate and one bit of the Y coordinate to determine one of the two possible Y coordinates. This would result in 33-byte public keys and 65-byte signatures. +# Encoding only the X coordinate, resulting in 32-byte public keys and 64-byte signatures. -As we chose the ''R''-option above, we're required to encode the point ''R'' into the signature. The possibilities are similar to the encoding of ''P'': -# Encoding the full X and Y coordinate of R, resulting in a 96-byte signature. -# Encoding the full X coordinate, but only whether Y is even or odd (like compressed public keys). This would result in 65-byte signatures. -# Encoding only the X coordinate, leaving us with 64-byte signature. +Using the first option would be slightly more efficient for verification (around 10%), but we prioritize compactness, and therefore choose option 3. -Using the first option for both ''P'' and ''R'' would be slightly more efficient for verification (around 5%), but we prioritize compactness, and therefore choose option 3. - -'''Implicit Y coordinates''' In order to support batch verification, the Y coordinate of ''P'' and of ''R'' cannot be ambiguous (every valid X coordinate has two possible Y coordinates). We have a choice between several options for symmetry breaking: +'''Implicit Y coordinates''' In order to support efficient verification and batch verification, the Y coordinate of ''P'' and of ''R'' cannot be ambiguous (every valid X coordinate has two possible Y coordinates). We have a choice between several options for symmetry breaking: # Implicitly choosing the Y coordinate that is in the lower half. # Implicitly choosing the Y coordinate that is evenSince ''p'' is odd, negation modulo ''p'' will map even numbers to odd numbers and the other way around. This means that for a valid X coordinate, one of the corresponding Y coordinates will be even, and the other will be odd.. # Implicitly choosing the Y coordinate that is a quadratic residue (has a square root modulo the field size)A product of two numbers is a quadratic residue when either both or none of the factors are quadratic residues. As ''-1'' is not a quadratic residue, and the two Y coordinates corresponding to a given X coordinate are each other's negation, this means exactly one of the two must be a quadratic residue.. @@ -80,13 +75,13 @@ In the case of ''R'' the third option is slower at signing time but a bit faster for elliptic curve operations). The two other options require a possibly expensive conversion to affine coordinates first. This would even be the case if the sign or oddness were explicitly coded (option 2 in the previous design choice). We therefore choose option 3. -For ''P'' the speed of signing and verification is not significantly different between any of the three options because affine coordinates of the point have to computed anyway. We therefore choose the same option as for ''R''. The signing algorithm ensures that the signature is valid under the correct public key by negating the secret key if necessary. +For ''P'' the speed of signing and verification does not significantly differ between any of the three options because affine coordinates of the point have to computed anyway. We therefore choose the same option as for ''R''. The signing algorithm ensures that the signature is valid under the correct public key by negating the secret key if necessary. -It is important to not mix up the 32 byte public key format and other existing public key formats. Concretely, a verifier should only accept 32 byte public keys and not, for example, convert a 33 byte public key by throwing away the first byte. Otherwise, two public keys would be valid for a single signature which can result in subtle malleability issues. +It is important to not mix up the 32-byte bip-schnorr public key format and other existing public key formats (e.g. encodings used in Bitcoin's ECDSA). Concretely, a verifier should only accept 32 byte public keys and not, for example, convert a 33 byte public key by throwing away the first byte. Otherwise, two public keys would be valid for a single signature which can result in subtle malleability issues (although this type of malleability already exists in the case of ECDSA signatures). Implicit Y coordinates are not a reduction in security when expressed as the number of elliptic curve operations an attacker is expected to perform to compute the secret key. An attacker can normalize any given public key to a point whose Y coordinate is a quadratic residue by negating the point if necessary. This is just a subtraction of field elements and not an elliptic curve operation. -'''Final scheme''' As a result, our final scheme ends up using public keys ''p'' where ''p'' is the X coordinate of a point ''P'' on the curve whose Y coordinate is a quadratic residue and signatures ''(r,s)'' where ''r'' is the X coordinate of a point ''R'' whose Y coordinate is a quadratic residue. The signature satisfies ''sG = R + H(r || p || m)P''. +'''Final scheme''' As a result, our final scheme ends up using public key ''pk'' which is the X coordinate of a point ''P'' on the curve whose Y coordinate is a quadratic residue and signatures ''(r,s)'' where ''r'' is the X coordinate of a point ''R'' whose Y coordinate is a quadratic residue. The signature satisfies ''sG = R + H(r || p || m)P''. === Specification === diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index a553791..5f8537c 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -65,7 +65,7 @@ In the text below, ''hashtag(m)'' is a shorthand for ''SHA256(SHA256( A Taproot output is a SegWit output (native or P2SH-nested, see [https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki BIP141]) with version number 1, and a 32-byte witness program. The following rules only apply when such an output is being spent. Any other outputs, including version 1 outputs with lengths other than 32 bytes, remain unencumbered. -* Let ''q'' be the 32-byte array containing the witness program (second push in scriptPubKey or P2SH redeemScript) which represents a public key according to bip-schnorr.'''Why is the public key directly included in the output?''' While typical earlier constructions store a hash of a script or a public key in the output, this is rather wasteful when a public key is always involved. To guarantee batch verifiability, ''q'' must be known to every verifier, and thus only revealing its hash as an output would imply adding an additional 32 bytes to the witness. Furthermore, to maintain [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2016-January/012198.html 128-bit collision security] for outputs, a 256-bit hash would be required anyway, which is comparable in size (and thus in cost for senders) to revealing the public key directly. While the usage of public key hashes is often said to protect against ECDLP breaks or quantum computers, this protection is very weak at best: transactions are not protected while being confirmed, and a very [https://twitter.com/pwuille/status/1108097835365339136 large portion] of the currency's supply is not under such protection regardless. Actual resistance to such systems can be introduced by relying on different cryptographic assumptions, but this proposal focuses on improvements that do not change the security model. Note that using P2SH-wrapped outputs only have 80-bit collision security. This is considered low, and is relevant whenever the output includes data from more than a single party (public keys, hashes, ...). . +* Let ''q'' be the 32-byte array containing the witness program (second push in scriptPubKey or P2SH redeemScript) which represents a public key according to bip-schnorr '''Why is the public key directly included in the output?''' While typical earlier constructions store a hash of a script or a public key in the output, this is rather wasteful when a public key is always involved. To guarantee batch verifiability, ''q'' must be known to every verifier, and thus only revealing its hash as an output would imply adding an additional 32 bytes to the witness. Furthermore, to maintain [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2016-January/012198.html 128-bit collision security] for outputs, a 256-bit hash would be required anyway, which is comparable in size (and thus in cost for senders) to revealing the public key directly. While the usage of public key hashes is often said to protect against ECDLP breaks or quantum computers, this protection is very weak at best: transactions are not protected while being confirmed, and a very [https://twitter.com/pwuille/status/1108097835365339136 large portion] of the currency's supply is not under such protection regardless. Actual resistance to such systems can be introduced by relying on different cryptographic assumptions, but this proposal focuses on improvements that do not change the security model. Note that using P2SH-wrapped outputs only have 80-bit collision security. This is considered low, and is relevant whenever the output includes data from more than a single party (public keys, hashes, ...). . * Fail if the witness stack has 0 elements. * If there are at least two witness elements, and the first byte of the last element is 0x50'''Why is the first byte of the annex 0x50?''' Like the 0xc0-0xc1 constants, 0x50 is chosen as it could not be confused with a valid P2WPKH or P2WSH spending. As the control block's initial byte's lowest bit is used to indicate the public key's Y quadratic residuosity, each script version needs two subsequence byte values that are both not yet used in P2WPKH or P2WSH spending. To indicate the annex, only an "unpaired" available byte is necessary like 0x50. This choice maximizes the available options for future script versions., this last element is called ''annex'' ''a'''''What is the purpose of the annex?''' The annex is a reserved space for future extensions, such as indicating the validation costs of computationally expensive new opcodes in a way that is recognizable without knowing the outputs being spent. Until the meaning of this field is defined by another softfork, users SHOULD NOT include annex in transactions, or it may lead to PERMANENT FUND LOSS. and is removed from the witness stack. The annex (or the lack of thereof) is always covered by the transaction digest and contributes to transaction weight, but is otherwise ignored during taproot validation. * If there is exactly one element left in the witness stack, key path spending is used: @@ -87,7 +87,7 @@ The following rules only apply when such an output is being spent. Any other out **** If ''kj ≥ ej'': ''kj+1 = hashTapBranch(ej || kj)''. ** Let ''t = hashTapTweak(bytes(P) || km) = hashTapTweak(2 + (c[0] & 1) || c[1:33] || km)''. ** If ''t ≥ 0xFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141'' (order of secp256k1), fail. -** Let ''Q = point(q) if (c[0] & 1) = 1 and -point(q) otherwise'' +** Let ''Q = point(q) if (c[0] & 1) = 1 and -point(q) otherwise''. Fail if this point is not on the curve. ** If ''Q ≠ P + int(t)G'', fail. ** Execute the script, according to the applicable script rules'''What are the applicable script rules in script path spends?''' Bip-tapscript specifies validity rules that apply if the leaf version is ''0xc0'', but future proposals can introduce rules for other leaf versions., using the witness stack elements excluding the script ''s'', the control block ''c'', and the annex ''a'' if present, as initial stack. @@ -210,7 +210,7 @@ The function taproot_output_script returns a byte array with the sc [[File:bip-taproot/tree.png|frame|This diagram shows the hashing structure to obtain the tweak from an internal key ''P'' and a Merkle tree consisting of 5 script leaves. ''A'', ''B'', ''C'' and ''E'' are ''TapLeaf'' hashes similar to ''D'' and ''AB'' is a ''TapBranch'' hash. Note that when ''CDE'' is computed ''E'' is hashed first because ''E'' is less than ''CD''.]] -'''Spending using the internal key''' A Taproot output can be spent with the private key corresponding to the internal_pubkey. To do so, a witness stack consists of a single element: a bip-schnorr signature on the signature hash as defined above, with the private key tweaked by the same t in the above snippet. In the code below, internal_privkey has a method pubkey_gen that returns a public key according to bip-schnorr and a boolean indicating the quadratic residuosity of the Y coordinate of the underlying point. +'''Spending using the internal key''' A Taproot output can be spent with the private key corresponding to the internal_pubkey. To do so, a witness stack consists of a single element: a bip-schnorr signature on the signature hash as defined above, with the private key tweaked by the same t as in the above snippet. In the code below, internal_privkey has a method pubkey_gen that returns a public key according to bip-schnorr and a boolean indicating the quadratic residuosity of the Y coordinate of the underlying point. See the code below: -- cgit v1.2.3 From 30fdc875993ccaaa7e15f310b79eda79e2f40a7e Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Tue, 20 Aug 2019 10:53:51 +0000 Subject: Update bip-schnorr.mediawiki Co-Authored-By: Tim Ruffing --- bip-schnorr.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 0eb79c4..e3eb187 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -77,7 +77,7 @@ expensive conversion to affine coordinates first. This would even be the case if For ''P'' the speed of signing and verification does not significantly differ between any of the three options because affine coordinates of the point have to computed anyway. We therefore choose the same option as for ''R''. The signing algorithm ensures that the signature is valid under the correct public key by negating the secret key if necessary. -It is important to not mix up the 32-byte bip-schnorr public key format and other existing public key formats (e.g. encodings used in Bitcoin's ECDSA). Concretely, a verifier should only accept 32 byte public keys and not, for example, convert a 33 byte public key by throwing away the first byte. Otherwise, two public keys would be valid for a single signature which can result in subtle malleability issues (although this type of malleability already exists in the case of ECDSA signatures). +It is important to not mix up the 32-byte bip-schnorr public key format and other existing public key formats (e.g. encodings used in Bitcoin's ECDSA). Concretely, a verifier should only accept 32-byte public keys and not, for example, convert a 33-byte public key by throwing away the first byte. Otherwise, two public keys would be valid for a single signature which can result in subtle malleability issues (although this type of malleability already exists in the case of ECDSA signatures). Implicit Y coordinates are not a reduction in security when expressed as the number of elliptic curve operations an attacker is expected to perform to compute the secret key. An attacker can normalize any given public key to a point whose Y coordinate is a quadratic residue by negating the point if necessary. This is just a subtraction of field elements and not an elliptic curve operation. -- cgit v1.2.3 From ae962289131f593f12a77fcae6d90971853c9d25 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Tue, 20 Aug 2019 10:53:58 +0000 Subject: Update bip-schnorr/test-vectors.py Co-Authored-By: Tim Ruffing --- bip-schnorr/test-vectors.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-schnorr/test-vectors.py b/bip-schnorr/test-vectors.py index 5088400..45c8b1c 100644 --- a/bip-schnorr/test-vectors.py +++ b/bip-schnorr/test-vectors.py @@ -30,7 +30,7 @@ def vector2(): msg = bytes_from_int(0x5E2D58D8B3BCDF1ABADEC7829054F90DDA9805AAB56C77333024B9D0A508B75C) sig = schnorr_sign(msg, seckey) - # This signature does not verify vector if the implementer would check the + # This singature vector would not verify if the implementer checked the # jacobi symbol of the X coordinate of R instead of the Y coordinate. R = point_from_bytes(sig[0:32]) assert(jacobi(R[0]) != 1) -- cgit v1.2.3 From 0d28b3c37bbb66543900760634fe6e50718a186a Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Wed, 21 Aug 2019 11:40:42 +0000 Subject: Address sipa's feedback --- bip-schnorr.mediawiki | 7 +++++-- bip-taproot.mediawiki | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index e3eb187..573a678 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -75,7 +75,7 @@ In the case of ''R'' the third option is slower at signing time but a bit faster for elliptic curve operations). The two other options require a possibly expensive conversion to affine coordinates first. This would even be the case if the sign or oddness were explicitly coded (option 2 in the previous design choice). We therefore choose option 3. -For ''P'' the speed of signing and verification does not significantly differ between any of the three options because affine coordinates of the point have to computed anyway. We therefore choose the same option as for ''R''. The signing algorithm ensures that the signature is valid under the correct public key by negating the secret key if necessary. +For ''P'' the speed of signing and verification does not significantly differ between any of the three options because affine coordinates of the point have to be computed anyway. For consistency resons we choose the same option as for ''R''. The signing algorithm ensures that the signature is valid under the correct public key by negating the secret key if necessary. It is important to not mix up the 32-byte bip-schnorr public key format and other existing public key formats (e.g. encodings used in Bitcoin's ECDSA). Concretely, a verifier should only accept 32-byte public keys and not, for example, convert a 33-byte public key by throwing away the first byte. Otherwise, two public keys would be valid for a single signature which can result in subtle malleability issues (although this type of malleability already exists in the case of ECDSA signatures). @@ -118,6 +118,9 @@ Input: The public key corresponding to secret key ''d'' is ''bytes(dG)''. +Alternatively, the public key can be created according to [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki BIP32] which describes the derivation of 33-byte compressed public keys. +In order to translate such public keys into bip-schnorr compatible keys, the first byte must be dropped. + ==== Verification ==== Input: @@ -155,7 +158,7 @@ All provided signatures are valid with overwhelming probability if and only if t ==== Signing ==== Input: -* The secret key ''d' '': an integer in the range ''1..n-1'' chosen uniformly at random. +* The secret key ''d' '': an integer in the range ''1..n-1'' * The message ''m'': a 32-byte array To sign ''m'' for public key ''bytes(dG)'': diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 5f8537c..d9a4cbc 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -85,7 +85,7 @@ The following rules only apply when such an output is being spent. Any other out *** Let ''kj+1 depend on whether ''kj < ej'' (lexicographically)'''Why are child elements sorted before hashing in the Merkle tree?''' By doing so, it is not necessary to reveal the left/right directions along with the hashes in revealed Merkle branches. This is possible because we do not actually care about the position of specific scripts in the tree; only that they are actually committed to.: **** If ''kj < ej'': ''kj+1 = hashTapBranch(kj || ej)'''''Why not use a more efficient hash construction for inner Merkle nodes?''' The chosen construction does require two invocations of the SHA256 compression functions, one of which can be avoided in theory (see BIP98). However, it seems preferable to stick to constructions that can be implemented using standard cryptographic primitives, both for implementation simplicity and analyzability. If necessary, a significant part of the second compression function can be optimized out by [https://github.com/bitcoin/bitcoin/pull/13191 specialization] for 64-byte inputs.. **** If ''kj ≥ ej'': ''kj+1 = hashTapBranch(ej || kj)''. -** Let ''t = hashTapTweak(bytes(P) || km) = hashTapTweak(2 + (c[0] & 1) || c[1:33] || km)''. +** Let ''t = hashTapTweak(bytes(P) || km) = hashTapTweak(c[1:33] || km)''. ** If ''t ≥ 0xFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141'' (order of secp256k1), fail. ** Let ''Q = point(q) if (c[0] & 1) = 1 and -point(q) otherwise''. Fail if this point is not on the curve. ** If ''Q ≠ P + int(t)G'', fail. -- cgit v1.2.3 From ad91099b8f0c21dc889aaec7fc0daf1479e170cf Mon Sep 17 00:00:00 2001 From: John Newbery Date: Sat, 18 May 2019 13:24:23 -0400 Subject: Define c in lift_x(x) --- bip-schnorr.mediawiki | 1 + 1 file changed, 1 insertion(+) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 573a678..2e2c308 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -104,6 +104,7 @@ The following convention is used, with constants as defined for secp256k1: ** The function ''bytes(P)'', where ''P'' is a point, returns ''bytes(x(P))'. ** The function ''int(x)'', where ''x'' is a 32-byte array, returns the 256-bit unsigned integer whose most significant byte encoding is ''x''. ** The function ''lift_x(x)'', where ''x'' is an integer in range ''0..p-1'', returns the point ''P'' for which ''x(P) = x'' and ''y(P)'' is a quadratic residue modulo ''p'', or fails if no such point existsGiven an candidate X coordinate ''x'' in the range ''0..p-1'', there exist either exactly two or exactly zero valid Y coordinates. If no valid Y coordinate exists, then ''x'' is not a valid X coordinate either, i.e., no point ''P'' exists for which ''x(P) = x''. Given a candidate ''x'', the valid Y coordinates are the square roots of ''c = x3 + 7 mod p'' and they can be computed as ''y = ±c(p+1)/4 mod p'' (see [https://en.wikipedia.org/wiki/Quadratic_residue#Prime_or_prime_power_modulus Quadratic residue]) if they exist, which can be checked by squaring and comparing with ''c''. Due to [https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion] it then holds that ''c(p-1)/2 = 1 mod p''. The same criterion applied to ''y'' results in ''y(p-1)/2 mod p = ±c((p+1)/4)((p-1)/2) mod p = ±1 mod p''. Therefore ''y = +c(p+1)/4 mod p'' is a quadratic residue and ''-y mod p'' is not.. The function ''lift_x(x)'' is equivalent to the following pseudocode: +*** Let ''c = x3 + 7 mod p''. *** Let ''y = c(p+1)/4 mod p''. *** Fail if ''c ≠ y2 mod p''. *** Return ''(r, y)''. -- cgit v1.2.3 From a462876b9a3a2c76fd1008cb5302c3335dd4cc87 Mon Sep 17 00:00:00 2001 From: John Newbery Date: Sat, 18 May 2019 13:38:00 -0400 Subject: Return a point from lift_x() --- bip-schnorr.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 2e2c308..ddb1bb0 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -107,7 +107,7 @@ The following convention is used, with constants as defined for secp256k1: *** Let ''c = x3 + 7 mod p''. *** Let ''y = c(p+1)/4 mod p''. *** Fail if ''c ≠ y2 mod p''. -*** Return ''(r, y)''. +*** Return the unique point ''P'' such that ''x(P) = x'' and ''y(P) = y''. ** The function ''point(x)'', where ''x'' is a 32-byte array, returns the point ''P = lift_x(int(x))''. ** The function ''hash(x)'', where ''x'' is a byte array, returns the 32-byte SHA256 hash of ''x''. ** The function ''jacobi(x)'', where ''x'' is an integer, returns the [https://en.wikipedia.org/wiki/Jacobi_symbol Jacobi symbol] of ''x / p''. It is equal to ''x(p-1)/2 mod p'' ([https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion])For points ''P'' on the secp256k1 curve it holds that ''jacobi(y(P)) ≠ 0''.. -- cgit v1.2.3 From 8492968f347d9f004b01fbe7625db0288e7c1b33 Mon Sep 17 00:00:00 2001 From: John Newbery Date: Sat, 18 May 2019 14:05:49 -0400 Subject: Replace 'quadratic residue of...' --- bip-schnorr.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 573a678..43ea9d7 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -70,7 +70,7 @@ Using the first option would be slightly more efficient for verification (around # Implicitly choosing the Y coordinate that is evenSince ''p'' is odd, negation modulo ''p'' will map even numbers to odd numbers and the other way around. This means that for a valid X coordinate, one of the corresponding Y coordinates will be even, and the other will be odd.. # Implicitly choosing the Y coordinate that is a quadratic residue (has a square root modulo the field size)A product of two numbers is a quadratic residue when either both or none of the factors are quadratic residues. As ''-1'' is not a quadratic residue, and the two Y coordinates corresponding to a given X coordinate are each other's negation, this means exactly one of the two must be a quadratic residue.. -In the case of ''R'' the third option is slower at signing time but a bit faster to verify, as the quadratic residue of the Y coordinate can be computed directly for points represented in +In the case of ''R'' the third option is slower at signing time but a bit faster to verify, as it is possible to directly compute whether the Y coordinate is a quadratic residue when the points are represented in [https://en.wikibooks.org/wiki/Cryptography/Prime_Curve/Jacobian_Coordinates Jacobian coordinates] (a common optimization to avoid modular inverses for elliptic curve operations). The two other options require a possibly expensive conversion to affine coordinates first. This would even be the case if the sign or oddness were explicitly coded (option 2 in the previous design choice). We therefore choose option 3. -- cgit v1.2.3 From 16bdfcf534e7beabcb0c177694364b38b662c2b0 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Mon, 19 Aug 2019 14:45:34 +0000 Subject: Use key path spend terminology more consistently in taproot/tapscript --- bip-taproot.mediawiki | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 527e1bc..b2d45a3 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -210,11 +210,11 @@ The function taproot_output_script returns a byte array with the sc [[File:bip-taproot/tree.png|frame|This diagram shows the hashing structure to obtain the tweak from an internal key ''P'' and a Merkle tree consisting of 5 script leaves. ''A'', ''B'', ''C'' and ''E'' are ''TapLeaf'' hashes similar to ''D'' and ''AB'' is a ''TapBranch'' hash. Note that when ''CDE'' is computed ''E'' is hashed first because ''E'' is less than ''CD''.]] -'''Spending using the internal key''' A Taproot output can be spent with the private key corresponding to the internal_pubkey. To do so, a witness stack consists of a single element: a bip-schnorr signature on the signature hash as defined above, with the private key tweaked by the same t as in the above snippet. In the code below, internal_privkey has a method pubkey_gen that returns a public key according to bip-schnorr and a boolean indicating the quadratic residuosity of the Y coordinate of the underlying point. +'''Spending using the key path''' A Taproot output can be spent with the private key corresponding to the internal_pubkey. To do so, a witness stack consists of a single element: a bip-schnorr signature on the signature hash as defined above, with the private key tweaked by the same t as in the above snippet. In the code below, internal_privkey has a method pubkey_gen that returns a public key according to bip-schnorr and a boolean indicating the quadratic residuosity of the Y coordinate of the underlying point. See the code below: -def taproot_sign_internal_key(script_tree, internal_privkey, hash_type): +def taproot_sign_key(script_tree, internal_privkey, hash_type): internal_pubkey, is_y_qresidue = internal_privkey.pubkey_gen() if is_y_qresidue: internal_privkey = internal_privkey.negate() -- cgit v1.2.3 From ed0bb5b0c2b51a1ce0361a5539b58da47cc1dd9e Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Wed, 5 Jun 2019 13:59:09 +0000 Subject: Prescribe that a taproot output key should always have a taproot commitment --- bip-taproot.mediawiki | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 527e1bc..6b3cb38 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -171,6 +171,18 @@ Satisfying any of these conditions is sufficient to spend the output. * When deciding between scripts with conditionals (OP_IF etc.) and splitting them up into multiple scripts (each corresponding to one execution path through the original script), it is generally preferable to pick the latter. * When a single condition requires signatures with multiple keys, key aggregation techniques like MuSig can be used to combine them into a single key. The details are out of scope for this document, but note that this may complicate the signing procedure. * If one or more of the spending conditions consist of just a single key (after aggregation), the most likely one should be made the internal key. If no such condition exists, it may be worthwhile adding one that consists of an aggregation of all keys participating in all scripts combined; effectively adding an "everyone agrees" branch. If that is inacceptable, pick as internal key a point with unknown discrete logarithm. One example of such a point is ''H = point(0x0250929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0)'' which is [https://github.com/ElementsProject/secp256k1-zkp/blob/11af7015de624b010424273be3d91f117f172c82/src/modules/rangeproof/main_impl.h#L16 constructed] by taking the hash of the standard uncompressed encoding of secp256k1 generator ''G'' as X coordinate. In order to avoid leaking the information that key path spending is not possible it is recommended to pick a fresh integer ''r'' in the range ''0...n-1'' uniformly at random and use ''H + rG'' as internal key. It is possible to prove that this internal key is does not have a known discrete logarithm with respect to ''G'' by revealing ''r'' to a verifier who can then reconstruct how the internal key was created. +* If the spending conditions do not require a script path, the output key should commit to an unspendable script path instead of having no script path. This can be achieved by computing the output key point as ''Q = P + int(hashTapTweak(bytes(P)))G''. '''Why should the output key always have a taproot commitment, even if there is no script path?''' +If the taproot output key is an aggregate of keys, there is the possibility for a malicious party to add a script path without being noticed by the other parties. +This allows to bypass the multiparty policy and to steal the coin. +MuSig key aggregation does not have this issue because it already causes the internal key to be randomized. + +The attack works as follows: Assume Alice and Mallory want to aggregate their keys into a taproot output key without a script path. +In order to prevent key cancellation and related attacks they use [https://eprint.iacr.org/2018/483.pdf MSDL-pop] instead of MuSig. +The MSDL-pop protocol requires all parties to provide a proof of possession of their corresponding private key and the aggregated key is just the sum of the individual keys. +After Mallory receives Alice's key ''A'', Mallory creates ''M = M0 + int(t)G'' where ''M0'' is Mallory's original key and ''t'' allows a script path spend with internal key ''P = A + M0'' and a script that only contains Mallory's key. +Mallory sends a proof of possession of ''M'' to Alice and both parties compute output key ''Q = A + M = P + int(t)G''. +Alice will not be able to notice the script path, but Mallory can unilaterally spend any coin with output key ''Q''. + * The remaining scripts should be organized into the leaves of a binary tree. This can be a balanced tree if each of the conditions these scripts correspond to are equally likely. If probabilities for each condition are known, consider constructing the tree as a Huffman tree. '''Computing the output script''' Once the spending conditions are split into an internal key internal_pubkey and a binary tree whose leaves are (leaf_version, script) tuples, the following Python3 algorithm can be used to compute the output script. In the code below, ser_script prefixes its input with a CCompactSize-encoded length. Public key objects hold 32-byte public keys according to bip-schnorr, have a method get_bytes to get the byte array and a method tweak_add which returns a new public key corresponding to the sum of the public key point and a multiple of the secp256k1 generator (similar to BIP32's derivation). The second return value of tweak_add is a boolean indicating the quadratic residuosity of the Y coordinate of the resulting point. @@ -199,7 +211,11 @@ def taproot_output_script(internal_pubkey, script_tree): script_tree is either: - a (leaf_version, script) tuple (leaf_version is 0xc0 for bip-tapscript scripts) - a list of two elements, each with the same structure as script_tree itself""" - _, h = taproot_tree_helper(script_tree) + - None + if script_tree is None: + h = b'' + else: + _, h = taproot_tree_helper(script_tree) t = tagged_hash("TapTweak", internal_pubkey.get_bytes() + h) assert int.from_bytes(t, 'big') < SECP256K1_ORDER output_pubkey, _ = internal_pubkey.tweak_add(t) -- cgit v1.2.3 From 7cd53f6eec269c607605af6163eb1a8858ed79e1 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Mon, 26 Aug 2019 11:32:04 +0000 Subject: Use a tagged hash in bip-schnorr nonce derivation --- bip-schnorr.mediawiki | 7 ++++++- bip-schnorr/reference.py | 6 +++++- bip-taproot.mediawiki | 19 ++----------------- 3 files changed, 13 insertions(+), 19 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 561ff6f..8781f2c 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -110,6 +110,11 @@ The following convention is used, with constants as defined for secp256k1: *** Return the unique point ''P'' such that ''x(P) = x'' and ''y(P) = y''. ** The function ''point(x)'', where ''x'' is a 32-byte array, returns the point ''P = lift_x(int(x))''. ** The function ''hash(x)'', where ''x'' is a byte array, returns the 32-byte SHA256 hash of ''x''. +** The function ''hashtag(x)'' is a shorthand for ''hash(hash(tag) || hash(tag) || x)'', where ''tag'' is a UTF-8 encoded tag name.Cryptographic hash functions are used for multiple purposes in the specification below and in Bitcoin in general. To make sure hashes used in one context can't be reinterpreted in another one, hash functions can be tweaked with a context-dependent tag name, in such a way that collisions across contexts can be assumed to be infeasible. + +* So far, nowhere in the Bitcoin protocol are hashes used where the input of SHA256 starts with two (non-double) SHA256 hashes, making collisions with existing uses of hash functions infeasible. +* Because the prefix ''SHA256(tag) || SHA256(tag)'' is a 64-byte long context-specific constant, optimized implementations are possible (identical to SHA256 itself, but with a modified initial state). +* Using SHA256 of the tag name itself is reasonably simple and efficient for implementations that don't choose to use the optimization above. ** The function ''jacobi(x)'', where ''x'' is an integer, returns the [https://en.wikipedia.org/wiki/Jacobi_symbol Jacobi symbol] of ''x / p''. It is equal to ''x(p-1)/2 mod p'' ([https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion])For points ''P'' on the secp256k1 curve it holds that ''jacobi(y(P)) ≠ 0''.. === Public Key Generation === @@ -165,7 +170,7 @@ Input: To sign ''m'' for public key ''bytes(dG)'': * Let ''P = dG'' * Let ''d = d' '' if ''jacobi(y(P)) = 1'', otherwise let ''d = n - d' ''. -* Let ''k' = int(hash(bytes(d) || m)) mod n''Note that in general, taking the output of a hash function modulo the curve order will produce an unacceptably biased result. However, for the secp256k1 curve, the order is sufficiently close to ''2256'' that this bias is not observable (''1 - n / 2256'' is around ''1.27 * 2-128'').. +* Let ''k' = int(hashBIPSchnorrDerive(bytes(d) || m)) mod n''Note that in general, taking the output of a hash function modulo the curve order will produce an unacceptably biased result. However, for the secp256k1 curve, the order is sufficiently close to ''2256'' that this bias is not observable (''1 - n / 2256'' is around ''1.27 * 2-128'').. * Fail if ''k' = 0''. * Let ''R = k'G''. * Let ''k = k' '' if ''jacobi(y(R)) = 1'', otherwise let ''k = n - k' ''. diff --git a/bip-schnorr/reference.py b/bip-schnorr/reference.py index f89b3c4..4f0d1df 100644 --- a/bip-schnorr/reference.py +++ b/bip-schnorr/reference.py @@ -5,6 +5,10 @@ p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F n = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 G = (0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798, 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8) +def tagged_hash(tag, msg): + tag_hash = hashlib.sha256(tag.encode()).digest() + return hashlib.sha256(tag_hash + tag_hash + msg).digest() + def point_add(P1, P2): if (P1 is None): return P2 @@ -61,7 +65,7 @@ def schnorr_sign(msg, seckey0): raise ValueError('The secret key must be an integer in the range 1..n-1.') P = point_mul(G, seckey0) seckey = seckey0 if (jacobi(P[1]) == 1) else n - seckey0 - k0 = int_from_bytes(hash_sha256(bytes_from_int(seckey) + msg)) % n + k0 = int_from_bytes(tagged_hash("BIPSchnorrDerive", bytes_from_int(seckey) + msg)) % n if k0 == 0: raise RuntimeError('Failure. This happens only with negligible probability.') R = point_mul(G, k0) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index b2d45a3..51fd45d 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -49,16 +49,7 @@ Not included in this proposal are additional features like new sighash modes or This section specifies the Taproot consensus rules. Validity is defined by exclusion: a block or transaction is valid if no condition exists that marks it failed. -The notation below follows that of bip-schnorr. - -=== Tagged hashes === - -Cryptographic hash functions are used for multiple purposes in the specification below and in Bitcoin in general. To make sure hashes used in one context can't be reinterpreted in another one, all hash functions are tweaked with a context-dependent tag name, in such a way that collisions across contexts can be assumed to be infeasible. - -In the text below, ''hashtag(m)'' is a shorthand for ''SHA256(SHA256(tag) || SHA256(tag) || m)'', where ''tag'' is a UTF-8 encoded tag name. -* So far, nowhere in the Bitcoin protocol are hashes used where the input of SHA256 starts with two (non-double) SHA256 hashes, making collisions with existing uses of hash functions infeasible. -* Because the prefix ''SHA256(tag) || SHA256(tag)'' is a 64-byte long context-specific constant, optimized implementations are possible (identical to SHA256 itself, but with a modified initial state). -* Using SHA256 of the tag name itself is reasonably simple and efficient for implementations that don't choose to use the optimization above. +The notation below follows that of bip-schnorr including the notion of tagged hashes. === Script validation rules === @@ -173,15 +164,9 @@ Satisfying any of these conditions is sufficient to spend the output. * If one or more of the spending conditions consist of just a single key (after aggregation), the most likely one should be made the internal key. If no such condition exists, it may be worthwhile adding one that consists of an aggregation of all keys participating in all scripts combined; effectively adding an "everyone agrees" branch. If that is inacceptable, pick as internal key a point with unknown discrete logarithm. One example of such a point is ''H = point(0x0250929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0)'' which is [https://github.com/ElementsProject/secp256k1-zkp/blob/11af7015de624b010424273be3d91f117f172c82/src/modules/rangeproof/main_impl.h#L16 constructed] by taking the hash of the standard uncompressed encoding of secp256k1 generator ''G'' as X coordinate. In order to avoid leaking the information that key path spending is not possible it is recommended to pick a fresh integer ''r'' in the range ''0...n-1'' uniformly at random and use ''H + rG'' as internal key. It is possible to prove that this internal key is does not have a known discrete logarithm with respect to ''G'' by revealing ''r'' to a verifier who can then reconstruct how the internal key was created. * The remaining scripts should be organized into the leaves of a binary tree. This can be a balanced tree if each of the conditions these scripts correspond to are equally likely. If probabilities for each condition are known, consider constructing the tree as a Huffman tree. -'''Computing the output script''' Once the spending conditions are split into an internal key internal_pubkey and a binary tree whose leaves are (leaf_version, script) tuples, the following Python3 algorithm can be used to compute the output script. In the code below, ser_script prefixes its input with a CCompactSize-encoded length. Public key objects hold 32-byte public keys according to bip-schnorr, have a method get_bytes to get the byte array and a method tweak_add which returns a new public key corresponding to the sum of the public key point and a multiple of the secp256k1 generator (similar to BIP32's derivation). The second return value of tweak_add is a boolean indicating the quadratic residuosity of the Y coordinate of the resulting point. +'''Computing the output script''' Once the spending conditions are split into an internal key internal_pubkey and a binary tree whose leaves are (leaf_version, script) tuples, the following Python3 algorithm can be used to compute the output script. In the code below, ser_script prefixes its input with a CCompactSize-encoded length. Public key objects hold 32-byte public keys according to bip-schnorr, have a method get_bytes to get the byte array and a method tweak_add which returns a new public key corresponding to the sum of the public key point and a multiple of the secp256k1 generator (similar to BIP32's derivation). The second return value of tweak_add is a boolean indicating the quadratic residuosity of the Y coordinate of the resulting point. tagged_hash computes the tagged hash according to bip-schnorr. -import hashlib - -def tagged_hash(tag, msg): - tag_hash = hashlib.sha256(tag.encode()).digest() - return hashlib.sha256(tag_hash + tag_hash + msg).digest() - def taproot_tree_helper(script_tree): if isinstance(script_tree, tuple): leaf_version, script = script_tree -- cgit v1.2.3 From 775cb2fd903cbfe459081fda49ada744ef3139be Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Mon, 26 Aug 2019 20:46:08 +0000 Subject: Tag signature hashes, improve rationale and update test vectors --- bip-schnorr.mediawiki | 29 +++++++++++++++-------------- bip-schnorr/reference.py | 6 ++++-- bip-schnorr/test-vectors.csv | 28 ++++++++++++++-------------- bip-schnorr/test-vectors.py | 4 ++-- bip-taproot.mediawiki | 6 ++++-- 5 files changed, 39 insertions(+), 34 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 8781f2c..ad0b9cf 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -50,13 +50,13 @@ encodings and operations. === Design === -'''Schnorr signature variant''' Elliptic Curve Schnorr signatures for message ''m'' and public key ''P'' generally involve a point ''R'', integers ''e'' and ''s'' picked by the signer, and generator ''G'' which satisfy ''e = H(R || m)'' and ''sG = R + eP''. Two formulations exist, depending on whether the signer reveals ''e'' or ''R'': -# Signatures are ''(e,s)'' that satisfy ''e = H(sG - eP || m)''. This avoids minor complexity introduced by the encoding of the point ''R'' in the signature (see paragraphs "Encoding the sign of R" and "Implicit Y coordinate" further below in this subsection). -# Signatures are ''(R,s)'' that satisfy ''sG = R + H(R || m)P''. This supports batch verification, as there are no elliptic curve operations inside the hashes. +'''Schnorr signature variant''' Elliptic Curve Schnorr signatures for message ''m'' and public key ''P'' generally involve a point ''R'', integers ''e'' and ''s'' picked by the signer, and generator ''G'' which satisfy ''e = hash(R || m)'' and ''sG = R + eP''. Two formulations exist, depending on whether the signer reveals ''e'' or ''R'': +# Signatures are ''(e,s)'' that satisfy ''e = hash(sG - eP || m)''. This avoids minor complexity introduced by the encoding of the point ''R'' in the signature (see paragraphs "Encoding the sign of R" and "Implicit Y coordinate" further below in this subsection). +# Signatures are ''(R,s)'' that satisfy ''sG = R + hash(R || m)P''. This supports batch verification, as there are no elliptic curve operations inside the hashes. We choose the ''R''-option to support batch verification. -'''Key prefixing''' When using the verification rule above directly, it is possible for a third party to convert a signature ''(R,s)'' for key ''P'' into a signature ''(R,s + aH(R || m))'' for key ''P + aG'' and the same message, for any integer ''a''. This is not a concern for Bitcoin currently, as all signature hashes indirectly commit to the public keys. However, this may change with proposals such as SIGHASH_NOINPUT ([https://github.com/bitcoin/bips/blob/master/bip-0118.mediawiki BIP 118]), or when the signature scheme is used for other purposes—especially in combination with schemes like [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki BIP32]'s unhardened derivation. To combat this, we choose ''key prefixed''A limitation of committing to the public key (rather than to a short hash of it, or not at all) is that it removes the ability for public key recovery or verifying signatures against a short public key hash. These constructions are generally incompatible with batch verification. Schnorr signatures; changing the equation to ''sG = R + H(R || P || m)P''. +'''Key prefixing''' When using the verification rule above directly, it is possible for a third party to convert a signature ''(R,s)'' for key ''P'' into a signature ''(R,s + ahash(R || m))'' for key ''P + aG'' and the same message, for any integer ''a''. This is not a concern for Bitcoin currently, as all signature hashes indirectly commit to the public keys. However, this may change with proposals such as SIGHASH_NOINPUT ([https://github.com/bitcoin/bips/blob/master/bip-0118.mediawiki BIP 118]), or when the signature scheme is used for other purposes—especially in combination with schemes like [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki BIP32]'s unhardened derivation. To combat this, we choose ''key prefixed''A limitation of committing to the public key (rather than to a short hash of it, or not at all) is that it removes the ability for public key recovery or verifying signatures against a short public key hash. These constructions are generally incompatible with batch verification. Schnorr signatures; changing the equation to ''sG = R + hash(R || P || m)P''. '''Encoding R and public key point P''' There exist several possibilities for encoding elliptic curve points: # Encoding the full X and Y coordinates of ''P'' and ''R'', resulting in a 64-byte public key and a 96-byte signature. @@ -81,7 +81,13 @@ It is important to not mix up the 32-byte bip-schnorr public key format and othe Implicit Y coordinates are not a reduction in security when expressed as the number of elliptic curve operations an attacker is expected to perform to compute the secret key. An attacker can normalize any given public key to a point whose Y coordinate is a quadratic residue by negating the point if necessary. This is just a subtraction of field elements and not an elliptic curve operation. -'''Final scheme''' As a result, our final scheme ends up using public key ''pk'' which is the X coordinate of a point ''P'' on the curve whose Y coordinate is a quadratic residue and signatures ''(r,s)'' where ''r'' is the X coordinate of a point ''R'' whose Y coordinate is a quadratic residue. The signature satisfies ''sG = R + H(r || p || m)P''. +'''Tagged Hashes''' Cryptographic hash functions are used for multiple purposes in the specification below and in Bitcoin in general. To make sure hashes used in one context can't be reinterpreted in another one, hash functions can be tweaked with a context-dependent tag name, in such a way that collisions across contexts can be assumed to be infeasible. Such collisions obviously can not be ruled out completely, but only for schemes using tagging with a unique name. As for other schemes collisions are at least less likely with tagging than without. + +For example, without tagged hashing a bip-schnorr signature could also be valid for a signature scheme where the only difference is that the arguments to the hash function are reordered. Worse, if the bip-schnorr nonce derivation function was copied or independently created, then the nonce could be accidentally reused in the other scheme leaking the private key. + +This proposal suggests to include the tag by prefixing the hashed data with ''SHA256(tag) || SHA256(tag)''. Because this is a 64-byte long context-specific constant, optimized implementations are possible (identical to SHA256 itself, but with a modified initial state). Using SHA256 of the tag name itself is reasonably simple and efficient for implementations that don't choose to use the optimization. + +'''Final scheme''' As a result, our final scheme ends up using public key ''pk'' which is the X coordinate of a point ''P'' on the curve whose Y coordinate is a quadratic residue and signatures ''(r,s)'' where ''r'' is the X coordinate of a point ''R'' whose Y coordinate is a quadratic residue. The signature satisfies ''sG = R + tagged_hash(r || p || m)P''. === Specification === @@ -109,12 +115,7 @@ The following convention is used, with constants as defined for secp256k1: *** Fail if ''c ≠ y2 mod p''. *** Return the unique point ''P'' such that ''x(P) = x'' and ''y(P) = y''. ** The function ''point(x)'', where ''x'' is a 32-byte array, returns the point ''P = lift_x(int(x))''. -** The function ''hash(x)'', where ''x'' is a byte array, returns the 32-byte SHA256 hash of ''x''. -** The function ''hashtag(x)'' is a shorthand for ''hash(hash(tag) || hash(tag) || x)'', where ''tag'' is a UTF-8 encoded tag name.Cryptographic hash functions are used for multiple purposes in the specification below and in Bitcoin in general. To make sure hashes used in one context can't be reinterpreted in another one, hash functions can be tweaked with a context-dependent tag name, in such a way that collisions across contexts can be assumed to be infeasible. - -* So far, nowhere in the Bitcoin protocol are hashes used where the input of SHA256 starts with two (non-double) SHA256 hashes, making collisions with existing uses of hash functions infeasible. -* Because the prefix ''SHA256(tag) || SHA256(tag)'' is a 64-byte long context-specific constant, optimized implementations are possible (identical to SHA256 itself, but with a modified initial state). -* Using SHA256 of the tag name itself is reasonably simple and efficient for implementations that don't choose to use the optimization above. +** The function ''hashtag(x)'' where ''tag'' is a UTF-8 encoded tag name and ''x'' is a byte array returns the 32-byte hash ''SHA256(SHA256(tag) || SHA256(tag) || x)''. ** The function ''jacobi(x)'', where ''x'' is an integer, returns the [https://en.wikipedia.org/wiki/Jacobi_symbol Jacobi symbol] of ''x / p''. It is equal to ''x(p-1)/2 mod p'' ([https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion])For points ''P'' on the secp256k1 curve it holds that ''jacobi(y(P)) ≠ 0''.. === Public Key Generation === @@ -138,7 +139,7 @@ The signature is valid if and only if the algorithm below does not fail. * Let ''P = point(pk)''; fail if ''point(pk)'' fails. * Let ''r = int(sig[0:32])''; fail if ''r ≥ p''. * Let ''s = int(sig[32:64])''; fail if ''s ≥ n''. -* Let ''e = int(hash(bytes(r) || bytes(P) || m)) mod n''. +* Let ''e = int(hashBIPSchnorr(bytes(r) || bytes(P) || m)) mod n''. * Let ''R = sG - eP''. * Fail if ''infinite(R)''. * Fail if ''jacobi(y(R)) ≠ 1'' or ''x(R) ≠ r''. @@ -157,7 +158,7 @@ All provided signatures are valid with overwhelming probability if and only if t ** Let ''Pi = point(pki)''; fail if ''point(pki)'' fails. ** Let ''r = int(sigi[0:32])''; fail if ''r ≥ p''. ** Let ''si = int(sigi[32:64])''; fail if ''si ≥ n''. -** Let ''ei = int(hash(bytes(r) || bytes(Pi) || mi)) mod n''. +** Let ''ei = int(hashBIPSchnorr(bytes(r) || bytes(Pi) || mi)) mod n''. ** Let ''Ri = lift_x(r)''; fail if ''lift_x(r)'' fails. * Fail if ''(s1 + a2s2 + ... + ausu)G ≠ R1 + a2R2 + ... + auRu + e1P1 + (a2e2)P2 + ... + (aueu)Pu''. @@ -174,7 +175,7 @@ To sign ''m'' for public key ''bytes(dG)'': * Fail if ''k' = 0''. * Let ''R = k'G''. * Let ''k = k' '' if ''jacobi(y(R)) = 1'', otherwise let ''k = n - k' ''. -* Let ''e = int(hash(bytes(R) || bytes(P) || m)) mod n''. +* Let ''e = int(hashBIPSchnorr(bytes(R) || bytes(P) || m)) mod n''. * The signature is ''bytes(R) || bytes((k + ed) mod n)''. '''Above deterministic derivation of ''R'' is designed specifically for this signing algorithm and may not be secure when used in other signature schemes.''' diff --git a/bip-schnorr/reference.py b/bip-schnorr/reference.py index 4f0d1df..95e9e53 100644 --- a/bip-schnorr/reference.py +++ b/bip-schnorr/reference.py @@ -5,6 +5,8 @@ p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F n = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 G = (0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798, 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8) +# This implementation can be sped up by storing the midstate after hashing +# tag_hash instead of rehashing it all the time. def tagged_hash(tag, msg): tag_hash = hashlib.sha256(tag.encode()).digest() return hashlib.sha256(tag_hash + tag_hash + msg).digest() @@ -70,7 +72,7 @@ def schnorr_sign(msg, seckey0): raise RuntimeError('Failure. This happens only with negligible probability.') R = point_mul(G, k0) k = n - k0 if (jacobi(R[1]) != 1) else k0 - e = int_from_bytes(hash_sha256(bytes_from_point(R) + bytes_from_point(P) + msg)) % n + e = int_from_bytes(tagged_hash("BIPSchnorr", bytes_from_point(R) + bytes_from_point(P) + msg)) % n return bytes_from_point(R) + bytes_from_int((k + e * seckey) % n) def schnorr_verify(msg, pubkey, sig): @@ -87,7 +89,7 @@ def schnorr_verify(msg, pubkey, sig): s = int_from_bytes(sig[32:64]) if (r >= p or s >= n): return False - e = int_from_bytes(hash_sha256(sig[0:32] + pubkey + msg)) % n + e = int_from_bytes(tagged_hash("BIPSchnorr", sig[0:32] + pubkey + msg)) % n R = point_add(point_mul(G, s), point_mul(P, n - e)) if R is None or jacobi(R[1]) != 1 or R[0] != r: return False diff --git a/bip-schnorr/test-vectors.csv b/bip-schnorr/test-vectors.csv index 3e17669..7ca6600 100644 --- a/bip-schnorr/test-vectors.csv +++ b/bip-schnorr/test-vectors.csv @@ -1,15 +1,15 @@ index,secret key,public key,message,signature,verification result,comment -0,0000000000000000000000000000000000000000000000000000000000000001,79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798,0000000000000000000000000000000000000000000000000000000000000000,787A848E71043D280C50470E8E1532B2DD5D20EE912A45DBDD2BD1DFBF187EF6166FCCEE14F021B31AF22A90D0639CC010C2B764C304A8FFF266ABBC01A0A880,TRUE, -1,B7E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEF,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,3C4D3ADB1F05C3E948216ECB6007D1534D97D35D5589EDB226AD0370C0293C780AEA9BA361509DA2FDF7BC6E5E38926E40B6ACCD24EA9E06B9DA8244A1D0B691,TRUE, -2,C90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B14E5C7,FAC2114C2FBB091527EB7C64ECB11F8021CB45E8E7809D3C0938E4B8C0E5F84B,5E2D58D8B3BCDF1ABADEC7829054F90DDA9805AAB56C77333024B9D0A508B75C,33380A613013115518CD6030ABC8220B2DED273FD3ABD13DF0882DC6A928E5AFAC72DF3248F8FAC522EF1A819EE5EE5BEA81D92D0E19A6FAB228E5D1D61BF833,TRUE, -3,0B432B2677937381AEF05BB02A66ECD012773062CF3FA2549E44F58ED2401710,25D1DFF95105F5253C4022F628A996AD3A0D95FBF21D468A1B33F8C160D8F517,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,7C4E8B0C2575A77A01AF41EE6678EF9C41F97CC4D15FF6D6CA45D73BC6FF7FF4919D246589AF2FA6306F4B7A392857E9C4A17CB21DBE72C38A48C99979EEDCB8,TRUE,test fails if msg is reduced modulo p or n -4,,D69C3509BB99E412E68B0FE8544E72837DFA30746D8BE2AA65975F29D22DC7B9,4DF3C3F68FCC83B27E9D42C90431A72499F17875C81A599B566C9889B9696703,00000000000000000000003B78CE563F89A0ED9414F5AA28AD0D96D6795F9C63F84A709CFFD89AD94FCBD808D41BD26BF62F263AA253527134DDC4A4715BF491,TRUE, -5,,EEFDEA4CDB677750A420FEE807EACF21EB9898AE79B9768766E4FAA04A2D4A34,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,3C4D3ADB1F05C3E948216ECB6007D1534D97D35D5589EDB226AD0370C0293C780AEA9BA361509DA2FDF7BC6E5E38926E40B6ACCD24EA9E06B9DA8244A1D0B691,FALSE,public key not on the curve -6,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F98631F4EF21D5F231A1000ED069E0348ED057EDF4FB1B6672009EDE9DBB2DEE14,FALSE,incorrect R residuosity -7,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,07636CBE3092D11AFCA4DD1D32E50F039EB5FF5FB2AB72A7DC2BA0F3A4E7ED418C312ED6ABF6A41446D28789DF4AA43A15E166F001D072536ADC6E49C21DC419,FALSE,negated message -8,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,3C4D3ADB1F05C3E948216ECB6007D1534D97D35D5589EDB226AD0370C0293C78F515645C9EAF625D02084391A1C76D9079F830198A5E023505F7DC482E658AB0,FALSE,negated s value -9,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,0000000000000000000000000000000000000000000000000000000000000000221A96FEEBA7AD29F11B675DB394948A83A220FD8FE181A7667BDBEE178011B1,FALSE,sG - eP is infinite. Test fails in single verification if jacobi(y(inf)) is defined as 1 and x(inf) as 0 -10,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,00000000000000000000000000000000000000000000000000000000000000011A39648F31350D8E591106B43B9EB364F8617BCD52DC96A3FA8C4E50347F31DE,FALSE,sG - eP is infinite. Test fails in single verification if jacobi(y(inf)) is defined as 1 and x(inf) as 1 -11,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,4A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1D0AEA9BA361509DA2FDF7BC6E5E38926E40B6ACCD24EA9E06B9DA8244A1D0B691,FALSE,sig[0:32] is not an X coordinate on the curve -12,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F0AEA9BA361509DA2FDF7BC6E5E38926E40B6ACCD24EA9E06B9DA8244A1D0B691,FALSE,sig[0:32] is equal to field size -13,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,3C4D3ADB1F05C3E948216ECB6007D1534D97D35D5589EDB226AD0370C0293C78FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141,FALSE,sig[32:64] is equal to curve order +0,0000000000000000000000000000000000000000000000000000000000000001,79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798,0000000000000000000000000000000000000000000000000000000000000000,528F745793E8472C0329742A463F59E58F3A3F1A4AC09C28F6F8514D4D0322A258BD08398F82CF67B812AB2C7717CE566F877C2F8795C846146978E8F04782AE,TRUE, +1,B7E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEF,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,667C2F778E0616E611BD0C14B8A600C5884551701A949EF0EBFD72D452D64E844160BCFC3F466ECB8FACD19ADE57D8699D74E7207D78C6AEDC3799B52A8E0598,TRUE, +2,C90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B14E5C9,DD308AFEC5777E13121FA72B9CC1B7CC0139715309B086C960E18FD969774EB8,5E2D58D8B3BCDF1ABADEC7829054F90DDA9805AAB56C77333024B9D0A508B75C,2D941B38E32624BF0AC7669C0971B990994AF6F9B18426BF4F4E7EC10E6CDF386CF646C6DDAFCFA7F1993EEB2E4D66416AEAD1DDAE2F22D63CAD901412D116C6,TRUE, +3,0B432B2677937381AEF05BB02A66ECD012773062CF3FA2549E44F58ED2401710,25D1DFF95105F5253C4022F628A996AD3A0D95FBF21D468A1B33F8C160D8F517,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,8BD2C11604B0A87A443FCC2E5D90E5328F934161B18864FB48CE10CB59B45FB9B5B2A0F129BD88F5BDC05D5C21E5C57176B913002335784F9777A24BD317CD36,TRUE,test fails if msg is reduced modulo p or n +4,,D69C3509BB99E412E68B0FE8544E72837DFA30746D8BE2AA65975F29D22DC7B9,4DF3C3F68FCC83B27E9D42C90431A72499F17875C81A599B566C9889B9696703,00000000000000000000003B78CE563F89A0ED9414F5AA28AD0D96D6795F9C63EE374AC7FAE927D334CCB190F6FB8FD27A2DDC639CCEE46D43F113A4035A2C7F,TRUE, +5,,EEFDEA4CDB677750A420FEE807EACF21EB9898AE79B9768766E4FAA04A2D4A34,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,667C2F778E0616E611BD0C14B8A600C5884551701A949EF0EBFD72D452D64E844160BCFC3F466ECB8FACD19ADE57D8699D74E7207D78C6AEDC3799B52A8E0598,FALSE,public key not on the curve +6,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9935554D1AA5F0374E5CDAACB3925035C7C169B27C4426DF0A6B19AF3BAEAB138,FALSE,incorrect R residuosity +7,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,10AC49A6A2EBF604189C5F40FC75AF2D42D77DE9A2782709B1EB4EAF1CFE9108D7003B703A3499D5E29529D39BA040A44955127140F81A8A89A96F992AC0FE79,FALSE,negated message +8,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,667C2F778E0616E611BD0C14B8A600C5884551701A949EF0EBFD72D452D64E84BE9F4303C0B9913470532E6521A827951D39F5C631CFD98CE39AC4D7A5A83BA9,FALSE,negated s value +9,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,000000000000000000000000000000000000000000000000000000000000000099D2F0EBC2996808208633CD9926BF7EC3DAB73DAAD36E85B3040A698E6D1CE0,FALSE,sG - eP is infinite. Test fails in single verification if jacobi(y(inf)) is defined as 1 and x(inf) as 0 +10,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,000000000000000000000000000000000000000000000000000000000000000124E81D89F01304695CE943F7D5EBD00EF726A0864B4FF33895B4E86BEADC5456,FALSE,sG - eP is infinite. Test fails in single verification if jacobi(y(inf)) is defined as 1 and x(inf) as 1 +11,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,4A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1D4160BCFC3F466ECB8FACD19ADE57D8699D74E7207D78C6AEDC3799B52A8E0598,FALSE,sig[0:32] is not an X coordinate on the curve +12,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F4160BCFC3F466ECB8FACD19ADE57D8699D74E7207D78C6AEDC3799B52A8E0598,FALSE,sig[0:32] is equal to field size +13,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,667C2F778E0616E611BD0C14B8A600C5884551701A949EF0EBFD72D452D64E84FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141,FALSE,sig[32:64] is equal to curve order diff --git a/bip-schnorr/test-vectors.py b/bip-schnorr/test-vectors.py index 45c8b1c..52e3b05 100644 --- a/bip-schnorr/test-vectors.py +++ b/bip-schnorr/test-vectors.py @@ -26,7 +26,7 @@ def vector1(): return (bytes_from_int(seckey), pubkey, msg, sig, "TRUE", None) def vector2(): - seckey = 0xC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B14E5C7 + seckey = 0xC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B14E5C9 msg = bytes_from_int(0x5E2D58D8B3BCDF1ABADEC7829054F90DDA9805AAB56C77333024B9D0A508B75C) sig = schnorr_sign(msg, seckey) @@ -53,7 +53,7 @@ def schnorr_sign_fixed_nonce(msg, seckey0, k): P = point_mul(G, seckey0) seckey = seckey0 if (jacobi(P[1]) == 1) else n - seckey0 R = point_mul(G, k) - e = int_from_bytes(hash_sha256(bytes_from_point(R) + bytes_from_point(P) + msg)) % n + e = int_from_bytes(tagged_hash("BIPSchnorr", bytes_from_point(R) + bytes_from_point(P) + msg)) % n return bytes_from_point(R) + bytes_from_int((k + e * seckey) % n) # Creates a singature with a small x(R) by using k = 1/2 diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 51fd45d..6d05610 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -41,7 +41,7 @@ As a result we choose this combination of technologies: * Taproot's advantages become apparent under the assumption that most applications involve outputs that could be spent by all parties agreeing. That's where '''Schnorr''' signatures come in, as they permit [https://eprint.iacr.org/2018/068 key aggregation]: a public key can be constructed from multiple participant public keys, and which requires cooperation between all participants to sign for. Such multi-party public keys and signatures are indistinguishable from their single-party equivalents. This means that under this Taproot assumption, the all-parties-agree case can be handled using the key-based spending path, which is both private and efficient using Taproot. This can be generalized to arbitrary M-of-N policies, as Schnorr signatures support threshold signing, at the cost of more complex setup protocols. * As Schnorr signatures also permit '''batch validation''', allowing multiple signatures to be validated together more efficiently than validating each one independently, we make sure all parts of the design are compatible with this. * Where unused bits appear as a result of the above changes, they are reserved for mechanisms for '''future extensions'''. As a result, every script in the Merkle tree has an associated version such that new script versions can be introduced with a soft fork while remaining compatible with bip-taproot. Additionally, future soft forks can make use of the currently unused annex in the witness (see [[#Rationale]]). -* While the core semantics of the '''signature hashing algorithm''' are not changed, a number of improvements are included in this proposal. The new signature hashing algorithm fixes the verification capabilities of offline signing devices by including amount and scriptPubKey in the digest, avoids unnecessary hashing, introduces '''tagged hashes''' and defines a default sighash byte. +* While the core semantics of the '''signature hashing algorithm''' are not changed, a number of improvements are included in this proposal. The new signature hashing algorithm fixes the verification capabilities of offline signing devices by including amount and scriptPubKey in the digest, avoids unnecessary hashing, uses '''tagged hashes''' and defines a default sighash byte. Not included in this proposal are additional features like new sighash modes or opcodes that can be included with no loss in effectiveness as a future extension. Also not included is cross-input aggregation, as it [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-March/015838.html interacts] in complex ways with upgrade mechanisms and solutions to that are still [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-October/016461.html in flux]. @@ -49,7 +49,9 @@ Not included in this proposal are additional features like new sighash modes or This section specifies the Taproot consensus rules. Validity is defined by exclusion: a block or transaction is valid if no condition exists that marks it failed. -The notation below follows that of bip-schnorr including the notion of tagged hashes. +The notation below follows that of bip-schnorr. +This includes the notion of tagged hashes which make collisions with existing uses of hash functions in Bitcoin infeasible. +The reason is that so far nowhere in the Bitcoin protocol are hashes used where the input of SHA256 starts with two (non-double) SHA256 hashes. === Script validation rules === -- cgit v1.2.3 From dc6b91c1a913f004ffa306c68295ac0b0f361264 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Tue, 27 Aug 2019 15:13:08 +0000 Subject: Address sipa's comments --- bip-schnorr.mediawiki | 2 +- bip-taproot.mediawiki | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index ad0b9cf..e96ee44 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -56,7 +56,7 @@ encodings and operations. We choose the ''R''-option to support batch verification. -'''Key prefixing''' When using the verification rule above directly, it is possible for a third party to convert a signature ''(R,s)'' for key ''P'' into a signature ''(R,s + ahash(R || m))'' for key ''P + aG'' and the same message, for any integer ''a''. This is not a concern for Bitcoin currently, as all signature hashes indirectly commit to the public keys. However, this may change with proposals such as SIGHASH_NOINPUT ([https://github.com/bitcoin/bips/blob/master/bip-0118.mediawiki BIP 118]), or when the signature scheme is used for other purposes—especially in combination with schemes like [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki BIP32]'s unhardened derivation. To combat this, we choose ''key prefixed''A limitation of committing to the public key (rather than to a short hash of it, or not at all) is that it removes the ability for public key recovery or verifying signatures against a short public key hash. These constructions are generally incompatible with batch verification. Schnorr signatures; changing the equation to ''sG = R + hash(R || P || m)P''. +'''Key prefixing''' When using the verification rule above directly, it is possible for a third party to convert a signature ''(R,s)'' for key ''P'' into a signature ''(R,s + a⋅hash(R || m))'' for key ''P + aG'' and the same message, for any integer ''a''. This is not a concern for Bitcoin currently, as all signature hashes indirectly commit to the public keys. However, this may change with proposals such as SIGHASH_NOINPUT ([https://github.com/bitcoin/bips/blob/master/bip-0118.mediawiki BIP 118]), or when the signature scheme is used for other purposes—especially in combination with schemes like [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki BIP32]'s unhardened derivation. To combat this, we choose ''key prefixed''A limitation of committing to the public key (rather than to a short hash of it, or not at all) is that it removes the ability for public key recovery or verifying signatures against a short public key hash. These constructions are generally incompatible with batch verification. Schnorr signatures; changing the equation to ''sG = R + hash(R || P || m)P''. '''Encoding R and public key point P''' There exist several possibilities for encoding elliptic curve points: # Encoding the full X and Y coordinates of ''P'' and ''R'', resulting in a 64-byte public key and a 96-byte signature. diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 6d05610..769f13d 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -41,7 +41,7 @@ As a result we choose this combination of technologies: * Taproot's advantages become apparent under the assumption that most applications involve outputs that could be spent by all parties agreeing. That's where '''Schnorr''' signatures come in, as they permit [https://eprint.iacr.org/2018/068 key aggregation]: a public key can be constructed from multiple participant public keys, and which requires cooperation between all participants to sign for. Such multi-party public keys and signatures are indistinguishable from their single-party equivalents. This means that under this Taproot assumption, the all-parties-agree case can be handled using the key-based spending path, which is both private and efficient using Taproot. This can be generalized to arbitrary M-of-N policies, as Schnorr signatures support threshold signing, at the cost of more complex setup protocols. * As Schnorr signatures also permit '''batch validation''', allowing multiple signatures to be validated together more efficiently than validating each one independently, we make sure all parts of the design are compatible with this. * Where unused bits appear as a result of the above changes, they are reserved for mechanisms for '''future extensions'''. As a result, every script in the Merkle tree has an associated version such that new script versions can be introduced with a soft fork while remaining compatible with bip-taproot. Additionally, future soft forks can make use of the currently unused annex in the witness (see [[#Rationale]]). -* While the core semantics of the '''signature hashing algorithm''' are not changed, a number of improvements are included in this proposal. The new signature hashing algorithm fixes the verification capabilities of offline signing devices by including amount and scriptPubKey in the digest, avoids unnecessary hashing, uses '''tagged hashes''' and defines a default sighash byte. +* While the core semantics of the '''signature hashing algorithm''' are not changed, a number of improvements are included in this proposal. The new signature hashing algorithm fixes the verification capabilities of offline signing devices by including amount and scriptPubKey in the digest, avoids unnecessary hashing, uses '''tagged hashes''''''Why use tagged hashes?''' So far, nowhere in the Bitcoin protocol are hashes used where the input of SHA256 starts with two (non-double) SHA256 hashes, making collisions with existing uses of hash functions infeasible. (according to bip-schnorr) and defines a default sighash byte. Not included in this proposal are additional features like new sighash modes or opcodes that can be included with no loss in effectiveness as a future extension. Also not included is cross-input aggregation, as it [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-March/015838.html interacts] in complex ways with upgrade mechanisms and solutions to that are still [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-October/016461.html in flux]. @@ -50,8 +50,6 @@ Not included in this proposal are additional features like new sighash modes or This section specifies the Taproot consensus rules. Validity is defined by exclusion: a block or transaction is valid if no condition exists that marks it failed. The notation below follows that of bip-schnorr. -This includes the notion of tagged hashes which make collisions with existing uses of hash functions in Bitcoin infeasible. -The reason is that so far nowhere in the Bitcoin protocol are hashes used where the input of SHA256 starts with two (non-double) SHA256 hashes. === Script validation rules === -- cgit v1.2.3 From e9600e6ed88b632520ecd4e4fb27ffca13869469 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Thu, 22 Aug 2019 10:11:10 +1000 Subject: public keys aren't identical --- bip-schnorr.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index e96ee44..b921b18 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -40,7 +40,7 @@ made: [[File:bip-schnorr/speedup-batch.png|frame|This graph shows the ratio between the time it takes to verify ''n'' signatures individually and to verify a batch of ''n'' signatures. This ratio goes up logarithmically with the number of signatures, or in other words: the total time to verify ''n'' signatures grows with ''O(n / log n)''.]] -By reusing the same curve as Bitcoin has used for ECDSA, private and public keys remain identical for Schnorr signatures, and we avoid introducing new assumptions about elliptic curve group security. +By reusing the same curve as Bitcoin has used for ECDSA, we are able to retain existing mechanisms for choosing private and public keys, and we avoid introducing new assumptions about elliptic curve group security. == Description == -- cgit v1.2.3 From 01e1f6e6b238f1c859512704e4b9bf33fe21d1ec Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Thu, 22 Aug 2019 10:20:12 +1000 Subject: pk not p --- bip-schnorr.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index b921b18..4de2596 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -87,7 +87,7 @@ For example, without tagged hashing a bip-schnorr signature could also be valid This proposal suggests to include the tag by prefixing the hashed data with ''SHA256(tag) || SHA256(tag)''. Because this is a 64-byte long context-specific constant, optimized implementations are possible (identical to SHA256 itself, but with a modified initial state). Using SHA256 of the tag name itself is reasonably simple and efficient for implementations that don't choose to use the optimization. -'''Final scheme''' As a result, our final scheme ends up using public key ''pk'' which is the X coordinate of a point ''P'' on the curve whose Y coordinate is a quadratic residue and signatures ''(r,s)'' where ''r'' is the X coordinate of a point ''R'' whose Y coordinate is a quadratic residue. The signature satisfies ''sG = R + tagged_hash(r || p || m)P''. +'''Final scheme''' As a result, our final scheme ends up using public key ''pk'' which is the X coordinate of a point ''P'' on the curve whose Y coordinate is a quadratic residue and signatures ''(r,s)'' where ''r'' is the X coordinate of a point ''R'' whose Y coordinate is a quadratic residue. The signature satisfies ''sG = R + tagged_hash(r || pk || m)P''. === Specification === -- cgit v1.2.3 From 4643538d4f07193726c796a9fe354a39ba250dfb Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Thu, 22 Aug 2019 11:06:19 +1000 Subject: make secret key a 32-byte array called sk, introduce pubkey() --- bip-schnorr.mediawiki | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 4de2596..8e53403 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -117,13 +117,16 @@ The following convention is used, with constants as defined for secp256k1: ** The function ''point(x)'', where ''x'' is a 32-byte array, returns the point ''P = lift_x(int(x))''. ** The function ''hashtag(x)'' where ''tag'' is a UTF-8 encoded tag name and ''x'' is a byte array returns the 32-byte hash ''SHA256(SHA256(tag) || SHA256(tag) || x)''. ** The function ''jacobi(x)'', where ''x'' is an integer, returns the [https://en.wikipedia.org/wiki/Jacobi_symbol Jacobi symbol] of ''x / p''. It is equal to ''x(p-1)/2 mod p'' ([https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion])For points ''P'' on the secp256k1 curve it holds that ''jacobi(y(P)) ≠ 0''.. +** The function ''pubkey(x)'', where ''x'' is a 32-byte array, returns ''bytes(dG)'' where ''d = int(x) mod n''. -=== Public Key Generation === +==== Public Key Generation ==== Input: -* The secret key ''d'': an integer in the range ''1..n-1'' chosen uniformly at random. +* The secret key ''sk'': a 32-byte array, generated uniformly at random -The public key corresponding to secret key ''d'' is ''bytes(dG)''. +To generate the corresponding public key: +* Fail if ''int(sk) = 0'' or ''int(sk) >= n'' +* The public key corresponding to secret key ''sk'' is ''pubkey(sk)''. Alternatively, the public key can be created according to [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki BIP32] which describes the derivation of 33-byte compressed public keys. In order to translate such public keys into bip-schnorr compatible keys, the first byte must be dropped. @@ -165,11 +168,13 @@ All provided signatures are valid with overwhelming probability if and only if t ==== Signing ==== Input: -* The secret key ''d' '': an integer in the range ''1..n-1'' +* The secret key ''sk'': a 32-byte array * The message ''m'': a 32-byte array -To sign ''m'' for public key ''bytes(dG)'': -* Let ''P = dG'' +To sign ''m'' for public key ''pubkey(sk)'': +* Let ''d' = int(sk)'' +* Fail if ''d' = 0'' or ''d' >= n'' +* Let ''P = d'G'' * Let ''d = d' '' if ''jacobi(y(P)) = 1'', otherwise let ''d = n - d' ''. * Let ''k' = int(hashBIPSchnorrDerive(bytes(d) || m)) mod n''Note that in general, taking the output of a hash function modulo the curve order will produce an unacceptably biased result. However, for the secp256k1 curve, the order is sufficiently close to ''2256'' that this bias is not observable (''1 - n / 2256'' is around ''1.27 * 2-128'').. * Fail if ''k' = 0''. -- cgit v1.2.3 From d3951f63f3886b4942f624f11cc9082b4e6a1be0 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Fri, 23 Aug 2019 15:19:28 +1000 Subject: use p for taproot internal key --- bip-taproot.mediawiki | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 769f13d..ef30fee 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -64,7 +64,7 @@ The following rules only apply when such an output is being spent. Any other out * If there are at least two witness elements left, script path spending is used: ** Call the second-to-last stack element ''s'', the script. ** The last stack element is called the control block ''c'', and must have length ''33 + 32m'', for a value of ''m'' that is an integer between 0 and 32, inclusive. Fail if it does not have such a length. -** Let ''P = point(c[1:33])'' where ''point'' is defined as in bip-schnorr. Fail if this point is not on the curve. +** Let ''p = c[1:33]'' and let ''P = point(p)'' where ''point'' is defined as in bip-schnorr. Fail if this point is not on the curve. ** Let ''l = c[0] & 0xfe'', the leaf version'''What is the purpose of the first byte of the control block?''' The first byte of the control block has three distinct functions: * The low bit is used to denote whether the ''Q'' point's Y coordinate is a quadratic residue.'''Why is the quadratic residuosity of the output public key's Y coordinate required in a script path spend?''' The ''point'' function always constructs a point with Y coordinate having that property, but because ''Q'' is constructed by adding the taproot tweak to the internal public key ''P'', it cannot easily be guaranteed that ''Q'' in fact has such a Y coordinate. We can not ignore the Y coordinate because it would prevent batch verification. Trying out multiple internal keys until there's such a ''Q'' is possible but undesirable and unnecessary since this information about the Y coordinate only consumes an unused bit. * By keeping the top two bits set to true, it can be guaranteed that scripts can be recognized without knowledge of the UTXO being spent, simplifying analysis. This is because such values cannot occur as first byte of the final stack element in either P2WPKH or P2WSH spends. @@ -76,13 +76,13 @@ The following rules only apply when such an output is being spent. Any other out *** Let ''kj+1 depend on whether ''kj < ej'' (lexicographically)'''Why are child elements sorted before hashing in the Merkle tree?''' By doing so, it is not necessary to reveal the left/right directions along with the hashes in revealed Merkle branches. This is possible because we do not actually care about the position of specific scripts in the tree; only that they are actually committed to.: **** If ''kj < ej'': ''kj+1 = hashTapBranch(kj || ej)'''''Why not use a more efficient hash construction for inner Merkle nodes?''' The chosen construction does require two invocations of the SHA256 compression functions, one of which can be avoided in theory (see BIP98). However, it seems preferable to stick to constructions that can be implemented using standard cryptographic primitives, both for implementation simplicity and analyzability. If necessary, a significant part of the second compression function can be optimized out by [https://github.com/bitcoin/bitcoin/pull/13191 specialization] for 64-byte inputs.. **** If ''kj ≥ ej'': ''kj+1 = hashTapBranch(ej || kj)''. -** Let ''t = hashTapTweak(bytes(P) || km) = hashTapTweak(c[1:33] || km)''. +** Let ''t = hashTapTweak(p || km)''. ** If ''t ≥ 0xFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141'' (order of secp256k1), fail. ** Let ''Q = point(q) if (c[0] & 1) = 1 and -point(q) otherwise''. Fail if this point is not on the curve. ** If ''Q ≠ P + int(t)G'', fail. ** Execute the script, according to the applicable script rules'''What are the applicable script rules in script path spends?''' Bip-tapscript specifies validity rules that apply if the leaf version is ''0xc0'', but future proposals can introduce rules for other leaf versions., using the witness stack elements excluding the script ''s'', the control block ''c'', and the annex ''a'' if present, as initial stack. -''q'' is referred to as ''taproot output key'' and ''c[1:33]'' as ''taproot internal key''. +''q'' is referred to as ''taproot output key'' and ''p'' as ''taproot internal key''. === Signature validation rules === -- cgit v1.2.3 From fc74ec6b356c83ac380ba33e48a434c2e0d6a270 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Fri, 23 Aug 2019 15:42:00 +1000 Subject: key gen, verify, sign in intro --- bip-schnorr.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 8e53403..9c80cd5 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -91,7 +91,7 @@ This proposal suggests to include the tag by prefixing the hashed data with ''SH === Specification === -We first describe the verification algorithm, and then the signature algorithm. +We first describe the key generation algorithm, then the verification algorithm, and then the signature algorithm. The following convention is used, with constants as defined for secp256k1: * Lowercase variables represent integers or byte arrays. -- cgit v1.2.3 From 30bc716add2e654847d59fbd49ea0f953589ab73 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Sat, 24 Aug 2019 15:08:05 +1000 Subject: note about pubkey collision --- bip-schnorr.mediawiki | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 9c80cd5..bb2f9dc 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -128,6 +128,8 @@ To generate the corresponding public key: * Fail if ''int(sk) = 0'' or ''int(sk) >= n'' * The public key corresponding to secret key ''sk'' is ''pubkey(sk)''. +Note that the two secret keys ''sk'' and ''bytes(n-int(sk))'' will generate the same public key. + Alternatively, the public key can be created according to [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki BIP32] which describes the derivation of 33-byte compressed public keys. In order to translate such public keys into bip-schnorr compatible keys, the first byte must be dropped. -- cgit v1.2.3 From 02bdf88ef9c5e180e7bfd408ab900508d549f8e6 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Thu, 29 Aug 2019 20:46:47 +0000 Subject: Fix privkey negation in taproot_sign_key --- bip-taproot.mediawiki | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 769f13d..d720be1 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -200,10 +200,10 @@ See the code below: def taproot_sign_key(script_tree, internal_privkey, hash_type): + _, h = taproot_tree_helper(script_tree) internal_pubkey, is_y_qresidue = internal_privkey.pubkey_gen() - if is_y_qresidue: + if not is_y_qresidue: internal_privkey = internal_privkey.negate() - _, h = taproot_tree_helper(script_tree) t = tagged_hash("TapTweak", internal_pubkey.get_bytes() + h) output_privkey = internal_privkey.tweak_add(t) sig = output_privkey.schnorr_sign(sighash(hash_type)) -- cgit v1.2.3 From 6d99e4512640fa4424ef6f1a2c2c6b50c80d4bae Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Sun, 8 Sep 2019 16:38:15 +0200 Subject: Rework Applications section --- bip-schnorr.mediawiki | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index bb2f9dc..2a1450d 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -8,17 +8,17 @@ Post-History: 2018-07-06: https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-July/016203.html [bitcoin-dev] Schnorr signatures BIP -==Introduction== +== Introduction == -===Abstract=== +=== Abstract === This document proposes a standard for 64-byte Schnorr signatures over the elliptic curve ''secp256k1''. -===Copyright=== +=== Copyright === This document is licensed under the 2-clause BSD license. -===Motivation=== +=== Motivation === Bitcoin has traditionally used [https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm ECDSA] signatures over the [http://www.secg.org/sec2-v2.pdf secp256k1 curve] for authenticating @@ -205,13 +205,13 @@ Many techniques are known for optimizing elliptic curve implementations. Several There are several interesting applications beyond simple signatures. While recent academic papers claim that they are also possible with ECDSA, consensus support for Schnorr signature verification would significantly simplify the constructions. -===Multisignatures and Threshold Signatures=== +=== Multisignatures and Threshold Signatures === -By means of an interactive scheme such as [https://eprint.iacr.org/2018/068 MuSig], participants can produce a combined public key which they can jointly sign for. This allows n-of-n multisignatures which, from a verifier's perspective, are no different from ordinary signatures, giving improved privacy and efficiency versus ''CHECKMULTISIG'' or other means. +By means of an interactive scheme such as [https://eprint.iacr.org/2018/068 MuSig], participants can aggregate their public keys into a single public key which they can jointly sign for. This allows n-of-n multisignatures which, from a verifier's perspective, are no different from ordinary signatures, giving improved privacy and efficiency versus ''CHECKMULTISIG'' or other means. -Further, by combining Schnorr signatures with [https://link.springer.com/content/pdf/10.1007/3-540-46766-1_9.pdf Pedersen Secret Sharing], it is possible to obtain [http://cacr.uwaterloo.ca/techreports/2001/corr2001-13.ps an interactive threshold signature scheme] that ensures that signatures can only be produced by arbitrary but predetermined sets of signers. For example, k-of-n threshold signatures can be realized this way. Furthermore, it is possible to replace the combination of participant keys in this scheme with MuSig, though the security of that combination still needs analysis. +Moreover, Schnorr signatures are compatible with [https://web.archive.org/web/20031003232851/http://www.research.ibm.com/security/dkg.ps distributed key generation], which enables interactive threshold signatures schemes, e.g., the schemes described by [http://cacr.uwaterloo.ca/techreports/2001/corr2001-13.ps Stinson and Strobl (2001)] or [https://web.archive.org/web/20060911151529/http://theory.lcs.mit.edu/~stasio/Papers/gjkr03.pdf Genaro, Jarecki and Krawczyk (2003)]. These protocols make it possible to realize k-of-n threshold signatures, which ensure that any subset of size k of the set of n signers can sign but no subset of size less than k can produce a valid Schnorr signature. However, the practicality of the existing schemes is limited: most schemes in the literature have been proven secure only for the case k < n/2, are not secure when used concurrently in multiple sessions, or require a reliable broadcast mechanism to be secure. Further research is necessary to improve this situation. -===Adaptor Signatures=== +=== Adaptor Signatures === [https://download.wpsoftware.net/bitcoin/wizardry/mw-slides/2018-05-18-l2/slides.pdf Adaptor signatures] can be produced by a signer by offsetting his public nonce with a known point ''T = tG'', but not offsetting his secret nonce. A correct signature (or partial signature, as individual signers' contributions to a multisignature are called) on the same message with same nonce will then be equal to the adaptor signature offset by ''t'', meaning that learning ''t'' is equivalent to learning a correct signature. @@ -219,12 +219,11 @@ This can be used to enable atomic swaps or even [https://eprint.iacr.org/2018/47 Adaptor signatures, beyond the efficiency and privacy benefits of encoding script semantics into constant-sized signatures, have additional benefits over traditional hash-based payment channels. Specifically, the secret values ''t'' may be reblinded between hops, allowing long chains of transactions to be made atomic while even the participants cannot identify which transactions are part of the chain. Also, because the secret values are chosen at signing time, rather than key generation time, existing outputs may be repurposed for different applications without recourse to the blockchain, even multiple times. -===Blind Signatures=== +=== Blind Signatures === -Schnorr signatures admit a very [https://www.math.uni-frankfurt.de/~dmst/research/papers/schnorr.blind_sigs_attack.2001.pdf simple '''blind signature''' construction] which is a signature that a signer produces at the behest of another party without learning what he has signed. -These can for example be used in [https://github.com/jonasnick/scriptless-scripts/blob/blind-swaps/md/partially-blind-swap.md Partially Blind Atomic Swaps], a construction to enable transferring of coins, mediated by an untrusted escrow agent, without connecting the transactors in the public blockchain transaction graph. +A blind signature protocol is an interactive protocol that enables a signer to sign a message at the behest of another party without learning the signer learning any information about the signed message or the signature. Schnorr signatures admit a very [https://www.math.uni-frankfurt.de/~dmst/research/papers/schnorr.blind_sigs_attack.2001.pdf simple blind signature scheme] which is however insecure because it's vulnerable to [https://www.iacr.org/archive/crypto2002/24420288/24420288.pdf Wagner's attack]. A known mitigation is to let the signer abort a signing session with a certain probability, and the resulting scheme can be [https://eprint.iacr.org/2019/877 proven secure under non-standard cryptographic assumptions]. -While the traditional Schnorr blind signatures are vulnerable to [https://www.iacr.org/archive/crypto2002/24420288/24420288.pdf Wagner's attack], there are [https://www.math.uni-frankfurt.de/~dmst/teaching/SS2012/Vorlesung/EBS5.pdf a number of mitigations] which allow them to be usable in practice without any known attacks. Nevertheless, more analysis is required to be confident about the security of the blind signature scheme. +Blind Schnorr signatures could for example be used in [https://github.com/jonasnick/scriptless-scripts/blob/blind-swaps/md/partially-blind-swap.md Partially Blind Atomic Swaps], a construction to enable transferring of coins, mediated by an untrusted escrow agent, without connecting the transactors in the public blockchain transaction graph. == Test Vectors and Reference Code == -- cgit v1.2.3 From 4a383064fb492c6170c49953460a7960854c28b7 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Sun, 8 Sep 2019 16:38:55 +0200 Subject: Add a footnote about 32-byte security --- bip-schnorr.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index bb2f9dc..de55ded 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -79,7 +79,7 @@ For ''P'' the speed of signing and verification does not significantly differ be It is important to not mix up the 32-byte bip-schnorr public key format and other existing public key formats (e.g. encodings used in Bitcoin's ECDSA). Concretely, a verifier should only accept 32-byte public keys and not, for example, convert a 33-byte public key by throwing away the first byte. Otherwise, two public keys would be valid for a single signature which can result in subtle malleability issues (although this type of malleability already exists in the case of ECDSA signatures). -Implicit Y coordinates are not a reduction in security when expressed as the number of elliptic curve operations an attacker is expected to perform to compute the secret key. An attacker can normalize any given public key to a point whose Y coordinate is a quadratic residue by negating the point if necessary. This is just a subtraction of field elements and not an elliptic curve operation. +Implicit Y coordinates are not a reduction in security when expressed as the number of elliptic curve operations an attacker is expected to perform to compute the secret key. An attacker can normalize any given public key to a point whose Y coordinate is a quadratic residue by negating the point if necessary. This is just a subtraction of field elements and not an elliptic curve operationThis can be formalized by a simple reduction that reduces an attack on Schnorr signatures with implicit Y coordinates to an attack to Schnorr signatures with explicit Y coordinates. The reduction works by reencoding public keys and negating the result of the hash function, which is modeled as random oracle, whenever the challenge public key has an explicit Y coordinate that is not a quadratic residue.. '''Tagged Hashes''' Cryptographic hash functions are used for multiple purposes in the specification below and in Bitcoin in general. To make sure hashes used in one context can't be reinterpreted in another one, hash functions can be tweaked with a context-dependent tag name, in such a way that collisions across contexts can be assumed to be infeasible. Such collisions obviously can not be ruled out completely, but only for schemes using tagging with a unique name. As for other schemes collisions are at least less likely with tagging than without. -- cgit v1.2.3 From 0995c8a5b58b76d6b2a935502afc181d2fae70d1 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Fri, 10 May 2019 12:11:07 +0000 Subject: Move plain public key in output rationale to design section Rebased by Pieter Wuille --- bip-taproot.mediawiki | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 7d58b16..5b29943 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -42,6 +42,7 @@ As a result we choose this combination of technologies: * As Schnorr signatures also permit '''batch validation''', allowing multiple signatures to be validated together more efficiently than validating each one independently, we make sure all parts of the design are compatible with this. * Where unused bits appear as a result of the above changes, they are reserved for mechanisms for '''future extensions'''. As a result, every script in the Merkle tree has an associated version such that new script versions can be introduced with a soft fork while remaining compatible with bip-taproot. Additionally, future soft forks can make use of the currently unused annex in the witness (see [[#Rationale]]). * While the core semantics of the '''signature hashing algorithm''' are not changed, a number of improvements are included in this proposal. The new signature hashing algorithm fixes the verification capabilities of offline signing devices by including amount and scriptPubKey in the digest, avoids unnecessary hashing, uses '''tagged hashes''''''Why use tagged hashes?''' So far, nowhere in the Bitcoin protocol are hashes used where the input of SHA256 starts with two (non-double) SHA256 hashes, making collisions with existing uses of hash functions infeasible. (according to bip-schnorr) and defines a default sighash byte. +* The '''public key is directly included in the output''' in contrast to typical earlier constructions which store a hash of the public key or script in the output. This has the same cost for senders and is more space efficient overall if the key-based spending path is taken. '''Why is the public key directly included in the output?''' While typical earlier constructions store a hash of a script or a public key in the output, this is rather wasteful when a public key is always involved. To guarantee batch verifiability, ''q'' must be known to every verifier, and thus only revealing its hash as an output would imply adding an additional 32 bytes to the witness. Furthermore, to maintain [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2016-January/012198.html 128-bit collision security] for outputs, a 256-bit hash would be required anyway, which is comparable in size (and thus in cost for senders) to revealing the public key directly. While the usage of public key hashes is often said to protect against ECDLP breaks or quantum computers, this protection is very weak at best: transactions are not protected while being confirmed, and a very [https://twitter.com/pwuille/status/1108097835365339136 large portion] of the currency's supply is not under such protection regardless. Actual resistance to such systems can be introduced by relying on different cryptographic assumptions, but this proposal focuses on improvements that do not change the security model. Note that using P2SH-wrapped outputs only have 80-bit collision security. This is considered low, and is relevant whenever the output includes data from more than a single party (public keys, hashes, ...). . Not included in this proposal are additional features like new sighash modes or opcodes that can be included with no loss in effectiveness as a future extension. Also not included is cross-input aggregation, as it [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-March/015838.html interacts] in complex ways with upgrade mechanisms and solutions to that are still [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-October/016461.html in flux]. @@ -56,7 +57,7 @@ The notation below follows that of bip-schnorr. A Taproot output is a SegWit output (native or P2SH-nested, see [https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki BIP141]) with version number 1, and a 32-byte witness program. The following rules only apply when such an output is being spent. Any other outputs, including version 1 outputs with lengths other than 32 bytes, remain unencumbered. -* Let ''q'' be the 32-byte array containing the witness program (second push in scriptPubKey or P2SH redeemScript) which represents a public key according to bip-schnorr '''Why is the public key directly included in the output?''' While typical earlier constructions store a hash of a script or a public key in the output, this is rather wasteful when a public key is always involved. To guarantee batch verifiability, ''q'' must be known to every verifier, and thus only revealing its hash as an output would imply adding an additional 32 bytes to the witness. Furthermore, to maintain [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2016-January/012198.html 128-bit collision security] for outputs, a 256-bit hash would be required anyway, which is comparable in size (and thus in cost for senders) to revealing the public key directly. While the usage of public key hashes is often said to protect against ECDLP breaks or quantum computers, this protection is very weak at best: transactions are not protected while being confirmed, and a very [https://twitter.com/pwuille/status/1108097835365339136 large portion] of the currency's supply is not under such protection regardless. Actual resistance to such systems can be introduced by relying on different cryptographic assumptions, but this proposal focuses on improvements that do not change the security model. Note that using P2SH-wrapped outputs only have 80-bit collision security. This is considered low, and is relevant whenever the output includes data from more than a single party (public keys, hashes, ...). . +* Let ''q'' be the 32-byte array containing the witness program (second push in scriptPubKey or P2SH redeemScript) which represents a public key according to bip-schnorr. * Fail if the witness stack has 0 elements. * If there are at least two witness elements, and the first byte of the last element is 0x50'''Why is the first byte of the annex 0x50?''' Like the 0xc0-0xc1 constants, 0x50 is chosen as it could not be confused with a valid P2WPKH or P2WSH spending. As the control block's initial byte's lowest bit is used to indicate the public key's Y quadratic residuosity, each script version needs two subsequence byte values that are both not yet used in P2WPKH or P2WSH spending. To indicate the annex, only an "unpaired" available byte is necessary like 0x50. This choice maximizes the available options for future script versions., this last element is called ''annex'' ''a'''''What is the purpose of the annex?''' The annex is a reserved space for future extensions, such as indicating the validation costs of computationally expensive new opcodes in a way that is recognizable without knowing the outputs being spent. Until the meaning of this field is defined by another softfork, users SHOULD NOT include annex in transactions, or it may lead to PERMANENT FUND LOSS. and is removed from the witness stack. The annex (or the lack of thereof) is always covered by the transaction digest and contributes to transaction weight, but is otherwise ignored during taproot validation. * If there is exactly one element left in the witness stack, key path spending is used: -- cgit v1.2.3 From fa423aced998974b87bdd21936d0836a5f7792a3 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 10 Sep 2019 16:24:07 -0700 Subject: Address some nits --- bip-schnorr.mediawiki | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index f88660e..39e7b43 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -221,9 +221,9 @@ Adaptor signatures, beyond the efficiency and privacy benefits of encoding scrip === Blind Signatures === -A blind signature protocol is an interactive protocol that enables a signer to sign a message at the behest of another party without learning the signer learning any information about the signed message or the signature. Schnorr signatures admit a very [https://www.math.uni-frankfurt.de/~dmst/research/papers/schnorr.blind_sigs_attack.2001.pdf simple blind signature scheme] which is however insecure because it's vulnerable to [https://www.iacr.org/archive/crypto2002/24420288/24420288.pdf Wagner's attack]. A known mitigation is to let the signer abort a signing session with a certain probability, and the resulting scheme can be [https://eprint.iacr.org/2019/877 proven secure under non-standard cryptographic assumptions]. +A blind signature protocol is an interactive protocol that enables a signer to sign a message at the behest of another party without learning any information about the signed message or the signature. Schnorr signatures admit a very [https://www.math.uni-frankfurt.de/~dmst/research/papers/schnorr.blind_sigs_attack.2001.pdf simple blind signature scheme] which is however insecure because it's vulnerable to [https://www.iacr.org/archive/crypto2002/24420288/24420288.pdf Wagner's attack]. A known mitigation is to let the signer abort a signing session with a certain probability, and the resulting scheme can be [https://eprint.iacr.org/2019/877 proven secure under non-standard cryptographic assumptions]. -Blind Schnorr signatures could for example be used in [https://github.com/jonasnick/scriptless-scripts/blob/blind-swaps/md/partially-blind-swap.md Partially Blind Atomic Swaps], a construction to enable transferring of coins, mediated by an untrusted escrow agent, without connecting the transactors in the public blockchain transaction graph. +Blind Schnorr signatures could for example be used in [https://github.com/ElementsProject/scriptless-scripts/blob/master/md/partially-blind-swap.md Partially Blind Atomic Swaps], a construction to enable transferring of coins, mediated by an untrusted escrow agent, without connecting the transactors in the public blockchain transaction graph. == Test Vectors and Reference Code == -- cgit v1.2.3 From 87fa069b8f747f7c30f66905e9dded46c0d4023f Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Thu, 22 Aug 2019 12:26:57 +0000 Subject: Mention SHA256 block size Rebased by Pieter Wuille --- bip-schnorr.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index de55ded..4b4720d 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -85,7 +85,7 @@ Implicit Y coordinates are not a reduction in security when expressed as the num For example, without tagged hashing a bip-schnorr signature could also be valid for a signature scheme where the only difference is that the arguments to the hash function are reordered. Worse, if the bip-schnorr nonce derivation function was copied or independently created, then the nonce could be accidentally reused in the other scheme leaking the private key. -This proposal suggests to include the tag by prefixing the hashed data with ''SHA256(tag) || SHA256(tag)''. Because this is a 64-byte long context-specific constant, optimized implementations are possible (identical to SHA256 itself, but with a modified initial state). Using SHA256 of the tag name itself is reasonably simple and efficient for implementations that don't choose to use the optimization. +This proposal suggests to include the tag by prefixing the hashed data with ''SHA256(tag) || SHA256(tag)''. Because this is a 64-byte long context-specific constant and the ''SHA256'' block size is also 64 bytes, optimized implementations are possible (identical to SHA256 itself, but with a modified initial state). Using SHA256 of the tag name itself is reasonably simple and efficient for implementations that don't choose to use the optimization. '''Final scheme''' As a result, our final scheme ends up using public key ''pk'' which is the X coordinate of a point ''P'' on the curve whose Y coordinate is a quadratic residue and signatures ''(r,s)'' where ''r'' is the X coordinate of a point ''R'' whose Y coordinate is a quadratic residue. The signature satisfies ''sG = R + tagged_hash(r || pk || m)P''. -- cgit v1.2.3 From d191359e75a2205c26be8947c9817c03181d3a4d Mon Sep 17 00:00:00 2001 From: JamesC Date: Mon, 16 Sep 2019 21:59:54 +0200 Subject: Removed reference to 0xc1 leaf version. No longer necessary with 32B pubkeys. --- bip-tapscript.mediawiki | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index af46afd..603990e 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -47,7 +47,7 @@ The rules below only apply when validating a transaction input for which all of * The transaction output is a '''segregated witness spend''' (i.e., either the scriptPubKey or BIP16 redeemScript is a witness program as defined in BIP141). * It is a '''taproot spend''' as defined in bip-taproot (i.e., the witness version is 1, the witness program is 32 bytes). * It is a '''script path spend''' as defined in bip-taproot (i.e., after removing the optional annex from the witness stack, two or more stack elements remain). -* The leaf version is ''0xc0'' (i.e. the first byte of the last witness element after removing the optional annex is ''0xc0'' or ''0xc1'')'''How is the ''0xc0'' constant chosen?''' Following the guidelines in bip-taproot, by choosing a value having the two top bits set, tapscript spends are identifiable even without access to the UTXO being spent., marking it as a '''tapscript spend'''. +* The leaf version is ''0xc0'' (i.e. the first byte of the last witness element after removing the optional annex is ''0xc0'')'''How is the ''0xc0'' constant chosen?''' Following the guidelines in bip-taproot, by choosing a value having the two top bits set, tapscript spends are identifiable even without access to the UTXO being spent., marking it as a '''tapscript spend'''. Validation of such inputs must be equivalent to performing the following steps in the specified order. # If the input is invalid due to BIP16, BIP141, or bip-taproot, fail. @@ -142,4 +142,3 @@ This rule limits worst-case validation costs in tapscript similar to the ''sigop ==Acknowledgements== This document is the result of many discussions and contains contributions by Jonas Nick, Anthony Towns, and others. - -- cgit v1.2.3 From 1a8818a4469784ba148dfe22c6f6c7b84d78078c Mon Sep 17 00:00:00 2001 From: Bryan Bishop Date: Mon, 16 Sep 2019 18:47:54 -0500 Subject: bip-taproot: fix small typo (is does not) --- bip-taproot.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index d92f955..76c23dc 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -162,7 +162,7 @@ Satisfying any of these conditions is sufficient to spend the output. '''Initial steps''' The first step is determining what the internal key and the organization of the rest of the scripts should be. The specifics are likely application dependent, but here are some general guidelines: * When deciding between scripts with conditionals (OP_IF etc.) and splitting them up into multiple scripts (each corresponding to one execution path through the original script), it is generally preferable to pick the latter. * When a single condition requires signatures with multiple keys, key aggregation techniques like MuSig can be used to combine them into a single key. The details are out of scope for this document, but note that this may complicate the signing procedure. -* If one or more of the spending conditions consist of just a single key (after aggregation), the most likely one should be made the internal key. If no such condition exists, it may be worthwhile adding one that consists of an aggregation of all keys participating in all scripts combined; effectively adding an "everyone agrees" branch. If that is inacceptable, pick as internal key a point with unknown discrete logarithm. One example of such a point is ''H = point(0x0250929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0)'' which is [https://github.com/ElementsProject/secp256k1-zkp/blob/11af7015de624b010424273be3d91f117f172c82/src/modules/rangeproof/main_impl.h#L16 constructed] by taking the hash of the standard uncompressed encoding of secp256k1 generator ''G'' as X coordinate. In order to avoid leaking the information that key path spending is not possible it is recommended to pick a fresh integer ''r'' in the range ''0...n-1'' uniformly at random and use ''H + rG'' as internal key. It is possible to prove that this internal key is does not have a known discrete logarithm with respect to ''G'' by revealing ''r'' to a verifier who can then reconstruct how the internal key was created. +* If one or more of the spending conditions consist of just a single key (after aggregation), the most likely one should be made the internal key. If no such condition exists, it may be worthwhile adding one that consists of an aggregation of all keys participating in all scripts combined; effectively adding an "everyone agrees" branch. If that is inacceptable, pick as internal key a point with unknown discrete logarithm. One example of such a point is ''H = point(0x0250929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0)'' which is [https://github.com/ElementsProject/secp256k1-zkp/blob/11af7015de624b010424273be3d91f117f172c82/src/modules/rangeproof/main_impl.h#L16 constructed] by taking the hash of the standard uncompressed encoding of secp256k1 generator ''G'' as X coordinate. In order to avoid leaking the information that key path spending is not possible it is recommended to pick a fresh integer ''r'' in the range ''0...n-1'' uniformly at random and use ''H + rG'' as internal key. It is possible to prove that this internal key does not have a known discrete logarithm with respect to ''G'' by revealing ''r'' to a verifier who can then reconstruct how the internal key was created. * If the spending conditions do not require a script path, the output key should commit to an unspendable script path instead of having no script path. This can be achieved by computing the output key point as ''Q = P + int(hashTapTweak(bytes(P)))G''. '''Why should the output key always have a taproot commitment, even if there is no script path?''' If the taproot output key is an aggregate of keys, there is the possibility for a malicious party to add a script path without being noticed by the other parties. This allows to bypass the multiparty policy and to steal the coin. -- cgit v1.2.3 From 77dad346ecf3f789153eede2d54fa7ac3671202a Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 20 Sep 2019 15:01:57 -0700 Subject: Move/reword tagged hashes motivation --- bip-taproot.mediawiki | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 76c23dc..0bafac9 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -41,7 +41,7 @@ As a result we choose this combination of technologies: * Taproot's advantages become apparent under the assumption that most applications involve outputs that could be spent by all parties agreeing. That's where '''Schnorr''' signatures come in, as they permit [https://eprint.iacr.org/2018/068 key aggregation]: a public key can be constructed from multiple participant public keys, and which requires cooperation between all participants to sign for. Such multi-party public keys and signatures are indistinguishable from their single-party equivalents. This means that under this Taproot assumption, the all-parties-agree case can be handled using the key-based spending path, which is both private and efficient using Taproot. This can be generalized to arbitrary M-of-N policies, as Schnorr signatures support threshold signing, at the cost of more complex setup protocols. * As Schnorr signatures also permit '''batch validation''', allowing multiple signatures to be validated together more efficiently than validating each one independently, we make sure all parts of the design are compatible with this. * Where unused bits appear as a result of the above changes, they are reserved for mechanisms for '''future extensions'''. As a result, every script in the Merkle tree has an associated version such that new script versions can be introduced with a soft fork while remaining compatible with bip-taproot. Additionally, future soft forks can make use of the currently unused annex in the witness (see [[#Rationale]]). -* While the core semantics of the '''signature hashing algorithm''' are not changed, a number of improvements are included in this proposal. The new signature hashing algorithm fixes the verification capabilities of offline signing devices by including amount and scriptPubKey in the digest, avoids unnecessary hashing, uses '''tagged hashes''''''Why use tagged hashes?''' So far, nowhere in the Bitcoin protocol are hashes used where the input of SHA256 starts with two (non-double) SHA256 hashes, making collisions with existing uses of hash functions infeasible. (according to bip-schnorr) and defines a default sighash byte. +* While the core semantics of the '''signature hashing algorithm''' are not changed, a number of improvements are included in this proposal. The new signature hashing algorithm fixes the verification capabilities of offline signing devices by including amount and scriptPubKey in the digest, avoids unnecessary hashing, uses '''tagged hashes''' and defines a default sighash byte. * The '''public key is directly included in the output''' in contrast to typical earlier constructions which store a hash of the public key or script in the output. This has the same cost for senders and is more space efficient overall if the key-based spending path is taken. '''Why is the public key directly included in the output?''' While typical earlier constructions store a hash of a script or a public key in the output, this is rather wasteful when a public key is always involved. To guarantee batch verifiability, ''q'' must be known to every verifier, and thus only revealing its hash as an output would imply adding an additional 32 bytes to the witness. Furthermore, to maintain [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2016-January/012198.html 128-bit collision security] for outputs, a 256-bit hash would be required anyway, which is comparable in size (and thus in cost for senders) to revealing the public key directly. While the usage of public key hashes is often said to protect against ECDLP breaks or quantum computers, this protection is very weak at best: transactions are not protected while being confirmed, and a very [https://twitter.com/pwuille/status/1108097835365339136 large portion] of the currency's supply is not under such protection regardless. Actual resistance to such systems can be introduced by relying on different cryptographic assumptions, but this proposal focuses on improvements that do not change the security model. Note that using P2SH-wrapped outputs only have 80-bit collision security. This is considered low, and is relevant whenever the output includes data from more than a single party (public keys, hashes, ...). . Not included in this proposal are additional features like new sighash modes or opcodes that can be included with no loss in effectiveness as a future extension. Also not included is cross-input aggregation, as it [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-March/015838.html interacts] in complex ways with upgrade mechanisms and solutions to that are still [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-October/016461.html in flux]. @@ -50,7 +50,7 @@ Not included in this proposal are additional features like new sighash modes or This section specifies the Taproot consensus rules. Validity is defined by exclusion: a block or transaction is valid if no condition exists that marks it failed. -The notation below follows that of bip-schnorr. +The notation below follows that of bip-schnorr. This includes the ''hashtag(x)'' notation to refer to ''SHA256(SHA256(tag) || SHA256(tag) || x)''. To the best of the authors' knowledge, no existing use of SHA256 in Bitcoin feeds it a message that starts with two single SHA256 outputs, making collisions between ''hashtag'' with other hashes extremely unlikely. === Script validation rules === -- cgit v1.2.3 From f2899666f80436be55aa5f4b28bd9dd8717529e2 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 20 Sep 2019 19:38:03 -0700 Subject: Rework resource limits section --- bip-tapscript.mediawiki | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index 603990e..33b64da 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -61,18 +61,18 @@ Validation of such inputs must be equivalent to performing the following steps i # If the size of any element in the '''initial stack''' as defined in bip-taproot (i.e., the witness stack after removing both the optional annex and the two last stack elements after that) is bigger than 520 bytes, fail. # If the tapscript is bigger than 10000 bytes, fail. # The tapscript is executed according to the rules in the following section, with the initial stack as input. -## If execution fails for any reason (including the 201 non-push opcode limit), fail. +## If execution fails for any reason, fail. ## If the execution results in anything but exactly one element on the stack which evaluates to true with CastToBool(), fail. # If this step is reached without encountering a failure, validation succeeds. ===Script execution=== The execution rules for tapscript are based on those for P2WSH according to BIP141, including the OP_CHECKLOCKTIMEVERIFY and OP_CHECKSEQUENCEVERIFY opcodes defined in BIP65 and BIP112, but with the following modifications: -* '''Disabled script opcodes''' The following script opcodes are disabled in tapscript: OP_CHECKMULTISIG and OP_CHECKMULTISIGVERIFY. The disabled opcodes behave in the same way as OP_RETURN, by failing and terminating the script immediately when executed, and being ignored when found in unexecuted branch. While being ignored, they are still counted towards the 201 non-push opcodes limit. +* '''Disabled script opcodes''' The following script opcodes are disabled in tapscript: OP_CHECKMULTISIG and OP_CHECKMULTISIGVERIFY. The disabled opcodes behave in the same way as OP_RETURN, by failing and terminating the script immediately when executed, and being ignored when found in unexecuted branch. * '''Consensus-enforced MINIMALIF''' The MINIMALIF rules, which are only a standardness rule in P2WSH, are consensus enforced in tapscript. This means that the input argument to the OP_IF and OP_NOTIF opcodes must be either exactly 0 (the empty vector) or exactly 1 (the one-byte vector with value 1)'''Why make MINIMALIF consensus?''' This makes it considerably easier to write non-malleable scripts that take branch information from the stack.. * '''OP_SUCCESSx opcodes''' As listed above, some opcodes are renamed to OP_SUCCESSx, and make the script unconditionally valid. * '''Signature opcodes'''. The OP_CHECKSIG and OP_CHECKSIGVERIFY are modified to operate on Schnorr public keys and signatures (see bip-schnorr) instead of ECDSA, and a new opcode OP_CHECKSIGADD is added. -** The opcode 186 (0xba) is named as OP_CHECKSIGADD. '''OP_CHECKSIGADD''' This opcode is added to compensate for the loss of OP_CHECKMULTISIG-like opcodes, which are incompatible with batch verification. OP_CHECKSIGADD is functionally equivalent to OP_ROT OP_SWAP OP_CHECKSIG OP_ADD, but is only counted as one opcode towards the 201 non-push opcodes limit. All CScriptNum-related behaviours of OP_ADD are also applicable to OP_CHECKSIGADD.'''Comparison of CHECKMULTISIG and CHECKSIG''' A CHECKMULTISIG script m ... n CHECKMULTISIG with witness 0 ... can be rewritten as script CHECKSIG ... CHECKSIGADD m NUMEQUAL with witness ... . Every witness element w_i is either a signature corresponding to the public key with the same index or an empty vector. A similar CHECKMULTISIGVERIFY script can be translated to bip-tapscript by replacing NUMEQUAL with NUMEQUALVERIFY. Alternatively, an m-of-n multisig policy can be implemented by splitting the script into several leaves of the Merkle tree, each implementing an m-of-m policy using CHECKSIGVERIFY ... CHECKSIGVERIFY CHECKSIG. If the setting allows the participants to interactively collaborate while signing, multisig policies can be realized with [https://eprint.iacr.org/2018/068 MuSig] for m-of-m and with [http://cacr.uwaterloo.ca/techreports/2001/corr2001-13.ps threshold signatures] using verifiable secret sharing for m-of-n. +** The opcode 186 (0xba) is named as OP_CHECKSIGADD. '''OP_CHECKSIGADD''' This opcode is added to compensate for the loss of OP_CHECKMULTISIG-like opcodes, which are incompatible with batch verification. OP_CHECKSIGADD is functionally equivalent to OP_ROT OP_SWAP OP_CHECKSIG OP_ADD, but only takes 1 byte. All CScriptNum-related behaviours of OP_ADD are also applicable to OP_CHECKSIGADD.'''Comparison of CHECKMULTISIG and CHECKSIG''' A CHECKMULTISIG script m ... n CHECKMULTISIG with witness 0 ... can be rewritten as script CHECKSIG ... CHECKSIGADD m NUMEQUAL with witness ... . Every witness element w_i is either a signature corresponding to the public key with the same index or an empty vector. A similar CHECKMULTISIGVERIFY script can be translated to bip-tapscript by replacing NUMEQUAL with NUMEQUALVERIFY. Alternatively, an m-of-n multisig policy can be implemented by splitting the script into several leaves of the Merkle tree, each implementing an m-of-m policy using CHECKSIGVERIFY ... CHECKSIGVERIFY CHECKSIG. If the setting allows the participants to interactively collaborate while signing, multisig policies can be realized with [https://eprint.iacr.org/2018/068 MuSig] for m-of-m and with [http://cacr.uwaterloo.ca/techreports/2001/corr2001-13.ps threshold signatures] using verifiable secret sharing for m-of-n. ===Rules for signature opcodes=== @@ -97,8 +97,6 @@ The following rules apply to OP_CHECKSIG, OP_CHECKSIGVERIFYOP_CHECKSIG, a 1-byte value 0x01 is pushed onto the stack. *** For OP_CHECKSIGADD, a CScriptNum with value of n + 1 is pushed onto the stack. -These opcodes count toward the 201 non-push opcodes limit. - ===Transaction digest=== As the message for signature opcodes signature verification, transaction digest has the same definition as in bip-taproot, except the following: @@ -122,16 +120,14 @@ In summary, the semantics of the BIP143 sighash types remain unchanged, except t # The digest commits to the executed script through the tapleaf_hash which includes the leaf version and script instead of scriptCode. This implies that this commitment is unaffected by OP_CODESEPARATOR. # The digest commits to the opcode position of the last executed OP_CODESEPARATOR.'''Why does the transaction digest commit to the position of the last executed OP_CODESEPARATOR?''' This allows continuing to use OP_CODESEPARATOR to sign the executed path of the script. Because the codeseparator_position is the last input to the digest, the SHA256 midstate can be efficiently cached for multiple OP_CODESEPARATORs in a single script. In contrast, the BIP143 handling of OP_CODESEPARATOR is to commit to the executed script only from the last executed OP_CODESEPARATOR onwards which requires unnecessary rehashing of the script. It should be noted that the one known OP_CODESEPARATOR use case of saving a second public key push in a script by sharing the first one between two code branches can be most likely expressed even cheaper by moving each branch into a separate taproot leaf. -===Signature opcodes limitation=== - -In addition to the 201 non-push opcodes limit, the use of signature opcodes is subject to further limitations. - -* input_witness_weight is defined as the size of the serialized input witness associated to a particular transaction input. As defined in BIP141, a serialized input witness includes CCompactSize tags indicating the number of elements and size of each element, and contents of each element. input_witness_weight is the total size of the said CCompactSize tags and element contents. -* sigops_passed is defined as the total number of successfully executed signature opcodes, which have non-zero signature size and do not fail and terminate the script. For the avoidance of doubt, passing signature opcodes with unknown type public key and non-zero size signature are also counted towards sigops_passed. -* If 50 * (sigops_passed - 1) is greater than input_witness_weight, the script MUST fail and terminate immediately. +===Resource limits=== -This rule limits worst-case validation costs in tapscript similar to the ''sigops limit'' that only applies to legacy and P2WSH scripts'''The tapscript sigop limit''' The signature opcode limit protects against scripts which are slow to verify due to excessively many signature operations. In tapscript the number of signature opcodes does not count towards the BIP141 or legacy sigop limit. The old sigop limit makes transaction selection in block construction unnecessarily difficult because it is a second constraint in addition to weight. Instead, the number of tapscript signature opcodes is limited by witness weight. Additionally, the limit applies to the transaction input instead of the block and only actually executed signature opcodes are counted. Tapscript execution allows one signature opcode per 50 witness weight units plus one free signature opcode. The tapscript signature opcode limit allows to add new signature opcodes like CHECKSIGFROMSTACK to count towards the limit through a soft fork. Even if in the future new opcodes are introduced which change normal script cost there is need to stuff the witness with meaningless data. In that case the taproot annex can be used to add weight to the witness without increasing the actual witness size. -'''Parameter choice of the sigop limit''' Regular witnesses are unaffected by the limit as their weight is composed of public key and (SIGHASH_ALL) signature pairs with ''33 + 65'' weight units each (which includes a 1 weight unit CCompactSize tag). This is also the case if public keys are reused in the script because a signature's weight alone is 65 or 66 weight units. However, the limit increases the fees of abnormal scripts with duplicate signatures (and public keys) by requiring additional weight. The weight per sigop factor 50 corresponds to the ratio of BIP141 block limits: 4 mega weight units divided by 80,000 sigops. The "free" signature opcode permitted by the limit exists to account for the weight of the non-witness parts of the transaction input.. +In addition to changing the semantics of a number of opcodes, there are also some changes to the resource limitations: +* '''Script size limit''' The maximum script size of 10000 bytes does not apply. Their size is only implicitly limited by the limits on transaction and block size.'''Why is a limit on script size no longer needed?''' Since there is no scriptCode directly included in the signature hash (only indirectly through a precomputable tapleaf hash), the CPU time spent on a signature check is no longer proportional to the size of the script being executed. +* '''Non-push opcodes limit''' The maximum non-push opcodes limit of 201 per script does not apply.'''Why is a limit on the number of opcodes no longer needed?''' An opcode limit only helps to the extent that it can prevent data structures from growing unboundedly during execution (both because of memory usage, and because of time that may grow in proportion to the size of those structures. The size of stack and altstack is already independently limited. Using O(1) logic for OP_IF, OP_NOTIF, OP_ELSE, and OP_ENDIF like suggested [https://bitslog.com/2017/04/17/new-quadratic-delays-in-bitcoin-scripts/ here] and implemented [https://github.com/bitcoin/bitcoin/pull/16902 here] the only other instance can be avoided as well. +* '''Sigops limit''' The sigops in tapscripts do not count towards the block-wide limit of 80000 (weighted). Instead, there is a per-script sigops ''budget''. The budget equals 50 + the total serialized size in bytes of the transaction input's witness (including the CCompactSize prefix). Executing a signature opcode (OP_CHECKSIG, OP_CHECKSIGVERIFY, or OP_CHECKSIGADD) with a non-empty signature decrements the budget by 50. If that brings the budget below zero, the script fails immediately. Signature opcodes with unknown public key type and non-empty signature are also counted.'''The tapscript sigop limit''' The signature opcode limit protects against scripts which are slow to verify due to excessively many signature operations. In tapscript the number of signature opcodes does not count towards the BIP141 or legacy sigop limit. The old sigop limit makes transaction selection in block construction unnecessarily difficult because it is a second constraint in addition to weight. Instead, the number of tapscript signature opcodes is limited by witness weight. Additionally, the limit applies to the transaction input instead of the block and only actually executed signature opcodes are counted. Tapscript execution allows one signature opcode per 50 witness weight units plus one free signature opcode.'''Parameter choice of the sigop limit''' Regular witnesses are unaffected by the limit as their weight is composed of public key and (SIGHASH_ALL) signature pairs with ''33 + 65'' weight units each (which includes a 1 weight unit CCompactSize tag). This is also the case if public keys are reused in the script because a signature's weight alone is 65 or 66 weight units. However, the limit increases the fees of abnormal scripts with duplicate signatures (and public keys) by requiring additional weight. The weight per sigop factor 50 corresponds to the ratio of BIP141 block limits: 4 mega weight units divided by 80,000 sigops. The "free" signature opcode permitted by the limit exists to account for the weight of the non-witness parts of the transaction input.'''Why are only signature opcodes counted toward the budget, and not for example hashing opcodes or other expensive operations?''' It turns out that the CPU cost per witness byte for verification of a script consisting of the maximum density of signature checking opcodes (taking the 50 WU/sigop limit into account) is already very close to that of scripts packed with other opcodes, including hashing opcodes (taking the 520 byte stack element limit into account) and OP_ROLL (taking the 1000 stack element limit into account). That said, the construction is very flexible, and allows adding new signature opcodes like CHECKSIGFROMSTACK to count towards the limit through a soft fork. Even if in the future new opcodes are introduced which change normal script cost there is no need to stuff the witness with meaningless data. Instead, the taproot annex can be used to add weight to the witness without increasing the actual witness size.. +* '''Stack + altstack element count limit''' The existing limit of 1000 elements in the stack and altstack together after every executed opcode remains. It is extended to also apply to the size of initial stack. +* '''Stack element size limit''' The existing limit of maximum 520 bytes per stack element remains, both in the initial stack and in push opcodes. ==Rationale== -- cgit v1.2.3 From 1ee15f7dd9315f24a681ef3b49f2db49e48298d0 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 20 Sep 2019 16:14:25 -0700 Subject: Remove P2SH support --- bip-taproot.mediawiki | 22 ++++++++++------------ bip-tapscript.mediawiki | 13 ++++++------- 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 76c23dc..0823c6b 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -54,10 +54,10 @@ The notation below follows that of bip-schnorr. === Script validation rules === -A Taproot output is a SegWit output (native or P2SH-nested, see [https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki BIP141]) with version number 1, and a 32-byte witness program. -The following rules only apply when such an output is being spent. Any other outputs, including version 1 outputs with lengths other than 32 bytes, remain unencumbered. +A Taproot output is a native SegWit output (see [https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki BIP141]) with version number 1, and a 32-byte witness program. +The following rules only apply when such an output is being spent. Any other outputs, including version 1 outputs with lengths other than 32 bytes, or P2SH-wrapped version 1 outputs, remain unencumbered. -* Let ''q'' be the 32-byte array containing the witness program (second push in scriptPubKey or P2SH redeemScript) which represents a public key according to bip-schnorr. +* Let ''q'' be the 32-byte array containing the witness program (the second push in the scriptPubKey) which represents a public key according to bip-schnorr. * Fail if the witness stack has 0 elements. * If there are at least two witness elements, and the first byte of the last element is 0x50'''Why is the first byte of the annex 0x50?''' Like the 0xc0-0xc1 constants, 0x50 is chosen as it could not be confused with a valid P2WPKH or P2WSH spending. As the control block's initial byte's lowest bit is used to indicate the public key's Y quadratic residuosity, each script version needs two subsequence byte values that are both not yet used in P2WPKH or P2WSH spending. To indicate the annex, only an "unpaired" available byte is necessary like 0x50. This choice maximizes the available options for future script versions., this last element is called ''annex'' ''a'''''What is the purpose of the annex?''' The annex is a reserved space for future extensions, such as indicating the validation costs of computationally expensive new opcodes in a way that is recognizable without knowing the outputs being spent. Until the meaning of this field is defined by another softfork, users SHOULD NOT include annex in transactions, or it may lead to PERMANENT FUND LOSS. and is removed from the witness stack. The annex (or the lack of thereof) is always covered by the transaction digest and contributes to transaction weight, but is otherwise ignored during taproot validation. * If there is exactly one element left in the witness stack, key path spending is used: @@ -126,10 +126,9 @@ As the message for signature verification, transaction digest is ''hashTapS *** sha_outputs (32): the SHA256 of the serialization of all outputs in CTxOut format. * Data about this input: ** spend_type (1): -*** Bit-0 is set if the scriptPubKey being spent is P2SH (opposed to "native segwit"). -*** Bit-1 is set if an annex is present (the original witness stack has two or more witness elements, and the first byte of the last element is 0x50). +*** Bit 0 is set if an annex is present (the original witness stack has two or more witness elements, and the first byte of the last element is 0x50). *** The other bits are unset. -** scriptPubKey (24 or 35): scriptPubKey of the previous output spent by this input, serialized as script inside CTxOut. The size is 24-byte for P2SH-embedded segwit, or 35-byte for native segwit. +** scriptPubKey (35): scriptPubKey of the previous output spent by this input, serialized as script inside CTxOut. Its size is always 35 bytes. ** If the SIGHASH_ANYONECANPAY flag is set: *** outpoint (36): the COutPoint of this input (32-byte hash + 4-byte little-endian). *** amount (8): value of the previous output spent by this input. @@ -142,11 +141,11 @@ As the message for signature verification, transaction digest is ''hashTapS ** If the SIGHASH_SINGLE flag is set: *** sha_single_output (32): the SHA256 of the corresponding output in CTxOut format. -The total number of bytes hashed is at most ''209'''''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''176 - is_anyonecanpay * 50 - is_none * 32 - is_p2sh_spending * 11 + has_annex * 32''.. +The total number of bytes hashed is at most ''209'''''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''176 - is_anyonecanpay * 50 - is_none * 32 + has_annex * 32''.. In summary, the semantics of the BIP143 sighash types remain unchanged, except the following: # The way and order of serialization is changed.'''Why is the serialization in the transaction digest changed?''' Hashes that go into the digest and the digest itself are now computed with a single SHA256 invocation instead of double SHA256. There is no expected security improvement by doubling SHA256 because this only protects against length-extension attacks against SHA256 which are not a concern for transaction digests because there is no secret data. Therefore doubling SHA256 is a waste of resources. The digest computation now follows a logical order with transaction level data first, then input data and output data. This allows to efficiently cache the transaction part of the digest across different inputs using the SHA256 midstate. Additionally, digest computation avoids unnecessary hashing as opposed to BIP143 digests in which parts may be set zero and before hashing them. Despite that, collisions are made impossible by committing to the length of the data (implicit in hash_type and spend_type) before the variable length data. -# The digest commits to the scriptPubKey'''Why does the transaction digest commit to the scriptPubKey?''' This prevents lying to offline signing devices about the type of output being spent, even when the actually executed script (scriptCode in BIP143) is correct. Without committing to the scriptPubKey an attacker can fool the device into overpaying fees by asking it to sign for a P2SH wrapped segwit output but actually using it to spend a native segwit output.. +# The digest commits to the scriptPubKey'''Why does the transaction digest commit to the scriptPubKey?''' This prevents lying to offline signing devices about output being spent, even when the actually executed script (scriptCode in BIP143) is correct. This means it's possible to compactly prove to a hardware wallet what (unused) execution paths existed.. # If the SIGHASH_ANYONECANPAY flag is not set, the digest commits to the amounts of ''all'' transaction inputs.'''Why does the transaction digest commit to the amounts of all transaction inputs?''' This eliminates the possibility to lie to offline signing devices about the fee of a transaction. # The digest commits to all input nSequence if SIGHASH_NONE or SIGHASH_SINGLE are set (unless SIGHASH_ANYONECANPAY is set as well).'''Why does the transaction digest commit to all input nSequence if SIGHASH_SINGLE or SIGHASH_NONE are set?''' Because setting them already makes the digest commit to the prevouts part of all transaction inputs, it is not useful to treat the nSequence any different. Moreover, this change makes nSequence consistent with the view that SIGHASH_SINGLE and SIGHASH_NONE only modify the digest with respect to transaction outputs and not inputs. # The digest commits to taproot-specific data epoch, spend_type and annex (if present). @@ -208,7 +207,7 @@ def taproot_output_script(internal_pubkey, script_tree): return bytes([0x51, 0x20]) + output_pubkey.get_bytes() -The function taproot_output_script returns a byte array with the scriptPubKey. It can be P2SH wrapped if desired (see BIP141). +The function taproot_output_script returns a byte array with the scriptPubKey (see BIP141). [[File:bip-taproot/tree.png|frame|This diagram shows the hashing structure to obtain the tweak from an internal key ''P'' and a Merkle tree consisting of 5 script leaves. ''A'', ''B'', ''C'' and ''E'' are ''TapLeaf'' hashes similar to ''D'' and ''AB'' is a ''TapBranch'' hash. Note that when ''CDE'' is computed ''E'' is hashed first because ''E'' is less than ''CD''.]] @@ -229,7 +228,7 @@ def taproot_sign_key(script_tree, internal_privkey, hash_type): return [sig] -This function returns the witness stack necessary, and assumes a tweak_add method on private keys, and a sighash function to compute the signature hash as defined above (for simplicity, the snippet above ignores passing information like the transaction, the input position, P2SH or not, ... to the sighashing code). +This function returns the witness stack necessary, and assumes a tweak_add method on private keys, and a sighash function to compute the signature hash as defined above (for simplicity, the snippet above ignores passing information like the transaction, the input position, ... to the sighashing code). '''Spending using one of the scripts''' A Taproot output can be spent by satisfying any of the scripts used in its construction. To do so, a witness stack consisting of the script's inputs, plus the script itself and the control block are necessary. See the code below: @@ -282,8 +281,7 @@ Non-upgraded nodes, however, will consider all SegWit version 1 witness programs They are strongly encouraged to upgrade in order to fully validate the new programs. Non-upgraded wallets can receive and send bitcoin from non-upgraded and upgraded wallets using SegWit version 0 programs, traditional pay-to-pubkey-hash, etc. -Depending on the implementation non-upgraded wallets may be able to send to Segwit version 1 programs if they support sending to BIP173 Bech32 addresses and non-standardness of these outputs does not prevent transaction broadcasting. -Non-upgraded wallets can send bitcoin to upgraded wallets using Segwit version 1 programs nested in BIP16 P2SH. +Depending on the implementation non-upgraded wallets may be able to send to Segwit version 1 programs if they support sending to BIP173 Bech32 addresses. == Acknowledgements == diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index 603990e..0f4fdf5 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -44,8 +44,8 @@ Additionally, the new tapscript OP_SUCCESS opcodes allow introducin ==Specification== The rules below only apply when validating a transaction input for which all of the conditions below are true: -* The transaction output is a '''segregated witness spend''' (i.e., either the scriptPubKey or BIP16 redeemScript is a witness program as defined in BIP141). -* It is a '''taproot spend''' as defined in bip-taproot (i.e., the witness version is 1, the witness program is 32 bytes). +* The transaction output is a '''segregated witness spend''' (i.e., the scriptPubKey is a witness program as defined in BIP141). +* It is a '''taproot spend''' as defined in bip-taproot (i.e., the witness version is 1, the witness program is 32 bytes, and it is not P2SH wrapped). * It is a '''script path spend''' as defined in bip-taproot (i.e., after removing the optional annex from the witness stack, two or more stack elements remain). * The leaf version is ''0xc0'' (i.e. the first byte of the last witness element after removing the optional annex is ''0xc0'')'''How is the ''0xc0'' constant chosen?''' Following the guidelines in bip-taproot, by choosing a value having the two top bits set, tapscript spends are identifiable even without access to the UTXO being spent., marking it as a '''tapscript spend'''. @@ -103,10 +103,9 @@ These opcodes count toward the 201 non-push opcodes limit. As the message for signature opcodes signature verification, transaction digest has the same definition as in bip-taproot, except the following: -The one-byte spend_type has a different value, specificially at bit-2: -* Bit-0 is set if the scriptPubKey being spent is P2SH (opposed to "native segwit"). -* Bit-1 is set if an annex is present (the original witness stack has at least two witness elements, and the first byte of the last element is 0x50). -* Bit-2 is set. +The one-byte spend_type has a different value, specificially at bit 1: +* Bit 0 is set if an annex is present (the original witness stack has at least two witness elements, and the first byte of the last element is 0x50). +* Bit 1 is set. * The other bits are unset. As additional pieces of data, added at the end of the input to the ''hashTapSighash'' function: @@ -114,7 +113,7 @@ As additional pieces of data, added at the end of the input to the ''hashTa * key_version (1): a constant value 0x00 representing the current version of public keys in the tapscript signature opcode execution. * codeseparator_position (2): the opcode position of the last executed OP_CODESEPARATOR before the currently executed signature opcode, with the value in little endian (or 0xffff if none executed). The first opcode in a script has a position of 0. A multi-byte push opcode is counted as one opcode, regardless of the size of data being pushed. -The total number of bytes hashed is at most ''244'''''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''211 - is_anyonecanpay * 50 - is_none * 32 - is_p2sh_spending * 11 + has_annex * 32''.. +The total number of bytes hashed is at most ''244'''''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''211 - is_anyonecanpay * 50 - is_none * 32 + has_annex * 32''.. In summary, the semantics of the BIP143 sighash types remain unchanged, except the following: # The exceptions mentioned in bip-taproot. -- cgit v1.2.3 From aa463b8193624e28d462aafbd14f9d173dd85e5e Mon Sep 17 00:00:00 2001 From: Elichai Turkel Date: Mon, 23 Sep 2019 02:06:14 +0300 Subject: Euler's Criterion prime only nit --- bip-schnorr.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index e1fe634..0473a29 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -116,7 +116,7 @@ The following convention is used, with constants as defined for secp256k1: *** Return the unique point ''P'' such that ''x(P) = x'' and ''y(P) = y''. ** The function ''point(x)'', where ''x'' is a 32-byte array, returns the point ''P = lift_x(int(x))''. ** The function ''hashtag(x)'' where ''tag'' is a UTF-8 encoded tag name and ''x'' is a byte array returns the 32-byte hash ''SHA256(SHA256(tag) || SHA256(tag) || x)''. -** The function ''jacobi(x)'', where ''x'' is an integer, returns the [https://en.wikipedia.org/wiki/Jacobi_symbol Jacobi symbol] of ''x / p''. It is equal to ''x(p-1)/2 mod p'' ([https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion])For points ''P'' on the secp256k1 curve it holds that ''jacobi(y(P)) ≠ 0''.. +** The function ''jacobi(x)'', where ''x'' is an integer, returns the [https://en.wikipedia.org/wiki/Jacobi_symbol Jacobi symbol] of ''x / p''. Since ''p'' is prime, it is equal to ''x(p-1)/2 mod p'' ([https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion])For points ''P'' on the secp256k1 curve it holds that ''jacobi(y(P)) ≠ 0''.. ** The function ''pubkey(x)'', where ''x'' is a 32-byte array, returns ''bytes(dG)'' where ''d = int(x) mod n''. ==== Public Key Generation ==== -- cgit v1.2.3 From 079ae4b048c8f58ee98cefd864f15051cfdf0ccf Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 23 Sep 2019 13:24:33 -0700 Subject: Fixups --- bip-tapscript.mediawiki | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index f4aaf34..a40cfc8 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -59,7 +59,6 @@ Validation of such inputs must be equivalent to performing the following steps i * Given that OP_SUCCESSx even causes potentially unparseable scripts to pass, it can be used to introduce multi-byte opcodes, or even a completely new scripting language when prefixed with a specific OP_SUCCESSx opcode.. ## If any push opcode fails to decode because it would extend past the end of the tapscript, fail. # If the size of any element in the '''initial stack''' as defined in bip-taproot (i.e., the witness stack after removing both the optional annex and the two last stack elements after that) is bigger than 520 bytes, fail. -# If the tapscript is bigger than 10000 bytes, fail. # The tapscript is executed according to the rules in the following section, with the initial stack as input. ## If execution fails for any reason, fail. ## If the execution results in anything but exactly one element on the stack which evaluates to true with CastToBool(), fail. @@ -92,7 +91,7 @@ The following rules apply to OP_CHECKSIG, OP_CHECKSIGVERIFYOP_CHECKSIGVERIFY, the script MUST fail and terminate immediately. *** For OP_CHECKSIG, an empty vector is pushed onto the stack, and execution continues with the next opcode. *** For OP_CHECKSIGADD, a CScriptNum with value n is pushed onto the stack, and execution continues with the next opcode. -** If the signature is not the empty vector, the sigops_passed counter is incremented (see further) +** If the signature is not the empty vector, the opcode is counted towards the sigops budget (see further). *** For OP_CHECKSIGVERIFY, execution continues without any further changes to the stack. *** For OP_CHECKSIG, a 1-byte value 0x01 is pushed onto the stack. *** For OP_CHECKSIGADD, a CScriptNum with value of n + 1 is pushed onto the stack. -- cgit v1.2.3 From 4c2eb9a6007ed30ae39e1c728d8398b811a46dc5 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 23 Sep 2019 22:48:12 -0700 Subject: Extend codeseparator_position from 16 to 32 bits --- bip-tapscript.mediawiki | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index a40cfc8..87b307a 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -108,9 +108,9 @@ The one-byte spend_type has a different value, specificially at bit As additional pieces of data, added at the end of the input to the ''hashTapSighash'' function: * tapleaf_hash (32): the tapleaf hash as defined in bip-taproot * key_version (1): a constant value 0x00 representing the current version of public keys in the tapscript signature opcode execution. -* codeseparator_position (2): the opcode position of the last executed OP_CODESEPARATOR before the currently executed signature opcode, with the value in little endian (or 0xffff if none executed). The first opcode in a script has a position of 0. A multi-byte push opcode is counted as one opcode, regardless of the size of data being pushed. +* codeseparator_position (4): the opcode position of the last executed OP_CODESEPARATOR before the currently executed signature opcode, with the value in little endian (or 0xffffffff if none executed). The first opcode in a script has a position of 0. A multi-byte push opcode is counted as one opcode, regardless of the size of data being pushed. -The total number of bytes hashed is at most ''244'''''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''211 - is_anyonecanpay * 50 - is_none * 32 + has_annex * 32''.. +The total number of bytes hashed is at most ''246'''''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''213 - is_anyonecanpay * 50 - is_none * 32 + has_annex * 32''.. In summary, the semantics of the BIP143 sighash types remain unchanged, except the following: # The exceptions mentioned in bip-taproot. -- cgit v1.2.3 From 0d5ac28f2c9612b6d7d316d54d601fe1fb0a07e0 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 24 Sep 2019 10:36:41 -0700 Subject: Extend input_index from 16 to 32 bits --- bip-taproot.mediawiki | 4 ++-- bip-tapscript.mediawiki | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 7a81949..062a88a 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -134,14 +134,14 @@ As the message for signature verification, transaction digest is ''hashTapS *** amount (8): value of the previous output spent by this input. *** nSequence (4): nSequence of this input. ** If the SIGHASH_ANYONECANPAY flag is not set: -*** input_index (2): index of this input in the transaction input vector. Index of the first input is 0. +*** input_index (4): index of this input in the transaction input vector. Index of the first input is 0. ** If the bit-1 of spend_type is set: *** sha_annex (32): the SHA256 of (compact_size(size of annex) || annex). * Data about this output: ** If the SIGHASH_SINGLE flag is set: *** sha_single_output (32): the SHA256 of the corresponding output in CTxOut format. -The total number of bytes hashed is at most ''209'''''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''176 - is_anyonecanpay * 50 - is_none * 32 + has_annex * 32''.. +The total number of bytes hashed is at most ''211'''''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''178 - is_anyonecanpay * 50 - is_none * 32 + has_annex * 32''.. In summary, the semantics of the BIP143 sighash types remain unchanged, except the following: # The way and order of serialization is changed.'''Why is the serialization in the transaction digest changed?''' Hashes that go into the digest and the digest itself are now computed with a single SHA256 invocation instead of double SHA256. There is no expected security improvement by doubling SHA256 because this only protects against length-extension attacks against SHA256 which are not a concern for transaction digests because there is no secret data. Therefore doubling SHA256 is a waste of resources. The digest computation now follows a logical order with transaction level data first, then input data and output data. This allows to efficiently cache the transaction part of the digest across different inputs using the SHA256 midstate. Additionally, digest computation avoids unnecessary hashing as opposed to BIP143 digests in which parts may be set zero and before hashing them. Despite that, collisions are made impossible by committing to the length of the data (implicit in hash_type and spend_type) before the variable length data. diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index 87b307a..1b9d429 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -110,7 +110,7 @@ As additional pieces of data, added at the end of the input to the ''hashTa * key_version (1): a constant value 0x00 representing the current version of public keys in the tapscript signature opcode execution. * codeseparator_position (4): the opcode position of the last executed OP_CODESEPARATOR before the currently executed signature opcode, with the value in little endian (or 0xffffffff if none executed). The first opcode in a script has a position of 0. A multi-byte push opcode is counted as one opcode, regardless of the size of data being pushed. -The total number of bytes hashed is at most ''246'''''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''213 - is_anyonecanpay * 50 - is_none * 32 + has_annex * 32''.. +The total number of bytes hashed is at most ''248'''''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''215 - is_anyonecanpay * 50 - is_none * 32 + has_annex * 32''.. In summary, the semantics of the BIP143 sighash types remain unchanged, except the following: # The exceptions mentioned in bip-taproot. -- cgit v1.2.3 From 7ce33c01ec57170e1b64f264b6bb499153cd3f10 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Wed, 25 Sep 2019 14:02:42 +1000 Subject: typo --- bip-tapscript.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index a40cfc8..1d3e6fa 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -100,7 +100,7 @@ The following rules apply to OP_CHECKSIG, OP_CHECKSIGVERIFYspend_type has a different value, specificially at bit 1: +The one-byte spend_type has a different value, specifically at bit 1: * Bit 0 is set if an annex is present (the original witness stack has at least two witness elements, and the first byte of the last element is 0x50). * Bit 1 is set. * The other bits are unset. -- cgit v1.2.3 From f8313861030fb19948434d203d823fa4272cd4cf Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Wed, 25 Sep 2019 14:14:14 +1000 Subject: separate p2sh wrapped security rationale --- bip-taproot.mediawiki | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 7a81949..64d8b94 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -42,7 +42,7 @@ As a result we choose this combination of technologies: * As Schnorr signatures also permit '''batch validation''', allowing multiple signatures to be validated together more efficiently than validating each one independently, we make sure all parts of the design are compatible with this. * Where unused bits appear as a result of the above changes, they are reserved for mechanisms for '''future extensions'''. As a result, every script in the Merkle tree has an associated version such that new script versions can be introduced with a soft fork while remaining compatible with bip-taproot. Additionally, future soft forks can make use of the currently unused annex in the witness (see [[#Rationale]]). * While the core semantics of the '''signature hashing algorithm''' are not changed, a number of improvements are included in this proposal. The new signature hashing algorithm fixes the verification capabilities of offline signing devices by including amount and scriptPubKey in the digest, avoids unnecessary hashing, uses '''tagged hashes''' and defines a default sighash byte. -* The '''public key is directly included in the output''' in contrast to typical earlier constructions which store a hash of the public key or script in the output. This has the same cost for senders and is more space efficient overall if the key-based spending path is taken. '''Why is the public key directly included in the output?''' While typical earlier constructions store a hash of a script or a public key in the output, this is rather wasteful when a public key is always involved. To guarantee batch verifiability, ''q'' must be known to every verifier, and thus only revealing its hash as an output would imply adding an additional 32 bytes to the witness. Furthermore, to maintain [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2016-January/012198.html 128-bit collision security] for outputs, a 256-bit hash would be required anyway, which is comparable in size (and thus in cost for senders) to revealing the public key directly. While the usage of public key hashes is often said to protect against ECDLP breaks or quantum computers, this protection is very weak at best: transactions are not protected while being confirmed, and a very [https://twitter.com/pwuille/status/1108097835365339136 large portion] of the currency's supply is not under such protection regardless. Actual resistance to such systems can be introduced by relying on different cryptographic assumptions, but this proposal focuses on improvements that do not change the security model. Note that using P2SH-wrapped outputs only have 80-bit collision security. This is considered low, and is relevant whenever the output includes data from more than a single party (public keys, hashes, ...). . +* The '''public key is directly included in the output''' in contrast to typical earlier constructions which store a hash of the public key or script in the output. This has the same cost for senders and is more space efficient overall if the key-based spending path is taken. '''Why is the public key directly included in the output?''' While typical earlier constructions store a hash of a script or a public key in the output, this is rather wasteful when a public key is always involved. To guarantee batch verifiability, ''q'' must be known to every verifier, and thus only revealing its hash as an output would imply adding an additional 32 bytes to the witness. Furthermore, to maintain [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2016-January/012198.html 128-bit collision security] for outputs, a 256-bit hash would be required anyway, which is comparable in size (and thus in cost for senders) to revealing the public key directly. While the usage of public key hashes is often said to protect against ECDLP breaks or quantum computers, this protection is very weak at best: transactions are not protected while being confirmed, and a very [https://twitter.com/pwuille/status/1108097835365339136 large portion] of the currency's supply is not under such protection regardless. Actual resistance to such systems can be introduced by relying on different cryptographic assumptions, but this proposal focuses on improvements that do not change the security model. Not included in this proposal are additional features like new sighash modes or opcodes that can be included with no loss in effectiveness as a future extension. Also not included is cross-input aggregation, as it [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-March/015838.html interacts] in complex ways with upgrade mechanisms and solutions to that are still [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-October/016461.html in flux]. @@ -55,7 +55,7 @@ The notation below follows that of bip-schnorr. This includes the ''hashtag === Script validation rules === A Taproot output is a native SegWit output (see [https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki BIP141]) with version number 1, and a 32-byte witness program. -The following rules only apply when such an output is being spent. Any other outputs, including version 1 outputs with lengths other than 32 bytes, or P2SH-wrapped version 1 outputs, remain unencumbered. +The following rules only apply when such an output is being spent. Any other outputs, including version 1 outputs with lengths other than 32 bytes, or P2SH-wrapped version 1 outputs'''Why is P2SH-wrapping not supported?''' Using P2SH-wrapped outputs only provides 80-bit collision security due to the use of a 160-bit hash. This is considered low, and becomes a security risk whenever the output includes data from more than a single party (public keys, hashes, ...)., remain unencumbered. * Let ''q'' be the 32-byte array containing the witness program (the second push in the scriptPubKey) which represents a public key according to bip-schnorr. * Fail if the witness stack has 0 elements. -- cgit v1.2.3 From 479fe5f365a416115b8029fca121e59adfaa7e6d Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Wed, 25 Sep 2019 21:02:43 +0000 Subject: Remove 0xc1 --- bip-taproot.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 64d8b94..75eacca 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -59,7 +59,7 @@ The following rules only apply when such an output is being spent. Any other out * Let ''q'' be the 32-byte array containing the witness program (the second push in the scriptPubKey) which represents a public key according to bip-schnorr. * Fail if the witness stack has 0 elements. -* If there are at least two witness elements, and the first byte of the last element is 0x50'''Why is the first byte of the annex 0x50?''' Like the 0xc0-0xc1 constants, 0x50 is chosen as it could not be confused with a valid P2WPKH or P2WSH spending. As the control block's initial byte's lowest bit is used to indicate the public key's Y quadratic residuosity, each script version needs two subsequence byte values that are both not yet used in P2WPKH or P2WSH spending. To indicate the annex, only an "unpaired" available byte is necessary like 0x50. This choice maximizes the available options for future script versions., this last element is called ''annex'' ''a'''''What is the purpose of the annex?''' The annex is a reserved space for future extensions, such as indicating the validation costs of computationally expensive new opcodes in a way that is recognizable without knowing the outputs being spent. Until the meaning of this field is defined by another softfork, users SHOULD NOT include annex in transactions, or it may lead to PERMANENT FUND LOSS. and is removed from the witness stack. The annex (or the lack of thereof) is always covered by the transaction digest and contributes to transaction weight, but is otherwise ignored during taproot validation. +* If there are at least two witness elements, and the first byte of the last element is 0x50'''Why is the first byte of the annex 0x50?''' Like the 0xc0 constant, 0x50 is chosen as it could not be confused with a valid P2WPKH or P2WSH spending. As the control block's initial byte's lowest bit is used to indicate the public key's Y quadratic residuosity, each script version needs two subsequence byte values that are both not yet used in P2WPKH or P2WSH spending. To indicate the annex, only an "unpaired" available byte is necessary like 0x50. This choice maximizes the available options for future script versions., this last element is called ''annex'' ''a'''''What is the purpose of the annex?''' The annex is a reserved space for future extensions, such as indicating the validation costs of computationally expensive new opcodes in a way that is recognizable without knowing the outputs being spent. Until the meaning of this field is defined by another softfork, users SHOULD NOT include annex in transactions, or it may lead to PERMANENT FUND LOSS. and is removed from the witness stack. The annex (or the lack of thereof) is always covered by the transaction digest and contributes to transaction weight, but is otherwise ignored during taproot validation. * If there is exactly one element left in the witness stack, key path spending is used: ** The single witness stack element is interpreted as the signature and must be valid (see the next section) for the public key ''q'' and taproot transaction digest (to be defined hereinafter) as message. Fail if it is not. Otherwise pass. * If there are at least two witness elements left, script path spending is used: -- cgit v1.2.3 From 472911379c2493a5cb4192653f8c14b9fa0c612b Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Thu, 26 Sep 2019 21:12:21 +0000 Subject: Accept seckey in the form of bytes and not int in the reference BIP-schnorr code to match the spec. --- bip-schnorr/reference.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/bip-schnorr/reference.py b/bip-schnorr/reference.py index 95e9e53..ae8ef6e 100644 --- a/bip-schnorr/reference.py +++ b/bip-schnorr/reference.py @@ -57,12 +57,16 @@ def jacobi(x): return pow(x, (p - 1) // 2, p) def pubkey_gen(seckey): - P = point_mul(G, seckey) + x = int_from_bytes(seckey) + if not (1 <= x <= n - 1): + raise ValueError('The secret key must be an integer in the range 1..n-1.') + P = point_mul(G, x) return bytes_from_point(P) def schnorr_sign(msg, seckey0): if len(msg) != 32: raise ValueError('The message must be a 32-byte array.') + seckey0 = int_from_bytes(seckey0) if not (1 <= seckey0 <= n - 1): raise ValueError('The secret key must be an integer in the range 1..n-1.') P = point_mul(G, seckey0) @@ -113,7 +117,7 @@ def test_vectors(): result = result == 'TRUE' print('\nTest vector #%-3i: ' % int(index)) if seckey != '': - seckey = int(seckey, 16) + seckey = bytes.fromhex(seckey) pubkey_actual = pubkey_gen(seckey) if pubkey != pubkey_actual: print(' * Failed key generation.') -- cgit v1.2.3 From 7e273fbda601e96f452fcc37c1676508f3560631 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Thu, 26 Sep 2019 21:18:53 +0000 Subject: Add x() and y() functions for points to bip-schnorr --- bip-schnorr/reference.py | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/bip-schnorr/reference.py b/bip-schnorr/reference.py index 95e9e53..bd12212 100644 --- a/bip-schnorr/reference.py +++ b/bip-schnorr/reference.py @@ -11,19 +11,25 @@ def tagged_hash(tag, msg): tag_hash = hashlib.sha256(tag.encode()).digest() return hashlib.sha256(tag_hash + tag_hash + msg).digest() +def x(P): + return P[0] + +def y(P): + return P[1] + def point_add(P1, P2): if (P1 is None): return P2 if (P2 is None): return P1 - if (P1[0] == P2[0] and P1[1] != P2[1]): + if (x(P1) == x(P2) and y(P1) != y(P2)): return None if (P1 == P2): - lam = (3 * P1[0] * P1[0] * pow(2 * P1[1], p - 2, p)) % p + lam = (3 * x(P1) * x(P1) * pow(2 * y(P1), p - 2, p)) % p else: - lam = ((P2[1] - P1[1]) * pow(P2[0] - P1[0], p - 2, p)) % p - x3 = (lam * lam - P1[0] - P2[0]) % p - return (x3, (lam * (P1[0] - x3) - P1[1]) % p) + lam = ((y(P2) - y(P1)) * pow(x(P2) - x(P1), p - 2, p)) % p + x3 = (lam * lam - x(P1) - x(P2)) % p + return (x3, (lam * (x(P1) - x3) - y(P1)) % p) def point_mul(P, n): R = None @@ -37,7 +43,7 @@ def bytes_from_int(x): return x.to_bytes(32, byteorder="big") def bytes_from_point(P): - return bytes_from_int(P[0]) + return bytes_from_int(x(P)) def point_from_bytes(b): x = int_from_bytes(b) @@ -66,12 +72,12 @@ def schnorr_sign(msg, seckey0): if not (1 <= seckey0 <= n - 1): raise ValueError('The secret key must be an integer in the range 1..n-1.') P = point_mul(G, seckey0) - seckey = seckey0 if (jacobi(P[1]) == 1) else n - seckey0 + seckey = seckey0 if (jacobi(y(P)) == 1) else n - seckey0 k0 = int_from_bytes(tagged_hash("BIPSchnorrDerive", bytes_from_int(seckey) + msg)) % n if k0 == 0: raise RuntimeError('Failure. This happens only with negligible probability.') R = point_mul(G, k0) - k = n - k0 if (jacobi(R[1]) != 1) else k0 + k = n - k0 if (jacobi(y(R)) != 1) else k0 e = int_from_bytes(tagged_hash("BIPSchnorr", bytes_from_point(R) + bytes_from_point(P) + msg)) % n return bytes_from_point(R) + bytes_from_int((k + e * seckey) % n) @@ -91,7 +97,7 @@ def schnorr_verify(msg, pubkey, sig): return False e = int_from_bytes(tagged_hash("BIPSchnorr", sig[0:32] + pubkey + msg)) % n R = point_add(point_mul(G, s), point_mul(P, n - e)) - if R is None or jacobi(R[1]) != 1 or R[0] != r: + if R is None or jacobi(y(R)) != 1 or x(R) != r: return False return True -- cgit v1.2.3 From 5c52872fe07c880ed205b47cffd8a569f7466089 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Fri, 27 Sep 2019 09:00:37 +0000 Subject: Standardize on secret key in bip-schnorr --- bip-schnorr.mediawiki | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 0473a29..5ae6e87 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -26,7 +26,7 @@ transactions. These are [http://www.secg.org/sec1-v2.pdf standardized], but have compared to [https://en.wikipedia.org/wiki/Schnorr_signature Schnorr signatures] over the same curve: * '''Security proof''': The security of Schnorr signatures is easily [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf provable] in the random oracle model assuming the elliptic curve discrete logarithm problem (ECDLP) is hard. Such a proof does not exist for ECDSA. -* '''Non-malleability''': ECDSA signatures are inherently malleable; a third party without access to the private key can alter an existing valid signature for a given public key and message into another signature that is valid for the same key and message. This issue is discussed in [https://github.com/bitcoin/bips/blob/master/bip-0062.mediawiki BIP62] and [https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki BIP66]. On the other hand, Schnorr signatures are provably non-malleableMore precisely they are '' '''strongly''' unforgeable under chosen message attacks '' (SUF-CMA), which informally means that without knowledge of the secret key but given a valid signature of a message, it is not possible to come up with a second valid signature for the same message. A security proof in the random oracle model can be found for example in [https://eprint.iacr.org/2016/191 a paper by Kiltz, Masny and Pan], which essentially restates [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf the original security proof of Schnorr signatures by Pointcheval and Stern] more explicitly. These proofs are for the Schnorr signature variant using ''(e,s)'' instead of ''(R,s)'' (see Design above). Since we use a unique encoding of ''R'', there is an efficiently computable bijection that maps ''(R, s)'' to ''(e, s)'', which allows to convert a successful SUF-CMA attacker for the ''(e, s)'' variant to a successful SUF-CMA attacker for the ''(r, s)'' variant (and vice-versa). Furthermore, the aforementioned proofs consider a variant of Schnorr signatures without key prefixing (see Design above), but it can be verified that the proofs are also correct for the variant with key prefixing. As a result, the aforementioned security proofs apply to the variant of Schnorr signatures proposed in this document.. +* '''Non-malleability''': ECDSA signatures are inherently malleable; a third party without access to the secret key can alter an existing valid signature for a given public key and message into another signature that is valid for the same key and message. This issue is discussed in [https://github.com/bitcoin/bips/blob/master/bip-0062.mediawiki BIP62] and [https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki BIP66]. On the other hand, Schnorr signatures are provably non-malleableMore precisely they are '' '''strongly''' unforgeable under chosen message attacks '' (SUF-CMA), which informally means that without knowledge of the secret key but given a valid signature of a message, it is not possible to come up with a second valid signature for the same message. A security proof in the random oracle model can be found for example in [https://eprint.iacr.org/2016/191 a paper by Kiltz, Masny and Pan], which essentially restates [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf the original security proof of Schnorr signatures by Pointcheval and Stern] more explicitly. These proofs are for the Schnorr signature variant using ''(e,s)'' instead of ''(R,s)'' (see Design above). Since we use a unique encoding of ''R'', there is an efficiently computable bijection that maps ''(R, s)'' to ''(e, s)'', which allows to convert a successful SUF-CMA attacker for the ''(e, s)'' variant to a successful SUF-CMA attacker for the ''(r, s)'' variant (and vice-versa). Furthermore, the aforementioned proofs consider a variant of Schnorr signatures without key prefixing (see Design above), but it can be verified that the proofs are also correct for the variant with key prefixing. As a result, the aforementioned security proofs apply to the variant of Schnorr signatures proposed in this document.. * '''Linearity''': Schnorr signatures have the remarkable property that multiple parties can collaborate to produce a signature that is valid for the sum of their public keys. This is the building block for various higher-level constructions that improve efficiency and privacy, such as multisignatures and others (see Applications below). For all these advantages, there are virtually no disadvantages, apart @@ -40,7 +40,7 @@ made: [[File:bip-schnorr/speedup-batch.png|frame|This graph shows the ratio between the time it takes to verify ''n'' signatures individually and to verify a batch of ''n'' signatures. This ratio goes up logarithmically with the number of signatures, or in other words: the total time to verify ''n'' signatures grows with ''O(n / log n)''.]] -By reusing the same curve as Bitcoin has used for ECDSA, we are able to retain existing mechanisms for choosing private and public keys, and we avoid introducing new assumptions about elliptic curve group security. +By reusing the same curve as Bitcoin has used for ECDSA, we are able to retain existing mechanisms for choosing secret and public keys, and we avoid introducing new assumptions about elliptic curve group security. == Description == @@ -83,7 +83,7 @@ Implicit Y coordinates are not a reduction in security when expressed as the num '''Tagged Hashes''' Cryptographic hash functions are used for multiple purposes in the specification below and in Bitcoin in general. To make sure hashes used in one context can't be reinterpreted in another one, hash functions can be tweaked with a context-dependent tag name, in such a way that collisions across contexts can be assumed to be infeasible. Such collisions obviously can not be ruled out completely, but only for schemes using tagging with a unique name. As for other schemes collisions are at least less likely with tagging than without. -For example, without tagged hashing a bip-schnorr signature could also be valid for a signature scheme where the only difference is that the arguments to the hash function are reordered. Worse, if the bip-schnorr nonce derivation function was copied or independently created, then the nonce could be accidentally reused in the other scheme leaking the private key. +For example, without tagged hashing a bip-schnorr signature could also be valid for a signature scheme where the only difference is that the arguments to the hash function are reordered. Worse, if the bip-schnorr nonce derivation function was copied or independently created, then the nonce could be accidentally reused in the other scheme leaking the secret key. This proposal suggests to include the tag by prefixing the hashed data with ''SHA256(tag) || SHA256(tag)''. Because this is a 64-byte long context-specific constant and the ''SHA256'' block size is also 64 bytes, optimized implementations are possible (identical to SHA256 itself, but with a modified initial state). Using SHA256 of the tag name itself is reasonably simple and efficient for implementations that don't choose to use the optimization. -- cgit v1.2.3 From 1882aa7b8f7401dd754000ac69db5471c7cd12ac Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Fri, 27 Sep 2019 09:56:21 +0000 Subject: Add is_quad function to bip-schnorr reference code --- bip-schnorr/reference.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/bip-schnorr/reference.py b/bip-schnorr/reference.py index bd12212..016ce97 100644 --- a/bip-schnorr/reference.py +++ b/bip-schnorr/reference.py @@ -62,6 +62,9 @@ def hash_sha256(b): def jacobi(x): return pow(x, (p - 1) // 2, p) +def is_quad(x): + return jacobi(x) == 1 + def pubkey_gen(seckey): P = point_mul(G, seckey) return bytes_from_point(P) @@ -72,12 +75,12 @@ def schnorr_sign(msg, seckey0): if not (1 <= seckey0 <= n - 1): raise ValueError('The secret key must be an integer in the range 1..n-1.') P = point_mul(G, seckey0) - seckey = seckey0 if (jacobi(y(P)) == 1) else n - seckey0 + seckey = seckey0 if is_quad(y(P)) else n - seckey0 k0 = int_from_bytes(tagged_hash("BIPSchnorrDerive", bytes_from_int(seckey) + msg)) % n if k0 == 0: raise RuntimeError('Failure. This happens only with negligible probability.') R = point_mul(G, k0) - k = n - k0 if (jacobi(y(R)) != 1) else k0 + k = n - k0 if not is_quad(y(R)) else k0 e = int_from_bytes(tagged_hash("BIPSchnorr", bytes_from_point(R) + bytes_from_point(P) + msg)) % n return bytes_from_point(R) + bytes_from_int((k + e * seckey) % n) @@ -97,7 +100,7 @@ def schnorr_verify(msg, pubkey, sig): return False e = int_from_bytes(tagged_hash("BIPSchnorr", sig[0:32] + pubkey + msg)) % n R = point_add(point_mul(G, s), point_mul(P, n - e)) - if R is None or jacobi(y(R)) != 1 or x(R) != r: + if R is None or not is_quad(y(R)) or x(R) != r: return False return True -- cgit v1.2.3 From 398897cd29fb04da60220358ef05249913e5ff38 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Fri, 27 Sep 2019 15:34:55 +0000 Subject: Add taproot_tweak_pubkey and taproot_tweak_privkey functions to bip-taproot wallet section --- bip-taproot.mediawiki | 57 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 35 insertions(+), 22 deletions(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 75eacca..8abf6e1 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -169,14 +169,37 @@ MuSig key aggregation does not have this issue because it already causes the int The attack works as follows: Assume Alice and Mallory want to aggregate their keys into a taproot output key without a script path. In order to prevent key cancellation and related attacks they use [https://eprint.iacr.org/2018/483.pdf MSDL-pop] instead of MuSig. -The MSDL-pop protocol requires all parties to provide a proof of possession of their corresponding private key and the aggregated key is just the sum of the individual keys. +The MSDL-pop protocol requires all parties to provide a proof of possession of their corresponding secret key and the aggregated key is just the sum of the individual keys. After Mallory receives Alice's key ''A'', Mallory creates ''M = M0 + int(t)G'' where ''M0'' is Mallory's original key and ''t'' allows a script path spend with internal key ''P = A + M0'' and a script that only contains Mallory's key. Mallory sends a proof of possession of ''M'' to Alice and both parties compute output key ''Q = A + M = P + int(t)G''. Alice will not be able to notice the script path, but Mallory can unilaterally spend any coin with output key ''Q''. * The remaining scripts should be organized into the leaves of a binary tree. This can be a balanced tree if each of the conditions these scripts correspond to are equally likely. If probabilities for each condition are known, consider constructing the tree as a Huffman tree. -'''Computing the output script''' Once the spending conditions are split into an internal key internal_pubkey and a binary tree whose leaves are (leaf_version, script) tuples, the following Python3 algorithm can be used to compute the output script. In the code below, ser_script prefixes its input with a CCompactSize-encoded length. Public key objects hold 32-byte public keys according to bip-schnorr, have a method get_bytes to get the byte array and a method tweak_add which returns a new public key corresponding to the sum of the public key point and a multiple of the secp256k1 generator (similar to BIP32's derivation). The second return value of tweak_add is a boolean indicating the quadratic residuosity of the Y coordinate of the resulting point. tagged_hash computes the tagged hash according to bip-schnorr. +'''Computing the output script''' Once the spending conditions are split into an internal key internal_pubkey and a binary tree whose leaves are (leaf_version, script) tuples, the output script can be computed using the following Python3 algorithms with helper functions from the bip-schnorr reference code for integer conversion, point multiplication and tagged hashes. + +First, we define taproot_tweak_pubkey for 32-byte bip-schnorr public key arrays. +In addition to the tweaked public key byte array, the function returns a boolean for the quadratic residuosity of the tweaked points' Y coordinate modulo the secp256k1 field order. +This will be required for spending the output with a script path. +In order to allow spending with the key path, we define taproot_tweak_seckey to compute the secret key for a tweaked public key. +For any byte string h it holds that taproot_tweak_pubkey(pubkey_gen(seckey), h)[0] == pubkey_gen(taproot_tweak_seckey(seckey, h)). + + +def taproot_tweak_pubkey(pubkey, h): + t = int_from_bytes(tagged_hash("TapTweak", pubkey + h)) + assert t < SECP256K1_ORDER + Q = point_mul(point(pubkey), t) + return bytes_from_int(x(Q)), is_quad(y(Q)) + +def taproot_tweak_seckey(seckey0, h): + P = point_mul(G, int_from_bytes(seckey0)) + seckey = SECP256K1_ORDER - seckey0 if not is_quad(y(R)) else seckey + t = int_from_bytes(tagged_hash("TapTweak", bytes_from_int(x(P)) + h)) + return (seckey + t) % SECP256K1_ORDER + + +The following function, taproot_output_script, returns a byte array with the scriptPubKey (see BIP141). +ser_script refers to a function that prefixes its input with a CCompactSize-encoded length. def taproot_tree_helper(script_tree): @@ -201,34 +224,25 @@ def taproot_output_script(internal_pubkey, script_tree): h = b'' else: _, h = taproot_tree_helper(script_tree) - t = tagged_hash("TapTweak", internal_pubkey.get_bytes() + h) - assert int.from_bytes(t, 'big') < SECP256K1_ORDER - output_pubkey, _ = internal_pubkey.tweak_add(t) - return bytes([0x51, 0x20]) + output_pubkey.get_bytes() + output_pubkey, _ = taproot_tweak_pubkey(internal_pubkey, h) + return bytes([0x51, 0x20]) + output_pubkey -The function taproot_output_script returns a byte array with the scriptPubKey (see BIP141). - [[File:bip-taproot/tree.png|frame|This diagram shows the hashing structure to obtain the tweak from an internal key ''P'' and a Merkle tree consisting of 5 script leaves. ''A'', ''B'', ''C'' and ''E'' are ''TapLeaf'' hashes similar to ''D'' and ''AB'' is a ''TapBranch'' hash. Note that when ''CDE'' is computed ''E'' is hashed first because ''E'' is less than ''CD''.]] -'''Spending using the key path''' A Taproot output can be spent with the private key corresponding to the internal_pubkey. To do so, a witness stack consists of a single element: a bip-schnorr signature on the signature hash as defined above, with the private key tweaked by the same t as in the above snippet. In the code below, internal_privkey has a method pubkey_gen that returns a public key according to bip-schnorr and a boolean indicating the quadratic residuosity of the Y coordinate of the underlying point. -See the code below: +'''Spending using the key path''' A Taproot output can be spent with the secret key corresponding to the internal_pubkey. To do so, a witness stack consists of a single element: a bip-schnorr signature on the signature hash as defined above, with the secret key tweaked by the same h as in the above snippet. See the code below: -def taproot_sign_key(script_tree, internal_privkey, hash_type): +def taproot_sign_key(script_tree, internal_seckey, hash_type): _, h = taproot_tree_helper(script_tree) - internal_pubkey, is_y_qresidue = internal_privkey.pubkey_gen() - if not is_y_qresidue: - internal_privkey = internal_privkey.negate() - t = tagged_hash("TapTweak", internal_pubkey.get_bytes() + h) - output_privkey = internal_privkey.tweak_add(t) - sig = output_privkey.schnorr_sign(sighash(hash_type)) + output_seckey = taproot_tweak_seckey(internal_seckey, h) + sig = schnorr_sign(sighash(hash_type), output_seckey) if hash_type != 0: sig += bytes([hash_type]) return [sig] -This function returns the witness stack necessary, and assumes a tweak_add method on private keys, and a sighash function to compute the signature hash as defined above (for simplicity, the snippet above ignores passing information like the transaction, the input position, ... to the sighashing code). +This function returns the witness stack necessary and a sighash function to compute the signature hash as defined above (for simplicity, the snippet above ignores passing information like the transaction, the input position, ... to the sighashing code). '''Spending using one of the scripts''' A Taproot output can be spent by satisfying any of the scripts used in its construction. To do so, a witness stack consisting of the script's inputs, plus the script itself and the control block are necessary. See the code below: @@ -236,10 +250,9 @@ This function returns the witness stack necessary, and assumes a tweak_add def taproot_sign_script(internal_pubkey, script_tree, script_num, inputs): info, h = taproot_tree_helper(script_tree) (leaf_version, script), path = info[script_num] - t = tagged_hash("TapTweak", internal_pubkey.get_bytes() + h) - _, is_y_qresidue = internal_pubkey.tweak_add(t) - output_pubkey_tag = 0 if is_y_qresidue else 1 - pubkey_data = bytes([output_pubkey_tag + leaf_version]) + internal_pubkey.get_bytes() + _, is_y_quad = taproot_tweak_pubkey(internal_pubkey, t) + output_pubkey_tag = 0 if is_y_quad else 1 + pubkey_data = bytes([output_pubkey_tag + leaf_version]) + internal_pubkey return inputs + [script, pubkey_data + path] -- cgit v1.2.3 From a6e5c16821b232d47dfe744fdee2816c7bd30a6d Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Mon, 30 Sep 2019 11:15:23 +0000 Subject: Replace taproot_tweak_pubkey assertion with exception and add it to taproot_tweak_seckey too --- bip-taproot.mediawiki | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 8abf6e1..ba54689 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -187,7 +187,8 @@ For any byte string h it holds that taproot_tweak_pubkey(pubk def taproot_tweak_pubkey(pubkey, h): t = int_from_bytes(tagged_hash("TapTweak", pubkey + h)) - assert t < SECP256K1_ORDER + if t >= SECP256K1_ORDER: + raise ValueError Q = point_mul(point(pubkey), t) return bytes_from_int(x(Q)), is_quad(y(Q)) @@ -195,6 +196,8 @@ def taproot_tweak_seckey(seckey0, h): P = point_mul(G, int_from_bytes(seckey0)) seckey = SECP256K1_ORDER - seckey0 if not is_quad(y(R)) else seckey t = int_from_bytes(tagged_hash("TapTweak", bytes_from_int(x(P)) + h)) + if t >= SECP256K1_ORDER: + raise ValueError return (seckey + t) % SECP256K1_ORDER -- cgit v1.2.3 From 3f61b2b1e764c9f3fb122f78ead450f100a0440c Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Thu, 3 Oct 2019 11:21:24 +0200 Subject: Link to Schnorr's paper instead of Wikipedia --- bip-schnorr.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 0473a29..acf46cf 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -23,7 +23,7 @@ This document is licensed under the 2-clause BSD license. Bitcoin has traditionally used [https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm ECDSA] signatures over the [http://www.secg.org/sec2-v2.pdf secp256k1 curve] for authenticating transactions. These are [http://www.secg.org/sec1-v2.pdf standardized], but have a number of downsides -compared to [https://en.wikipedia.org/wiki/Schnorr_signature Schnorr signatures] over the same curve: +compared to [http://publikationen.ub.uni-frankfurt.de/opus4/files/4280/schnorr.pdf Schnorr signatures] over the same curve: * '''Security proof''': The security of Schnorr signatures is easily [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf provable] in the random oracle model assuming the elliptic curve discrete logarithm problem (ECDLP) is hard. Such a proof does not exist for ECDSA. * '''Non-malleability''': ECDSA signatures are inherently malleable; a third party without access to the private key can alter an existing valid signature for a given public key and message into another signature that is valid for the same key and message. This issue is discussed in [https://github.com/bitcoin/bips/blob/master/bip-0062.mediawiki BIP62] and [https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki BIP66]. On the other hand, Schnorr signatures are provably non-malleableMore precisely they are '' '''strongly''' unforgeable under chosen message attacks '' (SUF-CMA), which informally means that without knowledge of the secret key but given a valid signature of a message, it is not possible to come up with a second valid signature for the same message. A security proof in the random oracle model can be found for example in [https://eprint.iacr.org/2016/191 a paper by Kiltz, Masny and Pan], which essentially restates [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf the original security proof of Schnorr signatures by Pointcheval and Stern] more explicitly. These proofs are for the Schnorr signature variant using ''(e,s)'' instead of ''(R,s)'' (see Design above). Since we use a unique encoding of ''R'', there is an efficiently computable bijection that maps ''(R, s)'' to ''(e, s)'', which allows to convert a successful SUF-CMA attacker for the ''(e, s)'' variant to a successful SUF-CMA attacker for the ''(r, s)'' variant (and vice-versa). Furthermore, the aforementioned proofs consider a variant of Schnorr signatures without key prefixing (see Design above), but it can be verified that the proofs are also correct for the variant with key prefixing. As a result, the aforementioned security proofs apply to the variant of Schnorr signatures proposed in this document.. -- cgit v1.2.3 From 15d5aa27323b5a987c02f442b7f00752032af05d Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 7 Oct 2019 14:37:41 -0700 Subject: Fix formula --- bip-taproot.mediawiki | 2 +- bip-tapscript.mediawiki | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 4827956..5058255 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -141,7 +141,7 @@ As the message for signature verification, transaction digest is ''hashTapS ** If the SIGHASH_SINGLE flag is set: *** sha_single_output (32): the SHA256 of the corresponding output in CTxOut format. -The total number of bytes hashed is at most ''211'''''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''178 - is_anyonecanpay * 50 - is_none * 32 + has_annex * 32''.. +The total number of bytes hashed is at most ''211'''''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''178 - is_anyonecanpay * 52 - is_none * 32 + has_annex * 32''.. In summary, the semantics of the BIP143 sighash types remain unchanged, except the following: # The way and order of serialization is changed.'''Why is the serialization in the transaction digest changed?''' Hashes that go into the digest and the digest itself are now computed with a single SHA256 invocation instead of double SHA256. There is no expected security improvement by doubling SHA256 because this only protects against length-extension attacks against SHA256 which are not a concern for transaction digests because there is no secret data. Therefore doubling SHA256 is a waste of resources. The digest computation now follows a logical order with transaction level data first, then input data and output data. This allows to efficiently cache the transaction part of the digest across different inputs using the SHA256 midstate. Additionally, digest computation avoids unnecessary hashing as opposed to BIP143 digests in which parts may be set zero and before hashing them. Despite that, collisions are made impossible by committing to the length of the data (implicit in hash_type and spend_type) before the variable length data. diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index da5dc18..a31774f 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -110,7 +110,7 @@ As additional pieces of data, added at the end of the input to the ''hashTa * key_version (1): a constant value 0x00 representing the current version of public keys in the tapscript signature opcode execution. * codeseparator_position (4): the opcode position of the last executed OP_CODESEPARATOR before the currently executed signature opcode, with the value in little endian (or 0xffffffff if none executed). The first opcode in a script has a position of 0. A multi-byte push opcode is counted as one opcode, regardless of the size of data being pushed. -The total number of bytes hashed is at most ''248'''''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''215 - is_anyonecanpay * 50 - is_none * 32 + has_annex * 32''.. +The total number of bytes hashed is at most ''248'''''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''215 - is_anyonecanpay * 52 - is_none * 32 + has_annex * 32''.. In summary, the semantics of the BIP143 sighash types remain unchanged, except the following: # The exceptions mentioned in bip-taproot. -- cgit v1.2.3 From 6b72dfff51947c45ac73ac50b4d673ddc515d99d Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 8 Oct 2019 18:37:58 -0700 Subject: Increase max Merkle path length --- bip-taproot.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 5058255..4f84c28 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -64,7 +64,7 @@ The following rules only apply when such an output is being spent. Any other out ** The single witness stack element is interpreted as the signature and must be valid (see the next section) for the public key ''q'' and taproot transaction digest (to be defined hereinafter) as message. Fail if it is not. Otherwise pass. * If there are at least two witness elements left, script path spending is used: ** Call the second-to-last stack element ''s'', the script. -** The last stack element is called the control block ''c'', and must have length ''33 + 32m'', for a value of ''m'' that is an integer between 0 and 32, inclusive. Fail if it does not have such a length. +** The last stack element is called the control block ''c'', and must have length ''33 + 32m'', for a value of ''m'' that is an integer between 0 and 128'''Why is the Merkle path length limited to 128?''' The optimally space-efficient Merkle tree can be constructed based on the probabilities of the scripts in the leaves, using the Huffman algorithm. This algorithm will construct branches with lengths approximately equal to ''log2(1/probability)'', but to have branches longer than 128 you would need to have scripts with an execution chance below 1 in ''2128''. As that is our security bound, scripts that truly have such a low chance can probably be removed entirely., inclusive. Fail if it does not have such a length. ** Let ''p = c[1:33]'' and let ''P = point(p)'' where ''point'' is defined as in bip-schnorr. Fail if this point is not on the curve. ** Let ''l = c[0] & 0xfe'', the leaf version'''What is the purpose of the first byte of the control block?''' The first byte of the control block has three distinct functions: * The low bit is used to denote whether the ''Q'' point's Y coordinate is a quadratic residue.'''Why is the quadratic residuosity of the output public key's Y coordinate required in a script path spend?''' The ''point'' function always constructs a point with Y coordinate having that property, but because ''Q'' is constructed by adding the taproot tweak to the internal public key ''P'', it cannot easily be guaranteed that ''Q'' in fact has such a Y coordinate. We can not ignore the Y coordinate because it would prevent batch verification. Trying out multiple internal keys until there's such a ''Q'' is possible but undesirable and unnecessary since this information about the Y coordinate only consumes an unused bit. -- cgit v1.2.3 From 9413cc1f0783e3473ea1dba0b8241d6fbac4a384 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Wed, 9 Oct 2019 12:12:55 -0700 Subject: Small fix: 0xc1 is possible as first control block byte --- bip-tapscript.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index a31774f..a325573 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -47,7 +47,7 @@ The rules below only apply when validating a transaction input for which all of * The transaction output is a '''segregated witness spend''' (i.e., the scriptPubKey is a witness program as defined in BIP141). * It is a '''taproot spend''' as defined in bip-taproot (i.e., the witness version is 1, the witness program is 32 bytes, and it is not P2SH wrapped). * It is a '''script path spend''' as defined in bip-taproot (i.e., after removing the optional annex from the witness stack, two or more stack elements remain). -* The leaf version is ''0xc0'' (i.e. the first byte of the last witness element after removing the optional annex is ''0xc0'')'''How is the ''0xc0'' constant chosen?''' Following the guidelines in bip-taproot, by choosing a value having the two top bits set, tapscript spends are identifiable even without access to the UTXO being spent., marking it as a '''tapscript spend'''. +* The leaf version is ''0xc0'' (i.e. the first byte of the last witness element after removing the optional annex is ''0xc0'' or ''0xc1'')'''How is the ''0xc0'' constant chosen?''' Following the guidelines in bip-taproot, by choosing a value having the two top bits set, tapscript spends are identifiable even without access to the UTXO being spent., marking it as a '''tapscript spend'''. Validation of such inputs must be equivalent to performing the following steps in the specified order. # If the input is invalid due to BIP16, BIP141, or bip-taproot, fail. -- cgit v1.2.3 From 69f1c93d9217813423bb18da091e55dbd3a820f5 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 14 Oct 2019 17:55:19 -0700 Subject: Small fixes from review with real-or-random --- bip-schnorr.mediawiki | 76 +++++++++++++++++++++++++-------------------------- 1 file changed, 37 insertions(+), 39 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index b0c7e02..7843510 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -40,7 +40,7 @@ made: [[File:bip-schnorr/speedup-batch.png|frame|This graph shows the ratio between the time it takes to verify ''n'' signatures individually and to verify a batch of ''n'' signatures. This ratio goes up logarithmically with the number of signatures, or in other words: the total time to verify ''n'' signatures grows with ''O(n / log n)''.]] -By reusing the same curve as Bitcoin has used for ECDSA, we are able to retain existing mechanisms for choosing secret and public keys, and we avoid introducing new assumptions about elliptic curve group security. +By reusing the same curve as Bitcoin uses for ECDSA, we are able to retain existing mechanisms for choosing secret and public keys, and we avoid introducing new assumptions about elliptic curve group security. == Description == @@ -75,9 +75,9 @@ In the case of ''R'' the third option is slower at signing time but a bit faster for elliptic curve operations). The two other options require a possibly expensive conversion to affine coordinates first. This would even be the case if the sign or oddness were explicitly coded (option 2 in the previous design choice). We therefore choose option 3. -For ''P'' the speed of signing and verification does not significantly differ between any of the three options because affine coordinates of the point have to be computed anyway. For consistency resons we choose the same option as for ''R''. The signing algorithm ensures that the signature is valid under the correct public key by negating the secret key if necessary. +For ''P'' the speed of signing and verification does not significantly differ between any of the three options because affine coordinates of the point have to be computed anyway. For consistency reasons we choose the same option as for ''R''. The signing algorithm ensures that the signature is valid under the correct public key by negating the secret key if necessary. -It is important to not mix up the 32-byte bip-schnorr public key format and other existing public key formats (e.g. encodings used in Bitcoin's ECDSA). Concretely, a verifier should only accept 32-byte public keys and not, for example, convert a 33-byte public key by throwing away the first byte. Otherwise, two public keys would be valid for a single signature which can result in subtle malleability issues (although this type of malleability already exists in the case of ECDSA signatures). +It is important not to mix up the 32-byte bip-schnorr public key format and other existing public key formats (e.g. encodings used in Bitcoin's ECDSA). Concretely, a verifier should only accept 32-byte public keys and not, for example, convert a 33-byte public key by throwing away the first byte. Otherwise, two public keys would be valid for a single signature which can result in subtle malleability issues (although this type of malleability already exists in the case of ECDSA signatures). Implicit Y coordinates are not a reduction in security when expressed as the number of elliptic curve operations an attacker is expected to perform to compute the secret key. An attacker can normalize any given public key to a point whose Y coordinate is a quadratic residue by negating the point if necessary. This is just a subtraction of field elements and not an elliptic curve operationThis can be formalized by a simple reduction that reduces an attack on Schnorr signatures with implicit Y coordinates to an attack to Schnorr signatures with explicit Y coordinates. The reduction works by reencoding public keys and negating the result of the hash function, which is modeled as random oracle, whenever the challenge public key has an explicit Y coordinate that is not a quadratic residue.. @@ -91,9 +91,7 @@ This proposal suggests to include the tag by prefixing the hashed data with ''SH === Specification === -We first describe the key generation algorithm, then the verification algorithm, and then the signature algorithm. - -The following convention is used, with constants as defined for secp256k1: +The following conventions are used, with constants as defined for [http://www.secg.org/sec2-v2.pdf secp256k1]: * Lowercase variables represent integers or byte arrays. ** The constant ''p'' refers to the field size, ''0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F''. ** The constant ''n'' refers to the curve order, ''0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141''. @@ -108,12 +106,12 @@ The following convention is used, with constants as defined for secp256k1: ** The function ''x[i:j]'', where ''x'' is a byte array, returns a ''(j - i)''-byte array with a copy of the ''i''-th byte (inclusive) to the ''j''-th byte (exclusive) of ''x''. ** The function ''bytes(x)'', where ''x'' is an integer, returns the 32-byte encoding of ''x'', most significant byte first. ** The function ''bytes(P)'', where ''P'' is a point, returns ''bytes(x(P))'. -** The function ''int(x)'', where ''x'' is a 32-byte array, returns the 256-bit unsigned integer whose most significant byte encoding is ''x''. +** The function ''int(x)'', where ''x'' is a 32-byte array, returns the 256-bit unsigned integer whose most significant byte first encoding is ''x''. ** The function ''lift_x(x)'', where ''x'' is an integer in range ''0..p-1'', returns the point ''P'' for which ''x(P) = x'' and ''y(P)'' is a quadratic residue modulo ''p'', or fails if no such point existsGiven an candidate X coordinate ''x'' in the range ''0..p-1'', there exist either exactly two or exactly zero valid Y coordinates. If no valid Y coordinate exists, then ''x'' is not a valid X coordinate either, i.e., no point ''P'' exists for which ''x(P) = x''. Given a candidate ''x'', the valid Y coordinates are the square roots of ''c = x3 + 7 mod p'' and they can be computed as ''y = ±c(p+1)/4 mod p'' (see [https://en.wikipedia.org/wiki/Quadratic_residue#Prime_or_prime_power_modulus Quadratic residue]) if they exist, which can be checked by squaring and comparing with ''c''. Due to [https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion] it then holds that ''c(p-1)/2 = 1 mod p''. The same criterion applied to ''y'' results in ''y(p-1)/2 mod p = ±c((p+1)/4)((p-1)/2) mod p = ±1 mod p''. Therefore ''y = +c(p+1)/4 mod p'' is a quadratic residue and ''-y mod p'' is not.. The function ''lift_x(x)'' is equivalent to the following pseudocode: *** Let ''c = x3 + 7 mod p''. *** Let ''y = c(p+1)/4 mod p''. *** Fail if ''c ≠ y2 mod p''. -*** Return the unique point ''P'' such that ''x(P) = x'' and ''y(P) = y''. +*** Return the unique point ''P'' such that ''x(P) = x'' and ''y(P) = y'', or fail if no such point exists. ** The function ''point(x)'', where ''x'' is a 32-byte array, returns the point ''P = lift_x(int(x))''. ** The function ''hashtag(x)'' where ''tag'' is a UTF-8 encoded tag name and ''x'' is a byte array returns the 32-byte hash ''SHA256(SHA256(tag) || SHA256(tag) || x)''. ** The function ''jacobi(x)'', where ''x'' is an integer, returns the [https://en.wikipedia.org/wiki/Jacobi_symbol Jacobi symbol] of ''x / p''. Since ''p'' is prime, it is equal to ''x(p-1)/2 mod p'' ([https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion])For points ''P'' on the secp256k1 curve it holds that ''jacobi(y(P)) ≠ 0''.. @@ -125,7 +123,7 @@ Input: * The secret key ''sk'': a 32-byte array, generated uniformly at random To generate the corresponding public key: -* Fail if ''int(sk) = 0'' or ''int(sk) >= n'' +* Fail if ''int(sk) = 0'' or ''int(sk) ≥ n'' * The public key corresponding to secret key ''sk'' is ''pubkey(sk)''. Note that the two secret keys ''sk'' and ''bytes(n-int(sk))'' will generate the same public key. @@ -133,6 +131,29 @@ Note that the two secret keys ''sk'' and ''bytes(n-int(sk))'' will generate the Alternatively, the public key can be created according to [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki BIP32] which describes the derivation of 33-byte compressed public keys. In order to translate such public keys into bip-schnorr compatible keys, the first byte must be dropped. +==== Signing ==== + +Input: +* The secret key ''sk'': a 32-byte array +* The message ''m'': a 32-byte array + +To sign ''m'' for public key ''pubkey(sk)'': +* Let ''d' = int(sk)'' +* Fail if ''d' = 0'' or ''d' ≥ n'' +* Let ''P = d'G'' +* Let ''d = d' '' if ''jacobi(y(P)) = 1'', otherwise let ''d = n - d' ''. +* Let ''k' = int(hashBIPSchnorrDerive(bytes(d) || m)) mod n''Note that in general, taking the output of a hash function modulo the curve order will produce an unacceptably biased result. However, for the secp256k1 curve, the order is sufficiently close to ''2256'' that this bias is not observable (''1 - n / 2256'' is around ''1.27 * 2-128'').. +* Fail if ''k' = 0''. +* Let ''R = k'G''. +* Let ''k = k' '' if ''jacobi(y(R)) = 1'', otherwise let ''k = n - k' ''. +* Let ''e = int(hashBIPSchnorr(bytes(R) || bytes(P) || m)) mod n''. +* The signature is ''bytes(R) || bytes((k + ed) mod n)''. + +'''Above deterministic derivation of ''R'' is designed specifically for this signing algorithm and may not be secure when used in other signature schemes.''' +For example, using the same derivation in the MuSig multi-signature scheme leaks the secret key (see the [https://eprint.iacr.org/2018/068 MuSig paper] for details). + +Note that this is not a ''unique signature'' scheme: while this algorithm will always produce the same signature for a given message and public key, ''k'' (and hence ''R'') may be generated in other ways (such as by a CSPRNG) producing a different, but still valid, signature. + ==== Verification ==== Input: @@ -161,35 +182,12 @@ All provided signatures are valid with overwhelming probability if and only if t * Generate ''u-1'' random integers ''a2...u'' in the range ''1...n-1''. They are generated deterministically using a [https://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator CSPRNG] seeded by a cryptographic hash of all inputs of the algorithm, i.e. ''seed = seed_hash(pk1..pku || m1..mu || sig1..sigu )''. A safe choice is to instantiate ''seed_hash'' with SHA256 and use [https://tools.ietf.org/html/rfc8439 ChaCha20] with key ''seed'' as a CSPRNG to generate 256-bit integers, skipping integers not in the range ''1...n-1''. * For ''i = 1 .. u'': ** Let ''Pi = point(pki)''; fail if ''point(pki)'' fails. -** Let ''r = int(sigi[0:32])''; fail if ''r ≥ p''. +** Let ''ri = int(sigi[0:32])''; fail if ''ri ≥ p''. ** Let ''si = int(sigi[32:64])''; fail if ''si ≥ n''. -** Let ''ei = int(hashBIPSchnorr(bytes(r) || bytes(Pi) || mi)) mod n''. -** Let ''Ri = lift_x(r)''; fail if ''lift_x(r)'' fails. +** Let ''ei = int(hashBIPSchnorr(bytes(ri) || bytes(Pi) || mi)) mod n''. +** Let ''Ri = lift_x(ri)''; fail if ''lift_x(ri)'' fails. * Fail if ''(s1 + a2s2 + ... + ausu)G ≠ R1 + a2R2 + ... + auRu + e1P1 + (a2e2)P2 + ... + (aueu)Pu''. -==== Signing ==== - -Input: -* The secret key ''sk'': a 32-byte array -* The message ''m'': a 32-byte array - -To sign ''m'' for public key ''pubkey(sk)'': -* Let ''d' = int(sk)'' -* Fail if ''d' = 0'' or ''d' >= n'' -* Let ''P = d'G'' -* Let ''d = d' '' if ''jacobi(y(P)) = 1'', otherwise let ''d = n - d' ''. -* Let ''k' = int(hashBIPSchnorrDerive(bytes(d) || m)) mod n''Note that in general, taking the output of a hash function modulo the curve order will produce an unacceptably biased result. However, for the secp256k1 curve, the order is sufficiently close to ''2256'' that this bias is not observable (''1 - n / 2256'' is around ''1.27 * 2-128'').. -* Fail if ''k' = 0''. -* Let ''R = k'G''. -* Let ''k = k' '' if ''jacobi(y(R)) = 1'', otherwise let ''k = n - k' ''. -* Let ''e = int(hashBIPSchnorr(bytes(R) || bytes(P) || m)) mod n''. -* The signature is ''bytes(R) || bytes((k + ed) mod n)''. - -'''Above deterministic derivation of ''R'' is designed specifically for this signing algorithm and may not be secure when used in other signature schemes.''' -For example, using the same derivation in the MuSig multi-signature scheme leaks the secret key (see the [https://eprint.iacr.org/2018/068 MuSig paper] for details). - -Note that this is not a ''unique signature'' scheme: while this algorithm will always produce the same signature for a given message and public key, ''k'' (and hence ''R'') may be generated in other ways (such as by a CSPRNG) producing a different, but still valid, signature. - === Optimizations === Many techniques are known for optimizing elliptic curve implementations. Several of them apply here, but are out of scope for this document. Two are listed below however, as they are relevant to the design decisions: @@ -198,7 +196,7 @@ Many techniques are known for optimizing elliptic curve implementations. Several '''Jacobian coordinates''' Elliptic Curve operations can be implemented more efficiently by using [https://en.wikibooks.org/wiki/Cryptography/Prime_Curve/Jacobian_Coordinates Jacobian coordinates]. Elliptic Curve operations implemented this way avoid many intermediate modular inverses (which are computationally expensive), and the scheme proposed in this document is in fact designed to not need any inversions at all for verification. When operating on a point ''P'' with Jacobian coordinates ''(x,y,z)'' which is not the point at infinity and for which ''x(P)'' is defined as ''x / z2'' and ''y(P)'' is defined as ''y / z3'': * ''jacobi(y(P))'' can be implemented as ''jacobi(yz mod p)''. -* ''x(P) ≠ r'' can be implemented as ''x ≠ z2r mod p''. +* ''x(P) ≠ r'' can be implemented as ''(0 ≤ r < p) and (x ≠ z2r mod p)''. == Applications == @@ -207,9 +205,9 @@ While recent academic papers claim that they are also possible with ECDSA, conse === Multisignatures and Threshold Signatures === -By means of an interactive scheme such as [https://eprint.iacr.org/2018/068 MuSig], participants can aggregate their public keys into a single public key which they can jointly sign for. This allows n-of-n multisignatures which, from a verifier's perspective, are no different from ordinary signatures, giving improved privacy and efficiency versus ''CHECKMULTISIG'' or other means. +By means of an interactive scheme such as [https://eprint.iacr.org/2018/068 MuSig], participants can aggregate their public keys into a single public key which they can jointly sign for. This allows ''n''-of-''n'' multisignatures which, from a verifier's perspective, are no different from ordinary signatures, giving improved privacy and efficiency versus ''CHECKMULTISIG'' or other means. -Moreover, Schnorr signatures are compatible with [https://web.archive.org/web/20031003232851/http://www.research.ibm.com/security/dkg.ps distributed key generation], which enables interactive threshold signatures schemes, e.g., the schemes described by [http://cacr.uwaterloo.ca/techreports/2001/corr2001-13.ps Stinson and Strobl (2001)] or [https://web.archive.org/web/20060911151529/http://theory.lcs.mit.edu/~stasio/Papers/gjkr03.pdf Genaro, Jarecki and Krawczyk (2003)]. These protocols make it possible to realize k-of-n threshold signatures, which ensure that any subset of size k of the set of n signers can sign but no subset of size less than k can produce a valid Schnorr signature. However, the practicality of the existing schemes is limited: most schemes in the literature have been proven secure only for the case k < n/2, are not secure when used concurrently in multiple sessions, or require a reliable broadcast mechanism to be secure. Further research is necessary to improve this situation. +Moreover, Schnorr signatures are compatible with [https://web.archive.org/web/20031003232851/http://www.research.ibm.com/security/dkg.ps distributed key generation], which enables interactive threshold signatures schemes, e.g., the schemes described by [http://cacr.uwaterloo.ca/techreports/2001/corr2001-13.ps Stinson and Strobl (2001)] or [https://web.archive.org/web/20060911151529/http://theory.lcs.mit.edu/~stasio/Papers/gjkr03.pdf Genaro, Jarecki and Krawczyk (2003)]. These protocols make it possible to realize ''k''-of-''n'' threshold signatures, which ensure that any subset of size ''k'' of the set of ''n'' signers can sign but no subset of size less than ''k'' can produce a valid Schnorr signature. However, the practicality of the existing schemes is limited: most schemes in the literature have been proven secure only for the case ''k-1 < n/2'', are not secure when used concurrently in multiple sessions, or require a reliable broadcast mechanism to be secure. Further research is necessary to improve this situation. === Adaptor Signatures === @@ -227,7 +225,7 @@ Blind Schnorr signatures could for example be used in [https://github.com/Elemen == Test Vectors and Reference Code == -For development and testing purposes, we provide a [[bip-schnorr/test-vectors.csv|collection of test vectors in CSV format]] and a naive but highly inefficient and non-constant time [[bip-schnorr/reference.py|pure Python 3.7 reference implementation of the signing and verification algorithm]]. +For development and testing purposes, we provide a [[bip-schnorr/test-vectors.csv|collection of test vectors in CSV format]] and a naive, highly inefficient, and non-constant time [[bip-schnorr/reference.py|pure Python 3.7 reference implementation of the signing and verification algorithm]]. The reference implementation is for demonstration purposes only and not to be used in production environments. == Footnotes == -- cgit v1.2.3 From 3c7fd7a83083147b1688c11e60946ef52f8d6543 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 15 Oct 2019 09:30:06 -0700 Subject: HTTPS links where possible --- bip-schnorr.mediawiki | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 7843510..2674959 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -21,8 +21,8 @@ This document is licensed under the 2-clause BSD license. === Motivation === Bitcoin has traditionally used -[https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm ECDSA] signatures over the [http://www.secg.org/sec2-v2.pdf secp256k1 curve] for authenticating -transactions. These are [http://www.secg.org/sec1-v2.pdf standardized], but have a number of downsides +[https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm ECDSA] signatures over the [https://www.secg.org/sec2-v2.pdf secp256k1 curve] for authenticating +transactions. These are [https://www.secg.org/sec1-v2.pdf standardized], but have a number of downsides compared to [http://publikationen.ub.uni-frankfurt.de/opus4/files/4280/schnorr.pdf Schnorr signatures] over the same curve: * '''Security proof''': The security of Schnorr signatures is easily [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf provable] in the random oracle model assuming the elliptic curve discrete logarithm problem (ECDLP) is hard. Such a proof does not exist for ECDSA. @@ -91,7 +91,7 @@ This proposal suggests to include the tag by prefixing the hashed data with ''SH === Specification === -The following conventions are used, with constants as defined for [http://www.secg.org/sec2-v2.pdf secp256k1]: +The following conventions are used, with constants as defined for [https://www.secg.org/sec2-v2.pdf secp256k1]: * Lowercase variables represent integers or byte arrays. ** The constant ''p'' refers to the field size, ''0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F''. ** The constant ''n'' refers to the curve order, ''0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141''. -- cgit v1.2.3 From 0655cc3c642bc65d5c515695a8e74f7bdda01634 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 15 Oct 2019 10:34:41 -0700 Subject: Use is_square/is_positive and introduce algorithm names --- bip-schnorr.mediawiki | 56 ++++++++++++++++++++++++++++----------------------- 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 2674959..af279c7 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -68,9 +68,9 @@ Using the first option would be slightly more efficient for verification (around '''Implicit Y coordinates''' In order to support efficient verification and batch verification, the Y coordinate of ''P'' and of ''R'' cannot be ambiguous (every valid X coordinate has two possible Y coordinates). We have a choice between several options for symmetry breaking: # Implicitly choosing the Y coordinate that is in the lower half. # Implicitly choosing the Y coordinate that is evenSince ''p'' is odd, negation modulo ''p'' will map even numbers to odd numbers and the other way around. This means that for a valid X coordinate, one of the corresponding Y coordinates will be even, and the other will be odd.. -# Implicitly choosing the Y coordinate that is a quadratic residue (has a square root modulo the field size)A product of two numbers is a quadratic residue when either both or none of the factors are quadratic residues. As ''-1'' is not a quadratic residue, and the two Y coordinates corresponding to a given X coordinate are each other's negation, this means exactly one of the two must be a quadratic residue.. +# Implicitly choosing the Y coordinate that is a quadratic residue (has a square root modulo the field size, or "is square" for short)A product of two numbers is a quadratic residue when either both or none of the factors are quadratic residues. As ''-1'' is not a quadratic residue, and the two Y coordinates corresponding to a given X coordinate are each other's negation, this means exactly one of the two must be a quadratic residue.. -In the case of ''R'' the third option is slower at signing time but a bit faster to verify, as it is possible to directly compute whether the Y coordinate is a quadratic residue when the points are represented in +In the case of ''R'' the third option is slower at signing time but a bit faster to verify, as it is possible to directly compute whether the Y coordinate is square when the points are represented in [https://en.wikibooks.org/wiki/Cryptography/Prime_Curve/Jacobian_Coordinates Jacobian coordinates] (a common optimization to avoid modular inverses for elliptic curve operations). The two other options require a possibly expensive conversion to affine coordinates first. This would even be the case if the sign or oddness were explicitly coded (option 2 in the previous design choice). We therefore choose option 3. @@ -79,7 +79,7 @@ For ''P'' the speed of signing and verification does not significantly differ be It is important not to mix up the 32-byte bip-schnorr public key format and other existing public key formats (e.g. encodings used in Bitcoin's ECDSA). Concretely, a verifier should only accept 32-byte public keys and not, for example, convert a 33-byte public key by throwing away the first byte. Otherwise, two public keys would be valid for a single signature which can result in subtle malleability issues (although this type of malleability already exists in the case of ECDSA signatures). -Implicit Y coordinates are not a reduction in security when expressed as the number of elliptic curve operations an attacker is expected to perform to compute the secret key. An attacker can normalize any given public key to a point whose Y coordinate is a quadratic residue by negating the point if necessary. This is just a subtraction of field elements and not an elliptic curve operationThis can be formalized by a simple reduction that reduces an attack on Schnorr signatures with implicit Y coordinates to an attack to Schnorr signatures with explicit Y coordinates. The reduction works by reencoding public keys and negating the result of the hash function, which is modeled as random oracle, whenever the challenge public key has an explicit Y coordinate that is not a quadratic residue.. +Implicit Y coordinates are not a reduction in security when expressed as the number of elliptic curve operations an attacker is expected to perform to compute the secret key. An attacker can normalize any given public key to a point whose Y coordinate is square by negating the point if necessary. This is just a subtraction of field elements and not an elliptic curve operationThis can be formalized by a simple reduction that reduces an attack on Schnorr signatures with implicit Y coordinates to an attack to Schnorr signatures with explicit Y coordinates. The reduction works by reencoding public keys and negating the result of the hash function, which is modeled as random oracle, whenever the challenge public key has an explicit Y coordinate that is not square.. '''Tagged Hashes''' Cryptographic hash functions are used for multiple purposes in the specification below and in Bitcoin in general. To make sure hashes used in one context can't be reinterpreted in another one, hash functions can be tweaked with a context-dependent tag name, in such a way that collisions across contexts can be assumed to be infeasible. Such collisions obviously can not be ruled out completely, but only for schemes using tagging with a unique name. As for other schemes collisions are at least less likely with tagging than without. @@ -87,7 +87,7 @@ For example, without tagged hashing a bip-schnorr signature could also be valid This proposal suggests to include the tag by prefixing the hashed data with ''SHA256(tag) || SHA256(tag)''. Because this is a 64-byte long context-specific constant and the ''SHA256'' block size is also 64 bytes, optimized implementations are possible (identical to SHA256 itself, but with a modified initial state). Using SHA256 of the tag name itself is reasonably simple and efficient for implementations that don't choose to use the optimization. -'''Final scheme''' As a result, our final scheme ends up using public key ''pk'' which is the X coordinate of a point ''P'' on the curve whose Y coordinate is a quadratic residue and signatures ''(r,s)'' where ''r'' is the X coordinate of a point ''R'' whose Y coordinate is a quadratic residue. The signature satisfies ''sG = R + tagged_hash(r || pk || m)P''. +'''Final scheme''' As a result, our final scheme ends up using public key ''pk'' which is the X coordinate of a point ''P'' on the curve whose Y coordinate is square and signatures ''(r,s)'' where ''r'' is the X coordinate of a point ''R'' whose Y coordinate is square. The signature satisfies ''sG = R + tagged_hash(r || pk || m)P''. === Specification === @@ -100,33 +100,34 @@ The following conventions are used, with constants as defined for [https://www.s ** ''x(P)'' and ''y(P)'' are integers in the range ''0..p-1'' and refer to the X and Y coordinates of a point ''P'' (assuming it is not infinity). ** The constant ''G'' refers to the generator, for which ''x(G) = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798'' and ''y(G) = 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8''. ** Addition of points refers to the usual [https://en.wikipedia.org/wiki/Elliptic_curve#The_group_law elliptic curve group operation]. -** [https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication Multiplication of an integer and a point] refers to the repeated application of the group operation. +** [https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication Multiplication (⋅) of an integer and a point] refers to the repeated application of the group operation. * Functions and operations: ** ''||'' refers to byte array concatenation. ** The function ''x[i:j]'', where ''x'' is a byte array, returns a ''(j - i)''-byte array with a copy of the ''i''-th byte (inclusive) to the ''j''-th byte (exclusive) of ''x''. ** The function ''bytes(x)'', where ''x'' is an integer, returns the 32-byte encoding of ''x'', most significant byte first. ** The function ''bytes(P)'', where ''P'' is a point, returns ''bytes(x(P))'. ** The function ''int(x)'', where ''x'' is a 32-byte array, returns the 256-bit unsigned integer whose most significant byte first encoding is ''x''. -** The function ''lift_x(x)'', where ''x'' is an integer in range ''0..p-1'', returns the point ''P'' for which ''x(P) = x'' and ''y(P)'' is a quadratic residue modulo ''p'', or fails if no such point existsGiven an candidate X coordinate ''x'' in the range ''0..p-1'', there exist either exactly two or exactly zero valid Y coordinates. If no valid Y coordinate exists, then ''x'' is not a valid X coordinate either, i.e., no point ''P'' exists for which ''x(P) = x''. Given a candidate ''x'', the valid Y coordinates are the square roots of ''c = x3 + 7 mod p'' and they can be computed as ''y = ±c(p+1)/4 mod p'' (see [https://en.wikipedia.org/wiki/Quadratic_residue#Prime_or_prime_power_modulus Quadratic residue]) if they exist, which can be checked by squaring and comparing with ''c''. Due to [https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion] it then holds that ''c(p-1)/2 = 1 mod p''. The same criterion applied to ''y'' results in ''y(p-1)/2 mod p = ±c((p+1)/4)((p-1)/2) mod p = ±1 mod p''. Therefore ''y = +c(p+1)/4 mod p'' is a quadratic residue and ''-y mod p'' is not.. The function ''lift_x(x)'' is equivalent to the following pseudocode: +** The function ''is_square(x)'', where ''x'' is an integer, returns whether or not ''x'' is a quadratic residue modulo ''p''. Since ''p'' is prime, it is equivalent to the Legendre symbol ''(x / p) = x(p-1)/2 mod p'' being equal to ''1'' (see [https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion])For points ''P'' on the secp256k1 curve it holds that ''x(p-1)/2 ≠ 0 mod p''.. +** The function ''is_positive(P)'', where ''P'' is a point, is defined as ''not infinite(P) and is_square(y(P))''For points ''P'' on the secp256k1 curve it holds that ''is_positive(P) = not is_positive(-P)''.. +** The function ''lift_x(x)'', where ''x'' is an integer in range ''0..p-1'', returns the point ''P'' for which ''x(P) = x'' and ''is_positive(P)'', or fails if no such point existsGiven an candidate X coordinate ''x'' in the range ''0..p-1'', there exist either exactly two or exactly zero valid Y coordinates. If no valid Y coordinate exists, then ''x'' is not a valid X coordinate either, i.e., no point ''P'' exists for which ''x(P) = x''. Given a candidate ''x'', the valid Y coordinates are the square roots of ''c = x3 + 7 mod p'' and they can be computed as ''y = ±c(p+1)/4 mod p'' (see [https://en.wikipedia.org/wiki/Quadratic_residue#Prime_or_prime_power_modulus Quadratic residue]) if they exist, which can be checked by squaring and comparing with ''c''. Due to [https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion] it then holds that ''c(p-1)/2 = 1 mod p''. The same criterion applied to ''y'' results in ''y(p-1)/2 mod p = ±c((p+1)/4)((p-1)/2) mod p = ±1 mod p''. Therefore ''y = +c(p+1)/4 mod p'' is a quadratic residue and ''-y mod p'' is not.. The function ''lift_x(x)'' is equivalent to the following pseudocode: *** Let ''c = x3 + 7 mod p''. *** Let ''y = c(p+1)/4 mod p''. *** Fail if ''c ≠ y2 mod p''. *** Return the unique point ''P'' such that ''x(P) = x'' and ''y(P) = y'', or fail if no such point exists. ** The function ''point(x)'', where ''x'' is a 32-byte array, returns the point ''P = lift_x(int(x))''. ** The function ''hashtag(x)'' where ''tag'' is a UTF-8 encoded tag name and ''x'' is a byte array returns the 32-byte hash ''SHA256(SHA256(tag) || SHA256(tag) || x)''. -** The function ''jacobi(x)'', where ''x'' is an integer, returns the [https://en.wikipedia.org/wiki/Jacobi_symbol Jacobi symbol] of ''x / p''. Since ''p'' is prime, it is equal to ''x(p-1)/2 mod p'' ([https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion])For points ''P'' on the secp256k1 curve it holds that ''jacobi(y(P)) ≠ 0''.. -** The function ''pubkey(x)'', where ''x'' is a 32-byte array, returns ''bytes(dG)'' where ''d = int(x) mod n''. ==== Public Key Generation ==== Input: * The secret key ''sk'': a 32-byte array, generated uniformly at random -To generate the corresponding public key: -* Fail if ''int(sk) = 0'' or ''int(sk) ≥ n'' -* The public key corresponding to secret key ''sk'' is ''pubkey(sk)''. +The algorithm ''PubKey(sk)'' is defined as: +* Let ''d = int(sk)''. +* Fail if ''d = 0'' or ''d ≥ n''. +* Return ''bytes(d⋅G)''. -Note that the two secret keys ''sk'' and ''bytes(n-int(sk))'' will generate the same public key. +Note that ''PubKey(sk) = PubKey(bytes(n - int(sk))'', so every public key has two corresponding private keys. Alternatively, the public key can be created according to [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki BIP32] which describes the derivation of 33-byte compressed public keys. In order to translate such public keys into bip-schnorr compatible keys, the first byte must be dropped. @@ -137,19 +138,19 @@ Input: * The secret key ''sk'': a 32-byte array * The message ''m'': a 32-byte array -To sign ''m'' for public key ''pubkey(sk)'': +The algorithm ''Sign(sk,m)'' is defined as: * Let ''d' = int(sk)'' * Fail if ''d' = 0'' or ''d' ≥ n'' * Let ''P = d'G'' -* Let ''d = d' '' if ''jacobi(y(P)) = 1'', otherwise let ''d = n - d' ''. +* Let ''d = d' '' if ''is_positive(P)'', otherwise let ''d = n - d' ''. * Let ''k' = int(hashBIPSchnorrDerive(bytes(d) || m)) mod n''Note that in general, taking the output of a hash function modulo the curve order will produce an unacceptably biased result. However, for the secp256k1 curve, the order is sufficiently close to ''2256'' that this bias is not observable (''1 - n / 2256'' is around ''1.27 * 2-128'').. * Fail if ''k' = 0''. * Let ''R = k'G''. -* Let ''k = k' '' if ''jacobi(y(R)) = 1'', otherwise let ''k = n - k' ''. +* Let ''k = k' '' if ''is_positive(R)'', otherwise let ''k = n - k' ''. * Let ''e = int(hashBIPSchnorr(bytes(R) || bytes(P) || m)) mod n''. -* The signature is ''bytes(R) || bytes((k + ed) mod n)''. +* Return the signature ''bytes(R) || bytes((k + ed) mod n)''. -'''Above deterministic derivation of ''R'' is designed specifically for this signing algorithm and may not be secure when used in other signature schemes.''' +'''Above deterministic derivation of ''R'' is designed specifically for this signing algorithm and may not be secure when used in other signature schemes or for other curves.''' For example, using the same derivation in the MuSig multi-signature scheme leaks the secret key (see the [https://eprint.iacr.org/2018/068 MuSig paper] for details). Note that this is not a ''unique signature'' scheme: while this algorithm will always produce the same signature for a given message and public key, ''k'' (and hence ''R'') may be generated in other ways (such as by a CSPRNG) producing a different, but still valid, signature. @@ -161,14 +162,16 @@ Input: * The message ''m'': a 32-byte array * A signature ''sig'': a 64-byte array -The signature is valid if and only if the algorithm below does not fail. +The algorithm ''Verify(pk,m,sig)'' is defined as: * Let ''P = point(pk)''; fail if ''point(pk)'' fails. * Let ''r = int(sig[0:32])''; fail if ''r ≥ p''. * Let ''s = int(sig[32:64])''; fail if ''s ≥ n''. * Let ''e = int(hashBIPSchnorr(bytes(r) || bytes(P) || m)) mod n''. -* Let ''R = sG - eP''. -* Fail if ''infinite(R)''. -* Fail if ''jacobi(y(R)) ≠ 1'' or ''x(R) ≠ r''. +* Let ''R = s⋅G - e⋅P''. +* Fail if ''not is_positive(R)'' or ''x(R) ≠ r''. +* Return success iff no failure occurred before reaching this point. + +For every valid secret key ''sk'' and message ''m'', ''Verify(PubKey(sk),m,Sign(sk,m))'' will succeed. ==== Batch Verification ==== @@ -178,7 +181,7 @@ Input: * The messages ''m1..u'': ''u'' 32-byte arrays * The signatures ''sig1..u'': ''u'' 64-byte arrays -All provided signatures are valid with overwhelming probability if and only if the algorithm below does not fail. +The algorithm ''BatchVerify(pk1..u,m1..u,sig1..u)'' is defined as: * Generate ''u-1'' random integers ''a2...u'' in the range ''1...n-1''. They are generated deterministically using a [https://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator CSPRNG] seeded by a cryptographic hash of all inputs of the algorithm, i.e. ''seed = seed_hash(pk1..pku || m1..mu || sig1..sigu )''. A safe choice is to instantiate ''seed_hash'' with SHA256 and use [https://tools.ietf.org/html/rfc8439 ChaCha20] with key ''seed'' as a CSPRNG to generate 256-bit integers, skipping integers not in the range ''1...n-1''. * For ''i = 1 .. u'': ** Let ''Pi = point(pki)''; fail if ''point(pki)'' fails. @@ -186,16 +189,19 @@ All provided signatures are valid with overwhelming probability if and only if t ** Let ''si = int(sigi[32:64])''; fail if ''si ≥ n''. ** Let ''ei = int(hashBIPSchnorr(bytes(ri) || bytes(Pi) || mi)) mod n''. ** Let ''Ri = lift_x(ri)''; fail if ''lift_x(ri)'' fails. -* Fail if ''(s1 + a2s2 + ... + ausu)G ≠ R1 + a2R2 + ... + auRu + e1P1 + (a2e2)P2 + ... + (aueu)Pu''. +* Fail if ''(s1 + a2s2 + ... + ausu)⋅G ≠ R1 + a2⋅R2 + ... + au⋅Ru + e1⋅P1 + (a2e2)⋅P2 + ... + (aueu)⋅Pu''. +* Return success iff no failure occurred before reaching this point. + +With overwhelming probability, ''BatchVerify(pk1..u,m1..u,sig1..u) = Verify(pk1,m1,sig1) and Verify(pk2,m2,sig2) and ... and Verify(pku,mu,sigu)''. If all signatures are valid it will always succeed. If one or more signatures are invalid, it will succeed with probability ''2-n''. === Optimizations === Many techniques are known for optimizing elliptic curve implementations. Several of them apply here, but are out of scope for this document. Two are listed below however, as they are relevant to the design decisions: -'''Jacobi symbol''' The function ''jacobi(x)'' is defined as above, but can be computed more efficiently using an [https://en.wikipedia.org/wiki/Jacobi_symbol#Calculating_the_Jacobi_symbol extended GCD algorithm]. +'''Quadratic residue testing''' The function ''is_square(x)'' is defined as above, but can be computed more efficiently using an [https://en.wikipedia.org/wiki/Jacobi_symbol#Calculating_the_Jacobi_symbol extended GCD algorithm]. '''Jacobian coordinates''' Elliptic Curve operations can be implemented more efficiently by using [https://en.wikibooks.org/wiki/Cryptography/Prime_Curve/Jacobian_Coordinates Jacobian coordinates]. Elliptic Curve operations implemented this way avoid many intermediate modular inverses (which are computationally expensive), and the scheme proposed in this document is in fact designed to not need any inversions at all for verification. When operating on a point ''P'' with Jacobian coordinates ''(x,y,z)'' which is not the point at infinity and for which ''x(P)'' is defined as ''x / z2'' and ''y(P)'' is defined as ''y / z3'': -* ''jacobi(y(P))'' can be implemented as ''jacobi(yz mod p)''. +* ''is_positive(P)'' can be implemented as ''is_square(yz mod p)''. * ''x(P) ≠ r'' can be implemented as ''(0 ≤ r < p) and (x ≠ z2r mod p)''. == Applications == -- cgit v1.2.3 From 1442d4dabca9ac9a5323c0c366c6d10fd9f9c38c Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 15 Oct 2019 12:11:17 -0700 Subject: Formulate claims about BatchVerify more accurately --- bip-schnorr.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index af279c7..b7bd541 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -192,7 +192,7 @@ The algorithm ''BatchVerify(pk1..u,m1..u,sig1..u1 + a2s2 + ... + ausu)⋅G ≠ R1 + a2⋅R2 + ... + au⋅Ru + e1⋅P1 + (a2e2)⋅P2 + ... + (aueu)⋅Pu''. * Return success iff no failure occurred before reaching this point. -With overwhelming probability, ''BatchVerify(pk1..u,m1..u,sig1..u) = Verify(pk1,m1,sig1) and Verify(pk2,m2,sig2) and ... and Verify(pku,mu,sigu)''. If all signatures are valid it will always succeed. If one or more signatures are invalid, it will succeed with probability ''2-n''. +If all individual signatures are valid (i.e., ''Verify'' would return success for them), ''BatchVerify'' will always return success. If at least one signature is invalid, ''BatchVerify'' will return success with at most a negligable probability. === Optimizations === -- cgit v1.2.3 From 1e00d6ef6a7ecc0c235ed787ccdbbd1d1f84eb91 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 15 Oct 2019 12:22:31 -0700 Subject: Apply suggestions from code review Co-Authored-By: Tim Ruffing --- bip-schnorr.mediawiki | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index b7bd541..f63e3ae 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -68,9 +68,9 @@ Using the first option would be slightly more efficient for verification (around '''Implicit Y coordinates''' In order to support efficient verification and batch verification, the Y coordinate of ''P'' and of ''R'' cannot be ambiguous (every valid X coordinate has two possible Y coordinates). We have a choice between several options for symmetry breaking: # Implicitly choosing the Y coordinate that is in the lower half. # Implicitly choosing the Y coordinate that is evenSince ''p'' is odd, negation modulo ''p'' will map even numbers to odd numbers and the other way around. This means that for a valid X coordinate, one of the corresponding Y coordinates will be even, and the other will be odd.. -# Implicitly choosing the Y coordinate that is a quadratic residue (has a square root modulo the field size, or "is square" for short)A product of two numbers is a quadratic residue when either both or none of the factors are quadratic residues. As ''-1'' is not a quadratic residue, and the two Y coordinates corresponding to a given X coordinate are each other's negation, this means exactly one of the two must be a quadratic residue.. +# Implicitly choosing the Y coordinate that is a quadratic residue (has a square root modulo the field size, or "is a square" for short)A product of two numbers is a square when either both or none of the factors are squares. As ''-1'' is not a square, and the two Y coordinates corresponding to a given X coordinate are each other's negation, this means exactly one of the two must be a square.. -In the case of ''R'' the third option is slower at signing time but a bit faster to verify, as it is possible to directly compute whether the Y coordinate is square when the points are represented in +In the case of ''R'' the third option is slower at signing time but a bit faster to verify, as it is possible to directly compute whether the Y coordinate is a square when the points are represented in [https://en.wikibooks.org/wiki/Cryptography/Prime_Curve/Jacobian_Coordinates Jacobian coordinates] (a common optimization to avoid modular inverses for elliptic curve operations). The two other options require a possibly expensive conversion to affine coordinates first. This would even be the case if the sign or oddness were explicitly coded (option 2 in the previous design choice). We therefore choose option 3. @@ -79,7 +79,7 @@ For ''P'' the speed of signing and verification does not significantly differ be It is important not to mix up the 32-byte bip-schnorr public key format and other existing public key formats (e.g. encodings used in Bitcoin's ECDSA). Concretely, a verifier should only accept 32-byte public keys and not, for example, convert a 33-byte public key by throwing away the first byte. Otherwise, two public keys would be valid for a single signature which can result in subtle malleability issues (although this type of malleability already exists in the case of ECDSA signatures). -Implicit Y coordinates are not a reduction in security when expressed as the number of elliptic curve operations an attacker is expected to perform to compute the secret key. An attacker can normalize any given public key to a point whose Y coordinate is square by negating the point if necessary. This is just a subtraction of field elements and not an elliptic curve operationThis can be formalized by a simple reduction that reduces an attack on Schnorr signatures with implicit Y coordinates to an attack to Schnorr signatures with explicit Y coordinates. The reduction works by reencoding public keys and negating the result of the hash function, which is modeled as random oracle, whenever the challenge public key has an explicit Y coordinate that is not square.. +Implicit Y coordinates are not a reduction in security when expressed as the number of elliptic curve operations an attacker is expected to perform to compute the secret key. An attacker can normalize any given public key to a point whose Y coordinate is a square by negating the point if necessary. This is just a subtraction of field elements and not an elliptic curve operationThis can be formalized by a simple reduction that reduces an attack on Schnorr signatures with implicit Y coordinates to an attack to Schnorr signatures with explicit Y coordinates. The reduction works by reencoding public keys and negating the result of the hash function, which is modeled as random oracle, whenever the challenge public key has an explicit Y coordinate that is not a square.. '''Tagged Hashes''' Cryptographic hash functions are used for multiple purposes in the specification below and in Bitcoin in general. To make sure hashes used in one context can't be reinterpreted in another one, hash functions can be tweaked with a context-dependent tag name, in such a way that collisions across contexts can be assumed to be infeasible. Such collisions obviously can not be ruled out completely, but only for schemes using tagging with a unique name. As for other schemes collisions are at least less likely with tagging than without. @@ -87,7 +87,7 @@ For example, without tagged hashing a bip-schnorr signature could also be valid This proposal suggests to include the tag by prefixing the hashed data with ''SHA256(tag) || SHA256(tag)''. Because this is a 64-byte long context-specific constant and the ''SHA256'' block size is also 64 bytes, optimized implementations are possible (identical to SHA256 itself, but with a modified initial state). Using SHA256 of the tag name itself is reasonably simple and efficient for implementations that don't choose to use the optimization. -'''Final scheme''' As a result, our final scheme ends up using public key ''pk'' which is the X coordinate of a point ''P'' on the curve whose Y coordinate is square and signatures ''(r,s)'' where ''r'' is the X coordinate of a point ''R'' whose Y coordinate is square. The signature satisfies ''sG = R + tagged_hash(r || pk || m)P''. +'''Final scheme''' As a result, our final scheme ends up using public key ''pk'' which is the X coordinate of a point ''P'' on the curve whose Y coordinate is a square and signatures ''(r,s)'' where ''r'' is the X coordinate of a point ''R'' whose Y coordinate is a square. The signature satisfies ''sG = R + tagged_hash(r || pk || m)P''. === Specification === @@ -138,10 +138,10 @@ Input: * The secret key ''sk'': a 32-byte array * The message ''m'': a 32-byte array -The algorithm ''Sign(sk,m)'' is defined as: +The algorithm ''Sign(sk, m)'' is defined as: * Let ''d' = int(sk)'' * Fail if ''d' = 0'' or ''d' ≥ n'' -* Let ''P = d'G'' + * Let ''P = d'⋅G'' * Let ''d = d' '' if ''is_positive(P)'', otherwise let ''d = n - d' ''. * Let ''k' = int(hashBIPSchnorrDerive(bytes(d) || m)) mod n''Note that in general, taking the output of a hash function modulo the curve order will produce an unacceptably biased result. However, for the secp256k1 curve, the order is sufficiently close to ''2256'' that this bias is not observable (''1 - n / 2256'' is around ''1.27 * 2-128'').. * Fail if ''k' = 0''. @@ -162,7 +162,7 @@ Input: * The message ''m'': a 32-byte array * A signature ''sig'': a 64-byte array -The algorithm ''Verify(pk,m,sig)'' is defined as: +The algorithm ''Verify(pk, m, sig)'' is defined as: * Let ''P = point(pk)''; fail if ''point(pk)'' fails. * Let ''r = int(sig[0:32])''; fail if ''r ≥ p''. * Let ''s = int(sig[32:64])''; fail if ''s ≥ n''. @@ -181,7 +181,7 @@ Input: * The messages ''m1..u'': ''u'' 32-byte arrays * The signatures ''sig1..u'': ''u'' 64-byte arrays -The algorithm ''BatchVerify(pk1..u,m1..u,sig1..u)'' is defined as: +The algorithm ''BatchVerify(pk1..u, m1..u, sig1..u)'' is defined as: * Generate ''u-1'' random integers ''a2...u'' in the range ''1...n-1''. They are generated deterministically using a [https://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator CSPRNG] seeded by a cryptographic hash of all inputs of the algorithm, i.e. ''seed = seed_hash(pk1..pku || m1..mu || sig1..sigu )''. A safe choice is to instantiate ''seed_hash'' with SHA256 and use [https://tools.ietf.org/html/rfc8439 ChaCha20] with key ''seed'' as a CSPRNG to generate 256-bit integers, skipping integers not in the range ''1...n-1''. * For ''i = 1 .. u'': ** Let ''Pi = point(pki)''; fail if ''point(pki)'' fails. @@ -198,7 +198,7 @@ If all individual signatures are valid (i.e., ''Verify'' would return success fo Many techniques are known for optimizing elliptic curve implementations. Several of them apply here, but are out of scope for this document. Two are listed below however, as they are relevant to the design decisions: -'''Quadratic residue testing''' The function ''is_square(x)'' is defined as above, but can be computed more efficiently using an [https://en.wikipedia.org/wiki/Jacobi_symbol#Calculating_the_Jacobi_symbol extended GCD algorithm]. +'''Squareness testing''' The function ''is_square(x)'' is defined as above, but can be computed more efficiently using an [https://en.wikipedia.org/wiki/Jacobi_symbol#Calculating_the_Jacobi_symbol extended GCD algorithm]. '''Jacobian coordinates''' Elliptic Curve operations can be implemented more efficiently by using [https://en.wikibooks.org/wiki/Cryptography/Prime_Curve/Jacobian_Coordinates Jacobian coordinates]. Elliptic Curve operations implemented this way avoid many intermediate modular inverses (which are computationally expensive), and the scheme proposed in this document is in fact designed to not need any inversions at all for verification. When operating on a point ''P'' with Jacobian coordinates ''(x,y,z)'' which is not the point at infinity and for which ''x(P)'' is defined as ''x / z2'' and ''y(P)'' is defined as ''y / z3'': * ''is_positive(P)'' can be implemented as ''is_square(yz mod p)''. -- cgit v1.2.3 From 8c0b29cc94e7b8b13837a5d797d3d96bb581de8f Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 15 Oct 2019 12:24:07 -0700 Subject: Prefix infinite with is_ --- bip-schnorr.mediawiki | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index f63e3ae..dbc474b 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -96,7 +96,7 @@ The following conventions are used, with constants as defined for [https://www.s ** The constant ''p'' refers to the field size, ''0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F''. ** The constant ''n'' refers to the curve order, ''0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141''. * Uppercase variables refer to points on the curve with equation ''y2 = x3 + 7'' over the integers modulo ''p''. -** ''infinite(P)'' returns whether or not ''P'' is the point at infinity. +** ''is_infinite(P)'' returns whether or not ''P'' is the point at infinity. ** ''x(P)'' and ''y(P)'' are integers in the range ''0..p-1'' and refer to the X and Y coordinates of a point ''P'' (assuming it is not infinity). ** The constant ''G'' refers to the generator, for which ''x(G) = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798'' and ''y(G) = 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8''. ** Addition of points refers to the usual [https://en.wikipedia.org/wiki/Elliptic_curve#The_group_law elliptic curve group operation]. @@ -108,7 +108,7 @@ The following conventions are used, with constants as defined for [https://www.s ** The function ''bytes(P)'', where ''P'' is a point, returns ''bytes(x(P))'. ** The function ''int(x)'', where ''x'' is a 32-byte array, returns the 256-bit unsigned integer whose most significant byte first encoding is ''x''. ** The function ''is_square(x)'', where ''x'' is an integer, returns whether or not ''x'' is a quadratic residue modulo ''p''. Since ''p'' is prime, it is equivalent to the Legendre symbol ''(x / p) = x(p-1)/2 mod p'' being equal to ''1'' (see [https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion])For points ''P'' on the secp256k1 curve it holds that ''x(p-1)/2 ≠ 0 mod p''.. -** The function ''is_positive(P)'', where ''P'' is a point, is defined as ''not infinite(P) and is_square(y(P))''For points ''P'' on the secp256k1 curve it holds that ''is_positive(P) = not is_positive(-P)''.. +** The function ''is_positive(P)'', where ''P'' is a point, is defined as ''not is_infinite(P) and is_square(y(P))''For points ''P'' on the secp256k1 curve it holds that ''is_positive(P) = not is_positive(-P)''.. ** The function ''lift_x(x)'', where ''x'' is an integer in range ''0..p-1'', returns the point ''P'' for which ''x(P) = x'' and ''is_positive(P)'', or fails if no such point existsGiven an candidate X coordinate ''x'' in the range ''0..p-1'', there exist either exactly two or exactly zero valid Y coordinates. If no valid Y coordinate exists, then ''x'' is not a valid X coordinate either, i.e., no point ''P'' exists for which ''x(P) = x''. Given a candidate ''x'', the valid Y coordinates are the square roots of ''c = x3 + 7 mod p'' and they can be computed as ''y = ±c(p+1)/4 mod p'' (see [https://en.wikipedia.org/wiki/Quadratic_residue#Prime_or_prime_power_modulus Quadratic residue]) if they exist, which can be checked by squaring and comparing with ''c''. Due to [https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion] it then holds that ''c(p-1)/2 = 1 mod p''. The same criterion applied to ''y'' results in ''y(p-1)/2 mod p = ±c((p+1)/4)((p-1)/2) mod p = ±1 mod p''. Therefore ''y = +c(p+1)/4 mod p'' is a quadratic residue and ''-y mod p'' is not.. The function ''lift_x(x)'' is equivalent to the following pseudocode: *** Let ''c = x3 + 7 mod p''. *** Let ''y = c(p+1)/4 mod p''. -- cgit v1.2.3 From cdf7dd8cca5178dcdf998d0e931ab9c51b8aacd8 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 15 Oct 2019 12:26:21 -0700 Subject: Drop other curve comment --- bip-schnorr.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index dbc474b..5dd5305 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -150,7 +150,7 @@ The algorithm ''Sign(sk, m)'' is defined as: * Let ''e = int(hashBIPSchnorr(bytes(R) || bytes(P) || m)) mod n''. * Return the signature ''bytes(R) || bytes((k + ed) mod n)''. -'''Above deterministic derivation of ''R'' is designed specifically for this signing algorithm and may not be secure when used in other signature schemes or for other curves.''' +'''Above deterministic derivation of ''R'' is designed specifically for this signing algorithm and may not be secure when used in other signature schemes.''' For example, using the same derivation in the MuSig multi-signature scheme leaks the secret key (see the [https://eprint.iacr.org/2018/068 MuSig paper] for details). Note that this is not a ''unique signature'' scheme: while this algorithm will always produce the same signature for a given message and public key, ''k'' (and hence ''R'') may be generated in other ways (such as by a CSPRNG) producing a different, but still valid, signature. -- cgit v1.2.3 From 348110ec52118c4751f38d1b48bef77be908e1a7 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 15 Oct 2019 12:29:52 -0700 Subject: Typo --- bip-schnorr.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 5dd5305..c936ed3 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -192,7 +192,7 @@ The algorithm ''BatchVerify(pk1..u, m1..u, sig1..u1 + a2s2 + ... + ausu)⋅G ≠ R1 + a2⋅R2 + ... + au⋅Ru + e1⋅P1 + (a2e2)⋅P2 + ... + (aueu)⋅Pu''. * Return success iff no failure occurred before reaching this point. -If all individual signatures are valid (i.e., ''Verify'' would return success for them), ''BatchVerify'' will always return success. If at least one signature is invalid, ''BatchVerify'' will return success with at most a negligable probability. +If all individual signatures are valid (i.e., ''Verify'' would return success for them), ''BatchVerify'' will always return success. If at least one signature is invalid, ''BatchVerify'' will return success with at most a negligible probability. === Optimizations === -- cgit v1.2.3 From e139975eff5e9dec5fb640ca1da10e3a42118590 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Tue, 15 Oct 2019 16:02:09 -0700 Subject: bip-schnorr: more on provable security I'll try to get a link to the CCS paper that does not have a paywall... --- bip-schnorr.mediawiki | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index c936ed3..d7ac9b1 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -25,8 +25,8 @@ Bitcoin has traditionally used transactions. These are [https://www.secg.org/sec1-v2.pdf standardized], but have a number of downsides compared to [http://publikationen.ub.uni-frankfurt.de/opus4/files/4280/schnorr.pdf Schnorr signatures] over the same curve: -* '''Security proof''': The security of Schnorr signatures is easily [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf provable] in the random oracle model assuming the elliptic curve discrete logarithm problem (ECDLP) is hard. Such a proof does not exist for ECDSA. -* '''Non-malleability''': ECDSA signatures are inherently malleable; a third party without access to the secret key can alter an existing valid signature for a given public key and message into another signature that is valid for the same key and message. This issue is discussed in [https://github.com/bitcoin/bips/blob/master/bip-0062.mediawiki BIP62] and [https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki BIP66]. On the other hand, Schnorr signatures are provably non-malleableMore precisely they are '' '''strongly''' unforgeable under chosen message attacks '' (SUF-CMA), which informally means that without knowledge of the secret key but given a valid signature of a message, it is not possible to come up with a second valid signature for the same message. A security proof in the random oracle model can be found for example in [https://eprint.iacr.org/2016/191 a paper by Kiltz, Masny and Pan], which essentially restates [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf the original security proof of Schnorr signatures by Pointcheval and Stern] more explicitly. These proofs are for the Schnorr signature variant using ''(e,s)'' instead of ''(R,s)'' (see Design above). Since we use a unique encoding of ''R'', there is an efficiently computable bijection that maps ''(R, s)'' to ''(e, s)'', which allows to convert a successful SUF-CMA attacker for the ''(e, s)'' variant to a successful SUF-CMA attacker for the ''(r, s)'' variant (and vice-versa). Furthermore, the aforementioned proofs consider a variant of Schnorr signatures without key prefixing (see Design above), but it can be verified that the proofs are also correct for the variant with key prefixing. As a result, the aforementioned security proofs apply to the variant of Schnorr signatures proposed in this document.. +* '''Provable security''': Schnorr signatures are provably secure. In more detail, they are ''strongly unforgeable under chosen message attack (SUF-CMA)''Informally, this means that without knowledge of the secret key but given valid signatures of arbitrary messages, it is not possible to come up with further valid signatures. [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf in the random oracle model assuming the hardness of the elliptic curve discrete logarithm problem (ECDLP)] and [http://www.neven.org/papers/schnorr.pdf in the generic group model assuming prefix assuming variants of preimage and second preimage resistance of the used hash function]A detailed security proof in the random oracle model, which essentially restates [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf the original security proof by Pointcheval and Stern] more explicitly, can be found in [https://eprint.iacr.org/2016/191 a paper by Kiltz, Masny and Pan]. All these security proofs assume a variant of Schnorr signatures that use ''(e,s)'' instead of ''(R,s)'' (see Design above). Since we use a unique encoding of ''R'', there is an efficiently computable bijection that maps ''(R, s)'' to ''(e, s)'', which allows to convert a successful SUF-CMA attacker for the ''(e, s)'' variant to a successful SUF-CMA attacker for the ''(r, s)'' variant (and vice-versa). Furthermore, the proofs consider a variant of Schnorr signatures without key prefixing (see Design above), but it can be verified that the proofs are also correct for the variant with key prefixing. As a result, all the aforementioned security proofs apply to the variant of Schnorr signatures proposed in this document.. The [https://dl.acm.org/citation.cfm?id=2978413 best known security proof for ECDSA] relies on stronger assumptions. +* '''Non-malleability''': The SUF-CMA security of Schnorr signatures implies that they are non-malleable. On the other hand, ECDSA signatures are inherently malleable; a third party without access to the secret key can alter an existing valid signature for a given public key and message into another signature that is valid for the same key and message. This issue is discussed in [https://github.com/bitcoin/bips/blob/master/bip-0062.mediawiki BIP62] and [https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki BIP66]. * '''Linearity''': Schnorr signatures have the remarkable property that multiple parties can collaborate to produce a signature that is valid for the sum of their public keys. This is the building block for various higher-level constructions that improve efficiency and privacy, such as multisignatures and others (see Applications below). For all these advantages, there are virtually no disadvantages, apart -- cgit v1.2.3 From 2d9877e6e1cd05120a4c60ef1fb831f73f4b1c1d Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Tue, 15 Oct 2019 16:21:40 -0700 Subject: bip-schnorr: more on (e,s) --- bip-schnorr.mediawiki | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index d7ac9b1..1876469 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -25,7 +25,7 @@ Bitcoin has traditionally used transactions. These are [https://www.secg.org/sec1-v2.pdf standardized], but have a number of downsides compared to [http://publikationen.ub.uni-frankfurt.de/opus4/files/4280/schnorr.pdf Schnorr signatures] over the same curve: -* '''Provable security''': Schnorr signatures are provably secure. In more detail, they are ''strongly unforgeable under chosen message attack (SUF-CMA)''Informally, this means that without knowledge of the secret key but given valid signatures of arbitrary messages, it is not possible to come up with further valid signatures. [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf in the random oracle model assuming the hardness of the elliptic curve discrete logarithm problem (ECDLP)] and [http://www.neven.org/papers/schnorr.pdf in the generic group model assuming prefix assuming variants of preimage and second preimage resistance of the used hash function]A detailed security proof in the random oracle model, which essentially restates [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf the original security proof by Pointcheval and Stern] more explicitly, can be found in [https://eprint.iacr.org/2016/191 a paper by Kiltz, Masny and Pan]. All these security proofs assume a variant of Schnorr signatures that use ''(e,s)'' instead of ''(R,s)'' (see Design above). Since we use a unique encoding of ''R'', there is an efficiently computable bijection that maps ''(R, s)'' to ''(e, s)'', which allows to convert a successful SUF-CMA attacker for the ''(e, s)'' variant to a successful SUF-CMA attacker for the ''(r, s)'' variant (and vice-versa). Furthermore, the proofs consider a variant of Schnorr signatures without key prefixing (see Design above), but it can be verified that the proofs are also correct for the variant with key prefixing. As a result, all the aforementioned security proofs apply to the variant of Schnorr signatures proposed in this document.. The [https://dl.acm.org/citation.cfm?id=2978413 best known security proof for ECDSA] relies on stronger assumptions. +* '''Provable security''': Schnorr signatures are provably secure. In more detail, they are ''strongly unforgeable under chosen message attack (SUF-CMA)''Informally, this means that without knowledge of the secret key but given valid signatures of arbitrary messages, it is not possible to come up with further valid signatures. [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf in the random oracle model assuming the hardness of the elliptic curve discrete logarithm problem (ECDLP)] and [http://www.neven.org/papers/schnorr.pdf in the generic group model assuming variants of preimage and second preimage resistance of the used hash function]A detailed security proof in the random oracle model, which essentially restates [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf the original security proof by Pointcheval and Stern] more explicitly, can be found in [https://eprint.iacr.org/2016/191 a paper by Kiltz, Masny and Pan]. All these security proofs assume a variant of Schnorr signatures that use ''(e,s)'' instead of ''(R,s)'' (see Design above). Since we use a unique encoding of ''R'', there is an efficiently computable bijection that maps ''(R,s)'' to ''(e,s)'', which allows to convert a successful SUF-CMA attacker for the ''(e,s)'' variant to a successful SUF-CMA attacker for the ''(r,s)'' variant (and vice-versa). Furthermore, the proofs consider a variant of Schnorr signatures without key prefixing (see Design above), but it can be verified that the proofs are also correct for the variant with key prefixing. As a result, all the aforementioned security proofs apply to the variant of Schnorr signatures proposed in this document.. The [https://dl.acm.org/citation.cfm?id=2978413 best known security proof for ECDSA] relies on stronger assumptions. * '''Non-malleability''': The SUF-CMA security of Schnorr signatures implies that they are non-malleable. On the other hand, ECDSA signatures are inherently malleable; a third party without access to the secret key can alter an existing valid signature for a given public key and message into another signature that is valid for the same key and message. This issue is discussed in [https://github.com/bitcoin/bips/blob/master/bip-0062.mediawiki BIP62] and [https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki BIP66]. * '''Linearity''': Schnorr signatures have the remarkable property that multiple parties can collaborate to produce a signature that is valid for the sum of their public keys. This is the building block for various higher-level constructions that improve efficiency and privacy, such as multisignatures and others (see Applications below). @@ -38,8 +38,6 @@ made: * '''Public key encoding''': Instead of using ''compressed'' 33-byte encodings of elliptic curve points which are common in Bitcoin today, public keys in this proposal are encoded as 32 bytes. * '''Batch verification''': The specific formulation of ECDSA signatures that is standardized cannot be verified more efficiently in batch compared to individually, unless additional witness data is added. Changing the signature scheme offers an opportunity to avoid this. -[[File:bip-schnorr/speedup-batch.png|frame|This graph shows the ratio between the time it takes to verify ''n'' signatures individually and to verify a batch of ''n'' signatures. This ratio goes up logarithmically with the number of signatures, or in other words: the total time to verify ''n'' signatures grows with ''O(n / log n)''.]] - By reusing the same curve as Bitcoin uses for ECDSA, we are able to retain existing mechanisms for choosing secret and public keys, and we avoid introducing new assumptions about elliptic curve group security. == Description == @@ -50,13 +48,15 @@ encodings and operations. === Design === -'''Schnorr signature variant''' Elliptic Curve Schnorr signatures for message ''m'' and public key ''P'' generally involve a point ''R'', integers ''e'' and ''s'' picked by the signer, and generator ''G'' which satisfy ''e = hash(R || m)'' and ''sG = R + eP''. Two formulations exist, depending on whether the signer reveals ''e'' or ''R'': -# Signatures are ''(e,s)'' that satisfy ''e = hash(sG - eP || m)''. This avoids minor complexity introduced by the encoding of the point ''R'' in the signature (see paragraphs "Encoding the sign of R" and "Implicit Y coordinate" further below in this subsection). -# Signatures are ''(R,s)'' that satisfy ''sG = R + hash(R || m)P''. This supports batch verification, as there are no elliptic curve operations inside the hashes. +'''Schnorr signature variant''' Elliptic Curve Schnorr signatures for message ''m'' and public key ''P'' generally involve a point ''R'', integers ''e'' and ''s'' picked by the signer, and generator ''G'' which satisfy ''e = hash(R || m)'' and ''s⋅G = R + e⋅P''. Two formulations exist, depending on whether the signer reveals ''e'' or ''R'': +# Signatures are ''(e,s)'' that satisfy ''e = hash(s⋅G - e⋅P || m)''. This supports more compact signatures, since [http://www.neven.org/papers/schnorr.pdf the hash ''e'' can be made as small as 16 bytes without sacrificing security], whereas an encoding of ''R'' inherently needs about 32 bytes. Moreover, this variant avoids minor complexity introduced by the encoding of the point ''R'' in the signature (see paragraphs "Encoding the sign of R" and "Implicit Y coordinate" further below in this subsection). +# Signatures are ''(R,s)'' that satisfy ''s⋅G = R + hash(R || m)⋅P''. This supports batch verification, as there are no elliptic curve operations inside the hashes. Batch verification enables significant speedups. + +[[File:bip-schnorr/speedup-batch.png|center|frame|This graph shows the ratio between the time it takes to verify ''n'' signatures individually and to verify a batch of ''n'' signatures. This ratio goes up logarithmically with the number of signatures, or in other words: the total time to verify ''n'' signatures grows with ''O(n / log n)''.]] We choose the ''R''-option to support batch verification. -'''Key prefixing''' When using the verification rule above directly, it is possible for a third party to convert a signature ''(R,s)'' for key ''P'' into a signature ''(R,s + a⋅hash(R || m))'' for key ''P + aG'' and the same message, for any integer ''a''. This is not a concern for Bitcoin currently, as all signature hashes indirectly commit to the public keys. However, this may change with proposals such as SIGHASH_NOINPUT ([https://github.com/bitcoin/bips/blob/master/bip-0118.mediawiki BIP 118]), or when the signature scheme is used for other purposes—especially in combination with schemes like [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki BIP32]'s unhardened derivation. To combat this, we choose ''key prefixed''A limitation of committing to the public key (rather than to a short hash of it, or not at all) is that it removes the ability for public key recovery or verifying signatures against a short public key hash. These constructions are generally incompatible with batch verification. Schnorr signatures; changing the equation to ''sG = R + hash(R || P || m)P''. +'''Key prefixing''' When using the verification rule above directly, it is possible for a third party to convert a signature ''(R,s)'' for key ''P'' into a signature ''(R,s + a⋅hash(R || m))'' for key ''P + a⋅G'' and the same message, for any integer ''a''. This is not a concern for Bitcoin currently, as all signature hashes indirectly commit to the public keys. However, this may change with proposals such as SIGHASH_NOINPUT ([https://github.com/bitcoin/bips/blob/master/bip-0118.mediawiki BIP 118]), or when the signature scheme is used for other purposes—especially in combination with schemes like [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki BIP32]'s unhardened derivation. To combat this, we choose ''key prefixed''A limitation of committing to the public key (rather than to a short hash of it, or not at all) is that it removes the ability for public key recovery or verifying signatures against a short public key hash. These constructions are generally incompatible with batch verification. Schnorr signatures; changing the equation to ''s⋅G = R + hash(R || P || m)⋅P''. '''Encoding R and public key point P''' There exist several possibilities for encoding elliptic curve points: # Encoding the full X and Y coordinates of ''P'' and ''R'', resulting in a 64-byte public key and a 96-byte signature. @@ -87,7 +87,7 @@ For example, without tagged hashing a bip-schnorr signature could also be valid This proposal suggests to include the tag by prefixing the hashed data with ''SHA256(tag) || SHA256(tag)''. Because this is a 64-byte long context-specific constant and the ''SHA256'' block size is also 64 bytes, optimized implementations are possible (identical to SHA256 itself, but with a modified initial state). Using SHA256 of the tag name itself is reasonably simple and efficient for implementations that don't choose to use the optimization. -'''Final scheme''' As a result, our final scheme ends up using public key ''pk'' which is the X coordinate of a point ''P'' on the curve whose Y coordinate is a square and signatures ''(r,s)'' where ''r'' is the X coordinate of a point ''R'' whose Y coordinate is a square. The signature satisfies ''sG = R + tagged_hash(r || pk || m)P''. +'''Final scheme''' As a result, our final scheme ends up using public key ''pk'' which is the X coordinate of a point ''P'' on the curve whose Y coordinate is a square and signatures ''(r,s)'' where ''r'' is the X coordinate of a point ''R'' whose Y coordinate is a square. The signature satisfies ''s⋅G = R + tagged_hash(r || pk || m)⋅P''. === Specification === @@ -141,7 +141,7 @@ Input: The algorithm ''Sign(sk, m)'' is defined as: * Let ''d' = int(sk)'' * Fail if ''d' = 0'' or ''d' ≥ n'' - * Let ''P = d'⋅G'' +* Let ''P = d'⋅G'' * Let ''d = d' '' if ''is_positive(P)'', otherwise let ''d = n - d' ''. * Let ''k' = int(hashBIPSchnorrDerive(bytes(d) || m)) mod n''Note that in general, taking the output of a hash function modulo the curve order will produce an unacceptably biased result. However, for the secp256k1 curve, the order is sufficiently close to ''2256'' that this bias is not observable (''1 - n / 2256'' is around ''1.27 * 2-128'').. * Fail if ''k' = 0''. -- cgit v1.2.3 From 59ac6a96832e89de8fa0082743171a9f3659e600 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 15 Oct 2019 15:21:08 -0700 Subject: Explain that MuSig needs key prefixing --- bip-schnorr.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 1876469..4fede9d 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -56,7 +56,7 @@ encodings and operations. We choose the ''R''-option to support batch verification. -'''Key prefixing''' When using the verification rule above directly, it is possible for a third party to convert a signature ''(R,s)'' for key ''P'' into a signature ''(R,s + a⋅hash(R || m))'' for key ''P + a⋅G'' and the same message, for any integer ''a''. This is not a concern for Bitcoin currently, as all signature hashes indirectly commit to the public keys. However, this may change with proposals such as SIGHASH_NOINPUT ([https://github.com/bitcoin/bips/blob/master/bip-0118.mediawiki BIP 118]), or when the signature scheme is used for other purposes—especially in combination with schemes like [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki BIP32]'s unhardened derivation. To combat this, we choose ''key prefixed''A limitation of committing to the public key (rather than to a short hash of it, or not at all) is that it removes the ability for public key recovery or verifying signatures against a short public key hash. These constructions are generally incompatible with batch verification. Schnorr signatures; changing the equation to ''s⋅G = R + hash(R || P || m)⋅P''. +'''Key prefixing''' When using the verification rule above directly, it is possible for a third party to convert a signature ''(R, s)'' for key ''P'' into a signature ''(R, s + a⋅hash(R || m))'' for key ''P + a⋅G'' and the same message, for any integer ''a''. To combat this, we choose ''key prefixed''A limitation of committing to the public key (rather than to a short hash of it, or not at all) is that it removes the ability for public key recovery or verifying signatures against a short public key hash. These constructions are generally incompatible with batch verification. Schnorr signatures; changing the equation to ''s⋅G = R + hash(R || P || m)⋅P''. Key prefixing also seems to be a requirement for the security proof of the MuSig multisignature scheme (see below, under applications). It is not strictly necessary to do this explicitly for Bitcoin currently, as all signature hashes indirectly commit to the public keys already. However, this may change with proposals such as SIGHASH_NOINPUT ([https://github.com/bitcoin/bips/blob/master/bip-0118.mediawiki BIP 118]), or when the signature scheme is used for other purposes—especially in combination with schemes like [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki BIP32]'s unhardened derivation. '''Encoding R and public key point P''' There exist several possibilities for encoding elliptic curve points: # Encoding the full X and Y coordinates of ''P'' and ''R'', resulting in a 64-byte public key and a 96-byte signature. -- cgit v1.2.3 From d434c18af8f9eaa66524889014a4829bb9e44f2a Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 15 Oct 2019 17:28:52 -0700 Subject: Update bip-schnorr.mediawiki Co-Authored-By: Tim Ruffing --- bip-schnorr.mediawiki | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 4fede9d..12a7379 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -49,14 +49,14 @@ encodings and operations. === Design === '''Schnorr signature variant''' Elliptic Curve Schnorr signatures for message ''m'' and public key ''P'' generally involve a point ''R'', integers ''e'' and ''s'' picked by the signer, and generator ''G'' which satisfy ''e = hash(R || m)'' and ''s⋅G = R + e⋅P''. Two formulations exist, depending on whether the signer reveals ''e'' or ''R'': -# Signatures are ''(e,s)'' that satisfy ''e = hash(s⋅G - e⋅P || m)''. This supports more compact signatures, since [http://www.neven.org/papers/schnorr.pdf the hash ''e'' can be made as small as 16 bytes without sacrificing security], whereas an encoding of ''R'' inherently needs about 32 bytes. Moreover, this variant avoids minor complexity introduced by the encoding of the point ''R'' in the signature (see paragraphs "Encoding the sign of R" and "Implicit Y coordinate" further below in this subsection). -# Signatures are ''(R,s)'' that satisfy ''s⋅G = R + hash(R || m)⋅P''. This supports batch verification, as there are no elliptic curve operations inside the hashes. Batch verification enables significant speedups. +# Signatures are ''(e, s)'' that satisfy ''e = hash(s⋅G - e⋅P || m)''. This supports more compact signatures, since [http://www.neven.org/papers/schnorr.pdf the hash ''e'' can be made as small as 16 bytes without sacrificing security], whereas an encoding of ''R'' inherently needs about 32 bytes. Moreover, this variant avoids minor complexity introduced by the encoding of the point ''R'' in the signature (see paragraphs "Encoding the sign of R" and "Implicit Y coordinate" further below in this subsection). +# Signatures are ''(R, s)'' that satisfy ''s⋅G = R + hash(R || m)⋅P''. This supports batch verification, as there are no elliptic curve operations inside the hashes. Batch verification enables significant speedups. [[File:bip-schnorr/speedup-batch.png|center|frame|This graph shows the ratio between the time it takes to verify ''n'' signatures individually and to verify a batch of ''n'' signatures. This ratio goes up logarithmically with the number of signatures, or in other words: the total time to verify ''n'' signatures grows with ''O(n / log n)''.]] We choose the ''R''-option to support batch verification. -'''Key prefixing''' When using the verification rule above directly, it is possible for a third party to convert a signature ''(R, s)'' for key ''P'' into a signature ''(R, s + a⋅hash(R || m))'' for key ''P + a⋅G'' and the same message, for any integer ''a''. To combat this, we choose ''key prefixed''A limitation of committing to the public key (rather than to a short hash of it, or not at all) is that it removes the ability for public key recovery or verifying signatures against a short public key hash. These constructions are generally incompatible with batch verification. Schnorr signatures; changing the equation to ''s⋅G = R + hash(R || P || m)⋅P''. Key prefixing also seems to be a requirement for the security proof of the MuSig multisignature scheme (see below, under applications). It is not strictly necessary to do this explicitly for Bitcoin currently, as all signature hashes indirectly commit to the public keys already. However, this may change with proposals such as SIGHASH_NOINPUT ([https://github.com/bitcoin/bips/blob/master/bip-0118.mediawiki BIP 118]), or when the signature scheme is used for other purposes—especially in combination with schemes like [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki BIP32]'s unhardened derivation. +'''Key prefixing''' When using the verification rule above directly, it is possible for a third party to convert a signature ''(R, s)'' for key ''P'' into a signature ''(R, s + a⋅hash(R || m))'' for key ''P + a⋅G'' and the same message, for any integer ''a''. To combat this, we choose ''key prefixed''A limitation of committing to the public key (rather than to a short hash of it, or not at all) is that it removes the ability for public key recovery or verifying signatures against a short public key hash. These constructions are generally incompatible with batch verification. Schnorr signatures; changing the equation to ''s⋅G = R + hash(R || P || m)⋅P''. Key prefixing also seems to be a requirement for the security proof of the MuSig multisignature scheme (see Applications below). It is not strictly necessary to do this explicitly for Bitcoin currently, as all signature hashes indirectly commit to the public keys already. However, this may change with proposals such as SIGHASH_NOINPUT ([https://github.com/bitcoin/bips/blob/master/bip-0118.mediawiki BIP 118]), or when the signature scheme is used for other purposes—especially in combination with schemes like [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki BIP32]'s unhardened derivation. '''Encoding R and public key point P''' There exist several possibilities for encoding elliptic curve points: # Encoding the full X and Y coordinates of ''P'' and ''R'', resulting in a 64-byte public key and a 96-byte signature. -- cgit v1.2.3 From 0a45ecbf04252823ac5e4df23a9eb0be4fda5a55 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 15 Oct 2019 16:03:19 -0700 Subject: Clarify interaction x-only keys with verification --- bip-schnorr.mediawiki | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 1876469..fe0bdf5 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -77,8 +77,6 @@ expensive conversion to affine coordinates first. This would even be the case if For ''P'' the speed of signing and verification does not significantly differ between any of the three options because affine coordinates of the point have to be computed anyway. For consistency reasons we choose the same option as for ''R''. The signing algorithm ensures that the signature is valid under the correct public key by negating the secret key if necessary. -It is important not to mix up the 32-byte bip-schnorr public key format and other existing public key formats (e.g. encodings used in Bitcoin's ECDSA). Concretely, a verifier should only accept 32-byte public keys and not, for example, convert a 33-byte public key by throwing away the first byte. Otherwise, two public keys would be valid for a single signature which can result in subtle malleability issues (although this type of malleability already exists in the case of ECDSA signatures). - Implicit Y coordinates are not a reduction in security when expressed as the number of elliptic curve operations an attacker is expected to perform to compute the secret key. An attacker can normalize any given public key to a point whose Y coordinate is a square by negating the point if necessary. This is just a subtraction of field elements and not an elliptic curve operationThis can be formalized by a simple reduction that reduces an attack on Schnorr signatures with implicit Y coordinates to an attack to Schnorr signatures with explicit Y coordinates. The reduction works by reencoding public keys and negating the result of the hash function, which is modeled as random oracle, whenever the challenge public key has an explicit Y coordinate that is not a square.. '''Tagged Hashes''' Cryptographic hash functions are used for multiple purposes in the specification below and in Bitcoin in general. To make sure hashes used in one context can't be reinterpreted in another one, hash functions can be tweaked with a context-dependent tag name, in such a way that collisions across contexts can be assumed to be infeasible. Such collisions obviously can not be ruled out completely, but only for schemes using tagging with a unique name. As for other schemes collisions are at least less likely with tagging than without. @@ -173,6 +171,8 @@ The algorithm ''Verify(pk, m, sig)'' is defined as: For every valid secret key ''sk'' and message ''m'', ''Verify(PubKey(sk),m,Sign(sk,m))'' will succeed. +Note that the correctness of verification relies on the fact that ''point(pk)'' always returns a positive point (i.e., with a square Y coordinate). A hypothetical verification algorithm that treats points as public keys, and takes the point ''P'' directly as input would fail any time a negative point is used. While it is possible to correct for this by negating negative points before further processing, this would result in a scheme where every (message, signature) pair is valid for two public keys (a type of malleability that exists for ECDSA as well, but we don't wish to retain). We avoid these problems by treating just the X coordinate as public key. + ==== Batch Verification ==== Input: -- cgit v1.2.3 From 2a9a70c92ac33f88dffe82a3b3739f5e905510f1 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 15 Oct 2019 17:54:04 -0700 Subject: More on key generation --- bip-schnorr.mediawiki | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index fe0bdf5..a323b7e 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -125,10 +125,9 @@ The algorithm ''PubKey(sk)'' is defined as: * Fail if ''d = 0'' or ''d ≥ n''. * Return ''bytes(d⋅G)''. -Note that ''PubKey(sk) = PubKey(bytes(n - int(sk))'', so every public key has two corresponding private keys. +Note that we use a very different public key format (32 bytes) than the ones used by existing systems (which typically use elliptic curve points as public keys, or 33-byte or 65-byte encodings of them). A side effect is that ''PubKey(sk) = PubKey(bytes(n - int(sk))'', so every public key has two corresponding private keys. -Alternatively, the public key can be created according to [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki BIP32] which describes the derivation of 33-byte compressed public keys. -In order to translate such public keys into bip-schnorr compatible keys, the first byte must be dropped. +As an alternative to generating keys randomly, it is also possible and safe to repurpose existing key generation algorithms for ECDSA in a compatible way. The private keys constructed by such an algorithm can be used as ''sk'' directly. The public keys constructed by such an algorithm (assuming they use the 33-byte compressed encoding) need to be converted by dropping the first byte. Specifically, [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki BIP32] and schemes built on top of it remain usable. ==== Signing ==== -- cgit v1.2.3 From 01e0c43023d3a48c9ecbeded1546b65bf100f119 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Fri, 18 Oct 2019 13:41:00 +1000 Subject: annex is bit 0 of spend_type --- bip-taproot.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 4f84c28..1b8ed0c 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -135,7 +135,7 @@ As the message for signature verification, transaction digest is ''hashTapS *** nSequence (4): nSequence of this input. ** If the SIGHASH_ANYONECANPAY flag is not set: *** input_index (4): index of this input in the transaction input vector. Index of the first input is 0. -** If the bit-1 of spend_type is set: +** If bit 0 of spend_type is set: *** sha_annex (32): the SHA256 of (compact_size(size of annex) || annex). * Data about this output: ** If the SIGHASH_SINGLE flag is set: -- cgit v1.2.3 From 0176ed187159d36acc5e9309543d0b993291bc40 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Mon, 21 Oct 2019 13:27:01 +0200 Subject: Change reference for ECDSA proofs Refer to Manuel Fersch's dissertation for provable security of ECDSA. It's freely accessible and multiple results put well in context. --- bip-schnorr.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index fd77d22..14f8610 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -25,7 +25,7 @@ Bitcoin has traditionally used transactions. These are [https://www.secg.org/sec1-v2.pdf standardized], but have a number of downsides compared to [http://publikationen.ub.uni-frankfurt.de/opus4/files/4280/schnorr.pdf Schnorr signatures] over the same curve: -* '''Provable security''': Schnorr signatures are provably secure. In more detail, they are ''strongly unforgeable under chosen message attack (SUF-CMA)''Informally, this means that without knowledge of the secret key but given valid signatures of arbitrary messages, it is not possible to come up with further valid signatures. [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf in the random oracle model assuming the hardness of the elliptic curve discrete logarithm problem (ECDLP)] and [http://www.neven.org/papers/schnorr.pdf in the generic group model assuming variants of preimage and second preimage resistance of the used hash function]A detailed security proof in the random oracle model, which essentially restates [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf the original security proof by Pointcheval and Stern] more explicitly, can be found in [https://eprint.iacr.org/2016/191 a paper by Kiltz, Masny and Pan]. All these security proofs assume a variant of Schnorr signatures that use ''(e,s)'' instead of ''(R,s)'' (see Design above). Since we use a unique encoding of ''R'', there is an efficiently computable bijection that maps ''(R,s)'' to ''(e,s)'', which allows to convert a successful SUF-CMA attacker for the ''(e,s)'' variant to a successful SUF-CMA attacker for the ''(r,s)'' variant (and vice-versa). Furthermore, the proofs consider a variant of Schnorr signatures without key prefixing (see Design above), but it can be verified that the proofs are also correct for the variant with key prefixing. As a result, all the aforementioned security proofs apply to the variant of Schnorr signatures proposed in this document.. The [https://dl.acm.org/citation.cfm?id=2978413 best known security proof for ECDSA] relies on stronger assumptions. +* '''Provable security''': Schnorr signatures are provably secure. In more detail, they are ''strongly unforgeable under chosen message attack (SUF-CMA)''Informally, this means that without knowledge of the secret key but given valid signatures of arbitrary messages, it is not possible to come up with further valid signatures. [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf in the random oracle model assuming the hardness of the elliptic curve discrete logarithm problem (ECDLP)] and [http://www.neven.org/papers/schnorr.pdf in the generic group model assuming variants of preimage and second preimage resistance of the used hash function]A detailed security proof in the random oracle model, which essentially restates [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf the original security proof by Pointcheval and Stern] more explicitly, can be found in [https://eprint.iacr.org/2016/191 a paper by Kiltz, Masny and Pan]. All these security proofs assume a variant of Schnorr signatures that use ''(e,s)'' instead of ''(R,s)'' (see Design above). Since we use a unique encoding of ''R'', there is an efficiently computable bijection that maps ''(R,s)'' to ''(e,s)'', which allows to convert a successful SUF-CMA attacker for the ''(e,s)'' variant to a successful SUF-CMA attacker for the ''(r,s)'' variant (and vice-versa). Furthermore, the proofs consider a variant of Schnorr signatures without key prefixing (see Design above), but it can be verified that the proofs are also correct for the variant with key prefixing. As a result, all the aforementioned security proofs apply to the variant of Schnorr signatures proposed in this document.. In contrast, the [https://nbn-resolving.de/urn:nbn:de:hbz:294-60803 best known results for the provable security of ECDSA] rely on stronger assumptions. * '''Non-malleability''': The SUF-CMA security of Schnorr signatures implies that they are non-malleable. On the other hand, ECDSA signatures are inherently malleable; a third party without access to the secret key can alter an existing valid signature for a given public key and message into another signature that is valid for the same key and message. This issue is discussed in [https://github.com/bitcoin/bips/blob/master/bip-0062.mediawiki BIP62] and [https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki BIP66]. * '''Linearity''': Schnorr signatures have the remarkable property that multiple parties can collaborate to produce a signature that is valid for the sum of their public keys. This is the building block for various higher-level constructions that improve efficiency and privacy, such as multisignatures and others (see Applications below). -- cgit v1.2.3 From 474d214d03cc32705482dad44399d5fd1b068d56 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 21 Oct 2019 16:16:47 -0700 Subject: Improve section on alternatives to OP_CHECKMULTISIG --- bip-tapscript.mediawiki | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index a325573..91ed97c 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -71,7 +71,11 @@ The execution rules for tapscript are based on those for P2WSH according to BIP1 * '''Consensus-enforced MINIMALIF''' The MINIMALIF rules, which are only a standardness rule in P2WSH, are consensus enforced in tapscript. This means that the input argument to the OP_IF and OP_NOTIF opcodes must be either exactly 0 (the empty vector) or exactly 1 (the one-byte vector with value 1)'''Why make MINIMALIF consensus?''' This makes it considerably easier to write non-malleable scripts that take branch information from the stack.. * '''OP_SUCCESSx opcodes''' As listed above, some opcodes are renamed to OP_SUCCESSx, and make the script unconditionally valid. * '''Signature opcodes'''. The OP_CHECKSIG and OP_CHECKSIGVERIFY are modified to operate on Schnorr public keys and signatures (see bip-schnorr) instead of ECDSA, and a new opcode OP_CHECKSIGADD is added. -** The opcode 186 (0xba) is named as OP_CHECKSIGADD. '''OP_CHECKSIGADD''' This opcode is added to compensate for the loss of OP_CHECKMULTISIG-like opcodes, which are incompatible with batch verification. OP_CHECKSIGADD is functionally equivalent to OP_ROT OP_SWAP OP_CHECKSIG OP_ADD, but only takes 1 byte. All CScriptNum-related behaviours of OP_ADD are also applicable to OP_CHECKSIGADD.'''Comparison of CHECKMULTISIG and CHECKSIG''' A CHECKMULTISIG script m ... n CHECKMULTISIG with witness 0 ... can be rewritten as script CHECKSIG ... CHECKSIGADD m NUMEQUAL with witness ... . Every witness element w_i is either a signature corresponding to the public key with the same index or an empty vector. A similar CHECKMULTISIGVERIFY script can be translated to bip-tapscript by replacing NUMEQUAL with NUMEQUALVERIFY. Alternatively, an m-of-n multisig policy can be implemented by splitting the script into several leaves of the Merkle tree, each implementing an m-of-m policy using CHECKSIGVERIFY ... CHECKSIGVERIFY CHECKSIG. If the setting allows the participants to interactively collaborate while signing, multisig policies can be realized with [https://eprint.iacr.org/2018/068 MuSig] for m-of-m and with [http://cacr.uwaterloo.ca/techreports/2001/corr2001-13.ps threshold signatures] using verifiable secret sharing for m-of-n. +** The opcode 186 (0xba) is named as OP_CHECKSIGADD. '''OP_CHECKSIGADD''' This opcode is added to compensate for the loss of OP_CHECKMULTISIG-like opcodes, which are incompatible with batch verification. OP_CHECKSIGADD is functionally equivalent to OP_ROT OP_SWAP OP_CHECKSIG OP_ADD, but only takes 1 byte. All CScriptNum-related behaviours of OP_ADD are also applicable to OP_CHECKSIGADD.'''Alternatives to CHECKMULTISIG''' There are multiple ways of implementing a threshold ''k''-of-''n'' policy using Taproot and Tapscript: +* '''Using a single OP_CHECKSIGADD-based script''' A CHECKMULTISIG script m ... n CHECKMULTISIG with witness 0 ... can be rewritten as script CHECKSIG ... CHECKSIGADD m NUMEQUAL with witness ... . Every witness element w_i is either a signature corresponding to the public key with the same index or an empty vector. A similar CHECKMULTISIGVERIFY script can be translated to bip-tapscript by replacing NUMEQUAL with NUMEQUALVERIFY. This approach has very similar characteristics to the existing OP_CHECKMULTISIG-based scripts. +* '''Using a ''k''-of-''k'' script for every combination''' A ''k''-of-''n'' policy can be implemented by splitting the script into several leaves of the Merkle tree, each implementing a ''k''-of-''k'' policy using CHECKSIGVERIFY ... CHECKSIGVERIFY CHECKSIG. This may be preferable for privacy reasons over the previous approach, as it only exposes the participating public keys, but it is only more cost effective for small values of ''k'' (1-of-''n'' for any ''n'', 2-of-''n'' for ''n ≥ 6'', 3-of-''n'' for ''n ≥ 9'', ...). Furthermore, the signatures here depend on the branch used, which means signers need to be aware of which other signers will be participating, or produce signatures for each of the tree leaves. +* '''Using an aggregated public key for every combination''' Instead of building a tree where every leaf consists of ''k'' public keys, it is possible instead build a tree where every leaf contains a single ''aggregate'' of those ''k'' keys using [https://eprint.iacr.org/2018/068 MuSig]. This approach is far more efficient, but does require a 3-round interactive signing protocol to jointly produce the (single) signature. +* '''Native Schnorr threshold signatures''' Multisig policies can also be realized with [http://cacr.uwaterloo.ca/techreports/2001/corr2001-13.ps threshold signatures] using verifiable secret sharing. This results in outputs and inputs that are indistinguishable from single-key payments, but at the cost of needing an interactive protocol (and associated backup procedures) before determining the address to send to. ===Rules for signature opcodes=== -- cgit v1.2.3 From 6ad79bcd466bf6eca1aa6ca372b246e1d206f71d Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 22 Oct 2019 11:15:36 -0700 Subject: Address aj comments --- bip-tapscript.mediawiki | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index 91ed97c..34d7e48 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -72,8 +72,8 @@ The execution rules for tapscript are based on those for P2WSH according to BIP1 * '''OP_SUCCESSx opcodes''' As listed above, some opcodes are renamed to OP_SUCCESSx, and make the script unconditionally valid. * '''Signature opcodes'''. The OP_CHECKSIG and OP_CHECKSIGVERIFY are modified to operate on Schnorr public keys and signatures (see bip-schnorr) instead of ECDSA, and a new opcode OP_CHECKSIGADD is added. ** The opcode 186 (0xba) is named as OP_CHECKSIGADD. '''OP_CHECKSIGADD''' This opcode is added to compensate for the loss of OP_CHECKMULTISIG-like opcodes, which are incompatible with batch verification. OP_CHECKSIGADD is functionally equivalent to OP_ROT OP_SWAP OP_CHECKSIG OP_ADD, but only takes 1 byte. All CScriptNum-related behaviours of OP_ADD are also applicable to OP_CHECKSIGADD.'''Alternatives to CHECKMULTISIG''' There are multiple ways of implementing a threshold ''k''-of-''n'' policy using Taproot and Tapscript: -* '''Using a single OP_CHECKSIGADD-based script''' A CHECKMULTISIG script m ... n CHECKMULTISIG with witness 0 ... can be rewritten as script CHECKSIG ... CHECKSIGADD m NUMEQUAL with witness ... . Every witness element w_i is either a signature corresponding to the public key with the same index or an empty vector. A similar CHECKMULTISIGVERIFY script can be translated to bip-tapscript by replacing NUMEQUAL with NUMEQUALVERIFY. This approach has very similar characteristics to the existing OP_CHECKMULTISIG-based scripts. -* '''Using a ''k''-of-''k'' script for every combination''' A ''k''-of-''n'' policy can be implemented by splitting the script into several leaves of the Merkle tree, each implementing a ''k''-of-''k'' policy using CHECKSIGVERIFY ... CHECKSIGVERIFY CHECKSIG. This may be preferable for privacy reasons over the previous approach, as it only exposes the participating public keys, but it is only more cost effective for small values of ''k'' (1-of-''n'' for any ''n'', 2-of-''n'' for ''n ≥ 6'', 3-of-''n'' for ''n ≥ 9'', ...). Furthermore, the signatures here depend on the branch used, which means signers need to be aware of which other signers will be participating, or produce signatures for each of the tree leaves. +* '''Using a single OP_CHECKSIGADD-based script''' A CHECKMULTISIG script m ... n CHECKMULTISIG with witness 0 ... can be rewritten as script CHECKSIG ... CHECKSIGADD m NUMEQUAL with witness ... . Every witness element w_i is either a signature corresponding to pubkey_i or an empty vector. A similar CHECKMULTISIGVERIFY script can be translated to bip-tapscript by replacing NUMEQUAL with NUMEQUALVERIFY. This approach has very similar characteristics to the existing OP_CHECKMULTISIG-based scripts. +* '''Using a ''k''-of-''k'' script for every combination''' A ''k''-of-''n'' policy can be implemented by splitting the script into several leaves of the Merkle tree, each implementing a ''k''-of-''k'' policy using CHECKSIGVERIFY ... CHECKSIGVERIFY CHECKSIG. This may be preferable for privacy reasons over the previous approach, as it only exposes the participating public keys, but it is only more cost effective for small values of ''k'' (1-of-''n'' for any ''n'', 2-of-''n'' for ''n ≥ 6'', 3-of-''n'' for ''n ≥ 9'', ...). Furthermore, the signatures here commit to the branch used, which means signers need to be aware of which other signers will be participating, or produce signatures for each of the tree leaves. * '''Using an aggregated public key for every combination''' Instead of building a tree where every leaf consists of ''k'' public keys, it is possible instead build a tree where every leaf contains a single ''aggregate'' of those ''k'' keys using [https://eprint.iacr.org/2018/068 MuSig]. This approach is far more efficient, but does require a 3-round interactive signing protocol to jointly produce the (single) signature. * '''Native Schnorr threshold signatures''' Multisig policies can also be realized with [http://cacr.uwaterloo.ca/techreports/2001/corr2001-13.ps threshold signatures] using verifiable secret sharing. This results in outputs and inputs that are indistinguishable from single-key payments, but at the cost of needing an interactive protocol (and associated backup procedures) before determining the address to send to. -- cgit v1.2.3 From 2973e09a88930ec3b4fe69e58b133476e1a50150 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 22 Oct 2019 11:46:31 -0700 Subject: Explain why CMS is not turned into SUCCESSx --- bip-tapscript.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index a325573..1ace177 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -67,7 +67,7 @@ Validation of such inputs must be equivalent to performing the following steps i ===Script execution=== The execution rules for tapscript are based on those for P2WSH according to BIP141, including the OP_CHECKLOCKTIMEVERIFY and OP_CHECKSEQUENCEVERIFY opcodes defined in BIP65 and BIP112, but with the following modifications: -* '''Disabled script opcodes''' The following script opcodes are disabled in tapscript: OP_CHECKMULTISIG and OP_CHECKMULTISIGVERIFY. The disabled opcodes behave in the same way as OP_RETURN, by failing and terminating the script immediately when executed, and being ignored when found in unexecuted branch. +* '''Disabled script opcodes''' The following script opcodes are disabled in tapscript: OP_CHECKMULTISIG and OP_CHECKMULTISIGVERIFY'''Why are OP_CHECKMULTISIG and OP_CHECKMULTISIGVERIFY disabled, and not turned into OP_SUCCESSx?''' This is a precaution to make sure people who accidentally keep using OP_CHECKMULTISIG in Tapscript notice a problem immediately. It also avoids the complication of script disassemblers needing to become context-dependent.. The disabled opcodes behave in the same way as OP_RETURN, by failing and terminating the script immediately when executed, and being ignored when found in unexecuted branch. * '''Consensus-enforced MINIMALIF''' The MINIMALIF rules, which are only a standardness rule in P2WSH, are consensus enforced in tapscript. This means that the input argument to the OP_IF and OP_NOTIF opcodes must be either exactly 0 (the empty vector) or exactly 1 (the one-byte vector with value 1)'''Why make MINIMALIF consensus?''' This makes it considerably easier to write non-malleable scripts that take branch information from the stack.. * '''OP_SUCCESSx opcodes''' As listed above, some opcodes are renamed to OP_SUCCESSx, and make the script unconditionally valid. * '''Signature opcodes'''. The OP_CHECKSIG and OP_CHECKSIGVERIFY are modified to operate on Schnorr public keys and signatures (see bip-schnorr) instead of ECDSA, and a new opcode OP_CHECKSIGADD is added. -- cgit v1.2.3 From 6d6b9c694047b9c4ef3b4b795658d610df358f4e Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Thu, 24 Oct 2019 11:12:59 -0700 Subject: Consistently mention resource limits in bip-tapscript --- bip-tapscript.mediawiki | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index 34d7e48..cac892e 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -52,13 +52,13 @@ The rules below only apply when validating a transaction input for which all of Validation of such inputs must be equivalent to performing the following steps in the specified order. # If the input is invalid due to BIP16, BIP141, or bip-taproot, fail. # The script as defined in bip-taproot (i.e., the penultimate witness stack element after removing the optional annex) is called the '''tapscript''' and is decoded into opcodes, one by one: -## If any opcode numbered ''80, 98, 126-129, 131-134, 137-138, 141-142, 149-153, 187-254'' is encountered, validation succeeds (none of the rules below apply). This is true even if later bytes in the tapscript would fail to decode otherwise. These opcodes are renamed to OP_SUCCESS80, ..., OP_SUCCESS254, and collectively known as OP_SUCCESSx'''OP_SUCCESSx''' OP_SUCCESSx is a mechanism to upgrade the Script system. Using an OP_SUCCESSx before its meaning is defined by a softfork is insecure and leads to fund loss. The inclusion of OP_SUCCESSx in a script will pass it unconditionally. It precedes any script execution rules to avoid the difficulties in specifying various edge cases, for example: OP_SUCCESSx being the 202nd opcode, OP_SUCCESSx after too many signature opcodes, or even scripts with conditionals lacking OP_ENDIF. The mere existence of an OP_SUCCESSx anywhere in the script will guarantee a pass for all such cases. OP_SUCCESSx are similar to the OP_RETURN in very early bitcoin versions (v0.1 up to and including v0.3.5). The original OP_RETURN terminates script execution immediately, and return pass or fail based on the top stack element at the moment of termination. This was one of a major design flaws in the original bitcoin protocol as it permitted unconditional third party theft by placing an OP_RETURN in scriptSig. This is not a concern in the present proposal since it is not possible for a third party to inject an OP_SUCCESSx to the validation process, as the OP_SUCCESSx is part of the script (and thus committed to be the taproot output), implying the consent of the coin owner. OP_SUCCESSx can be used for a variety of upgrade possibilities: +## If any opcode numbered ''80, 98, 126-129, 131-134, 137-138, 141-142, 149-153, 187-254'' is encountered, validation succeeds (none of the rules below apply). This is true even if later bytes in the tapscript would fail to decode otherwise. These opcodes are renamed to OP_SUCCESS80, ..., OP_SUCCESS254, and collectively known as OP_SUCCESSx'''OP_SUCCESSx''' OP_SUCCESSx is a mechanism to upgrade the Script system. Using an OP_SUCCESSx before its meaning is defined by a softfork is insecure and leads to fund loss. The inclusion of OP_SUCCESSx in a script will pass it unconditionally. It precedes any script execution rules to avoid the difficulties in specifying various edge cases, for example: OP_SUCCESSx in a script with an input stack larger than 1000 elements, OP_SUCCESSx after too many signature opcodes, or even scripts with conditionals lacking OP_ENDIF. The mere existence of an OP_SUCCESSx anywhere in the script will guarantee a pass for all such cases. OP_SUCCESSx are similar to the OP_RETURN in very early bitcoin versions (v0.1 up to and including v0.3.5). The original OP_RETURN terminates script execution immediately, and return pass or fail based on the top stack element at the moment of termination. This was one of a major design flaws in the original bitcoin protocol as it permitted unconditional third party theft by placing an OP_RETURN in scriptSig. This is not a concern in the present proposal since it is not possible for a third party to inject an OP_SUCCESSx to the validation process, as the OP_SUCCESSx is part of the script (and thus committed to be the taproot output), implying the consent of the coin owner. OP_SUCCESSx can be used for a variety of upgrade possibilities: * An OP_SUCCESSx could be turned into a functional opcode through a softfork. Unlike OP_NOPx-derived opcodes which only have read-only access to the stack, OP_SUCCESSx may also write to the stack. Any rule changes to an OP_SUCCESSx-containing script may only turn a valid script into an invalid one, and this is always achievable with softforks. * Since OP_SUCCESSx precedes size check of initial stack and push opcodes, an OP_SUCCESSx-derived opcode requiring stack elements bigger than 520 bytes may uplift the limit in a softfork. * OP_SUCCESSx may also redefine the behavior of existing opcodes so they could work together with the new opcode. For example, if an OP_SUCCESSx-derived opcode works with 64-bit integers, it may also allow the existing arithmetic opcodes in the ''same script'' to do the same. * Given that OP_SUCCESSx even causes potentially unparseable scripts to pass, it can be used to introduce multi-byte opcodes, or even a completely new scripting language when prefixed with a specific OP_SUCCESSx opcode.. ## If any push opcode fails to decode because it would extend past the end of the tapscript, fail. -# If the size of any element in the '''initial stack''' as defined in bip-taproot (i.e., the witness stack after removing both the optional annex and the two last stack elements after that) is bigger than 520 bytes, fail. +# If the '''initial stack''' as defined in bip-taproot (i.e., the witness stack after removing both the optional annex and the two last stack elements after that) violates any resource limits (stack size, and size of the elements in the stack; see "Resource Limits" below), fail. Note that this check can be bypassed using OP_SUCCESSx. # The tapscript is executed according to the rules in the following section, with the initial stack as input. ## If execution fails for any reason, fail. ## If the execution results in anything but exactly one element on the stack which evaluates to true with CastToBool(), fail. -- cgit v1.2.3 From f95ac706065c9ad79dce8b8310d8d6bc2aa1ec5c Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Thu, 24 Oct 2019 14:48:24 -0700 Subject: Elaborate on default and alternative signing --- bip-schnorr.mediawiki | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 14f8610..44b2c84 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -129,7 +129,7 @@ Note that we use a very different public key format (32 bytes) than the ones use As an alternative to generating keys randomly, it is also possible and safe to repurpose existing key generation algorithms for ECDSA in a compatible way. The private keys constructed by such an algorithm can be used as ''sk'' directly. The public keys constructed by such an algorithm (assuming they use the 33-byte compressed encoding) need to be converted by dropping the first byte. Specifically, [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki BIP32] and schemes built on top of it remain usable. -==== Signing ==== +==== Default Signing ==== Input: * The secret key ''sk'': a 32-byte array @@ -147,10 +147,15 @@ The algorithm ''Sign(sk, m)'' is defined as: * Let ''e = int(hashBIPSchnorr(bytes(R) || bytes(P) || m)) mod n''. * Return the signature ''bytes(R) || bytes((k + ed) mod n)''. -'''Above deterministic derivation of ''R'' is designed specifically for this signing algorithm and may not be secure when used in other signature schemes.''' -For example, using the same derivation in the MuSig multi-signature scheme leaks the secret key (see the [https://eprint.iacr.org/2018/068 MuSig paper] for details). +==== Alternative Signing ==== -Note that this is not a ''unique signature'' scheme: while this algorithm will always produce the same signature for a given message and public key, ''k'' (and hence ''R'') may be generated in other ways (such as by a CSPRNG) producing a different, but still valid, signature. +It should be noted that various alternative signing algorithms can be used to produce equally valid signatures. The algorithm in the previous section will always produce the same signature for a given message and public key, but the ''k'' value (and hence ''R'') may be generated in other ways, producing a different, but still valid, signature (in other words, it is not a ''unique'' signature scheme). + +'''Synthetic nonces''' When actual randomness is available, it can be appended to the input to ''hashBIPSchnorrDerive''s, after ''d'' and ''m''. This may improve protection against [https://moderncrypto.org/mail-archive/curves/2017/000925.html fault injection attacks]. + +'''Nonce exfiltration protection''' It is possible to strengthen the nonce generation algorithm using a second device. In this case, the second device contributes randomness which the actual signer provably incorporates into its nonce. This prevents certain attacks where the signer device is compromised and intentionally tries to leak the private key through its nonce selection. + +'''Multisignatures''' This signature scheme is compatible with various types of multisignature and threshold schemes, where a single public key requires holders of multiple private keys to participate in signing. One example is [https://eprint.iacr.org/2018/068 MuSig], which provides a way to aggregate multiple public keys into a single one, which all of the corresponding private keys need to sign for. It is important to note that multisignature signing schemes in general ''cannot'' be used with the nonce generation from the default signing algorithm above (or any deterministic nonce algorithm). ==== Verification ==== -- cgit v1.2.3 From 322ce53625fdb2be34e6b4ccfa3226cc96887e33 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 25 Oct 2019 10:18:17 -0700 Subject: Update bip-schnorr.mediawiki Co-Authored-By: Tim Ruffing --- bip-schnorr.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 44b2c84..f8d0f47 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -151,7 +151,7 @@ The algorithm ''Sign(sk, m)'' is defined as: It should be noted that various alternative signing algorithms can be used to produce equally valid signatures. The algorithm in the previous section will always produce the same signature for a given message and public key, but the ''k'' value (and hence ''R'') may be generated in other ways, producing a different, but still valid, signature (in other words, it is not a ''unique'' signature scheme). -'''Synthetic nonces''' When actual randomness is available, it can be appended to the input to ''hashBIPSchnorrDerive''s, after ''d'' and ''m''. This may improve protection against [https://moderncrypto.org/mail-archive/curves/2017/000925.html fault injection attacks]. +'''Synthetic nonces''' When a random number generator (RNG) is available, 32 bytes of RNG output can be appended to the input to ''hashBIPSchnorrDerive''. This will changes the corresponding line in the signing algorithm to ''k' = int(hashBIPSchnorrDerive(bytes(d) || m || get_32_bytes_from_rng())) mod n'', where ''get_32_bytes_from_rng()'' is the call the RNG. Adding RNG output may improve protection against [https://moderncrypto.org/mail-archive/curves/2017/000925.html fault injection attacks and side-channel attacks]. It is safe to add randomness from a low-quality randomness source, i.e., an RNG with low entropy. '''Nonce exfiltration protection''' It is possible to strengthen the nonce generation algorithm using a second device. In this case, the second device contributes randomness which the actual signer provably incorporates into its nonce. This prevents certain attacks where the signer device is compromised and intentionally tries to leak the private key through its nonce selection. -- cgit v1.2.3 From da4721cdc62ba35230643723a0f01ca1f9fc397c Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 25 Oct 2019 10:18:29 -0700 Subject: Update bip-schnorr.mediawiki Co-Authored-By: Tim Ruffing --- bip-schnorr.mediawiki | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index f8d0f47..6830ec7 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -155,7 +155,8 @@ It should be noted that various alternative signing algorithms can be used to pr '''Nonce exfiltration protection''' It is possible to strengthen the nonce generation algorithm using a second device. In this case, the second device contributes randomness which the actual signer provably incorporates into its nonce. This prevents certain attacks where the signer device is compromised and intentionally tries to leak the private key through its nonce selection. -'''Multisignatures''' This signature scheme is compatible with various types of multisignature and threshold schemes, where a single public key requires holders of multiple private keys to participate in signing. One example is [https://eprint.iacr.org/2018/068 MuSig], which provides a way to aggregate multiple public keys into a single one, which all of the corresponding private keys need to sign for. It is important to note that multisignature signing schemes in general ''cannot'' be used with the nonce generation from the default signing algorithm above (or any deterministic nonce algorithm). +'''Multisignatures''' This signature scheme is compatible with various types of multisignature and threshold schemes such as [https://eprint.iacr.org/2018/068 MuSig], where a single public key requires holders of multiple private keys to participate in signing (see Applications below). +'''It is important to note that multisignature signing schemes in general are insecure with the nonce generation from the default signing algorithm above (or any deterministic nonce algorithm).''' ==== Verification ==== -- cgit v1.2.3 From 73b8e3aeeb62dfc046193e564b6edcbbfdcc2400 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Wed, 30 Oct 2019 01:27:26 +0100 Subject: typos --- bip-schnorr.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 6830ec7..3d85754 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -151,7 +151,7 @@ The algorithm ''Sign(sk, m)'' is defined as: It should be noted that various alternative signing algorithms can be used to produce equally valid signatures. The algorithm in the previous section will always produce the same signature for a given message and public key, but the ''k'' value (and hence ''R'') may be generated in other ways, producing a different, but still valid, signature (in other words, it is not a ''unique'' signature scheme). -'''Synthetic nonces''' When a random number generator (RNG) is available, 32 bytes of RNG output can be appended to the input to ''hashBIPSchnorrDerive''. This will changes the corresponding line in the signing algorithm to ''k' = int(hashBIPSchnorrDerive(bytes(d) || m || get_32_bytes_from_rng())) mod n'', where ''get_32_bytes_from_rng()'' is the call the RNG. Adding RNG output may improve protection against [https://moderncrypto.org/mail-archive/curves/2017/000925.html fault injection attacks and side-channel attacks]. It is safe to add randomness from a low-quality randomness source, i.e., an RNG with low entropy. +'''Synthetic nonces''' When a random number generator (RNG) is available, 32 bytes of RNG output can be appended to the input to ''hashBIPSchnorrDerive''. This will change the corresponding line in the signing algorithm to ''k' = int(hashBIPSchnorrDerive(bytes(d) || m || get_32_bytes_from_rng())) mod n'', where ''get_32_bytes_from_rng()'' is the call to the RNG. Adding RNG output may improve protection against [https://moderncrypto.org/mail-archive/curves/2017/000925.html fault injection attacks and side-channel attacks]. It is safe to add randomness from a low-quality randomness source, i.e., an RNG with low entropy. '''Nonce exfiltration protection''' It is possible to strengthen the nonce generation algorithm using a second device. In this case, the second device contributes randomness which the actual signer provably incorporates into its nonce. This prevents certain attacks where the signer device is compromised and intentionally tries to leak the private key through its nonce selection. -- cgit v1.2.3 From db1973ffba60d3a007f9c6fbc2ff2e2f53d8bf5e Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Wed, 23 Oct 2019 17:26:45 +0200 Subject: improve rationale for key prefixing --- bip-schnorr.mediawiki | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 14f8610..624872b 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -56,7 +56,11 @@ encodings and operations. We choose the ''R''-option to support batch verification. -'''Key prefixing''' When using the verification rule above directly, it is possible for a third party to convert a signature ''(R, s)'' for key ''P'' into a signature ''(R, s + a⋅hash(R || m))'' for key ''P + a⋅G'' and the same message, for any integer ''a''. To combat this, we choose ''key prefixed''A limitation of committing to the public key (rather than to a short hash of it, or not at all) is that it removes the ability for public key recovery or verifying signatures against a short public key hash. These constructions are generally incompatible with batch verification. Schnorr signatures; changing the equation to ''s⋅G = R + hash(R || P || m)⋅P''. Key prefixing also seems to be a requirement for the security proof of the MuSig multisignature scheme (see Applications below). It is not strictly necessary to do this explicitly for Bitcoin currently, as all signature hashes indirectly commit to the public keys already. However, this may change with proposals such as SIGHASH_NOINPUT ([https://github.com/bitcoin/bips/blob/master/bip-0118.mediawiki BIP 118]), or when the signature scheme is used for other purposes—especially in combination with schemes like [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki BIP32]'s unhardened derivation. +'''Key prefixing''' Using the verification rule above directly makes Schnorr signatures vulnerable to "related-key attacks" in which a third party can convert a signature ''(R, s)'' for public key ''P'' into a signature ''(R, s + a⋅hash(R || m))'' for public key ''P + a⋅G'' and the same message ''m'', for any given additive tweak ''a'' to the signing key. This would render signatures insecure when keys are generated using [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#public-parent-key--public-child-key BIP32's unhardened derivation] and other methods that rely on additive tweaks to existing keys such as Taproot. + +To protect against these attacks, we choose ''key prefixed''A limitation of committing to the public key (rather than to a short hash of it, or not at all) is that it removes the ability for public key recovery or verifying signatures against a short public key hash. These constructions are generally incompatible with batch verification. Schnorr signatures; changing the equation to ''s⋅G = R + hash(R || P || m)⋅P''. [https://eprint.iacr.org/2015/1135.pdf It can be shown] that key prefixing protects against related-key attacks with additive tweaks. In general, key prefixing increases robustness in multi-user settings, e.g., it seems to be a requirement for proving the MuSig multisignature scheme secure (see Applications below). + +We note that key prefixing is not strictly necessary for transaction signatures as used in Bitcoin currently, because signed transactions indirectly commit to the public keys already, i.e., ''m'' contains a commitment to ''pk''. However, this indirect commitment should not relied upon because it may change with proposals such as SIGHASH_NOINPUT ([https://github.com/bitcoin/bips/blob/master/bip-0118.mediawiki BIP118]), and would render the signature scheme unsuitable for other purposes than signing transactions, e.g., [https://bitcoin.org/en/developer-reference#signmessage signing ordinary messages]. '''Encoding R and public key point P''' There exist several possibilities for encoding elliptic curve points: # Encoding the full X and Y coordinates of ''P'' and ''R'', resulting in a 64-byte public key and a 96-byte signature. -- cgit v1.2.3 From 12d8d5baa88f63aaf10c8b4a938aa9e0abf11b21 Mon Sep 17 00:00:00 2001 From: Dmitry Petukhov Date: Mon, 4 Nov 2019 19:15:12 +0500 Subject: use bytes() instead of b'' - avoid markdown issue Currently github markdown renders `b''` inside `` tags incorrectly. This makes `h = b''` show as `h = b` and creates some confusion. The issue can be avoided by using bytes() to create empty byte array --- bip-taproot.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 1b8ed0c..460ce12 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -224,7 +224,7 @@ def taproot_output_script(internal_pubkey, script_tree): - a list of two elements, each with the same structure as script_tree itself""" - None if script_tree is None: - h = b'' + h = bytes() else: _, h = taproot_tree_helper(script_tree) output_pubkey, _ = taproot_tweak_pubkey(internal_pubkey, h) -- cgit v1.2.3 From db8d6d426f8fcb0ea5094e20fe6cdc88976a9870 Mon Sep 17 00:00:00 2001 From: Dmitry Petukhov Date: Mon, 4 Nov 2019 17:46:00 +0500 Subject: fix docstring in taproot_output_script the final "-None" line in the docstring of `taproot_output_script` example function was actually outside of the docstring --- bip-taproot.mediawiki | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 460ce12..fd25b77 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -221,8 +221,9 @@ def taproot_output_script(internal_pubkey, script_tree): """Given a internal public key and a tree of scripts, compute the output script. script_tree is either: - a (leaf_version, script) tuple (leaf_version is 0xc0 for bip-tapscript scripts) - - a list of two elements, each with the same structure as script_tree itself""" + - a list of two elements, each with the same structure as script_tree itself - None + """ if script_tree is None: h = bytes() else: -- cgit v1.2.3 From 0c6a9cffad08ac118137b56ba6ee1cac73e97eac Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 4 Nov 2019 11:56:48 -0800 Subject: Settle on notation: is_square(y), has_square_y(P) --- bip-schnorr.mediawiki | 14 +++++++------- bip-schnorr/reference.py | 17 ++++++++++------- bip-schnorr/test-vectors.py | 19 +++++++++---------- bip-taproot.mediawiki | 14 +++++++------- 4 files changed, 33 insertions(+), 31 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 3d85754..61414f5 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -106,8 +106,8 @@ The following conventions are used, with constants as defined for [https://www.s ** The function ''bytes(P)'', where ''P'' is a point, returns ''bytes(x(P))'. ** The function ''int(x)'', where ''x'' is a 32-byte array, returns the 256-bit unsigned integer whose most significant byte first encoding is ''x''. ** The function ''is_square(x)'', where ''x'' is an integer, returns whether or not ''x'' is a quadratic residue modulo ''p''. Since ''p'' is prime, it is equivalent to the Legendre symbol ''(x / p) = x(p-1)/2 mod p'' being equal to ''1'' (see [https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion])For points ''P'' on the secp256k1 curve it holds that ''x(p-1)/2 ≠ 0 mod p''.. -** The function ''is_positive(P)'', where ''P'' is a point, is defined as ''not is_infinite(P) and is_square(y(P))''For points ''P'' on the secp256k1 curve it holds that ''is_positive(P) = not is_positive(-P)''.. -** The function ''lift_x(x)'', where ''x'' is an integer in range ''0..p-1'', returns the point ''P'' for which ''x(P) = x'' and ''is_positive(P)'', or fails if no such point existsGiven an candidate X coordinate ''x'' in the range ''0..p-1'', there exist either exactly two or exactly zero valid Y coordinates. If no valid Y coordinate exists, then ''x'' is not a valid X coordinate either, i.e., no point ''P'' exists for which ''x(P) = x''. Given a candidate ''x'', the valid Y coordinates are the square roots of ''c = x3 + 7 mod p'' and they can be computed as ''y = ±c(p+1)/4 mod p'' (see [https://en.wikipedia.org/wiki/Quadratic_residue#Prime_or_prime_power_modulus Quadratic residue]) if they exist, which can be checked by squaring and comparing with ''c''. Due to [https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion] it then holds that ''c(p-1)/2 = 1 mod p''. The same criterion applied to ''y'' results in ''y(p-1)/2 mod p = ±c((p+1)/4)((p-1)/2) mod p = ±1 mod p''. Therefore ''y = +c(p+1)/4 mod p'' is a quadratic residue and ''-y mod p'' is not.. The function ''lift_x(x)'' is equivalent to the following pseudocode: +** The function ''has_square_y(P)'', where ''P'' is a point, is defined as ''not is_infinite(P) and is_square(y(P))''For points ''P'' on the secp256k1 curve it holds that ''has_square_y(P) = not has_square_y(-P)''.. +** The function ''lift_x(x)'', where ''x'' is an integer in range ''0..p-1'', returns the point ''P'' for which ''x(P) = x'' and ''has_square_y(P)'', or fails if no such point existsGiven an candidate X coordinate ''x'' in the range ''0..p-1'', there exist either exactly two or exactly zero valid Y coordinates. If no valid Y coordinate exists, then ''x'' is not a valid X coordinate either, i.e., no point ''P'' exists for which ''x(P) = x''. Given a candidate ''x'', the valid Y coordinates are the square roots of ''c = x3 + 7 mod p'' and they can be computed as ''y = ±c(p+1)/4 mod p'' (see [https://en.wikipedia.org/wiki/Quadratic_residue#Prime_or_prime_power_modulus Quadratic residue]) if they exist, which can be checked by squaring and comparing with ''c''. Due to [https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion] it then holds that ''c(p-1)/2 = 1 mod p''. The same criterion applied to ''y'' results in ''y(p-1)/2 mod p = ±c((p+1)/4)((p-1)/2) mod p = ±1 mod p''. Therefore ''y = +c(p+1)/4 mod p'' is a quadratic residue and ''-y mod p'' is not.. The function ''lift_x(x)'' is equivalent to the following pseudocode: *** Let ''c = x3 + 7 mod p''. *** Let ''y = c(p+1)/4 mod p''. *** Fail if ''c ≠ y2 mod p''. @@ -139,11 +139,11 @@ The algorithm ''Sign(sk, m)'' is defined as: * Let ''d' = int(sk)'' * Fail if ''d' = 0'' or ''d' ≥ n'' * Let ''P = d'⋅G'' -* Let ''d = d' '' if ''is_positive(P)'', otherwise let ''d = n - d' ''. +* Let ''d = d' '' if ''has_square_y(P)'', otherwise let ''d = n - d' ''. * Let ''k' = int(hashBIPSchnorrDerive(bytes(d) || m)) mod n''Note that in general, taking the output of a hash function modulo the curve order will produce an unacceptably biased result. However, for the secp256k1 curve, the order is sufficiently close to ''2256'' that this bias is not observable (''1 - n / 2256'' is around ''1.27 * 2-128'').. * Fail if ''k' = 0''. * Let ''R = k'G''. -* Let ''k = k' '' if ''is_positive(R)'', otherwise let ''k = n - k' ''. +* Let ''k = k' '' if ''has_square_y(R)'', otherwise let ''k = n - k' ''. * Let ''e = int(hashBIPSchnorr(bytes(R) || bytes(P) || m)) mod n''. * Return the signature ''bytes(R) || bytes((k + ed) mod n)''. @@ -171,12 +171,12 @@ The algorithm ''Verify(pk, m, sig)'' is defined as: * Let ''s = int(sig[32:64])''; fail if ''s ≥ n''. * Let ''e = int(hashBIPSchnorr(bytes(r) || bytes(P) || m)) mod n''. * Let ''R = s⋅G - e⋅P''. -* Fail if ''not is_positive(R)'' or ''x(R) ≠ r''. +* Fail if ''not has_square_y(R)'' or ''x(R) ≠ r''. * Return success iff no failure occurred before reaching this point. For every valid secret key ''sk'' and message ''m'', ''Verify(PubKey(sk),m,Sign(sk,m))'' will succeed. -Note that the correctness of verification relies on the fact that ''point(pk)'' always returns a positive point (i.e., with a square Y coordinate). A hypothetical verification algorithm that treats points as public keys, and takes the point ''P'' directly as input would fail any time a negative point is used. While it is possible to correct for this by negating negative points before further processing, this would result in a scheme where every (message, signature) pair is valid for two public keys (a type of malleability that exists for ECDSA as well, but we don't wish to retain). We avoid these problems by treating just the X coordinate as public key. +Note that the correctness of verification relies on the fact that ''point(pk)'' always returns a point with a square Y coordinate. A hypothetical verification algorithm that treats points as public keys, and takes the point ''P'' directly as input would fail any time a point with non-square Y is used. While it is possible to correct for this by negating points with non-square Y coordinate before further processing, this would result in a scheme where every (message, signature) pair is valid for two public keys (a type of malleability that exists for ECDSA as well, but we don't wish to retain). We avoid these problems by treating just the X coordinate as public key. ==== Batch Verification ==== @@ -206,7 +206,7 @@ Many techniques are known for optimizing elliptic curve implementations. Several '''Squareness testing''' The function ''is_square(x)'' is defined as above, but can be computed more efficiently using an [https://en.wikipedia.org/wiki/Jacobi_symbol#Calculating_the_Jacobi_symbol extended GCD algorithm]. '''Jacobian coordinates''' Elliptic Curve operations can be implemented more efficiently by using [https://en.wikibooks.org/wiki/Cryptography/Prime_Curve/Jacobian_Coordinates Jacobian coordinates]. Elliptic Curve operations implemented this way avoid many intermediate modular inverses (which are computationally expensive), and the scheme proposed in this document is in fact designed to not need any inversions at all for verification. When operating on a point ''P'' with Jacobian coordinates ''(x,y,z)'' which is not the point at infinity and for which ''x(P)'' is defined as ''x / z2'' and ''y(P)'' is defined as ''y / z3'': -* ''is_positive(P)'' can be implemented as ''is_square(yz mod p)''. +* ''has_square_y(P)'' can be implemented as ''is_square(yz mod p)''. * ''x(P) ≠ r'' can be implemented as ''(0 ≤ r < p) and (x ≠ z2r mod p)''. == Applications == diff --git a/bip-schnorr/reference.py b/bip-schnorr/reference.py index e5d9557..7de37c2 100644 --- a/bip-schnorr/reference.py +++ b/bip-schnorr/reference.py @@ -11,6 +11,9 @@ def tagged_hash(tag, msg): tag_hash = hashlib.sha256(tag.encode()).digest() return hashlib.sha256(tag_hash + tag_hash + msg).digest() +def is_infinity(P): + return P is None + def x(P): return P[0] @@ -59,11 +62,11 @@ def int_from_bytes(b): def hash_sha256(b): return hashlib.sha256(b).digest() -def jacobi(x): - return pow(x, (p - 1) // 2, p) +def is_square(x): + return pow(x, (p - 1) // 2, p) == 1 -def is_quad(x): - return jacobi(x) == 1 +def has_square_y(P): + return not is_infinity(P) and is_square(y(P)) def pubkey_gen(seckey): x = int_from_bytes(seckey) @@ -79,12 +82,12 @@ def schnorr_sign(msg, seckey0): if not (1 <= seckey0 <= n - 1): raise ValueError('The secret key must be an integer in the range 1..n-1.') P = point_mul(G, seckey0) - seckey = seckey0 if is_quad(y(P)) else n - seckey0 + seckey = seckey0 if has_square_y(P) else n - seckey0 k0 = int_from_bytes(tagged_hash("BIPSchnorrDerive", bytes_from_int(seckey) + msg)) % n if k0 == 0: raise RuntimeError('Failure. This happens only with negligible probability.') R = point_mul(G, k0) - k = n - k0 if not is_quad(y(R)) else k0 + k = n - k0 if not has_square_y(R) else k0 e = int_from_bytes(tagged_hash("BIPSchnorr", bytes_from_point(R) + bytes_from_point(P) + msg)) % n return bytes_from_point(R) + bytes_from_int((k + e * seckey) % n) @@ -104,7 +107,7 @@ def schnorr_verify(msg, pubkey, sig): return False e = int_from_bytes(tagged_hash("BIPSchnorr", sig[0:32] + pubkey + msg)) % n R = point_add(point_mul(G, s), point_mul(P, n - e)) - if R is None or not is_quad(y(R)) or x(R) != r: + if R is None or not has_square_y(R) or x(R) != r: return False return True diff --git a/bip-schnorr/test-vectors.py b/bip-schnorr/test-vectors.py index 52e3b05..768d9f1 100644 --- a/bip-schnorr/test-vectors.py +++ b/bip-schnorr/test-vectors.py @@ -30,10 +30,10 @@ def vector2(): msg = bytes_from_int(0x5E2D58D8B3BCDF1ABADEC7829054F90DDA9805AAB56C77333024B9D0A508B75C) sig = schnorr_sign(msg, seckey) - # This singature vector would not verify if the implementer checked the - # jacobi symbol of the X coordinate of R instead of the Y coordinate. + # This signature vector would not verify if the implementer checked the + # squareness of the X coordinate of R instead of the Y coordinate. R = point_from_bytes(sig[0:32]) - assert(jacobi(R[0]) != 1) + assert(not is_square(R[0])) return (bytes_from_int(seckey), pubkey_gen(seckey), msg, sig, "TRUE", None) @@ -43,15 +43,14 @@ def vector3(): sig = schnorr_sign(msg, seckey) return (bytes_from_int(seckey), pubkey_gen(seckey), msg, sig, "TRUE", "test fails if msg is reduced modulo p or n") -# Signs with a given nonce. Results in an invalid signature if y(kG) is not a -# quadratic residue. +# Signs with a given nonce. Results in an invalid signature if y(kG) is not a square def schnorr_sign_fixed_nonce(msg, seckey0, k): if len(msg) != 32: raise ValueError('The message must be a 32-byte array.') if not (1 <= seckey0 <= n - 1): raise ValueError('The secret key must be an integer in the range 1..n-1.') P = point_mul(G, seckey0) - seckey = seckey0 if (jacobi(P[1]) == 1) else n - seckey0 + seckey = seckey0 if has_square_y(P) else n - seckey0 R = point_mul(G, k) e = int_from_bytes(tagged_hash("BIPSchnorr", bytes_from_point(R) + bytes_from_point(P) + msg)) % n return bytes_from_point(R) + bytes_from_int((k + e * seckey) % n) @@ -84,9 +83,9 @@ def vector6(): k = 3 sig = schnorr_sign_fixed_nonce(msg, seckey, k) - # Y coordinate of R is not a quadratic residue + # Y coordinate of R is not a square R = point_mul(G, k) - assert(jacobi(R[1]) != 1) + assert(not has_square_y(R)) return (None, pubkey_gen(seckey), msg, sig, "FALSE", "incorrect R residuosity") @@ -121,7 +120,7 @@ def vector9(): sig = schnorr_sign_fixed_nonce(msg, seckey, k) bytes_from_point.__code__ = bytes_from_point_tmp - return (None, pubkey_gen(seckey), msg, sig, "FALSE", "sG - eP is infinite. Test fails in single verification if jacobi(y(inf)) is defined as 1 and x(inf) as 0") + return (None, pubkey_gen(seckey), msg, sig, "FALSE", "sG - eP is infinite. Test fails in single verification if has_square_y(inf) is defined as true and x(inf) as 0") def bytes_from_point_inf1(P): if P == None: @@ -140,7 +139,7 @@ def vector10(): sig = schnorr_sign_fixed_nonce(msg, seckey, k) bytes_from_point.__code__ = bytes_from_point_tmp - return (None, pubkey_gen(seckey), msg, sig, "FALSE", "sG - eP is infinite. Test fails in single verification if jacobi(y(inf)) is defined as 1 and x(inf) as 1") + return (None, pubkey_gen(seckey), msg, sig, "FALSE", "sG - eP is infinite. Test fails in single verification if has_square_y(inf) is defined as true and x(inf) as 1") # It's cryptographically impossible to create a test vector that fails if run # in an implementation which merely misses the check that sig[0:32] is an X diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 1b8ed0c..d6841e3 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -59,7 +59,7 @@ The following rules only apply when such an output is being spent. Any other out * Let ''q'' be the 32-byte array containing the witness program (the second push in the scriptPubKey) which represents a public key according to bip-schnorr. * Fail if the witness stack has 0 elements. -* If there are at least two witness elements, and the first byte of the last element is 0x50'''Why is the first byte of the annex 0x50?''' Like the 0xc0 constant, 0x50 is chosen as it could not be confused with a valid P2WPKH or P2WSH spending. As the control block's initial byte's lowest bit is used to indicate the public key's Y quadratic residuosity, each script version needs two subsequence byte values that are both not yet used in P2WPKH or P2WSH spending. To indicate the annex, only an "unpaired" available byte is necessary like 0x50. This choice maximizes the available options for future script versions., this last element is called ''annex'' ''a'''''What is the purpose of the annex?''' The annex is a reserved space for future extensions, such as indicating the validation costs of computationally expensive new opcodes in a way that is recognizable without knowing the outputs being spent. Until the meaning of this field is defined by another softfork, users SHOULD NOT include annex in transactions, or it may lead to PERMANENT FUND LOSS. and is removed from the witness stack. The annex (or the lack of thereof) is always covered by the transaction digest and contributes to transaction weight, but is otherwise ignored during taproot validation. +* If there are at least two witness elements, and the first byte of the last element is 0x50'''Why is the first byte of the annex 0x50?''' Like the 0xc0 constant, 0x50 is chosen as it could not be confused with a valid P2WPKH or P2WSH spending. As the control block's initial byte's lowest bit is used to indicate the public key's Y squareness, each script version needs two subsequence byte values that are both not yet used in P2WPKH or P2WSH spending. To indicate the annex, only an "unpaired" available byte is necessary like 0x50. This choice maximizes the available options for future script versions., this last element is called ''annex'' ''a'''''What is the purpose of the annex?''' The annex is a reserved space for future extensions, such as indicating the validation costs of computationally expensive new opcodes in a way that is recognizable without knowing the outputs being spent. Until the meaning of this field is defined by another softfork, users SHOULD NOT include annex in transactions, or it may lead to PERMANENT FUND LOSS. and is removed from the witness stack. The annex (or the lack of thereof) is always covered by the transaction digest and contributes to transaction weight, but is otherwise ignored during taproot validation. * If there is exactly one element left in the witness stack, key path spending is used: ** The single witness stack element is interpreted as the signature and must be valid (see the next section) for the public key ''q'' and taproot transaction digest (to be defined hereinafter) as message. Fail if it is not. Otherwise pass. * If there are at least two witness elements left, script path spending is used: @@ -67,7 +67,7 @@ The following rules only apply when such an output is being spent. Any other out ** The last stack element is called the control block ''c'', and must have length ''33 + 32m'', for a value of ''m'' that is an integer between 0 and 128'''Why is the Merkle path length limited to 128?''' The optimally space-efficient Merkle tree can be constructed based on the probabilities of the scripts in the leaves, using the Huffman algorithm. This algorithm will construct branches with lengths approximately equal to ''log2(1/probability)'', but to have branches longer than 128 you would need to have scripts with an execution chance below 1 in ''2128''. As that is our security bound, scripts that truly have such a low chance can probably be removed entirely., inclusive. Fail if it does not have such a length. ** Let ''p = c[1:33]'' and let ''P = point(p)'' where ''point'' is defined as in bip-schnorr. Fail if this point is not on the curve. ** Let ''l = c[0] & 0xfe'', the leaf version'''What is the purpose of the first byte of the control block?''' The first byte of the control block has three distinct functions: -* The low bit is used to denote whether the ''Q'' point's Y coordinate is a quadratic residue.'''Why is the quadratic residuosity of the output public key's Y coordinate required in a script path spend?''' The ''point'' function always constructs a point with Y coordinate having that property, but because ''Q'' is constructed by adding the taproot tweak to the internal public key ''P'', it cannot easily be guaranteed that ''Q'' in fact has such a Y coordinate. We can not ignore the Y coordinate because it would prevent batch verification. Trying out multiple internal keys until there's such a ''Q'' is possible but undesirable and unnecessary since this information about the Y coordinate only consumes an unused bit. +* The low bit is used to denote whether the ''has_square_y(Q)'' holds.'''Why is the squareness of the output public key's Y coordinate required in a script path spend?''' The ''point'' function always constructs a point with Y coordinate having that property, but because ''Q'' is constructed by adding the taproot tweak to the internal public key ''P'', it cannot easily be guaranteed that ''Q'' in fact has such a Y coordinate. We can not ignore the Y coordinate because it would prevent batch verification. Trying out multiple internal keys until there's such a ''Q'' is possible but undesirable and unnecessary since this information about the Y coordinate only consumes an unused bit. * By keeping the top two bits set to true, it can be guaranteed that scripts can be recognized without knowledge of the UTXO being spent, simplifying analysis. This is because such values cannot occur as first byte of the final stack element in either P2WPKH or P2WSH spends. * The remaining five bits are used for introducing new script versions that are not observable unless actually executed. . @@ -179,7 +179,7 @@ Alice will not be able to notice the script path, but Mallory can unilaterally s '''Computing the output script''' Once the spending conditions are split into an internal key internal_pubkey and a binary tree whose leaves are (leaf_version, script) tuples, the output script can be computed using the following Python3 algorithms with helper functions from the bip-schnorr reference code for integer conversion, point multiplication and tagged hashes. First, we define taproot_tweak_pubkey for 32-byte bip-schnorr public key arrays. -In addition to the tweaked public key byte array, the function returns a boolean for the quadratic residuosity of the tweaked points' Y coordinate modulo the secp256k1 field order. +In addition to the tweaked public key byte array, the function returns a boolean for the squareness of the tweaked points' Y coordinate modulo the secp256k1 field order. This will be required for spending the output with a script path. In order to allow spending with the key path, we define taproot_tweak_seckey to compute the secret key for a tweaked public key. For any byte string h it holds that taproot_tweak_pubkey(pubkey_gen(seckey), h)[0] == pubkey_gen(taproot_tweak_seckey(seckey, h)). @@ -190,11 +190,11 @@ def taproot_tweak_pubkey(pubkey, h): if t >= SECP256K1_ORDER: raise ValueError Q = point_mul(point(pubkey), t) - return bytes_from_int(x(Q)), is_quad(y(Q)) + return bytes_from_int(x(Q)), has_square_y(Q) def taproot_tweak_seckey(seckey0, h): P = point_mul(G, int_from_bytes(seckey0)) - seckey = SECP256K1_ORDER - seckey0 if not is_quad(y(R)) else seckey + seckey = SECP256K1_ORDER - seckey0 if not has_square_y(R) else seckey t = int_from_bytes(tagged_hash("TapTweak", bytes_from_int(x(P)) + h)) if t >= SECP256K1_ORDER: raise ValueError @@ -253,8 +253,8 @@ This function returns the witness stack necessary and a sighash fun def taproot_sign_script(internal_pubkey, script_tree, script_num, inputs): info, h = taproot_tree_helper(script_tree) (leaf_version, script), path = info[script_num] - _, is_y_quad = taproot_tweak_pubkey(internal_pubkey, t) - output_pubkey_tag = 0 if is_y_quad else 1 + _, is_y_square = taproot_tweak_pubkey(internal_pubkey, t) + output_pubkey_tag = 0 if is_y_square else 1 pubkey_data = bytes([output_pubkey_tag + leaf_version]) + internal_pubkey return inputs + [script, pubkey_data + path] -- cgit v1.2.3 From 854a33ab48771316932930978f47c9c2311ed5f1 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Fri, 1 Nov 2019 14:44:02 +0000 Subject: Fix test vector generation code after changing schnorrsig_sign api --- bip-schnorr/test-vectors.py | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/bip-schnorr/test-vectors.py b/bip-schnorr/test-vectors.py index 768d9f1..16b82f7 100644 --- a/bip-schnorr/test-vectors.py +++ b/bip-schnorr/test-vectors.py @@ -2,7 +2,7 @@ import sys from reference import * def vector0(): - seckey = 1 + seckey = bytes_from_int(1) msg = bytes_from_int(0) sig = schnorr_sign(msg, seckey) pubkey = pubkey_gen(seckey) @@ -11,10 +11,10 @@ def vector0(): pubkey_point = point_from_bytes(pubkey) assert(pubkey_point[1] & 1 == 0) - return (bytes_from_int(seckey), pubkey, msg, sig, "TRUE", None) + return (seckey, pubkey, msg, sig, "TRUE", None) def vector1(): - seckey = 0xB7E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEF + seckey = bytes_from_int(0xB7E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEF) msg = bytes_from_int(0x243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89) sig = schnorr_sign(msg, seckey) pubkey = pubkey_gen(seckey) @@ -23,10 +23,10 @@ def vector1(): pubkey_point = point_from_bytes(pubkey) assert(pubkey_point[1] & 1 == 1) - return (bytes_from_int(seckey), pubkey, msg, sig, "TRUE", None) + return (seckey, pubkey, msg, sig, "TRUE", None) def vector2(): - seckey = 0xC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B14E5C9 + seckey = bytes_from_int(0xC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B14E5C9) msg = bytes_from_int(0x5E2D58D8B3BCDF1ABADEC7829054F90DDA9805AAB56C77333024B9D0A508B75C) sig = schnorr_sign(msg, seckey) @@ -35,18 +35,19 @@ def vector2(): R = point_from_bytes(sig[0:32]) assert(not is_square(R[0])) - return (bytes_from_int(seckey), pubkey_gen(seckey), msg, sig, "TRUE", None) + return (seckey, pubkey_gen(seckey), msg, sig, "TRUE", None) def vector3(): - seckey = 0x0B432B2677937381AEF05BB02A66ECD012773062CF3FA2549E44F58ED2401710 + seckey = bytes_from_int(0x0B432B2677937381AEF05BB02A66ECD012773062CF3FA2549E44F58ED2401710) msg = bytes_from_int(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) sig = schnorr_sign(msg, seckey) - return (bytes_from_int(seckey), pubkey_gen(seckey), msg, sig, "TRUE", "test fails if msg is reduced modulo p or n") + return (seckey, pubkey_gen(seckey), msg, sig, "TRUE", "test fails if msg is reduced modulo p or n") # Signs with a given nonce. Results in an invalid signature if y(kG) is not a square def schnorr_sign_fixed_nonce(msg, seckey0, k): if len(msg) != 32: raise ValueError('The message must be a 32-byte array.') + seckey0 = int_from_bytes(seckey0) if not (1 <= seckey0 <= n - 1): raise ValueError('The secret key must be an integer in the range 1..n-1.') P = point_mul(G, seckey0) @@ -58,12 +59,12 @@ def schnorr_sign_fixed_nonce(msg, seckey0, k): # Creates a singature with a small x(R) by using k = 1/2 def vector4(): one_half = 0x7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0 - seckey = 0x763758E5CBEEDEE4F7D3FC86F531C36578933228998226672F13C4F0EBE855EB + seckey = bytes_from_int(0x763758E5CBEEDEE4F7D3FC86F531C36578933228998226672F13C4F0EBE855EB) msg = bytes_from_int(0x4DF3C3F68FCC83B27E9D42C90431A72499F17875C81A599B566C9889B9696703) sig = schnorr_sign_fixed_nonce(msg, seckey, one_half) return (None, pubkey_gen(seckey), msg, sig, "TRUE", None) -default_seckey = 0xB7E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEF +default_seckey = bytes_from_int(0xB7E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEF) default_msg = bytes_from_int(0x243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89) def vector5(): -- cgit v1.2.3 From 220df7da7868f36eecbca600c490ffb783bda07e Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Fri, 1 Nov 2019 14:50:26 +0000 Subject: Adjust test vector generation code to latest terminology --- bip-schnorr/test-vectors.csv | 6 +++--- bip-schnorr/test-vectors.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/bip-schnorr/test-vectors.csv b/bip-schnorr/test-vectors.csv index 7ca6600..9cd0d83 100644 --- a/bip-schnorr/test-vectors.csv +++ b/bip-schnorr/test-vectors.csv @@ -5,11 +5,11 @@ index,secret key,public key,message,signature,verification result,comment 3,0B432B2677937381AEF05BB02A66ECD012773062CF3FA2549E44F58ED2401710,25D1DFF95105F5253C4022F628A996AD3A0D95FBF21D468A1B33F8C160D8F517,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,8BD2C11604B0A87A443FCC2E5D90E5328F934161B18864FB48CE10CB59B45FB9B5B2A0F129BD88F5BDC05D5C21E5C57176B913002335784F9777A24BD317CD36,TRUE,test fails if msg is reduced modulo p or n 4,,D69C3509BB99E412E68B0FE8544E72837DFA30746D8BE2AA65975F29D22DC7B9,4DF3C3F68FCC83B27E9D42C90431A72499F17875C81A599B566C9889B9696703,00000000000000000000003B78CE563F89A0ED9414F5AA28AD0D96D6795F9C63EE374AC7FAE927D334CCB190F6FB8FD27A2DDC639CCEE46D43F113A4035A2C7F,TRUE, 5,,EEFDEA4CDB677750A420FEE807EACF21EB9898AE79B9768766E4FAA04A2D4A34,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,667C2F778E0616E611BD0C14B8A600C5884551701A949EF0EBFD72D452D64E844160BCFC3F466ECB8FACD19ADE57D8699D74E7207D78C6AEDC3799B52A8E0598,FALSE,public key not on the curve -6,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9935554D1AA5F0374E5CDAACB3925035C7C169B27C4426DF0A6B19AF3BAEAB138,FALSE,incorrect R residuosity +6,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9935554D1AA5F0374E5CDAACB3925035C7C169B27C4426DF0A6B19AF3BAEAB138,FALSE,has_square_y(R) is false 7,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,10AC49A6A2EBF604189C5F40FC75AF2D42D77DE9A2782709B1EB4EAF1CFE9108D7003B703A3499D5E29529D39BA040A44955127140F81A8A89A96F992AC0FE79,FALSE,negated message 8,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,667C2F778E0616E611BD0C14B8A600C5884551701A949EF0EBFD72D452D64E84BE9F4303C0B9913470532E6521A827951D39F5C631CFD98CE39AC4D7A5A83BA9,FALSE,negated s value -9,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,000000000000000000000000000000000000000000000000000000000000000099D2F0EBC2996808208633CD9926BF7EC3DAB73DAAD36E85B3040A698E6D1CE0,FALSE,sG - eP is infinite. Test fails in single verification if jacobi(y(inf)) is defined as 1 and x(inf) as 0 -10,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,000000000000000000000000000000000000000000000000000000000000000124E81D89F01304695CE943F7D5EBD00EF726A0864B4FF33895B4E86BEADC5456,FALSE,sG - eP is infinite. Test fails in single verification if jacobi(y(inf)) is defined as 1 and x(inf) as 1 +9,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,000000000000000000000000000000000000000000000000000000000000000099D2F0EBC2996808208633CD9926BF7EC3DAB73DAAD36E85B3040A698E6D1CE0,FALSE,sG - eP is infinite. Test fails in single verification if has_square_y(inf) is defined as true and x(inf) as 0 +10,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,000000000000000000000000000000000000000000000000000000000000000124E81D89F01304695CE943F7D5EBD00EF726A0864B4FF33895B4E86BEADC5456,FALSE,sG - eP is infinite. Test fails in single verification if has_square_y(inf) is defined as true and x(inf) as 1 11,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,4A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1D4160BCFC3F466ECB8FACD19ADE57D8699D74E7207D78C6AEDC3799B52A8E0598,FALSE,sig[0:32] is not an X coordinate on the curve 12,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F4160BCFC3F466ECB8FACD19ADE57D8699D74E7207D78C6AEDC3799B52A8E0598,FALSE,sig[0:32] is equal to field size 13,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,667C2F778E0616E611BD0C14B8A600C5884551701A949EF0EBFD72D452D64E84FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141,FALSE,sig[32:64] is equal to curve order diff --git a/bip-schnorr/test-vectors.py b/bip-schnorr/test-vectors.py index 16b82f7..dca700c 100644 --- a/bip-schnorr/test-vectors.py +++ b/bip-schnorr/test-vectors.py @@ -88,7 +88,7 @@ def vector6(): R = point_mul(G, k) assert(not has_square_y(R)) - return (None, pubkey_gen(seckey), msg, sig, "FALSE", "incorrect R residuosity") + return (None, pubkey_gen(seckey), msg, sig, "FALSE", "has_square_y(R) is false") def vector7(): seckey = default_seckey -- cgit v1.2.3 From c0f0c8d43ddcbcc79920d58b32bb5dea2a19ae7c Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Fri, 1 Nov 2019 16:14:57 +0000 Subject: Check infinity in is_positive --- bip-schnorr/reference.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/bip-schnorr/reference.py b/bip-schnorr/reference.py index 7de37c2..4ac93ee 100644 --- a/bip-schnorr/reference.py +++ b/bip-schnorr/reference.py @@ -3,6 +3,9 @@ import binascii p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F n = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 + +# Points are tuples X and Y coordinates and the point at infinity is +# represented by the None keyword. G = (0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798, 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8) # This implementation can be sped up by storing the midstate after hashing -- cgit v1.2.3 From 35f1fface55a4639ec300749be2b2fd27edae077 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Sat, 2 Nov 2019 12:17:17 +0000 Subject: Make more clear that signing function in test vectors generation code isn't intended to be used anywhere else --- bip-schnorr/test-vectors.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/bip-schnorr/test-vectors.py b/bip-schnorr/test-vectors.py index dca700c..da7aec6 100644 --- a/bip-schnorr/test-vectors.py +++ b/bip-schnorr/test-vectors.py @@ -43,8 +43,10 @@ def vector3(): sig = schnorr_sign(msg, seckey) return (seckey, pubkey_gen(seckey), msg, sig, "TRUE", "test fails if msg is reduced modulo p or n") -# Signs with a given nonce. Results in an invalid signature if y(kG) is not a square -def schnorr_sign_fixed_nonce(msg, seckey0, k): +# Signs with a given nonce. This can be INSECURE and is only INTENDED FOR +# GENERATING TEST VECTORS. Results in an invalid signature if y(kG) is not +# square. +def insecure_schnorr_sign_fixed_nonce(msg, seckey0, k): if len(msg) != 32: raise ValueError('The message must be a 32-byte array.') seckey0 = int_from_bytes(seckey0) @@ -61,7 +63,7 @@ def vector4(): one_half = 0x7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0 seckey = bytes_from_int(0x763758E5CBEEDEE4F7D3FC86F531C36578933228998226672F13C4F0EBE855EB) msg = bytes_from_int(0x4DF3C3F68FCC83B27E9D42C90431A72499F17875C81A599B566C9889B9696703) - sig = schnorr_sign_fixed_nonce(msg, seckey, one_half) + sig = insecure_schnorr_sign_fixed_nonce(msg, seckey, one_half) return (None, pubkey_gen(seckey), msg, sig, "TRUE", None) default_seckey = bytes_from_int(0xB7E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEF) @@ -82,7 +84,7 @@ def vector6(): seckey = default_seckey msg = default_msg k = 3 - sig = schnorr_sign_fixed_nonce(msg, seckey, k) + sig = insecure_schnorr_sign_fixed_nonce(msg, seckey, k) # Y coordinate of R is not a square R = point_mul(G, k) @@ -118,7 +120,7 @@ def vector9(): k = 0 bytes_from_point_tmp = bytes_from_point.__code__ bytes_from_point.__code__ = bytes_from_point_inf0.__code__ - sig = schnorr_sign_fixed_nonce(msg, seckey, k) + sig = insecure_schnorr_sign_fixed_nonce(msg, seckey, k) bytes_from_point.__code__ = bytes_from_point_tmp return (None, pubkey_gen(seckey), msg, sig, "FALSE", "sG - eP is infinite. Test fails in single verification if has_square_y(inf) is defined as true and x(inf) as 0") @@ -137,7 +139,7 @@ def vector10(): k = 0 bytes_from_point_tmp = bytes_from_point.__code__ bytes_from_point.__code__ = bytes_from_point_inf1.__code__ - sig = schnorr_sign_fixed_nonce(msg, seckey, k) + sig = insecure_schnorr_sign_fixed_nonce(msg, seckey, k) bytes_from_point.__code__ = bytes_from_point_tmp return (None, pubkey_gen(seckey), msg, sig, "FALSE", "sG - eP is infinite. Test fails in single verification if has_square_y(inf) is defined as true and x(inf) as 1") -- cgit v1.2.3 From 0ec01e9255cba2238d50e6115dfa5ba497381f84 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Sat, 2 Nov 2019 12:19:17 +0000 Subject: Fix typo in reference code comment --- bip-schnorr/reference.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-schnorr/reference.py b/bip-schnorr/reference.py index 4ac93ee..79be690 100644 --- a/bip-schnorr/reference.py +++ b/bip-schnorr/reference.py @@ -4,7 +4,7 @@ import binascii p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F n = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 -# Points are tuples X and Y coordinates and the point at infinity is +# Points are tuples of X and Y coordinates and the point at infinity is # represented by the None keyword. G = (0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798, 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8) -- cgit v1.2.3 From 8e7aef083e18d3f63a127be89083fdcd0b2adf2e Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Mon, 4 Nov 2019 12:53:37 +0000 Subject: Fix point_from_bytes accepting out-of-range pubkeys and add test vector --- bip-schnorr/reference.py | 2 ++ bip-schnorr/test-vectors.py | 26 +++++++++++++++++++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/bip-schnorr/reference.py b/bip-schnorr/reference.py index 79be690..f2a944f 100644 --- a/bip-schnorr/reference.py +++ b/bip-schnorr/reference.py @@ -53,6 +53,8 @@ def bytes_from_point(P): def point_from_bytes(b): x = int_from_bytes(b) + if x >= p: + return None y_sq = (pow(x, 3, p) + 7) % p y = pow(y_sq, (p + 1) // 4, p) if pow(y, 2, p) != y_sq: diff --git a/bip-schnorr/test-vectors.py b/bip-schnorr/test-vectors.py index da7aec6..195b61b 100644 --- a/bip-schnorr/test-vectors.py +++ b/bip-schnorr/test-vectors.py @@ -69,12 +69,14 @@ def vector4(): default_seckey = bytes_from_int(0xB7E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEF) default_msg = bytes_from_int(0x243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89) +# Public key is not on the curve def vector5(): + # This creates a dummy signature that doesn't have anything to do with the + # public key. seckey = default_seckey msg = default_msg sig = schnorr_sign(msg, seckey) - # Public key is not on the curve pubkey = bytes_from_int(0xEEFDEA4CDB677750A420FEE807EACF21EB9898AE79B9768766E4FAA04A2D4A34) assert(point_from_bytes(pubkey) is None) @@ -185,6 +187,27 @@ def vector13(): return (None, pubkey_gen(seckey), msg, sig, "FALSE", "sig[32:64] is equal to curve order") +# Test out of range pubkey +# It's cryptographically impossible to create a test vector that fails if run +# in an implementation which accepts out of range pubkeys because we can't find +# a secret key for such a public key and therefore can not create a signature. +# This test vector just increases test coverage. +def vector14(): + # This creates a dummy signature that doesn't have anything to do with the + # public key. + seckey = default_seckey + msg = default_msg + sig = schnorr_sign(msg, seckey) + + pubkey_int = p + 1 + pubkey = bytes_from_int(pubkey_int) + assert(point_from_bytes(pubkey) is None) + # If an implementation would reduce a given public key modulo p then the + # pubkey would be valid + assert(point_from_bytes(bytes_from_int(pubkey_int % p)) is not None) + + return (None, pubkey, msg, sig, "FALSE", "public key is not a valid X coordinate because it exceeds the field size") + vectors = [ vector0(), vector1(), @@ -200,6 +223,7 @@ vectors = [ vector11(), vector12(), vector13(), + vector14() ] # Converts the byte strings of a test vector into hex strings -- cgit v1.2.3 From 8a8a35bfc58e5d1a8bf78d0b3da486a8dcbd49f9 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Tue, 5 Nov 2019 10:14:23 +0000 Subject: Update test-vectors.csv --- bip-schnorr/test-vectors.csv | 1 + 1 file changed, 1 insertion(+) diff --git a/bip-schnorr/test-vectors.csv b/bip-schnorr/test-vectors.csv index 9cd0d83..3970803 100644 --- a/bip-schnorr/test-vectors.csv +++ b/bip-schnorr/test-vectors.csv @@ -13,3 +13,4 @@ index,secret key,public key,message,signature,verification result,comment 11,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,4A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1D4160BCFC3F466ECB8FACD19ADE57D8699D74E7207D78C6AEDC3799B52A8E0598,FALSE,sig[0:32] is not an X coordinate on the curve 12,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F4160BCFC3F466ECB8FACD19ADE57D8699D74E7207D78C6AEDC3799B52A8E0598,FALSE,sig[0:32] is equal to field size 13,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,667C2F778E0616E611BD0C14B8A600C5884551701A949EF0EBFD72D452D64E84FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141,FALSE,sig[32:64] is equal to curve order +14,,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC30,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,667C2F778E0616E611BD0C14B8A600C5884551701A949EF0EBFD72D452D64E844160BCFC3F466ECB8FACD19ADE57D8699D74E7207D78C6AEDC3799B52A8E0598,FALSE,public key is not a valid X coordinate because it exceeds the field size -- cgit v1.2.3 From 08622c94947f909aaf8eb21f70c5eb21a42564fc Mon Sep 17 00:00:00 2001 From: Fabian Jahr Date: Tue, 5 Nov 2019 14:53:16 +0100 Subject: Link design section of BIP Schnorr in Specification --- bip-taproot.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 0e27724..eb16fb1 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -50,7 +50,7 @@ Not included in this proposal are additional features like new sighash modes or This section specifies the Taproot consensus rules. Validity is defined by exclusion: a block or transaction is valid if no condition exists that marks it failed. -The notation below follows that of bip-schnorr. This includes the ''hashtag(x)'' notation to refer to ''SHA256(SHA256(tag) || SHA256(tag) || x)''. To the best of the authors' knowledge, no existing use of SHA256 in Bitcoin feeds it a message that starts with two single SHA256 outputs, making collisions between ''hashtag'' with other hashes extremely unlikely. +The notation below follows that of [https://github.com/sipa/bips/blob/bip-schnorr/bip-schnorr.mediawiki#design bip-schnorr]. This includes the ''hashtag(x)'' notation to refer to ''SHA256(SHA256(tag) || SHA256(tag) || x)''. To the best of the authors' knowledge, no existing use of SHA256 in Bitcoin feeds it a message that starts with two single SHA256 outputs, making collisions between ''hashtag'' with other hashes extremely unlikely. === Script validation rules === -- cgit v1.2.3 From 78eb015f634ccbac0c557091120de7fe64ee734b Mon Sep 17 00:00:00 2001 From: Max Hillebrand <30683012+MaxHillebrand@users.noreply.github.com> Date: Wed, 6 Nov 2019 05:58:11 +0100 Subject: fix: script spend, not key spend For the key spend the script tree depth is not revealed, it is only done for script spends. This sentence makes sense only for the script spend. --- bip-taproot.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 0e27724..d408357 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -268,7 +268,7 @@ A key path spend could be a "normal" payment from a single- or multi-signature w A script path spend leaks that there is a script path and that the key path was not applicable - for example because the involved parties failed to reach agreement. Moreover, the depth of a script in the Merkle root leaks information including the minimum depth of the tree, which suggests specific wallet software that created the output and helps clustering. -Therefore, the privacy of key spends can be improved by deviating from the optimal tree determined by the probability distribution over the leaves. +Therefore, the privacy of script spends can be improved by deviating from the optimal tree determined by the probability distribution over the leaves. Just like other existing output types, taproot outputs should never reuse keys. This does not only apply to the particular leaf that was used to spend an output but to all leaves committed to in the output. -- cgit v1.2.3 From de82b3ad26d4fa82fe973a2420ac45c5026ceab0 Mon Sep 17 00:00:00 2001 From: codeShark149 Date: Wed, 6 Nov 2019 23:48:29 +0530 Subject: Internal pubkey calculation fixed in taproot_tweak_pubkey() --- bip-taproot.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index d8f51ca..298df18 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -189,7 +189,7 @@ def taproot_tweak_pubkey(pubkey, h): t = int_from_bytes(tagged_hash("TapTweak", pubkey + h)) if t >= SECP256K1_ORDER: raise ValueError - Q = point_mul(point(pubkey), t) + Q = point_add(point(pubkey), point_mul(G, t)) return bytes_from_int(x(Q)), has_square_y(Q) def taproot_tweak_seckey(seckey0, h): -- cgit v1.2.3 From ad4156a39419883a485526908dc8f76965602a3d Mon Sep 17 00:00:00 2001 From: LaurentMT Date: Mon, 11 Nov 2019 01:20:28 +0100 Subject: Fxied typo in taproot_sign_script() --- bip-taproot.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 298df18..b20dd09 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -254,7 +254,7 @@ This function returns the witness stack necessary and a sighash fun def taproot_sign_script(internal_pubkey, script_tree, script_num, inputs): info, h = taproot_tree_helper(script_tree) (leaf_version, script), path = info[script_num] - _, is_y_square = taproot_tweak_pubkey(internal_pubkey, t) + _, is_y_square = taproot_tweak_pubkey(internal_pubkey, h) output_pubkey_tag = 0 if is_y_square else 1 pubkey_data = bytes([output_pubkey_tag + leaf_version]) + internal_pubkey return inputs + [script, pubkey_data + path] -- cgit v1.2.3 From 5ceb42b48b14ae941131834a71cbece7191dc39a Mon Sep 17 00:00:00 2001 From: Thomas Kerin Date: Mon, 11 Nov 2019 02:41:15 +0000 Subject: tapscript: fix minor typo --- bip-tapscript.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index 9044c71..ee20763 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -52,7 +52,7 @@ The rules below only apply when validating a transaction input for which all of Validation of such inputs must be equivalent to performing the following steps in the specified order. # If the input is invalid due to BIP16, BIP141, or bip-taproot, fail. # The script as defined in bip-taproot (i.e., the penultimate witness stack element after removing the optional annex) is called the '''tapscript''' and is decoded into opcodes, one by one: -## If any opcode numbered ''80, 98, 126-129, 131-134, 137-138, 141-142, 149-153, 187-254'' is encountered, validation succeeds (none of the rules below apply). This is true even if later bytes in the tapscript would fail to decode otherwise. These opcodes are renamed to OP_SUCCESS80, ..., OP_SUCCESS254, and collectively known as OP_SUCCESSx'''OP_SUCCESSx''' OP_SUCCESSx is a mechanism to upgrade the Script system. Using an OP_SUCCESSx before its meaning is defined by a softfork is insecure and leads to fund loss. The inclusion of OP_SUCCESSx in a script will pass it unconditionally. It precedes any script execution rules to avoid the difficulties in specifying various edge cases, for example: OP_SUCCESSx in a script with an input stack larger than 1000 elements, OP_SUCCESSx after too many signature opcodes, or even scripts with conditionals lacking OP_ENDIF. The mere existence of an OP_SUCCESSx anywhere in the script will guarantee a pass for all such cases. OP_SUCCESSx are similar to the OP_RETURN in very early bitcoin versions (v0.1 up to and including v0.3.5). The original OP_RETURN terminates script execution immediately, and return pass or fail based on the top stack element at the moment of termination. This was one of a major design flaws in the original bitcoin protocol as it permitted unconditional third party theft by placing an OP_RETURN in scriptSig. This is not a concern in the present proposal since it is not possible for a third party to inject an OP_SUCCESSx to the validation process, as the OP_SUCCESSx is part of the script (and thus committed to be the taproot output), implying the consent of the coin owner. OP_SUCCESSx can be used for a variety of upgrade possibilities: +## If any opcode numbered ''80, 98, 126-129, 131-134, 137-138, 141-142, 149-153, 187-254'' is encountered, validation succeeds (none of the rules below apply). This is true even if later bytes in the tapscript would fail to decode otherwise. These opcodes are renamed to OP_SUCCESS80, ..., OP_SUCCESS254, and collectively known as OP_SUCCESSx'''OP_SUCCESSx''' OP_SUCCESSx is a mechanism to upgrade the Script system. Using an OP_SUCCESSx before its meaning is defined by a softfork is insecure and leads to fund loss. The inclusion of OP_SUCCESSx in a script will pass it unconditionally. It precedes any script execution rules to avoid the difficulties in specifying various edge cases, for example: OP_SUCCESSx in a script with an input stack larger than 1000 elements, OP_SUCCESSx after too many signature opcodes, or even scripts with conditionals lacking OP_ENDIF. The mere existence of an OP_SUCCESSx anywhere in the script will guarantee a pass for all such cases. OP_SUCCESSx are similar to the OP_RETURN in very early bitcoin versions (v0.1 up to and including v0.3.5). The original OP_RETURN terminates script execution immediately, and return pass or fail based on the top stack element at the moment of termination. This was one of a major design flaws in the original bitcoin protocol as it permitted unconditional third party theft by placing an OP_RETURN in scriptSig. This is not a concern in the present proposal since it is not possible for a third party to inject an OP_SUCCESSx to the validation process, as the OP_SUCCESSx is part of the script (and thus committed to by the taproot output), implying the consent of the coin owner. OP_SUCCESSx can be used for a variety of upgrade possibilities: * An OP_SUCCESSx could be turned into a functional opcode through a softfork. Unlike OP_NOPx-derived opcodes which only have read-only access to the stack, OP_SUCCESSx may also write to the stack. Any rule changes to an OP_SUCCESSx-containing script may only turn a valid script into an invalid one, and this is always achievable with softforks. * Since OP_SUCCESSx precedes size check of initial stack and push opcodes, an OP_SUCCESSx-derived opcode requiring stack elements bigger than 520 bytes may uplift the limit in a softfork. * OP_SUCCESSx may also redefine the behavior of existing opcodes so they could work together with the new opcode. For example, if an OP_SUCCESSx-derived opcode works with 64-bit integers, it may also allow the existing arithmetic opcodes in the ''same script'' to do the same. -- cgit v1.2.3 From af1638ce187f09d49e35a2b6eb60bbec2effec36 Mon Sep 17 00:00:00 2001 From: Agis Anastasopoulos Date: Mon, 11 Nov 2019 12:39:53 +0200 Subject: Fix typo --- bip-taproot.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index b20dd09..7d646ea 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -302,7 +302,7 @@ Depending on the implementation non-upgraded wallets may be able to send to Segw == Acknowledgements == -This document is the result of discussions around script and signature improvements with many people, and had direct constributions from Jonas Nick, Anthony Towns, Greg Maxwell, and others. It further builds on top of earlier published proposals such as Taproot by Greg Maxwell, and Merkle branch constructions by Russell O'Connor, Johnson Lau, and Mark Friedenbach. +This document is the result of discussions around script and signature improvements with many people, and had direct contributions from Jonas Nick, Anthony Towns, Greg Maxwell, and others. It further builds on top of earlier published proposals such as Taproot by Greg Maxwell, and Merkle branch constructions by Russell O'Connor, Johnson Lau, and Mark Friedenbach. Thanks to Arik Sosman for suggesting to sort Merkle node children before hashes, removing the need to transfer the position in the tree. -- cgit v1.2.3 From 7e98e2fd84ef152d54b4ec7aa5d42d33c53956c4 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Mon, 11 Nov 2019 20:09:55 +0200 Subject: G refers to secp256k1 base point rather generator --- bip-schnorr.mediawiki | 4 ++-- bip-taproot.mediawiki | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 31a5904..cff066e 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -48,7 +48,7 @@ encodings and operations. === Design === -'''Schnorr signature variant''' Elliptic Curve Schnorr signatures for message ''m'' and public key ''P'' generally involve a point ''R'', integers ''e'' and ''s'' picked by the signer, and generator ''G'' which satisfy ''e = hash(R || m)'' and ''s⋅G = R + e⋅P''. Two formulations exist, depending on whether the signer reveals ''e'' or ''R'': +'''Schnorr signature variant''' Elliptic Curve Schnorr signatures for message ''m'' and public key ''P'' generally involve a point ''R'', integers ''e'' and ''s'' picked by the signer, and the base point ''G'' which satisfy ''e = hash(R || m)'' and ''s⋅G = R + e⋅P''. Two formulations exist, depending on whether the signer reveals ''e'' or ''R'': # Signatures are ''(e, s)'' that satisfy ''e = hash(s⋅G - e⋅P || m)''. This supports more compact signatures, since [http://www.neven.org/papers/schnorr.pdf the hash ''e'' can be made as small as 16 bytes without sacrificing security], whereas an encoding of ''R'' inherently needs about 32 bytes. Moreover, this variant avoids minor complexity introduced by the encoding of the point ''R'' in the signature (see paragraphs "Encoding the sign of R" and "Implicit Y coordinate" further below in this subsection). # Signatures are ''(R, s)'' that satisfy ''s⋅G = R + hash(R || m)⋅P''. This supports batch verification, as there are no elliptic curve operations inside the hashes. Batch verification enables significant speedups. @@ -100,7 +100,7 @@ The following conventions are used, with constants as defined for [https://www.s * Uppercase variables refer to points on the curve with equation ''y2 = x3 + 7'' over the integers modulo ''p''. ** ''is_infinite(P)'' returns whether or not ''P'' is the point at infinity. ** ''x(P)'' and ''y(P)'' are integers in the range ''0..p-1'' and refer to the X and Y coordinates of a point ''P'' (assuming it is not infinity). -** The constant ''G'' refers to the generator, for which ''x(G) = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798'' and ''y(G) = 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8''. +** The constant ''G'' refers to the base point, for which ''x(G) = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798'' and ''y(G) = 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8''. ** Addition of points refers to the usual [https://en.wikipedia.org/wiki/Elliptic_curve#The_group_law elliptic curve group operation]. ** [https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication Multiplication (⋅) of an integer and a point] refers to the repeated application of the group operation. * Functions and operations: diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 7d646ea..9e14845 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -161,7 +161,7 @@ Satisfying any of these conditions is sufficient to spend the output. '''Initial steps''' The first step is determining what the internal key and the organization of the rest of the scripts should be. The specifics are likely application dependent, but here are some general guidelines: * When deciding between scripts with conditionals (OP_IF etc.) and splitting them up into multiple scripts (each corresponding to one execution path through the original script), it is generally preferable to pick the latter. * When a single condition requires signatures with multiple keys, key aggregation techniques like MuSig can be used to combine them into a single key. The details are out of scope for this document, but note that this may complicate the signing procedure. -* If one or more of the spending conditions consist of just a single key (after aggregation), the most likely one should be made the internal key. If no such condition exists, it may be worthwhile adding one that consists of an aggregation of all keys participating in all scripts combined; effectively adding an "everyone agrees" branch. If that is inacceptable, pick as internal key a point with unknown discrete logarithm. One example of such a point is ''H = point(0x0250929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0)'' which is [https://github.com/ElementsProject/secp256k1-zkp/blob/11af7015de624b010424273be3d91f117f172c82/src/modules/rangeproof/main_impl.h#L16 constructed] by taking the hash of the standard uncompressed encoding of secp256k1 generator ''G'' as X coordinate. In order to avoid leaking the information that key path spending is not possible it is recommended to pick a fresh integer ''r'' in the range ''0...n-1'' uniformly at random and use ''H + rG'' as internal key. It is possible to prove that this internal key does not have a known discrete logarithm with respect to ''G'' by revealing ''r'' to a verifier who can then reconstruct how the internal key was created. +* If one or more of the spending conditions consist of just a single key (after aggregation), the most likely one should be made the internal key. If no such condition exists, it may be worthwhile adding one that consists of an aggregation of all keys participating in all scripts combined; effectively adding an "everyone agrees" branch. If that is inacceptable, pick as internal key a point with unknown discrete logarithm. One example of such a point is ''H = point(0x0250929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0)'' which is [https://github.com/ElementsProject/secp256k1-zkp/blob/11af7015de624b010424273be3d91f117f172c82/src/modules/rangeproof/main_impl.h#L16 constructed] by taking the hash of the standard uncompressed encoding of the [https://www.secg.org/sec2-v2.pdf secp256k1] base point ''G'' as X coordinate. In order to avoid leaking the information that key path spending is not possible it is recommended to pick a fresh integer ''r'' in the range ''0...n-1'' uniformly at random and use ''H + rG'' as internal key. It is possible to prove that this internal key does not have a known discrete logarithm with respect to ''G'' by revealing ''r'' to a verifier who can then reconstruct how the internal key was created. * If the spending conditions do not require a script path, the output key should commit to an unspendable script path instead of having no script path. This can be achieved by computing the output key point as ''Q = P + int(hashTapTweak(bytes(P)))G''. '''Why should the output key always have a taproot commitment, even if there is no script path?''' If the taproot output key is an aggregate of keys, there is the possibility for a malicious party to add a script path without being noticed by the other parties. This allows to bypass the multiparty policy and to steal the coin. -- cgit v1.2.3 From 5abcbca34330e137de13bf32c9829bf9ffde581a Mon Sep 17 00:00:00 2001 From: Anthony Date: Mon, 11 Nov 2019 13:40:42 -0500 Subject: ADD: Require Schnorr BIP for Taproot Per https://github.com/bitcoin/bips/blob/master/bip-0001.mediawiki: "BIPs may have a Requires header, indicating the BIP numbers that this BIP depends on" --- bip-taproot.mediawiki | 1 + 1 file changed, 1 insertion(+) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 7d646ea..2427e3d 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -9,6 +9,7 @@ Type: Standards Track Created: License: BSD-3-Clause + Requires: BIP-Schnorr ==Introduction== -- cgit v1.2.3 From c98970085d81e87b1d22683fe0828b46b4e999ce Mon Sep 17 00:00:00 2001 From: Gregory Sanders Date: Mon, 11 Nov 2019 15:32:57 -0500 Subject: BIP16 has no relation to bip-taproot/tapscript Previously did. --- bip-tapscript.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index 9044c71..3e0ccc8 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -50,7 +50,7 @@ The rules below only apply when validating a transaction input for which all of * The leaf version is ''0xc0'' (i.e. the first byte of the last witness element after removing the optional annex is ''0xc0'' or ''0xc1'')'''How is the ''0xc0'' constant chosen?''' Following the guidelines in bip-taproot, by choosing a value having the two top bits set, tapscript spends are identifiable even without access to the UTXO being spent., marking it as a '''tapscript spend'''. Validation of such inputs must be equivalent to performing the following steps in the specified order. -# If the input is invalid due to BIP16, BIP141, or bip-taproot, fail. +# If the input is invalid due to BIP141 or bip-taproot, fail. # The script as defined in bip-taproot (i.e., the penultimate witness stack element after removing the optional annex) is called the '''tapscript''' and is decoded into opcodes, one by one: ## If any opcode numbered ''80, 98, 126-129, 131-134, 137-138, 141-142, 149-153, 187-254'' is encountered, validation succeeds (none of the rules below apply). This is true even if later bytes in the tapscript would fail to decode otherwise. These opcodes are renamed to OP_SUCCESS80, ..., OP_SUCCESS254, and collectively known as OP_SUCCESSx'''OP_SUCCESSx''' OP_SUCCESSx is a mechanism to upgrade the Script system. Using an OP_SUCCESSx before its meaning is defined by a softfork is insecure and leads to fund loss. The inclusion of OP_SUCCESSx in a script will pass it unconditionally. It precedes any script execution rules to avoid the difficulties in specifying various edge cases, for example: OP_SUCCESSx in a script with an input stack larger than 1000 elements, OP_SUCCESSx after too many signature opcodes, or even scripts with conditionals lacking OP_ENDIF. The mere existence of an OP_SUCCESSx anywhere in the script will guarantee a pass for all such cases. OP_SUCCESSx are similar to the OP_RETURN in very early bitcoin versions (v0.1 up to and including v0.3.5). The original OP_RETURN terminates script execution immediately, and return pass or fail based on the top stack element at the moment of termination. This was one of a major design flaws in the original bitcoin protocol as it permitted unconditional third party theft by placing an OP_RETURN in scriptSig. This is not a concern in the present proposal since it is not possible for a third party to inject an OP_SUCCESSx to the validation process, as the OP_SUCCESSx is part of the script (and thus committed to be the taproot output), implying the consent of the coin owner. OP_SUCCESSx can be used for a variety of upgrade possibilities: * An OP_SUCCESSx could be turned into a functional opcode through a softfork. Unlike OP_NOPx-derived opcodes which only have read-only access to the stack, OP_SUCCESSx may also write to the stack. Any rule changes to an OP_SUCCESSx-containing script may only turn a valid script into an invalid one, and this is always achievable with softforks. -- cgit v1.2.3 From e5918b3b2952d39a5a8962ee88abddbb0c40328d Mon Sep 17 00:00:00 2001 From: Adam Gibson Date: Tue, 12 Nov 2019 11:41:27 +0000 Subject: Add clarification of semantics of 0x00 hash type --- bip-taproot.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 7d646ea..d3b3e4b 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -100,7 +100,7 @@ The following rules apply: ==== hash_type ==== -hash_type is an 8-bit unsigned value. The SIGHASH encodings from the legacy script system are used, including SIGHASH_ALL, SIGHASH_NONE, SIGHASH_SINGLE, and SIGHASH_ANYONECANPAY +hash_type is an 8-bit unsigned value. The SIGHASH encodings from the legacy script system are used, including SIGHASH_ALL, SIGHASH_NONE, SIGHASH_SINGLE, and SIGHASH_ANYONECANPAY. Use of the default hash_type = 0x00 results in signing over the whole transaction just as for SIGHASH_ALL. The following use of hash_type are invalid, and fail execution: -- cgit v1.2.3 From 0af4a352956b338b8bcf89f830145a7345423fe1 Mon Sep 17 00:00:00 2001 From: Anthony Date: Tue, 12 Nov 2019 14:08:09 -0500 Subject: ADD: Require Schnorr and Taproot BIPs for Tapscript https://github.com/sipa/bips/pull/135#issuecomment-552754867 --- bip-tapscript.mediawiki | 1 + 1 file changed, 1 insertion(+) diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index 9044c71..974575c 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -9,6 +9,7 @@ Type: Standards Track Created: License: BSD-3-Clause + Requires: BIP-Schnorr, BIP-Taproot ==Introduction== -- cgit v1.2.3 From f620c87eb7a04edbe6bedd4a2ede5d40a8d6fda2 Mon Sep 17 00:00:00 2001 From: Anthony Date: Tue, 12 Nov 2019 15:47:39 -0500 Subject: FIX: BIPs should be specified as lowercase to match filenames --- bip-taproot.mediawiki | 2 +- bip-tapscript.mediawiki | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 2427e3d..0566fcc 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -9,7 +9,7 @@ Type: Standards Track Created: License: BSD-3-Clause - Requires: BIP-Schnorr + Requires: bip-schnorr ==Introduction== diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index 974575c..1c5311f 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -9,7 +9,7 @@ Type: Standards Track Created: License: BSD-3-Clause - Requires: BIP-Schnorr, BIP-Taproot + Requires: bip-schnorr, bip-taproot ==Introduction== -- cgit v1.2.3 From 8b92d05be91f5d198e3f924a0ce5d92f92e6bf00 Mon Sep 17 00:00:00 2001 From: Jon Atack Date: Tue, 12 Nov 2019 22:37:47 +0100 Subject: bip-taproot: clarify bip-schnorr reference code - update the paragraph in question to more clearly convey that the helper functions, and not the Python3 example code, are from the bip-schnorr reference code - add a link to the reference code in https://github.com/sipa/bips/blob/bip-schnorr/bip-schnorr/reference.py --- bip-taproot.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 7d646ea..d1b1ec2 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -176,7 +176,7 @@ Alice will not be able to notice the script path, but Mallory can unilaterally s * The remaining scripts should be organized into the leaves of a binary tree. This can be a balanced tree if each of the conditions these scripts correspond to are equally likely. If probabilities for each condition are known, consider constructing the tree as a Huffman tree. -'''Computing the output script''' Once the spending conditions are split into an internal key internal_pubkey and a binary tree whose leaves are (leaf_version, script) tuples, the output script can be computed using the following Python3 algorithms with helper functions from the bip-schnorr reference code for integer conversion, point multiplication and tagged hashes. +'''Computing the output script''' Once the spending conditions are split into an internal key internal_pubkey and a binary tree whose leaves are (leaf_version, script) tuples, the output script can be computed using the Python3 algorithms below. These algorithms take advantage of helper functions from the [https://github.com/sipa/bips/blob/bip-schnorr/bip-schnorr/reference.py bip-schnorr reference code] for integer conversion, point multiplication, and tagged hashes. First, we define taproot_tweak_pubkey for 32-byte bip-schnorr public key arrays. In addition to the tweaked public key byte array, the function returns a boolean for the squareness of the tweaked points' Y coordinate modulo the secp256k1 field order. -- cgit v1.2.3 From 7bce5a0930ec05fa1da9f1109b8139eb606cfc34 Mon Sep 17 00:00:00 2001 From: Orfeas Stefanos Thyfronitis Litos Date: Wed, 13 Nov 2019 14:00:03 +0000 Subject: Replace R with P in taproot_tweak_seckey --- bip-taproot.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 7d646ea..de266b9 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -194,7 +194,7 @@ def taproot_tweak_pubkey(pubkey, h): def taproot_tweak_seckey(seckey0, h): P = point_mul(G, int_from_bytes(seckey0)) - seckey = SECP256K1_ORDER - seckey0 if not has_square_y(R) else seckey + seckey = SECP256K1_ORDER - seckey0 if not has_square_y(P) else seckey t = int_from_bytes(tagged_hash("TapTweak", bytes_from_int(x(P)) + h)) if t >= SECP256K1_ORDER: raise ValueError -- cgit v1.2.3 From b417bb3c50bbecaa6c00363d02e87cb634939975 Mon Sep 17 00:00:00 2001 From: Orfeas Stefanos Thyfronitis Litos Date: Wed, 13 Nov 2019 17:20:09 +0000 Subject: Add links to unlinked BIPs Only first mention of each BIP is made into a link --- bip-taproot.mediawiki | 6 +++--- bip-tapscript.mediawiki | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index de266b9..446cfba 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -75,7 +75,7 @@ The following rules only apply when such an output is being spent. Any other out ** For ''j'' in ''[0,1,...,m-1]'': *** Let ''ej = c[33+32j:65+32j]''. *** Let ''kj+1 depend on whether ''kj < ej'' (lexicographically)'''Why are child elements sorted before hashing in the Merkle tree?''' By doing so, it is not necessary to reveal the left/right directions along with the hashes in revealed Merkle branches. This is possible because we do not actually care about the position of specific scripts in the tree; only that they are actually committed to.: -**** If ''kj < ej'': ''kj+1 = hashTapBranch(kj || ej)'''''Why not use a more efficient hash construction for inner Merkle nodes?''' The chosen construction does require two invocations of the SHA256 compression functions, one of which can be avoided in theory (see BIP98). However, it seems preferable to stick to constructions that can be implemented using standard cryptographic primitives, both for implementation simplicity and analyzability. If necessary, a significant part of the second compression function can be optimized out by [https://github.com/bitcoin/bitcoin/pull/13191 specialization] for 64-byte inputs.. +**** If ''kj < ej'': ''kj+1 = hashTapBranch(kj || ej)'''''Why not use a more efficient hash construction for inner Merkle nodes?''' The chosen construction does require two invocations of the SHA256 compression functions, one of which can be avoided in theory (see [https://github.com/bitcoin/bips/blob/master/bip-0098.mediawiki BIP98]). However, it seems preferable to stick to constructions that can be implemented using standard cryptographic primitives, both for implementation simplicity and analyzability. If necessary, a significant part of the second compression function can be optimized out by [https://github.com/bitcoin/bitcoin/pull/13191 specialization] for 64-byte inputs.. **** If ''kj ≥ ej'': ''kj+1 = hashTapBranch(ej || kj)''. ** Let ''t = hashTapTweak(p || km)''. ** If ''t ≥ 0xFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141'' (order of secp256k1), fail. @@ -143,7 +143,7 @@ As the message for signature verification, transaction digest is ''hashTapS The total number of bytes hashed is at most ''211'''''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''178 - is_anyonecanpay * 52 - is_none * 32 + has_annex * 32''.. -In summary, the semantics of the BIP143 sighash types remain unchanged, except the following: +In summary, the semantics of the [https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki BIP143] sighash types remain unchanged, except the following: # The way and order of serialization is changed.'''Why is the serialization in the transaction digest changed?''' Hashes that go into the digest and the digest itself are now computed with a single SHA256 invocation instead of double SHA256. There is no expected security improvement by doubling SHA256 because this only protects against length-extension attacks against SHA256 which are not a concern for transaction digests because there is no secret data. Therefore doubling SHA256 is a waste of resources. The digest computation now follows a logical order with transaction level data first, then input data and output data. This allows to efficiently cache the transaction part of the digest across different inputs using the SHA256 midstate. Additionally, digest computation avoids unnecessary hashing as opposed to BIP143 digests in which parts may be set zero and before hashing them. Despite that, collisions are made impossible by committing to the length of the data (implicit in hash_type and spend_type) before the variable length data. # The digest commits to the scriptPubKey'''Why does the transaction digest commit to the scriptPubKey?''' This prevents lying to offline signing devices about output being spent, even when the actually executed script (scriptCode in BIP143) is correct. This means it's possible to compactly prove to a hardware wallet what (unused) execution paths existed.. # If the SIGHASH_ANYONECANPAY flag is not set, the digest commits to the amounts of ''all'' transaction inputs.'''Why does the transaction digest commit to the amounts of all transaction inputs?''' This eliminates the possibility to lie to offline signing devices about the fee of a transaction. @@ -298,7 +298,7 @@ Non-upgraded nodes, however, will consider all SegWit version 1 witness programs They are strongly encouraged to upgrade in order to fully validate the new programs. Non-upgraded wallets can receive and send bitcoin from non-upgraded and upgraded wallets using SegWit version 0 programs, traditional pay-to-pubkey-hash, etc. -Depending on the implementation non-upgraded wallets may be able to send to Segwit version 1 programs if they support sending to BIP173 Bech32 addresses. +Depending on the implementation non-upgraded wallets may be able to send to Segwit version 1 programs if they support sending to [https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki BIP173] Bech32 addresses. == Acknowledgements == diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index 3e0ccc8..bce6186 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -44,7 +44,7 @@ Additionally, the new tapscript OP_SUCCESS opcodes allow introducin ==Specification== The rules below only apply when validating a transaction input for which all of the conditions below are true: -* The transaction output is a '''segregated witness spend''' (i.e., the scriptPubKey is a witness program as defined in BIP141). +* The transaction output is a '''segregated witness spend''' (i.e., the scriptPubKey is a witness program as defined in [https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki BIP141]). * It is a '''taproot spend''' as defined in bip-taproot (i.e., the witness version is 1, the witness program is 32 bytes, and it is not P2SH wrapped). * It is a '''script path spend''' as defined in bip-taproot (i.e., after removing the optional annex from the witness stack, two or more stack elements remain). * The leaf version is ''0xc0'' (i.e. the first byte of the last witness element after removing the optional annex is ''0xc0'' or ''0xc1'')'''How is the ''0xc0'' constant chosen?''' Following the guidelines in bip-taproot, by choosing a value having the two top bits set, tapscript spends are identifiable even without access to the UTXO being spent., marking it as a '''tapscript spend'''. @@ -66,7 +66,7 @@ Validation of such inputs must be equivalent to performing the following steps i ===Script execution=== -The execution rules for tapscript are based on those for P2WSH according to BIP141, including the OP_CHECKLOCKTIMEVERIFY and OP_CHECKSEQUENCEVERIFY opcodes defined in BIP65 and BIP112, but with the following modifications: +The execution rules for tapscript are based on those for P2WSH according to BIP141, including the OP_CHECKLOCKTIMEVERIFY and OP_CHECKSEQUENCEVERIFY opcodes defined in [https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki BIP65] and [https://github.com/bitcoin/bips/blob/master/bip-0112.mediawiki BIP112], but with the following modifications: * '''Disabled script opcodes''' The following script opcodes are disabled in tapscript: OP_CHECKMULTISIG and OP_CHECKMULTISIGVERIFY'''Why are OP_CHECKMULTISIG and OP_CHECKMULTISIGVERIFY disabled, and not turned into OP_SUCCESSx?''' This is a precaution to make sure people who accidentally keep using OP_CHECKMULTISIG in Tapscript notice a problem immediately. It also avoids the complication of script disassemblers needing to become context-dependent.. The disabled opcodes behave in the same way as OP_RETURN, by failing and terminating the script immediately when executed, and being ignored when found in unexecuted branch. * '''Consensus-enforced MINIMALIF''' The MINIMALIF rules, which are only a standardness rule in P2WSH, are consensus enforced in tapscript. This means that the input argument to the OP_IF and OP_NOTIF opcodes must be either exactly 0 (the empty vector) or exactly 1 (the one-byte vector with value 1)'''Why make MINIMALIF consensus?''' This makes it considerably easier to write non-malleable scripts that take branch information from the stack.. * '''OP_SUCCESSx opcodes''' As listed above, some opcodes are renamed to OP_SUCCESSx, and make the script unconditionally valid. @@ -116,7 +116,7 @@ As additional pieces of data, added at the end of the input to the ''hashTa The total number of bytes hashed is at most ''248'''''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''215 - is_anyonecanpay * 52 - is_none * 32 + has_annex * 32''.. -In summary, the semantics of the BIP143 sighash types remain unchanged, except the following: +In summary, the semantics of the [https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki BIP143] sighash types remain unchanged, except the following: # The exceptions mentioned in bip-taproot. # The digest commits to taproot-specific data key_version.'''Why does the transaction digest commit to the key_version?''' This is for future extensions that define unknown public key types, making sure signatures can't be moved from one key type to another. # The digest commits to the executed script through the tapleaf_hash which includes the leaf version and script instead of scriptCode. This implies that this commitment is unaffected by OP_CODESEPARATOR. -- cgit v1.2.3 From 1a9c7f948aee96c2deaeade05009c245d417742b Mon Sep 17 00:00:00 2001 From: Devrandom Date: Wed, 13 Nov 2019 18:46:05 +0100 Subject: clarify 211 hash bytes and non-reuse of keys --- bip-taproot.mediawiki | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index de266b9..6d2e975 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -141,7 +141,7 @@ As the message for signature verification, transaction digest is ''hashTapS ** If the SIGHASH_SINGLE flag is set: *** sha_single_output (32): the SHA256 of the corresponding output in CTxOut format. -The total number of bytes hashed is at most ''211'''''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''178 - is_anyonecanpay * 52 - is_none * 32 + has_annex * 32''.. +The total number of bytes hashed at top level is at most ''211'''''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''178 - is_anyonecanpay * 52 - is_none * 32 + has_annex * 32''.. Sub-hashes, such as `sha_prevouts`, may be cached across signatures of the same transaction. In summary, the semantics of the BIP143 sighash types remain unchanged, except the following: # The way and order of serialization is changed.'''Why is the serialization in the transaction digest changed?''' Hashes that go into the digest and the digest itself are now computed with a single SHA256 invocation instead of double SHA256. There is no expected security improvement by doubling SHA256 because this only protects against length-extension attacks against SHA256 which are not a concern for transaction digests because there is no secret data. Therefore doubling SHA256 is a waste of resources. The digest computation now follows a logical order with transaction level data first, then input data and output data. This allows to efficiently cache the transaction part of the digest across different inputs using the SHA256 midstate. Additionally, digest computation avoids unnecessary hashing as opposed to BIP143 digests in which parts may be set zero and before hashing them. Despite that, collisions are made impossible by committing to the length of the data (implicit in hash_type and spend_type) before the variable length data. @@ -270,7 +270,7 @@ A script path spend leaks that there is a script path and that the key path was Moreover, the depth of a script in the Merkle root leaks information including the minimum depth of the tree, which suggests specific wallet software that created the output and helps clustering. Therefore, the privacy of script spends can be improved by deviating from the optimal tree determined by the probability distribution over the leaves. -Just like other existing output types, taproot outputs should never reuse keys. +Just like other existing output types, taproot outputs should never reuse keys, for privacy reasons. This does not only apply to the particular leaf that was used to spend an output but to all leaves committed to in the output. If leaves were reused, it could happen that spending a different output would reuse the same Merkle branches in the Merkle proof. Using fresh keys implies that taproot output construction does not need to take special measures to randomizing leaf positions because they are already randomized due to the branch-sorting Merkle tree construction used in taproot. -- cgit v1.2.3 From b8cbd419e6d338bff68afd98be4d52a450e7dff1 Mon Sep 17 00:00:00 2001 From: Dev Random Date: Thu, 14 Nov 2019 10:55:32 -0800 Subject: tweak 211 bytes text --- bip-taproot.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 6d2e975..18430b9 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -141,7 +141,7 @@ As the message for signature verification, transaction digest is ''hashTapS ** If the SIGHASH_SINGLE flag is set: *** sha_single_output (32): the SHA256 of the corresponding output in CTxOut format. -The total number of bytes hashed at top level is at most ''211'''''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''178 - is_anyonecanpay * 52 - is_none * 32 + has_annex * 32''.. Sub-hashes, such as `sha_prevouts`, may be cached across signatures of the same transaction. +The total number of bytes hashed is at most ''211'' (excluding sub-hashes such as `sha_prevouts`)'''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''178 - is_anyonecanpay * 52 - is_none * 32 + has_annex * 32''.. Sub-hashes may be cached across signatures of the same transaction. In summary, the semantics of the BIP143 sighash types remain unchanged, except the following: # The way and order of serialization is changed.'''Why is the serialization in the transaction digest changed?''' Hashes that go into the digest and the digest itself are now computed with a single SHA256 invocation instead of double SHA256. There is no expected security improvement by doubling SHA256 because this only protects against length-extension attacks against SHA256 which are not a concern for transaction digests because there is no secret data. Therefore doubling SHA256 is a waste of resources. The digest computation now follows a logical order with transaction level data first, then input data and output data. This allows to efficiently cache the transaction part of the digest across different inputs using the SHA256 midstate. Additionally, digest computation avoids unnecessary hashing as opposed to BIP143 digests in which parts may be set zero and before hashing them. Despite that, collisions are made impossible by committing to the length of the data (implicit in hash_type and spend_type) before the variable length data. -- cgit v1.2.3 From 8861bd503ab4db81ddaf65bd0f6406e8633f59c8 Mon Sep 17 00:00:00 2001 From: Gregory Sanders Date: Fri, 15 Nov 2019 13:46:35 -0500 Subject: remind reader where [:] is defined in addition to `point`. This caused confusion for one reader who expected inclusive at end of range. --- bip-taproot.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index de266b9..7ae422b 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -65,7 +65,7 @@ The following rules only apply when such an output is being spent. Any other out * If there are at least two witness elements left, script path spending is used: ** Call the second-to-last stack element ''s'', the script. ** The last stack element is called the control block ''c'', and must have length ''33 + 32m'', for a value of ''m'' that is an integer between 0 and 128'''Why is the Merkle path length limited to 128?''' The optimally space-efficient Merkle tree can be constructed based on the probabilities of the scripts in the leaves, using the Huffman algorithm. This algorithm will construct branches with lengths approximately equal to ''log2(1/probability)'', but to have branches longer than 128 you would need to have scripts with an execution chance below 1 in ''2128''. As that is our security bound, scripts that truly have such a low chance can probably be removed entirely., inclusive. Fail if it does not have such a length. -** Let ''p = c[1:33]'' and let ''P = point(p)'' where ''point'' is defined as in bip-schnorr. Fail if this point is not on the curve. +** Let ''p = c[1:33]'' and let ''P = point(p)'' where ''point'' and ''[:]'' are defined as in bip-schnorr. Fail if this point is not on the curve. ** Let ''l = c[0] & 0xfe'', the leaf version'''What is the purpose of the first byte of the control block?''' The first byte of the control block has three distinct functions: * The low bit is used to denote whether the ''has_square_y(Q)'' holds.'''Why is the squareness of the output public key's Y coordinate required in a script path spend?''' The ''point'' function always constructs a point with Y coordinate having that property, but because ''Q'' is constructed by adding the taproot tweak to the internal public key ''P'', it cannot easily be guaranteed that ''Q'' in fact has such a Y coordinate. We can not ignore the Y coordinate because it would prevent batch verification. Trying out multiple internal keys until there's such a ''Q'' is possible but undesirable and unnecessary since this information about the Y coordinate only consumes an unused bit. * By keeping the top two bits set to true, it can be guaranteed that scripts can be recognized without knowledge of the UTXO being spent, simplifying analysis. This is because such values cannot occur as first byte of the final stack element in either P2WPKH or P2WSH spends. -- cgit v1.2.3 From de14bad4dc163e16efab51b8b457b2d1966862a0 Mon Sep 17 00:00:00 2001 From: Max Hillebrand <30683012+MaxHillebrand@users.noreply.github.com> Date: Mon, 18 Nov 2019 14:56:29 +0800 Subject: make clear it's script branch In this context we are talking about the script branch, not the Merkle tree branch, right? If so, then this should clear things up a little. --- bip-tapscript.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index d4cd5da..c80433d 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -68,7 +68,7 @@ Validation of such inputs must be equivalent to performing the following steps i ===Script execution=== The execution rules for tapscript are based on those for P2WSH according to BIP141, including the OP_CHECKLOCKTIMEVERIFY and OP_CHECKSEQUENCEVERIFY opcodes defined in [https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki BIP65] and [https://github.com/bitcoin/bips/blob/master/bip-0112.mediawiki BIP112], but with the following modifications: -* '''Disabled script opcodes''' The following script opcodes are disabled in tapscript: OP_CHECKMULTISIG and OP_CHECKMULTISIGVERIFY'''Why are OP_CHECKMULTISIG and OP_CHECKMULTISIGVERIFY disabled, and not turned into OP_SUCCESSx?''' This is a precaution to make sure people who accidentally keep using OP_CHECKMULTISIG in Tapscript notice a problem immediately. It also avoids the complication of script disassemblers needing to become context-dependent.. The disabled opcodes behave in the same way as OP_RETURN, by failing and terminating the script immediately when executed, and being ignored when found in unexecuted branch. +* '''Disabled script opcodes''' The following script opcodes are disabled in tapscript: OP_CHECKMULTISIG and OP_CHECKMULTISIGVERIFY'''Why are OP_CHECKMULTISIG and OP_CHECKMULTISIGVERIFY disabled, and not turned into OP_SUCCESSx?''' This is a precaution to make sure people who accidentally keep using OP_CHECKMULTISIG in Tapscript notice a problem immediately. It also avoids the complication of script disassemblers needing to become context-dependent.. The disabled opcodes behave in the same way as OP_RETURN, by failing and terminating the script immediately when executed, and being ignored when found in unexecuted branch of the script. * '''Consensus-enforced MINIMALIF''' The MINIMALIF rules, which are only a standardness rule in P2WSH, are consensus enforced in tapscript. This means that the input argument to the OP_IF and OP_NOTIF opcodes must be either exactly 0 (the empty vector) or exactly 1 (the one-byte vector with value 1)'''Why make MINIMALIF consensus?''' This makes it considerably easier to write non-malleable scripts that take branch information from the stack.. * '''OP_SUCCESSx opcodes''' As listed above, some opcodes are renamed to OP_SUCCESSx, and make the script unconditionally valid. * '''Signature opcodes'''. The OP_CHECKSIG and OP_CHECKSIGVERIFY are modified to operate on Schnorr public keys and signatures (see bip-schnorr) instead of ECDSA, and a new opcode OP_CHECKSIGADD is added. -- cgit v1.2.3 From cacb82fc6dff97a98c935311d1918c3a0fbbe2b2 Mon Sep 17 00:00:00 2001 From: Orfeas Stefanos Thyfronitis Litos Date: Mon, 18 Nov 2019 14:42:56 +0000 Subject: Fix typo in schnorr, footnote 2 --- bip-schnorr.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index cff066e..861369c 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -25,7 +25,7 @@ Bitcoin has traditionally used transactions. These are [https://www.secg.org/sec1-v2.pdf standardized], but have a number of downsides compared to [http://publikationen.ub.uni-frankfurt.de/opus4/files/4280/schnorr.pdf Schnorr signatures] over the same curve: -* '''Provable security''': Schnorr signatures are provably secure. In more detail, they are ''strongly unforgeable under chosen message attack (SUF-CMA)''Informally, this means that without knowledge of the secret key but given valid signatures of arbitrary messages, it is not possible to come up with further valid signatures. [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf in the random oracle model assuming the hardness of the elliptic curve discrete logarithm problem (ECDLP)] and [http://www.neven.org/papers/schnorr.pdf in the generic group model assuming variants of preimage and second preimage resistance of the used hash function]A detailed security proof in the random oracle model, which essentially restates [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf the original security proof by Pointcheval and Stern] more explicitly, can be found in [https://eprint.iacr.org/2016/191 a paper by Kiltz, Masny and Pan]. All these security proofs assume a variant of Schnorr signatures that use ''(e,s)'' instead of ''(R,s)'' (see Design above). Since we use a unique encoding of ''R'', there is an efficiently computable bijection that maps ''(R,s)'' to ''(e,s)'', which allows to convert a successful SUF-CMA attacker for the ''(e,s)'' variant to a successful SUF-CMA attacker for the ''(r,s)'' variant (and vice-versa). Furthermore, the proofs consider a variant of Schnorr signatures without key prefixing (see Design above), but it can be verified that the proofs are also correct for the variant with key prefixing. As a result, all the aforementioned security proofs apply to the variant of Schnorr signatures proposed in this document.. In contrast, the [https://nbn-resolving.de/urn:nbn:de:hbz:294-60803 best known results for the provable security of ECDSA] rely on stronger assumptions. +* '''Provable security''': Schnorr signatures are provably secure. In more detail, they are ''strongly unforgeable under chosen message attack (SUF-CMA)''Informally, this means that without knowledge of the secret key but given valid signatures of arbitrary messages, it is not possible to come up with further valid signatures. [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf in the random oracle model assuming the hardness of the elliptic curve discrete logarithm problem (ECDLP)] and [http://www.neven.org/papers/schnorr.pdf in the generic group model assuming variants of preimage and second preimage resistance of the used hash function]A detailed security proof in the random oracle model, which essentially restates [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf the original security proof by Pointcheval and Stern] more explicitly, can be found in [https://eprint.iacr.org/2016/191 a paper by Kiltz, Masny and Pan]. All these security proofs assume a variant of Schnorr signatures that use ''(e,s)'' instead of ''(R,s)'' (see Design above). Since we use a unique encoding of ''R'', there is an efficiently computable bijection that maps ''(R,s)'' to ''(e,s)'', which allows to convert a successful SUF-CMA attacker for the ''(e,s)'' variant to a successful SUF-CMA attacker for the ''(R,s)'' variant (and vice-versa). Furthermore, the proofs consider a variant of Schnorr signatures without key prefixing (see Design above), but it can be verified that the proofs are also correct for the variant with key prefixing. As a result, all the aforementioned security proofs apply to the variant of Schnorr signatures proposed in this document.. In contrast, the [https://nbn-resolving.de/urn:nbn:de:hbz:294-60803 best known results for the provable security of ECDSA] rely on stronger assumptions. * '''Non-malleability''': The SUF-CMA security of Schnorr signatures implies that they are non-malleable. On the other hand, ECDSA signatures are inherently malleable; a third party without access to the secret key can alter an existing valid signature for a given public key and message into another signature that is valid for the same key and message. This issue is discussed in [https://github.com/bitcoin/bips/blob/master/bip-0062.mediawiki BIP62] and [https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki BIP66]. * '''Linearity''': Schnorr signatures have the remarkable property that multiple parties can collaborate to produce a signature that is valid for the sum of their public keys. This is the building block for various higher-level constructions that improve efficiency and privacy, such as multisignatures and others (see Applications below). -- cgit v1.2.3 From e544fc66baa1ab71fe6bc1b53f140c9345707115 Mon Sep 17 00:00:00 2001 From: Orfeas Stefanos Thyfronitis Litos Date: Mon, 18 Nov 2019 16:46:10 +0000 Subject: Link to proof sketch of security of implicit Y Thanks to @ajtowns for providing the link --- bip-schnorr.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 861369c..42f54d2 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -81,7 +81,7 @@ expensive conversion to affine coordinates first. This would even be the case if For ''P'' the speed of signing and verification does not significantly differ between any of the three options because affine coordinates of the point have to be computed anyway. For consistency reasons we choose the same option as for ''R''. The signing algorithm ensures that the signature is valid under the correct public key by negating the secret key if necessary. -Implicit Y coordinates are not a reduction in security when expressed as the number of elliptic curve operations an attacker is expected to perform to compute the secret key. An attacker can normalize any given public key to a point whose Y coordinate is a square by negating the point if necessary. This is just a subtraction of field elements and not an elliptic curve operationThis can be formalized by a simple reduction that reduces an attack on Schnorr signatures with implicit Y coordinates to an attack to Schnorr signatures with explicit Y coordinates. The reduction works by reencoding public keys and negating the result of the hash function, which is modeled as random oracle, whenever the challenge public key has an explicit Y coordinate that is not a square.. +Implicit Y coordinates are not a reduction in security when expressed as the number of elliptic curve operations an attacker is expected to perform to compute the secret key. An attacker can normalize any given public key to a point whose Y coordinate is a square by negating the point if necessary. This is just a subtraction of field elements and not an elliptic curve operationThis can be formalized by a simple reduction that reduces an attack on Schnorr signatures with implicit Y coordinates to an attack to Schnorr signatures with explicit Y coordinates. The reduction works by reencoding public keys and negating the result of the hash function, which is modeled as random oracle, whenever the challenge public key has an explicit Y coordinate that is not a square. A proof sketch can be found [here](https://medium.com/blockstream/reducing-bitcoin-transaction-sizes-with-x-only-pubkeys-f86476af05d7). '''Tagged Hashes''' Cryptographic hash functions are used for multiple purposes in the specification below and in Bitcoin in general. To make sure hashes used in one context can't be reinterpreted in another one, hash functions can be tweaked with a context-dependent tag name, in such a way that collisions across contexts can be assumed to be infeasible. Such collisions obviously can not be ruled out completely, but only for schemes using tagging with a unique name. As for other schemes collisions are at least less likely with tagging than without. -- cgit v1.2.3 From 314e9fd9043de0a0a01b15f55d9b7cce61b88d06 Mon Sep 17 00:00:00 2001 From: Orfeas Stefanos Thyfronitis Litos Date: Mon, 18 Nov 2019 17:00:39 +0000 Subject: Add missing quote --- bip-schnorr.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 861369c..3d6a957 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -107,7 +107,7 @@ The following conventions are used, with constants as defined for [https://www.s ** ''||'' refers to byte array concatenation. ** The function ''x[i:j]'', where ''x'' is a byte array, returns a ''(j - i)''-byte array with a copy of the ''i''-th byte (inclusive) to the ''j''-th byte (exclusive) of ''x''. ** The function ''bytes(x)'', where ''x'' is an integer, returns the 32-byte encoding of ''x'', most significant byte first. -** The function ''bytes(P)'', where ''P'' is a point, returns ''bytes(x(P))'. +** The function ''bytes(P)'', where ''P'' is a point, returns ''bytes(x(P))''. ** The function ''int(x)'', where ''x'' is a 32-byte array, returns the 256-bit unsigned integer whose most significant byte first encoding is ''x''. ** The function ''is_square(x)'', where ''x'' is an integer, returns whether or not ''x'' is a quadratic residue modulo ''p''. Since ''p'' is prime, it is equivalent to the Legendre symbol ''(x / p) = x(p-1)/2 mod p'' being equal to ''1'' (see [https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion])For points ''P'' on the secp256k1 curve it holds that ''x(p-1)/2 ≠ 0 mod p''.. ** The function ''has_square_y(P)'', where ''P'' is a point, is defined as ''not is_infinite(P) and is_square(y(P))''For points ''P'' on the secp256k1 curve it holds that ''has_square_y(P) = not has_square_y(-P)''.. -- cgit v1.2.3 From 09c12e40521d6f17ab530a9fb6804f23ac1ad409 Mon Sep 17 00:00:00 2001 From: stefanwouldgo Date: Tue, 19 Nov 2019 10:10:34 +0100 Subject: grammar typo fix: inserted "be" --- bip-schnorr.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 3d6a957..54d2b19 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -60,7 +60,7 @@ We choose the ''R''-option to support batch verification. To protect against these attacks, we choose ''key prefixed''A limitation of committing to the public key (rather than to a short hash of it, or not at all) is that it removes the ability for public key recovery or verifying signatures against a short public key hash. These constructions are generally incompatible with batch verification. Schnorr signatures; changing the equation to ''s⋅G = R + hash(R || P || m)⋅P''. [https://eprint.iacr.org/2015/1135.pdf It can be shown] that key prefixing protects against related-key attacks with additive tweaks. In general, key prefixing increases robustness in multi-user settings, e.g., it seems to be a requirement for proving the MuSig multisignature scheme secure (see Applications below). -We note that key prefixing is not strictly necessary for transaction signatures as used in Bitcoin currently, because signed transactions indirectly commit to the public keys already, i.e., ''m'' contains a commitment to ''pk''. However, this indirect commitment should not relied upon because it may change with proposals such as SIGHASH_NOINPUT ([https://github.com/bitcoin/bips/blob/master/bip-0118.mediawiki BIP118]), and would render the signature scheme unsuitable for other purposes than signing transactions, e.g., [https://bitcoin.org/en/developer-reference#signmessage signing ordinary messages]. +We note that key prefixing is not strictly necessary for transaction signatures as used in Bitcoin currently, because signed transactions indirectly commit to the public keys already, i.e., ''m'' contains a commitment to ''pk''. However, this indirect commitment should not be relied upon because it may change with proposals such as SIGHASH_NOINPUT ([https://github.com/bitcoin/bips/blob/master/bip-0118.mediawiki BIP118]), and would render the signature scheme unsuitable for other purposes than signing transactions, e.g., [https://bitcoin.org/en/developer-reference#signmessage signing ordinary messages]. '''Encoding R and public key point P''' There exist several possibilities for encoding elliptic curve points: # Encoding the full X and Y coordinates of ''P'' and ''R'', resulting in a 64-byte public key and a 96-byte signature. -- cgit v1.2.3 From 75b464ad76a9fab06ee0d28db524f413ff02fad7 Mon Sep 17 00:00:00 2001 From: Dmitry Petukhov Date: Thu, 21 Nov 2019 14:25:53 +0500 Subject: Add missing dots that denote multiplication MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Throughout the document, elliptic curve multiplication is denoted with dots, as in `d'⋅G` as opposed to `d'G`. This is not the case in one place in the 'Default Signing' section, and one place in 'Adaptor Signatures' section Missing dots are added for consistency. --- bip-schnorr.mediawiki | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 3d6a957..5e4bd47 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -146,7 +146,7 @@ The algorithm ''Sign(sk, m)'' is defined as: * Let ''d = d' '' if ''has_square_y(P)'', otherwise let ''d = n - d' ''. * Let ''k' = int(hashBIPSchnorrDerive(bytes(d) || m)) mod n''Note that in general, taking the output of a hash function modulo the curve order will produce an unacceptably biased result. However, for the secp256k1 curve, the order is sufficiently close to ''2256'' that this bias is not observable (''1 - n / 2256'' is around ''1.27 * 2-128'').. * Fail if ''k' = 0''. -* Let ''R = k'G''. +* Let ''R = k'⋅G''. * Let ''k = k' '' if ''has_square_y(R)'', otherwise let ''k = n - k' ''. * Let ''e = int(hashBIPSchnorr(bytes(R) || bytes(P) || m)) mod n''. * Return the signature ''bytes(R) || bytes((k + ed) mod n)''. @@ -226,7 +226,7 @@ Moreover, Schnorr signatures are compatible with [https://web.archive.org/web/20 === Adaptor Signatures === -[https://download.wpsoftware.net/bitcoin/wizardry/mw-slides/2018-05-18-l2/slides.pdf Adaptor signatures] can be produced by a signer by offsetting his public nonce with a known point ''T = tG'', but not offsetting his secret nonce. +[https://download.wpsoftware.net/bitcoin/wizardry/mw-slides/2018-05-18-l2/slides.pdf Adaptor signatures] can be produced by a signer by offsetting his public nonce with a known point ''T = t⋅G'', but not offsetting his secret nonce. A correct signature (or partial signature, as individual signers' contributions to a multisignature are called) on the same message with same nonce will then be equal to the adaptor signature offset by ''t'', meaning that learning ''t'' is equivalent to learning a correct signature. This can be used to enable atomic swaps or even [https://eprint.iacr.org/2018/472 general payment channels] in which the atomicity of disjoint transactions is ensured using the signatures themselves, rather than Bitcoin script support. The resulting transactions will appear to verifiers to be no different from ordinary single-signer transactions, except perhaps for the inclusion of locktime refund logic. -- cgit v1.2.3 From fbd304575f2f2dfadc4277e12004120129380c3c Mon Sep 17 00:00:00 2001 From: Orfeas Stefanos Thyfronitis Litos Date: Fri, 22 Nov 2019 11:41:36 +0000 Subject: Replace BIP66 link with BIP146 BIP66 does not mention the inherent ECDSA malleability, but BIP146 does --- bip-schnorr.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 5e4bd47..7bf3509 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -26,7 +26,7 @@ transactions. These are [https://www.secg.org/sec1-v2.pdf standardized], but hav compared to [http://publikationen.ub.uni-frankfurt.de/opus4/files/4280/schnorr.pdf Schnorr signatures] over the same curve: * '''Provable security''': Schnorr signatures are provably secure. In more detail, they are ''strongly unforgeable under chosen message attack (SUF-CMA)''Informally, this means that without knowledge of the secret key but given valid signatures of arbitrary messages, it is not possible to come up with further valid signatures. [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf in the random oracle model assuming the hardness of the elliptic curve discrete logarithm problem (ECDLP)] and [http://www.neven.org/papers/schnorr.pdf in the generic group model assuming variants of preimage and second preimage resistance of the used hash function]A detailed security proof in the random oracle model, which essentially restates [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf the original security proof by Pointcheval and Stern] more explicitly, can be found in [https://eprint.iacr.org/2016/191 a paper by Kiltz, Masny and Pan]. All these security proofs assume a variant of Schnorr signatures that use ''(e,s)'' instead of ''(R,s)'' (see Design above). Since we use a unique encoding of ''R'', there is an efficiently computable bijection that maps ''(R,s)'' to ''(e,s)'', which allows to convert a successful SUF-CMA attacker for the ''(e,s)'' variant to a successful SUF-CMA attacker for the ''(R,s)'' variant (and vice-versa). Furthermore, the proofs consider a variant of Schnorr signatures without key prefixing (see Design above), but it can be verified that the proofs are also correct for the variant with key prefixing. As a result, all the aforementioned security proofs apply to the variant of Schnorr signatures proposed in this document.. In contrast, the [https://nbn-resolving.de/urn:nbn:de:hbz:294-60803 best known results for the provable security of ECDSA] rely on stronger assumptions. -* '''Non-malleability''': The SUF-CMA security of Schnorr signatures implies that they are non-malleable. On the other hand, ECDSA signatures are inherently malleable; a third party without access to the secret key can alter an existing valid signature for a given public key and message into another signature that is valid for the same key and message. This issue is discussed in [https://github.com/bitcoin/bips/blob/master/bip-0062.mediawiki BIP62] and [https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki BIP66]. +* '''Non-malleability''': The SUF-CMA security of Schnorr signatures implies that they are non-malleable. On the other hand, ECDSA signatures are inherently malleable; a third party without access to the secret key can alter an existing valid signature for a given public key and message into another signature that is valid for the same key and message. This issue is discussed in [https://github.com/bitcoin/bips/blob/master/bip-0062.mediawiki BIP62] and [https://github.com/bitcoin/bips/blob/master/bip-0146.mediawiki BIP146]. * '''Linearity''': Schnorr signatures have the remarkable property that multiple parties can collaborate to produce a signature that is valid for the sum of their public keys. This is the building block for various higher-level constructions that improve efficiency and privacy, such as multisignatures and others (see Applications below). For all these advantages, there are virtually no disadvantages, apart -- cgit v1.2.3 From 9208857b921cebffb7c5902466264cb8b8b1842e Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Fri, 22 Nov 2019 20:35:54 +0000 Subject: Rename is_y_square to is_negated in taproot signing --- bip-taproot.mediawiki | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 1119785..a8106fc 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -68,7 +68,7 @@ The following rules only apply when such an output is being spent. Any other out ** The last stack element is called the control block ''c'', and must have length ''33 + 32m'', for a value of ''m'' that is an integer between 0 and 128'''Why is the Merkle path length limited to 128?''' The optimally space-efficient Merkle tree can be constructed based on the probabilities of the scripts in the leaves, using the Huffman algorithm. This algorithm will construct branches with lengths approximately equal to ''log2(1/probability)'', but to have branches longer than 128 you would need to have scripts with an execution chance below 1 in ''2128''. As that is our security bound, scripts that truly have such a low chance can probably be removed entirely., inclusive. Fail if it does not have such a length. ** Let ''p = c[1:33]'' and let ''P = point(p)'' where ''point'' and ''[:]'' are defined as in bip-schnorr. Fail if this point is not on the curve. ** Let ''l = c[0] & 0xfe'', the leaf version'''What is the purpose of the first byte of the control block?''' The first byte of the control block has three distinct functions: -* The low bit is used to denote whether the ''has_square_y(Q)'' holds.'''Why is the squareness of the output public key's Y coordinate required in a script path spend?''' The ''point'' function always constructs a point with Y coordinate having that property, but because ''Q'' is constructed by adding the taproot tweak to the internal public key ''P'', it cannot easily be guaranteed that ''Q'' in fact has such a Y coordinate. We can not ignore the Y coordinate because it would prevent batch verification. Trying out multiple internal keys until there's such a ''Q'' is possible but undesirable and unnecessary since this information about the Y coordinate only consumes an unused bit. +* The low bit is used to denote whether the point represented by public key ''q'' is negated before verifying the taproot tweak.'''Why is it necessary to reveal a bit to indicate if the point represented by the output public key is negated in a script path spend?''' The ''point'' function (defined in bip-schnorr) always constructs a point with a square Y coordinate, but because ''Q'' is constructed by adding the taproot tweak to the internal public key ''P'', it cannot easily be guaranteed that ''Q'' in fact has such a Y coordinate. Therefore, before verifying the taproot tweak the original point is restored by negating if necessary. We can not ignore the Y coordinate because it would prevent batch verification. Trying out multiple internal keys until there's such a ''Q'' is possible but undesirable and unnecessary since this information about the Y coordinate only consumes an unused bit. * By keeping the top two bits set to true, it can be guaranteed that scripts can be recognized without knowledge of the UTXO being spent, simplifying analysis. This is because such values cannot occur as first byte of the final stack element in either P2WPKH or P2WSH spends. * The remaining five bits are used for introducing new script versions that are not observable unless actually executed. . @@ -180,7 +180,7 @@ Alice will not be able to notice the script path, but Mallory can unilaterally s '''Computing the output script''' Once the spending conditions are split into an internal key internal_pubkey and a binary tree whose leaves are (leaf_version, script) tuples, the output script can be computed using the Python3 algorithms below. These algorithms take advantage of helper functions from the [https://github.com/sipa/bips/blob/bip-schnorr/bip-schnorr/reference.py bip-schnorr reference code] for integer conversion, point multiplication, and tagged hashes. First, we define taproot_tweak_pubkey for 32-byte bip-schnorr public key arrays. -In addition to the tweaked public key byte array, the function returns a boolean for the squareness of the tweaked points' Y coordinate modulo the secp256k1 field order. +In addition to the tweaked public key byte array, the function returns a boolean indicating whether the public key represents the tweaked point or its negation. This will be required for spending the output with a script path. In order to allow spending with the key path, we define taproot_tweak_seckey to compute the secret key for a tweaked public key. For any byte string h it holds that taproot_tweak_pubkey(pubkey_gen(seckey), h)[0] == pubkey_gen(taproot_tweak_seckey(seckey, h)). @@ -191,7 +191,8 @@ def taproot_tweak_pubkey(pubkey, h): if t >= SECP256K1_ORDER: raise ValueError Q = point_add(point(pubkey), point_mul(G, t)) - return bytes_from_int(x(Q)), has_square_y(Q) + is_negated = not has_square_y(Q) + return bytes_from_int(x(Q)), is_negated def taproot_tweak_seckey(seckey0, h): P = point_mul(G, int_from_bytes(seckey0)) @@ -255,8 +256,8 @@ This function returns the witness stack necessary and a sighash fun def taproot_sign_script(internal_pubkey, script_tree, script_num, inputs): info, h = taproot_tree_helper(script_tree) (leaf_version, script), path = info[script_num] - _, is_y_square = taproot_tweak_pubkey(internal_pubkey, h) - output_pubkey_tag = 0 if is_y_square else 1 + _, is_negated = taproot_tweak_pubkey(internal_pubkey, h) + output_pubkey_tag = 0 if is_negated else 1 pubkey_data = bytes([output_pubkey_tag + leaf_version]) + internal_pubkey return inputs + [script, pubkey_data + path] -- cgit v1.2.3 From 4fa7cba6415ff30a79842dc0cd802f0eb0ec86a6 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sat, 23 Nov 2019 21:27:44 +0200 Subject: Fix paragraph naming and typo --- bip-schnorr.mediawiki | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 5e4bd47..4255bd0 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -49,7 +49,7 @@ encodings and operations. === Design === '''Schnorr signature variant''' Elliptic Curve Schnorr signatures for message ''m'' and public key ''P'' generally involve a point ''R'', integers ''e'' and ''s'' picked by the signer, and the base point ''G'' which satisfy ''e = hash(R || m)'' and ''s⋅G = R + e⋅P''. Two formulations exist, depending on whether the signer reveals ''e'' or ''R'': -# Signatures are ''(e, s)'' that satisfy ''e = hash(s⋅G - e⋅P || m)''. This supports more compact signatures, since [http://www.neven.org/papers/schnorr.pdf the hash ''e'' can be made as small as 16 bytes without sacrificing security], whereas an encoding of ''R'' inherently needs about 32 bytes. Moreover, this variant avoids minor complexity introduced by the encoding of the point ''R'' in the signature (see paragraphs "Encoding the sign of R" and "Implicit Y coordinate" further below in this subsection). +# Signatures are ''(e, s)'' that satisfy ''e = hash(s⋅G - e⋅P || m)''. This supports more compact signatures, since [http://www.neven.org/papers/schnorr.pdf the hash ''e'' can be made as small as 16 bytes without sacrificing security], whereas an encoding of ''R'' inherently needs about 32 bytes. Moreover, this variant avoids minor complexity introduced by the encoding of the point ''R'' in the signature (see paragraphs "Encoding R and public key point P" and "Implicit Y coordinates" further below in this subsection). # Signatures are ''(R, s)'' that satisfy ''s⋅G = R + hash(R || m)⋅P''. This supports batch verification, as there are no elliptic curve operations inside the hashes. Batch verification enables significant speedups. [[File:bip-schnorr/speedup-batch.png|center|frame|This graph shows the ratio between the time it takes to verify ''n'' signatures individually and to verify a batch of ''n'' signatures. This ratio goes up logarithmically with the number of signatures, or in other words: the total time to verify ''n'' signatures grows with ''O(n / log n)''.]] @@ -58,7 +58,7 @@ We choose the ''R''-option to support batch verification. '''Key prefixing''' Using the verification rule above directly makes Schnorr signatures vulnerable to "related-key attacks" in which a third party can convert a signature ''(R, s)'' for public key ''P'' into a signature ''(R, s + a⋅hash(R || m))'' for public key ''P + a⋅G'' and the same message ''m'', for any given additive tweak ''a'' to the signing key. This would render signatures insecure when keys are generated using [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#public-parent-key--public-child-key BIP32's unhardened derivation] and other methods that rely on additive tweaks to existing keys such as Taproot. -To protect against these attacks, we choose ''key prefixed''A limitation of committing to the public key (rather than to a short hash of it, or not at all) is that it removes the ability for public key recovery or verifying signatures against a short public key hash. These constructions are generally incompatible with batch verification. Schnorr signatures; changing the equation to ''s⋅G = R + hash(R || P || m)⋅P''. [https://eprint.iacr.org/2015/1135.pdf It can be shown] that key prefixing protects against related-key attacks with additive tweaks. In general, key prefixing increases robustness in multi-user settings, e.g., it seems to be a requirement for proving the MuSig multisignature scheme secure (see Applications below). +To protect against these attacks, we choose ''key prefixed''A limitation of committing to the public key (rather than to a short hash of it, or not at all) is that it removes the ability for public key recovery or verifying signatures against a short public key hash. These constructions are generally incompatible with batch verification. Schnorr signatures; changing the equation to ''s⋅G = R + hash(R || P || m)⋅P''. [https://eprint.iacr.org/2015/1135.pdf It can be shown] that key prefixing protects against related-key attacks with additive tweaks. In general, key prefixing increases robustness in multi-user settings, e.g., it seems to be a requirement for proving the MuSig multisignature scheme secure (see Applications below). We note that key prefixing is not strictly necessary for transaction signatures as used in Bitcoin currently, because signed transactions indirectly commit to the public keys already, i.e., ''m'' contains a commitment to ''pk''. However, this indirect commitment should not relied upon because it may change with proposals such as SIGHASH_NOINPUT ([https://github.com/bitcoin/bips/blob/master/bip-0118.mediawiki BIP118]), and would render the signature scheme unsuitable for other purposes than signing transactions, e.g., [https://bitcoin.org/en/developer-reference#signmessage signing ordinary messages]. @@ -111,7 +111,7 @@ The following conventions are used, with constants as defined for [https://www.s ** The function ''int(x)'', where ''x'' is a 32-byte array, returns the 256-bit unsigned integer whose most significant byte first encoding is ''x''. ** The function ''is_square(x)'', where ''x'' is an integer, returns whether or not ''x'' is a quadratic residue modulo ''p''. Since ''p'' is prime, it is equivalent to the Legendre symbol ''(x / p) = x(p-1)/2 mod p'' being equal to ''1'' (see [https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion])For points ''P'' on the secp256k1 curve it holds that ''x(p-1)/2 ≠ 0 mod p''.. ** The function ''has_square_y(P)'', where ''P'' is a point, is defined as ''not is_infinite(P) and is_square(y(P))''For points ''P'' on the secp256k1 curve it holds that ''has_square_y(P) = not has_square_y(-P)''.. -** The function ''lift_x(x)'', where ''x'' is an integer in range ''0..p-1'', returns the point ''P'' for which ''x(P) = x'' and ''has_square_y(P)'', or fails if no such point existsGiven an candidate X coordinate ''x'' in the range ''0..p-1'', there exist either exactly two or exactly zero valid Y coordinates. If no valid Y coordinate exists, then ''x'' is not a valid X coordinate either, i.e., no point ''P'' exists for which ''x(P) = x''. Given a candidate ''x'', the valid Y coordinates are the square roots of ''c = x3 + 7 mod p'' and they can be computed as ''y = ±c(p+1)/4 mod p'' (see [https://en.wikipedia.org/wiki/Quadratic_residue#Prime_or_prime_power_modulus Quadratic residue]) if they exist, which can be checked by squaring and comparing with ''c''. Due to [https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion] it then holds that ''c(p-1)/2 = 1 mod p''. The same criterion applied to ''y'' results in ''y(p-1)/2 mod p = ±c((p+1)/4)((p-1)/2) mod p = ±1 mod p''. Therefore ''y = +c(p+1)/4 mod p'' is a quadratic residue and ''-y mod p'' is not.. The function ''lift_x(x)'' is equivalent to the following pseudocode: +** The function ''lift_x(x)'', where ''x'' is an integer in range ''0..p-1'', returns the point ''P'' for which ''x(P) = x'' and ''has_square_y(P)'', or fails if no such point existsGiven a candidate X coordinate ''x'' in the range ''0..p-1'', there exist either exactly two or exactly zero valid Y coordinates. If no valid Y coordinate exists, then ''x'' is not a valid X coordinate either, i.e., no point ''P'' exists for which ''x(P) = x''. Given a candidate ''x'', the valid Y coordinates are the square roots of ''c = x3 + 7 mod p'' and they can be computed as ''y = ±c(p+1)/4 mod p'' (see [https://en.wikipedia.org/wiki/Quadratic_residue#Prime_or_prime_power_modulus Quadratic residue]) if they exist, which can be checked by squaring and comparing with ''c''. Due to [https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion] it then holds that ''c(p-1)/2 = 1 mod p''. The same criterion applied to ''y'' results in ''y(p-1)/2 mod p = ±c((p+1)/4)((p-1)/2) mod p = ±1 mod p''. Therefore ''y = +c(p+1)/4 mod p'' is a quadratic residue and ''-y mod p'' is not.. The function ''lift_x(x)'' is equivalent to the following pseudocode: *** Let ''c = x3 + 7 mod p''. *** Let ''y = c(p+1)/4 mod p''. *** Fail if ''c ≠ y2 mod p''. @@ -159,7 +159,7 @@ It should be noted that various alternative signing algorithms can be used to pr '''Nonce exfiltration protection''' It is possible to strengthen the nonce generation algorithm using a second device. In this case, the second device contributes randomness which the actual signer provably incorporates into its nonce. This prevents certain attacks where the signer device is compromised and intentionally tries to leak the private key through its nonce selection. -'''Multisignatures''' This signature scheme is compatible with various types of multisignature and threshold schemes such as [https://eprint.iacr.org/2018/068 MuSig], where a single public key requires holders of multiple private keys to participate in signing (see Applications below). +'''Multisignatures''' This signature scheme is compatible with various types of multisignature and threshold schemes such as [https://eprint.iacr.org/2018/068 MuSig], where a single public key requires holders of multiple private keys to participate in signing (see Applications below). '''It is important to note that multisignature signing schemes in general are insecure with the nonce generation from the default signing algorithm above (or any deterministic nonce algorithm).''' ==== Verification ==== -- cgit v1.2.3 From 8ca122e8febdc4918cebf3dcd0f2b7e2f7ec7d26 Mon Sep 17 00:00:00 2001 From: Orfeas Stefanos Thyfronitis Litos Date: Mon, 25 Nov 2019 12:25:19 +0000 Subject: Rephrase "previous design choice" to "list above" --- bip-schnorr.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 5e4bd47..fa57cdc 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -77,7 +77,7 @@ Using the first option would be slightly more efficient for verification (around In the case of ''R'' the third option is slower at signing time but a bit faster to verify, as it is possible to directly compute whether the Y coordinate is a square when the points are represented in [https://en.wikibooks.org/wiki/Cryptography/Prime_Curve/Jacobian_Coordinates Jacobian coordinates] (a common optimization to avoid modular inverses for elliptic curve operations). The two other options require a possibly -expensive conversion to affine coordinates first. This would even be the case if the sign or oddness were explicitly coded (option 2 in the previous design choice). We therefore choose option 3. +expensive conversion to affine coordinates first. This would even be the case if the sign or oddness were explicitly coded (option 2 in the list above). We therefore choose option 3. For ''P'' the speed of signing and verification does not significantly differ between any of the three options because affine coordinates of the point have to be computed anyway. For consistency reasons we choose the same option as for ''R''. The signing algorithm ensures that the signature is valid under the correct public key by negating the secret key if necessary. -- cgit v1.2.3 From 75d753868c4e4124eb91a018e0d4388fb90d3c91 Mon Sep 17 00:00:00 2001 From: Orfeas Stefanos Thyfronitis Litos Date: Mon, 25 Nov 2019 16:25:24 +0000 Subject: Typo: max bytes hashed for sig is 210 --- bip-taproot.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 1119785..8137c92 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -142,7 +142,7 @@ As the message for signature verification, transaction digest is ''hashTapS ** If the SIGHASH_SINGLE flag is set: *** sha_single_output (32): the SHA256 of the corresponding output in CTxOut format. -The total number of bytes hashed is at most ''211'' (excluding sub-hashes such as `sha_prevouts`)'''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''178 - is_anyonecanpay * 52 - is_none * 32 + has_annex * 32''.. Sub-hashes may be cached across signatures of the same transaction. +The total number of bytes hashed is at most ''210'' (excluding sub-hashes such as `sha_prevouts`)'''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''178 - is_anyonecanpay * 52 - is_none * 32 + has_annex * 32''.. Sub-hashes may be cached across signatures of the same transaction. In summary, the semantics of the [https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki BIP143] sighash types remain unchanged, except the following: # The way and order of serialization is changed.'''Why is the serialization in the transaction digest changed?''' Hashes that go into the digest and the digest itself are now computed with a single SHA256 invocation instead of double SHA256. There is no expected security improvement by doubling SHA256 because this only protects against length-extension attacks against SHA256 which are not a concern for transaction digests because there is no secret data. Therefore doubling SHA256 is a waste of resources. The digest computation now follows a logical order with transaction level data first, then input data and output data. This allows to efficiently cache the transaction part of the digest across different inputs using the SHA256 midstate. Additionally, digest computation avoids unnecessary hashing as opposed to BIP143 digests in which parts may be set zero and before hashing them. Despite that, collisions are made impossible by committing to the length of the data (implicit in hash_type and spend_type) before the variable length data. -- cgit v1.2.3 From 1e1795de46b016a4a27de95b50c924b6bd44aeed Mon Sep 17 00:00:00 2001 From: Orfeas Stefanos Thyfronitis Litos Date: Mon, 25 Nov 2019 16:43:05 +0000 Subject: Replace signing with signature before validation --- bip-tapscript.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index c80433d..6206ef8 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -89,7 +89,7 @@ The following rules apply to OP_CHECKSIG, OP_CHECKSIGVERIFYn is larger than 4 bytes, the script MUST fail and terminate immediately. * If the public key size is zero, the script MUST fail and terminate immediately. * If the public key size is 32 bytes, it is considered to be a public key as described in bip-schnorr: -** If the signature is not the empty vector, the signature is validated according to the bip-taproot signing validation rules against the public key and the tapscript transaction digest (to be defined hereinafter) as message. Validation failure MUST cause the script to fail and terminate immediately. +** If the signature is not the empty vector, the signature is validated according to the bip-taproot signature validation rules against the public key and the tapscript transaction digest (to be defined hereinafter) as message. Validation failure MUST cause the script to fail and terminate immediately. * If the public key size is not zero and not 32 bytes, the public key is of an ''unknown public key type'''''Unknown public key types''' allow adding new signature validation rules through softforks. A softfork could add actual signature validation which either passes or makes the script fail and terminate immediately. This way, new SIGHASH modes can be added, as well as [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-December/016549.html NOINPUT-tagged public keys] and a public key constant which is replaced by the taproot internal key for signature validation. and no actual signature verification is applied. During script execution of signature opcodes they behave exactly as known public key types except that signature validation is considered to be successful. * If the script did not fail and terminate before this step, regardless of the public key type: ** If the signature is the empty vector: -- cgit v1.2.3 From 633b52fbc0271f5fbf7b92498aa09d0529fe9165 Mon Sep 17 00:00:00 2001 From: Orfeas Stefanos Thyfronitis Litos Date: Mon, 25 Nov 2019 16:50:11 +0000 Subject: Typo: script signature max bytes unhashed are 247 --- bip-tapscript.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index c80433d..0d81445 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -115,7 +115,7 @@ As additional pieces of data, added at the end of the input to the ''hashTa * key_version (1): a constant value 0x00 representing the current version of public keys in the tapscript signature opcode execution. * codeseparator_position (4): the opcode position of the last executed OP_CODESEPARATOR before the currently executed signature opcode, with the value in little endian (or 0xffffffff if none executed). The first opcode in a script has a position of 0. A multi-byte push opcode is counted as one opcode, regardless of the size of data being pushed. -The total number of bytes hashed is at most ''248'''''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''215 - is_anyonecanpay * 52 - is_none * 32 + has_annex * 32''.. +The total number of bytes hashed is at most ''247'''''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''215 - is_anyonecanpay * 52 - is_none * 32 + has_annex * 32''.. In summary, the semantics of the [https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki BIP143] sighash types remain unchanged, except the following: # The exceptions mentioned in bip-taproot. -- cgit v1.2.3 From 7ec4ce9a8d2b8bf25249b9d372dedac049586e2a Mon Sep 17 00:00:00 2001 From: Orfeas Litos Date: Tue, 26 Nov 2019 12:39:34 +0000 Subject: Replace "both are not" with "neither is" --- bip-taproot.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 1119785..7197c2d 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -123,7 +123,7 @@ As the message for signature verification, transaction digest is ''hashTapS *** sha_prevouts (32): the SHA256 of the serialization of all input outpoints. *** sha_amounts (32): the SHA256 of the serialization of all input amounts. *** sha_sequences (32): the SHA256 of the serialization of all input nSequence. -** If both the SIGHASH_NONE and SIGHASH_SINGLE flags are not set: +** If neither the SIGHASH_NONE nor the SIGHASH_SINGLE flag is set: *** sha_outputs (32): the SHA256 of the serialization of all outputs in CTxOut format. * Data about this input: ** spend_type (1): -- cgit v1.2.3 From b44d5c95311c017c0829f1febc9c2c44a620085b Mon Sep 17 00:00:00 2001 From: Orfeas Litos Date: Tue, 26 Nov 2019 12:43:34 +0000 Subject: Mention hash_type malleability would change wtxid --- bip-taproot.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 1119785..cffbfbb 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -93,7 +93,7 @@ The following rules apply: * If the signature is not 64'''Why permit two signature lengths?''' By making the most common type of hash_type implicit, a byte can often be saved. or 65 bytes, fail. * If the signature size is 65 bytes: ** If the final byte is not a valid hash_type (defined hereinafter), fail. -** If the final byte is 0x00, fail'''Why can the hash_type not be 0x00 in 65-byte signatures?''' Permitting that would enable malleating 64-byte signatures into 65-byte ones, resulting a different fee rate than the creator intended. +** If the final byte is 0x00, fail'''Why can the hash_type not be 0x00 in 65-byte signatures?''' Permitting that would enable malleating 64-byte signatures into 65-byte ones, resulting in a different `wtxid` and a different fee rate than the creator intended. ** If the first 64 bytes are not a valid signature according to bip-schnorr for the public key and message set to the transaction digest with hash_type set as the final byte, fail. * If the signature size is 64 bytes: ** If it is not a valid signature according to bip-schnorr for the public key and the hash_type = 0x00 transaction digest as message, fail. -- cgit v1.2.3 From 2e79be9f72cf3253bbfe4cb362287079c1af1429 Mon Sep 17 00:00:00 2001 From: Orfeas Stefanos Thyfronitis Litos Date: Tue, 26 Nov 2019 15:30:12 +0000 Subject: Mention that miners could malleate signatures --- bip-taproot.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index cffbfbb..1b9f831 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -93,7 +93,7 @@ The following rules apply: * If the signature is not 64'''Why permit two signature lengths?''' By making the most common type of hash_type implicit, a byte can often be saved. or 65 bytes, fail. * If the signature size is 65 bytes: ** If the final byte is not a valid hash_type (defined hereinafter), fail. -** If the final byte is 0x00, fail'''Why can the hash_type not be 0x00 in 65-byte signatures?''' Permitting that would enable malleating 64-byte signatures into 65-byte ones, resulting in a different `wtxid` and a different fee rate than the creator intended. +** If the final byte is 0x00, fail'''Why can the hash_type not be 0x00 in 65-byte signatures?''' Permitting that would enable malleating (by third parties, including miners) 64-byte signatures into 65-byte ones, resulting in a different `wtxid` and a different fee rate than the creator intended. ** If the first 64 bytes are not a valid signature according to bip-schnorr for the public key and message set to the transaction digest with hash_type set as the final byte, fail. * If the signature size is 64 bytes: ** If it is not a valid signature according to bip-schnorr for the public key and the hash_type = 0x00 transaction digest as message, fail. -- cgit v1.2.3 From 83e886ce07d3a6cbce1189dbda995209e7620745 Mon Sep 17 00:00:00 2001 From: andrewtoth Date: Fri, 29 Nov 2019 03:57:00 +0000 Subject: Add missing closing parenthesis and comma --- bip-tapscript.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index c80433d..450e63c 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -127,7 +127,7 @@ In summary, the semantics of the [https://github.com/bitcoin/bips/blob/master/bi In addition to changing the semantics of a number of opcodes, there are also some changes to the resource limitations: * '''Script size limit''' The maximum script size of 10000 bytes does not apply. Their size is only implicitly limited by the limits on transaction and block size.'''Why is a limit on script size no longer needed?''' Since there is no scriptCode directly included in the signature hash (only indirectly through a precomputable tapleaf hash), the CPU time spent on a signature check is no longer proportional to the size of the script being executed. -* '''Non-push opcodes limit''' The maximum non-push opcodes limit of 201 per script does not apply.'''Why is a limit on the number of opcodes no longer needed?''' An opcode limit only helps to the extent that it can prevent data structures from growing unboundedly during execution (both because of memory usage, and because of time that may grow in proportion to the size of those structures. The size of stack and altstack is already independently limited. Using O(1) logic for OP_IF, OP_NOTIF, OP_ELSE, and OP_ENDIF like suggested [https://bitslog.com/2017/04/17/new-quadratic-delays-in-bitcoin-scripts/ here] and implemented [https://github.com/bitcoin/bitcoin/pull/16902 here] the only other instance can be avoided as well. +* '''Non-push opcodes limit''' The maximum non-push opcodes limit of 201 per script does not apply.'''Why is a limit on the number of opcodes no longer needed?''' An opcode limit only helps to the extent that it can prevent data structures from growing unboundedly during execution (both because of memory usage, and because of time that may grow in proportion to the size of those structures). The size of stack and altstack is already independently limited. Using O(1) logic for OP_IF, OP_NOTIF, OP_ELSE, and OP_ENDIF as suggested [https://bitslog.com/2017/04/17/new-quadratic-delays-in-bitcoin-scripts/ here] and implemented [https://github.com/bitcoin/bitcoin/pull/16902 here], the only other instance can be avoided as well. * '''Sigops limit''' The sigops in tapscripts do not count towards the block-wide limit of 80000 (weighted). Instead, there is a per-script sigops ''budget''. The budget equals 50 + the total serialized size in bytes of the transaction input's witness (including the CCompactSize prefix). Executing a signature opcode (OP_CHECKSIG, OP_CHECKSIGVERIFY, or OP_CHECKSIGADD) with a non-empty signature decrements the budget by 50. If that brings the budget below zero, the script fails immediately. Signature opcodes with unknown public key type and non-empty signature are also counted.'''The tapscript sigop limit''' The signature opcode limit protects against scripts which are slow to verify due to excessively many signature operations. In tapscript the number of signature opcodes does not count towards the BIP141 or legacy sigop limit. The old sigop limit makes transaction selection in block construction unnecessarily difficult because it is a second constraint in addition to weight. Instead, the number of tapscript signature opcodes is limited by witness weight. Additionally, the limit applies to the transaction input instead of the block and only actually executed signature opcodes are counted. Tapscript execution allows one signature opcode per 50 witness weight units plus one free signature opcode.'''Parameter choice of the sigop limit''' Regular witnesses are unaffected by the limit as their weight is composed of public key and (SIGHASH_ALL) signature pairs with ''33 + 65'' weight units each (which includes a 1 weight unit CCompactSize tag). This is also the case if public keys are reused in the script because a signature's weight alone is 65 or 66 weight units. However, the limit increases the fees of abnormal scripts with duplicate signatures (and public keys) by requiring additional weight. The weight per sigop factor 50 corresponds to the ratio of BIP141 block limits: 4 mega weight units divided by 80,000 sigops. The "free" signature opcode permitted by the limit exists to account for the weight of the non-witness parts of the transaction input.'''Why are only signature opcodes counted toward the budget, and not for example hashing opcodes or other expensive operations?''' It turns out that the CPU cost per witness byte for verification of a script consisting of the maximum density of signature checking opcodes (taking the 50 WU/sigop limit into account) is already very close to that of scripts packed with other opcodes, including hashing opcodes (taking the 520 byte stack element limit into account) and OP_ROLL (taking the 1000 stack element limit into account). That said, the construction is very flexible, and allows adding new signature opcodes like CHECKSIGFROMSTACK to count towards the limit through a soft fork. Even if in the future new opcodes are introduced which change normal script cost there is no need to stuff the witness with meaningless data. Instead, the taproot annex can be used to add weight to the witness without increasing the actual witness size.. * '''Stack + altstack element count limit''' The existing limit of 1000 elements in the stack and altstack together after every executed opcode remains. It is extended to also apply to the size of initial stack. * '''Stack element size limit''' The existing limit of maximum 520 bytes per stack element remains, both in the initial stack and in push opcodes. -- cgit v1.2.3 From 6a72458bf95f3800feb7d7e8a924e5a286c02152 Mon Sep 17 00:00:00 2001 From: andrewtoth Date: Fri, 29 Nov 2019 04:01:53 +0000 Subject: Update bip-tapscript.mediawiki --- bip-tapscript.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index 450e63c..4336f9c 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -127,7 +127,7 @@ In summary, the semantics of the [https://github.com/bitcoin/bips/blob/master/bi In addition to changing the semantics of a number of opcodes, there are also some changes to the resource limitations: * '''Script size limit''' The maximum script size of 10000 bytes does not apply. Their size is only implicitly limited by the limits on transaction and block size.'''Why is a limit on script size no longer needed?''' Since there is no scriptCode directly included in the signature hash (only indirectly through a precomputable tapleaf hash), the CPU time spent on a signature check is no longer proportional to the size of the script being executed. -* '''Non-push opcodes limit''' The maximum non-push opcodes limit of 201 per script does not apply.'''Why is a limit on the number of opcodes no longer needed?''' An opcode limit only helps to the extent that it can prevent data structures from growing unboundedly during execution (both because of memory usage, and because of time that may grow in proportion to the size of those structures). The size of stack and altstack is already independently limited. Using O(1) logic for OP_IF, OP_NOTIF, OP_ELSE, and OP_ENDIF as suggested [https://bitslog.com/2017/04/17/new-quadratic-delays-in-bitcoin-scripts/ here] and implemented [https://github.com/bitcoin/bitcoin/pull/16902 here], the only other instance can be avoided as well. +* '''Non-push opcodes limit''' The maximum non-push opcodes limit of 201 per script does not apply.'''Why is a limit on the number of opcodes no longer needed?''' An opcode limit only helps to the extent that it can prevent data structures from growing unboundedly during execution (both because of memory usage, and because of time that may grow in proportion to the size of those structures). The size of stack and altstack is already independently limited. By using O(1) logic for OP_IF, OP_NOTIF, OP_ELSE, and OP_ENDIF as suggested [https://bitslog.com/2017/04/17/new-quadratic-delays-in-bitcoin-scripts/ here] and implemented [https://github.com/bitcoin/bitcoin/pull/16902 here], the only other instance can be avoided as well. * '''Sigops limit''' The sigops in tapscripts do not count towards the block-wide limit of 80000 (weighted). Instead, there is a per-script sigops ''budget''. The budget equals 50 + the total serialized size in bytes of the transaction input's witness (including the CCompactSize prefix). Executing a signature opcode (OP_CHECKSIG, OP_CHECKSIGVERIFY, or OP_CHECKSIGADD) with a non-empty signature decrements the budget by 50. If that brings the budget below zero, the script fails immediately. Signature opcodes with unknown public key type and non-empty signature are also counted.'''The tapscript sigop limit''' The signature opcode limit protects against scripts which are slow to verify due to excessively many signature operations. In tapscript the number of signature opcodes does not count towards the BIP141 or legacy sigop limit. The old sigop limit makes transaction selection in block construction unnecessarily difficult because it is a second constraint in addition to weight. Instead, the number of tapscript signature opcodes is limited by witness weight. Additionally, the limit applies to the transaction input instead of the block and only actually executed signature opcodes are counted. Tapscript execution allows one signature opcode per 50 witness weight units plus one free signature opcode.'''Parameter choice of the sigop limit''' Regular witnesses are unaffected by the limit as their weight is composed of public key and (SIGHASH_ALL) signature pairs with ''33 + 65'' weight units each (which includes a 1 weight unit CCompactSize tag). This is also the case if public keys are reused in the script because a signature's weight alone is 65 or 66 weight units. However, the limit increases the fees of abnormal scripts with duplicate signatures (and public keys) by requiring additional weight. The weight per sigop factor 50 corresponds to the ratio of BIP141 block limits: 4 mega weight units divided by 80,000 sigops. The "free" signature opcode permitted by the limit exists to account for the weight of the non-witness parts of the transaction input.'''Why are only signature opcodes counted toward the budget, and not for example hashing opcodes or other expensive operations?''' It turns out that the CPU cost per witness byte for verification of a script consisting of the maximum density of signature checking opcodes (taking the 50 WU/sigop limit into account) is already very close to that of scripts packed with other opcodes, including hashing opcodes (taking the 520 byte stack element limit into account) and OP_ROLL (taking the 1000 stack element limit into account). That said, the construction is very flexible, and allows adding new signature opcodes like CHECKSIGFROMSTACK to count towards the limit through a soft fork. Even if in the future new opcodes are introduced which change normal script cost there is no need to stuff the witness with meaningless data. Instead, the taproot annex can be used to add weight to the witness without increasing the actual witness size.. * '''Stack + altstack element count limit''' The existing limit of 1000 elements in the stack and altstack together after every executed opcode remains. It is extended to also apply to the size of initial stack. * '''Stack element size limit''' The existing limit of maximum 520 bytes per stack element remains, both in the initial stack and in push opcodes. -- cgit v1.2.3 From 3acb1508292b791115fab954c599a4e5b41c1878 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Fri, 29 Nov 2019 15:42:46 +0000 Subject: Fix bip-schnorr footnote 7 by specifying that we're referring to P's y coordinate and not some undefined 'x' --- bip-schnorr.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index c71449a..297c3a0 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -109,7 +109,7 @@ The following conventions are used, with constants as defined for [https://www.s ** The function ''bytes(x)'', where ''x'' is an integer, returns the 32-byte encoding of ''x'', most significant byte first. ** The function ''bytes(P)'', where ''P'' is a point, returns ''bytes(x(P))''. ** The function ''int(x)'', where ''x'' is a 32-byte array, returns the 256-bit unsigned integer whose most significant byte first encoding is ''x''. -** The function ''is_square(x)'', where ''x'' is an integer, returns whether or not ''x'' is a quadratic residue modulo ''p''. Since ''p'' is prime, it is equivalent to the Legendre symbol ''(x / p) = x(p-1)/2 mod p'' being equal to ''1'' (see [https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion])For points ''P'' on the secp256k1 curve it holds that ''x(p-1)/2 ≠ 0 mod p''.. +** The function ''is_square(x)'', where ''x'' is an integer, returns whether or not ''x'' is a quadratic residue modulo ''p''. Since ''p'' is prime, it is equivalent to the Legendre symbol ''(x / p) = x(p-1)/2 mod p'' being equal to ''1'' (see [https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion])For points ''P'' on the secp256k1 curve it holds that ''y(P)(p-1)/2 ≠ 0 mod p''.. ** The function ''has_square_y(P)'', where ''P'' is a point, is defined as ''not is_infinite(P) and is_square(y(P))''For points ''P'' on the secp256k1 curve it holds that ''has_square_y(P) = not has_square_y(-P)''.. ** The function ''lift_x(x)'', where ''x'' is an integer in range ''0..p-1'', returns the point ''P'' for which ''x(P) = x'' and ''has_square_y(P)'', or fails if no such point existsGiven a candidate X coordinate ''x'' in the range ''0..p-1'', there exist either exactly two or exactly zero valid Y coordinates. If no valid Y coordinate exists, then ''x'' is not a valid X coordinate either, i.e., no point ''P'' exists for which ''x(P) = x''. Given a candidate ''x'', the valid Y coordinates are the square roots of ''c = x3 + 7 mod p'' and they can be computed as ''y = ±c(p+1)/4 mod p'' (see [https://en.wikipedia.org/wiki/Quadratic_residue#Prime_or_prime_power_modulus Quadratic residue]) if they exist, which can be checked by squaring and comparing with ''c''. Due to [https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion] it then holds that ''c(p-1)/2 = 1 mod p''. The same criterion applied to ''y'' results in ''y(p-1)/2 mod p = ±c((p+1)/4)((p-1)/2) mod p = ±1 mod p''. Therefore ''y = +c(p+1)/4 mod p'' is a quadratic residue and ''-y mod p'' is not.. The function ''lift_x(x)'' is equivalent to the following pseudocode: *** Let ''c = x3 + 7 mod p''. -- cgit v1.2.3 From 382a1d19a0fa299d599f1d4e504f95282e2ab244 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Fri, 29 Nov 2019 15:47:33 +0000 Subject: Replace references to Euler's criterion with Legendre symbol in bip-schnorr --- bip-schnorr.mediawiki | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 297c3a0..b816ecd 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -109,9 +109,9 @@ The following conventions are used, with constants as defined for [https://www.s ** The function ''bytes(x)'', where ''x'' is an integer, returns the 32-byte encoding of ''x'', most significant byte first. ** The function ''bytes(P)'', where ''P'' is a point, returns ''bytes(x(P))''. ** The function ''int(x)'', where ''x'' is a 32-byte array, returns the 256-bit unsigned integer whose most significant byte first encoding is ''x''. -** The function ''is_square(x)'', where ''x'' is an integer, returns whether or not ''x'' is a quadratic residue modulo ''p''. Since ''p'' is prime, it is equivalent to the Legendre symbol ''(x / p) = x(p-1)/2 mod p'' being equal to ''1'' (see [https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion])For points ''P'' on the secp256k1 curve it holds that ''y(P)(p-1)/2 ≠ 0 mod p''.. +** The function ''is_square(x)'', where ''x'' is an integer, returns whether or not ''x'' is a quadratic residue modulo ''p''. Since ''p'' is prime, it is equivalent to the [https://en.wikipedia.org/wiki/Legendre_symbol Legendre symbol] ''(x / p) = x(p-1)/2 mod p'' being equal to ''1''For points ''P'' on the secp256k1 curve it holds that ''y(P)(p-1)/2 ≠ 0 mod p''.. ** The function ''has_square_y(P)'', where ''P'' is a point, is defined as ''not is_infinite(P) and is_square(y(P))''For points ''P'' on the secp256k1 curve it holds that ''has_square_y(P) = not has_square_y(-P)''.. -** The function ''lift_x(x)'', where ''x'' is an integer in range ''0..p-1'', returns the point ''P'' for which ''x(P) = x'' and ''has_square_y(P)'', or fails if no such point existsGiven a candidate X coordinate ''x'' in the range ''0..p-1'', there exist either exactly two or exactly zero valid Y coordinates. If no valid Y coordinate exists, then ''x'' is not a valid X coordinate either, i.e., no point ''P'' exists for which ''x(P) = x''. Given a candidate ''x'', the valid Y coordinates are the square roots of ''c = x3 + 7 mod p'' and they can be computed as ''y = ±c(p+1)/4 mod p'' (see [https://en.wikipedia.org/wiki/Quadratic_residue#Prime_or_prime_power_modulus Quadratic residue]) if they exist, which can be checked by squaring and comparing with ''c''. Due to [https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion] it then holds that ''c(p-1)/2 = 1 mod p''. The same criterion applied to ''y'' results in ''y(p-1)/2 mod p = ±c((p+1)/4)((p-1)/2) mod p = ±1 mod p''. Therefore ''y = +c(p+1)/4 mod p'' is a quadratic residue and ''-y mod p'' is not.. The function ''lift_x(x)'' is equivalent to the following pseudocode: +** The function ''lift_x(x)'', where ''x'' is an integer in range ''0..p-1'', returns the point ''P'' for which ''x(P) = x'' and ''has_square_y(P)'', or fails if no such point existsGiven a candidate X coordinate ''x'' in the range ''0..p-1'', there exist either exactly two or exactly zero valid Y coordinates. If no valid Y coordinate exists, then ''x'' is not a valid X coordinate either, i.e., no point ''P'' exists for which ''x(P) = x''. Given a candidate ''x'', the valid Y coordinates are the square roots of ''c = x3 + 7 mod p'' and they can be computed as ''y = ±c(p+1)/4 mod p'' (see [https://en.wikipedia.org/wiki/Quadratic_residue#Prime_or_prime_power_modulus Quadratic residue]) if they exist, which can be checked by squaring and comparing with ''c''. The [https://en.wikipedia.org/wiki/Legendre_symbol Legendre symbol] ''( c / p)'' is ''c(p-1)/2 = 1 mod p''. The Legendre symbol ''( y / p )'' is ''y(p-1)/2 mod p = ±c((p+1)/4)((p-1)/2) mod p = ±1 mod p''. Therefore ''y = +c(p+1)/4 mod p'' is a quadratic residue and ''-y mod p'' is not.. The function ''lift_x(x)'' is equivalent to the following pseudocode: *** Let ''c = x3 + 7 mod p''. *** Let ''y = c(p+1)/4 mod p''. *** Fail if ''c ≠ y2 mod p''. -- cgit v1.2.3 From 2c6b472e9cc81346145adbaca95e14fc4b12807a Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Fri, 29 Nov 2019 16:32:44 +0000 Subject: Clarify bip-taproot digest difference to bip143 regarding sub-hashes --- bip-taproot.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index a8106fc..fb86fa6 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -145,7 +145,7 @@ As the message for signature verification, transaction digest is ''hashTapS The total number of bytes hashed is at most ''211'' (excluding sub-hashes such as `sha_prevouts`)'''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''178 - is_anyonecanpay * 52 - is_none * 32 + has_annex * 32''.. Sub-hashes may be cached across signatures of the same transaction. In summary, the semantics of the [https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki BIP143] sighash types remain unchanged, except the following: -# The way and order of serialization is changed.'''Why is the serialization in the transaction digest changed?''' Hashes that go into the digest and the digest itself are now computed with a single SHA256 invocation instead of double SHA256. There is no expected security improvement by doubling SHA256 because this only protects against length-extension attacks against SHA256 which are not a concern for transaction digests because there is no secret data. Therefore doubling SHA256 is a waste of resources. The digest computation now follows a logical order with transaction level data first, then input data and output data. This allows to efficiently cache the transaction part of the digest across different inputs using the SHA256 midstate. Additionally, digest computation avoids unnecessary hashing as opposed to BIP143 digests in which parts may be set zero and before hashing them. Despite that, collisions are made impossible by committing to the length of the data (implicit in hash_type and spend_type) before the variable length data. +# The way and order of serialization is changed.'''Why is the serialization in the transaction digest changed?''' Hashes that go into the digest and the digest itself are now computed with a single SHA256 invocation instead of double SHA256. There is no expected security improvement by doubling SHA256 because this only protects against length-extension attacks against SHA256 which are not a concern for transaction digests because there is no secret data. Therefore doubling SHA256 is a waste of resources. The digest computation now follows a logical order with transaction level data first, then input data and output data. This allows to efficiently cache the transaction part of the digest across different inputs using the SHA256 midstate. Additionally, sub-hashes can be skipped when calculating the digest (for example `sha_prevouts` if SIGHASH_ANYONECANPAY is set) instead of setting them to zero and then hashing them as in BIP143. Despite that, collisions are made impossible by committing to the length of the data (implicit in hash_type and spend_type) before the variable length data. # The digest commits to the scriptPubKey'''Why does the transaction digest commit to the scriptPubKey?''' This prevents lying to offline signing devices about output being spent, even when the actually executed script (scriptCode in BIP143) is correct. This means it's possible to compactly prove to a hardware wallet what (unused) execution paths existed.. # If the SIGHASH_ANYONECANPAY flag is not set, the digest commits to the amounts of ''all'' transaction inputs.'''Why does the transaction digest commit to the amounts of all transaction inputs?''' This eliminates the possibility to lie to offline signing devices about the fee of a transaction. # The digest commits to all input nSequence if SIGHASH_NONE or SIGHASH_SINGLE are set (unless SIGHASH_ANYONECANPAY is set as well).'''Why does the transaction digest commit to all input nSequence if SIGHASH_SINGLE or SIGHASH_NONE are set?''' Because setting them already makes the digest commit to the prevouts part of all transaction inputs, it is not useful to treat the nSequence any different. Moreover, this change makes nSequence consistent with the view that SIGHASH_SINGLE and SIGHASH_NONE only modify the digest with respect to transaction outputs and not inputs. -- cgit v1.2.3 From 93e1921d83781ae32c19674669dceb6a27311496 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Wed, 4 Dec 2019 19:26:06 +0000 Subject: Improve clarity of footnotes for lift_x --- bip-schnorr.mediawiki | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index b816ecd..5204dc6 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -72,7 +72,7 @@ Using the first option would be slightly more efficient for verification (around '''Implicit Y coordinates''' In order to support efficient verification and batch verification, the Y coordinate of ''P'' and of ''R'' cannot be ambiguous (every valid X coordinate has two possible Y coordinates). We have a choice between several options for symmetry breaking: # Implicitly choosing the Y coordinate that is in the lower half. # Implicitly choosing the Y coordinate that is evenSince ''p'' is odd, negation modulo ''p'' will map even numbers to odd numbers and the other way around. This means that for a valid X coordinate, one of the corresponding Y coordinates will be even, and the other will be odd.. -# Implicitly choosing the Y coordinate that is a quadratic residue (has a square root modulo the field size, or "is a square" for short)A product of two numbers is a square when either both or none of the factors are squares. As ''-1'' is not a square, and the two Y coordinates corresponding to a given X coordinate are each other's negation, this means exactly one of the two must be a square.. +# Implicitly choosing the Y coordinate that is a quadratic residue (has a square root modulo the field size, or "is a square" for short)A product of two numbers is a square when either both or none of the factors are squares. As ''-1'' is not a square modulo secp256k1's field size ''p'', and the two Y coordinates corresponding to a given X coordinate are each other's negation, this means exactly one of the two must be a square.. In the case of ''R'' the third option is slower at signing time but a bit faster to verify, as it is possible to directly compute whether the Y coordinate is a square when the points are represented in [https://en.wikibooks.org/wiki/Cryptography/Prime_Curve/Jacobian_Coordinates Jacobian coordinates] (a common optimization to avoid modular inverses @@ -111,7 +111,11 @@ The following conventions are used, with constants as defined for [https://www.s ** The function ''int(x)'', where ''x'' is a 32-byte array, returns the 256-bit unsigned integer whose most significant byte first encoding is ''x''. ** The function ''is_square(x)'', where ''x'' is an integer, returns whether or not ''x'' is a quadratic residue modulo ''p''. Since ''p'' is prime, it is equivalent to the [https://en.wikipedia.org/wiki/Legendre_symbol Legendre symbol] ''(x / p) = x(p-1)/2 mod p'' being equal to ''1''For points ''P'' on the secp256k1 curve it holds that ''y(P)(p-1)/2 ≠ 0 mod p''.. ** The function ''has_square_y(P)'', where ''P'' is a point, is defined as ''not is_infinite(P) and is_square(y(P))''For points ''P'' on the secp256k1 curve it holds that ''has_square_y(P) = not has_square_y(-P)''.. -** The function ''lift_x(x)'', where ''x'' is an integer in range ''0..p-1'', returns the point ''P'' for which ''x(P) = x'' and ''has_square_y(P)'', or fails if no such point existsGiven a candidate X coordinate ''x'' in the range ''0..p-1'', there exist either exactly two or exactly zero valid Y coordinates. If no valid Y coordinate exists, then ''x'' is not a valid X coordinate either, i.e., no point ''P'' exists for which ''x(P) = x''. Given a candidate ''x'', the valid Y coordinates are the square roots of ''c = x3 + 7 mod p'' and they can be computed as ''y = ±c(p+1)/4 mod p'' (see [https://en.wikipedia.org/wiki/Quadratic_residue#Prime_or_prime_power_modulus Quadratic residue]) if they exist, which can be checked by squaring and comparing with ''c''. The [https://en.wikipedia.org/wiki/Legendre_symbol Legendre symbol] ''( c / p)'' is ''c(p-1)/2 = 1 mod p''. The Legendre symbol ''( y / p )'' is ''y(p-1)/2 mod p = ±c((p+1)/4)((p-1)/2) mod p = ±1 mod p''. Therefore ''y = +c(p+1)/4 mod p'' is a quadratic residue and ''-y mod p'' is not.. The function ''lift_x(x)'' is equivalent to the following pseudocode: +** The function ''lift_x(x)'', where ''x'' is an integer in range ''0..p-1'', returns the point ''P'' for which ''x(P) = x'' + Given a candidate X coordinate ''x'' in the range ''0..p-1'', there exist either exactly two or exactly zero valid Y coordinates. If no valid Y coordinate exists, then ''x'' is not a valid X coordinate either, i.e., no point ''P'' exists for which ''x(P) = x''. The valid Y coordinates for a given candidate ''x'' are the square roots of ''c = x3 + 7 mod p'' and they can be computed as ''y = ±c(p+1)/4 mod p'' (see [https://en.wikipedia.org/wiki/Quadratic_residue#Prime_or_prime_power_modulus Quadratic residue]) if they exist, which can be checked by squaring and comparing with ''c''. + and ''has_square_y(P)'' + If ''P := lift_x(x)'' does not fail, then ''y := y(P) = c(p+1)/4 mod p'' is square. Proof: If ''lift_x'' does not fail, ''y'' is a square root of ''c'' and therefore the [https://en.wikipedia.org/wiki/Legendre_symbol Legendre symbol] ''(c / p)'' is ''c(p-1)/2 = 1 mod p''. Because the Legendre symbol ''(y / p)'' is ''y(p-1)/2 mod p = c((p+1)/4)((p-1)/2) mod p = 1((p+1)/4) mod p = 1 mod p'', ''y'' is square. +, or fails if no such point exists. The function ''lift_x(x)'' is equivalent to the following pseudocode: *** Let ''c = x3 + 7 mod p''. *** Let ''y = c(p+1)/4 mod p''. *** Fail if ''c ≠ y2 mod p''. -- cgit v1.2.3 From adf4d78e6c4bed77cb5c7ff178403c6ec7693958 Mon Sep 17 00:00:00 2001 From: Kalle Rosenbaum Date: Mon, 9 Dec 2019 21:20:40 +0100 Subject: Nits --- bip-schnorr.mediawiki | 2 +- bip-taproot.mediawiki | 8 ++++---- bip-tapscript.mediawiki | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index c71449a..0697902 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -36,7 +36,7 @@ made: * '''Signature encoding''': Instead of using [https://en.wikipedia.org/wiki/X.690#DER_encoding DER]-encoding for signatures (which are variable size, and up to 72 bytes), we can use a simple fixed 64-byte format. * '''Public key encoding''': Instead of using ''compressed'' 33-byte encodings of elliptic curve points which are common in Bitcoin today, public keys in this proposal are encoded as 32 bytes. -* '''Batch verification''': The specific formulation of ECDSA signatures that is standardized cannot be verified more efficiently in batch compared to individually, unless additional witness data is added. Changing the signature scheme offers an opportunity to avoid this. +* '''Batch verification''': The specific formulation of ECDSA signatures that is standardized cannot be verified more efficiently in batch compared to individually, unless additional witness data is added. Changing the signature scheme offers an opportunity to address this. By reusing the same curve as Bitcoin uses for ECDSA, we are able to retain existing mechanisms for choosing secret and public keys, and we avoid introducing new assumptions about elliptic curve group security. diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index ea198fc..7f2f443 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -30,7 +30,7 @@ Combining all these ideas in a single proposal would be an extensive change, be ==Design== -This proposal focuses on improvements to privacy, efficiency, and flexibility of Bitcoin's smart contracts, subject to two restrictions: +This proposal focuses on improvements to privacy, efficiency, and flexibility of Bitcoin's scripting capabilities, subject to two restrictions: * Not adding any new strong security assumptions * Not combining into the proposal any functionality which could be simply implemented independently. @@ -39,11 +39,11 @@ Specifically, it seeks to minimize how much information about the spendability c As a result we choose this combination of technologies: * '''Merkle branches''' let us only reveal the actually executed part of the script to the blockchain, as opposed to all possible ways a script can be executed. Among the various known mechanisms for implementing this, one where the Merkle tree becomes part of the script's structure directly maximizes the space savings, so that approach is chosen. * '''Taproot''' on top of that lets us merge the traditionally separate pay-to-pubkey and pay-to-scripthash policies, making all outputs spendable by either a key or (optionally) a script, and indistinguishable from each other. As long as the key-based spending path is used for spending, it is not revealed whether a script path was permitted as well, resulting in space savings and an increase in scripting privacy at spending time. -* Taproot's advantages become apparent under the assumption that most applications involve outputs that could be spent by all parties agreeing. That's where '''Schnorr''' signatures come in, as they permit [https://eprint.iacr.org/2018/068 key aggregation]: a public key can be constructed from multiple participant public keys, and which requires cooperation between all participants to sign for. Such multi-party public keys and signatures are indistinguishable from their single-party equivalents. This means that under this Taproot assumption, the all-parties-agree case can be handled using the key-based spending path, which is both private and efficient using Taproot. This can be generalized to arbitrary M-of-N policies, as Schnorr signatures support threshold signing, at the cost of more complex setup protocols. +* Taproot's advantages become apparent under the assumption that most applications involve outputs that could be spent by all parties agreeing. That's where '''Schnorr''' signatures come in, as they permit [https://eprint.iacr.org/2018/068 key aggregation]: a public key can be constructed from multiple participant public keys, and which requires cooperation between all participants to sign for. Such multi-party public keys and signatures are indistinguishable from their single-party equivalents. This means that the all-parties-agree case can be handled using the key-based spending path, which is efficient and (under the Taproot assumption) private using taproot. This can be generalized to arbitrary M-of-N policies, as Schnorr signatures support threshold signing, at the cost of more complex setup protocols. * As Schnorr signatures also permit '''batch validation''', allowing multiple signatures to be validated together more efficiently than validating each one independently, we make sure all parts of the design are compatible with this. * Where unused bits appear as a result of the above changes, they are reserved for mechanisms for '''future extensions'''. As a result, every script in the Merkle tree has an associated version such that new script versions can be introduced with a soft fork while remaining compatible with bip-taproot. Additionally, future soft forks can make use of the currently unused annex in the witness (see [[#Rationale]]). * While the core semantics of the '''signature hashing algorithm''' are not changed, a number of improvements are included in this proposal. The new signature hashing algorithm fixes the verification capabilities of offline signing devices by including amount and scriptPubKey in the digest, avoids unnecessary hashing, uses '''tagged hashes''' and defines a default sighash byte. -* The '''public key is directly included in the output''' in contrast to typical earlier constructions which store a hash of the public key or script in the output. This has the same cost for senders and is more space efficient overall if the key-based spending path is taken. '''Why is the public key directly included in the output?''' While typical earlier constructions store a hash of a script or a public key in the output, this is rather wasteful when a public key is always involved. To guarantee batch verifiability, ''q'' must be known to every verifier, and thus only revealing its hash as an output would imply adding an additional 32 bytes to the witness. Furthermore, to maintain [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2016-January/012198.html 128-bit collision security] for outputs, a 256-bit hash would be required anyway, which is comparable in size (and thus in cost for senders) to revealing the public key directly. While the usage of public key hashes is often said to protect against ECDLP breaks or quantum computers, this protection is very weak at best: transactions are not protected while being confirmed, and a very [https://twitter.com/pwuille/status/1108097835365339136 large portion] of the currency's supply is not under such protection regardless. Actual resistance to such systems can be introduced by relying on different cryptographic assumptions, but this proposal focuses on improvements that do not change the security model. +* The '''public key is directly included in the output''' in contrast to typical earlier constructions which store a hash of the public key or script in the output. This has the same cost for senders and is more space efficient overall if the key-based spending path is taken. '''Why is the public key directly included in the output?''' While typical earlier constructions store a hash of a script or a public key in the output, this is rather wasteful when a public key is always involved. To guarantee batch verifiability, the public key must be known to every verifier, and thus only revealing its hash as an output would imply adding an additional 32 bytes to the witness. Furthermore, to maintain [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2016-January/012198.html 128-bit collision security] for outputs, a 256-bit hash would be required anyway, which is comparable in size (and thus in cost for senders) to revealing the public key directly. While the usage of public key hashes is often said to protect against ECDLP breaks or quantum computers, this protection is very weak at best: transactions are not protected while being confirmed, and a very [https://twitter.com/pwuille/status/1108097835365339136 large portion] of the currency's supply is not under such protection regardless. Actual resistance to such systems can be introduced by relying on different cryptographic assumptions, but this proposal focuses on improvements that do not change the security model. Not included in this proposal are additional features like new sighash modes or opcodes that can be included with no loss in effectiveness as a future extension. Also not included is cross-input aggregation, as it [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-March/015838.html interacts] in complex ways with upgrade mechanisms and solutions to that are still [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-October/016461.html in flux]. @@ -114,7 +114,7 @@ The following use of hash_type are invalid, and fail execution: As the message for signature verification, transaction digest is ''hashTapSighash'' of the following values (size in byte) serialized. Numerical values in 2, 4, or 8-byte are encoded in little-endian. * Control: -** epoch (1): always 0. '''What's the purpose of the epoch?''' The epoch can be increased to allow securely creating a new transaction digest algorithms with large changes to the structure or interpretation of hash_type if needed. +** epoch (1): always 0. '''What's the purpose of the epoch?''' The epoch can be increased to allow securely creating a new transaction digest algorithm with large changes to the structure or interpretation of hash_type if needed. ** hash_type (1). * Transaction data: ** nVersion (4): the nVersion of the transaction. diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index 4336f9c..a1302ec 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -45,7 +45,7 @@ Additionally, the new tapscript OP_SUCCESS opcodes allow introducin ==Specification== The rules below only apply when validating a transaction input for which all of the conditions below are true: -* The transaction output is a '''segregated witness spend''' (i.e., the scriptPubKey is a witness program as defined in [https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki BIP141]). +* The transaction input is a '''segregated witness spend''' (i.e., the scriptPubKey contains a witness program as defined in [https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki BIP141]). * It is a '''taproot spend''' as defined in bip-taproot (i.e., the witness version is 1, the witness program is 32 bytes, and it is not P2SH wrapped). * It is a '''script path spend''' as defined in bip-taproot (i.e., after removing the optional annex from the witness stack, two or more stack elements remain). * The leaf version is ''0xc0'' (i.e. the first byte of the last witness element after removing the optional annex is ''0xc0'' or ''0xc1'')'''How is the ''0xc0'' constant chosen?''' Following the guidelines in bip-taproot, by choosing a value having the two top bits set, tapscript spends are identifiable even without access to the UTXO being spent., marking it as a '''tapscript spend'''. -- cgit v1.2.3 From fd898f118a345f0288e52f9010c00044271ae4c3 Mon Sep 17 00:00:00 2001 From: Kalle Rosenbaum Date: Tue, 10 Dec 2019 22:01:43 +0100 Subject: Fix @jonasnick's comment --- bip-taproot.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 7f2f443..882a377 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -39,7 +39,7 @@ Specifically, it seeks to minimize how much information about the spendability c As a result we choose this combination of technologies: * '''Merkle branches''' let us only reveal the actually executed part of the script to the blockchain, as opposed to all possible ways a script can be executed. Among the various known mechanisms for implementing this, one where the Merkle tree becomes part of the script's structure directly maximizes the space savings, so that approach is chosen. * '''Taproot''' on top of that lets us merge the traditionally separate pay-to-pubkey and pay-to-scripthash policies, making all outputs spendable by either a key or (optionally) a script, and indistinguishable from each other. As long as the key-based spending path is used for spending, it is not revealed whether a script path was permitted as well, resulting in space savings and an increase in scripting privacy at spending time. -* Taproot's advantages become apparent under the assumption that most applications involve outputs that could be spent by all parties agreeing. That's where '''Schnorr''' signatures come in, as they permit [https://eprint.iacr.org/2018/068 key aggregation]: a public key can be constructed from multiple participant public keys, and which requires cooperation between all participants to sign for. Such multi-party public keys and signatures are indistinguishable from their single-party equivalents. This means that the all-parties-agree case can be handled using the key-based spending path, which is efficient and (under the Taproot assumption) private using taproot. This can be generalized to arbitrary M-of-N policies, as Schnorr signatures support threshold signing, at the cost of more complex setup protocols. +* Taproot's advantages become apparent under the assumption that most applications involve outputs that could be spent by all parties agreeing. That's where '''Schnorr''' signatures come in, as they permit [https://eprint.iacr.org/2018/068 key aggregation]: a public key can be constructed from multiple participant public keys, and which requires cooperation between all participants to sign for. Such multi-party public keys and signatures are indistinguishable from their single-party equivalents. This means that with taproot most applications can use the key-based spending path, which is both efficient and private. This can be generalized to arbitrary M-of-N policies, as Schnorr signatures support threshold signing, at the cost of more complex setup protocols. * As Schnorr signatures also permit '''batch validation''', allowing multiple signatures to be validated together more efficiently than validating each one independently, we make sure all parts of the design are compatible with this. * Where unused bits appear as a result of the above changes, they are reserved for mechanisms for '''future extensions'''. As a result, every script in the Merkle tree has an associated version such that new script versions can be introduced with a soft fork while remaining compatible with bip-taproot. Additionally, future soft forks can make use of the currently unused annex in the witness (see [[#Rationale]]). * While the core semantics of the '''signature hashing algorithm''' are not changed, a number of improvements are included in this proposal. The new signature hashing algorithm fixes the verification capabilities of offline signing devices by including amount and scriptPubKey in the digest, avoids unnecessary hashing, uses '''tagged hashes''' and defines a default sighash byte. -- cgit v1.2.3 From cc6fa25c799fa09b6e486728537eb0cbca46d2fa Mon Sep 17 00:00:00 2001 From: stefanwouldgo Date: Thu, 28 Nov 2019 13:41:28 +0100 Subject: fix singular/plural ambiguity --- bip-taproot.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index ba8d048..d3e2222 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -114,7 +114,7 @@ The following use of hash_type are invalid, and fail execution: As the message for signature verification, transaction digest is ''hashTapSighash'' of the following values (size in byte) serialized. Numerical values in 2, 4, or 8-byte are encoded in little-endian. * Control: -** epoch (1): always 0. '''What's the purpose of the epoch?''' The epoch can be increased to allow securely creating a new transaction digest algorithm with large changes to the structure or interpretation of hash_type if needed. +** epoch (1): always 0. '''What's the purpose of the epoch?''' The epoch can be increased to allow securely creating new transaction digest algorithms with large changes to the structure or interpretation of hash_type if needed. ** hash_type (1). * Transaction data: ** nVersion (4): the nVersion of the transaction. -- cgit v1.2.3 From 2e0c9435a89766fd0fc59d9477935979a668aebb Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Wed, 11 Dec 2019 15:33:39 +0200 Subject: Fix reference formatting --- bip-schnorr.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 3925f07..e102df7 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -81,7 +81,7 @@ expensive conversion to affine coordinates first. This would even be the case if For ''P'' the speed of signing and verification does not significantly differ between any of the three options because affine coordinates of the point have to be computed anyway. For consistency reasons we choose the same option as for ''R''. The signing algorithm ensures that the signature is valid under the correct public key by negating the secret key if necessary. -Implicit Y coordinates are not a reduction in security when expressed as the number of elliptic curve operations an attacker is expected to perform to compute the secret key. An attacker can normalize any given public key to a point whose Y coordinate is a square by negating the point if necessary. This is just a subtraction of field elements and not an elliptic curve operationThis can be formalized by a simple reduction that reduces an attack on Schnorr signatures with implicit Y coordinates to an attack to Schnorr signatures with explicit Y coordinates. The reduction works by reencoding public keys and negating the result of the hash function, which is modeled as random oracle, whenever the challenge public key has an explicit Y coordinate that is not a square. A proof sketch can be found [here](https://medium.com/blockstream/reducing-bitcoin-transaction-sizes-with-x-only-pubkeys-f86476af05d7). +Implicit Y coordinates are not a reduction in security when expressed as the number of elliptic curve operations an attacker is expected to perform to compute the secret key. An attacker can normalize any given public key to a point whose Y coordinate is a square by negating the point if necessary. This is just a subtraction of field elements and not an elliptic curve operationThis can be formalized by a simple reduction that reduces an attack on Schnorr signatures with implicit Y coordinates to an attack to Schnorr signatures with explicit Y coordinates. The reduction works by reencoding public keys and negating the result of the hash function, which is modeled as random oracle, whenever the challenge public key has an explicit Y coordinate that is not a square. A proof sketch can be found [https://medium.com/blockstream/reducing-bitcoin-transaction-sizes-with-x-only-pubkeys-f86476af05d7 here].. '''Tagged Hashes''' Cryptographic hash functions are used for multiple purposes in the specification below and in Bitcoin in general. To make sure hashes used in one context can't be reinterpreted in another one, hash functions can be tweaked with a context-dependent tag name, in such a way that collisions across contexts can be assumed to be infeasible. Such collisions obviously can not be ruled out completely, but only for schemes using tagging with a unique name. As for other schemes collisions are at least less likely with tagging than without. -- cgit v1.2.3 From 92582c2a33a19f9ae1b4c59d931062077bd0a155 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Thu, 12 Dec 2019 22:49:21 +0100 Subject: Clarify why we don't want short hashes This is supposed to supersede https://github.com/sipa/bips/pull/158. I tried to say this carefully. I don't think that multiparty signing is in general broken with short hashes. For example the attack in #158 could be avoided by letting everybody not only commit to the nonce but also to the message. It's just that using a collision-resistant hash just eliminates the problem entirely... --- bip-schnorr.mediawiki | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 4cfe6b4..a5f7c59 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -49,12 +49,12 @@ encodings and operations. === Design === '''Schnorr signature variant''' Elliptic Curve Schnorr signatures for message ''m'' and public key ''P'' generally involve a point ''R'', integers ''e'' and ''s'' picked by the signer, and the base point ''G'' which satisfy ''e = hash(R || m)'' and ''s⋅G = R + e⋅P''. Two formulations exist, depending on whether the signer reveals ''e'' or ''R'': -# Signatures are ''(e, s)'' that satisfy ''e = hash(s⋅G - e⋅P || m)''. This supports more compact signatures, since [http://www.neven.org/papers/schnorr.pdf the hash ''e'' can be made as small as 16 bytes without sacrificing security], whereas an encoding of ''R'' inherently needs about 32 bytes. Moreover, this variant avoids minor complexity introduced by the encoding of the point ''R'' in the signature (see paragraphs "Encoding R and public key point P" and "Implicit Y coordinates" further below in this subsection). -# Signatures are ''(R, s)'' that satisfy ''s⋅G = R + hash(R || m)⋅P''. This supports batch verification, as there are no elliptic curve operations inside the hashes. Batch verification enables significant speedups. +# Signatures are pairs ''(e, s)'' that satisfy ''e = hash(s⋅G - e⋅P || m)''. This variant avoids minor complexity introduced by the encoding of the point ''R'' in the signature (see paragraphs "Encoding R and public key point P" and "Implicit Y coordinates" further below in this subsection). Moreover, revealing ''e'' instead of ''R'' allows for potentially shorter signatures: Whereas an encoding of ''R'' inherently needs about 32 bytes, the hash ''e'' can be tuned to be shorter than 32 bytes, and [http://www.neven.org/papers/schnorr.pdf a short hash of only 16 bytes suffices to provide SUF-CMA security at the target security level of 128 bits]. However, a major drawback of this optimization is that finding collisions in a short hash function is easy. This complicates the implementation of secure signing protocols in scenarios in which a group of mutually distrusting signers work together to produce a single joint signature (see Applications below). In these scenarios, which are not captured by the SUF-CMA model due its assumption of a single honest signer, a promising attack strategy for malicious co-signers is to find a collision in the hash function in order to obtain a valid signature on a message that an honest co-signer did not intent to sign. +# Signatures are pairs ''(R, s)'' that satisfy ''s⋅G = R + hash(R || m)⋅P''. This supports batch verification, as there are no elliptic curve operations inside the hashes. Batch verification enables significant speedups. [[File:bip-schnorr/speedup-batch.png|center|frame|This graph shows the ratio between the time it takes to verify ''n'' signatures individually and to verify a batch of ''n'' signatures. This ratio goes up logarithmically with the number of signatures, or in other words: the total time to verify ''n'' signatures grows with ''O(n / log n)''.]] -We choose the ''R''-option to support batch verification. +Since we would like to avoid the fragility that comes with short hashes, the ''e'' variant does not provide significant advantages. We choose the ''R''-option, which supports batch verification. '''Key prefixing''' Using the verification rule above directly makes Schnorr signatures vulnerable to "related-key attacks" in which a third party can convert a signature ''(R, s)'' for public key ''P'' into a signature ''(R, s + a⋅hash(R || m))'' for public key ''P + a⋅G'' and the same message ''m'', for any given additive tweak ''a'' to the signing key. This would render signatures insecure when keys are generated using [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#public-parent-key--public-child-key BIP32's unhardened derivation] and other methods that rely on additive tweaks to existing keys such as Taproot. -- cgit v1.2.3 From aa18fdb07e17d8236c149c90b05b2e42b97cbfed Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Thu, 12 Dec 2019 16:23:20 -0800 Subject: Low-S ECDSA is non-malleable under nonstandard assumptions --- bip-schnorr.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index a5f7c59..7b86b08 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -26,7 +26,7 @@ transactions. These are [https://www.secg.org/sec1-v2.pdf standardized], but hav compared to [http://publikationen.ub.uni-frankfurt.de/opus4/files/4280/schnorr.pdf Schnorr signatures] over the same curve: * '''Provable security''': Schnorr signatures are provably secure. In more detail, they are ''strongly unforgeable under chosen message attack (SUF-CMA)''Informally, this means that without knowledge of the secret key but given valid signatures of arbitrary messages, it is not possible to come up with further valid signatures. [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf in the random oracle model assuming the hardness of the elliptic curve discrete logarithm problem (ECDLP)] and [http://www.neven.org/papers/schnorr.pdf in the generic group model assuming variants of preimage and second preimage resistance of the used hash function]A detailed security proof in the random oracle model, which essentially restates [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf the original security proof by Pointcheval and Stern] more explicitly, can be found in [https://eprint.iacr.org/2016/191 a paper by Kiltz, Masny and Pan]. All these security proofs assume a variant of Schnorr signatures that use ''(e,s)'' instead of ''(R,s)'' (see Design above). Since we use a unique encoding of ''R'', there is an efficiently computable bijection that maps ''(R,s)'' to ''(e,s)'', which allows to convert a successful SUF-CMA attacker for the ''(e,s)'' variant to a successful SUF-CMA attacker for the ''(R,s)'' variant (and vice-versa). Furthermore, the proofs consider a variant of Schnorr signatures without key prefixing (see Design above), but it can be verified that the proofs are also correct for the variant with key prefixing. As a result, all the aforementioned security proofs apply to the variant of Schnorr signatures proposed in this document.. In contrast, the [https://nbn-resolving.de/urn:nbn:de:hbz:294-60803 best known results for the provable security of ECDSA] rely on stronger assumptions. -* '''Non-malleability''': The SUF-CMA security of Schnorr signatures implies that they are non-malleable. On the other hand, ECDSA signatures are inherently malleable; a third party without access to the secret key can alter an existing valid signature for a given public key and message into another signature that is valid for the same key and message. This issue is discussed in [https://github.com/bitcoin/bips/blob/master/bip-0062.mediawiki BIP62] and [https://github.com/bitcoin/bips/blob/master/bip-0146.mediawiki BIP146]. +* '''Non-malleability''': The SUF-CMA security of Schnorr signatures implies that they are non-malleable. On the other hand, ECDSA signatures are inherently malleableIf ''(r,s)'' is a valid ECDSA signature for a given message and key, then ''(r,n-s)'' is also valid for the same message and key. If ECDSA is restricted to only permit one of the two variants (as Bitcoin does through a policy rule on the network), it can be [https://nbn-resolving.de/urn:nbn:de:hbz:294-60803 proven] non-malleable under stronger than usual assumptions.; a third party without access to the secret key can alter an existing valid signature for a given public key and message into another signature that is valid for the same key and message. This issue is discussed in [https://github.com/bitcoin/bips/blob/master/bip-0062.mediawiki BIP62] and [https://github.com/bitcoin/bips/blob/master/bip-0146.mediawiki BIP146]. * '''Linearity''': Schnorr signatures have the remarkable property that multiple parties can collaborate to produce a signature that is valid for the sum of their public keys. This is the building block for various higher-level constructions that improve efficiency and privacy, such as multisignatures and others (see Applications below). For all these advantages, there are virtually no disadvantages, apart -- cgit v1.2.3 From ff2b53737c626404de30caacc73a83c5e5c202db Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Fri, 13 Dec 2019 12:11:50 +0100 Subject: Mention that we don't change the hash function --- bip-schnorr.mediawiki | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index a5f7c59..f417467 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -21,7 +21,7 @@ This document is licensed under the 2-clause BSD license. === Motivation === Bitcoin has traditionally used -[https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm ECDSA] signatures over the [https://www.secg.org/sec2-v2.pdf secp256k1 curve] for authenticating +[https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm ECDSA] signatures over the [https://www.secg.org/sec2-v2.pdf secp256k1 curve] and with [https://en.wikipedia.org/wiki/SHA-2 SHA256] hashes for authenticating transactions. These are [https://www.secg.org/sec1-v2.pdf standardized], but have a number of downsides compared to [http://publikationen.ub.uni-frankfurt.de/opus4/files/4280/schnorr.pdf Schnorr signatures] over the same curve: @@ -38,7 +38,7 @@ made: * '''Public key encoding''': Instead of using ''compressed'' 33-byte encodings of elliptic curve points which are common in Bitcoin today, public keys in this proposal are encoded as 32 bytes. * '''Batch verification''': The specific formulation of ECDSA signatures that is standardized cannot be verified more efficiently in batch compared to individually, unless additional witness data is added. Changing the signature scheme offers an opportunity to address this. -By reusing the same curve as Bitcoin uses for ECDSA, we are able to retain existing mechanisms for choosing secret and public keys, and we avoid introducing new assumptions about elliptic curve group security. +By reusing the same curve and hash function as Bitcoin has used for ECDSA, we are able to retain existing mechanisms for choosing private and public keys, and we avoid introducing new assumptions about the security of elliptic curves and hash functions. == Description == -- cgit v1.2.3 From 633cca9b1c920d445591472c0c9efe55428fd9c0 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Fri, 13 Dec 2019 13:25:16 +0000 Subject: Replace private key with secret key --- bip-schnorr.mediawiki | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index a5f7c59..e1b3ed2 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -133,9 +133,9 @@ The algorithm ''PubKey(sk)'' is defined as: * Fail if ''d = 0'' or ''d ≥ n''. * Return ''bytes(d⋅G)''. -Note that we use a very different public key format (32 bytes) than the ones used by existing systems (which typically use elliptic curve points as public keys, or 33-byte or 65-byte encodings of them). A side effect is that ''PubKey(sk) = PubKey(bytes(n - int(sk))'', so every public key has two corresponding private keys. +Note that we use a very different public key format (32 bytes) than the ones used by existing systems (which typically use elliptic curve points as public keys, or 33-byte or 65-byte encodings of them). A side effect is that ''PubKey(sk) = PubKey(bytes(n - int(sk))'', so every public key has two corresponding secret keys. -As an alternative to generating keys randomly, it is also possible and safe to repurpose existing key generation algorithms for ECDSA in a compatible way. The private keys constructed by such an algorithm can be used as ''sk'' directly. The public keys constructed by such an algorithm (assuming they use the 33-byte compressed encoding) need to be converted by dropping the first byte. Specifically, [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki BIP32] and schemes built on top of it remain usable. +As an alternative to generating keys randomly, it is also possible and safe to repurpose existing key generation algorithms for ECDSA in a compatible way. The secret keys constructed by such an algorithm can be used as ''sk'' directly. The public keys constructed by such an algorithm (assuming they use the 33-byte compressed encoding) need to be converted by dropping the first byte. Specifically, [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki BIP32] and schemes built on top of it remain usable. ==== Default Signing ==== @@ -161,9 +161,9 @@ It should be noted that various alternative signing algorithms can be used to pr '''Synthetic nonces''' When a random number generator (RNG) is available, 32 bytes of RNG output can be appended to the input to ''hashBIPSchnorrDerive''. This will change the corresponding line in the signing algorithm to ''k' = int(hashBIPSchnorrDerive(bytes(d) || m || get_32_bytes_from_rng())) mod n'', where ''get_32_bytes_from_rng()'' is the call to the RNG. Adding RNG output may improve protection against [https://moderncrypto.org/mail-archive/curves/2017/000925.html fault injection attacks and side-channel attacks]. It is safe to add randomness from a low-quality randomness source, i.e., an RNG with low entropy. -'''Nonce exfiltration protection''' It is possible to strengthen the nonce generation algorithm using a second device. In this case, the second device contributes randomness which the actual signer provably incorporates into its nonce. This prevents certain attacks where the signer device is compromised and intentionally tries to leak the private key through its nonce selection. +'''Nonce exfiltration protection''' It is possible to strengthen the nonce generation algorithm using a second device. In this case, the second device contributes randomness which the actual signer provably incorporates into its nonce. This prevents certain attacks where the signer device is compromised and intentionally tries to leak the secret key through its nonce selection. -'''Multisignatures''' This signature scheme is compatible with various types of multisignature and threshold schemes such as [https://eprint.iacr.org/2018/068 MuSig], where a single public key requires holders of multiple private keys to participate in signing (see Applications below). +'''Multisignatures''' This signature scheme is compatible with various types of multisignature and threshold schemes such as [https://eprint.iacr.org/2018/068 MuSig], where a single public key requires holders of multiple secret keys to participate in signing (see Applications below). '''It is important to note that multisignature signing schemes in general are insecure with the nonce generation from the default signing algorithm above (or any deterministic nonce algorithm).''' ==== Verification ==== -- cgit v1.2.3 From f1380bdc11536d8910d857f6a5612364476806d5 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Thu, 12 Dec 2019 19:53:08 -0800 Subject: Completely specified --- bip-schnorr.mediawiki | 1 + 1 file changed, 1 insertion(+) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index e1b3ed2..b810cfc 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -37,6 +37,7 @@ made: * '''Signature encoding''': Instead of using [https://en.wikipedia.org/wiki/X.690#DER_encoding DER]-encoding for signatures (which are variable size, and up to 72 bytes), we can use a simple fixed 64-byte format. * '''Public key encoding''': Instead of using ''compressed'' 33-byte encodings of elliptic curve points which are common in Bitcoin today, public keys in this proposal are encoded as 32 bytes. * '''Batch verification''': The specific formulation of ECDSA signatures that is standardized cannot be verified more efficiently in batch compared to individually, unless additional witness data is added. Changing the signature scheme offers an opportunity to address this. +* '''Completely specified''': To be safe for usage in consensus systems, the verification algorithm must be completely specified at the byte level. This guarantees that nobody can construct a signature that is valid to some verifiers but not all. This is traditionally not a requirement for digital signature schemes, and the lack of exact specification for the DER parsing of ECDSA signatures has caused problems for Bitcoin [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2015-July/009697.html in the past], needing [https://github.com/bitcoin/bips/blob/master/bip-0146.mediawiki BIP66] to address it. In this document we aim to meet this property by design. For batch verification, which is inherently non-deterministic as the verifier can choose their batches, this property implies that the outcome of verification may only differ from individual verifications with negligible probability, even to an attacker who intentionally tries to make batch- and non-batch verification differ. By reusing the same curve as Bitcoin uses for ECDSA, we are able to retain existing mechanisms for choosing secret and public keys, and we avoid introducing new assumptions about elliptic curve group security. -- cgit v1.2.3 From a8ebb65eb1bab6ddbca799dab131b99a656a7810 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Wed, 11 Dec 2019 19:00:29 -0800 Subject: Linearity makes sign-for-sum-of-keys easier, not possible entirely. I'm sure it's possible to construct a complex MPC that can sign for the sum of keys under ECDSA as well. --- bip-schnorr.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 36652c3..29f94e9 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -27,7 +27,7 @@ compared to [http://publikationen.ub.uni-frankfurt.de/opus4/files/4280/schnorr.p * '''Provable security''': Schnorr signatures are provably secure. In more detail, they are ''strongly unforgeable under chosen message attack (SUF-CMA)''Informally, this means that without knowledge of the secret key but given valid signatures of arbitrary messages, it is not possible to come up with further valid signatures. [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf in the random oracle model assuming the hardness of the elliptic curve discrete logarithm problem (ECDLP)] and [http://www.neven.org/papers/schnorr.pdf in the generic group model assuming variants of preimage and second preimage resistance of the used hash function]A detailed security proof in the random oracle model, which essentially restates [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf the original security proof by Pointcheval and Stern] more explicitly, can be found in [https://eprint.iacr.org/2016/191 a paper by Kiltz, Masny and Pan]. All these security proofs assume a variant of Schnorr signatures that use ''(e,s)'' instead of ''(R,s)'' (see Design above). Since we use a unique encoding of ''R'', there is an efficiently computable bijection that maps ''(R,s)'' to ''(e,s)'', which allows to convert a successful SUF-CMA attacker for the ''(e,s)'' variant to a successful SUF-CMA attacker for the ''(R,s)'' variant (and vice-versa). Furthermore, the proofs consider a variant of Schnorr signatures without key prefixing (see Design above), but it can be verified that the proofs are also correct for the variant with key prefixing. As a result, all the aforementioned security proofs apply to the variant of Schnorr signatures proposed in this document.. In contrast, the [https://nbn-resolving.de/urn:nbn:de:hbz:294-60803 best known results for the provable security of ECDSA] rely on stronger assumptions. * '''Non-malleability''': The SUF-CMA security of Schnorr signatures implies that they are non-malleable. On the other hand, ECDSA signatures are inherently malleableIf ''(r,s)'' is a valid ECDSA signature for a given message and key, then ''(r,n-s)'' is also valid for the same message and key. If ECDSA is restricted to only permit one of the two variants (as Bitcoin does through a policy rule on the network), it can be [https://nbn-resolving.de/urn:nbn:de:hbz:294-60803 proven] non-malleable under stronger than usual assumptions.; a third party without access to the secret key can alter an existing valid signature for a given public key and message into another signature that is valid for the same key and message. This issue is discussed in [https://github.com/bitcoin/bips/blob/master/bip-0062.mediawiki BIP62] and [https://github.com/bitcoin/bips/blob/master/bip-0146.mediawiki BIP146]. -* '''Linearity''': Schnorr signatures have the remarkable property that multiple parties can collaborate to produce a signature that is valid for the sum of their public keys. This is the building block for various higher-level constructions that improve efficiency and privacy, such as multisignatures and others (see Applications below). +* '''Linearity''': Schnorr signatures have the remarkable property that multiple parties can easily collaborate to produce a signature that is valid for the sum of their public keys. This is the building block for various higher-level constructions that improve efficiency and privacy, such as multisignatures and others (see Applications below). For all these advantages, there are virtually no disadvantages, apart from not being standardized. This document seeks to change that. As we -- cgit v1.2.3 From 83adab4af92739200258f7a0ccb6d9b2cc71cf2a Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 13 Dec 2019 18:35:10 -0500 Subject: Update bip-schnorr.mediawiki Co-Authored-By: Tim Ruffing --- bip-schnorr.mediawiki | 2 +- bip-schnorr/__pycache__/reference.cpython-36.pyc | Bin 0 -> 5278 bytes 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 bip-schnorr/__pycache__/reference.cpython-36.pyc diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 29f94e9..a291348 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -27,7 +27,7 @@ compared to [http://publikationen.ub.uni-frankfurt.de/opus4/files/4280/schnorr.p * '''Provable security''': Schnorr signatures are provably secure. In more detail, they are ''strongly unforgeable under chosen message attack (SUF-CMA)''Informally, this means that without knowledge of the secret key but given valid signatures of arbitrary messages, it is not possible to come up with further valid signatures. [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf in the random oracle model assuming the hardness of the elliptic curve discrete logarithm problem (ECDLP)] and [http://www.neven.org/papers/schnorr.pdf in the generic group model assuming variants of preimage and second preimage resistance of the used hash function]A detailed security proof in the random oracle model, which essentially restates [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf the original security proof by Pointcheval and Stern] more explicitly, can be found in [https://eprint.iacr.org/2016/191 a paper by Kiltz, Masny and Pan]. All these security proofs assume a variant of Schnorr signatures that use ''(e,s)'' instead of ''(R,s)'' (see Design above). Since we use a unique encoding of ''R'', there is an efficiently computable bijection that maps ''(R,s)'' to ''(e,s)'', which allows to convert a successful SUF-CMA attacker for the ''(e,s)'' variant to a successful SUF-CMA attacker for the ''(R,s)'' variant (and vice-versa). Furthermore, the proofs consider a variant of Schnorr signatures without key prefixing (see Design above), but it can be verified that the proofs are also correct for the variant with key prefixing. As a result, all the aforementioned security proofs apply to the variant of Schnorr signatures proposed in this document.. In contrast, the [https://nbn-resolving.de/urn:nbn:de:hbz:294-60803 best known results for the provable security of ECDSA] rely on stronger assumptions. * '''Non-malleability''': The SUF-CMA security of Schnorr signatures implies that they are non-malleable. On the other hand, ECDSA signatures are inherently malleableIf ''(r,s)'' is a valid ECDSA signature for a given message and key, then ''(r,n-s)'' is also valid for the same message and key. If ECDSA is restricted to only permit one of the two variants (as Bitcoin does through a policy rule on the network), it can be [https://nbn-resolving.de/urn:nbn:de:hbz:294-60803 proven] non-malleable under stronger than usual assumptions.; a third party without access to the secret key can alter an existing valid signature for a given public key and message into another signature that is valid for the same key and message. This issue is discussed in [https://github.com/bitcoin/bips/blob/master/bip-0062.mediawiki BIP62] and [https://github.com/bitcoin/bips/blob/master/bip-0146.mediawiki BIP146]. -* '''Linearity''': Schnorr signatures have the remarkable property that multiple parties can easily collaborate to produce a signature that is valid for the sum of their public keys. This is the building block for various higher-level constructions that improve efficiency and privacy, such as multisignatures and others (see Applications below). +* '''Linearity''': Schnorr signatures provide a simple and efficient method that enables multiple collaborating parties to produce a signature that is valid for the sum of their public keys. This is the building block for various higher-level constructions that improve efficiency and privacy, such as multisignatures and others (see Applications below). For all these advantages, there are virtually no disadvantages, apart from not being standardized. This document seeks to change that. As we diff --git a/bip-schnorr/__pycache__/reference.cpython-36.pyc b/bip-schnorr/__pycache__/reference.cpython-36.pyc new file mode 100644 index 0000000..cce1e04 Binary files /dev/null and b/bip-schnorr/__pycache__/reference.cpython-36.pyc differ -- cgit v1.2.3 From ad1eba008cb8911f434716bc3d177046785eadee Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Fri, 13 Dec 2019 15:28:15 +0100 Subject: Update bip-schnorr.mediawiki --- bip-schnorr.mediawiki | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index f417467..d72d8ed 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -21,7 +21,7 @@ This document is licensed under the 2-clause BSD license. === Motivation === Bitcoin has traditionally used -[https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm ECDSA] signatures over the [https://www.secg.org/sec2-v2.pdf secp256k1 curve] and with [https://en.wikipedia.org/wiki/SHA-2 SHA256] hashes for authenticating +[https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm ECDSA] signatures over the [https://www.secg.org/sec2-v2.pdf secp256k1 curve] with [https://en.wikipedia.org/wiki/SHA-2 SHA256] hashes for authenticating transactions. These are [https://www.secg.org/sec1-v2.pdf standardized], but have a number of downsides compared to [http://publikationen.ub.uni-frankfurt.de/opus4/files/4280/schnorr.pdf Schnorr signatures] over the same curve: @@ -38,7 +38,7 @@ made: * '''Public key encoding''': Instead of using ''compressed'' 33-byte encodings of elliptic curve points which are common in Bitcoin today, public keys in this proposal are encoded as 32 bytes. * '''Batch verification''': The specific formulation of ECDSA signatures that is standardized cannot be verified more efficiently in batch compared to individually, unless additional witness data is added. Changing the signature scheme offers an opportunity to address this. -By reusing the same curve and hash function as Bitcoin has used for ECDSA, we are able to retain existing mechanisms for choosing private and public keys, and we avoid introducing new assumptions about the security of elliptic curves and hash functions. +By reusing the same curve and hash function as Bitcoin uses for ECDSA, we are able to retain existing mechanisms for choosing secret and public keys, and we avoid introducing new assumptions about the security of elliptic curves and hash functions. == Description == -- cgit v1.2.3 From 01e5bfbf19c4337f5a6b74cf94c1ebfe19af6817 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sat, 14 Dec 2019 16:28:44 -0800 Subject: Improve and restructure motivation and design --- bip-taproot.mediawiki | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 0fa4194..be8409b 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -24,17 +24,13 @@ This document is licensed under the 3-clause BSD license. ===Motivation=== -A number of related ideas for improving Bitcoin's scripting capabilities have been previously proposed: Schnorr signatures (bip-schnorr), Merkle branches ("MAST", [https://github.com/bitcoin/bips/blob/master/bip-0114.mediawiki BIP114], [https://github.com/bitcoin/bips/blob/master/bip-0117.mediawiki BIP117]), new sighash modes ([https://github.com/bitcoin/bips/blob/master/bip-0118.mediawiki BIP118]), new opcodes like CHECKSIGFROMSTACK, [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-January/015614.html Taproot], [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-February/015700.html Graftroot], [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-July/016249.html G'root], and [https://bitcointalk.org/index.php?topic=1377298.0 cross-input aggregation]. - -Combining all these ideas in a single proposal would be an extensive change, be hard to review, and likely miss new discoveries that otherwise could have been made along the way. Some of these ideas are also less mature than others. On the other hand, separating them all into independent proposals would reduce the efficiency and privacy gains to be had, and complicate analysis of their interactions. It seems preferable to focus on one goal set at a time, and combine interacting technologies to achieve them. +This proposal aims to improve privacy, efficiency, and flexibility of Bitcoin's scripting capabilities without adding new security assumptions. Specifically, it seeks to minimize how much information about the spendability conditions of a transaction output is revealed on chain at creation or spending time and to add a number of upgrade mechanisms, while fixing a few minor but long-standing issues. ==Design== -This proposal focuses on improvements to privacy, efficiency, and flexibility of Bitcoin's scripting capabilities, subject to two restrictions: -* Not adding any new strong security assumptions -* Not combining into the proposal any functionality which could be simply implemented independently. +A number of related ideas for improving Bitcoin's scripting capabilities have been previously proposed: Schnorr signatures (bip-schnorr), Merkle branches ("MAST", [https://github.com/bitcoin/bips/blob/master/bip-0114.mediawiki BIP114], [https://github.com/bitcoin/bips/blob/master/bip-0117.mediawiki BIP117]), new sighash modes ([https://github.com/bitcoin/bips/blob/master/bip-0118.mediawiki BIP118]), new opcodes like CHECKSIGFROMSTACK, [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-January/015614.html Taproot], [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-February/015700.html Graftroot], [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-July/016249.html G'root], and [https://bitcointalk.org/index.php?topic=1377298.0 cross-input aggregation]. -Specifically, it seeks to minimize how much information about the spendability conditions of a transaction output is revealed on chain at creation or spending time. To avoid reducing the effectiveness of future improvements a number of upgrade mechanisms are also included, as well as fixes for minor but long-standing issues. +Combining all these ideas in a single proposal would be an extensive change, be hard to review, and likely miss new discoveries that otherwise could have been made along the way. Not all are equally mature as well. For example, cross-input aggregation [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-March/015838.html interacts] in complex ways with upgrade mechanisms, and solutions to that are still [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-October/016461.html in flux]. On the other hand, separating them all into independent upgrades would reduce the efficiency and privacy gains to be had, and wallet and service providers may not be inclined to go through many incremental updates. Therefore, we're faced with a tradeoff between functionality and scope creep. In this design we strike a balance by focusing on the structural script improvements offered by Taproot and Merkle branches, as well as changes necessary to make them usable and efficient. For things like sighashes and opcodes we include fixes for known problems, but exclude new features that can be added independently with no downsides. As a result we choose this combination of technologies: * '''Merkle branches''' let us only reveal the actually executed part of the script to the blockchain, as opposed to all possible ways a script can be executed. Among the various known mechanisms for implementing this, one where the Merkle tree becomes part of the script's structure directly maximizes the space savings, so that approach is chosen. @@ -45,7 +41,6 @@ As a result we choose this combination of technologies: * While the core semantics of the '''signature hashing algorithm''' are not changed, a number of improvements are included in this proposal. The new signature hashing algorithm fixes the verification capabilities of offline signing devices by including amount and scriptPubKey in the digest, avoids unnecessary hashing, uses '''tagged hashes''' and defines a default sighash byte. * The '''public key is directly included in the output''' in contrast to typical earlier constructions which store a hash of the public key or script in the output. This has the same cost for senders and is more space efficient overall if the key-based spending path is taken. '''Why is the public key directly included in the output?''' While typical earlier constructions store a hash of a script or a public key in the output, this is rather wasteful when a public key is always involved. To guarantee batch verifiability, the public key must be known to every verifier, and thus only revealing its hash as an output would imply adding an additional 32 bytes to the witness. Furthermore, to maintain [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2016-January/012198.html 128-bit collision security] for outputs, a 256-bit hash would be required anyway, which is comparable in size (and thus in cost for senders) to revealing the public key directly. While the usage of public key hashes is often said to protect against ECDLP breaks or quantum computers, this protection is very weak at best: transactions are not protected while being confirmed, and a very [https://twitter.com/pwuille/status/1108097835365339136 large portion] of the currency's supply is not under such protection regardless. Actual resistance to such systems can be introduced by relying on different cryptographic assumptions, but this proposal focuses on improvements that do not change the security model. -Not included in this proposal are additional features like new sighash modes or opcodes that can be included with no loss in effectiveness as a future extension. Also not included is cross-input aggregation, as it [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-March/015838.html interacts] in complex ways with upgrade mechanisms and solutions to that are still [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-October/016461.html in flux]. == Specification == -- cgit v1.2.3 From 1c163188eedeb7159286edd2984b4b907a7e9c96 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sat, 14 Dec 2019 16:28:58 -0800 Subject: Add an informal summary of the design --- bip-taproot.mediawiki | 1 + 1 file changed, 1 insertion(+) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index be8409b..6488c90 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -41,6 +41,7 @@ As a result we choose this combination of technologies: * While the core semantics of the '''signature hashing algorithm''' are not changed, a number of improvements are included in this proposal. The new signature hashing algorithm fixes the verification capabilities of offline signing devices by including amount and scriptPubKey in the digest, avoids unnecessary hashing, uses '''tagged hashes''' and defines a default sighash byte. * The '''public key is directly included in the output''' in contrast to typical earlier constructions which store a hash of the public key or script in the output. This has the same cost for senders and is more space efficient overall if the key-based spending path is taken. '''Why is the public key directly included in the output?''' While typical earlier constructions store a hash of a script or a public key in the output, this is rather wasteful when a public key is always involved. To guarantee batch verifiability, the public key must be known to every verifier, and thus only revealing its hash as an output would imply adding an additional 32 bytes to the witness. Furthermore, to maintain [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2016-January/012198.html 128-bit collision security] for outputs, a 256-bit hash would be required anyway, which is comparable in size (and thus in cost for senders) to revealing the public key directly. While the usage of public key hashes is often said to protect against ECDLP breaks or quantum computers, this protection is very weak at best: transactions are not protected while being confirmed, and a very [https://twitter.com/pwuille/status/1108097835365339136 large portion] of the currency's supply is not under such protection regardless. Actual resistance to such systems can be introduced by relying on different cryptographic assumptions, but this proposal focuses on improvements that do not change the security model. +Informally, the resulting design is as follows. A new witness version is added (1), whose programs consist of 32-byte encodings of points ''Q''. ''Q'' is computed as ''P + hash(P||m)G'' for a public key ''P'', and the root ''m'' of a Merkle tree whose leaves consist of a version number and a script. These outputs can be spent directly by providing a signature for ''Q'', or indirectly by revealing ''P'', the script and leaf version, inputs that satisfy the script, and a Merkle path that proves ''Q'' committed to that leaf. All hashes in this construction (the hash for computing ''Q'' from ''P'', the hashes inside the Merkle tree's inner nodes, and the signature hashes used) are tagged to guarantee domain separation. == Specification == -- cgit v1.2.3 From 6b42461f8e83684442494958f5bcd532722a4779 Mon Sep 17 00:00:00 2001 From: Matthew Zipkin Date: Sun, 15 Dec 2019 10:32:33 -0500 Subject: bip-taproot: example from diagram --- bip-taproot.mediawiki | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 0fa4194..dedc5ab 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -236,6 +236,20 @@ def taproot_output_script(internal_pubkey, script_tree): [[File:bip-taproot/tree.png|frame|This diagram shows the hashing structure to obtain the tweak from an internal key ''P'' and a Merkle tree consisting of 5 script leaves. ''A'', ''B'', ''C'' and ''E'' are ''TapLeaf'' hashes similar to ''D'' and ''AB'' is a ''TapBranch'' hash. Note that when ''CDE'' is computed ''E'' is hashed first because ''E'' is less than ''CD''.]] +To spend this output using script ''D'', the control block would contain the following data in this order: + + + +The TapTweak would then be computed as described in [[#script-validation-rules]] like so: + + +D = tagged_hash("TapLeaf", bytes([leaf_version]) + ser_script(script)) +CD = tagged_hash("TapBranch", C + D) +CDE = tagged_hash("TapBranch", E + CD) +ABCDE = tagged_hash("TapBranch", AB + CDE) +TapTweak = tagged_hash("TapTweak", p + ABCDE) + + '''Spending using the key path''' A Taproot output can be spent with the secret key corresponding to the internal_pubkey. To do so, a witness stack consists of a single element: a bip-schnorr signature on the signature hash as defined above, with the secret key tweaked by the same h as in the above snippet. See the code below: -- cgit v1.2.3 From 882e46350d5544088d65cce0356985e21656be3f Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sun, 15 Dec 2019 14:44:39 -0800 Subject: Add rationale on security assumptions --- bip-taproot.mediawiki | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 6488c90..ef065f2 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -24,7 +24,7 @@ This document is licensed under the 3-clause BSD license. ===Motivation=== -This proposal aims to improve privacy, efficiency, and flexibility of Bitcoin's scripting capabilities without adding new security assumptions. Specifically, it seeks to minimize how much information about the spendability conditions of a transaction output is revealed on chain at creation or spending time and to add a number of upgrade mechanisms, while fixing a few minor but long-standing issues. +This proposal aims to improve privacy, efficiency, and flexibility of Bitcoin's scripting capabilities without adding new security assumptions'''What does not adding security assumptions mean?''' Unforgeability of signatures is a necessary requirement to prevent theft. At least when treating script execution as a digital signature scheme itself, unforgeability can be [https://github.com/apoelstra/taproot proven] in the Random Oracle Model assuming the Discrete Logarithm problem is hard. A [https://nbn-resolving.de/urn:nbn:de:hbz:294-60803 proof] for unforgeability of ECDSA in the current script system needs non-standard assumptions on top of that. Note that it is hard in general to model exactly what security for script means, as it depends on the policies and protocols used by wallet software.. Specifically, it seeks to minimize how much information about the spendability conditions of a transaction output is revealed on chain at creation or spending time and to add a number of upgrade mechanisms, while fixing a few minor but long-standing issues. ==Design== @@ -41,7 +41,7 @@ As a result we choose this combination of technologies: * While the core semantics of the '''signature hashing algorithm''' are not changed, a number of improvements are included in this proposal. The new signature hashing algorithm fixes the verification capabilities of offline signing devices by including amount and scriptPubKey in the digest, avoids unnecessary hashing, uses '''tagged hashes''' and defines a default sighash byte. * The '''public key is directly included in the output''' in contrast to typical earlier constructions which store a hash of the public key or script in the output. This has the same cost for senders and is more space efficient overall if the key-based spending path is taken. '''Why is the public key directly included in the output?''' While typical earlier constructions store a hash of a script or a public key in the output, this is rather wasteful when a public key is always involved. To guarantee batch verifiability, the public key must be known to every verifier, and thus only revealing its hash as an output would imply adding an additional 32 bytes to the witness. Furthermore, to maintain [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2016-January/012198.html 128-bit collision security] for outputs, a 256-bit hash would be required anyway, which is comparable in size (and thus in cost for senders) to revealing the public key directly. While the usage of public key hashes is often said to protect against ECDLP breaks or quantum computers, this protection is very weak at best: transactions are not protected while being confirmed, and a very [https://twitter.com/pwuille/status/1108097835365339136 large portion] of the currency's supply is not under such protection regardless. Actual resistance to such systems can be introduced by relying on different cryptographic assumptions, but this proposal focuses on improvements that do not change the security model. -Informally, the resulting design is as follows. A new witness version is added (1), whose programs consist of 32-byte encodings of points ''Q''. ''Q'' is computed as ''P + hash(P||m)G'' for a public key ''P'', and the root ''m'' of a Merkle tree whose leaves consist of a version number and a script. These outputs can be spent directly by providing a signature for ''Q'', or indirectly by revealing ''P'', the script and leaf version, inputs that satisfy the script, and a Merkle path that proves ''Q'' committed to that leaf. All hashes in this construction (the hash for computing ''Q'' from ''P'', the hashes inside the Merkle tree's inner nodes, and the signature hashes used) are tagged to guarantee domain separation. +Informally, the resulting design is as follows: a new witness version is added (version 1), whose programs consist of 32-byte encodings of points ''Q''. ''Q'' is computed as ''P + hash(P||m)G'' for a public key ''P'', and the root ''m'' of a Merkle tree whose leaves consist of a version number and a script. These outputs can be spent directly by providing a signature for ''Q'', or indirectly by revealing ''P'', the script and leaf version, inputs that satisfy the script, and a Merkle path that proves ''Q'' committed to that leaf. All hashes in this construction (the hash for computing ''Q'' from ''P'', the hashes inside the Merkle tree's inner nodes, and the signature hashes used) are tagged to guarantee domain separation. == Specification == -- cgit v1.2.3 From b90b53cd176749f59e3d2784776a6a8aa4801265 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 17 Dec 2019 17:27:22 -0800 Subject: Update authors --- bip-schnorr.mediawiki | 2 ++ bip-taproot.mediawiki | 2 ++ bip-tapscript.mediawiki | 2 ++ 3 files changed, 6 insertions(+) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index e4b38f6..b20fb48 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -2,6 +2,8 @@ BIP: ? Title: Schnorr Signatures for secp256k1 Author: Pieter Wuille + Jonas Nick + Tim Ruffing Status: Draft Type: Informational License: BSD-2-Clause diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 2abb185..7b75fa0 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -3,6 +3,8 @@ Layer: Consensus (soft fork) Title: Taproot: SegWit version 1 output spending rules Author: Pieter Wuille + Jonas Nick + Anthony Towns Comments-Summary: No comments yet. Comments-URI: Status: Draft diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index 50f9d5e..ceb7fd8 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -3,6 +3,8 @@ Layer: Consensus (soft fork) Title: Validation of Taproot Scripts Author: Pieter Wuille + Jonas Nick + Anthony Towns Comments-Summary: No comments yet. Comments-URI: Status: Draft -- cgit v1.2.3 From 17b3f9e01aad881695ac9104f877b07c2cf9a9ce Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 17 Dec 2019 17:27:36 -0800 Subject: Update Post-History field for taproot/tapscript --- bip-taproot.mediawiki | 1 + bip-tapscript.mediawiki | 1 + 2 files changed, 2 insertions(+) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 7b75fa0..6090a71 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -12,6 +12,7 @@ Created: License: BSD-3-Clause Requires: bip-schnorr + Post-History: 2019-05-06: https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2019-May/016914.html [bitcoin-dev] Taproot proposal ==Introduction== diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index ceb7fd8..ab0b5a2 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -12,6 +12,7 @@ Created: License: BSD-3-Clause Requires: bip-schnorr, bip-taproot + Post-History: 2019-05-06: https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2019-May/016914.html [bitcoin-dev] Taproot proposal ==Introduction== -- cgit v1.2.3 From 3318d707e1ba6f146a9fdee8720783f9de61247e Mon Sep 17 00:00:00 2001 From: stefanwouldgo Date: Thu, 28 Nov 2019 14:48:20 +0100 Subject: more precise wording on limits there are no tx or block size limits (post-Segwit), just block weight limit better wording --- bip-tapscript.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index a1302ec..d4347a6 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -126,7 +126,7 @@ In summary, the semantics of the [https://github.com/bitcoin/bips/blob/master/bi ===Resource limits=== In addition to changing the semantics of a number of opcodes, there are also some changes to the resource limitations: -* '''Script size limit''' The maximum script size of 10000 bytes does not apply. Their size is only implicitly limited by the limits on transaction and block size.'''Why is a limit on script size no longer needed?''' Since there is no scriptCode directly included in the signature hash (only indirectly through a precomputable tapleaf hash), the CPU time spent on a signature check is no longer proportional to the size of the script being executed. +* '''Script size limit''' The maximum script size of 10000 bytes does not apply. Their size is only implicitly bounded by the block weight limit.'''Why is a limit on script size no longer needed?''' Since there is no scriptCode directly included in the signature hash (only indirectly through a precomputable tapleaf hash), the CPU time spent on a signature check is no longer proportional to the size of the script being executed. * '''Non-push opcodes limit''' The maximum non-push opcodes limit of 201 per script does not apply.'''Why is a limit on the number of opcodes no longer needed?''' An opcode limit only helps to the extent that it can prevent data structures from growing unboundedly during execution (both because of memory usage, and because of time that may grow in proportion to the size of those structures). The size of stack and altstack is already independently limited. By using O(1) logic for OP_IF, OP_NOTIF, OP_ELSE, and OP_ENDIF as suggested [https://bitslog.com/2017/04/17/new-quadratic-delays-in-bitcoin-scripts/ here] and implemented [https://github.com/bitcoin/bitcoin/pull/16902 here], the only other instance can be avoided as well. * '''Sigops limit''' The sigops in tapscripts do not count towards the block-wide limit of 80000 (weighted). Instead, there is a per-script sigops ''budget''. The budget equals 50 + the total serialized size in bytes of the transaction input's witness (including the CCompactSize prefix). Executing a signature opcode (OP_CHECKSIG, OP_CHECKSIGVERIFY, or OP_CHECKSIGADD) with a non-empty signature decrements the budget by 50. If that brings the budget below zero, the script fails immediately. Signature opcodes with unknown public key type and non-empty signature are also counted.'''The tapscript sigop limit''' The signature opcode limit protects against scripts which are slow to verify due to excessively many signature operations. In tapscript the number of signature opcodes does not count towards the BIP141 or legacy sigop limit. The old sigop limit makes transaction selection in block construction unnecessarily difficult because it is a second constraint in addition to weight. Instead, the number of tapscript signature opcodes is limited by witness weight. Additionally, the limit applies to the transaction input instead of the block and only actually executed signature opcodes are counted. Tapscript execution allows one signature opcode per 50 witness weight units plus one free signature opcode.'''Parameter choice of the sigop limit''' Regular witnesses are unaffected by the limit as their weight is composed of public key and (SIGHASH_ALL) signature pairs with ''33 + 65'' weight units each (which includes a 1 weight unit CCompactSize tag). This is also the case if public keys are reused in the script because a signature's weight alone is 65 or 66 weight units. However, the limit increases the fees of abnormal scripts with duplicate signatures (and public keys) by requiring additional weight. The weight per sigop factor 50 corresponds to the ratio of BIP141 block limits: 4 mega weight units divided by 80,000 sigops. The "free" signature opcode permitted by the limit exists to account for the weight of the non-witness parts of the transaction input.'''Why are only signature opcodes counted toward the budget, and not for example hashing opcodes or other expensive operations?''' It turns out that the CPU cost per witness byte for verification of a script consisting of the maximum density of signature checking opcodes (taking the 50 WU/sigop limit into account) is already very close to that of scripts packed with other opcodes, including hashing opcodes (taking the 520 byte stack element limit into account) and OP_ROLL (taking the 1000 stack element limit into account). That said, the construction is very flexible, and allows adding new signature opcodes like CHECKSIGFROMSTACK to count towards the limit through a soft fork. Even if in the future new opcodes are introduced which change normal script cost there is no need to stuff the witness with meaningless data. Instead, the taproot annex can be used to add weight to the witness without increasing the actual witness size.. * '''Stack + altstack element count limit''' The existing limit of 1000 elements in the stack and altstack together after every executed opcode remains. It is extended to also apply to the size of initial stack. -- cgit v1.2.3 From 63a19990fde1989f838a05bfc621adcb51485bb5 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Tue, 31 Dec 2019 14:26:50 +0100 Subject: Clarify nonce generation - Separate nonce generation into getting a random byte string and converting it to a suitable scalar ... - ... to make clear that the byte string can be generated differently. - Make the warning a little bit more prominent and improve writing --- bip-schnorr.mediawiki | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index b20fb48..084b33f 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -151,7 +151,8 @@ The algorithm ''Sign(sk, m)'' is defined as: * Fail if ''d' = 0'' or ''d' ≥ n'' * Let ''P = d'⋅G'' * Let ''d = d' '' if ''has_square_y(P)'', otherwise let ''d = n - d' ''. -* Let ''k' = int(hashBIPSchnorrDerive(bytes(d) || m)) mod n''Note that in general, taking the output of a hash function modulo the curve order will produce an unacceptably biased result. However, for the secp256k1 curve, the order is sufficiently close to ''2256'' that this bias is not observable (''1 - n / 2256'' is around ''1.27 * 2-128'').. +* Let ''rand = hashBIPSchnorrDerive(bytes(d) || m)''. +* Let ''k' = int(rand) mod n''Note that in general, taking a uniformly random 256-bit integer modulo the curve order will produce an unacceptably biased result. However, for the secp256k1 curve, the order is sufficiently close to ''2256'' that this bias is not observable (''1 - n / 2256'' is around ''1.27 * 2-128'').. * Fail if ''k' = 0''. * Let ''R = k'⋅G''. * Let ''k = k' '' if ''has_square_y(R)'', otherwise let ''k = n - k' ''. @@ -160,14 +161,14 @@ The algorithm ''Sign(sk, m)'' is defined as: ==== Alternative Signing ==== -It should be noted that various alternative signing algorithms can be used to produce equally valid signatures. The algorithm in the previous section will always produce the same signature for a given message and public key, but the ''k'' value (and hence ''R'') may be generated in other ways, producing a different, but still valid, signature (in other words, it is not a ''unique'' signature scheme). +It should be noted that various alternative signing algorithms can be used to produce equally valid signatures. The algorithm in the previous section is deterministic, i.e., it will always produce the same signature for a given message and secret key. This method does not need a random number generator (RNG) at signing time and is thus trivially robust against failures of RNGs. Alternatively the 32-byte ''rand'' value may be generated in other ways, producing a different but still valid signature (in other words, this is not a ''unique'' signature scheme). '''No matter which method is used to generate the ''rand'' value, the value must be a fresh uniformly random 32-byte string which is not even partially predictable for the attacker.''' -'''Synthetic nonces''' When a random number generator (RNG) is available, 32 bytes of RNG output can be appended to the input to ''hashBIPSchnorrDerive''. This will change the corresponding line in the signing algorithm to ''k' = int(hashBIPSchnorrDerive(bytes(d) || m || get_32_bytes_from_rng())) mod n'', where ''get_32_bytes_from_rng()'' is the call to the RNG. Adding RNG output may improve protection against [https://moderncrypto.org/mail-archive/curves/2017/000925.html fault injection attacks and side-channel attacks]. It is safe to add randomness from a low-quality randomness source, i.e., an RNG with low entropy. +'''Synthetic nonces''' For instance when a RNG is available, 32 bytes of RNG output can be appended to the input to ''hashBIPSchnorrDerive''. This will change the corresponding line in the signing algorithm to ''rand = hashBIPSchnorrDerive(bytes(d) || m || get_32_bytes_from_rng())'', where ''get_32_bytes_from_rng()'' is the call to the RNG. Adding RNG output may improve protection against [https://moderncrypto.org/mail-archive/curves/2017/000925.html fault injection attacks and side-channel attacks], and it is safe to add the output of a low-entropy RNG. '''Nonce exfiltration protection''' It is possible to strengthen the nonce generation algorithm using a second device. In this case, the second device contributes randomness which the actual signer provably incorporates into its nonce. This prevents certain attacks where the signer device is compromised and intentionally tries to leak the secret key through its nonce selection. '''Multisignatures''' This signature scheme is compatible with various types of multisignature and threshold schemes such as [https://eprint.iacr.org/2018/068 MuSig], where a single public key requires holders of multiple secret keys to participate in signing (see Applications below). -'''It is important to note that multisignature signing schemes in general are insecure with the nonce generation from the default signing algorithm above (or any deterministic nonce algorithm).''' +'''It is important to note that multisignature signing schemes in general are insecure with the ''rand'' generation from the default signing algorithm above (or any other deterministic method).''' ==== Verification ==== -- cgit v1.2.3 From 39a18f4b18c507cf425aa2dc620b7d0d7e3cf1ab Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 7 Jan 2020 13:17:13 -0800 Subject: Redefine leaf versions to be incrementally increasing from 0 --- bip-taproot.mediawiki | 20 ++++++++++---------- bip-tapscript.mediawiki | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 6090a71..2b91da8 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -59,19 +59,19 @@ The following rules only apply when such an output is being spent. Any other out * Let ''q'' be the 32-byte array containing the witness program (the second push in the scriptPubKey) which represents a public key according to bip-schnorr. * Fail if the witness stack has 0 elements. -* If there are at least two witness elements, and the first byte of the last element is 0x50'''Why is the first byte of the annex 0x50?''' Like the 0xc0 constant, 0x50 is chosen as it could not be confused with a valid P2WPKH or P2WSH spending. As the control block's initial byte's lowest bit is used to indicate the public key's Y squareness, each script version needs two subsequence byte values that are both not yet used in P2WPKH or P2WSH spending. To indicate the annex, only an "unpaired" available byte is necessary like 0x50. This choice maximizes the available options for future script versions., this last element is called ''annex'' ''a'''''What is the purpose of the annex?''' The annex is a reserved space for future extensions, such as indicating the validation costs of computationally expensive new opcodes in a way that is recognizable without knowing the outputs being spent. Until the meaning of this field is defined by another softfork, users SHOULD NOT include annex in transactions, or it may lead to PERMANENT FUND LOSS. and is removed from the witness stack. The annex (or the lack of thereof) is always covered by the transaction digest and contributes to transaction weight, but is otherwise ignored during taproot validation. +* If there are at least two witness elements, and the first byte of the last element is 0x50'''Why is the first byte of the annex 0x50?''' Like the choice to always set the top two bits of the control block's first byte the, 0x50 is chosen as it could not be confused with a valid P2WPKH or P2WSH spending. As the control block's initial byte's lowest bit is used to indicate the public key's Y squareness, each leaf version needs two subsequent byte values that are both not yet used in P2WPKH or P2WSH spending. To indicate the annex, only an "unpaired" available byte is necessary like 0x50. This choice maximizes the available options for future script versions., this last element is called ''annex'' ''a'''''What is the purpose of the annex?''' The annex is a reserved space for future extensions, such as indicating the validation costs of computationally expensive new opcodes in a way that is recognizable without knowing the scriptPubKey of the output being spent. Until the meaning of this field is defined by another softfork, users SHOULD NOT include annex in transactions, or it may lead to PERMANENT FUND LOSS. and is removed from the witness stack. The annex (or the lack of thereof) is always covered by the transaction digest and contributes to transaction weight, but is otherwise ignored during taproot validation. * If there is exactly one element left in the witness stack, key path spending is used: ** The single witness stack element is interpreted as the signature and must be valid (see the next section) for the public key ''q'' and taproot transaction digest (to be defined hereinafter) as message. Fail if it is not. Otherwise pass. * If there are at least two witness elements left, script path spending is used: ** Call the second-to-last stack element ''s'', the script. ** The last stack element is called the control block ''c'', and must have length ''33 + 32m'', for a value of ''m'' that is an integer between 0 and 128'''Why is the Merkle path length limited to 128?''' The optimally space-efficient Merkle tree can be constructed based on the probabilities of the scripts in the leaves, using the Huffman algorithm. This algorithm will construct branches with lengths approximately equal to ''log2(1/probability)'', but to have branches longer than 128 you would need to have scripts with an execution chance below 1 in ''2128''. As that is our security bound, scripts that truly have such a low chance can probably be removed entirely., inclusive. Fail if it does not have such a length. ** Let ''p = c[1:33]'' and let ''P = point(p)'' where ''point'' and ''[:]'' are defined as in bip-schnorr. Fail if this point is not on the curve. -** Let ''l = c[0] & 0xfe'', the leaf version'''What is the purpose of the first byte of the control block?''' The first byte of the control block has three distinct functions: +** Call ''(c[0] ^ 0xc0) >> 1'' the leaf version'''What is the purpose of the first byte of the control block?''' The first byte of the control block has three distinct functions: * The low bit is used to denote whether the point represented by public key ''q'' is negated before verifying the taproot tweak.'''Why is it necessary to reveal a bit to indicate if the point represented by the output public key is negated in a script path spend?''' The ''point'' function (defined in bip-schnorr) always constructs a point with a square Y coordinate, but because ''Q'' is constructed by adding the taproot tweak to the internal public key ''P'', it cannot easily be guaranteed that ''Q'' in fact has such a Y coordinate. Therefore, before verifying the taproot tweak the original point is restored by negating if necessary. We can not ignore the Y coordinate because it would prevent batch verification. Trying out multiple internal keys until there's such a ''Q'' is possible but undesirable and unnecessary since this information about the Y coordinate only consumes an unused bit. -* By keeping the top two bits set to true, it can be guaranteed that scripts can be recognized without knowledge of the UTXO being spent, simplifying analysis. This is because such values cannot occur as first byte of the final stack element in either P2WPKH or P2WSH spends. -* The remaining five bits are used for introducing new script versions that are not observable unless actually executed. +* Some types of static analysis may benefit from the ability to analyse spends without access to the output being spent. We achieve that for leaf versions 0 to 31 via flipping the top two bits of the first byte of the control block and observing that this ensures they can be distinguished from P2WPKH and P2WSH spends -- as for P2WPKH, the last witness stack item is a public key, whose first byte is either 0x02 or 0x03, and for P2WSH, the last item is a script, and scripts must contain valid opcodes, but no value ≥ 0xc0 is a valid opcode. +* The remaining five bits encode the leaf version, which can be used for introducing new script versions that are not observable unless actually executed. . -** Let ''k0 = hashTapLeaf(l || compact_size(size of s) || s)''; also call it the ''tapleaf hash''. +** Let ''k0 = hashTapLeaf(c[0] & 0xfe || compact_size(size of s) || s)''; also call it the ''tapleaf hash''. ** For ''j'' in ''[0,1,...,m-1]'': *** Let ''ej = c[33+32j:65+32j]''. *** Let ''kj+1 depend on whether ''kj < ej'' (lexicographically)'''Why are child elements sorted before hashing in the Merkle tree?''' By doing so, it is not necessary to reveal the left/right directions along with the hashes in revealed Merkle branches. This is possible because we do not actually care about the position of specific scripts in the tree; only that they are actually committed to.: @@ -81,7 +81,7 @@ The following rules only apply when such an output is being spent. Any other out ** If ''t ≥ 0xFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141'' (order of secp256k1), fail. ** Let ''Q = point(q) if (c[0] & 1) = 1 and -point(q) otherwise''. Fail if this point is not on the curve. ** If ''Q ≠ P + int(t)G'', fail. -** Execute the script, according to the applicable script rules'''What are the applicable script rules in script path spends?''' Bip-tapscript specifies validity rules that apply if the leaf version is ''0xc0'', but future proposals can introduce rules for other leaf versions., using the witness stack elements excluding the script ''s'', the control block ''c'', and the annex ''a'' if present, as initial stack. +** Execute the script, according to the applicable script rules'''What are the applicable script rules in script path spends?''' Bip-tapscript specifies validity rules that apply if the leaf version is 0, but future proposals can introduce rules for other leaf versions., using the witness stack elements excluding the script ''s'', the control block ''c'', and the annex ''a'' if present, as initial stack. ''q'' is referred to as ''taproot output key'' and ''p'' as ''taproot internal key''. @@ -209,7 +209,7 @@ The following function, taproot_output_script, returns a byte array def taproot_tree_helper(script_tree): if isinstance(script_tree, tuple): leaf_version, script = script_tree - h = tagged_hash("TapLeaf", bytes([leaf_version]) + ser_script(script)) + h = tagged_hash("TapLeaf", bytes([(2 * leaf_version) ^ 0xc0]) + ser_script(script)) return ([((leaf_version, script), bytes())], h) left, left_h = taproot_tree_helper(script_tree[0]) right, right_h = taproot_tree_helper(script_tree[1]) @@ -221,8 +221,8 @@ def taproot_tree_helper(script_tree): def taproot_output_script(internal_pubkey, script_tree): """Given a internal public key and a tree of scripts, compute the output script. script_tree is either: - - a (leaf_version, script) tuple (leaf_version is 0xc0 for bip-tapscript scripts) - - a list of two elements, each with the same structure as script_tree itself + - a (leaf_version, script) tuple (leaf_version is 0 for bip-tapscript scripts) + - a list of two elements, each with the same structure as script_tree itself""" - None """ if script_tree is None: @@ -271,7 +271,7 @@ def taproot_sign_script(internal_pubkey, script_tree, script_num, inputs): (leaf_version, script), path = info[script_num] _, is_negated = taproot_tweak_pubkey(internal_pubkey, h) output_pubkey_tag = 0 if is_negated else 1 - pubkey_data = bytes([output_pubkey_tag + leaf_version]) + internal_pubkey + pubkey_data = bytes([output_pubkey_tag ^ (2 * leaf_version) ^ 0xc0]) + internal_pubkey return inputs + [script, pubkey_data + path] diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index 759d0d8..120a617 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -51,7 +51,7 @@ The rules below only apply when validating a transaction input for which all of * The transaction input is a '''segregated witness spend''' (i.e., the scriptPubKey contains a witness program as defined in [https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki BIP141]). * It is a '''taproot spend''' as defined in bip-taproot (i.e., the witness version is 1, the witness program is 32 bytes, and it is not P2SH wrapped). * It is a '''script path spend''' as defined in bip-taproot (i.e., after removing the optional annex from the witness stack, two or more stack elements remain). -* The leaf version is ''0xc0'' (i.e. the first byte of the last witness element after removing the optional annex is ''0xc0'' or ''0xc1'')'''How is the ''0xc0'' constant chosen?''' Following the guidelines in bip-taproot, by choosing a value having the two top bits set, tapscript spends are identifiable even without access to the UTXO being spent., marking it as a '''tapscript spend'''. +* The leaf version is 0 (i.e. the first byte of the last witness element after removing the optional annex is ''0xc0'' or ''0xc1''), marking it as a '''tapscript spend'''. Validation of such inputs must be equivalent to performing the following steps in the specified order. # If the input is invalid due to BIP141 or bip-taproot, fail. -- cgit v1.2.3 From f978178d6b8738425d27fb1c007cee6ac136efc4 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Fri, 10 Jan 2020 21:42:34 +1000 Subject: go back to leaf_version but different rationale --- bip-taproot.mediawiki | 24 ++++++++++-------------- bip-tapscript.mediawiki | 2 +- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 2b91da8..7d2318e 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -59,19 +59,15 @@ The following rules only apply when such an output is being spent. Any other out * Let ''q'' be the 32-byte array containing the witness program (the second push in the scriptPubKey) which represents a public key according to bip-schnorr. * Fail if the witness stack has 0 elements. -* If there are at least two witness elements, and the first byte of the last element is 0x50'''Why is the first byte of the annex 0x50?''' Like the choice to always set the top two bits of the control block's first byte the, 0x50 is chosen as it could not be confused with a valid P2WPKH or P2WSH spending. As the control block's initial byte's lowest bit is used to indicate the public key's Y squareness, each leaf version needs two subsequent byte values that are both not yet used in P2WPKH or P2WSH spending. To indicate the annex, only an "unpaired" available byte is necessary like 0x50. This choice maximizes the available options for future script versions., this last element is called ''annex'' ''a'''''What is the purpose of the annex?''' The annex is a reserved space for future extensions, such as indicating the validation costs of computationally expensive new opcodes in a way that is recognizable without knowing the scriptPubKey of the output being spent. Until the meaning of this field is defined by another softfork, users SHOULD NOT include annex in transactions, or it may lead to PERMANENT FUND LOSS. and is removed from the witness stack. The annex (or the lack of thereof) is always covered by the transaction digest and contributes to transaction weight, but is otherwise ignored during taproot validation. +* If there are at least two witness elements, and the first byte of the last element is 0x50'''Why is the first byte of the annex 0x50?''' The 0x50 is chosen as it could not be confused with a valid P2WPKH or P2WSH spending. As the control block's initial byte's lowest bit is used to indicate the public key's Y squareness, each leaf version needs an even byte value and the immediately following odd byte value that are both not yet used in P2WPKH or P2WSH spending. To indicate the annex, only an "unpaired" available byte is necessary like 0x50. This choice maximizes the available options for future script versions., this last element is called ''annex'' ''a'''''What is the purpose of the annex?''' The annex is a reserved space for future extensions, such as indicating the validation costs of computationally expensive new opcodes in a way that is recognizable without knowing the scriptPubKey of the output being spent. Until the meaning of this field is defined by another softfork, users SHOULD NOT include annex in transactions, or it may lead to PERMANENT FUND LOSS. and is removed from the witness stack. The annex (or the lack of thereof) is always covered by the transaction digest and contributes to transaction weight, but is otherwise ignored during taproot validation. * If there is exactly one element left in the witness stack, key path spending is used: ** The single witness stack element is interpreted as the signature and must be valid (see the next section) for the public key ''q'' and taproot transaction digest (to be defined hereinafter) as message. Fail if it is not. Otherwise pass. * If there are at least two witness elements left, script path spending is used: ** Call the second-to-last stack element ''s'', the script. ** The last stack element is called the control block ''c'', and must have length ''33 + 32m'', for a value of ''m'' that is an integer between 0 and 128'''Why is the Merkle path length limited to 128?''' The optimally space-efficient Merkle tree can be constructed based on the probabilities of the scripts in the leaves, using the Huffman algorithm. This algorithm will construct branches with lengths approximately equal to ''log2(1/probability)'', but to have branches longer than 128 you would need to have scripts with an execution chance below 1 in ''2128''. As that is our security bound, scripts that truly have such a low chance can probably be removed entirely., inclusive. Fail if it does not have such a length. ** Let ''p = c[1:33]'' and let ''P = point(p)'' where ''point'' and ''[:]'' are defined as in bip-schnorr. Fail if this point is not on the curve. -** Call ''(c[0] ^ 0xc0) >> 1'' the leaf version'''What is the purpose of the first byte of the control block?''' The first byte of the control block has three distinct functions: -* The low bit is used to denote whether the point represented by public key ''q'' is negated before verifying the taproot tweak.'''Why is it necessary to reveal a bit to indicate if the point represented by the output public key is negated in a script path spend?''' The ''point'' function (defined in bip-schnorr) always constructs a point with a square Y coordinate, but because ''Q'' is constructed by adding the taproot tweak to the internal public key ''P'', it cannot easily be guaranteed that ''Q'' in fact has such a Y coordinate. Therefore, before verifying the taproot tweak the original point is restored by negating if necessary. We can not ignore the Y coordinate because it would prevent batch verification. Trying out multiple internal keys until there's such a ''Q'' is possible but undesirable and unnecessary since this information about the Y coordinate only consumes an unused bit. -* Some types of static analysis may benefit from the ability to analyse spends without access to the output being spent. We achieve that for leaf versions 0 to 31 via flipping the top two bits of the first byte of the control block and observing that this ensures they can be distinguished from P2WPKH and P2WSH spends -- as for P2WPKH, the last witness stack item is a public key, whose first byte is either 0x02 or 0x03, and for P2WSH, the last item is a script, and scripts must contain valid opcodes, but no value ≥ 0xc0 is a valid opcode. -* The remaining five bits encode the leaf version, which can be used for introducing new script versions that are not observable unless actually executed. -. -** Let ''k0 = hashTapLeaf(c[0] & 0xfe || compact_size(size of s) || s)''; also call it the ''tapleaf hash''. +** Let ''v = c[0] & 0xfe'' and call it the ''leaf version'''''What constraints are there on the leaf version?''' First, the leaf version cannot be odd as ''c[0] & 0xfe'' will always be even, and cannot be ''0x50'' as that would result in ambiguity with the annex. In addition, in order to support some forms of static analysis that rely on being able to identify script spends without access to the output being spent, it is recommended to avoid using any leaf versions that would conflict with a valid first byte of either a valid P2WPKH pubkey or a valid P2WSH script (that is, both ''v'' and ''v | 1'' should be an undefined, invalid or disabled opcode or an opcode that is not valid as the first opcode). The values that comply to this rule are the 32 even values between ''0xc0'' and ''0xfe'' and also ''0x66'', ''0x7e'', ''0x80'', ''0x84'', ''0x96'', ''0x98'', ''0xba'', ''0xbc'', ''0xbe''. Note also that this constraint implies that leaf versions should be shared amongst different witness versions, as knowing the witness version requires access to the output being spent.. +** Let ''k0 = hashTapLeaf(v || compact_size(size of s) || s)''; also call it the ''tapleaf hash''. ** For ''j'' in ''[0,1,...,m-1]'': *** Let ''ej = c[33+32j:65+32j]''. *** Let ''kj+1 depend on whether ''kj < ej'' (lexicographically)'''Why are child elements sorted before hashing in the Merkle tree?''' By doing so, it is not necessary to reveal the left/right directions along with the hashes in revealed Merkle branches. This is possible because we do not actually care about the position of specific scripts in the tree; only that they are actually committed to.: @@ -79,9 +75,9 @@ The following rules only apply when such an output is being spent. Any other out **** If ''kj ≥ ej'': ''kj+1 = hashTapBranch(ej || kj)''. ** Let ''t = hashTapTweak(p || km)''. ** If ''t ≥ 0xFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141'' (order of secp256k1), fail. -** Let ''Q = point(q) if (c[0] & 1) = 1 and -point(q) otherwise''. Fail if this point is not on the curve. +** Let ''Q = point(q) if (c[0] & 1) = 1 and -point(q) otherwise'''''Why is it necessary to reveal a bit to indicate if the point represented by the output public key is negated in a script path spend?''' The ''point'' function (defined in bip-schnorr) always constructs a point with a square Y coordinate, but because ''Q'' is constructed by adding the taproot tweak to the internal public key ''P'', it cannot easily be guaranteed that ''Q'' in fact has such a Y coordinate. Therefore, before verifying the taproot tweak the original point is restored by negating if necessary. We can not ignore the Y coordinate because it would prevent batch verification. Trying out multiple internal keys until there's such a ''Q'' is possible but undesirable and unnecessary since this information about the Y coordinate only consumes an unused bit.. Fail if this point is not on the curve. ** If ''Q ≠ P + int(t)G'', fail. -** Execute the script, according to the applicable script rules'''What are the applicable script rules in script path spends?''' Bip-tapscript specifies validity rules that apply if the leaf version is 0, but future proposals can introduce rules for other leaf versions., using the witness stack elements excluding the script ''s'', the control block ''c'', and the annex ''a'' if present, as initial stack. +** Execute the script, according to the applicable script rules'''What are the applicable script rules in script path spends?''' Bip-tapscript specifies validity rules that apply for leaf version 0xc0, but future proposals can introduce rules for other leaf versions., using the witness stack elements excluding the script ''s'', the control block ''c'', and the annex ''a'' if present, as initial stack. ''q'' is referred to as ''taproot output key'' and ''p'' as ''taproot internal key''. @@ -209,7 +205,7 @@ The following function, taproot_output_script, returns a byte array def taproot_tree_helper(script_tree): if isinstance(script_tree, tuple): leaf_version, script = script_tree - h = tagged_hash("TapLeaf", bytes([(2 * leaf_version) ^ 0xc0]) + ser_script(script)) + h = tagged_hash("TapLeaf", bytes([leaf_version]) + ser_script(script)) return ([((leaf_version, script), bytes())], h) left, left_h = taproot_tree_helper(script_tree[0]) right, right_h = taproot_tree_helper(script_tree[1]) @@ -221,8 +217,8 @@ def taproot_tree_helper(script_tree): def taproot_output_script(internal_pubkey, script_tree): """Given a internal public key and a tree of scripts, compute the output script. script_tree is either: - - a (leaf_version, script) tuple (leaf_version is 0 for bip-tapscript scripts) - - a list of two elements, each with the same structure as script_tree itself""" + - a (leaf_version, script) tuple (leaf_version is 0xc0 for bip-tapscript scripts) + - a list of two elements, each with the same structure as script_tree itself - None """ if script_tree is None: @@ -237,7 +233,7 @@ def taproot_output_script(internal_pubkey, script_tree): To spend this output using script ''D'', the control block would contain the following data in this order: - + The TapTweak would then be computed as described in [[#script-validation-rules]] like so: @@ -271,7 +267,7 @@ def taproot_sign_script(internal_pubkey, script_tree, script_num, inputs): (leaf_version, script), path = info[script_num] _, is_negated = taproot_tweak_pubkey(internal_pubkey, h) output_pubkey_tag = 0 if is_negated else 1 - pubkey_data = bytes([output_pubkey_tag ^ (2 * leaf_version) ^ 0xc0]) + internal_pubkey + pubkey_data = bytes([output_pubkey_tag + leaf_version]) + internal_pubkey return inputs + [script, pubkey_data + path] diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index 120a617..e9c4278 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -51,7 +51,7 @@ The rules below only apply when validating a transaction input for which all of * The transaction input is a '''segregated witness spend''' (i.e., the scriptPubKey contains a witness program as defined in [https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki BIP141]). * It is a '''taproot spend''' as defined in bip-taproot (i.e., the witness version is 1, the witness program is 32 bytes, and it is not P2SH wrapped). * It is a '''script path spend''' as defined in bip-taproot (i.e., after removing the optional annex from the witness stack, two or more stack elements remain). -* The leaf version is 0 (i.e. the first byte of the last witness element after removing the optional annex is ''0xc0'' or ''0xc1''), marking it as a '''tapscript spend'''. +* The leaf version is ''0xc0'' (i.e. the first byte of the last witness element after removing the optional annex is ''0xc0'' or ''0xc1''), marking it as a '''tapscript spend'''. Validation of such inputs must be equivalent to performing the following steps in the specified order. # If the input is invalid due to BIP141 or bip-taproot, fail. -- cgit v1.2.3 From 138c62c8b04427988e3ae9d84940d121371eb31b Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 13 Jan 2020 07:27:18 -0800 Subject: Delete precompiled file --- bip-schnorr/__pycache__/reference.cpython-36.pyc | Bin 5278 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 bip-schnorr/__pycache__/reference.cpython-36.pyc diff --git a/bip-schnorr/__pycache__/reference.cpython-36.pyc b/bip-schnorr/__pycache__/reference.cpython-36.pyc deleted file mode 100644 index cce1e04..0000000 Binary files a/bip-schnorr/__pycache__/reference.cpython-36.pyc and /dev/null differ -- cgit v1.2.3 From c0d2f93f3c3c3dcee2318ea26f946ae17de37865 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 13 Jan 2020 14:10:26 -0800 Subject: Abstract out common signature message calculation --- bip-taproot.mediawiki | 87 +++++++++++++++++++++++-------------------------- bip-tapscript.mediawiki | 32 ++++++++---------- 2 files changed, 53 insertions(+), 66 deletions(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 7d2318e..a05d064 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -83,68 +83,61 @@ The following rules only apply when such an output is being spent. Any other out === Signature validation rules === -The following rules apply: +We first define a reusable common signature message calculation function, followed by the actual signature validation as it's used in key path spending. -* If the signature is not 64'''Why permit two signature lengths?''' By making the most common type of hash_type implicit, a byte can often be saved. or 65 bytes, fail. -* If the signature size is 65 bytes: -** If the final byte is not a valid hash_type (defined hereinafter), fail. -** If the final byte is 0x00, fail'''Why can the hash_type not be 0x00 in 65-byte signatures?''' Permitting that would enable malleating (by third parties, including miners) 64-byte signatures into 65-byte ones, resulting in a different `wtxid` and a different fee rate than the creator intended. -** If the first 64 bytes are not a valid signature according to bip-schnorr for the public key and message set to the transaction digest with hash_type set as the final byte, fail. -* If the signature size is 64 bytes: -** If it is not a valid signature according to bip-schnorr for the public key and the hash_type = 0x00 transaction digest as message, fail. -* Otherwise the signature is valid. +==== Common signature message ==== -==== hash_type ==== - -hash_type is an 8-bit unsigned value. The SIGHASH encodings from the legacy script system are used, including SIGHASH_ALL, SIGHASH_NONE, SIGHASH_SINGLE, and SIGHASH_ANYONECANPAY. Use of the default hash_type = 0x00 results in signing over the whole transaction just as for SIGHASH_ALL. - -The following use of hash_type are invalid, and fail execution: +The function ''SigMsg(hash_type, ext_flag)'' computes the message being signed as a byte array. It is implicitly also a function of the spending transaction and the outputs it spends, but these are not listed to keep notation simple. +The parameter ''hash_type'' is an 8-bit unsigned value. The SIGHASH encodings from the legacy script system are reused, including SIGHASH_ALL, SIGHASH_NONE, SIGHASH_SINGLE, and SIGHASH_ANYONECANPAY, plus a default ''hash_type'' (0) which results in signing over the whole transaction just as for SIGHASH_ALL. The following restrictions apply, which cause validation failure if violated: +* Using any undefined ''hash_type'' (not ''0x00'', ''0x01'', ''0x02'', ''0x03'', ''0x81'', ''0x82'', or ''0x83'''''Why reject unknown ''hash_type'' values?''' By doing so, it is easier to reason about the worst case amount of signature hashing an implementation with adequate caching must perform.). * Using SIGHASH_SINGLE without a "corresponding output" (an output with the same index as the input being verified). -* Using any hash_type value that is not 0x00, 0x01, 0x02, 0x03, 0x81, 0x82, or 0x83'''Why reject unknown hash_type values?''' By doing so, it is easier to reason about the worst case amount of signature hashing an implementation with adequate caching must perform.. -* The signature has 65 bytes, and hash_type is 0x00. -==== Transaction digest ==== +The parameter ''ext_flag'' is an integer in range 0-127, and is used for indicating the presence of extensions. -As the message for signature verification, transaction digest is ''hashTapSighash'' of the following values (size in byte) serialized. Numerical values in 2, 4, or 8-byte are encoded in little-endian. +If the parameters take acceptable values, the message is the concatenation of the following data, in order(with byte size of each item listed in parentheses). Numerical values in 2, 4, or 8-byte are encoded in little-endian. * Control: -** epoch (1): always 0. '''What's the purpose of the epoch?''' The epoch can be increased to allow securely creating new transaction digest algorithms with large changes to the structure or interpretation of hash_type if needed. -** hash_type (1). +** ''hash_type'' (1). * Transaction data: -** nVersion (4): the nVersion of the transaction. -** nLockTime (4): the nLockTime of the transaction. -** If the SIGHASH_ANYONECANPAY flag is not set: -*** sha_prevouts (32): the SHA256 of the serialization of all input outpoints. -*** sha_amounts (32): the SHA256 of the serialization of all input amounts. -*** sha_sequences (32): the SHA256 of the serialization of all input nSequence. -** If neither the SIGHASH_NONE nor the SIGHASH_SINGLE flag is set: -*** sha_outputs (32): the SHA256 of the serialization of all outputs in CTxOut format. +** ''nVersion'' (4): the ''nVersion'' of the transaction. +** ''nLockTime'' (4): the ''nLockTime'' of the transaction. +** If the ''hash_type & 0x80'' does not equal SIGHASH_ANYONECANPAY: +*** ''sha_prevouts'' (32): the SHA256 of the serialization of all input outpoints. +*** ''sha_amounts'' (32): the SHA256 of the serialization of all input amounts. +*** ''sha_sequences'' (32): the SHA256 of the serialization of all input ''nSequence''. +** If ''hash_type & 3'' does not equal SIGHASH_NONE or SIGHASH_SINGLE: +*** ''sha_outputs'' (32): the SHA256 of the serialization of all outputs in CTxOut format. * Data about this input: -** spend_type (1): -*** Bit 0 is set if an annex is present (the original witness stack has two or more witness elements, and the first byte of the last element is 0x50). -*** The other bits are unset. -** scriptPubKey (35): scriptPubKey of the previous output spent by this input, serialized as script inside CTxOut. Its size is always 35 bytes. -** If the SIGHASH_ANYONECANPAY flag is set: -*** outpoint (36): the COutPoint of this input (32-byte hash + 4-byte little-endian). -*** amount (8): value of the previous output spent by this input. -*** nSequence (4): nSequence of this input. -** If the SIGHASH_ANYONECANPAY flag is not set: -*** input_index (4): index of this input in the transaction input vector. Index of the first input is 0. -** If bit 0 of spend_type is set: -*** sha_annex (32): the SHA256 of (compact_size(size of annex) || annex). +** ''spend_type'' (1): equal to ''(ext_flag * 2) + annex_present'', where ''annex_present'' is 0 if no annex is present, or 1 otherwise (the original witness stack has two or more witness elements, and the first byte of the last element is ''0x50'') +** ''scriptPubKey'' (35): ''scriptPubKey'' of the previous output spent by this input, serialized as script inside CTxOut. Its size is always 35 bytes. +** If ''hash_type & 0x80'' equals SIGHASH_ANYONECANPAY: +*** ''outpoint'' (36): the COutPoint of this input (32-byte hash + 4-byte little-endian). +*** ''amount'' (8): value of the previous output spent by this input. +*** ''nSequence'' (4): ''nSequence'' of this input. +** If ''hash_type & 0x80'' does not equal SIGHASH_ANYONECANPAY: +*** ''input_index'' (4): index of this input in the transaction input vector. Index of the first input is 0. +** If an annex is present (the lowest bit of ''spend_type'' is set): +*** ''sha_annex'' (32): the SHA256 of ''(compact_size(size of annex) || annex)'', where ''annex'' includes the mandatory ''0x50'' prefix. * Data about this output: -** If the SIGHASH_SINGLE flag is set: -*** sha_single_output (32): the SHA256 of the corresponding output in CTxOut format. +** If ''hash_type & 3'' equals SIGHASH_SINGLE: +*** ''sha_single_output'' (32): the SHA256 of the corresponding output in CTxOut format. -The total number of bytes hashed is at most ''210'' (excluding sub-hashes such as `sha_prevouts`)'''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''178 - is_anyonecanpay * 52 - is_none * 32 + has_annex * 32''.. Sub-hashes may be cached across signatures of the same transaction. +The total length of ''SigMsg()'' is at most ''209'' bytes'''What is the output length of ''SigMsg()''?''' The total length of ''SigMsg()'' can be computed using the following formula: ''177 - is_anyonecanpay * 52 - is_none * 32 + has_annex * 32''.. Note that this does not include the size of sub-hashes such as ''sha_prevouts'', which may be cached across signatures of the same transaction. In summary, the semantics of the [https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki BIP143] sighash types remain unchanged, except the following: -# The way and order of serialization is changed.'''Why is the serialization in the transaction digest changed?''' Hashes that go into the digest and the digest itself are now computed with a single SHA256 invocation instead of double SHA256. There is no expected security improvement by doubling SHA256 because this only protects against length-extension attacks against SHA256 which are not a concern for transaction digests because there is no secret data. Therefore doubling SHA256 is a waste of resources. The digest computation now follows a logical order with transaction level data first, then input data and output data. This allows to efficiently cache the transaction part of the digest across different inputs using the SHA256 midstate. Additionally, sub-hashes can be skipped when calculating the digest (for example `sha_prevouts` if SIGHASH_ANYONECANPAY is set) instead of setting them to zero and then hashing them as in BIP143. Despite that, collisions are made impossible by committing to the length of the data (implicit in hash_type and spend_type) before the variable length data. -# The digest commits to the scriptPubKey'''Why does the transaction digest commit to the scriptPubKey?''' This prevents lying to offline signing devices about output being spent, even when the actually executed script (scriptCode in BIP143) is correct. This means it's possible to compactly prove to a hardware wallet what (unused) execution paths existed.. +# The way and order of serialization is changed.'''Why is the serialization in the transaction digest changed?''' Hashes that go into the digest and the digest itself are now computed with a single SHA256 invocation instead of double SHA256. There is no expected security improvement by doubling SHA256 because this only protects against length-extension attacks against SHA256 which are not a concern for transaction digests because there is no secret data. Therefore doubling SHA256 is a waste of resources. The digest computation now follows a logical order with transaction level data first, then input data and output data. This allows to efficiently cache the transaction part of the digest across different inputs using the SHA256 midstate. Additionally, sub-hashes can be skipped when calculating the digest (for example `sha_prevouts` if SIGHASH_ANYONECANPAY is set) instead of setting them to zero and then hashing them as in BIP143. Despite that, collisions are made impossible by committing to the length of the data (implicit in ''hash_type'' and ''spend_type'') before the variable length data. +# The digest commits to the ''scriptPubKey'''''Why does the transaction digest commit to the ''scriptPubKey''?''' This prevents lying to offline signing devices about output being spent, even when the actually executed script (''scriptCode'' in BIP143) is correct. This means it's possible to compactly prove to a hardware wallet what (unused) execution paths existed.. # If the SIGHASH_ANYONECANPAY flag is not set, the digest commits to the amounts of ''all'' transaction inputs.'''Why does the transaction digest commit to the amounts of all transaction inputs?''' This eliminates the possibility to lie to offline signing devices about the fee of a transaction. -# The digest commits to all input nSequence if SIGHASH_NONE or SIGHASH_SINGLE are set (unless SIGHASH_ANYONECANPAY is set as well).'''Why does the transaction digest commit to all input nSequence if SIGHASH_SINGLE or SIGHASH_NONE are set?''' Because setting them already makes the digest commit to the prevouts part of all transaction inputs, it is not useful to treat the nSequence any different. Moreover, this change makes nSequence consistent with the view that SIGHASH_SINGLE and SIGHASH_NONE only modify the digest with respect to transaction outputs and not inputs. -# The digest commits to taproot-specific data epoch, spend_type and annex (if present). +# The digest commits to all input ''nSequence'' if SIGHASH_NONE or SIGHASH_SINGLE are set (unless SIGHASH_ANYONECANPAY is set as well).'''Why does the transaction digest commit to all input ''nSequence'' if SIGHASH_SINGLE or SIGHASH_NONE are set?''' Because setting them already makes the digest commit to the prevouts part of all transaction inputs, it is not useful to treat the ''nSequence'' any different. Moreover, this change makes ''nSequence'' consistent with the view that SIGHASH_SINGLE and SIGHASH_NONE only modify the digest with respect to transaction outputs and not inputs. +# The message includes commitments to the taproot-specific data ''spend_type'' and ''annex'' (if present). + +==== Taproot key path spending signature validation ==== + +To validate a signature ''sig'' with public key ''q'': +* If the ''sig'' is 64 bytes long, return ''Verify(q, hashTapSigHash(0x00 || SigMsg(0x00, 0)), sig)'''''Why is the input to ''hashTapSigHash'' prefixed with 0x00?''' This prefix is called the sighash epoch, and allows reusing the ''hashTapSigHash'' tagged hash in future extensions that make invasive changes to how hashing is performed. An alternative is switching to a different tag, but supporting a growing number of tags may become undesirable., where ''Verify'' is defined in bip-schnorr. +* If the ''sig'' is 65 bytes long, return ''sig[64] ≠ 0x00'''Why can the hash_type not be 0x00 in 65-byte signatures?''' Permitting that would enable malleating (by third parties, including miners) 64-byte signatures into 65-byte ones, resulting in a different `wtxid` and a different fee rate than the creator intended and Verify(q, hashTapSighash(0x00 || SigMsg(sig[64], 0)), sig[0:64])''. +* Otherwise, fail'''Why permit two signature lengths?''' By making the most common type of hash_type implicit, a byte can often be saved.. == Constructing and spending Taproot outputs == diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index e9c4278..a66e5f3 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -92,7 +92,7 @@ The following rules apply to OP_CHECKSIG, OP_CHECKSIGVERIFYn is larger than 4 bytes, the script MUST fail and terminate immediately. * If the public key size is zero, the script MUST fail and terminate immediately. * If the public key size is 32 bytes, it is considered to be a public key as described in bip-schnorr: -** If the signature is not the empty vector, the signature is validated according to the bip-taproot signature validation rules against the public key and the tapscript transaction digest (to be defined hereinafter) as message. Validation failure MUST cause the script to fail and terminate immediately. +** If the signature is not the empty vector, the signature is validated against the public key (see the next subsection). * If the public key size is not zero and not 32 bytes, the public key is of an ''unknown public key type'''''Unknown public key types''' allow adding new signature validation rules through softforks. A softfork could add actual signature validation which either passes or makes the script fail and terminate immediately. This way, new SIGHASH modes can be added, as well as [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-December/016549.html NOINPUT-tagged public keys] and a public key constant which is replaced by the taproot internal key for signature validation. and no actual signature verification is applied. During script execution of signature opcodes they behave exactly as known public key types except that signature validation is considered to be successful. * If the script did not fail and terminate before this step, regardless of the public key type: ** If the signature is the empty vector: @@ -104,26 +104,20 @@ The following rules apply to OP_CHECKSIG, OP_CHECKSIGVERIFYOP_CHECKSIG, a 1-byte value 0x01 is pushed onto the stack. *** For OP_CHECKSIGADD, a CScriptNum with value of n + 1 is pushed onto the stack. -===Transaction digest=== +===Signature validation=== -As the message for signature opcodes signature verification, transaction digest has the same definition as in bip-taproot, except the following: +To validate a signature ''sig'' with public key ''p'': +* Compute the tapscript message extension ''ext'', consisting of: +** ''tapleaf_hash'' (32): the tapleaf hash as defined in bip-taproot +** ''key_version'' (1): a constant value ''0x00'' representing the current version of public keys in the tapscript signature opcode execution. +** ''codesep_pos'' (4): the opcode position of the last executed OP_CODESEPARATOR before the currently executed signature opcode, with the value in little endian (or ''0xffffffff'' if none executed). The first opcode in a script has a position of 0. A multi-byte push opcode is counted as one opcode, regardless of the size of data being pushed. +* If the ''sig'' is 64 bytes long, return ''Verify(q, hashTapSigHash(0x00 || SigMsg(0x00, 1) || ext), sig)'', where ''Verify'' is defined in bip-schnorr. +* If the ''sig'' is 65 bytes long, return ''sig[64] ≠ 0x00 and Verify(q, hashTapSighash(0x00 || SigMsg(sig[64], 0) || ext), sig[0:64])''. +* Otherwise, fail. -The one-byte spend_type has a different value, specifically at bit 1: -* Bit 0 is set if an annex is present (the original witness stack has at least two witness elements, and the first byte of the last element is 0x50). -* Bit 1 is set. -* The other bits are unset. - -As additional pieces of data, added at the end of the input to the ''hashTapSighash'' function: -* tapleaf_hash (32): the tapleaf hash as defined in bip-taproot -* key_version (1): a constant value 0x00 representing the current version of public keys in the tapscript signature opcode execution. -* codeseparator_position (4): the opcode position of the last executed OP_CODESEPARATOR before the currently executed signature opcode, with the value in little endian (or 0xffffffff if none executed). The first opcode in a script has a position of 0. A multi-byte push opcode is counted as one opcode, regardless of the size of data being pushed. - -The total number of bytes hashed is at most ''247'''''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''215 - is_anyonecanpay * 52 - is_none * 32 + has_annex * 32''.. - -In summary, the semantics of the [https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki BIP143] sighash types remain unchanged, except the following: -# The exceptions mentioned in bip-taproot. -# The digest commits to taproot-specific data key_version.'''Why does the transaction digest commit to the key_version?''' This is for future extensions that define unknown public key types, making sure signatures can't be moved from one key type to another. -# The digest commits to the executed script through the tapleaf_hash which includes the leaf version and script instead of scriptCode. This implies that this commitment is unaffected by OP_CODESEPARATOR. +In summary, the semantics of signature validation is identical to bip-taproot, except the following: +# The digest commits to tapscript-specific data ''key_version''.'''Why does the transaction digest commit to the ''key_version''?''' This is for future extensions that define unknown public key types, making sure signatures can't be moved from one key type to another. +# The digest commits to the executed script through the ''tapleaf_hash'' which includes the leaf version and script instead of ''scriptCode''. This implies that this commitment is unaffected by OP_CODESEPARATOR. # The digest commits to the opcode position of the last executed OP_CODESEPARATOR.'''Why does the transaction digest commit to the position of the last executed OP_CODESEPARATOR?''' This allows continuing to use OP_CODESEPARATOR to sign the executed path of the script. Because the codeseparator_position is the last input to the digest, the SHA256 midstate can be efficiently cached for multiple OP_CODESEPARATORs in a single script. In contrast, the BIP143 handling of OP_CODESEPARATOR is to commit to the executed script only from the last executed OP_CODESEPARATOR onwards which requires unnecessary rehashing of the script. It should be noted that the one known OP_CODESEPARATOR use case of saving a second public key push in a script by sharing the first one between two code branches can be most likely expressed even cheaper by moving each branch into a separate taproot leaf. ===Resource limits=== -- cgit v1.2.3 From 7497bdecebee902160bf4c98c73942e999be25c6 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 13 Jan 2020 14:39:32 -0800 Subject: Update acknowledgements, remove authors --- bip-schnorr.mediawiki | 2 +- bip-taproot.mediawiki | 5 ++--- bip-tapscript.mediawiki | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 084b33f..fbfd408 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -257,4 +257,4 @@ The reference implementation is for demonstration purposes only and not to be us == Acknowledgements == -This document is the result of many discussions around Schnorr based signatures over the years, and had input from Johnson Lau, Greg Maxwell, Jonas Nick, Andrew Poelstra, Tim Ruffing, Rusty Russell, and Anthony Towns. +This document is the result of many discussions around Schnorr based signatures over the years, and had input from Johnson Lau, Greg Maxwell, Andrew Poelstra, Rusty Russell, and Anthony Towns. The authors further wish to thank all those who provided valuable feedback and reviews, including the participants of the [https://github.com/ajtowns/taproot-review structured reviews]. diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 7d2318e..d11f936 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -313,7 +313,6 @@ Depending on the implementation non-upgraded wallets may be able to send to Segw == Acknowledgements == -This document is the result of discussions around script and signature improvements with many people, and had direct contributions from Jonas Nick, Anthony Towns, Greg Maxwell, and others. It further builds on top of earlier published proposals such as Taproot by Greg Maxwell, and Merkle branch constructions by Russell O'Connor, Johnson Lau, and Mark Friedenbach. - -Thanks to Arik Sosman for suggesting to sort Merkle node children before hashes, removing the need to transfer the position in the tree. +This document is the result of discussions around script and signature improvements with many people, and had direct contributions from Greg Maxwell and others. It further builds on top of earlier published proposals such as Taproot by Greg Maxwell, and Merkle branch constructions by Russell O'Connor, Johnson Lau, and Mark Friedenbach. +The authors wish the thank Arik Sosman for suggesting to sort Merkle node children before hashes, removing the need to transfer the position in the tree, as well as all those who provided valuable feedback and reviews, including the participants of the [https://github.com/ajtowns/taproot-review structured reviews]. diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index e9c4278..ed729c7 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -143,4 +143,4 @@ In addition to changing the semantics of a number of opcodes, there are also som ==Acknowledgements== -This document is the result of many discussions and contains contributions by Jonas Nick, Anthony Towns, and others. +This document is the result of many discussions and contains contributions by a number of people. The authors wish to thank all those who provided valuable feedback and reviews, including the participants of the [https://github.com/ajtowns/taproot-review structured reviews]. -- cgit v1.2.3 From 0e3b6c595c2b90eecb969e9bc84314f4b677ac46 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 14 Jan 2020 10:28:49 -0800 Subject: Address jonas' comments --- bip-taproot.mediawiki | 22 +++++++++++----------- bip-tapscript.mediawiki | 18 +++++++++--------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index a05d064..7126149 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -41,7 +41,7 @@ As a result we choose this combination of technologies: * Taproot's advantages become apparent under the assumption that most applications involve outputs that could be spent by all parties agreeing. That's where '''Schnorr''' signatures come in, as they permit [https://eprint.iacr.org/2018/068 key aggregation]: a public key can be constructed from multiple participant public keys, and which requires cooperation between all participants to sign for. Such multi-party public keys and signatures are indistinguishable from their single-party equivalents. This means that with taproot most applications can use the key-based spending path, which is both efficient and private. This can be generalized to arbitrary M-of-N policies, as Schnorr signatures support threshold signing, at the cost of more complex setup protocols. * As Schnorr signatures also permit '''batch validation''', allowing multiple signatures to be validated together more efficiently than validating each one independently, we make sure all parts of the design are compatible with this. * Where unused bits appear as a result of the above changes, they are reserved for mechanisms for '''future extensions'''. As a result, every script in the Merkle tree has an associated version such that new script versions can be introduced with a soft fork while remaining compatible with bip-taproot. Additionally, future soft forks can make use of the currently unused annex in the witness (see [[#Rationale]]). -* While the core semantics of the '''signature hashing algorithm''' are not changed, a number of improvements are included in this proposal. The new signature hashing algorithm fixes the verification capabilities of offline signing devices by including amount and scriptPubKey in the digest, avoids unnecessary hashing, uses '''tagged hashes''' and defines a default sighash byte. +* While the core semantics of the '''signature hashing algorithm''' are not changed, a number of improvements are included in this proposal. The new signature hashing algorithm fixes the verification capabilities of offline signing devices by including amount and scriptPubKey in the signature message, avoids unnecessary hashing, uses '''tagged hashes''' and defines a default sighash byte. * The '''public key is directly included in the output''' in contrast to typical earlier constructions which store a hash of the public key or script in the output. This has the same cost for senders and is more space efficient overall if the key-based spending path is taken. '''Why is the public key directly included in the output?''' While typical earlier constructions store a hash of a script or a public key in the output, this is rather wasteful when a public key is always involved. To guarantee batch verifiability, the public key must be known to every verifier, and thus only revealing its hash as an output would imply adding an additional 32 bytes to the witness. Furthermore, to maintain [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2016-January/012198.html 128-bit collision security] for outputs, a 256-bit hash would be required anyway, which is comparable in size (and thus in cost for senders) to revealing the public key directly. While the usage of public key hashes is often said to protect against ECDLP breaks or quantum computers, this protection is very weak at best: transactions are not protected while being confirmed, and a very [https://twitter.com/pwuille/status/1108097835365339136 large portion] of the currency's supply is not under such protection regardless. Actual resistance to such systems can be introduced by relying on different cryptographic assumptions, but this proposal focuses on improvements that do not change the security model. Informally, the resulting design is as follows: a new witness version is added (version 1), whose programs consist of 32-byte encodings of points ''Q''. ''Q'' is computed as ''P + hash(P||m)G'' for a public key ''P'', and the root ''m'' of a Merkle tree whose leaves consist of a version number and a script. These outputs can be spent directly by providing a signature for ''Q'', or indirectly by revealing ''P'', the script and leaf version, inputs that satisfy the script, and a Merkle path that proves ''Q'' committed to that leaf. All hashes in this construction (the hash for computing ''Q'' from ''P'', the hashes inside the Merkle tree's inner nodes, and the signature hashes used) are tagged to guarantee domain separation. @@ -59,9 +59,9 @@ The following rules only apply when such an output is being spent. Any other out * Let ''q'' be the 32-byte array containing the witness program (the second push in the scriptPubKey) which represents a public key according to bip-schnorr. * Fail if the witness stack has 0 elements. -* If there are at least two witness elements, and the first byte of the last element is 0x50'''Why is the first byte of the annex 0x50?''' The 0x50 is chosen as it could not be confused with a valid P2WPKH or P2WSH spending. As the control block's initial byte's lowest bit is used to indicate the public key's Y squareness, each leaf version needs an even byte value and the immediately following odd byte value that are both not yet used in P2WPKH or P2WSH spending. To indicate the annex, only an "unpaired" available byte is necessary like 0x50. This choice maximizes the available options for future script versions., this last element is called ''annex'' ''a'''''What is the purpose of the annex?''' The annex is a reserved space for future extensions, such as indicating the validation costs of computationally expensive new opcodes in a way that is recognizable without knowing the scriptPubKey of the output being spent. Until the meaning of this field is defined by another softfork, users SHOULD NOT include annex in transactions, or it may lead to PERMANENT FUND LOSS. and is removed from the witness stack. The annex (or the lack of thereof) is always covered by the transaction digest and contributes to transaction weight, but is otherwise ignored during taproot validation. +* If there are at least two witness elements, and the first byte of the last element is 0x50'''Why is the first byte of the annex 0x50?''' The 0x50 is chosen as it could not be confused with a valid P2WPKH or P2WSH spending. As the control block's initial byte's lowest bit is used to indicate the public key's Y squareness, each leaf version needs an even byte value and the immediately following odd byte value that are both not yet used in P2WPKH or P2WSH spending. To indicate the annex, only an "unpaired" available byte is necessary like 0x50. This choice maximizes the available options for future script versions., this last element is called ''annex'' ''a'''''What is the purpose of the annex?''' The annex is a reserved space for future extensions, such as indicating the validation costs of computationally expensive new opcodes in a way that is recognizable without knowing the scriptPubKey of the output being spent. Until the meaning of this field is defined by another softfork, users SHOULD NOT include annex in transactions, or it may lead to PERMANENT FUND LOSS. and is removed from the witness stack. The annex (or the lack of thereof) is always covered by the signature and contributes to transaction weight, but is otherwise ignored during taproot validation. * If there is exactly one element left in the witness stack, key path spending is used: -** The single witness stack element is interpreted as the signature and must be valid (see the next section) for the public key ''q'' and taproot transaction digest (to be defined hereinafter) as message. Fail if it is not. Otherwise pass. +** The single witness stack element is interpreted as the signature and must be valid (see the next section) for the public key ''q'' (see the next subsection). * If there are at least two witness elements left, script path spending is used: ** Call the second-to-last stack element ''s'', the script. ** The last stack element is called the control block ''c'', and must have length ''33 + 32m'', for a value of ''m'' that is an integer between 0 and 128'''Why is the Merkle path length limited to 128?''' The optimally space-efficient Merkle tree can be constructed based on the probabilities of the scripts in the leaves, using the Huffman algorithm. This algorithm will construct branches with lengths approximately equal to ''log2(1/probability)'', but to have branches longer than 128 you would need to have scripts with an execution chance below 1 in ''2128''. As that is our security bound, scripts that truly have such a low chance can probably be removed entirely., inclusive. Fail if it does not have such a length. @@ -89,11 +89,11 @@ We first define a reusable common signature message calculation function, follow The function ''SigMsg(hash_type, ext_flag)'' computes the message being signed as a byte array. It is implicitly also a function of the spending transaction and the outputs it spends, but these are not listed to keep notation simple. -The parameter ''hash_type'' is an 8-bit unsigned value. The SIGHASH encodings from the legacy script system are reused, including SIGHASH_ALL, SIGHASH_NONE, SIGHASH_SINGLE, and SIGHASH_ANYONECANPAY, plus a default ''hash_type'' (0) which results in signing over the whole transaction just as for SIGHASH_ALL. The following restrictions apply, which cause validation failure if violated: +The parameter ''hash_type'' is an 8-bit unsigned value. The SIGHASH encodings from the legacy script system are reused, including SIGHASH_ALL, SIGHASH_NONE, SIGHASH_SINGLE, and SIGHASH_ANYONECANPAY, plus the default ''hash_type'' value ''0x00'' which results in signing over the whole transaction just as for SIGHASH_ALL. The following restrictions apply, which cause validation failure if violated: * Using any undefined ''hash_type'' (not ''0x00'', ''0x01'', ''0x02'', ''0x03'', ''0x81'', ''0x82'', or ''0x83'''''Why reject unknown ''hash_type'' values?''' By doing so, it is easier to reason about the worst case amount of signature hashing an implementation with adequate caching must perform.). * Using SIGHASH_SINGLE without a "corresponding output" (an output with the same index as the input being verified). -The parameter ''ext_flag'' is an integer in range 0-127, and is used for indicating the presence of extensions. +The parameter ''ext_flag'' is an integer in range 0-127, and is used for indicating (in the message) that extensions are added at the end of the message'''What extensions use the ''ext_flag'' mechanism?''' Bip-tapscript reuses the same common signature message algorithm, but adds tapscript-specific data at the end, which is indicated using ''ext_flag = 1''.. If the parameters take acceptable values, the message is the concatenation of the following data, in order(with byte size of each item listed in parentheses). Numerical values in 2, 4, or 8-byte are encoded in little-endian. @@ -126,16 +126,16 @@ If the parameters take acceptable values, the message is the concatenation of th The total length of ''SigMsg()'' is at most ''209'' bytes'''What is the output length of ''SigMsg()''?''' The total length of ''SigMsg()'' can be computed using the following formula: ''177 - is_anyonecanpay * 52 - is_none * 32 + has_annex * 32''.. Note that this does not include the size of sub-hashes such as ''sha_prevouts'', which may be cached across signatures of the same transaction. In summary, the semantics of the [https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki BIP143] sighash types remain unchanged, except the following: -# The way and order of serialization is changed.'''Why is the serialization in the transaction digest changed?''' Hashes that go into the digest and the digest itself are now computed with a single SHA256 invocation instead of double SHA256. There is no expected security improvement by doubling SHA256 because this only protects against length-extension attacks against SHA256 which are not a concern for transaction digests because there is no secret data. Therefore doubling SHA256 is a waste of resources. The digest computation now follows a logical order with transaction level data first, then input data and output data. This allows to efficiently cache the transaction part of the digest across different inputs using the SHA256 midstate. Additionally, sub-hashes can be skipped when calculating the digest (for example `sha_prevouts` if SIGHASH_ANYONECANPAY is set) instead of setting them to zero and then hashing them as in BIP143. Despite that, collisions are made impossible by committing to the length of the data (implicit in ''hash_type'' and ''spend_type'') before the variable length data. -# The digest commits to the ''scriptPubKey'''''Why does the transaction digest commit to the ''scriptPubKey''?''' This prevents lying to offline signing devices about output being spent, even when the actually executed script (''scriptCode'' in BIP143) is correct. This means it's possible to compactly prove to a hardware wallet what (unused) execution paths existed.. -# If the SIGHASH_ANYONECANPAY flag is not set, the digest commits to the amounts of ''all'' transaction inputs.'''Why does the transaction digest commit to the amounts of all transaction inputs?''' This eliminates the possibility to lie to offline signing devices about the fee of a transaction. -# The digest commits to all input ''nSequence'' if SIGHASH_NONE or SIGHASH_SINGLE are set (unless SIGHASH_ANYONECANPAY is set as well).'''Why does the transaction digest commit to all input ''nSequence'' if SIGHASH_SINGLE or SIGHASH_NONE are set?''' Because setting them already makes the digest commit to the prevouts part of all transaction inputs, it is not useful to treat the ''nSequence'' any different. Moreover, this change makes ''nSequence'' consistent with the view that SIGHASH_SINGLE and SIGHASH_NONE only modify the digest with respect to transaction outputs and not inputs. -# The message includes commitments to the taproot-specific data ''spend_type'' and ''annex'' (if present). +# The way and order of serialization is changed.'''Why is the serialization in the signature message changed?''' Hashes that go into the signature message and the message itself are now computed with a single SHA256 invocation instead of double SHA256. There is no expected security improvement by doubling SHA256 because this only protects against length-extension attacks against SHA256 which are not a concern for signature messages because there is no secret data. Therefore doubling SHA256 is a waste of resources. The message computation now follows a logical order with transaction level data first, then input data and output data. This allows to efficiently cache the transaction part of the message across different inputs using the SHA256 midstate. Additionally, sub-hashes can be skipped when calculating the message (for example `sha_prevouts` if SIGHASH_ANYONECANPAY is set) instead of setting them to zero and then hashing them as in BIP143. Despite that, collisions are made impossible by committing to the length of the data (implicit in ''hash_type'' and ''spend_type'') before the variable length data. +# The signature message commits to the ''scriptPubKey'''''Why does the signature message commit to the ''scriptPubKey''?''' This prevents lying to offline signing devices about output being spent, even when the actually executed script (''scriptCode'' in BIP143) is correct. This means it's possible to compactly prove to a hardware wallet what (unused) execution paths existed.. +# If the SIGHASH_ANYONECANPAY flag is not set, the message commits to the amounts of ''all'' transaction inputs.'''Why does the signature message commit to the amounts of all transaction inputs?''' This eliminates the possibility to lie to offline signing devices about the fee of a transaction. +# The signature message commits to all input ''nSequence'' if SIGHASH_NONE or SIGHASH_SINGLE are set (unless SIGHASH_ANYONECANPAY is set as well).'''Why does the signature message commit to all input ''nSequence'' if SIGHASH_SINGLE or SIGHASH_NONE are set?''' Because setting them already makes the message commit to the prevouts part of all transaction inputs, it is not useful to treat the ''nSequence'' any different. Moreover, this change makes ''nSequence'' consistent with the view that SIGHASH_SINGLE and SIGHASH_NONE only modify the signature message with respect to transaction outputs and not inputs. +# The signature message includes commitments to the taproot-specific data ''spend_type'' and ''annex'' (if present). ==== Taproot key path spending signature validation ==== To validate a signature ''sig'' with public key ''q'': -* If the ''sig'' is 64 bytes long, return ''Verify(q, hashTapSigHash(0x00 || SigMsg(0x00, 0)), sig)'''''Why is the input to ''hashTapSigHash'' prefixed with 0x00?''' This prefix is called the sighash epoch, and allows reusing the ''hashTapSigHash'' tagged hash in future extensions that make invasive changes to how hashing is performed. An alternative is switching to a different tag, but supporting a growing number of tags may become undesirable., where ''Verify'' is defined in bip-schnorr. +* If the ''sig'' is 64 bytes long, return ''Verify(q, hashTapSigHash(0x00 || SigMsg(0x00, 0)), sig)'''''Why is the input to ''hashTapSigHash'' prefixed with 0x00?''' This prefix is called the sighash epoch, and allows reusing the ''hashTapSigHash'' tagged hash in future signature algorithms that make invasive changes to how hashing is performed (as opposed to the ''ext_flag'' mechanism that is used for incremental extensions). An alternative is having them use a different tag, but supporting a growing number of tags may become undesirable., where ''Verify'' is defined in bip-schnorr. * If the ''sig'' is 65 bytes long, return ''sig[64] ≠ 0x00'''Why can the hash_type not be 0x00 in 65-byte signatures?''' Permitting that would enable malleating (by third parties, including miners) 64-byte signatures into 65-byte ones, resulting in a different `wtxid` and a different fee rate than the creator intended and Verify(q, hashTapSighash(0x00 || SigMsg(sig[64], 0)), sig[0:64])''. * Otherwise, fail'''Why permit two signature lengths?''' By making the most common type of hash_type implicit, a byte can often be saved.. diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index a66e5f3..8beef28 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -34,8 +34,8 @@ Specifically, the goal is making '''Schnorr signatures''', '''batch validation'' ==Design== -In order to achieve these goals, signature opcodes OP_CHECKSIG and OP_CHECKSIGVERIFY are modified to verify Schnorr signatures as specified in bip-schnorr and to use a new transaction digest based on the taproot transaction digest. -The tapscript transaction digest also simplifies OP_CODESEPARATOR handling and makes it more efficient. +In order to achieve these goals, signature opcodes OP_CHECKSIG and OP_CHECKSIGVERIFY are modified to verify Schnorr signatures as specified in bip-schnorr and to use a signature message algorithm based on the common message calculation in bip-taproot. +The tapscript signature message also simplifies OP_CODESEPARATOR handling and makes it more efficient. The inefficient OP_CHECKMULTISIG and OP_CHECKMULTISIGVERIFY opcodes are disabled. Instead, a new opcode OP_CHECKSIGADD is introduced to allow creating the same multisignature policies in a batch-verifiable way. @@ -92,7 +92,7 @@ The following rules apply to OP_CHECKSIG, OP_CHECKSIGVERIFYn is larger than 4 bytes, the script MUST fail and terminate immediately. * If the public key size is zero, the script MUST fail and terminate immediately. * If the public key size is 32 bytes, it is considered to be a public key as described in bip-schnorr: -** If the signature is not the empty vector, the signature is validated against the public key (see the next subsection). +** If the signature is not the empty vector, the signature is validated against the public key (see the next subsection). Validation failure in this case immediately terminates script execution with failure. * If the public key size is not zero and not 32 bytes, the public key is of an ''unknown public key type'''''Unknown public key types''' allow adding new signature validation rules through softforks. A softfork could add actual signature validation which either passes or makes the script fail and terminate immediately. This way, new SIGHASH modes can be added, as well as [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-December/016549.html NOINPUT-tagged public keys] and a public key constant which is replaced by the taproot internal key for signature validation. and no actual signature verification is applied. During script execution of signature opcodes they behave exactly as known public key types except that signature validation is considered to be successful. * If the script did not fail and terminate before this step, regardless of the public key type: ** If the signature is the empty vector: @@ -107,18 +107,18 @@ The following rules apply to OP_CHECKSIG, OP_CHECKSIGVERIFYOP_CODESEPARATOR before the currently executed signature opcode, with the value in little endian (or ''0xffffffff'' if none executed). The first opcode in a script has a position of 0. A multi-byte push opcode is counted as one opcode, regardless of the size of data being pushed. -* If the ''sig'' is 64 bytes long, return ''Verify(q, hashTapSigHash(0x00 || SigMsg(0x00, 1) || ext), sig)'', where ''Verify'' is defined in bip-schnorr. -* If the ''sig'' is 65 bytes long, return ''sig[64] ≠ 0x00 and Verify(q, hashTapSighash(0x00 || SigMsg(sig[64], 0) || ext), sig[0:64])''. +* If the ''sig'' is 64 bytes long, return ''Verify(p, hashTapSigHash(0x00 || SigMsg(0x00, 1) || ext), sig)'', where ''Verify'' is defined in bip-schnorr. +* If the ''sig'' is 65 bytes long, return ''sig[64] ≠ 0x00 and Verify(p, hashTapSighash(0x00 || SigMsg(sig[64], 1) || ext), sig[0:64])''. * Otherwise, fail. In summary, the semantics of signature validation is identical to bip-taproot, except the following: -# The digest commits to tapscript-specific data ''key_version''.'''Why does the transaction digest commit to the ''key_version''?''' This is for future extensions that define unknown public key types, making sure signatures can't be moved from one key type to another. -# The digest commits to the executed script through the ''tapleaf_hash'' which includes the leaf version and script instead of ''scriptCode''. This implies that this commitment is unaffected by OP_CODESEPARATOR. -# The digest commits to the opcode position of the last executed OP_CODESEPARATOR.'''Why does the transaction digest commit to the position of the last executed OP_CODESEPARATOR?''' This allows continuing to use OP_CODESEPARATOR to sign the executed path of the script. Because the codeseparator_position is the last input to the digest, the SHA256 midstate can be efficiently cached for multiple OP_CODESEPARATORs in a single script. In contrast, the BIP143 handling of OP_CODESEPARATOR is to commit to the executed script only from the last executed OP_CODESEPARATOR onwards which requires unnecessary rehashing of the script. It should be noted that the one known OP_CODESEPARATOR use case of saving a second public key push in a script by sharing the first one between two code branches can be most likely expressed even cheaper by moving each branch into a separate taproot leaf. +# The signature message includes the tapscript-specific data ''key_version''.'''Why does the signature message commit to the ''key_version''?''' This is for future extensions that define unknown public key types, making sure signatures can't be moved from one key type to another. +# The signature message commits to the executed script through the ''tapleaf_hash'' which includes the leaf version and script instead of ''scriptCode''. This implies that this commitment is unaffected by OP_CODESEPARATOR. +# The signature message includes the opcode position of the last executed OP_CODESEPARATOR.'''Why does the signature message include the position of the last executed OP_CODESEPARATOR?''' This allows continuing to use OP_CODESEPARATOR to sign the executed path of the script. Because the codeseparator_position is the last input to the hash, the SHA256 midstate can be efficiently cached for multiple OP_CODESEPARATORs in a single script. In contrast, the BIP143 handling of OP_CODESEPARATOR is to commit to the executed script only from the last executed OP_CODESEPARATOR onwards which requires unnecessary rehashing of the script. It should be noted that the one known OP_CODESEPARATOR use case of saving a second public key push in a script by sharing the first one between two code branches can be most likely expressed even cheaper by moving each branch into a separate taproot leaf. ===Resource limits=== -- cgit v1.2.3 From 6e77233b571e137aff6916025e39fd959a6dcdc2 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Thu, 5 Jul 2018 18:45:34 -0700 Subject: Add draft for Schnorr BIP Includes squashed contributions by GitHub users jonasnick, real-or-random, AustinWilliams, JustinTArthur, ysangkok, RCassatta, Sjors, tnakagawa, and guggero. --- bip-schnorr.mediawiki | 216 ++++++++++++++++++++++++++++++++++++++++++ bip-schnorr/reference.py | 136 ++++++++++++++++++++++++++ bip-schnorr/speedup-batch.png | Bin 0 -> 11914 bytes bip-schnorr/test-vectors.csv | 17 ++++ 4 files changed, 369 insertions(+) create mode 100644 bip-schnorr.mediawiki create mode 100644 bip-schnorr/reference.py create mode 100644 bip-schnorr/speedup-batch.png create mode 100644 bip-schnorr/test-vectors.csv diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki new file mode 100644 index 0000000..d4e4ff1 --- /dev/null +++ b/bip-schnorr.mediawiki @@ -0,0 +1,216 @@ +
+  BIP: ?
+  Title: Schnorr Signatures for secp256k1
+  Author: Pieter Wuille 
+  Status: Draft
+  Type: Informational
+  License: BSD-2-Clause
+  Post-History: 2018-07-06: https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-July/016203.html [bitcoin-dev] Schnorr signatures BIP
+
+ +==Introduction== + +===Abstract=== + +This document proposes a standard for 64-byte Schnorr signatures over the elliptic curve ''secp256k1''. + +===Copyright=== + +This document is licensed under the 2-clause BSD license. + +===Motivation=== + +Bitcoin has traditionally used +[https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm ECDSA] signatures over the [http://www.secg.org/sec2-v2.pdf secp256k1 curve] for authenticating +transactions. These are [http://www.secg.org/sec1-v2.pdf standardized], but have a number of downsides +compared to [https://en.wikipedia.org/wiki/Schnorr_signature Schnorr signatures] over the same curve: + +* '''Security proof''': The security of Schnorr signatures is easily [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf provable] in the random oracle model assuming the elliptic curve discrete logarithm problem (ECDLP) is hard. Such a proof does not exist for ECDSA. +* '''Non-malleability''': ECDSA signatures are inherently malleable; a third party without access to the private key can alter an existing valid signature for a given public key and message into another signature that is valid for the same key and message. This issue is discussed in [https://github.com/bitcoin/bips/blob/master/bip-0062.mediawiki BIP62] and [https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki BIP66]. On the other hand, Schnorr signatures are provably non-malleableMore precisely they are '' '''strongly''' unforgeable under chosen message attacks '' (SUF-CMA), which informally means that without knowledge of the secret key but given a valid signature of a message, it is not possible to come up with a second valid signature for the same message. A security proof in the random oracle model can be found for example in [https://eprint.iacr.org/2016/191 a paper by Kiltz, Masny and Pan], which essentially restates [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf the original security proof of Schnorr signatures by Pointcheval and Stern] more explicitly. These proofs are for the Schnorr signature variant using ''(e,s)'' instead of ''(R,s)'' (see Design above). Since we use a unique encoding of ''R'', there is an efficiently computable bijection that maps ''(R, s)'' to ''(e, s)'', which allows to convert a successful SUF-CMA attacker for the ''(e, s)'' variant to a successful SUF-CMA attacker for the ''(r, s)'' variant (and vice-versa). Furthermore, the aforementioned proofs consider a variant of Schnorr signatures without key prefixing (see Design above), but it can be verified that the proofs are also correct for the variant with key prefixing. As a result, the aforementioned security proofs apply to the variant of Schnorr signatures proposed in this document.. +* '''Linearity''': Schnorr signatures have the remarkable property that multiple parties can collaborate to produce a signature that is valid for the sum of their public keys. This is the building block for various higher-level constructions that improve efficiency and privacy, such as multisignatures and others (see Applications below). + +For all these advantages, there are virtually no disadvantages, apart +from not being standardized. This document seeks to change that. As we +propose a new standard, a number of improvements not specific to Schnorr signatures can be +made: + +* '''Signature encoding''': Instead of [https://en.wikipedia.org/wiki/X.690#DER_encoding DER]-encoding for signatures (which are variable size, and up to 72 bytes), we can use a simple fixed 64-byte format. +* '''Batch verification''': The specific formulation of ECDSA signatures that is standardized cannot be verified more efficiently in batch compared to individually, unless additional witness data is added. Changing the signature scheme offers an opportunity to avoid this. + +[[File:bip-schnorr/speedup-batch.png|frame|This graph shows the ratio between the time it takes to verify ''n'' signatures individually and to verify a batch of ''n'' signatures. This ratio goes up logarithmically with the number of signatures, or in other words: the total time to verify ''n'' signatures grows with ''O(n / log n)''.]] + +By reusing the same curve as Bitcoin has used for ECDSA, private and public keys remain identical for Schnorr signatures, and we avoid introducing new assumptions about elliptic curve group security. + +== Description == + +We first build up the algebraic formulation of the signature scheme by +going through the design choices. Afterwards, we specify the exact +encodings and operations. + +=== Design === + +'''Schnorr signature variant''' Elliptic Curve Schnorr signatures for message ''m'' and public key ''P'' generally involve a point ''R'', integers ''e'' and ''s'' picked by the signer, and generator ''G'' which satisfy ''e = H(R || m)'' and ''sG = R + eP''. Two formulations exist, depending on whether the signer reveals ''e'' or ''R'': +# Signatures are ''(e,s)'' that satisfy ''e = H(sG - eP || m)''. This avoids minor complexity introduced by the encoding of the point ''R'' in the signature (see paragraphs "Encoding the sign of R" and "Implicit Y coordinate" further below in this subsection). +# Signatures are ''(R,s)'' that satisfy ''sG = R + H(R || m)P''. This supports batch verification, as there are no elliptic curve operations inside the hashes. + +We choose the ''R''-option to support batch verification. + +'''Key prefixing''' When using the verification rule above directly, it is possible for a third party to convert a signature ''(R,s)'' for key ''P'' into a signature ''(R,s + aH(R || m))'' for key ''P + aG'' and the same message, for any integer ''a''. This is not a concern for Bitcoin currently, as all signature hashes indirectly commit to the public keys. However, this may change with proposals such as SIGHASH_NOINPUT ([https://github.com/bitcoin/bips/blob/master/bip-0118.mediawiki BIP 118]), or when the signature scheme is used for other purposes—especially in combination with schemes like [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki BIP32]'s unhardened derivation. To combat this, we choose ''key prefixed''A limitation of committing to the public key (rather than to a short hash of it, or not at all) is that it removes the ability for public key recovery or verifying signatures against a short public key hash. These constructions are generally incompatible with batch verification. Schnorr signatures; changing the equation to ''sG = R + H(R || P || m)P''. + +'''Encoding the sign of R''' As we chose the ''R''-option above, we're required to encode the point ''R'' into the signature. Several possibilities exist: +# Encoding the full X and Y coordinate of R, resulting in a 96-byte signature. +# Encoding the full X coordinate, but only whether Y is even or odd (like compressed public keys). This would result in 65-byte signatures. +# Encoding only the X coordinate, leaving us with 64-byte signature. + +Using the first option would be slightly more efficient for verification (around 5%), but we prioritize compactness, and therefore choose option 3. + +'''Implicit Y coordinate''' In order to support batch verification, the Y coordinate of ''R'' cannot be ambiguous (every valid X coordinate has two possible Y coordinates). We have a choice between several options for symmetry breaking: +# Implicitly choosing the Y coordinate that is in the lower half. +# Implicitly choosing the Y coordinate that is evenSince ''p'' is odd, negation modulo ''p'' will map even numbers to odd numbers and the other way around. This means that for a valid X coordinate, one of the corresponding Y coordinates will be even, and the other will be odd.. +# Implicitly choosing the Y coordinate that is a quadratic residue (has a square root modulo the field size)A product of two numbers is a quadratic residue when either both or none of the factors are quadratic residues. As ''-1'' is not a quadratic residue, and the two Y coordinates corresponding to a given X coordinate are each other's negation, this means exactly one of the two must be a quadratic residue.. + +The third option is slower at signing time but a bit faster to verify, as the quadratic residue of the Y coordinate can be computed directly for points represented in +[https://en.wikibooks.org/wiki/Cryptography/Prime_Curve/Jacobian_Coordinates Jacobian coordinates] (a common optimization to avoid modular inverses +for elliptic curve operations). The two other options require a possibly +expensive conversion to affine coordinates first. This would even be the case if the sign or oddness were explicitly coded (option 2 in the previous design choice). We therefore choose option 3. + +'''Final scheme''' As a result, our final scheme ends up using signatures ''(r,s)'' where ''r'' is the X coordinate of a point ''R'' on the curve whose Y coordinate is a quadratic residue, and which satisfies ''sG = R + H(r || P || m)P''. + +=== Specification === + +We first describe the verification algorithm, and then the signature algorithm. + +The following convention is used, with constants as defined for secp256k1: +* Lowercase variables represent integers or byte arrays. +** The constant ''p'' refers to the field size, ''0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F''. +** The constant ''n'' refers to the curve order, ''0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141''. +* Uppercase variables refer to points on the curve with equation ''y2 = x3 + 7'' over the integers modulo ''p''. +** ''infinite(P)'' returns whether or not ''P'' is the point at infinity. +** ''x(P)'' and ''y(P)'' are integers in the range ''0..p-1'' and refer to the X and Y coordinates of a point ''P'' (assuming it is not infinity). +** The constant ''G'' refers to the generator, for which ''x(G) = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798'' and ''y(G) = 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8''. +** Addition of points refers to the usual [https://en.wikipedia.org/wiki/Elliptic_curve#The_group_law elliptic curve group operation]. +** [https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication Multiplication of an integer and a point] refers to the repeated application of the group operation. +* Functions and operations: +** ''||'' refers to byte array concatenation. +** The function ''x[i:j]'', where ''x'' is a byte array, returns a ''(j - i)''-byte array with a copy of the ''i''-th byte (inclusive) to the ''j''-th byte (exclusive) of ''x''. +** The function ''bytes(x)'', where ''x'' is an integer, returns the 32-byte encoding of ''x'', most significant byte first. +** The function ''bytes(P)'', where ''P'' is a point, returns ''bytes(0x02 + (y(P) & 1)) || bytes(x(P))''This matches the ''compressed'' encoding for elliptic curve points used in Bitcoin already, following section 2.3.3 of the [http://www.secg.org/sec1-v2.pdf SEC 1] standard.. +** The function ''int(x)'', where ''x'' is a 32-byte array, returns the 256-bit unsigned integer whose most significant byte encoding is ''x''. +** The function ''lift_x(x)'', where ''x'' is an integer in range ''0..p-1'', returns the point ''P'' for which ''x(P) = x'' and ''y(P)'' is a quadratic residue modulo ''p'', or fails if no such point existsGiven an candidate X coordinate ''x'' in the range ''0..p-1'', there exist either exactly two or exactly zero valid Y coordinates. If no valid Y coordinate exists, then ''x'' is not a valid X coordinate either, i.e., no point ''P'' exists for which ''x(P) = x''. Given a candidate ''x'', the valid Y coordinates are the square roots of ''c = x3 + 7 mod p'' and they can be computed as ''y = ±c(p+1)/4 mod p'' (see [https://en.wikipedia.org/wiki/Quadratic_residue#Prime_or_prime_power_modulus Quadratic residue]) if they exist, which can be checked by squaring and comparing with ''c''. Due to [https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion] it then holds that ''c(p-1)/2 = 1 mod p''. The same criterion applied to ''y'' results in ''y(p-1)/2 mod p = ±c((p+1)/4)((p-1)/2) mod p = ±1 mod p''. Therefore ''y = +c(p+1)/4 mod p'' is a quadratic residue and ''-y mod p'' is not.. The function ''lift_x(x)'' is equivalent to the following pseudocode: +*** Let ''y = c(p+1)/4 mod p''. +*** Fail if ''c ≠ y2 mod p''. +*** Return ''(r, y)''. +** The function ''point(x)'', where ''x'' is a 33-byte array, returns the point ''P'' for which ''x(P) = int(x[1:33])'' and ''y(P) & 1 = int(x[0:1]) - 0x02)'', or fails if no such point exists. The function ''point(x)'' is equivalent to the following pseudocode: +*** Fail if (''x[0:1] ≠ 0x02'' and ''x[0:1] ≠ 0x03''). +*** Set flag ''odd'' if ''x[0:1] = 0x03''. +*** Let ''(r, y) = lift_x(x)''; fail if ''lift_x(x)'' fails. +*** If (flag ''odd'' is set and ''y'' is an even integer) or (flag ''odd'' is not set and ''y'' is an odd integer): +**** Let ''y = p - y''. +*** Return ''(r, y)''. +** The function ''hash(x)'', where ''x'' is a byte array, returns the 32-byte SHA256 hash of ''x''. +** The function ''jacobi(x)'', where ''x'' is an integer, returns the [https://en.wikipedia.org/wiki/Jacobi_symbol Jacobi symbol] of ''x / p''. It is equal to ''x(p-1)/2 mod p'' ([https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion])For points ''P'' on the secp256k1 curve it holds that ''jacobi(y(P)) ≠ 0''.. + +==== Verification ==== + +Input: +* The public key ''pk'': a 33-byte array +* The message ''m'': a 32-byte array +* A signature ''sig'': a 64-byte array + +The signature is valid if and only if the algorithm below does not fail. +* Let ''P = point(pk)''; fail if ''point(pk)'' fails. +* Let ''r = int(sig[0:32])''; fail if ''r ≥ p''. +* Let ''s = int(sig[32:64])''; fail if ''s ≥ n''. +* Let ''e = int(hash(bytes(r) || bytes(P) || m)) mod n''. +* Let ''R = sG - eP''. +* Fail if ''infinite(R)''. +* Fail if ''jacobi(y(R)) ≠ 1'' or ''x(R) ≠ r''. + +==== Batch Verification ==== + +Input: +* The number ''u'' of signatures +* The public keys ''pk1..u'': ''u'' 33-byte arrays +* The messages ''m1..u'': ''u'' 32-byte arrays +* The signatures ''sig1..u'': ''u'' 64-byte arrays + +All provided signatures are valid with overwhelming probability if and only if the algorithm below does not fail. +* Generate ''u-1'' random integers ''a2...u'' in the range ''1...n-1''. They are generated deterministically using a [https://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator CSPRNG] seeded by a cryptographic hash of all inputs of the algorithm, i.e. ''seed = seed_hash(pk1..pku || m1..mu || sig1..sigu )''. A safe choice is to instantiate ''seed_hash'' with SHA256 and use [https://tools.ietf.org/html/rfc8439 ChaCha20] with key ''seed'' as a CSPRNG to generate 256-bit integers, skipping integers not in the range ''1...n-1''. +* For ''i = 1 .. u'': +** Let ''Pi = point(pki)''; fail if ''point(pki)'' fails. +** Let ''r = int(sigi[0:32])''; fail if ''r ≥ p''. +** Let ''si = int(sigi[32:64])''; fail if ''si ≥ n''. +** Let ''ei = int(hash(bytes(r) || bytes(Pi) || mi)) mod n''. +** Let ''Ri = lift_x(r)''; fail if ''lift_x(r)'' fails. +* Fail if ''(s1 + a2s2 + ... + ausu)G ≠ R1 + a2R2 + ... + auRu + e1P1 + (a2e2)P2 + ... + (aueu)Pu''. + +==== Signing ==== + +Input: +* The secret key ''d'': an integer in the range ''1..n-1''. +* The message ''m'': a 32-byte array + +To sign ''m'' for public key ''dG'': +* Let ''k' = int(hash(bytes(d) || m)) mod n''Note that in general, taking the output of a hash function modulo the curve order will produce an unacceptably biased result. However, for the secp256k1 curve, the order is sufficiently close to ''2256'' that this bias is not observable (''1 - n / 2256'' is around ''1.27 * 2-128'').. +* Fail if ''k' = 0''. +* Let ''R = k'G''. +* Let ''k = k' '' if ''jacobi(y(R)) = 1'', otherwise let ''k = n - k' ''. +* Let ''e = int(hash(bytes(x(R)) || bytes(dG) || m)) mod n''. +* The signature is ''bytes(x(R)) || bytes((k + ed) mod n)''. + +'''Above deterministic derivation of ''R'' is designed specifically for this signing algorithm and may not be secure when used in other signature schemes.''' +For example, using the same derivation in the MuSig multi-signature scheme leaks the secret key (see the [https://eprint.iacr.org/2018/068 MuSig paper] for details). + +'''Above deterministic derivation of ''R'' is designed specifically for this signing algorithm and may not be secure when used in other signature schemes.''' +For example, using the same derivation in the MuSig multi-signature scheme leaks the secret key (see the [https://eprint.iacr.org/2018/068 MuSig paper] for details). + +Note that this is not a ''unique signature'' scheme: while this algorithm will always produce the same signature for a given message and public key, ''k'' (and hence ''R'') may be generated in other ways (such as by a CSPRNG) producing a different, but still valid, signature. + +=== Optimizations === + +Many techniques are known for optimizing elliptic curve implementations. Several of them apply here, but are out of scope for this document. Two are listed below however, as they are relevant to the design decisions: + +'''Jacobi symbol''' The function ''jacobi(x)'' is defined as above, but can be computed more efficiently using an [https://en.wikipedia.org/wiki/Jacobi_symbol#Calculating_the_Jacobi_symbol extended GCD algorithm]. + +'''Jacobian coordinates''' Elliptic Curve operations can be implemented more efficiently by using [https://en.wikibooks.org/wiki/Cryptography/Prime_Curve/Jacobian_Coordinates Jacobian coordinates]. Elliptic Curve operations implemented this way avoid many intermediate modular inverses (which are computationally expensive), and the scheme proposed in this document is in fact designed to not need any inversions at all for verification. When operating on a point ''P'' with Jacobian coordinates ''(x,y,z)'' which is not the point at infinity and for which ''x(P)'' is defined as ''x / z2'' and ''y(P)'' is defined as ''y / z3'': +* ''jacobi(y(P))'' can be implemented as ''jacobi(yz mod p)''. +* ''x(P) ≠ r'' can be implemented as ''x ≠ z2r mod p''. + +== Applications == + +There are several interesting applications beyond simple signatures. +While recent academic papers claim that they are also possible with ECDSA, consensus support for Schnorr signature verification would significantly simplify the constructions. + +===Multisignatures and Threshold Signatures=== + +By means of an interactive scheme such as [https://eprint.iacr.org/2018/068 MuSig], participants can produce a combined public key which they can jointly sign for. This allows n-of-n multisignatures which, from a verifier's perspective, are no different from ordinary signatures, giving improved privacy and efficiency versus ''CHECKMULTISIG'' or other means. + +Further, by combining Schnorr signatures with [https://link.springer.com/content/pdf/10.1007/3-540-46766-1_9.pdf Pedersen Secret Sharing], it is possible to obtain [http://cacr.uwaterloo.ca/techreports/2001/corr2001-13.ps an interactive threshold signature scheme] that ensures that signatures can only be produced by arbitrary but predetermined sets of signers. For example, k-of-n threshold signatures can be realized this way. Furthermore, it is possible to replace the combination of participant keys in this scheme with MuSig, though the security of that combination still needs analysis. + +===Adaptor Signatures=== + +[https://download.wpsoftware.net/bitcoin/wizardry/mw-slides/2018-05-18-l2/slides.pdf Adaptor signatures] can be produced by a signer by offsetting his public nonce with a known point ''T = tG'', but not offsetting his secret nonce. +A correct signature (or partial signature, as individual signers' contributions to a multisignature are called) on the same message with same nonce will then be equal to the adaptor signature offset by ''t'', meaning that learning ''t'' is equivalent to learning a correct signature. +This can be used to enable atomic swaps or even [https://eprint.iacr.org/2018/472 general payment channels] in which the atomicity of disjoint transactions is ensured using the signatures themselves, rather than Bitcoin script support. The resulting transactions will appear to verifiers to be no different from ordinary single-signer transactions, except perhaps for the inclusion of locktime refund logic. + +Adaptor signatures, beyond the efficiency and privacy benefits of encoding script semantics into constant-sized signatures, have additional benefits over traditional hash-based payment channels. Specifically, the secret values ''t'' may be reblinded between hops, allowing long chains of transactions to be made atomic while even the participants cannot identify which transactions are part of the chain. Also, because the secret values are chosen at signing time, rather than key generation time, existing outputs may be repurposed for different applications without recourse to the blockchain, even multiple times. + +===Blind Signatures=== + +Schnorr signatures admit a very [https://www.math.uni-frankfurt.de/~dmst/research/papers/schnorr.blind_sigs_attack.2001.pdf simple '''blind signature''' construction] which is a signature that a signer produces at the behest of another party without learning what he has signed. +These can for example be used in [https://github.com/jonasnick/scriptless-scripts/blob/blind-swaps/md/partially-blind-swap.md Partially Blind Atomic Swaps], a construction to enable transferring of coins, mediated by an untrusted escrow agent, without connecting the transactors in the public blockchain transaction graph. + +While the traditional Schnorr blind signatures are vulnerable to [https://www.iacr.org/archive/crypto2002/24420288/24420288.pdf Wagner's attack], there are [https://www.math.uni-frankfurt.de/~dmst/teaching/SS2012/Vorlesung/EBS5.pdf a number of mitigations] which allow them to be usable in practice without any known attacks. Nevertheless, more analysis is required to be confident about the security of the blind signature scheme. + +== Test Vectors and Reference Code == + +For development and testing purposes, we provide a [[bip-schnorr/test-vectors.csv|collection of test vectors in CSV format]] and a naive but highly inefficient and non-constant time [[bip-schnorr/reference.py|pure Python 3.7 reference implementation of the signing and verification algorithm]]. +The reference implementation is for demonstration purposes only and not to be used in production environments. + +== Footnotes == + + + +== Acknowledgements == + +This document is the result of many discussions around Schnorr based signatures over the years, and had input from Johnson Lau, Greg Maxwell, Jonas Nick, Andrew Poelstra, Tim Ruffing, Rusty Russell, and Anthony Towns. diff --git a/bip-schnorr/reference.py b/bip-schnorr/reference.py new file mode 100644 index 0000000..48a36a6 --- /dev/null +++ b/bip-schnorr/reference.py @@ -0,0 +1,136 @@ +import hashlib +import binascii + +p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F +n = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 +G = (0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798, 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8) + +def point_add(P1, P2): + if (P1 is None): + return P2 + if (P2 is None): + return P1 + if (P1[0] == P2[0] and P1[1] != P2[1]): + return None + if (P1 == P2): + lam = (3 * P1[0] * P1[0] * pow(2 * P1[1], p - 2, p)) % p + else: + lam = ((P2[1] - P1[1]) * pow(P2[0] - P1[0], p - 2, p)) % p + x3 = (lam * lam - P1[0] - P2[0]) % p + return (x3, (lam * (P1[0] - x3) - P1[1]) % p) + +def point_mul(P, n): + R = None + for i in range(256): + if ((n >> i) & 1): + R = point_add(R, P) + P = point_add(P, P) + return R + +def bytes_from_int(x): + return x.to_bytes(32, byteorder="big") + +def bytes_from_point(P): + return (b'\x03' if P[1] & 1 else b'\x02') + bytes_from_int(P[0]) + +def point_from_bytes(b): + if b[0] in [b'\x02', b'\x03']: + odd = b[0] - 0x02 + else: + return None + x = int_from_bytes(b[1:33]) + y_sq = (pow(x, 3, p) + 7) % p + y0 = pow(y_sq, (p + 1) // 4, p) + if pow(y0, 2, p) != y_sq: + return None + y = p - y0 if y0 & 1 != odd else y0 + return [x, y] + +def int_from_bytes(b): + return int.from_bytes(b, byteorder="big") + +def hash_sha256(b): + return hashlib.sha256(b).digest() + +def jacobi(x): + return pow(x, (p - 1) // 2, p) + +def schnorr_sign(msg, seckey): + if len(msg) != 32: + raise ValueError('The message must be a 32-byte array.') + if not (1 <= seckey <= n - 1): + raise ValueError('The secret key must be an integer in the range 1..n-1.') + k0 = int_from_bytes(hash_sha256(bytes_from_int(seckey) + msg)) % n + if k0 == 0: + raise RuntimeError('Failure. This happens only with negligible probability.') + R = point_mul(G, k0) + k = n - k0 if (jacobi(R[1]) != 1) else k0 + e = int_from_bytes(hash_sha256(bytes_from_int(R[0]) + bytes_from_point(point_mul(G, seckey)) + msg)) % n + return bytes_from_int(R[0]) + bytes_from_int((k + e * seckey) % n) + +def schnorr_verify(msg, pubkey, sig): + if len(msg) != 32: + raise ValueError('The message must be a 32-byte array.') + if len(pubkey) != 33: + raise ValueError('The public key must be a 33-byte array.') + if len(sig) != 64: + raise ValueError('The signature must be a 64-byte array.') + P = point_from_bytes(pubkey) + if (P is None): + return False + r = int_from_bytes(sig[0:32]) + s = int_from_bytes(sig[32:64]) + if (r >= p or s >= n): + return False + e = int_from_bytes(hash_sha256(sig[0:32] + bytes_from_point(P) + msg)) % n + R = point_add(point_mul(G, s), point_mul(P, n - e)) + if R is None or jacobi(R[1]) != 1 or R[0] != r: + return False + return True + +# +# The following code is only used to verify the test vectors. +# +import csv + +def test_vectors(): + all_passed = True + with open('test-vectors.csv', newline='') as csvfile: + reader = csv.reader(csvfile) + reader.__next__() + for row in reader: + (index, seckey, pubkey, msg, sig, result, comment) = row + pubkey = bytes.fromhex(pubkey) + msg = bytes.fromhex(msg) + sig = bytes.fromhex(sig) + result = result == 'TRUE' + print('\nTest vector #%-3i: ' % int(index)) + if seckey != '': + seckey = int(seckey, 16) + sig_actual = schnorr_sign(msg, seckey) + if sig == sig_actual: + print(' * Passed signing test.') + else: + print(' * Failed signing test.') + print(' Excepted signature:', sig.hex()) + print(' Actual signature:', sig_actual.hex()) + all_passed = False + result_actual = schnorr_verify(msg, pubkey, sig) + if result == result_actual: + print(' * Passed verification test.') + else: + print(' * Failed verification test.') + print(' Excepted verification result:', result) + print(' Actual verification result:', result_actual) + if comment: + print(' Comment:', comment) + all_passed = False + print() + if all_passed: + print('All test vectors passed.') + else: + print('Some test vectors failed.') + return all_passed + +if __name__ == '__main__': + test_vectors() diff --git a/bip-schnorr/speedup-batch.png b/bip-schnorr/speedup-batch.png new file mode 100644 index 0000000..fe672d4 Binary files /dev/null and b/bip-schnorr/speedup-batch.png differ diff --git a/bip-schnorr/test-vectors.csv b/bip-schnorr/test-vectors.csv new file mode 100644 index 0000000..9b89a7b --- /dev/null +++ b/bip-schnorr/test-vectors.csv @@ -0,0 +1,17 @@ +index,secret key,public key,message,signature,verification result,comment +1,0000000000000000000000000000000000000000000000000000000000000001,0279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798,0000000000000000000000000000000000000000000000000000000000000000,787A848E71043D280C50470E8E1532B2DD5D20EE912A45DBDD2BD1DFBF187EF67031A98831859DC34DFFEEDDA86831842CCD0079E1F92AF177F7F22CC1DCED05,TRUE, +2,B7E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEF,02DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,2A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1D1E51A22CCEC35599B8F266912281F8365FFC2D035A230434A1A64DC59F7013FD,TRUE, +3,C90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B14E5C7,03FAC2114C2FBB091527EB7C64ECB11F8021CB45E8E7809D3C0938E4B8C0E5F84B,5E2D58D8B3BCDF1ABADEC7829054F90DDA9805AAB56C77333024B9D0A508B75C,00DA9B08172A9B6F0466A2DEFD817F2D7AB437E0D253CB5395A963866B3574BE00880371D01766935B92D2AB4CD5C8A2A5837EC57FED7660773A05F0DE142380,TRUE, +4,,03DEFDEA4CDB677750A420FEE807EACF21EB9898AE79B9768766E4FAA04A2D4A34,4DF3C3F68FCC83B27E9D42C90431A72499F17875C81A599B566C9889B9696703,00000000000000000000003B78CE563F89A0ED9414F5AA28AD0D96D6795F9C6302A8DC32E64E86A333F20EF56EAC9BA30B7246D6D25E22ADB8C6BE1AEB08D49D,TRUE, +5,,031B84C5567B126440995D3ED5AABA0565D71E1834604819FF9C17F5E9D5DD078F,0000000000000000000000000000000000000000000000000000000000000000,52818579ACA59767E3291D91B76B637BEF062083284992F2D95F564CA6CB4E3530B1DA849C8E8304ADC0CFE870660334B3CFC18E825EF1DB34CFAE3DFC5D8187,TRUE,"test fails if jacobi symbol of x(R) instead of y(R) is used" +6,,03FAC2114C2FBB091527EB7C64ECB11F8021CB45E8E7809D3C0938E4B8C0E5F84B,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,570DD4CA83D4E6317B8EE6BAE83467A1BF419D0767122DE409394414B05080DCE9EE5F237CBD108EABAE1E37759AE47F8E4203DA3532EB28DB860F33D62D49BD,TRUE,"test fails if msg is reduced" +7,,03EEFDEA4CDB677750A420FEE807EACF21EB9898AE79B9768766E4FAA04A2D4A34,4DF3C3F68FCC83B27E9D42C90431A72499F17875C81A599B566C9889B9696703,00000000000000000000003B78CE563F89A0ED9414F5AA28AD0D96D6795F9C6302A8DC32E64E86A333F20EF56EAC9BA30B7246D6D25E22ADB8C6BE1AEB08D49D,FALSE,"public key not on the curve" +8,,02DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,2A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1DFA16AEE06609280A19B67A24E1977E4697712B5FD2943914ECD5F730901B4AB7,FALSE,"incorrect R residuosity" +9,,03FAC2114C2FBB091527EB7C64ECB11F8021CB45E8E7809D3C0938E4B8C0E5F84B,5E2D58D8B3BCDF1ABADEC7829054F90DDA9805AAB56C77333024B9D0A508B75C, 00DA9B08172A9B6F0466A2DEFD817F2D7AB437E0D253CB5395A963866B3574BED092F9D860F1776A1F7412AD8A1EB50DACCC222BC8C0E26B2056DF2F273EFDEC,FALSE,"negated message hash" +10,,0279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798,0000000000000000000000000000000000000000000000000000000000000000,787A848E71043D280C50470E8E1532B2DD5D20EE912A45DBDD2BD1DFBF187EF68FCE5677CE7A623CB20011225797CE7A8DE1DC6CCD4F754A47DA6C600E59543C,FALSE,"negated s value" +11,,03DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,2A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1D1E51A22CCEC35599B8F266912281F8365FFC2D035A230434A1A64DC59F7013FD,FALSE,"negated public key" +12,,02DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,00000000000000000000000000000000000000000000000000000000000000009E9D01AF988B5CEDCE47221BFA9B222721F3FA408915444A4B489021DB55775F,FALSE,"sG - eP is infinite. Test fails in single verification if jacobi(y(inf)) is defined as 1 and x(inf) as 0" +13,,02DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,0000000000000000000000000000000000000000000000000000000000000001D37DDF0254351836D84B1BD6A795FD5D523048F298C4214D187FE4892947F728,FALSE,"sG - eP is infinite. Test fails in single verification if jacobi(y(inf)) is defined as 1 and x(inf) as 1" +14,,02DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,4A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1D1E51A22CCEC35599B8F266912281F8365FFC2D035A230434A1A64DC59F7013FD,FALSE,"sig[0:32] is not an X coordinate on the curve" +15,,02DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC2F1E51A22CCEC35599B8F266912281F8365FFC2D035A230434A1A64DC59F7013FD,FALSE,"sig[0:32] is equal to field size" +16,,02DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,2A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141,FALSE,"sig[32:64] is equal to curve order" -- cgit v1.2.3 From c7d7034b16f4229e6b723155e1192d4728cffeb1 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 6 May 2019 10:46:09 -0700 Subject: Add taproot/tapscript bips drafts --- bip-taproot.mediawiki | 285 ++++++++++++++++++++++++++++++++++++++++++++++++ bip-taproot/tree.png | Bin 0 -> 78937 bytes bip-tapscript.mediawiki | 147 +++++++++++++++++++++++++ 3 files changed, 432 insertions(+) create mode 100644 bip-taproot.mediawiki create mode 100644 bip-taproot/tree.png create mode 100644 bip-tapscript.mediawiki diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki new file mode 100644 index 0000000..2e8b43b --- /dev/null +++ b/bip-taproot.mediawiki @@ -0,0 +1,285 @@ +
+  BIP: bip-taproot
+  Layer: Consensus (soft fork)
+  Title: Taproot: SegWit version 1 output spending rules
+  Author: Pieter Wuille 
+  Comments-Summary: No comments yet.
+  Comments-URI:
+  Status: Draft
+  Type: Standards Track
+  Created:
+  License: BSD-3-Clause
+
+ +==Introduction== + +===Abstract=== + +This document proposes a new SegWit version 1 output type, with spending rules based on Taproot, Schnorr signatures, and Merkle branches. + +===Copyright=== + +This document is licensed under the 3-clause BSD license. + +===Motivation=== + +A number of related ideas for improving Bitcoin's scripting capabilities have been previously proposed: Schnorr signatures (bip-schnorr), Merkle branches ("MAST", [https://github.com/bitcoin/bips/blob/master/bip-0114.mediawiki BIP114], [https://github.com/bitcoin/bips/blob/master/bip-0117.mediawiki BIP117]), new sighash modes ([https://github.com/bitcoin/bips/blob/master/bip-0118.mediawiki BIP118]), new opcodes like CHECKSIGFROMSTACK, [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-January/015614.html Taproot], [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-February/015700.html Graftroot], [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-July/016249.html G'root], and [https://bitcointalk.org/index.php?topic=1377298.0 cross-input aggregation]. + +Combining all these ideas in a single proposal would be an extensive change, be hard to review, and likely miss new discoveries that otherwise could have been made along the way. Some of these ideas are also less mature than others. On the other hand, separating them all into independent proposals would reduce the efficiency and privacy gains to be had, and complicate analysis of their interactions. It seems preferable to focus on one goal set at a time, and combine interacting technologies to achieve them. + +==Design== + +This proposal focuses on improvements to privacy, efficiency, and flexibility of Bitcoin's smart contracts, subject to two restrictions: +* Not adding any new strong security assumptions +* Not combining into the proposal any functionality which could be simply implemented independently. + +Specifically, it seeks to minimize how much information about the spendability conditions of a transaction output is revealed on chain at creation or spending time. To avoid reducing the effectiveness of future improvements a number of upgrade mechanisms are also included, as well as fixes for minor but long-standing issues. + +As a result we choose this combination of technologies: +* '''Merkle branches''' let us only reveal the actually executed part of the script to the blockchain, as opposed to all possible ways a script can be executed. Among the various known mechanisms for implementing this, one where the Merkle tree becomes part of the script's structure directly maximizes the space savings, so that approach is chosen. +* '''Taproot''' on top of that lets us merge the traditionally separate pay-to-pubkey and pay-to-scripthash policies, making all outputs spendable by either a key or (optionally) a script, and indistinguishable from each other. As long as the key-based spending path is used for spending, it is not revealed whether a script path was permitted as well, resulting in space savings and an increase in scripting privacy at spending time. +* Taproot's advantages become apparent under the assumption that most applications involve outputs that could be spent by all parties agreeing. That's where '''Schnorr''' signatures come in, as they permit [https://eprint.iacr.org/2018/068 key aggregation]: a public key can be constructed from multiple participant public keys, and which requires cooperation between all participants to sign for. Such multi-party public keys and signatures are indistinguishable from their single-party equivalents. This means that under this Taproot assumption, the all-parties-agree case can be handled using the key-based spending path, which is both private and efficient using Taproot. This can be generalized to arbitrary M-of-N policies, as Schnorr signatures support threshold signing, at the cost of more complex setup protocols. +* As Schnorr signatures also permit '''batch validation''', allowing multiple signatures to be validated together more efficiently than validating each one independently, we make sure all parts of the design are compatible with this. +* Where unused bits appear as a result of the above changes, they are reserved for mechanisms for '''future extensions'''. As a result, every script in the Merkle tree has an associated version such that new script versions can be introduced with a soft fork while remaining compatible with bip-taproot. Additionally, future soft forks can make use of the currently unused annex in the witness (see [[#Rationale]]). +* While the core semantics of the '''signature hashing algorithm''' are not changed, a number of improvements are included in this proposal. The new signature hashing algorithm fixes the verification capabilities of offline signing devices by including amount and scriptPubKey in the digest, avoids unnecessary hashing, introduces '''tagged hashes''' and defines a default sighash byte. + +Not included in this proposal are additional features like new sighash modes or opcodes that can be included with no loss in effectiveness as a future extension. Also not included is cross-input aggregation, as it [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-March/015838.html interacts] in complex ways with upgrade mechanisms and solutions to that are still [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-October/016461.html in flux]. + +== Specification == + +This section specifies the Taproot consensus rules. Validity is defined by exclusion: a block or transaction is valid if no condition exists that marks it failed. + +The notation below follows that of bip-schnorr. + +=== Tagged hashes === + +Cryptographic hash functions are used for multiple purposes in the specification below and in Bitcoin in general. To make sure hashes used in one context can't be reinterpreted in another one, all hash functions are tweaked with a context-dependent tag name, in such a way that collisions across contexts can be assumed to be infeasible. + +In the text below, ''hashtag(m)'' is a shorthand for ''SHA256(SHA256(tag) || SHA256(tag) || m)'', where ''tag'' is a UTF-8 encoded tag name. +* So far, nowhere in the Bitcoin protocol are hashes used where the input of SHA256 starts with two (non-double) SHA256 hashes, making collisions with existing uses of hash functions infeasible. +* Because the prefix ''SHA256(tag) || SHA256(tag)'' is a 64-byte long context-specific constant, optimized implementations are possible (identical to SHA256 itself, but with a modified initial state). +* Using SHA256 of the tag name itself is reasonably simple and efficient for implementations that don't choose to use the optimization above. + +=== Script validation rules === + +A Taproot output is a SegWit output (native or P2SH-nested, see [https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki BIP141]) with version number 1, and a 33-byte witness program whose first byte is 0 or 1. +The following rules only apply when such an output is being spent. Any other outputs, including version 1 outputs with lengths other than 33 bytes, or with a first byte different from 0 or 1, remain unencumbered. + +* Let ''u'' be the 33-byte array containing the witness program (second push in scriptPubKey or P2SH redeemScript). +* Let ''Q = point(byte(2 + u[0]) || u[1:33])'''''Why is the public key directly included in the output?''' While typical earlier constructions store a hash of a script or a public key in the output, this is rather wasteful when a public key is always involved. To guarantee batch verifiability, ''Q'' must be known to every verifier, and thus only revealing its hash as an output would imply adding an additional 33 bytes to the witness. Furthermore, to maintain [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2016-January/012198.html 128-bit collision security] for outputs, a 256-bit hash would be required anyway, which is comparable in size (and thus in cost for senders) to revealing the public key directly. While the usage of public key hashes is often said to protect against ECDLP breaks or quantum computers, this protection is very weak at best: transactions are not protected while being confirmed, and a very [https://twitter.com/pwuille/status/1108097835365339136 large portion] of the currency's supply is not under such protection regardless. Actual resistance to such systems can be introduced by relying on different cryptographic assumptions, but this proposal focuses on improvements that do not change the security model. Note that using P2SH-wrapped outputs only have 80-bit collision security. This is considered low, and is relevant whenever the output includes data from more than a single party (public keys, hashes, ...). If this is not a valid point on the curve, fail. +* Fail if the witness stack has 0 elements. +* If there are at least two witness elements, and the first byte of the last element is 0x50'''Why is the first byte of the annex 0x50?''' Like the 0xc0-0xc1 constants, 0x50 is chosen as it could not be confused with a valid P2WPKH or P2WSH spending. As the control block's initial byte's lowest bit is used to indicate the public key's Y oddness, each script version needs two subsequence byte values that are both not yet used in P2WPKH or P2WSH spending. To indicate the annex, only an "unpaired" available byte is necessary like 0x50. This choice maximizes the available options for future script versions., this last element is called ''annex'' ''a'''''What is the purpose of the annex?''' The annex is a reserved space for future extensions, such as indicating the validation costs of computationally expensive new opcodes in a way that is recognizable without knowing the outputs being spent. Until the meaning of this field is defined by another softfork, users SHOULD NOT include annex in transactions, or it may lead to PERMANENT FUND LOSS. and is removed from the witness stack. The annex (or the lack of thereof) is always covered by the transaction digest and contributes to transaction weight, but is otherwise ignored during taproot validation. +* If there is exactly one element left in the witness stack, key path spending is used: +** The single witness stack element is interpreted as the signature and must be valid (see the next section) for the public key ''Q'' and taproot transaction digest (to be defined hereinafter) as message. Fail if it is not. Otherwise pass. +* If there are at least two witness elements left, script path spending is used: +** Call the second-to-last stack element ''s'', the script. +** The last stack element is called the control block ''c'', and must have length ''33 + 32m'', for a value of ''m'' that is an integer between 0 and 32, inclusive. Fail if it does not have such a length. +** Let ''P = point(byte(2 + (c[0] & 1)) || c[1:33])'''''What is the purpose of the first byte of the control block?''' The first byte of the control block has three distinct functions: +* The low bit is used to denote the oddness of the Y coordinate of the ''P'' point. +* By keeping the top two bits set to true, it can be guaranteed that scripts can be recognized without knowledge of the UTXO being spent, simplifying analysis. This is because such values cannot occur as first byte of the final stack element in either P2WPKH or P2WSH spends. +* The remaining five bits are used for introducing new script versions that are not observable unless actually executed. +. Fail if this point is not on the curve. +** Let ''l = c[0] & 0xfe'', the leaf version. +** Let ''k0 = hashTapLeaf(l || compact_size(size of s) || s)''; also call it the ''tapleaf hash''. +** For ''j'' in ''[0,1,...,m-1]'': +*** Let ''ej = c[33+32j:65+32j]''. +*** Let ''kj+1 depend on whether ''kj < ej'' (lexicographically)'''Why are child elements sorted before hashing in the Merkle tree?''' By doing so, it is not necessary to reveal the left/right directions along with the hashes in revealed Merkle branches. This is possible because we do not actually care about the position of specific scripts in the tree; only that they are actually committed to.: +**** If ''kj < ej'': ''kj+1 = hashTapBranch(kj || ej)'''''Why not use a more efficient hash construction for inner Merkle nodes?''' The chosen construction does require two invocations of the SHA256 compression functions, one of which can be avoided in theory (see BIP98). However, it seems preferable to stick to constructions that can be implemented using standard cryptographic primitives, both for implementation simplicity and analyzability. If necessary, a significant part of the second compression function can be optimized out by [https://github.com/bitcoin/bitcoin/pull/13191 specialization] for 64-byte inputs.. +**** If ''kj ≥ ej'': ''kj+1 = hashTapBranch(ej || kj)''. +** Let ''t = hashTapTweak(bytes(P) || km) = hashTapTweak(2 + (c[0] & 1) || c[1:33] || km)''. +** If ''t ≥ 0xFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141'' (order of secp256k1), fail. +** If ''Q ≠ P + int(t)G'', fail. +** Execute the script, according to the applicable script rules'''What are the applicable script rules in script path spends?''' Bip-tapscript specifies validity rules that apply if the leaf version is ''0xc0'', but future proposals can introduce rules for other leaf versions., using the witness stack elements excluding the script ''s'', the control block ''c'', and the annex ''a'' if present, as initial stack. + +''Q'' is referred to as ''taproot output key'' and ''P'' as ''taproot internal key''. + +=== Signature validation rules === + +The following rules apply: + +* If the signature is not 64'''Why permit two signature lengths?''' By making the most common type of hash_type implicit, a byte can often be saved. or 65 bytes, fail. +* If the signature size is 65 bytes: +** If the final byte is not a valid hash_type (defined hereinafter), fail. +** If the final byte is 0x00, fail'''Why can the hash_type not be 0x00 in 65-byte signatures?''' Permitting that would enable malleating 64-byte signatures into 65-byte ones, resulting a different fee rate than the creator intended. +** If the first 64 bytes are not a valid signature according to bip-schnorr for the public key and message set to the transaction digest with hash_type set as the final byte, fail. +* If the signature size is 64 bytes: +** If it is not a valid signature according to bip-schnorr for the public key and the hash_type = 0x00 transaction digest as message, fail. +* Otherwise the signature is valid. + +==== hash_type ==== + +hash_type is an 8-bit unsigned value. The SIGHASH encodings from the legacy script system are used, including SIGHASH_ALL, SIGHASH_NONE, SIGHASH_SINGLE, and SIGHASH_ANYONECANPAY + +The following use of hash_type are invalid, and fail execution: + +* Using SIGHASH_SINGLE without a "corresponding output" (an output with the same index as the input being verified). +* Using any hash_type value that is not 0x00, 0x01, 0x02, 0x03, 0x81, 0x82, or 0x83'''Why reject unknown hash_type values?''' By doing so, it is easier to reason about the worst case amount of signature hashing an implementation with adequate caching must perform.. +* The signature has 65 bytes, and hash_type is 0x00. + +==== Transaction digest ==== + +As the message for signature verification, transaction digest is ''hashTapSighash'' of the following values (size in byte) serialized. Numerical values in 2, 4, or 8-byte are encoded in little-endian. + +* Control: +** epoch (1): always 0. '''What's the purpose of the epoch?''' The epoch can be increased to allow securely creating a new transaction digest algorithms with large changes to the structure or interpretation of hash_type if needed. +** hash_type (1). +* Transaction data: +** nVersion (4): the nVersion of the transaction. +** nLockTime (4): the nLockTime of the transaction. +** If the SIGHASH_ANYONECANPAY flag is not set: +*** sha_prevouts (32): the SHA256 of the serialization of all input outpoints. +*** sha_amounts (32): the SHA256 of the serialization of all input amounts. +*** sha_sequences (32): the SHA256 of the serialization of all input nSequence. +** If both the SIGHASH_NONE and SIGHASH_SINGLE flags are not set: +*** sha_outputs (32): the SHA256 of the serialization of all outputs in CTxOut format. +* Data about this input: +** spend_type (1): +*** Bit-0 is set if the scriptPubKey being spent is P2SH (opposed to "native segwit"). +*** Bit-1 is set if an annex is present (the original witness stack has two or more witness elements, and the first byte of the last element is 0x50). +*** The other bits are unset. +** scriptPubKey (24 or 36): scriptPubKey of the previous output spent by this input, serialized as script inside CTxOut. The size is 24-byte for P2SH-embedded segwit, or 36-byte for native segwit. +** If the SIGHASH_ANYONECANPAY flag is set: +*** outpoint (36): the COutPoint of this input (32-byte hash + 4-byte little-endian). +*** amount (8): value of the previous output spent by this input. +*** nSequence (4): nSequence of this input. +** If the SIGHASH_ANYONECANPAY flag is not set: +*** input_index (2): index of this input in the transaction input vector. Index of the first input is 0. +** If the bit-1 of spend_type is set: +*** sha_annex (32): the SHA256 of (compact_size(size of annex) || annex). +* Data about this output: +** If the SIGHASH_SINGLE flag is set: +*** sha_single_output (32): the SHA256 of the corresponding output in CTxOut format. + +The total number of bytes hashed is at most ''209'''''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''177 - is_anyonecanpay * 50 - is_none * 32 - is_p2sh_spending * 12 + has_annex * 32''.. + +In summary, the semantics of the BIP143 sighash types remain unchanged, except the following: +# The way and order of serialization is changed.'''Why is the serialization in the transaction digest changed?''' Hashes that go into the digest and the digest itself are now computed with a single SHA256 invocation instead of double SHA256. There is no expected security improvement by doubling SHA256 because this only protects against length-extension attacks against SHA256 which are not a concern for transaction digests because there is no secret data. Therefore doubling SHA256 is a waste of resources. The digest computation now follows a logical order with transaction level data first, then input data and output data. This allows to efficiently cache the transaction part of the digest across different inputs using the SHA256 midstate. Additionally, digest computation avoids unnecessary hashing as opposed to BIP143 digests in which parts may be set zero and before hashing them. Despite that, collisions are made impossible by committing to the length of the data (implicit in hash_type and spend_type) before the variable length data. +# The digest commits to the scriptPubKey'''Why does the transaction digest commit to the scriptPubKey?''' This prevents lying to offline signing devices about the type of output being spent, even when the actually executed script (scriptCode in BIP143) is correct. Without committing to the scriptPubKey an attacker can fool the device into overpaying fees by asking it to sign for a P2SH wrapped segwit output but actually using it to spend a native segwit output.. +# If the SIGHASH_ANYONECANPAY flag is not set, the digest commits to the amounts of ''all'' transaction inputs.'''Why does the transaction digest commit to the amounts of all transaction inputs?''' This eliminates the possibility to lie to offline signing devices about the fee of a transaction. +# The digest commits to all input nSequence if SIGHASH_NONE or SIGHASH_SINGLE are set (unless SIGHASH_ANYONECANPAY is set as well).'''Why does the transaction digest commit to all input nSequence if SIGHASH_SINGLE or SIGHASH_NONE are set?''' Because setting them already makes the digest commit to the prevouts part of all transaction inputs, it is not useful to treat the nSequence any different. Moreover, this change makes nSequence consistent with the view that SIGHASH_SINGLE and SIGHASH_NONE only modify the digest with respect to transaction outputs and not inputs. +# The digest commits to taproot-specific data epoch, spend_type and annex (if present). + +== Constructing and spending Taproot outputs == + +This section discusses how to construct and spend Taproot outputs. It only affects wallet software that chooses to implement receiving and spending, +and is not consensus critical in any way. + +Conceptually, every Taproot output corresponds to a combination of a single public key condition (the internal key), and zero or more general conditions encoded in scripts organized in a tree. +Satisfying any of these conditions is sufficient to spend the output. + +'''Initial steps''' The first step is determining what the internal key and the organization of the rest of the scripts should be. The specifics are likely application dependent, but here are some general guidelines: +* When deciding between scripts with conditionals (OP_IF etc.) and splitting them up into multiple scripts (each corresponding to one execution path through the original script), it is generally preferable to pick the latter. +* When a single condition requires signatures with multiple keys, key aggregation techniques like MuSig can be used to combine them into a single key. The details are out of scope for this document, but note that this may complicate the signing procedure. +* If one or more of the spending conditions consist of just a single key (after aggregation), the most likely one should be made the internal key. If no such condition exists, it may be worthwhile adding one that consists of an aggregation of all keys participating in all scripts combined; effectively adding an "everyone agrees" branch. If that is inacceptable, pick as internal key a point with unknown discrete logarithm (TODO). +* The remaining scripts should be organized into the leaves of a binary tree. This can be a balanced tree if each of the conditions these scripts correspond to are equally likely. If probabilities for each condition are known, consider constructing the tree as a Huffman tree. + +'''Computing the output script''' Once the spending conditions are split into an internal key internal_pubkey and a binary tree whose leaves are (leaf_version, script) tuples, the following Python3 algorithm can be used to compute the output script. In the code below, ser_script prefixes its input with a CCompactSize-encoded length, and public key objects have methods get_bytes to get their compressed encoding (see bip-schnorr) and tweak_add to add a multiple of the secp256k1 generator to it (similar to BIP32's derivation). + + +import hashlib + +def tagged_hash(tag, msg): + tag_hash = hashlib.sha256(tag.encode()).digest() + return hashlib.sha256(tag_hash + tag_hash + msg).digest() + +def taproot_tree_helper(script_tree): + if isinstance(script_tree, tuple): + leaf_version, script = script_tree + h = tagged_hash("TapLeaf", bytes([leaf_version]) + ser_script(script)) + return ([((leaf_version, script), bytes())], h) + left, left_h = taproot_tree_helper(script_tree[0]) + right, right_h = taproot_tree_helper(script_tree[1]) + ret = [(l, c + right_h) for l, c in left] + [(l, c + left_h) for l, c in right] + if right_h < left_h: + left_h, right_h = right_h, left_h + return (ret, tagged_hash("TapBranch", left_h + right_h)) + +def taproot_output_script(internal_pubkey, script_tree): + """Given a internal public key and a tree of scripts, compute the output script. + script_tree is either: + - a (leaf_version, script) tuple (leaf_version is 0xc0 for bip-tapscript scripts) + - a list of two elements, each with the same structure as script_tree itself""" + _, h = taproot_tree_helper(script_tree) + t = tagged_hash("TapTweak", internal_pubkey.get_bytes() + h) + assert int.from_bytes(t, 'big') < SECP256K1_ORDER + output_pubkey = internal_pubkey.tweak_add(t).get_bytes() + return bytes([0x01, 0x21, output_pubkey[0] & 1]) + output_pubkey[1:] + + +The function taproot_output_script returns a byte array with the scriptPubKey. It can be P2SH wrapped if desired (see BIP141). + +[[File:bip-taproot/tree.png|frame|This diagram shows the hashing structure to obtain the tweak from an internal key ''P'' and a Merkle tree consisting of 3 script leaves.]] + +'''Spending using the internal key''' A Taproot output can be spent with the private key corresponding to the internal_pubkey. To do so, a witness stack consisting of a single element, a bip-schnorr signature on the signature hash as defined above, with the private key tweaked by the same t in the above snippet. See the code below: + + +def taproot_sign_internal_key(internal_pubkey, script_tree, internal_privkey, hash_type): + _, h = taproot_tree_helper(script_tree) + t = tagged_hash("TapTweak", internal_pubkey.get_bytes() + h) + output_privkey = internal_privkey.tweak_add(t) + sig = output_privkey.sign_schnorr(sighash(hash_type)) + if hash_type != 0: + sig += bytes([hash_type]) + return [sig] + + +This function returns the witness stack necessary, and assumes a tweak_add method on private keys, and a sighash function to compute the signature hash as defined above (for simplicity, the snippet above ignores passing information like the transaction, the input position, P2SH or not, ... to the sighashing code). + +'''Spending using one of the scripts''' A Taproot output can be spent by satisfying any of the scripts used in its construction. To do so, a witness stack consisting of the script's inputs, plus the script itself and the control block are necessary. See the code below: + + +def taproot_sign_script(internal_pubkey, script_tree, script_num, inputs): + info, _ = taproot_tree_helper(script_tree) + (leaf_version, script), path = info[script_num] + pubkey_bytes = internal_pubkey.get_bytes() + pubkey_data = bytes([(pubkey_bytes[0] & 1) + leaf_version]) + pubkey_bytes[1:] + return inputs + [script, pubkey_data + path] + + +== Security == + +Taproot improves the privacy of Bitcoin because instead of revealing all possible conditions for spending an output, only the satisfied spending condition has to be published. +Ideally, outputs are spent using the key path which prevents observers from learning the spending conditions of a coin. +A key path spend could be a "normal" payment from a single- or multi-signature wallet or the cooperative settlement of hidden multiparty contract. + +A script path spend leaks that there is a script path and that the key path was not applicable - for example because the involved parties failed to reach agreement. +Moreover, the depth of a script in the Merkle root leaks information including the minimum depth of the tree, which suggests specific wallet software that created the output and helps clustering. +Therefore, the privacy of key spends can be improved by deviating from the optimal tree determined by the probability distribution over the leaves. + +Just like other existing output types, taproot outputs should never reuse keys. +This does not only apply to the particular leaf that was used to spend an output but to all leaves committed to in the output. +If leaves were reused, it could happen that spending a different output would reuse the same Merkle branches in the Merkle proof. +Using fresh keys implies that taproot output construction does not need to take special measures to randomizing leaf positions because they are already randomized due to the branch-sorting Merkle tree construction used in taproot. +This does not avoid leaking information through the leaf depth and therefore only applies to balanced (sub-) trees. +In addition, every leaf should have a set of keys distinct from every other leaf. +The reason for this is to increase leaf entropy and prevent an observer from learning an undisclosed script using brute-force search. + +== Test vectors == + +Examples with creation transaction and spending transaction pairs, valid and invalid. + +Examples of preimage for sighashing for each of the sighash modes. + +== Rationale == + + + +== Deployment == + +TODO + +== Backwards compatibility == +As a soft fork, older software will continue to operate without modification. +Non-upgraded nodes, however, will consider all SegWit version 1 witness programs as anyone-can-spend scripts. +They are strongly encouraged to upgrade in order to fully validate the new programs. + +Non-upgraded wallets can receive and send bitcoin from non-upgraded and upgraded wallets using SegWit version 0 programs, traditional pay-to-pubkey-hash, etc. +Depending on the implementation non-upgraded wallets may be able to send to Segwit version 1 programs if they support sending to BIP173 Bech32 addresses and non-standardness of these outputs does not prevent transaction broadcasting. +Non-upgraded wallets can send bitcoin to upgraded wallets using Segwit version 1 programs nested in BIP16 P2SH. + +== Acknowledgements == + +This document is the result of discussions around script and signature improvements with many people, and had direct constributions from Jonas Nick, Anthony Towns, Greg Maxwell, and others. It further builds on top of earlier published proposals such as Taproot by Greg Maxwell, and Merkle branch constructions by Russell O'Connor, Johnson Lau, and Mark Friedenbach. + +Thanks to Arik Sosman for suggesting to sort Merkle node children before hashes, removing the need to transfer the position in the tree. + diff --git a/bip-taproot/tree.png b/bip-taproot/tree.png new file mode 100644 index 0000000..af56eda Binary files /dev/null and b/bip-taproot/tree.png differ diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki new file mode 100644 index 0000000..ce42098 --- /dev/null +++ b/bip-tapscript.mediawiki @@ -0,0 +1,147 @@ +
+  BIP: bip-tapscript
+  Layer: Consensus (soft fork)
+  Title: Validation of Taproot Scripts
+  Author: Pieter Wuille 
+  Comments-Summary: No comments yet.
+  Comments-URI:
+  Status: Draft
+  Type: Standards Track
+  Created:
+  License: BSD-3-Clause
+
+ +==Introduction== + +===Abstract=== + +This document specifies the semantics of the initial scripting system under bip-taproot. + +===Copyright=== + +This document is licensed under the 3-clause BSD license. + +===Motivation=== + +Bip-taproot proposes improvements to just the script structure, but some of its goals are incompatible with the semantics of certain opcodes within the scripting language itself. +While it is possible to deal with these in separate optional improvements, their impact is not guaranteed unless they are addressed simultaneously with bip-taproot itself. + +Specifically, the goal is making '''Schnorr signatures''', '''batch validation''', and '''signature hash''' improvements available to spends that use the script system as well. + +==Design== + +In order to achieve these goals, signature opcodes OP_CHECKSIG and OP_CHECKSIGVERIFY are modified to verify Schnorr signatures as specified in bip-schnorr and to use a new transaction digest based on the taproot transaction digest. +The tapscript transaction digest also simplifies OP_CODESEPARATOR handling and makes it more efficient. + +The inefficient OP_CHECKMULTISIG and OP_CHECKMULTISIGVERIFY opcodes are disabled. +Instead, a new opcode OP_CHECKSIGADD is introduced to allow creating the same multisignature policies in a batch-verifiable way. +Tapscript uses a new, simpler signature opcode limit fixing complicated interactions with transaction weight. +Furthermore, a potential malleability vector is eliminated by requiring MINIMALIF. + +Tapscript can be upgraded through soft forks by defining unknown key types, for example to add new hash_types or signature algorithms. +Additionally, the new tapscript OP_SUCCESS opcodes allow introducing new opcodes more cleanly than through OP_NOP. + +==Specification== + +The rules below only apply when validating a transaction input for which all of the conditions below are true: +* The transaction output is a '''segregated witness spend''' (i.e., either the scriptPubKey or BIP16 redeemScript is a witness program as defined in BIP141). +* It is a '''taproot spend''' as defined in bip-taproot (i.e., the witness version is 1, the witness program is 33 bytes, and the first of those is 0x00 or 0x01). +* It is a '''script path spend''' as defined in bip-taproot (i.e., after removing the optional annex from the witness stack, two or more stack elements remain). +* The leaf version is ''0xc0'' (i.e. the first byte of the last witness element after removing the optional annex is ''0xc0'' or ''0xc1'')'''How is the ''0xc0'' constant chosen?''' Following the guidelines in bip-taproot, by choosing a value having the two top bits set, tapscript spends are identifiable even without access to the UTXO being spent., marking it as a '''tapscript spend'''. + +Validation of such inputs must be equivalent to performing the following steps in the specified order. +# If the input is invalid due to BIP16, BIP141, or bip-taproot, fail. +# The script as defined in bip-taproot (i.e., the penultimate witness stack element after removing the optional annex) is called the '''tapscript''' and is decoded into opcodes, one by one: +## If any opcode numbered ''80, 98, 126-129, 131-134, 137-138, 141-142, 149-153, 187-254'' is encountered, validation succeeds (none of the rules below apply). This is true even if later bytes in the tapscript would fail to decode otherwise. These opcodes are renamed to OP_SUCCESS80, ..., OP_SUCCESS254, and collectively known as OP_SUCCESSx'''OP_SUCCESSx''' OP_SUCCESSx is a mechanism to upgrade the Script system. Using an OP_SUCCESSx before its meaning is defined by a softfork is insecure and leads to fund loss. The inclusion of OP_SUCCESSx in a script will pass it unconditionally. It precedes any script execution rules to avoid the difficulties in specifying various edge cases, for example: OP_SUCCESSx being the 202nd opcode, OP_SUCCESSx after too many signature opcodes, or even scripts with conditionals lacking OP_ENDIF. The mere existence of an OP_SUCCESSx anywhere in the script will guarantee a pass for all such cases. OP_SUCCESSx are similar to the OP_RETURN in very early bitcoin versions (v0.1 up to and including v0.3.5). The original OP_RETURN terminates script execution immediately, and return pass or fail based on the top stack element at the moment of termination. This was one of a major design flaws in the original bitcoin protocol as it permitted unconditional third party theft by placing an OP_RETURN in scriptSig. This is not a concern in the present proposal since it is not possible for a third party to inject an OP_SUCCESSx to the validation process, as the OP_SUCCESSx is part of the script (and thus committed to be the taproot output), implying the consent of the coin owner. OP_SUCCESSx can be used for a variety of upgrade possibilities: +* An OP_SUCCESSx could be turned into a functional opcode through a softfork. Unlike OP_NOPx-derived opcodes which only have read-only access to the stack, OP_SUCCESSx may also write to the stack. Any rule changes to an OP_SUCCESSx-containing script may only turn a valid script into an invalid one, and this is always achievable with softforks. +* Since OP_SUCCESSx precedes size check of initial stack and push opcodes, an OP_SUCCESSx-derived opcode requiring stack elements bigger than 520 bytes may uplift the limit in a softfork. +* OP_SUCCESSx may also redefine the behavior of existing opcodes so they could work together with the new opcode. For example, if an OP_SUCCESSx-derived opcode works with 64-bit integers, it may also allow the existing arithmetic opcodes in the ''same script'' to do the same. +* Given that OP_SUCCESSx even causes potentially unparseable scripts to pass, it can be used to introduce multi-byte opcodes, or even a completely new scripting language when prefixed with a specific OP_SUCCESSx opcode.. +## If any push opcode fails to decode because it would extend past the end of the tapscript, fail. +# If the size of any element in the '''initial stack''' as defined in bip-taproot (i.e., the witness stack after removing both the optional annex and the two last stack elements after that) is bigger than 520 bytes, fail. +# If the tapscript is bigger than 10000 bytes, fail. +# The tapscript is executed according to the rules in the following section, with the initial stack as input. +## If execution fails for any reason (including the 201 non-push opcode limit), fail. +## If the execution results in anything but exactly one element on the stack which evaluates to true with CastToBool(), fail. +# If this step is reached without encountering a failure, validation succeeds. + +===Script execution=== + +The execution rules for tapscript are based on those for P2WSH according to BIP141, including the OP_CHECKLOCKTIMEVERIFY and OP_CHECKSEQUENCEVERIFY opcodes defined in BIP65 and BIP112, but with the following modifications: +* '''Disabled script opcodes''' The following script opcodes are disabled in tapscript: OP_CHECKMULTISIG and OP_CHECKMULTISIGVERIFY. The disabled opcodes behave in the same way as OP_RETURN, by failing and terminating the script immediately when executed, and being ignored when found in unexecuted branch. While being ignored, they are still counted towards the 201 non-push opcodes limit. +* '''Consensus-enforced MINIMALIF''' The MINIMALIF rules, which are only a standardness rule in P2WSH, are consensus enforced in tapscript. This means that the input argument to the OP_IF and OP_NOTIF opcodes must be either exactly 0 (the empty vector) or exactly 1 (the one-byte vector with value 1)'''Why make MINIMALIF consensus?''' This makes it considerably easier to write non-malleable scripts that take branch information from the stack.. +* '''OP_SUCCESSx opcodes''' As listed above, some opcodes are renamed to OP_SUCCESSx, and make the script unconditionally valid. +* '''Signature opcodes'''. The OP_CHECKSIG and OP_CHECKSIGVERIFY are modified to operate on Schnorr signatures (see bip-schnorr) instead of ECDSA, and a new opcode OP_CHECKSIGADD is added. +** The opcode 186 (0xba) is named as OP_CHECKSIGADD. '''OP_CHECKSIGADD''' This opcode is added to compensate for the loss of OP_CHECKMULTISIG-like opcodes, which are incompatible with batch verification. OP_CHECKSIGADD is functionally equivalent to OP_ROT OP_SWAP OP_CHECKSIG OP_ADD, but is only counted as one opcode towards the 201 non-push opcodes limit. All CScriptNum-related behaviours of OP_ADD are also applicable to OP_CHECKSIGADD.'''Comparison of CHECKMULTISIG and CHECKSIG''' A CHECKMULTISIG script m ... n CHECKMULTISIG with witness 0 ... can be rewritten as script CHECKSIG ... CHECKSIGADD m NUMEQUAL with witness ... . Every witness element w_i is either a signature corresponding to the public key with the same index or an empty vector. A similar CHECKMULTISIGVERIFY script can be translated to bip-tapscript by replacing NUMEQUAL with NUMEQUALVERIFY. Alternatively, an m-of-n multisig policy can be implemented by splitting the script into several leaves of the Merkle tree, each implementing an m-of-m policy using CHECKSIGVERIFY ... CHECKSIGVERIFY CHECKSIG. If the setting allows the participants to interactively collaborate while signing, multisig policies can be realized with [https://eprint.iacr.org/2018/068 MuSig] for m-of-m and with [http://cacr.uwaterloo.ca/techreports/2001/corr2001-13.ps threshold signatures] using verifiable secret sharing for m-of-n. + +===Rules for signature opcodes=== + +The following rules apply to OP_CHECKSIG, OP_CHECKSIGVERIFY, and OP_CHECKSIGADD. + +* For OP_CHECKSIGVERIFY and OP_CHECKSIG, the public key (top element) and a signature (second to top element) are popped from the stack. +** If fewer than 2 elements are on the stack, the script MUST fail and terminate immediately. +* For OP_CHECKSIGADD, the public key (top element), a CScriptNum n (second to top element), and a signature (third to top element) are popped from the stack. +** If fewer than 3 elements are on the stack, the script MUST fail and terminate immediately. +** If n is larger than 4 bytes, the script MUST fail and terminate immediately. +* If the public key size is zero, the script MUST fail and terminate immediately. +* If the first byte of the public key is 0x04, 0x06, or 0x07, the script MUST fail and terminate immediately regardless of the public key size. +* If the first byte of the public key is 0x02 or 0x03, it is considered to be a public key as described in bip-schnorr: +** If the public key is not 33 bytes, the script MUST fail and terminate immediately. +** If the signature is not the empty vector, the signature is validated according to the bip-taproot signing validation rules against the public key and the tapscript transaction digest (to be defined hereinafter) as message. Validation failure MUST cause the script to fail and terminate immediately. +* If the first byte of the public key is not 0x02, 0x03, 0x04, 0x06, or 0x07, the public key is of an ''unknown public key type'''''Unknown public key types''' allow adding new signature validation rules through softforks. A softfork could add actual signature validation which either passes or makes the script fail and terminate immediately. This way, new SIGHASH modes can be added, as well as [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-December/016549.html NOINPUT-tagged public keys] and a public key constant which is replaced by the taproot internal key for signature validation. and no actual signature verification is applied. During script execution of signature opcodes they behave exactly as known public key types except that signature validation is considered to be successful. +* If the script did not fail and terminate before this step, regardless of the public key type: +** If the signature is the empty vector: +*** For OP_CHECKSIGVERIFY, the script MUST fail and terminate immediately. +*** For OP_CHECKSIG, an empty vector is pushed onto the stack, and execution continues with the next opcode. +*** For OP_CHECKSIGADD, a CScriptNum with value n is pushed onto the stack, and execution continues with the next opcode. +** If the signature is not the empty vector, the sigops_passed counter is incremented (see further) +*** For OP_CHECKSIGVERIFY, execution continues without any further changes to the stack. +*** For OP_CHECKSIG, a 1-byte value 0x01 is pushed onto the stack. +*** For OP_CHECKSIGADD, a CScriptNum with value of n + 1 is pushed onto the stack. + +These opcodes count toward the 201 non-push opcodes limit. + +===Transaction digest=== + +As the message for signature opcodes signature verification, transaction digest has the same definition as in bip-taproot, except the following: + +The one-byte spend_type has a different value, specificially at bit-2: +* Bit-0 is set if the scriptPubKey being spent is P2SH (opposed to "native segwit"). +* Bit-1 is set if an annex is present (the original witness stack has at least two witness elements, and the first byte of the last element is 0x50). +* Bit-2 is set. +* The other bits are unset. + +As additional pieces of data, added at the end of the input to the ''hashTapSighash'' function: +* tapleaf_hash (32): the tapleaf hash as defined in bip-taproot +* key_version (1): a constant value 0x02 representing the current version of public keys in the tapscript signature opcode execution. +* codeseparator_position (2): the opcode position of the last executed OP_CODESEPARATOR before the currently executed signature opcode, with the value in little endian (or 0xffff if none executed). The first opcode in a script has a position of 0. A multi-byte push opcode is counted as one opcode, regardless of the size of data being pushed. + +The total number of bytes hashed is at most ''244'''''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''212 - is_anyonecanpay * 50 - is_none * 32 - is_p2sh_spending * 12 + has_annex * 32''.. + +In summary, the semantics of the BIP143 sighash types remain unchanged, except the following: +# The exceptions mentioned in bip-taproot. +# The digest commits to taproot-specific data key_version.'''Why does the transaction digest commit to the key_version?''' This is for future extensions that define unknown public key types, making sure signatures can't be moved from one key type to another. This value is intended to be set equal to the first byte of the public key, after masking out flags like the oddness of the Y coordinate. +# The digest commits to the executed script through the tapleaf_hash which includes the leaf version and script instead of scriptCode. This implies that this commitment is unaffected by OP_CODESEPARATOR. +# The digest commits to the opcode position of the last executed OP_CODESEPARATOR.'''Why does the transaction digest commit to the position of the last executed OP_CODESEPARATOR?''' This allows continuing to use OP_CODESEPARATOR to sign the executed path of the script. Because the codeseparator_position is the last input to the digest, the SHA256 midstate can be efficiently cached for multiple OP_CODESEPARATORs in a single script. In contrast, the BIP143 handling of OP_CODESEPARATOR is to commit to the executed script only from the last executed OP_CODESEPARATOR onwards which requires unnecessary rehashing of the script. It should be noted that the one known OP_CODESEPARATOR use case of saving a second public key push in a script by sharing the first one between two code branches can be most likely expressed even cheaper by moving each branch into a separate taproot leaf. + +===Signature opcodes limitation=== + +In addition to the 201 non-push opcodes limit, the use of signature opcodes is subject to further limitations. + +* input_witness_weight is defined as the size of the serialized input witness associated to a particular transaction input. As defined in BIP141, a serialized input witness includes CCompactSize tags indicating the number of elements and size of each element, and contents of each element. input_witness_weight is the total size of the said CCompactSize tags and element contents. +* sigops_passed is defined as the total number of successfully executed signature opcodes, which have non-zero signature size and do not fail and terminate the script. For the avoidance of doubt, passing signature opcodes with unknown type public key and non-zero size signature are also counted towards sigops_passed. +* If 50 * (sigops_passed - 1) is greater than input_witness_weight, the script MUST fail and terminate immediately. + +This rule limits worst-case validation costs in tapscript similar to the ''sigops limit'' that only applies to legacy and P2WSH scripts'''The tapscript sigop limit''' The signature opcode limit protects against scripts which are slow to verify due to excessively many signature operations. In tapscript the number of signature opcodes does not count towards the BIP141 or legacy sigop limit. The old sigop limit makes transaction selection in block construction unnecessarily difficult because it is a second constraint in addition to weight. Instead, the number of tapscript signature opcodes is limited by witness weight. Additionally, the limit applies to the transaction input instead of the block and only actually executed signature opcodes are counted. Tapscript execution allows one signature opcode per 50 witness weight units plus one free signature opcode. The tapscript signature opcode limit allows to add new signature opcodes like CHECKSIGFROMSTACK to count towards the limit through a soft fork. Even if in the future new opcodes are introduced which change normal script cost there is need to stuff the witness with meaningless data. In that case the taproot annex can be used to add weight to the witness without increasing the actual witness size. +'''Parameter choice of the sigop limit''' Regular witnesses are unaffected by the limit as their weight is composed of public key and (SIGHASH_ALL) signature pairs with ''34 + 65'' weight units each (which includes a 1 weight unit CCompactSize tag). This is also the case if public keys are reused in the script because a signature's weight alone is 65 or 66 weight units. However, the limit increases the fees of abnormal scripts with duplicate signatures (and public keys) by requiring additional weight. The weight per sigop factor 50 corresponds to the ratio of BIP141 block limits: 4 mega weight units divided by 80,000 sigops. The "free" signature opcode permitted by the limit exists to account for the weight of the non-witness parts of the transaction input.. + +==Rationale== + + + +==Examples== + +==Acknowledgements== + +This document is the result of many discussions and contains contributions by Jonas Nick, Anthony Towns, and others. + -- cgit v1.2.3 From eb96be7a9dd0c20432744fcf711337c60b7a3f39 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Mon, 14 Jan 2019 15:54:24 +0000 Subject: Clarify what 'reduced' means in tests and use word 'message' instead of 'message hash' --- bip-schnorr/test-vectors.csv | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bip-schnorr/test-vectors.csv b/bip-schnorr/test-vectors.csv index 9b89a7b..a4218f7 100644 --- a/bip-schnorr/test-vectors.csv +++ b/bip-schnorr/test-vectors.csv @@ -4,10 +4,10 @@ index,secret key,public key,message,signature,verification result,comment 3,C90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B14E5C7,03FAC2114C2FBB091527EB7C64ECB11F8021CB45E8E7809D3C0938E4B8C0E5F84B,5E2D58D8B3BCDF1ABADEC7829054F90DDA9805AAB56C77333024B9D0A508B75C,00DA9B08172A9B6F0466A2DEFD817F2D7AB437E0D253CB5395A963866B3574BE00880371D01766935B92D2AB4CD5C8A2A5837EC57FED7660773A05F0DE142380,TRUE, 4,,03DEFDEA4CDB677750A420FEE807EACF21EB9898AE79B9768766E4FAA04A2D4A34,4DF3C3F68FCC83B27E9D42C90431A72499F17875C81A599B566C9889B9696703,00000000000000000000003B78CE563F89A0ED9414F5AA28AD0D96D6795F9C6302A8DC32E64E86A333F20EF56EAC9BA30B7246D6D25E22ADB8C6BE1AEB08D49D,TRUE, 5,,031B84C5567B126440995D3ED5AABA0565D71E1834604819FF9C17F5E9D5DD078F,0000000000000000000000000000000000000000000000000000000000000000,52818579ACA59767E3291D91B76B637BEF062083284992F2D95F564CA6CB4E3530B1DA849C8E8304ADC0CFE870660334B3CFC18E825EF1DB34CFAE3DFC5D8187,TRUE,"test fails if jacobi symbol of x(R) instead of y(R) is used" -6,,03FAC2114C2FBB091527EB7C64ECB11F8021CB45E8E7809D3C0938E4B8C0E5F84B,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,570DD4CA83D4E6317B8EE6BAE83467A1BF419D0767122DE409394414B05080DCE9EE5F237CBD108EABAE1E37759AE47F8E4203DA3532EB28DB860F33D62D49BD,TRUE,"test fails if msg is reduced" +6,,03FAC2114C2FBB091527EB7C64ECB11F8021CB45E8E7809D3C0938E4B8C0E5F84B,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,570DD4CA83D4E6317B8EE6BAE83467A1BF419D0767122DE409394414B05080DCE9EE5F237CBD108EABAE1E37759AE47F8E4203DA3532EB28DB860F33D62D49BD,TRUE,"test fails if msg is reduced modulo p or n" 7,,03EEFDEA4CDB677750A420FEE807EACF21EB9898AE79B9768766E4FAA04A2D4A34,4DF3C3F68FCC83B27E9D42C90431A72499F17875C81A599B566C9889B9696703,00000000000000000000003B78CE563F89A0ED9414F5AA28AD0D96D6795F9C6302A8DC32E64E86A333F20EF56EAC9BA30B7246D6D25E22ADB8C6BE1AEB08D49D,FALSE,"public key not on the curve" 8,,02DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,2A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1DFA16AEE06609280A19B67A24E1977E4697712B5FD2943914ECD5F730901B4AB7,FALSE,"incorrect R residuosity" -9,,03FAC2114C2FBB091527EB7C64ECB11F8021CB45E8E7809D3C0938E4B8C0E5F84B,5E2D58D8B3BCDF1ABADEC7829054F90DDA9805AAB56C77333024B9D0A508B75C, 00DA9B08172A9B6F0466A2DEFD817F2D7AB437E0D253CB5395A963866B3574BED092F9D860F1776A1F7412AD8A1EB50DACCC222BC8C0E26B2056DF2F273EFDEC,FALSE,"negated message hash" +9,,03FAC2114C2FBB091527EB7C64ECB11F8021CB45E8E7809D3C0938E4B8C0E5F84B,5E2D58D8B3BCDF1ABADEC7829054F90DDA9805AAB56C77333024B9D0A508B75C, 00DA9B08172A9B6F0466A2DEFD817F2D7AB437E0D253CB5395A963866B3574BED092F9D860F1776A1F7412AD8A1EB50DACCC222BC8C0E26B2056DF2F273EFDEC,FALSE,"negated message" 10,,0279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798,0000000000000000000000000000000000000000000000000000000000000000,787A848E71043D280C50470E8E1532B2DD5D20EE912A45DBDD2BD1DFBF187EF68FCE5677CE7A623CB20011225797CE7A8DE1DC6CCD4F754A47DA6C600E59543C,FALSE,"negated s value" 11,,03DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,2A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1D1E51A22CCEC35599B8F266912281F8365FFC2D035A230434A1A64DC59F7013FD,FALSE,"negated public key" 12,,02DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,00000000000000000000000000000000000000000000000000000000000000009E9D01AF988B5CEDCE47221BFA9B222721F3FA408915444A4B489021DB55775F,FALSE,"sG - eP is infinite. Test fails in single verification if jacobi(y(inf)) is defined as 1 and x(inf) as 0" -- cgit v1.2.3 From b65cd694676096dd31ea790485a2019ca653b34f Mon Sep 17 00:00:00 2001 From: Mark B Lundeberg <36528214+markblundeberg@users.noreply.github.com> Date: Mon, 6 May 2019 13:13:20 -0700 Subject: remove duplicate warning Though perhaps, the emphasis is warranted given its importance. :-) --- bip-schnorr.mediawiki | 3 --- 1 file changed, 3 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index d4e4ff1..f3df71e 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -161,9 +161,6 @@ To sign ''m'' for public key ''dG'': '''Above deterministic derivation of ''R'' is designed specifically for this signing algorithm and may not be secure when used in other signature schemes.''' For example, using the same derivation in the MuSig multi-signature scheme leaks the secret key (see the [https://eprint.iacr.org/2018/068 MuSig paper] for details). -'''Above deterministic derivation of ''R'' is designed specifically for this signing algorithm and may not be secure when used in other signature schemes.''' -For example, using the same derivation in the MuSig multi-signature scheme leaks the secret key (see the [https://eprint.iacr.org/2018/068 MuSig paper] for details). - Note that this is not a ''unique signature'' scheme: while this algorithm will always produce the same signature for a given message and public key, ''k'' (and hence ''R'') may be generated in other ways (such as by a CSPRNG) producing a different, but still valid, signature. === Optimizations === -- cgit v1.2.3 From 953dd236650a02aa964049f138513b158463bea4 Mon Sep 17 00:00:00 2001 From: Dmitry Petukhov Date: Fri, 10 May 2019 03:09:54 +0500 Subject: taproot_output_script: first returned byte should be OP_1 (0x51) If we look at def IsPayToTaproot(script): return len(script) == 35 and script[0] == OP_1 and script[1] == 33 and script[2] >= 0 and script[2] <= 1 First byte is is checked for OP_1. OP_1 is 0x51 But the example code in this BIP returns `bytes([0x01, 0x21, output_pubkey[0] & 1]) + output_pubkey[1:]` First byte 0x01, but it should be 0x51 --- bip-taproot.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 2e8b43b..0b6c04a 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -203,7 +203,7 @@ def taproot_output_script(internal_pubkey, script_tree): t = tagged_hash("TapTweak", internal_pubkey.get_bytes() + h) assert int.from_bytes(t, 'big') < SECP256K1_ORDER output_pubkey = internal_pubkey.tweak_add(t).get_bytes() - return bytes([0x01, 0x21, output_pubkey[0] & 1]) + output_pubkey[1:] + return bytes([0x51, 0x21, output_pubkey[0] & 1]) + output_pubkey[1:] The function taproot_output_script returns a byte array with the scriptPubKey. It can be P2SH wrapped if desired (see BIP141). -- cgit v1.2.3 From b2e6d11a6e1bbae2bccd17bd6abd0564d19ae549 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Fri, 10 May 2019 13:57:12 +0000 Subject: Clarify diagram --- bip-taproot.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 0b6c04a..f100e6e 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -208,7 +208,7 @@ def taproot_output_script(internal_pubkey, script_tree): The function taproot_output_script returns a byte array with the scriptPubKey. It can be P2SH wrapped if desired (see BIP141). -[[File:bip-taproot/tree.png|frame|This diagram shows the hashing structure to obtain the tweak from an internal key ''P'' and a Merkle tree consisting of 3 script leaves.]] +[[File:bip-taproot/tree.png|frame|This diagram shows the hashing structure to obtain the tweak from an internal key ''P'' and a Merkle tree consisting of 5 script leaves. ''A'', ''B'', ''C'' and ''E'' are ''TapLeaf'' hashes similar to ''D'' and ''AB'' is a ''TapBranch'' hash. Note that when ''CDE'' is computed ''E'' is hashed first because ''E'' is less than ''CD''.]] '''Spending using the internal key''' A Taproot output can be spent with the private key corresponding to the internal_pubkey. To do so, a witness stack consisting of a single element, a bip-schnorr signature on the signature hash as defined above, with the private key tweaked by the same t in the above snippet. See the code below: -- cgit v1.2.3 From 1a4b08ab72690caedae8b5398dde0fedd0a48856 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Sat, 6 Jul 2019 14:11:52 +0000 Subject: Fix point_from_bytes in bip-schnorr reference implementation --- bip-schnorr/reference.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-schnorr/reference.py b/bip-schnorr/reference.py index 48a36a6..d3efb52 100644 --- a/bip-schnorr/reference.py +++ b/bip-schnorr/reference.py @@ -34,7 +34,7 @@ def bytes_from_point(P): return (b'\x03' if P[1] & 1 else b'\x02') + bytes_from_int(P[0]) def point_from_bytes(b): - if b[0] in [b'\x02', b'\x03']: + if b[0:1] in [b'\x02', b'\x03']: odd = b[0] - 0x02 else: return None -- cgit v1.2.3 From e084aafb8b6ebacbce559cc55151a392ef653788 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Sat, 6 Jul 2019 16:32:41 +0000 Subject: Switch to 32 byte public keys in bip-schnorr --- bip-schnorr.mediawiki | 53 +++++++---- bip-schnorr/reference.py | 44 +++++---- bip-schnorr/test-vectors.csv | 30 +++--- bip-schnorr/test-vectors.py | 215 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 288 insertions(+), 54 deletions(-) create mode 100644 bip-schnorr/test-vectors.py diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index f3df71e..fa8faa5 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -35,6 +35,7 @@ propose a new standard, a number of improvements not specific to Schnorr signatu made: * '''Signature encoding''': Instead of [https://en.wikipedia.org/wiki/X.690#DER_encoding DER]-encoding for signatures (which are variable size, and up to 72 bytes), we can use a simple fixed 64-byte format. +* '''Public key encoding''': Instead of ''compressed'' 33-byte encoding of elliptic curve points which are common in Bitcoin, public keys in this proposal are encoded as 32 bytes. * '''Batch verification''': The specific formulation of ECDSA signatures that is standardized cannot be verified more efficiently in batch compared to individually, unless additional witness data is added. Changing the signature scheme offers an opportunity to avoid this. [[File:bip-schnorr/speedup-batch.png|frame|This graph shows the ratio between the time it takes to verify ''n'' signatures individually and to verify a batch of ''n'' signatures. This ratio goes up logarithmically with the number of signatures, or in other words: the total time to verify ''n'' signatures grows with ''O(n / log n)''.]] @@ -57,24 +58,35 @@ We choose the ''R''-option to support batch verification. '''Key prefixing''' When using the verification rule above directly, it is possible for a third party to convert a signature ''(R,s)'' for key ''P'' into a signature ''(R,s + aH(R || m))'' for key ''P + aG'' and the same message, for any integer ''a''. This is not a concern for Bitcoin currently, as all signature hashes indirectly commit to the public keys. However, this may change with proposals such as SIGHASH_NOINPUT ([https://github.com/bitcoin/bips/blob/master/bip-0118.mediawiki BIP 118]), or when the signature scheme is used for other purposes—especially in combination with schemes like [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki BIP32]'s unhardened derivation. To combat this, we choose ''key prefixed''A limitation of committing to the public key (rather than to a short hash of it, or not at all) is that it removes the ability for public key recovery or verifying signatures against a short public key hash. These constructions are generally incompatible with batch verification. Schnorr signatures; changing the equation to ''sG = R + H(R || P || m)P''. -'''Encoding the sign of R''' As we chose the ''R''-option above, we're required to encode the point ''R'' into the signature. Several possibilities exist: +'''Encoding the sign of P and the sign of R''' There exist several possibilities for encoding the sign of the public key point: +# Encoding the full X and Y coordinate of P, resulting in a 64-byte public key. +# Encoding the full X coordinate, but only whether Y is even or odd (like compressed public keys). This would result in 33-byte public keys. +# Encoding only the X coordinate, resulting in 32-byte public keys. + +As we chose the ''R''-option above, we're required to encode the point ''R'' into the signature. The possibilities are similar to the encoding of ''P'': # Encoding the full X and Y coordinate of R, resulting in a 96-byte signature. # Encoding the full X coordinate, but only whether Y is even or odd (like compressed public keys). This would result in 65-byte signatures. # Encoding only the X coordinate, leaving us with 64-byte signature. -Using the first option would be slightly more efficient for verification (around 5%), but we prioritize compactness, and therefore choose option 3. +Using the first option for both ''P'' and ''R'' would be slightly more efficient for verification (around 5%), but we prioritize compactness, and therefore choose option 3. -'''Implicit Y coordinate''' In order to support batch verification, the Y coordinate of ''R'' cannot be ambiguous (every valid X coordinate has two possible Y coordinates). We have a choice between several options for symmetry breaking: +'''Implicit Y coordinates''' In order to support batch verification, the Y coordinate of ''P'' and of ''R'' cannot be ambiguous (every valid X coordinate has two possible Y coordinates). We have a choice between several options for symmetry breaking: # Implicitly choosing the Y coordinate that is in the lower half. # Implicitly choosing the Y coordinate that is evenSince ''p'' is odd, negation modulo ''p'' will map even numbers to odd numbers and the other way around. This means that for a valid X coordinate, one of the corresponding Y coordinates will be even, and the other will be odd.. # Implicitly choosing the Y coordinate that is a quadratic residue (has a square root modulo the field size)A product of two numbers is a quadratic residue when either both or none of the factors are quadratic residues. As ''-1'' is not a quadratic residue, and the two Y coordinates corresponding to a given X coordinate are each other's negation, this means exactly one of the two must be a quadratic residue.. -The third option is slower at signing time but a bit faster to verify, as the quadratic residue of the Y coordinate can be computed directly for points represented in +In the case of ''R'' the third option is slower at signing time but a bit faster to verify, as the quadratic residue of the Y coordinate can be computed directly for points represented in [https://en.wikibooks.org/wiki/Cryptography/Prime_Curve/Jacobian_Coordinates Jacobian coordinates] (a common optimization to avoid modular inverses for elliptic curve operations). The two other options require a possibly expensive conversion to affine coordinates first. This would even be the case if the sign or oddness were explicitly coded (option 2 in the previous design choice). We therefore choose option 3. -'''Final scheme''' As a result, our final scheme ends up using signatures ''(r,s)'' where ''r'' is the X coordinate of a point ''R'' on the curve whose Y coordinate is a quadratic residue, and which satisfies ''sG = R + H(r || P || m)P''. +For ''P'' the speed of signing and verification is not significantly different between any of the three options because affine coordinates of the point have to computed anyway. We therefore choose the same option as for ''R''. The signing algorithm ensures that the signature is valid under the correct public key by negating the secret key if necessary. + +It is important to not mix up the 32 byte public key format and other existing public key formats. Concretely, a verifier should only accept 32 byte public keys and not, for example, convert a 33 byte public key by throwing away the first byte. Otherwise, two public keys would be valid for a single signature which can result in subtle malleability issues. + +Implicit Y coordinates are not a reduction in security when expressed as the number of elliptic curve operations an attacker is expected to perform to compute the secret key. An attacker can normalize any given public key to a point whose Y coordinate is a quadratic residue by negating the point if necessary. This is just a subtraction of field elements and not an elliptic curve operation. + +'''Final scheme''' As a result, our final scheme ends up using public keys ''p'' where ''p'' is the X coordinate of a point ''P'' on the curve whose Y coordinate is a quadratic residue and signatures ''(r,s)'' where ''r'' is the X coordinate of a point ''R'' whose Y coordinate is a quadratic residue. The signature satisfies ''sG = R + H(r || p || m)P''. === Specification === @@ -94,26 +106,27 @@ The following convention is used, with constants as defined for secp256k1: ** ''||'' refers to byte array concatenation. ** The function ''x[i:j]'', where ''x'' is a byte array, returns a ''(j - i)''-byte array with a copy of the ''i''-th byte (inclusive) to the ''j''-th byte (exclusive) of ''x''. ** The function ''bytes(x)'', where ''x'' is an integer, returns the 32-byte encoding of ''x'', most significant byte first. -** The function ''bytes(P)'', where ''P'' is a point, returns ''bytes(0x02 + (y(P) & 1)) || bytes(x(P))''This matches the ''compressed'' encoding for elliptic curve points used in Bitcoin already, following section 2.3.3 of the [http://www.secg.org/sec1-v2.pdf SEC 1] standard.. +** The function ''bytes(P)'', where ''P'' is a point, returns ''bytes(x(P))'. ** The function ''int(x)'', where ''x'' is a 32-byte array, returns the 256-bit unsigned integer whose most significant byte encoding is ''x''. ** The function ''lift_x(x)'', where ''x'' is an integer in range ''0..p-1'', returns the point ''P'' for which ''x(P) = x'' and ''y(P)'' is a quadratic residue modulo ''p'', or fails if no such point existsGiven an candidate X coordinate ''x'' in the range ''0..p-1'', there exist either exactly two or exactly zero valid Y coordinates. If no valid Y coordinate exists, then ''x'' is not a valid X coordinate either, i.e., no point ''P'' exists for which ''x(P) = x''. Given a candidate ''x'', the valid Y coordinates are the square roots of ''c = x3 + 7 mod p'' and they can be computed as ''y = ±c(p+1)/4 mod p'' (see [https://en.wikipedia.org/wiki/Quadratic_residue#Prime_or_prime_power_modulus Quadratic residue]) if they exist, which can be checked by squaring and comparing with ''c''. Due to [https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion] it then holds that ''c(p-1)/2 = 1 mod p''. The same criterion applied to ''y'' results in ''y(p-1)/2 mod p = ±c((p+1)/4)((p-1)/2) mod p = ±1 mod p''. Therefore ''y = +c(p+1)/4 mod p'' is a quadratic residue and ''-y mod p'' is not.. The function ''lift_x(x)'' is equivalent to the following pseudocode: *** Let ''y = c(p+1)/4 mod p''. *** Fail if ''c ≠ y2 mod p''. *** Return ''(r, y)''. -** The function ''point(x)'', where ''x'' is a 33-byte array, returns the point ''P'' for which ''x(P) = int(x[1:33])'' and ''y(P) & 1 = int(x[0:1]) - 0x02)'', or fails if no such point exists. The function ''point(x)'' is equivalent to the following pseudocode: -*** Fail if (''x[0:1] ≠ 0x02'' and ''x[0:1] ≠ 0x03''). -*** Set flag ''odd'' if ''x[0:1] = 0x03''. -*** Let ''(r, y) = lift_x(x)''; fail if ''lift_x(x)'' fails. -*** If (flag ''odd'' is set and ''y'' is an even integer) or (flag ''odd'' is not set and ''y'' is an odd integer): -**** Let ''y = p - y''. -*** Return ''(r, y)''. +** The function ''point(x)'', where ''x'' is a 32-byte array, returns the point ''P = lift_x(int(x))''. ** The function ''hash(x)'', where ''x'' is a byte array, returns the 32-byte SHA256 hash of ''x''. ** The function ''jacobi(x)'', where ''x'' is an integer, returns the [https://en.wikipedia.org/wiki/Jacobi_symbol Jacobi symbol] of ''x / p''. It is equal to ''x(p-1)/2 mod p'' ([https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion])For points ''P'' on the secp256k1 curve it holds that ''jacobi(y(P)) ≠ 0''.. +=== Public Key Generation === + +Input: +* The secret key ''d'': an integer in the range ''1..n-1'' chosen uniformly at random. + +The public key corresponding to secret key ''d'' is ''bytes(dG)''. + ==== Verification ==== Input: -* The public key ''pk'': a 33-byte array +* The public key ''pk'': a 32-byte array * The message ''m'': a 32-byte array * A signature ''sig'': a 64-byte array @@ -130,7 +143,7 @@ The signature is valid if and only if the algorithm below does not fail. Input: * The number ''u'' of signatures -* The public keys ''pk1..u'': ''u'' 33-byte arrays +* The public keys ''pk1..u'': ''u'' 32-byte arrays * The messages ''m1..u'': ''u'' 32-byte arrays * The signatures ''sig1..u'': ''u'' 64-byte arrays @@ -147,16 +160,18 @@ All provided signatures are valid with overwhelming probability if and only if t ==== Signing ==== Input: -* The secret key ''d'': an integer in the range ''1..n-1''. +* The secret key ''d' '': an integer in the range ''1..n-1'' chosen uniformly at random. * The message ''m'': a 32-byte array -To sign ''m'' for public key ''dG'': +To sign ''m'' for public key ''bytes(dG)'': +* Let ''P = dG'' +* Let ''d = d' '' if ''jacobi(y(P)) = 1'', otherwise let ''d = n - d' ''. * Let ''k' = int(hash(bytes(d) || m)) mod n''Note that in general, taking the output of a hash function modulo the curve order will produce an unacceptably biased result. However, for the secp256k1 curve, the order is sufficiently close to ''2256'' that this bias is not observable (''1 - n / 2256'' is around ''1.27 * 2-128'').. * Fail if ''k' = 0''. * Let ''R = k'G''. * Let ''k = k' '' if ''jacobi(y(R)) = 1'', otherwise let ''k = n - k' ''. -* Let ''e = int(hash(bytes(x(R)) || bytes(dG) || m)) mod n''. -* The signature is ''bytes(x(R)) || bytes((k + ed) mod n)''. +* Let ''e = int(hash(bytes(R) || bytes(P) || m)) mod n''. +* The signature is ''bytes(R) || bytes((k + ed) mod n)''. '''Above deterministic derivation of ''R'' is designed specifically for this signing algorithm and may not be secure when used in other signature schemes.''' For example, using the same derivation in the MuSig multi-signature scheme leaks the secret key (see the [https://eprint.iacr.org/2018/068 MuSig paper] for details). diff --git a/bip-schnorr/reference.py b/bip-schnorr/reference.py index d3efb52..f89b3c4 100644 --- a/bip-schnorr/reference.py +++ b/bip-schnorr/reference.py @@ -31,19 +31,14 @@ def bytes_from_int(x): return x.to_bytes(32, byteorder="big") def bytes_from_point(P): - return (b'\x03' if P[1] & 1 else b'\x02') + bytes_from_int(P[0]) + return bytes_from_int(P[0]) def point_from_bytes(b): - if b[0:1] in [b'\x02', b'\x03']: - odd = b[0] - 0x02 - else: - return None - x = int_from_bytes(b[1:33]) + x = int_from_bytes(b) y_sq = (pow(x, 3, p) + 7) % p - y0 = pow(y_sq, (p + 1) // 4, p) - if pow(y0, 2, p) != y_sq: + y = pow(y_sq, (p + 1) // 4, p) + if pow(y, 2, p) != y_sq: return None - y = p - y0 if y0 & 1 != odd else y0 return [x, y] def int_from_bytes(b): @@ -55,24 +50,30 @@ def hash_sha256(b): def jacobi(x): return pow(x, (p - 1) // 2, p) -def schnorr_sign(msg, seckey): +def pubkey_gen(seckey): + P = point_mul(G, seckey) + return bytes_from_point(P) + +def schnorr_sign(msg, seckey0): if len(msg) != 32: raise ValueError('The message must be a 32-byte array.') - if not (1 <= seckey <= n - 1): + if not (1 <= seckey0 <= n - 1): raise ValueError('The secret key must be an integer in the range 1..n-1.') + P = point_mul(G, seckey0) + seckey = seckey0 if (jacobi(P[1]) == 1) else n - seckey0 k0 = int_from_bytes(hash_sha256(bytes_from_int(seckey) + msg)) % n if k0 == 0: raise RuntimeError('Failure. This happens only with negligible probability.') R = point_mul(G, k0) k = n - k0 if (jacobi(R[1]) != 1) else k0 - e = int_from_bytes(hash_sha256(bytes_from_int(R[0]) + bytes_from_point(point_mul(G, seckey)) + msg)) % n - return bytes_from_int(R[0]) + bytes_from_int((k + e * seckey) % n) + e = int_from_bytes(hash_sha256(bytes_from_point(R) + bytes_from_point(P) + msg)) % n + return bytes_from_point(R) + bytes_from_int((k + e * seckey) % n) def schnorr_verify(msg, pubkey, sig): if len(msg) != 32: raise ValueError('The message must be a 32-byte array.') - if len(pubkey) != 33: - raise ValueError('The public key must be a 33-byte array.') + if len(pubkey) != 32: + raise ValueError('The public key must be a 32-byte array.') if len(sig) != 64: raise ValueError('The signature must be a 64-byte array.') P = point_from_bytes(pubkey) @@ -82,7 +83,7 @@ def schnorr_verify(msg, pubkey, sig): s = int_from_bytes(sig[32:64]) if (r >= p or s >= n): return False - e = int_from_bytes(hash_sha256(sig[0:32] + bytes_from_point(P) + msg)) % n + e = int_from_bytes(hash_sha256(sig[0:32] + pubkey + msg)) % n R = point_add(point_mul(G, s), point_mul(P, n - e)) if R is None or jacobi(R[1]) != 1 or R[0] != r: return False @@ -107,20 +108,25 @@ def test_vectors(): print('\nTest vector #%-3i: ' % int(index)) if seckey != '': seckey = int(seckey, 16) + pubkey_actual = pubkey_gen(seckey) + if pubkey != pubkey_actual: + print(' * Failed key generation.') + print(' Expected key:', pubkey.hex().upper()) + print(' Actual key:', pubkey_actual.hex().upper()) sig_actual = schnorr_sign(msg, seckey) if sig == sig_actual: print(' * Passed signing test.') else: print(' * Failed signing test.') - print(' Excepted signature:', sig.hex()) - print(' Actual signature:', sig_actual.hex()) + print(' Expected signature:', sig.hex().upper()) + print(' Actual signature:', sig_actual.hex().upper()) all_passed = False result_actual = schnorr_verify(msg, pubkey, sig) if result == result_actual: print(' * Passed verification test.') else: print(' * Failed verification test.') - print(' Excepted verification result:', result) + print(' Expected verification result:', result) print(' Actual verification result:', result_actual) if comment: print(' Comment:', comment) diff --git a/bip-schnorr/test-vectors.csv b/bip-schnorr/test-vectors.csv index a4218f7..3e17669 100644 --- a/bip-schnorr/test-vectors.csv +++ b/bip-schnorr/test-vectors.csv @@ -1,17 +1,15 @@ index,secret key,public key,message,signature,verification result,comment -1,0000000000000000000000000000000000000000000000000000000000000001,0279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798,0000000000000000000000000000000000000000000000000000000000000000,787A848E71043D280C50470E8E1532B2DD5D20EE912A45DBDD2BD1DFBF187EF67031A98831859DC34DFFEEDDA86831842CCD0079E1F92AF177F7F22CC1DCED05,TRUE, -2,B7E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEF,02DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,2A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1D1E51A22CCEC35599B8F266912281F8365FFC2D035A230434A1A64DC59F7013FD,TRUE, -3,C90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B14E5C7,03FAC2114C2FBB091527EB7C64ECB11F8021CB45E8E7809D3C0938E4B8C0E5F84B,5E2D58D8B3BCDF1ABADEC7829054F90DDA9805AAB56C77333024B9D0A508B75C,00DA9B08172A9B6F0466A2DEFD817F2D7AB437E0D253CB5395A963866B3574BE00880371D01766935B92D2AB4CD5C8A2A5837EC57FED7660773A05F0DE142380,TRUE, -4,,03DEFDEA4CDB677750A420FEE807EACF21EB9898AE79B9768766E4FAA04A2D4A34,4DF3C3F68FCC83B27E9D42C90431A72499F17875C81A599B566C9889B9696703,00000000000000000000003B78CE563F89A0ED9414F5AA28AD0D96D6795F9C6302A8DC32E64E86A333F20EF56EAC9BA30B7246D6D25E22ADB8C6BE1AEB08D49D,TRUE, -5,,031B84C5567B126440995D3ED5AABA0565D71E1834604819FF9C17F5E9D5DD078F,0000000000000000000000000000000000000000000000000000000000000000,52818579ACA59767E3291D91B76B637BEF062083284992F2D95F564CA6CB4E3530B1DA849C8E8304ADC0CFE870660334B3CFC18E825EF1DB34CFAE3DFC5D8187,TRUE,"test fails if jacobi symbol of x(R) instead of y(R) is used" -6,,03FAC2114C2FBB091527EB7C64ECB11F8021CB45E8E7809D3C0938E4B8C0E5F84B,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,570DD4CA83D4E6317B8EE6BAE83467A1BF419D0767122DE409394414B05080DCE9EE5F237CBD108EABAE1E37759AE47F8E4203DA3532EB28DB860F33D62D49BD,TRUE,"test fails if msg is reduced modulo p or n" -7,,03EEFDEA4CDB677750A420FEE807EACF21EB9898AE79B9768766E4FAA04A2D4A34,4DF3C3F68FCC83B27E9D42C90431A72499F17875C81A599B566C9889B9696703,00000000000000000000003B78CE563F89A0ED9414F5AA28AD0D96D6795F9C6302A8DC32E64E86A333F20EF56EAC9BA30B7246D6D25E22ADB8C6BE1AEB08D49D,FALSE,"public key not on the curve" -8,,02DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,2A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1DFA16AEE06609280A19B67A24E1977E4697712B5FD2943914ECD5F730901B4AB7,FALSE,"incorrect R residuosity" -9,,03FAC2114C2FBB091527EB7C64ECB11F8021CB45E8E7809D3C0938E4B8C0E5F84B,5E2D58D8B3BCDF1ABADEC7829054F90DDA9805AAB56C77333024B9D0A508B75C, 00DA9B08172A9B6F0466A2DEFD817F2D7AB437E0D253CB5395A963866B3574BED092F9D860F1776A1F7412AD8A1EB50DACCC222BC8C0E26B2056DF2F273EFDEC,FALSE,"negated message" -10,,0279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798,0000000000000000000000000000000000000000000000000000000000000000,787A848E71043D280C50470E8E1532B2DD5D20EE912A45DBDD2BD1DFBF187EF68FCE5677CE7A623CB20011225797CE7A8DE1DC6CCD4F754A47DA6C600E59543C,FALSE,"negated s value" -11,,03DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,2A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1D1E51A22CCEC35599B8F266912281F8365FFC2D035A230434A1A64DC59F7013FD,FALSE,"negated public key" -12,,02DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,00000000000000000000000000000000000000000000000000000000000000009E9D01AF988B5CEDCE47221BFA9B222721F3FA408915444A4B489021DB55775F,FALSE,"sG - eP is infinite. Test fails in single verification if jacobi(y(inf)) is defined as 1 and x(inf) as 0" -13,,02DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,0000000000000000000000000000000000000000000000000000000000000001D37DDF0254351836D84B1BD6A795FD5D523048F298C4214D187FE4892947F728,FALSE,"sG - eP is infinite. Test fails in single verification if jacobi(y(inf)) is defined as 1 and x(inf) as 1" -14,,02DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,4A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1D1E51A22CCEC35599B8F266912281F8365FFC2D035A230434A1A64DC59F7013FD,FALSE,"sig[0:32] is not an X coordinate on the curve" -15,,02DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC2F1E51A22CCEC35599B8F266912281F8365FFC2D035A230434A1A64DC59F7013FD,FALSE,"sig[0:32] is equal to field size" -16,,02DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,2A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141,FALSE,"sig[32:64] is equal to curve order" +0,0000000000000000000000000000000000000000000000000000000000000001,79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798,0000000000000000000000000000000000000000000000000000000000000000,787A848E71043D280C50470E8E1532B2DD5D20EE912A45DBDD2BD1DFBF187EF6166FCCEE14F021B31AF22A90D0639CC010C2B764C304A8FFF266ABBC01A0A880,TRUE, +1,B7E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEF,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,3C4D3ADB1F05C3E948216ECB6007D1534D97D35D5589EDB226AD0370C0293C780AEA9BA361509DA2FDF7BC6E5E38926E40B6ACCD24EA9E06B9DA8244A1D0B691,TRUE, +2,C90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B14E5C7,FAC2114C2FBB091527EB7C64ECB11F8021CB45E8E7809D3C0938E4B8C0E5F84B,5E2D58D8B3BCDF1ABADEC7829054F90DDA9805AAB56C77333024B9D0A508B75C,33380A613013115518CD6030ABC8220B2DED273FD3ABD13DF0882DC6A928E5AFAC72DF3248F8FAC522EF1A819EE5EE5BEA81D92D0E19A6FAB228E5D1D61BF833,TRUE, +3,0B432B2677937381AEF05BB02A66ECD012773062CF3FA2549E44F58ED2401710,25D1DFF95105F5253C4022F628A996AD3A0D95FBF21D468A1B33F8C160D8F517,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,7C4E8B0C2575A77A01AF41EE6678EF9C41F97CC4D15FF6D6CA45D73BC6FF7FF4919D246589AF2FA6306F4B7A392857E9C4A17CB21DBE72C38A48C99979EEDCB8,TRUE,test fails if msg is reduced modulo p or n +4,,D69C3509BB99E412E68B0FE8544E72837DFA30746D8BE2AA65975F29D22DC7B9,4DF3C3F68FCC83B27E9D42C90431A72499F17875C81A599B566C9889B9696703,00000000000000000000003B78CE563F89A0ED9414F5AA28AD0D96D6795F9C63F84A709CFFD89AD94FCBD808D41BD26BF62F263AA253527134DDC4A4715BF491,TRUE, +5,,EEFDEA4CDB677750A420FEE807EACF21EB9898AE79B9768766E4FAA04A2D4A34,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,3C4D3ADB1F05C3E948216ECB6007D1534D97D35D5589EDB226AD0370C0293C780AEA9BA361509DA2FDF7BC6E5E38926E40B6ACCD24EA9E06B9DA8244A1D0B691,FALSE,public key not on the curve +6,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F98631F4EF21D5F231A1000ED069E0348ED057EDF4FB1B6672009EDE9DBB2DEE14,FALSE,incorrect R residuosity +7,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,07636CBE3092D11AFCA4DD1D32E50F039EB5FF5FB2AB72A7DC2BA0F3A4E7ED418C312ED6ABF6A41446D28789DF4AA43A15E166F001D072536ADC6E49C21DC419,FALSE,negated message +8,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,3C4D3ADB1F05C3E948216ECB6007D1534D97D35D5589EDB226AD0370C0293C78F515645C9EAF625D02084391A1C76D9079F830198A5E023505F7DC482E658AB0,FALSE,negated s value +9,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,0000000000000000000000000000000000000000000000000000000000000000221A96FEEBA7AD29F11B675DB394948A83A220FD8FE181A7667BDBEE178011B1,FALSE,sG - eP is infinite. Test fails in single verification if jacobi(y(inf)) is defined as 1 and x(inf) as 0 +10,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,00000000000000000000000000000000000000000000000000000000000000011A39648F31350D8E591106B43B9EB364F8617BCD52DC96A3FA8C4E50347F31DE,FALSE,sG - eP is infinite. Test fails in single verification if jacobi(y(inf)) is defined as 1 and x(inf) as 1 +11,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,4A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1D0AEA9BA361509DA2FDF7BC6E5E38926E40B6ACCD24EA9E06B9DA8244A1D0B691,FALSE,sig[0:32] is not an X coordinate on the curve +12,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F0AEA9BA361509DA2FDF7BC6E5E38926E40B6ACCD24EA9E06B9DA8244A1D0B691,FALSE,sig[0:32] is equal to field size +13,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,3C4D3ADB1F05C3E948216ECB6007D1534D97D35D5589EDB226AD0370C0293C78FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141,FALSE,sig[32:64] is equal to curve order diff --git a/bip-schnorr/test-vectors.py b/bip-schnorr/test-vectors.py new file mode 100644 index 0000000..5088400 --- /dev/null +++ b/bip-schnorr/test-vectors.py @@ -0,0 +1,215 @@ +import sys +from reference import * + +def vector0(): + seckey = 1 + msg = bytes_from_int(0) + sig = schnorr_sign(msg, seckey) + pubkey = pubkey_gen(seckey) + + # The point reconstructed from the public key has an even Y coordinate. + pubkey_point = point_from_bytes(pubkey) + assert(pubkey_point[1] & 1 == 0) + + return (bytes_from_int(seckey), pubkey, msg, sig, "TRUE", None) + +def vector1(): + seckey = 0xB7E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEF + msg = bytes_from_int(0x243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89) + sig = schnorr_sign(msg, seckey) + pubkey = pubkey_gen(seckey) + + # The point reconstructed from the public key has an odd Y coordinate. + pubkey_point = point_from_bytes(pubkey) + assert(pubkey_point[1] & 1 == 1) + + return (bytes_from_int(seckey), pubkey, msg, sig, "TRUE", None) + +def vector2(): + seckey = 0xC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B14E5C7 + msg = bytes_from_int(0x5E2D58D8B3BCDF1ABADEC7829054F90DDA9805AAB56C77333024B9D0A508B75C) + sig = schnorr_sign(msg, seckey) + + # This signature does not verify vector if the implementer would check the + # jacobi symbol of the X coordinate of R instead of the Y coordinate. + R = point_from_bytes(sig[0:32]) + assert(jacobi(R[0]) != 1) + + return (bytes_from_int(seckey), pubkey_gen(seckey), msg, sig, "TRUE", None) + +def vector3(): + seckey = 0x0B432B2677937381AEF05BB02A66ECD012773062CF3FA2549E44F58ED2401710 + msg = bytes_from_int(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) + sig = schnorr_sign(msg, seckey) + return (bytes_from_int(seckey), pubkey_gen(seckey), msg, sig, "TRUE", "test fails if msg is reduced modulo p or n") + +# Signs with a given nonce. Results in an invalid signature if y(kG) is not a +# quadratic residue. +def schnorr_sign_fixed_nonce(msg, seckey0, k): + if len(msg) != 32: + raise ValueError('The message must be a 32-byte array.') + if not (1 <= seckey0 <= n - 1): + raise ValueError('The secret key must be an integer in the range 1..n-1.') + P = point_mul(G, seckey0) + seckey = seckey0 if (jacobi(P[1]) == 1) else n - seckey0 + R = point_mul(G, k) + e = int_from_bytes(hash_sha256(bytes_from_point(R) + bytes_from_point(P) + msg)) % n + return bytes_from_point(R) + bytes_from_int((k + e * seckey) % n) + +# Creates a singature with a small x(R) by using k = 1/2 +def vector4(): + one_half = 0x7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0 + seckey = 0x763758E5CBEEDEE4F7D3FC86F531C36578933228998226672F13C4F0EBE855EB + msg = bytes_from_int(0x4DF3C3F68FCC83B27E9D42C90431A72499F17875C81A599B566C9889B9696703) + sig = schnorr_sign_fixed_nonce(msg, seckey, one_half) + return (None, pubkey_gen(seckey), msg, sig, "TRUE", None) + +default_seckey = 0xB7E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEF +default_msg = bytes_from_int(0x243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89) + +def vector5(): + seckey = default_seckey + msg = default_msg + sig = schnorr_sign(msg, seckey) + + # Public key is not on the curve + pubkey = bytes_from_int(0xEEFDEA4CDB677750A420FEE807EACF21EB9898AE79B9768766E4FAA04A2D4A34) + assert(point_from_bytes(pubkey) is None) + + return (None, pubkey, msg, sig, "FALSE", "public key not on the curve") + +def vector6(): + seckey = default_seckey + msg = default_msg + k = 3 + sig = schnorr_sign_fixed_nonce(msg, seckey, k) + + # Y coordinate of R is not a quadratic residue + R = point_mul(G, k) + assert(jacobi(R[1]) != 1) + + return (None, pubkey_gen(seckey), msg, sig, "FALSE", "incorrect R residuosity") + +def vector7(): + seckey = default_seckey + msg = int_from_bytes(default_msg) + neg_msg = bytes_from_int(n - msg) + sig = schnorr_sign(neg_msg, seckey) + return (None, pubkey_gen(seckey), bytes_from_int(msg), sig, "FALSE", "negated message") + +def vector8(): + seckey = default_seckey + msg = default_msg + sig = schnorr_sign(msg, seckey) + sig = sig[0:32] + bytes_from_int(n - int_from_bytes(sig[32:64])) + return (None, pubkey_gen(seckey), msg, sig, "FALSE", "negated s value") + +def bytes_from_point_inf0(P): + if P == None: + return bytes_from_int(0) + return bytes_from_int(P[0]) + +def vector9(): + seckey = default_seckey + msg = default_msg + + # Override bytes_from_point in schnorr_sign to allow creating a signature + # with k = 0. + k = 0 + bytes_from_point_tmp = bytes_from_point.__code__ + bytes_from_point.__code__ = bytes_from_point_inf0.__code__ + sig = schnorr_sign_fixed_nonce(msg, seckey, k) + bytes_from_point.__code__ = bytes_from_point_tmp + + return (None, pubkey_gen(seckey), msg, sig, "FALSE", "sG - eP is infinite. Test fails in single verification if jacobi(y(inf)) is defined as 1 and x(inf) as 0") + +def bytes_from_point_inf1(P): + if P == None: + return bytes_from_int(1) + return bytes_from_int(P[0]) + +def vector10(): + seckey = default_seckey + msg = default_msg + + # Override bytes_from_point in schnorr_sign to allow creating a signature + # with k = 0. + k = 0 + bytes_from_point_tmp = bytes_from_point.__code__ + bytes_from_point.__code__ = bytes_from_point_inf1.__code__ + sig = schnorr_sign_fixed_nonce(msg, seckey, k) + bytes_from_point.__code__ = bytes_from_point_tmp + + return (None, pubkey_gen(seckey), msg, sig, "FALSE", "sG - eP is infinite. Test fails in single verification if jacobi(y(inf)) is defined as 1 and x(inf) as 1") + +# It's cryptographically impossible to create a test vector that fails if run +# in an implementation which merely misses the check that sig[0:32] is an X +# coordinate on the curve. This test vector just increases test coverage. +def vector11(): + seckey = default_seckey + msg = default_msg + sig = schnorr_sign(msg, seckey) + + # Replace R's X coordinate with an X coordinate that's not on the curve + x_not_on_curve = bytes_from_int(0x4A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1D) + assert(point_from_bytes(x_not_on_curve) is None) + sig = x_not_on_curve + sig[32:64] + + return (None, pubkey_gen(seckey), msg, sig, "FALSE", "sig[0:32] is not an X coordinate on the curve") + +# It's cryptographically impossible to create a test vector that fails if run +# in an implementation which merely misses the check that sig[0:32] is smaller +# than the field size. This test vector just increases test coverage. +def vector12(): + seckey = default_seckey + msg = default_msg + sig = schnorr_sign(msg, seckey) + + # Replace R's X coordinate with an X coordinate that's equal to field size + sig = bytes_from_int(p) + sig[32:64] + + return (None, pubkey_gen(seckey), msg, sig, "FALSE", "sig[0:32] is equal to field size") + +# It's cryptographically impossible to create a test vector that fails if run +# in an implementation which merely misses the check that sig[32:64] is smaller +# than the curve order. This test vector just increases test coverage. +def vector13(): + seckey = default_seckey + msg = default_msg + sig = schnorr_sign(msg, seckey) + + # Replace s with a number that's equal to the curve order + sig = sig[0:32] + bytes_from_int(n) + + return (None, pubkey_gen(seckey), msg, sig, "FALSE", "sig[32:64] is equal to curve order") + +vectors = [ + vector0(), + vector1(), + vector2(), + vector3(), + vector4(), + vector5(), + vector6(), + vector7(), + vector8(), + vector9(), + vector10(), + vector11(), + vector12(), + vector13(), + ] + +# Converts the byte strings of a test vector into hex strings +def bytes_to_hex(seckey, pubkey, msg, sig, result, comment): + return (seckey.hex().upper() if seckey is not None else None, pubkey.hex().upper(), msg.hex().upper(), sig.hex().upper(), result, comment) + +vectors = list(map(lambda vector: bytes_to_hex(vector[0], vector[1], vector[2], vector[3], vector[4], vector[5]), vectors)) + +def print_csv(vectors): + writer = csv.writer(sys.stdout) + writer.writerow(("index", "secret key", "public key", "message", "signature", "verification result", "comment")) + for (i,v) in enumerate(vectors): + writer.writerow((i,)+v) + +print_csv(vectors) -- cgit v1.2.3 From 08e1b3da7477edc3900e10cec2249f670f47b9e4 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Fri, 2 Aug 2019 13:52:29 +0000 Subject: Use short public keys for taproot output keys --- bip-taproot.mediawiki | 52 +++++++++++++++++++++++++++---------------------- bip-tapscript.mediawiki | 18 ++++++++--------- 2 files changed, 37 insertions(+), 33 deletions(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index f100e6e..a553791 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -62,24 +62,23 @@ In the text below, ''hashtag(m)'' is a shorthand for ''SHA256(SHA256( === Script validation rules === -A Taproot output is a SegWit output (native or P2SH-nested, see [https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki BIP141]) with version number 1, and a 33-byte witness program whose first byte is 0 or 1. -The following rules only apply when such an output is being spent. Any other outputs, including version 1 outputs with lengths other than 33 bytes, or with a first byte different from 0 or 1, remain unencumbered. +A Taproot output is a SegWit output (native or P2SH-nested, see [https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki BIP141]) with version number 1, and a 32-byte witness program. +The following rules only apply when such an output is being spent. Any other outputs, including version 1 outputs with lengths other than 32 bytes, remain unencumbered. -* Let ''u'' be the 33-byte array containing the witness program (second push in scriptPubKey or P2SH redeemScript). -* Let ''Q = point(byte(2 + u[0]) || u[1:33])'''''Why is the public key directly included in the output?''' While typical earlier constructions store a hash of a script or a public key in the output, this is rather wasteful when a public key is always involved. To guarantee batch verifiability, ''Q'' must be known to every verifier, and thus only revealing its hash as an output would imply adding an additional 33 bytes to the witness. Furthermore, to maintain [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2016-January/012198.html 128-bit collision security] for outputs, a 256-bit hash would be required anyway, which is comparable in size (and thus in cost for senders) to revealing the public key directly. While the usage of public key hashes is often said to protect against ECDLP breaks or quantum computers, this protection is very weak at best: transactions are not protected while being confirmed, and a very [https://twitter.com/pwuille/status/1108097835365339136 large portion] of the currency's supply is not under such protection regardless. Actual resistance to such systems can be introduced by relying on different cryptographic assumptions, but this proposal focuses on improvements that do not change the security model. Note that using P2SH-wrapped outputs only have 80-bit collision security. This is considered low, and is relevant whenever the output includes data from more than a single party (public keys, hashes, ...). If this is not a valid point on the curve, fail. +* Let ''q'' be the 32-byte array containing the witness program (second push in scriptPubKey or P2SH redeemScript) which represents a public key according to bip-schnorr.'''Why is the public key directly included in the output?''' While typical earlier constructions store a hash of a script or a public key in the output, this is rather wasteful when a public key is always involved. To guarantee batch verifiability, ''q'' must be known to every verifier, and thus only revealing its hash as an output would imply adding an additional 32 bytes to the witness. Furthermore, to maintain [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2016-January/012198.html 128-bit collision security] for outputs, a 256-bit hash would be required anyway, which is comparable in size (and thus in cost for senders) to revealing the public key directly. While the usage of public key hashes is often said to protect against ECDLP breaks or quantum computers, this protection is very weak at best: transactions are not protected while being confirmed, and a very [https://twitter.com/pwuille/status/1108097835365339136 large portion] of the currency's supply is not under such protection regardless. Actual resistance to such systems can be introduced by relying on different cryptographic assumptions, but this proposal focuses on improvements that do not change the security model. Note that using P2SH-wrapped outputs only have 80-bit collision security. This is considered low, and is relevant whenever the output includes data from more than a single party (public keys, hashes, ...). . * Fail if the witness stack has 0 elements. -* If there are at least two witness elements, and the first byte of the last element is 0x50'''Why is the first byte of the annex 0x50?''' Like the 0xc0-0xc1 constants, 0x50 is chosen as it could not be confused with a valid P2WPKH or P2WSH spending. As the control block's initial byte's lowest bit is used to indicate the public key's Y oddness, each script version needs two subsequence byte values that are both not yet used in P2WPKH or P2WSH spending. To indicate the annex, only an "unpaired" available byte is necessary like 0x50. This choice maximizes the available options for future script versions., this last element is called ''annex'' ''a'''''What is the purpose of the annex?''' The annex is a reserved space for future extensions, such as indicating the validation costs of computationally expensive new opcodes in a way that is recognizable without knowing the outputs being spent. Until the meaning of this field is defined by another softfork, users SHOULD NOT include annex in transactions, or it may lead to PERMANENT FUND LOSS. and is removed from the witness stack. The annex (or the lack of thereof) is always covered by the transaction digest and contributes to transaction weight, but is otherwise ignored during taproot validation. +* If there are at least two witness elements, and the first byte of the last element is 0x50'''Why is the first byte of the annex 0x50?''' Like the 0xc0-0xc1 constants, 0x50 is chosen as it could not be confused with a valid P2WPKH or P2WSH spending. As the control block's initial byte's lowest bit is used to indicate the public key's Y quadratic residuosity, each script version needs two subsequence byte values that are both not yet used in P2WPKH or P2WSH spending. To indicate the annex, only an "unpaired" available byte is necessary like 0x50. This choice maximizes the available options for future script versions., this last element is called ''annex'' ''a'''''What is the purpose of the annex?''' The annex is a reserved space for future extensions, such as indicating the validation costs of computationally expensive new opcodes in a way that is recognizable without knowing the outputs being spent. Until the meaning of this field is defined by another softfork, users SHOULD NOT include annex in transactions, or it may lead to PERMANENT FUND LOSS. and is removed from the witness stack. The annex (or the lack of thereof) is always covered by the transaction digest and contributes to transaction weight, but is otherwise ignored during taproot validation. * If there is exactly one element left in the witness stack, key path spending is used: -** The single witness stack element is interpreted as the signature and must be valid (see the next section) for the public key ''Q'' and taproot transaction digest (to be defined hereinafter) as message. Fail if it is not. Otherwise pass. +** The single witness stack element is interpreted as the signature and must be valid (see the next section) for the public key ''q'' and taproot transaction digest (to be defined hereinafter) as message. Fail if it is not. Otherwise pass. * If there are at least two witness elements left, script path spending is used: ** Call the second-to-last stack element ''s'', the script. ** The last stack element is called the control block ''c'', and must have length ''33 + 32m'', for a value of ''m'' that is an integer between 0 and 32, inclusive. Fail if it does not have such a length. -** Let ''P = point(byte(2 + (c[0] & 1)) || c[1:33])'''''What is the purpose of the first byte of the control block?''' The first byte of the control block has three distinct functions: -* The low bit is used to denote the oddness of the Y coordinate of the ''P'' point. +** Let ''P = point(c[1:33])'' where ''point'' is defined as in bip-schnorr. Fail if this point is not on the curve. +** Let ''l = c[0] & 0xfe'', the leaf version'''What is the purpose of the first byte of the control block?''' The first byte of the control block has three distinct functions: +* The low bit is used to denote whether the ''Q'' point's Y coordinate is a quadratic residue.'''Why is the quadratic residuosity of the output public key's Y coordinate required in a script path spend?''' The ''point'' function always constructs a point with Y coordinate having that property, but because ''Q'' is constructed by adding the taproot tweak to the internal public key ''P'', it cannot easily be guaranteed that ''Q'' in fact has such a Y coordinate. We can not ignore the Y coordinate because it would prevent batch verification. Trying out multiple internal keys until there's such a ''Q'' is possible but undesirable and unnecessary since this information about the Y coordinate only consumes an unused bit. * By keeping the top two bits set to true, it can be guaranteed that scripts can be recognized without knowledge of the UTXO being spent, simplifying analysis. This is because such values cannot occur as first byte of the final stack element in either P2WPKH or P2WSH spends. * The remaining five bits are used for introducing new script versions that are not observable unless actually executed. -. Fail if this point is not on the curve. -** Let ''l = c[0] & 0xfe'', the leaf version. +. ** Let ''k0 = hashTapLeaf(l || compact_size(size of s) || s)''; also call it the ''tapleaf hash''. ** For ''j'' in ''[0,1,...,m-1]'': *** Let ''ej = c[33+32j:65+32j]''. @@ -88,10 +87,11 @@ The following rules only apply when such an output is being spent. Any other out **** If ''kj ≥ ej'': ''kj+1 = hashTapBranch(ej || kj)''. ** Let ''t = hashTapTweak(bytes(P) || km) = hashTapTweak(2 + (c[0] & 1) || c[1:33] || km)''. ** If ''t ≥ 0xFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141'' (order of secp256k1), fail. +** Let ''Q = point(q) if (c[0] & 1) = 1 and -point(q) otherwise'' ** If ''Q ≠ P + int(t)G'', fail. ** Execute the script, according to the applicable script rules'''What are the applicable script rules in script path spends?''' Bip-tapscript specifies validity rules that apply if the leaf version is ''0xc0'', but future proposals can introduce rules for other leaf versions., using the witness stack elements excluding the script ''s'', the control block ''c'', and the annex ''a'' if present, as initial stack. -''Q'' is referred to as ''taproot output key'' and ''P'' as ''taproot internal key''. +''q'' is referred to as ''taproot output key'' and ''c[1:33]'' as ''taproot internal key''. === Signature validation rules === @@ -137,7 +137,7 @@ As the message for signature verification, transaction digest is ''hashTapS *** Bit-0 is set if the scriptPubKey being spent is P2SH (opposed to "native segwit"). *** Bit-1 is set if an annex is present (the original witness stack has two or more witness elements, and the first byte of the last element is 0x50). *** The other bits are unset. -** scriptPubKey (24 or 36): scriptPubKey of the previous output spent by this input, serialized as script inside CTxOut. The size is 24-byte for P2SH-embedded segwit, or 36-byte for native segwit. +** scriptPubKey (24 or 35): scriptPubKey of the previous output spent by this input, serialized as script inside CTxOut. The size is 24-byte for P2SH-embedded segwit, or 35-byte for native segwit. ** If the SIGHASH_ANYONECANPAY flag is set: *** outpoint (36): the COutPoint of this input (32-byte hash + 4-byte little-endian). *** amount (8): value of the previous output spent by this input. @@ -150,7 +150,7 @@ As the message for signature verification, transaction digest is ''hashTapS ** If the SIGHASH_SINGLE flag is set: *** sha_single_output (32): the SHA256 of the corresponding output in CTxOut format. -The total number of bytes hashed is at most ''209'''''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''177 - is_anyonecanpay * 50 - is_none * 32 - is_p2sh_spending * 12 + has_annex * 32''.. +The total number of bytes hashed is at most ''209'''''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''176 - is_anyonecanpay * 50 - is_none * 32 - is_p2sh_spending * 11 + has_annex * 32''.. In summary, the semantics of the BIP143 sighash types remain unchanged, except the following: # The way and order of serialization is changed.'''Why is the serialization in the transaction digest changed?''' Hashes that go into the digest and the digest itself are now computed with a single SHA256 invocation instead of double SHA256. There is no expected security improvement by doubling SHA256 because this only protects against length-extension attacks against SHA256 which are not a concern for transaction digests because there is no secret data. Therefore doubling SHA256 is a waste of resources. The digest computation now follows a logical order with transaction level data first, then input data and output data. This allows to efficiently cache the transaction part of the digest across different inputs using the SHA256 midstate. Additionally, digest computation avoids unnecessary hashing as opposed to BIP143 digests in which parts may be set zero and before hashing them. Despite that, collisions are made impossible by committing to the length of the data (implicit in hash_type and spend_type) before the variable length data. @@ -165,7 +165,7 @@ This section discusses how to construct and spend Taproot outputs. It only affec and is not consensus critical in any way. Conceptually, every Taproot output corresponds to a combination of a single public key condition (the internal key), and zero or more general conditions encoded in scripts organized in a tree. -Satisfying any of these conditions is sufficient to spend the output. +Satisfying any of these conditions is sufficient to spend the output. '''Initial steps''' The first step is determining what the internal key and the organization of the rest of the scripts should be. The specifics are likely application dependent, but here are some general guidelines: * When deciding between scripts with conditionals (OP_IF etc.) and splitting them up into multiple scripts (each corresponding to one execution path through the original script), it is generally preferable to pick the latter. @@ -173,7 +173,7 @@ Satisfying any of these conditions is sufficient to spend the output. * If one or more of the spending conditions consist of just a single key (after aggregation), the most likely one should be made the internal key. If no such condition exists, it may be worthwhile adding one that consists of an aggregation of all keys participating in all scripts combined; effectively adding an "everyone agrees" branch. If that is inacceptable, pick as internal key a point with unknown discrete logarithm (TODO). * The remaining scripts should be organized into the leaves of a binary tree. This can be a balanced tree if each of the conditions these scripts correspond to are equally likely. If probabilities for each condition are known, consider constructing the tree as a Huffman tree. -'''Computing the output script''' Once the spending conditions are split into an internal key internal_pubkey and a binary tree whose leaves are (leaf_version, script) tuples, the following Python3 algorithm can be used to compute the output script. In the code below, ser_script prefixes its input with a CCompactSize-encoded length, and public key objects have methods get_bytes to get their compressed encoding (see bip-schnorr) and tweak_add to add a multiple of the secp256k1 generator to it (similar to BIP32's derivation). +'''Computing the output script''' Once the spending conditions are split into an internal key internal_pubkey and a binary tree whose leaves are (leaf_version, script) tuples, the following Python3 algorithm can be used to compute the output script. In the code below, ser_script prefixes its input with a CCompactSize-encoded length. Public key objects hold 32-byte public keys according to bip-schnorr, have a method get_bytes to get the byte array and a method tweak_add which returns a new public key corresponding to the sum of the public key point and a multiple of the secp256k1 generator (similar to BIP32's derivation). The second return value of tweak_add is a boolean indicating the quadratic residuosity of the Y coordinate of the resulting point. import hashlib @@ -202,22 +202,26 @@ def taproot_output_script(internal_pubkey, script_tree): _, h = taproot_tree_helper(script_tree) t = tagged_hash("TapTweak", internal_pubkey.get_bytes() + h) assert int.from_bytes(t, 'big') < SECP256K1_ORDER - output_pubkey = internal_pubkey.tweak_add(t).get_bytes() - return bytes([0x51, 0x21, output_pubkey[0] & 1]) + output_pubkey[1:] + output_pubkey, _ = internal_pubkey.tweak_add(t) + return bytes([0x51, 0x20]) + output_pubkey.get_bytes() The function taproot_output_script returns a byte array with the scriptPubKey. It can be P2SH wrapped if desired (see BIP141). [[File:bip-taproot/tree.png|frame|This diagram shows the hashing structure to obtain the tweak from an internal key ''P'' and a Merkle tree consisting of 5 script leaves. ''A'', ''B'', ''C'' and ''E'' are ''TapLeaf'' hashes similar to ''D'' and ''AB'' is a ''TapBranch'' hash. Note that when ''CDE'' is computed ''E'' is hashed first because ''E'' is less than ''CD''.]] -'''Spending using the internal key''' A Taproot output can be spent with the private key corresponding to the internal_pubkey. To do so, a witness stack consisting of a single element, a bip-schnorr signature on the signature hash as defined above, with the private key tweaked by the same t in the above snippet. See the code below: +'''Spending using the internal key''' A Taproot output can be spent with the private key corresponding to the internal_pubkey. To do so, a witness stack consists of a single element: a bip-schnorr signature on the signature hash as defined above, with the private key tweaked by the same t in the above snippet. In the code below, internal_privkey has a method pubkey_gen that returns a public key according to bip-schnorr and a boolean indicating the quadratic residuosity of the Y coordinate of the underlying point. +See the code below: -def taproot_sign_internal_key(internal_pubkey, script_tree, internal_privkey, hash_type): +def taproot_sign_internal_key(script_tree, internal_privkey, hash_type): + internal_pubkey, is_y_qresidue = internal_privkey.pubkey_gen() + if is_y_qresidue: + internal_privkey = internal_privkey.negate() _, h = taproot_tree_helper(script_tree) t = tagged_hash("TapTweak", internal_pubkey.get_bytes() + h) output_privkey = internal_privkey.tweak_add(t) - sig = output_privkey.sign_schnorr(sighash(hash_type)) + sig = output_privkey.schnorr_sign(sighash(hash_type)) if hash_type != 0: sig += bytes([hash_type]) return [sig] @@ -229,10 +233,12 @@ This function returns the witness stack necessary, and assumes a tweak_add def taproot_sign_script(internal_pubkey, script_tree, script_num, inputs): - info, _ = taproot_tree_helper(script_tree) + info, h = taproot_tree_helper(script_tree) (leaf_version, script), path = info[script_num] - pubkey_bytes = internal_pubkey.get_bytes() - pubkey_data = bytes([(pubkey_bytes[0] & 1) + leaf_version]) + pubkey_bytes[1:] + t = tagged_hash("TapTweak", internal_pubkey.get_bytes() + h) + _, is_y_qresidue = internal_pubkey.tweak_add(t) + output_pubkey_tag = 0 if is_y_qresidue else 1 + pubkey_data = bytes([output_pubkey_tag + leaf_version]) + internal_pubkey.get_bytes() return inputs + [script, pubkey_data + path] diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index ce42098..af46afd 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -45,7 +45,7 @@ Additionally, the new tapscript OP_SUCCESS opcodes allow introducin The rules below only apply when validating a transaction input for which all of the conditions below are true: * The transaction output is a '''segregated witness spend''' (i.e., either the scriptPubKey or BIP16 redeemScript is a witness program as defined in BIP141). -* It is a '''taproot spend''' as defined in bip-taproot (i.e., the witness version is 1, the witness program is 33 bytes, and the first of those is 0x00 or 0x01). +* It is a '''taproot spend''' as defined in bip-taproot (i.e., the witness version is 1, the witness program is 32 bytes). * It is a '''script path spend''' as defined in bip-taproot (i.e., after removing the optional annex from the witness stack, two or more stack elements remain). * The leaf version is ''0xc0'' (i.e. the first byte of the last witness element after removing the optional annex is ''0xc0'' or ''0xc1'')'''How is the ''0xc0'' constant chosen?''' Following the guidelines in bip-taproot, by choosing a value having the two top bits set, tapscript spends are identifiable even without access to the UTXO being spent., marking it as a '''tapscript spend'''. @@ -71,7 +71,7 @@ The execution rules for tapscript are based on those for P2WSH according to BIP1 * '''Disabled script opcodes''' The following script opcodes are disabled in tapscript: OP_CHECKMULTISIG and OP_CHECKMULTISIGVERIFY. The disabled opcodes behave in the same way as OP_RETURN, by failing and terminating the script immediately when executed, and being ignored when found in unexecuted branch. While being ignored, they are still counted towards the 201 non-push opcodes limit. * '''Consensus-enforced MINIMALIF''' The MINIMALIF rules, which are only a standardness rule in P2WSH, are consensus enforced in tapscript. This means that the input argument to the OP_IF and OP_NOTIF opcodes must be either exactly 0 (the empty vector) or exactly 1 (the one-byte vector with value 1)'''Why make MINIMALIF consensus?''' This makes it considerably easier to write non-malleable scripts that take branch information from the stack.. * '''OP_SUCCESSx opcodes''' As listed above, some opcodes are renamed to OP_SUCCESSx, and make the script unconditionally valid. -* '''Signature opcodes'''. The OP_CHECKSIG and OP_CHECKSIGVERIFY are modified to operate on Schnorr signatures (see bip-schnorr) instead of ECDSA, and a new opcode OP_CHECKSIGADD is added. +* '''Signature opcodes'''. The OP_CHECKSIG and OP_CHECKSIGVERIFY are modified to operate on Schnorr public keys and signatures (see bip-schnorr) instead of ECDSA, and a new opcode OP_CHECKSIGADD is added. ** The opcode 186 (0xba) is named as OP_CHECKSIGADD. '''OP_CHECKSIGADD''' This opcode is added to compensate for the loss of OP_CHECKMULTISIG-like opcodes, which are incompatible with batch verification. OP_CHECKSIGADD is functionally equivalent to OP_ROT OP_SWAP OP_CHECKSIG OP_ADD, but is only counted as one opcode towards the 201 non-push opcodes limit. All CScriptNum-related behaviours of OP_ADD are also applicable to OP_CHECKSIGADD.'''Comparison of CHECKMULTISIG and CHECKSIG''' A CHECKMULTISIG script m ... n CHECKMULTISIG with witness 0 ... can be rewritten as script CHECKSIG ... CHECKSIGADD m NUMEQUAL with witness ... . Every witness element w_i is either a signature corresponding to the public key with the same index or an empty vector. A similar CHECKMULTISIGVERIFY script can be translated to bip-tapscript by replacing NUMEQUAL with NUMEQUALVERIFY. Alternatively, an m-of-n multisig policy can be implemented by splitting the script into several leaves of the Merkle tree, each implementing an m-of-m policy using CHECKSIGVERIFY ... CHECKSIGVERIFY CHECKSIG. If the setting allows the participants to interactively collaborate while signing, multisig policies can be realized with [https://eprint.iacr.org/2018/068 MuSig] for m-of-m and with [http://cacr.uwaterloo.ca/techreports/2001/corr2001-13.ps threshold signatures] using verifiable secret sharing for m-of-n. ===Rules for signature opcodes=== @@ -84,11 +84,9 @@ The following rules apply to OP_CHECKSIG, OP_CHECKSIGVERIFYn is larger than 4 bytes, the script MUST fail and terminate immediately. * If the public key size is zero, the script MUST fail and terminate immediately. -* If the first byte of the public key is 0x04, 0x06, or 0x07, the script MUST fail and terminate immediately regardless of the public key size. -* If the first byte of the public key is 0x02 or 0x03, it is considered to be a public key as described in bip-schnorr: -** If the public key is not 33 bytes, the script MUST fail and terminate immediately. +* If the public key size is 32 bytes, it is considered to be a public key as described in bip-schnorr: ** If the signature is not the empty vector, the signature is validated according to the bip-taproot signing validation rules against the public key and the tapscript transaction digest (to be defined hereinafter) as message. Validation failure MUST cause the script to fail and terminate immediately. -* If the first byte of the public key is not 0x02, 0x03, 0x04, 0x06, or 0x07, the public key is of an ''unknown public key type'''''Unknown public key types''' allow adding new signature validation rules through softforks. A softfork could add actual signature validation which either passes or makes the script fail and terminate immediately. This way, new SIGHASH modes can be added, as well as [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-December/016549.html NOINPUT-tagged public keys] and a public key constant which is replaced by the taproot internal key for signature validation. and no actual signature verification is applied. During script execution of signature opcodes they behave exactly as known public key types except that signature validation is considered to be successful. +* If the public key size is not zero and not 32 bytes, the public key is of an ''unknown public key type'''''Unknown public key types''' allow adding new signature validation rules through softforks. A softfork could add actual signature validation which either passes or makes the script fail and terminate immediately. This way, new SIGHASH modes can be added, as well as [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-December/016549.html NOINPUT-tagged public keys] and a public key constant which is replaced by the taproot internal key for signature validation. and no actual signature verification is applied. During script execution of signature opcodes they behave exactly as known public key types except that signature validation is considered to be successful. * If the script did not fail and terminate before this step, regardless of the public key type: ** If the signature is the empty vector: *** For OP_CHECKSIGVERIFY, the script MUST fail and terminate immediately. @@ -113,14 +111,14 @@ The one-byte spend_type has a different value, specificially at bit As additional pieces of data, added at the end of the input to the ''hashTapSighash'' function: * tapleaf_hash (32): the tapleaf hash as defined in bip-taproot -* key_version (1): a constant value 0x02 representing the current version of public keys in the tapscript signature opcode execution. +* key_version (1): a constant value 0x00 representing the current version of public keys in the tapscript signature opcode execution. * codeseparator_position (2): the opcode position of the last executed OP_CODESEPARATOR before the currently executed signature opcode, with the value in little endian (or 0xffff if none executed). The first opcode in a script has a position of 0. A multi-byte push opcode is counted as one opcode, regardless of the size of data being pushed. -The total number of bytes hashed is at most ''244'''''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''212 - is_anyonecanpay * 50 - is_none * 32 - is_p2sh_spending * 12 + has_annex * 32''.. +The total number of bytes hashed is at most ''244'''''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''211 - is_anyonecanpay * 50 - is_none * 32 - is_p2sh_spending * 11 + has_annex * 32''.. In summary, the semantics of the BIP143 sighash types remain unchanged, except the following: # The exceptions mentioned in bip-taproot. -# The digest commits to taproot-specific data key_version.'''Why does the transaction digest commit to the key_version?''' This is for future extensions that define unknown public key types, making sure signatures can't be moved from one key type to another. This value is intended to be set equal to the first byte of the public key, after masking out flags like the oddness of the Y coordinate. +# The digest commits to taproot-specific data key_version.'''Why does the transaction digest commit to the key_version?''' This is for future extensions that define unknown public key types, making sure signatures can't be moved from one key type to another. # The digest commits to the executed script through the tapleaf_hash which includes the leaf version and script instead of scriptCode. This implies that this commitment is unaffected by OP_CODESEPARATOR. # The digest commits to the opcode position of the last executed OP_CODESEPARATOR.'''Why does the transaction digest commit to the position of the last executed OP_CODESEPARATOR?''' This allows continuing to use OP_CODESEPARATOR to sign the executed path of the script. Because the codeseparator_position is the last input to the digest, the SHA256 midstate can be efficiently cached for multiple OP_CODESEPARATORs in a single script. In contrast, the BIP143 handling of OP_CODESEPARATOR is to commit to the executed script only from the last executed OP_CODESEPARATOR onwards which requires unnecessary rehashing of the script. It should be noted that the one known OP_CODESEPARATOR use case of saving a second public key push in a script by sharing the first one between two code branches can be most likely expressed even cheaper by moving each branch into a separate taproot leaf. @@ -133,7 +131,7 @@ In addition to the 201 non-push opcodes limit, the use of signature opcodes is s * If 50 * (sigops_passed - 1) is greater than input_witness_weight, the script MUST fail and terminate immediately. This rule limits worst-case validation costs in tapscript similar to the ''sigops limit'' that only applies to legacy and P2WSH scripts'''The tapscript sigop limit''' The signature opcode limit protects against scripts which are slow to verify due to excessively many signature operations. In tapscript the number of signature opcodes does not count towards the BIP141 or legacy sigop limit. The old sigop limit makes transaction selection in block construction unnecessarily difficult because it is a second constraint in addition to weight. Instead, the number of tapscript signature opcodes is limited by witness weight. Additionally, the limit applies to the transaction input instead of the block and only actually executed signature opcodes are counted. Tapscript execution allows one signature opcode per 50 witness weight units plus one free signature opcode. The tapscript signature opcode limit allows to add new signature opcodes like CHECKSIGFROMSTACK to count towards the limit through a soft fork. Even if in the future new opcodes are introduced which change normal script cost there is need to stuff the witness with meaningless data. In that case the taproot annex can be used to add weight to the witness without increasing the actual witness size. -'''Parameter choice of the sigop limit''' Regular witnesses are unaffected by the limit as their weight is composed of public key and (SIGHASH_ALL) signature pairs with ''34 + 65'' weight units each (which includes a 1 weight unit CCompactSize tag). This is also the case if public keys are reused in the script because a signature's weight alone is 65 or 66 weight units. However, the limit increases the fees of abnormal scripts with duplicate signatures (and public keys) by requiring additional weight. The weight per sigop factor 50 corresponds to the ratio of BIP141 block limits: 4 mega weight units divided by 80,000 sigops. The "free" signature opcode permitted by the limit exists to account for the weight of the non-witness parts of the transaction input.. +'''Parameter choice of the sigop limit''' Regular witnesses are unaffected by the limit as their weight is composed of public key and (SIGHASH_ALL) signature pairs with ''33 + 65'' weight units each (which includes a 1 weight unit CCompactSize tag). This is also the case if public keys are reused in the script because a signature's weight alone is 65 or 66 weight units. However, the limit increases the fees of abnormal scripts with duplicate signatures (and public keys) by requiring additional weight. The weight per sigop factor 50 corresponds to the ratio of BIP141 block limits: 4 mega weight units divided by 80,000 sigops. The "free" signature opcode permitted by the limit exists to account for the weight of the non-witness parts of the transaction input.. ==Rationale== -- cgit v1.2.3 From 303ff5fb26fc6ce4d6dfcc6e52a5da3dd6d65e4b Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Mon, 19 Aug 2019 14:37:55 +0000 Subject: Address Tim's comments --- bip-schnorr.mediawiki | 27 +++++++++++---------------- bip-taproot.mediawiki | 6 +++--- 2 files changed, 14 insertions(+), 19 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index fa8faa5..0eb79c4 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -34,8 +34,8 @@ from not being standardized. This document seeks to change that. As we propose a new standard, a number of improvements not specific to Schnorr signatures can be made: -* '''Signature encoding''': Instead of [https://en.wikipedia.org/wiki/X.690#DER_encoding DER]-encoding for signatures (which are variable size, and up to 72 bytes), we can use a simple fixed 64-byte format. -* '''Public key encoding''': Instead of ''compressed'' 33-byte encoding of elliptic curve points which are common in Bitcoin, public keys in this proposal are encoded as 32 bytes. +* '''Signature encoding''': Instead of using [https://en.wikipedia.org/wiki/X.690#DER_encoding DER]-encoding for signatures (which are variable size, and up to 72 bytes), we can use a simple fixed 64-byte format. +* '''Public key encoding''': Instead of using ''compressed'' 33-byte encodings of elliptic curve points which are common in Bitcoin today, public keys in this proposal are encoded as 32 bytes. * '''Batch verification''': The specific formulation of ECDSA signatures that is standardized cannot be verified more efficiently in batch compared to individually, unless additional witness data is added. Changing the signature scheme offers an opportunity to avoid this. [[File:bip-schnorr/speedup-batch.png|frame|This graph shows the ratio between the time it takes to verify ''n'' signatures individually and to verify a batch of ''n'' signatures. This ratio goes up logarithmically with the number of signatures, or in other words: the total time to verify ''n'' signatures grows with ''O(n / log n)''.]] @@ -58,19 +58,14 @@ We choose the ''R''-option to support batch verification. '''Key prefixing''' When using the verification rule above directly, it is possible for a third party to convert a signature ''(R,s)'' for key ''P'' into a signature ''(R,s + aH(R || m))'' for key ''P + aG'' and the same message, for any integer ''a''. This is not a concern for Bitcoin currently, as all signature hashes indirectly commit to the public keys. However, this may change with proposals such as SIGHASH_NOINPUT ([https://github.com/bitcoin/bips/blob/master/bip-0118.mediawiki BIP 118]), or when the signature scheme is used for other purposes—especially in combination with schemes like [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki BIP32]'s unhardened derivation. To combat this, we choose ''key prefixed''A limitation of committing to the public key (rather than to a short hash of it, or not at all) is that it removes the ability for public key recovery or verifying signatures against a short public key hash. These constructions are generally incompatible with batch verification. Schnorr signatures; changing the equation to ''sG = R + H(R || P || m)P''. -'''Encoding the sign of P and the sign of R''' There exist several possibilities for encoding the sign of the public key point: -# Encoding the full X and Y coordinate of P, resulting in a 64-byte public key. -# Encoding the full X coordinate, but only whether Y is even or odd (like compressed public keys). This would result in 33-byte public keys. -# Encoding only the X coordinate, resulting in 32-byte public keys. +'''Encoding R and public key point P''' There exist several possibilities for encoding elliptic curve points: +# Encoding the full X and Y coordinates of ''P'' and ''R'', resulting in a 64-byte public key and a 96-byte signature. +# Encoding the full X coordinate and one bit of the Y coordinate to determine one of the two possible Y coordinates. This would result in 33-byte public keys and 65-byte signatures. +# Encoding only the X coordinate, resulting in 32-byte public keys and 64-byte signatures. -As we chose the ''R''-option above, we're required to encode the point ''R'' into the signature. The possibilities are similar to the encoding of ''P'': -# Encoding the full X and Y coordinate of R, resulting in a 96-byte signature. -# Encoding the full X coordinate, but only whether Y is even or odd (like compressed public keys). This would result in 65-byte signatures. -# Encoding only the X coordinate, leaving us with 64-byte signature. +Using the first option would be slightly more efficient for verification (around 10%), but we prioritize compactness, and therefore choose option 3. -Using the first option for both ''P'' and ''R'' would be slightly more efficient for verification (around 5%), but we prioritize compactness, and therefore choose option 3. - -'''Implicit Y coordinates''' In order to support batch verification, the Y coordinate of ''P'' and of ''R'' cannot be ambiguous (every valid X coordinate has two possible Y coordinates). We have a choice between several options for symmetry breaking: +'''Implicit Y coordinates''' In order to support efficient verification and batch verification, the Y coordinate of ''P'' and of ''R'' cannot be ambiguous (every valid X coordinate has two possible Y coordinates). We have a choice between several options for symmetry breaking: # Implicitly choosing the Y coordinate that is in the lower half. # Implicitly choosing the Y coordinate that is evenSince ''p'' is odd, negation modulo ''p'' will map even numbers to odd numbers and the other way around. This means that for a valid X coordinate, one of the corresponding Y coordinates will be even, and the other will be odd.. # Implicitly choosing the Y coordinate that is a quadratic residue (has a square root modulo the field size)A product of two numbers is a quadratic residue when either both or none of the factors are quadratic residues. As ''-1'' is not a quadratic residue, and the two Y coordinates corresponding to a given X coordinate are each other's negation, this means exactly one of the two must be a quadratic residue.. @@ -80,13 +75,13 @@ In the case of ''R'' the third option is slower at signing time but a bit faster for elliptic curve operations). The two other options require a possibly expensive conversion to affine coordinates first. This would even be the case if the sign or oddness were explicitly coded (option 2 in the previous design choice). We therefore choose option 3. -For ''P'' the speed of signing and verification is not significantly different between any of the three options because affine coordinates of the point have to computed anyway. We therefore choose the same option as for ''R''. The signing algorithm ensures that the signature is valid under the correct public key by negating the secret key if necessary. +For ''P'' the speed of signing and verification does not significantly differ between any of the three options because affine coordinates of the point have to computed anyway. We therefore choose the same option as for ''R''. The signing algorithm ensures that the signature is valid under the correct public key by negating the secret key if necessary. -It is important to not mix up the 32 byte public key format and other existing public key formats. Concretely, a verifier should only accept 32 byte public keys and not, for example, convert a 33 byte public key by throwing away the first byte. Otherwise, two public keys would be valid for a single signature which can result in subtle malleability issues. +It is important to not mix up the 32-byte bip-schnorr public key format and other existing public key formats (e.g. encodings used in Bitcoin's ECDSA). Concretely, a verifier should only accept 32 byte public keys and not, for example, convert a 33 byte public key by throwing away the first byte. Otherwise, two public keys would be valid for a single signature which can result in subtle malleability issues (although this type of malleability already exists in the case of ECDSA signatures). Implicit Y coordinates are not a reduction in security when expressed as the number of elliptic curve operations an attacker is expected to perform to compute the secret key. An attacker can normalize any given public key to a point whose Y coordinate is a quadratic residue by negating the point if necessary. This is just a subtraction of field elements and not an elliptic curve operation. -'''Final scheme''' As a result, our final scheme ends up using public keys ''p'' where ''p'' is the X coordinate of a point ''P'' on the curve whose Y coordinate is a quadratic residue and signatures ''(r,s)'' where ''r'' is the X coordinate of a point ''R'' whose Y coordinate is a quadratic residue. The signature satisfies ''sG = R + H(r || p || m)P''. +'''Final scheme''' As a result, our final scheme ends up using public key ''pk'' which is the X coordinate of a point ''P'' on the curve whose Y coordinate is a quadratic residue and signatures ''(r,s)'' where ''r'' is the X coordinate of a point ''R'' whose Y coordinate is a quadratic residue. The signature satisfies ''sG = R + H(r || p || m)P''. === Specification === diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index a553791..5f8537c 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -65,7 +65,7 @@ In the text below, ''hashtag(m)'' is a shorthand for ''SHA256(SHA256( A Taproot output is a SegWit output (native or P2SH-nested, see [https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki BIP141]) with version number 1, and a 32-byte witness program. The following rules only apply when such an output is being spent. Any other outputs, including version 1 outputs with lengths other than 32 bytes, remain unencumbered. -* Let ''q'' be the 32-byte array containing the witness program (second push in scriptPubKey or P2SH redeemScript) which represents a public key according to bip-schnorr.'''Why is the public key directly included in the output?''' While typical earlier constructions store a hash of a script or a public key in the output, this is rather wasteful when a public key is always involved. To guarantee batch verifiability, ''q'' must be known to every verifier, and thus only revealing its hash as an output would imply adding an additional 32 bytes to the witness. Furthermore, to maintain [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2016-January/012198.html 128-bit collision security] for outputs, a 256-bit hash would be required anyway, which is comparable in size (and thus in cost for senders) to revealing the public key directly. While the usage of public key hashes is often said to protect against ECDLP breaks or quantum computers, this protection is very weak at best: transactions are not protected while being confirmed, and a very [https://twitter.com/pwuille/status/1108097835365339136 large portion] of the currency's supply is not under such protection regardless. Actual resistance to such systems can be introduced by relying on different cryptographic assumptions, but this proposal focuses on improvements that do not change the security model. Note that using P2SH-wrapped outputs only have 80-bit collision security. This is considered low, and is relevant whenever the output includes data from more than a single party (public keys, hashes, ...). . +* Let ''q'' be the 32-byte array containing the witness program (second push in scriptPubKey or P2SH redeemScript) which represents a public key according to bip-schnorr '''Why is the public key directly included in the output?''' While typical earlier constructions store a hash of a script or a public key in the output, this is rather wasteful when a public key is always involved. To guarantee batch verifiability, ''q'' must be known to every verifier, and thus only revealing its hash as an output would imply adding an additional 32 bytes to the witness. Furthermore, to maintain [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2016-January/012198.html 128-bit collision security] for outputs, a 256-bit hash would be required anyway, which is comparable in size (and thus in cost for senders) to revealing the public key directly. While the usage of public key hashes is often said to protect against ECDLP breaks or quantum computers, this protection is very weak at best: transactions are not protected while being confirmed, and a very [https://twitter.com/pwuille/status/1108097835365339136 large portion] of the currency's supply is not under such protection regardless. Actual resistance to such systems can be introduced by relying on different cryptographic assumptions, but this proposal focuses on improvements that do not change the security model. Note that using P2SH-wrapped outputs only have 80-bit collision security. This is considered low, and is relevant whenever the output includes data from more than a single party (public keys, hashes, ...). . * Fail if the witness stack has 0 elements. * If there are at least two witness elements, and the first byte of the last element is 0x50'''Why is the first byte of the annex 0x50?''' Like the 0xc0-0xc1 constants, 0x50 is chosen as it could not be confused with a valid P2WPKH or P2WSH spending. As the control block's initial byte's lowest bit is used to indicate the public key's Y quadratic residuosity, each script version needs two subsequence byte values that are both not yet used in P2WPKH or P2WSH spending. To indicate the annex, only an "unpaired" available byte is necessary like 0x50. This choice maximizes the available options for future script versions., this last element is called ''annex'' ''a'''''What is the purpose of the annex?''' The annex is a reserved space for future extensions, such as indicating the validation costs of computationally expensive new opcodes in a way that is recognizable without knowing the outputs being spent. Until the meaning of this field is defined by another softfork, users SHOULD NOT include annex in transactions, or it may lead to PERMANENT FUND LOSS. and is removed from the witness stack. The annex (or the lack of thereof) is always covered by the transaction digest and contributes to transaction weight, but is otherwise ignored during taproot validation. * If there is exactly one element left in the witness stack, key path spending is used: @@ -87,7 +87,7 @@ The following rules only apply when such an output is being spent. Any other out **** If ''kj ≥ ej'': ''kj+1 = hashTapBranch(ej || kj)''. ** Let ''t = hashTapTweak(bytes(P) || km) = hashTapTweak(2 + (c[0] & 1) || c[1:33] || km)''. ** If ''t ≥ 0xFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141'' (order of secp256k1), fail. -** Let ''Q = point(q) if (c[0] & 1) = 1 and -point(q) otherwise'' +** Let ''Q = point(q) if (c[0] & 1) = 1 and -point(q) otherwise''. Fail if this point is not on the curve. ** If ''Q ≠ P + int(t)G'', fail. ** Execute the script, according to the applicable script rules'''What are the applicable script rules in script path spends?''' Bip-tapscript specifies validity rules that apply if the leaf version is ''0xc0'', but future proposals can introduce rules for other leaf versions., using the witness stack elements excluding the script ''s'', the control block ''c'', and the annex ''a'' if present, as initial stack. @@ -210,7 +210,7 @@ The function taproot_output_script returns a byte array with the sc [[File:bip-taproot/tree.png|frame|This diagram shows the hashing structure to obtain the tweak from an internal key ''P'' and a Merkle tree consisting of 5 script leaves. ''A'', ''B'', ''C'' and ''E'' are ''TapLeaf'' hashes similar to ''D'' and ''AB'' is a ''TapBranch'' hash. Note that when ''CDE'' is computed ''E'' is hashed first because ''E'' is less than ''CD''.]] -'''Spending using the internal key''' A Taproot output can be spent with the private key corresponding to the internal_pubkey. To do so, a witness stack consists of a single element: a bip-schnorr signature on the signature hash as defined above, with the private key tweaked by the same t in the above snippet. In the code below, internal_privkey has a method pubkey_gen that returns a public key according to bip-schnorr and a boolean indicating the quadratic residuosity of the Y coordinate of the underlying point. +'''Spending using the internal key''' A Taproot output can be spent with the private key corresponding to the internal_pubkey. To do so, a witness stack consists of a single element: a bip-schnorr signature on the signature hash as defined above, with the private key tweaked by the same t as in the above snippet. In the code below, internal_privkey has a method pubkey_gen that returns a public key according to bip-schnorr and a boolean indicating the quadratic residuosity of the Y coordinate of the underlying point. See the code below: -- cgit v1.2.3 From 5da30bd5688df5738afa157db877797f5cf480dd Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Tue, 20 Aug 2019 10:53:51 +0000 Subject: Update bip-schnorr.mediawiki Co-Authored-By: Tim Ruffing --- bip-schnorr.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 0eb79c4..e3eb187 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -77,7 +77,7 @@ expensive conversion to affine coordinates first. This would even be the case if For ''P'' the speed of signing and verification does not significantly differ between any of the three options because affine coordinates of the point have to computed anyway. We therefore choose the same option as for ''R''. The signing algorithm ensures that the signature is valid under the correct public key by negating the secret key if necessary. -It is important to not mix up the 32-byte bip-schnorr public key format and other existing public key formats (e.g. encodings used in Bitcoin's ECDSA). Concretely, a verifier should only accept 32 byte public keys and not, for example, convert a 33 byte public key by throwing away the first byte. Otherwise, two public keys would be valid for a single signature which can result in subtle malleability issues (although this type of malleability already exists in the case of ECDSA signatures). +It is important to not mix up the 32-byte bip-schnorr public key format and other existing public key formats (e.g. encodings used in Bitcoin's ECDSA). Concretely, a verifier should only accept 32-byte public keys and not, for example, convert a 33-byte public key by throwing away the first byte. Otherwise, two public keys would be valid for a single signature which can result in subtle malleability issues (although this type of malleability already exists in the case of ECDSA signatures). Implicit Y coordinates are not a reduction in security when expressed as the number of elliptic curve operations an attacker is expected to perform to compute the secret key. An attacker can normalize any given public key to a point whose Y coordinate is a quadratic residue by negating the point if necessary. This is just a subtraction of field elements and not an elliptic curve operation. -- cgit v1.2.3 From a67e5e323ca31aba1e525326462956d7e6e785b1 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Tue, 20 Aug 2019 10:53:58 +0000 Subject: Update bip-schnorr/test-vectors.py Co-Authored-By: Tim Ruffing --- bip-schnorr/test-vectors.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-schnorr/test-vectors.py b/bip-schnorr/test-vectors.py index 5088400..45c8b1c 100644 --- a/bip-schnorr/test-vectors.py +++ b/bip-schnorr/test-vectors.py @@ -30,7 +30,7 @@ def vector2(): msg = bytes_from_int(0x5E2D58D8B3BCDF1ABADEC7829054F90DDA9805AAB56C77333024B9D0A508B75C) sig = schnorr_sign(msg, seckey) - # This signature does not verify vector if the implementer would check the + # This singature vector would not verify if the implementer checked the # jacobi symbol of the X coordinate of R instead of the Y coordinate. R = point_from_bytes(sig[0:32]) assert(jacobi(R[0]) != 1) -- cgit v1.2.3 From f3bef4f459b25d6450fdce3ac07cdd87f09f4c76 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Wed, 21 Aug 2019 11:40:42 +0000 Subject: Address sipa's feedback --- bip-schnorr.mediawiki | 7 +++++-- bip-taproot.mediawiki | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index e3eb187..573a678 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -75,7 +75,7 @@ In the case of ''R'' the third option is slower at signing time but a bit faster for elliptic curve operations). The two other options require a possibly expensive conversion to affine coordinates first. This would even be the case if the sign or oddness were explicitly coded (option 2 in the previous design choice). We therefore choose option 3. -For ''P'' the speed of signing and verification does not significantly differ between any of the three options because affine coordinates of the point have to computed anyway. We therefore choose the same option as for ''R''. The signing algorithm ensures that the signature is valid under the correct public key by negating the secret key if necessary. +For ''P'' the speed of signing and verification does not significantly differ between any of the three options because affine coordinates of the point have to be computed anyway. For consistency resons we choose the same option as for ''R''. The signing algorithm ensures that the signature is valid under the correct public key by negating the secret key if necessary. It is important to not mix up the 32-byte bip-schnorr public key format and other existing public key formats (e.g. encodings used in Bitcoin's ECDSA). Concretely, a verifier should only accept 32-byte public keys and not, for example, convert a 33-byte public key by throwing away the first byte. Otherwise, two public keys would be valid for a single signature which can result in subtle malleability issues (although this type of malleability already exists in the case of ECDSA signatures). @@ -118,6 +118,9 @@ Input: The public key corresponding to secret key ''d'' is ''bytes(dG)''. +Alternatively, the public key can be created according to [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki BIP32] which describes the derivation of 33-byte compressed public keys. +In order to translate such public keys into bip-schnorr compatible keys, the first byte must be dropped. + ==== Verification ==== Input: @@ -155,7 +158,7 @@ All provided signatures are valid with overwhelming probability if and only if t ==== Signing ==== Input: -* The secret key ''d' '': an integer in the range ''1..n-1'' chosen uniformly at random. +* The secret key ''d' '': an integer in the range ''1..n-1'' * The message ''m'': a 32-byte array To sign ''m'' for public key ''bytes(dG)'': diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 5f8537c..d9a4cbc 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -85,7 +85,7 @@ The following rules only apply when such an output is being spent. Any other out *** Let ''kj+1 depend on whether ''kj < ej'' (lexicographically)'''Why are child elements sorted before hashing in the Merkle tree?''' By doing so, it is not necessary to reveal the left/right directions along with the hashes in revealed Merkle branches. This is possible because we do not actually care about the position of specific scripts in the tree; only that they are actually committed to.: **** If ''kj < ej'': ''kj+1 = hashTapBranch(kj || ej)'''''Why not use a more efficient hash construction for inner Merkle nodes?''' The chosen construction does require two invocations of the SHA256 compression functions, one of which can be avoided in theory (see BIP98). However, it seems preferable to stick to constructions that can be implemented using standard cryptographic primitives, both for implementation simplicity and analyzability. If necessary, a significant part of the second compression function can be optimized out by [https://github.com/bitcoin/bitcoin/pull/13191 specialization] for 64-byte inputs.. **** If ''kj ≥ ej'': ''kj+1 = hashTapBranch(ej || kj)''. -** Let ''t = hashTapTweak(bytes(P) || km) = hashTapTweak(2 + (c[0] & 1) || c[1:33] || km)''. +** Let ''t = hashTapTweak(bytes(P) || km) = hashTapTweak(c[1:33] || km)''. ** If ''t ≥ 0xFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141'' (order of secp256k1), fail. ** Let ''Q = point(q) if (c[0] & 1) = 1 and -point(q) otherwise''. Fail if this point is not on the curve. ** If ''Q ≠ P + int(t)G'', fail. -- cgit v1.2.3 From 16073d0c205889c9f9a59ad2831db8b76921648e Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Fri, 10 May 2019 13:29:21 +0000 Subject: Clarify how to disable key path spending --- bip-taproot.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index d9a4cbc..527e1bc 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -170,7 +170,7 @@ Satisfying any of these conditions is sufficient to spend the output. '''Initial steps''' The first step is determining what the internal key and the organization of the rest of the scripts should be. The specifics are likely application dependent, but here are some general guidelines: * When deciding between scripts with conditionals (OP_IF etc.) and splitting them up into multiple scripts (each corresponding to one execution path through the original script), it is generally preferable to pick the latter. * When a single condition requires signatures with multiple keys, key aggregation techniques like MuSig can be used to combine them into a single key. The details are out of scope for this document, but note that this may complicate the signing procedure. -* If one or more of the spending conditions consist of just a single key (after aggregation), the most likely one should be made the internal key. If no such condition exists, it may be worthwhile adding one that consists of an aggregation of all keys participating in all scripts combined; effectively adding an "everyone agrees" branch. If that is inacceptable, pick as internal key a point with unknown discrete logarithm (TODO). +* If one or more of the spending conditions consist of just a single key (after aggregation), the most likely one should be made the internal key. If no such condition exists, it may be worthwhile adding one that consists of an aggregation of all keys participating in all scripts combined; effectively adding an "everyone agrees" branch. If that is inacceptable, pick as internal key a point with unknown discrete logarithm. One example of such a point is ''H = point(0x0250929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0)'' which is [https://github.com/ElementsProject/secp256k1-zkp/blob/11af7015de624b010424273be3d91f117f172c82/src/modules/rangeproof/main_impl.h#L16 constructed] by taking the hash of the standard uncompressed encoding of secp256k1 generator ''G'' as X coordinate. In order to avoid leaking the information that key path spending is not possible it is recommended to pick a fresh integer ''r'' in the range ''0...n-1'' uniformly at random and use ''H + rG'' as internal key. It is possible to prove that this internal key is does not have a known discrete logarithm with respect to ''G'' by revealing ''r'' to a verifier who can then reconstruct how the internal key was created. * The remaining scripts should be organized into the leaves of a binary tree. This can be a balanced tree if each of the conditions these scripts correspond to are equally likely. If probabilities for each condition are known, consider constructing the tree as a Huffman tree. '''Computing the output script''' Once the spending conditions are split into an internal key internal_pubkey and a binary tree whose leaves are (leaf_version, script) tuples, the following Python3 algorithm can be used to compute the output script. In the code below, ser_script prefixes its input with a CCompactSize-encoded length. Public key objects hold 32-byte public keys according to bip-schnorr, have a method get_bytes to get the byte array and a method tweak_add which returns a new public key corresponding to the sum of the public key point and a multiple of the secp256k1 generator (similar to BIP32's derivation). The second return value of tweak_add is a boolean indicating the quadratic residuosity of the Y coordinate of the resulting point. -- cgit v1.2.3 From 1c6b104597d6a6f374e1ae22e748f78a5295c151 Mon Sep 17 00:00:00 2001 From: John Newbery Date: Sat, 18 May 2019 14:05:49 -0400 Subject: Replace 'quadratic residue of...' --- bip-schnorr.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 573a678..43ea9d7 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -70,7 +70,7 @@ Using the first option would be slightly more efficient for verification (around # Implicitly choosing the Y coordinate that is evenSince ''p'' is odd, negation modulo ''p'' will map even numbers to odd numbers and the other way around. This means that for a valid X coordinate, one of the corresponding Y coordinates will be even, and the other will be odd.. # Implicitly choosing the Y coordinate that is a quadratic residue (has a square root modulo the field size)A product of two numbers is a quadratic residue when either both or none of the factors are quadratic residues. As ''-1'' is not a quadratic residue, and the two Y coordinates corresponding to a given X coordinate are each other's negation, this means exactly one of the two must be a quadratic residue.. -In the case of ''R'' the third option is slower at signing time but a bit faster to verify, as the quadratic residue of the Y coordinate can be computed directly for points represented in +In the case of ''R'' the third option is slower at signing time but a bit faster to verify, as it is possible to directly compute whether the Y coordinate is a quadratic residue when the points are represented in [https://en.wikibooks.org/wiki/Cryptography/Prime_Curve/Jacobian_Coordinates Jacobian coordinates] (a common optimization to avoid modular inverses for elliptic curve operations). The two other options require a possibly expensive conversion to affine coordinates first. This would even be the case if the sign or oddness were explicitly coded (option 2 in the previous design choice). We therefore choose option 3. -- cgit v1.2.3 From bba0bad5e8001a7302557883d655ec5b583ac8a6 Mon Sep 17 00:00:00 2001 From: John Newbery Date: Sat, 18 May 2019 13:24:23 -0400 Subject: Define c in lift_x(x) --- bip-schnorr.mediawiki | 1 + 1 file changed, 1 insertion(+) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 43ea9d7..c267640 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -104,6 +104,7 @@ The following convention is used, with constants as defined for secp256k1: ** The function ''bytes(P)'', where ''P'' is a point, returns ''bytes(x(P))'. ** The function ''int(x)'', where ''x'' is a 32-byte array, returns the 256-bit unsigned integer whose most significant byte encoding is ''x''. ** The function ''lift_x(x)'', where ''x'' is an integer in range ''0..p-1'', returns the point ''P'' for which ''x(P) = x'' and ''y(P)'' is a quadratic residue modulo ''p'', or fails if no such point existsGiven an candidate X coordinate ''x'' in the range ''0..p-1'', there exist either exactly two or exactly zero valid Y coordinates. If no valid Y coordinate exists, then ''x'' is not a valid X coordinate either, i.e., no point ''P'' exists for which ''x(P) = x''. Given a candidate ''x'', the valid Y coordinates are the square roots of ''c = x3 + 7 mod p'' and they can be computed as ''y = ±c(p+1)/4 mod p'' (see [https://en.wikipedia.org/wiki/Quadratic_residue#Prime_or_prime_power_modulus Quadratic residue]) if they exist, which can be checked by squaring and comparing with ''c''. Due to [https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion] it then holds that ''c(p-1)/2 = 1 mod p''. The same criterion applied to ''y'' results in ''y(p-1)/2 mod p = ±c((p+1)/4)((p-1)/2) mod p = ±1 mod p''. Therefore ''y = +c(p+1)/4 mod p'' is a quadratic residue and ''-y mod p'' is not.. The function ''lift_x(x)'' is equivalent to the following pseudocode: +*** Let ''c = x3 + 7 mod p''. *** Let ''y = c(p+1)/4 mod p''. *** Fail if ''c ≠ y2 mod p''. *** Return ''(r, y)''. -- cgit v1.2.3 From 680af7db4c423754d59905e76e60a4069b9d67fe Mon Sep 17 00:00:00 2001 From: John Newbery Date: Sat, 18 May 2019 13:38:00 -0400 Subject: Return a point from lift_x() --- bip-schnorr.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index c267640..561ff6f 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -107,7 +107,7 @@ The following convention is used, with constants as defined for secp256k1: *** Let ''c = x3 + 7 mod p''. *** Let ''y = c(p+1)/4 mod p''. *** Fail if ''c ≠ y2 mod p''. -*** Return ''(r, y)''. +*** Return the unique point ''P'' such that ''x(P) = x'' and ''y(P) = y''. ** The function ''point(x)'', where ''x'' is a 32-byte array, returns the point ''P = lift_x(int(x))''. ** The function ''hash(x)'', where ''x'' is a byte array, returns the 32-byte SHA256 hash of ''x''. ** The function ''jacobi(x)'', where ''x'' is an integer, returns the [https://en.wikipedia.org/wiki/Jacobi_symbol Jacobi symbol] of ''x / p''. It is equal to ''x(p-1)/2 mod p'' ([https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion])For points ''P'' on the secp256k1 curve it holds that ''jacobi(y(P)) ≠ 0''.. -- cgit v1.2.3 From ba748dcd93896885e41c620f9d1d88aac748ca63 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Mon, 19 Aug 2019 14:45:34 +0000 Subject: Use key path spend terminology more consistently in taproot/tapscript --- bip-taproot.mediawiki | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 527e1bc..b2d45a3 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -210,11 +210,11 @@ The function taproot_output_script returns a byte array with the sc [[File:bip-taproot/tree.png|frame|This diagram shows the hashing structure to obtain the tweak from an internal key ''P'' and a Merkle tree consisting of 5 script leaves. ''A'', ''B'', ''C'' and ''E'' are ''TapLeaf'' hashes similar to ''D'' and ''AB'' is a ''TapBranch'' hash. Note that when ''CDE'' is computed ''E'' is hashed first because ''E'' is less than ''CD''.]] -'''Spending using the internal key''' A Taproot output can be spent with the private key corresponding to the internal_pubkey. To do so, a witness stack consists of a single element: a bip-schnorr signature on the signature hash as defined above, with the private key tweaked by the same t as in the above snippet. In the code below, internal_privkey has a method pubkey_gen that returns a public key according to bip-schnorr and a boolean indicating the quadratic residuosity of the Y coordinate of the underlying point. +'''Spending using the key path''' A Taproot output can be spent with the private key corresponding to the internal_pubkey. To do so, a witness stack consists of a single element: a bip-schnorr signature on the signature hash as defined above, with the private key tweaked by the same t as in the above snippet. In the code below, internal_privkey has a method pubkey_gen that returns a public key according to bip-schnorr and a boolean indicating the quadratic residuosity of the Y coordinate of the underlying point. See the code below: -def taproot_sign_internal_key(script_tree, internal_privkey, hash_type): +def taproot_sign_key(script_tree, internal_privkey, hash_type): internal_pubkey, is_y_qresidue = internal_privkey.pubkey_gen() if is_y_qresidue: internal_privkey = internal_privkey.negate() -- cgit v1.2.3 From 7f3611d2398f053d4c1a9889cb20d814bd6abedd Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Mon, 26 Aug 2019 11:32:04 +0000 Subject: Use a tagged hash in bip-schnorr nonce derivation --- bip-schnorr.mediawiki | 7 ++++++- bip-schnorr/reference.py | 6 +++++- bip-taproot.mediawiki | 19 ++----------------- 3 files changed, 13 insertions(+), 19 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 561ff6f..8781f2c 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -110,6 +110,11 @@ The following convention is used, with constants as defined for secp256k1: *** Return the unique point ''P'' such that ''x(P) = x'' and ''y(P) = y''. ** The function ''point(x)'', where ''x'' is a 32-byte array, returns the point ''P = lift_x(int(x))''. ** The function ''hash(x)'', where ''x'' is a byte array, returns the 32-byte SHA256 hash of ''x''. +** The function ''hashtag(x)'' is a shorthand for ''hash(hash(tag) || hash(tag) || x)'', where ''tag'' is a UTF-8 encoded tag name.Cryptographic hash functions are used for multiple purposes in the specification below and in Bitcoin in general. To make sure hashes used in one context can't be reinterpreted in another one, hash functions can be tweaked with a context-dependent tag name, in such a way that collisions across contexts can be assumed to be infeasible. + +* So far, nowhere in the Bitcoin protocol are hashes used where the input of SHA256 starts with two (non-double) SHA256 hashes, making collisions with existing uses of hash functions infeasible. +* Because the prefix ''SHA256(tag) || SHA256(tag)'' is a 64-byte long context-specific constant, optimized implementations are possible (identical to SHA256 itself, but with a modified initial state). +* Using SHA256 of the tag name itself is reasonably simple and efficient for implementations that don't choose to use the optimization above. ** The function ''jacobi(x)'', where ''x'' is an integer, returns the [https://en.wikipedia.org/wiki/Jacobi_symbol Jacobi symbol] of ''x / p''. It is equal to ''x(p-1)/2 mod p'' ([https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion])For points ''P'' on the secp256k1 curve it holds that ''jacobi(y(P)) ≠ 0''.. === Public Key Generation === @@ -165,7 +170,7 @@ Input: To sign ''m'' for public key ''bytes(dG)'': * Let ''P = dG'' * Let ''d = d' '' if ''jacobi(y(P)) = 1'', otherwise let ''d = n - d' ''. -* Let ''k' = int(hash(bytes(d) || m)) mod n''Note that in general, taking the output of a hash function modulo the curve order will produce an unacceptably biased result. However, for the secp256k1 curve, the order is sufficiently close to ''2256'' that this bias is not observable (''1 - n / 2256'' is around ''1.27 * 2-128'').. +* Let ''k' = int(hashBIPSchnorrDerive(bytes(d) || m)) mod n''Note that in general, taking the output of a hash function modulo the curve order will produce an unacceptably biased result. However, for the secp256k1 curve, the order is sufficiently close to ''2256'' that this bias is not observable (''1 - n / 2256'' is around ''1.27 * 2-128'').. * Fail if ''k' = 0''. * Let ''R = k'G''. * Let ''k = k' '' if ''jacobi(y(R)) = 1'', otherwise let ''k = n - k' ''. diff --git a/bip-schnorr/reference.py b/bip-schnorr/reference.py index f89b3c4..4f0d1df 100644 --- a/bip-schnorr/reference.py +++ b/bip-schnorr/reference.py @@ -5,6 +5,10 @@ p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F n = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 G = (0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798, 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8) +def tagged_hash(tag, msg): + tag_hash = hashlib.sha256(tag.encode()).digest() + return hashlib.sha256(tag_hash + tag_hash + msg).digest() + def point_add(P1, P2): if (P1 is None): return P2 @@ -61,7 +65,7 @@ def schnorr_sign(msg, seckey0): raise ValueError('The secret key must be an integer in the range 1..n-1.') P = point_mul(G, seckey0) seckey = seckey0 if (jacobi(P[1]) == 1) else n - seckey0 - k0 = int_from_bytes(hash_sha256(bytes_from_int(seckey) + msg)) % n + k0 = int_from_bytes(tagged_hash("BIPSchnorrDerive", bytes_from_int(seckey) + msg)) % n if k0 == 0: raise RuntimeError('Failure. This happens only with negligible probability.') R = point_mul(G, k0) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index b2d45a3..51fd45d 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -49,16 +49,7 @@ Not included in this proposal are additional features like new sighash modes or This section specifies the Taproot consensus rules. Validity is defined by exclusion: a block or transaction is valid if no condition exists that marks it failed. -The notation below follows that of bip-schnorr. - -=== Tagged hashes === - -Cryptographic hash functions are used for multiple purposes in the specification below and in Bitcoin in general. To make sure hashes used in one context can't be reinterpreted in another one, all hash functions are tweaked with a context-dependent tag name, in such a way that collisions across contexts can be assumed to be infeasible. - -In the text below, ''hashtag(m)'' is a shorthand for ''SHA256(SHA256(tag) || SHA256(tag) || m)'', where ''tag'' is a UTF-8 encoded tag name. -* So far, nowhere in the Bitcoin protocol are hashes used where the input of SHA256 starts with two (non-double) SHA256 hashes, making collisions with existing uses of hash functions infeasible. -* Because the prefix ''SHA256(tag) || SHA256(tag)'' is a 64-byte long context-specific constant, optimized implementations are possible (identical to SHA256 itself, but with a modified initial state). -* Using SHA256 of the tag name itself is reasonably simple and efficient for implementations that don't choose to use the optimization above. +The notation below follows that of bip-schnorr including the notion of tagged hashes. === Script validation rules === @@ -173,15 +164,9 @@ Satisfying any of these conditions is sufficient to spend the output. * If one or more of the spending conditions consist of just a single key (after aggregation), the most likely one should be made the internal key. If no such condition exists, it may be worthwhile adding one that consists of an aggregation of all keys participating in all scripts combined; effectively adding an "everyone agrees" branch. If that is inacceptable, pick as internal key a point with unknown discrete logarithm. One example of such a point is ''H = point(0x0250929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0)'' which is [https://github.com/ElementsProject/secp256k1-zkp/blob/11af7015de624b010424273be3d91f117f172c82/src/modules/rangeproof/main_impl.h#L16 constructed] by taking the hash of the standard uncompressed encoding of secp256k1 generator ''G'' as X coordinate. In order to avoid leaking the information that key path spending is not possible it is recommended to pick a fresh integer ''r'' in the range ''0...n-1'' uniformly at random and use ''H + rG'' as internal key. It is possible to prove that this internal key is does not have a known discrete logarithm with respect to ''G'' by revealing ''r'' to a verifier who can then reconstruct how the internal key was created. * The remaining scripts should be organized into the leaves of a binary tree. This can be a balanced tree if each of the conditions these scripts correspond to are equally likely. If probabilities for each condition are known, consider constructing the tree as a Huffman tree. -'''Computing the output script''' Once the spending conditions are split into an internal key internal_pubkey and a binary tree whose leaves are (leaf_version, script) tuples, the following Python3 algorithm can be used to compute the output script. In the code below, ser_script prefixes its input with a CCompactSize-encoded length. Public key objects hold 32-byte public keys according to bip-schnorr, have a method get_bytes to get the byte array and a method tweak_add which returns a new public key corresponding to the sum of the public key point and a multiple of the secp256k1 generator (similar to BIP32's derivation). The second return value of tweak_add is a boolean indicating the quadratic residuosity of the Y coordinate of the resulting point. +'''Computing the output script''' Once the spending conditions are split into an internal key internal_pubkey and a binary tree whose leaves are (leaf_version, script) tuples, the following Python3 algorithm can be used to compute the output script. In the code below, ser_script prefixes its input with a CCompactSize-encoded length. Public key objects hold 32-byte public keys according to bip-schnorr, have a method get_bytes to get the byte array and a method tweak_add which returns a new public key corresponding to the sum of the public key point and a multiple of the secp256k1 generator (similar to BIP32's derivation). The second return value of tweak_add is a boolean indicating the quadratic residuosity of the Y coordinate of the resulting point. tagged_hash computes the tagged hash according to bip-schnorr. -import hashlib - -def tagged_hash(tag, msg): - tag_hash = hashlib.sha256(tag.encode()).digest() - return hashlib.sha256(tag_hash + tag_hash + msg).digest() - def taproot_tree_helper(script_tree): if isinstance(script_tree, tuple): leaf_version, script = script_tree -- cgit v1.2.3 From c33c7d0a0c78327e6ca78dd4f6a37296fa49fd2b Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Mon, 26 Aug 2019 20:46:08 +0000 Subject: Tag signature hashes, improve rationale and update test vectors --- bip-schnorr.mediawiki | 29 +++++++++++++++-------------- bip-schnorr/reference.py | 6 ++++-- bip-schnorr/test-vectors.csv | 28 ++++++++++++++-------------- bip-schnorr/test-vectors.py | 4 ++-- bip-taproot.mediawiki | 6 ++++-- 5 files changed, 39 insertions(+), 34 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 8781f2c..ad0b9cf 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -50,13 +50,13 @@ encodings and operations. === Design === -'''Schnorr signature variant''' Elliptic Curve Schnorr signatures for message ''m'' and public key ''P'' generally involve a point ''R'', integers ''e'' and ''s'' picked by the signer, and generator ''G'' which satisfy ''e = H(R || m)'' and ''sG = R + eP''. Two formulations exist, depending on whether the signer reveals ''e'' or ''R'': -# Signatures are ''(e,s)'' that satisfy ''e = H(sG - eP || m)''. This avoids minor complexity introduced by the encoding of the point ''R'' in the signature (see paragraphs "Encoding the sign of R" and "Implicit Y coordinate" further below in this subsection). -# Signatures are ''(R,s)'' that satisfy ''sG = R + H(R || m)P''. This supports batch verification, as there are no elliptic curve operations inside the hashes. +'''Schnorr signature variant''' Elliptic Curve Schnorr signatures for message ''m'' and public key ''P'' generally involve a point ''R'', integers ''e'' and ''s'' picked by the signer, and generator ''G'' which satisfy ''e = hash(R || m)'' and ''sG = R + eP''. Two formulations exist, depending on whether the signer reveals ''e'' or ''R'': +# Signatures are ''(e,s)'' that satisfy ''e = hash(sG - eP || m)''. This avoids minor complexity introduced by the encoding of the point ''R'' in the signature (see paragraphs "Encoding the sign of R" and "Implicit Y coordinate" further below in this subsection). +# Signatures are ''(R,s)'' that satisfy ''sG = R + hash(R || m)P''. This supports batch verification, as there are no elliptic curve operations inside the hashes. We choose the ''R''-option to support batch verification. -'''Key prefixing''' When using the verification rule above directly, it is possible for a third party to convert a signature ''(R,s)'' for key ''P'' into a signature ''(R,s + aH(R || m))'' for key ''P + aG'' and the same message, for any integer ''a''. This is not a concern for Bitcoin currently, as all signature hashes indirectly commit to the public keys. However, this may change with proposals such as SIGHASH_NOINPUT ([https://github.com/bitcoin/bips/blob/master/bip-0118.mediawiki BIP 118]), or when the signature scheme is used for other purposes—especially in combination with schemes like [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki BIP32]'s unhardened derivation. To combat this, we choose ''key prefixed''A limitation of committing to the public key (rather than to a short hash of it, or not at all) is that it removes the ability for public key recovery or verifying signatures against a short public key hash. These constructions are generally incompatible with batch verification. Schnorr signatures; changing the equation to ''sG = R + H(R || P || m)P''. +'''Key prefixing''' When using the verification rule above directly, it is possible for a third party to convert a signature ''(R,s)'' for key ''P'' into a signature ''(R,s + ahash(R || m))'' for key ''P + aG'' and the same message, for any integer ''a''. This is not a concern for Bitcoin currently, as all signature hashes indirectly commit to the public keys. However, this may change with proposals such as SIGHASH_NOINPUT ([https://github.com/bitcoin/bips/blob/master/bip-0118.mediawiki BIP 118]), or when the signature scheme is used for other purposes—especially in combination with schemes like [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki BIP32]'s unhardened derivation. To combat this, we choose ''key prefixed''A limitation of committing to the public key (rather than to a short hash of it, or not at all) is that it removes the ability for public key recovery or verifying signatures against a short public key hash. These constructions are generally incompatible with batch verification. Schnorr signatures; changing the equation to ''sG = R + hash(R || P || m)P''. '''Encoding R and public key point P''' There exist several possibilities for encoding elliptic curve points: # Encoding the full X and Y coordinates of ''P'' and ''R'', resulting in a 64-byte public key and a 96-byte signature. @@ -81,7 +81,13 @@ It is important to not mix up the 32-byte bip-schnorr public key format and othe Implicit Y coordinates are not a reduction in security when expressed as the number of elliptic curve operations an attacker is expected to perform to compute the secret key. An attacker can normalize any given public key to a point whose Y coordinate is a quadratic residue by negating the point if necessary. This is just a subtraction of field elements and not an elliptic curve operation. -'''Final scheme''' As a result, our final scheme ends up using public key ''pk'' which is the X coordinate of a point ''P'' on the curve whose Y coordinate is a quadratic residue and signatures ''(r,s)'' where ''r'' is the X coordinate of a point ''R'' whose Y coordinate is a quadratic residue. The signature satisfies ''sG = R + H(r || p || m)P''. +'''Tagged Hashes''' Cryptographic hash functions are used for multiple purposes in the specification below and in Bitcoin in general. To make sure hashes used in one context can't be reinterpreted in another one, hash functions can be tweaked with a context-dependent tag name, in such a way that collisions across contexts can be assumed to be infeasible. Such collisions obviously can not be ruled out completely, but only for schemes using tagging with a unique name. As for other schemes collisions are at least less likely with tagging than without. + +For example, without tagged hashing a bip-schnorr signature could also be valid for a signature scheme where the only difference is that the arguments to the hash function are reordered. Worse, if the bip-schnorr nonce derivation function was copied or independently created, then the nonce could be accidentally reused in the other scheme leaking the private key. + +This proposal suggests to include the tag by prefixing the hashed data with ''SHA256(tag) || SHA256(tag)''. Because this is a 64-byte long context-specific constant, optimized implementations are possible (identical to SHA256 itself, but with a modified initial state). Using SHA256 of the tag name itself is reasonably simple and efficient for implementations that don't choose to use the optimization. + +'''Final scheme''' As a result, our final scheme ends up using public key ''pk'' which is the X coordinate of a point ''P'' on the curve whose Y coordinate is a quadratic residue and signatures ''(r,s)'' where ''r'' is the X coordinate of a point ''R'' whose Y coordinate is a quadratic residue. The signature satisfies ''sG = R + tagged_hash(r || p || m)P''. === Specification === @@ -109,12 +115,7 @@ The following convention is used, with constants as defined for secp256k1: *** Fail if ''c ≠ y2 mod p''. *** Return the unique point ''P'' such that ''x(P) = x'' and ''y(P) = y''. ** The function ''point(x)'', where ''x'' is a 32-byte array, returns the point ''P = lift_x(int(x))''. -** The function ''hash(x)'', where ''x'' is a byte array, returns the 32-byte SHA256 hash of ''x''. -** The function ''hashtag(x)'' is a shorthand for ''hash(hash(tag) || hash(tag) || x)'', where ''tag'' is a UTF-8 encoded tag name.Cryptographic hash functions are used for multiple purposes in the specification below and in Bitcoin in general. To make sure hashes used in one context can't be reinterpreted in another one, hash functions can be tweaked with a context-dependent tag name, in such a way that collisions across contexts can be assumed to be infeasible. - -* So far, nowhere in the Bitcoin protocol are hashes used where the input of SHA256 starts with two (non-double) SHA256 hashes, making collisions with existing uses of hash functions infeasible. -* Because the prefix ''SHA256(tag) || SHA256(tag)'' is a 64-byte long context-specific constant, optimized implementations are possible (identical to SHA256 itself, but with a modified initial state). -* Using SHA256 of the tag name itself is reasonably simple and efficient for implementations that don't choose to use the optimization above. +** The function ''hashtag(x)'' where ''tag'' is a UTF-8 encoded tag name and ''x'' is a byte array returns the 32-byte hash ''SHA256(SHA256(tag) || SHA256(tag) || x)''. ** The function ''jacobi(x)'', where ''x'' is an integer, returns the [https://en.wikipedia.org/wiki/Jacobi_symbol Jacobi symbol] of ''x / p''. It is equal to ''x(p-1)/2 mod p'' ([https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion])For points ''P'' on the secp256k1 curve it holds that ''jacobi(y(P)) ≠ 0''.. === Public Key Generation === @@ -138,7 +139,7 @@ The signature is valid if and only if the algorithm below does not fail. * Let ''P = point(pk)''; fail if ''point(pk)'' fails. * Let ''r = int(sig[0:32])''; fail if ''r ≥ p''. * Let ''s = int(sig[32:64])''; fail if ''s ≥ n''. -* Let ''e = int(hash(bytes(r) || bytes(P) || m)) mod n''. +* Let ''e = int(hashBIPSchnorr(bytes(r) || bytes(P) || m)) mod n''. * Let ''R = sG - eP''. * Fail if ''infinite(R)''. * Fail if ''jacobi(y(R)) ≠ 1'' or ''x(R) ≠ r''. @@ -157,7 +158,7 @@ All provided signatures are valid with overwhelming probability if and only if t ** Let ''Pi = point(pki)''; fail if ''point(pki)'' fails. ** Let ''r = int(sigi[0:32])''; fail if ''r ≥ p''. ** Let ''si = int(sigi[32:64])''; fail if ''si ≥ n''. -** Let ''ei = int(hash(bytes(r) || bytes(Pi) || mi)) mod n''. +** Let ''ei = int(hashBIPSchnorr(bytes(r) || bytes(Pi) || mi)) mod n''. ** Let ''Ri = lift_x(r)''; fail if ''lift_x(r)'' fails. * Fail if ''(s1 + a2s2 + ... + ausu)G ≠ R1 + a2R2 + ... + auRu + e1P1 + (a2e2)P2 + ... + (aueu)Pu''. @@ -174,7 +175,7 @@ To sign ''m'' for public key ''bytes(dG)'': * Fail if ''k' = 0''. * Let ''R = k'G''. * Let ''k = k' '' if ''jacobi(y(R)) = 1'', otherwise let ''k = n - k' ''. -* Let ''e = int(hash(bytes(R) || bytes(P) || m)) mod n''. +* Let ''e = int(hashBIPSchnorr(bytes(R) || bytes(P) || m)) mod n''. * The signature is ''bytes(R) || bytes((k + ed) mod n)''. '''Above deterministic derivation of ''R'' is designed specifically for this signing algorithm and may not be secure when used in other signature schemes.''' diff --git a/bip-schnorr/reference.py b/bip-schnorr/reference.py index 4f0d1df..95e9e53 100644 --- a/bip-schnorr/reference.py +++ b/bip-schnorr/reference.py @@ -5,6 +5,8 @@ p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F n = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 G = (0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798, 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8) +# This implementation can be sped up by storing the midstate after hashing +# tag_hash instead of rehashing it all the time. def tagged_hash(tag, msg): tag_hash = hashlib.sha256(tag.encode()).digest() return hashlib.sha256(tag_hash + tag_hash + msg).digest() @@ -70,7 +72,7 @@ def schnorr_sign(msg, seckey0): raise RuntimeError('Failure. This happens only with negligible probability.') R = point_mul(G, k0) k = n - k0 if (jacobi(R[1]) != 1) else k0 - e = int_from_bytes(hash_sha256(bytes_from_point(R) + bytes_from_point(P) + msg)) % n + e = int_from_bytes(tagged_hash("BIPSchnorr", bytes_from_point(R) + bytes_from_point(P) + msg)) % n return bytes_from_point(R) + bytes_from_int((k + e * seckey) % n) def schnorr_verify(msg, pubkey, sig): @@ -87,7 +89,7 @@ def schnorr_verify(msg, pubkey, sig): s = int_from_bytes(sig[32:64]) if (r >= p or s >= n): return False - e = int_from_bytes(hash_sha256(sig[0:32] + pubkey + msg)) % n + e = int_from_bytes(tagged_hash("BIPSchnorr", sig[0:32] + pubkey + msg)) % n R = point_add(point_mul(G, s), point_mul(P, n - e)) if R is None or jacobi(R[1]) != 1 or R[0] != r: return False diff --git a/bip-schnorr/test-vectors.csv b/bip-schnorr/test-vectors.csv index 3e17669..7ca6600 100644 --- a/bip-schnorr/test-vectors.csv +++ b/bip-schnorr/test-vectors.csv @@ -1,15 +1,15 @@ index,secret key,public key,message,signature,verification result,comment -0,0000000000000000000000000000000000000000000000000000000000000001,79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798,0000000000000000000000000000000000000000000000000000000000000000,787A848E71043D280C50470E8E1532B2DD5D20EE912A45DBDD2BD1DFBF187EF6166FCCEE14F021B31AF22A90D0639CC010C2B764C304A8FFF266ABBC01A0A880,TRUE, -1,B7E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEF,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,3C4D3ADB1F05C3E948216ECB6007D1534D97D35D5589EDB226AD0370C0293C780AEA9BA361509DA2FDF7BC6E5E38926E40B6ACCD24EA9E06B9DA8244A1D0B691,TRUE, -2,C90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B14E5C7,FAC2114C2FBB091527EB7C64ECB11F8021CB45E8E7809D3C0938E4B8C0E5F84B,5E2D58D8B3BCDF1ABADEC7829054F90DDA9805AAB56C77333024B9D0A508B75C,33380A613013115518CD6030ABC8220B2DED273FD3ABD13DF0882DC6A928E5AFAC72DF3248F8FAC522EF1A819EE5EE5BEA81D92D0E19A6FAB228E5D1D61BF833,TRUE, -3,0B432B2677937381AEF05BB02A66ECD012773062CF3FA2549E44F58ED2401710,25D1DFF95105F5253C4022F628A996AD3A0D95FBF21D468A1B33F8C160D8F517,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,7C4E8B0C2575A77A01AF41EE6678EF9C41F97CC4D15FF6D6CA45D73BC6FF7FF4919D246589AF2FA6306F4B7A392857E9C4A17CB21DBE72C38A48C99979EEDCB8,TRUE,test fails if msg is reduced modulo p or n -4,,D69C3509BB99E412E68B0FE8544E72837DFA30746D8BE2AA65975F29D22DC7B9,4DF3C3F68FCC83B27E9D42C90431A72499F17875C81A599B566C9889B9696703,00000000000000000000003B78CE563F89A0ED9414F5AA28AD0D96D6795F9C63F84A709CFFD89AD94FCBD808D41BD26BF62F263AA253527134DDC4A4715BF491,TRUE, -5,,EEFDEA4CDB677750A420FEE807EACF21EB9898AE79B9768766E4FAA04A2D4A34,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,3C4D3ADB1F05C3E948216ECB6007D1534D97D35D5589EDB226AD0370C0293C780AEA9BA361509DA2FDF7BC6E5E38926E40B6ACCD24EA9E06B9DA8244A1D0B691,FALSE,public key not on the curve -6,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F98631F4EF21D5F231A1000ED069E0348ED057EDF4FB1B6672009EDE9DBB2DEE14,FALSE,incorrect R residuosity -7,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,07636CBE3092D11AFCA4DD1D32E50F039EB5FF5FB2AB72A7DC2BA0F3A4E7ED418C312ED6ABF6A41446D28789DF4AA43A15E166F001D072536ADC6E49C21DC419,FALSE,negated message -8,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,3C4D3ADB1F05C3E948216ECB6007D1534D97D35D5589EDB226AD0370C0293C78F515645C9EAF625D02084391A1C76D9079F830198A5E023505F7DC482E658AB0,FALSE,negated s value -9,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,0000000000000000000000000000000000000000000000000000000000000000221A96FEEBA7AD29F11B675DB394948A83A220FD8FE181A7667BDBEE178011B1,FALSE,sG - eP is infinite. Test fails in single verification if jacobi(y(inf)) is defined as 1 and x(inf) as 0 -10,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,00000000000000000000000000000000000000000000000000000000000000011A39648F31350D8E591106B43B9EB364F8617BCD52DC96A3FA8C4E50347F31DE,FALSE,sG - eP is infinite. Test fails in single verification if jacobi(y(inf)) is defined as 1 and x(inf) as 1 -11,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,4A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1D0AEA9BA361509DA2FDF7BC6E5E38926E40B6ACCD24EA9E06B9DA8244A1D0B691,FALSE,sig[0:32] is not an X coordinate on the curve -12,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F0AEA9BA361509DA2FDF7BC6E5E38926E40B6ACCD24EA9E06B9DA8244A1D0B691,FALSE,sig[0:32] is equal to field size -13,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,3C4D3ADB1F05C3E948216ECB6007D1534D97D35D5589EDB226AD0370C0293C78FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141,FALSE,sig[32:64] is equal to curve order +0,0000000000000000000000000000000000000000000000000000000000000001,79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798,0000000000000000000000000000000000000000000000000000000000000000,528F745793E8472C0329742A463F59E58F3A3F1A4AC09C28F6F8514D4D0322A258BD08398F82CF67B812AB2C7717CE566F877C2F8795C846146978E8F04782AE,TRUE, +1,B7E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEF,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,667C2F778E0616E611BD0C14B8A600C5884551701A949EF0EBFD72D452D64E844160BCFC3F466ECB8FACD19ADE57D8699D74E7207D78C6AEDC3799B52A8E0598,TRUE, +2,C90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B14E5C9,DD308AFEC5777E13121FA72B9CC1B7CC0139715309B086C960E18FD969774EB8,5E2D58D8B3BCDF1ABADEC7829054F90DDA9805AAB56C77333024B9D0A508B75C,2D941B38E32624BF0AC7669C0971B990994AF6F9B18426BF4F4E7EC10E6CDF386CF646C6DDAFCFA7F1993EEB2E4D66416AEAD1DDAE2F22D63CAD901412D116C6,TRUE, +3,0B432B2677937381AEF05BB02A66ECD012773062CF3FA2549E44F58ED2401710,25D1DFF95105F5253C4022F628A996AD3A0D95FBF21D468A1B33F8C160D8F517,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,8BD2C11604B0A87A443FCC2E5D90E5328F934161B18864FB48CE10CB59B45FB9B5B2A0F129BD88F5BDC05D5C21E5C57176B913002335784F9777A24BD317CD36,TRUE,test fails if msg is reduced modulo p or n +4,,D69C3509BB99E412E68B0FE8544E72837DFA30746D8BE2AA65975F29D22DC7B9,4DF3C3F68FCC83B27E9D42C90431A72499F17875C81A599B566C9889B9696703,00000000000000000000003B78CE563F89A0ED9414F5AA28AD0D96D6795F9C63EE374AC7FAE927D334CCB190F6FB8FD27A2DDC639CCEE46D43F113A4035A2C7F,TRUE, +5,,EEFDEA4CDB677750A420FEE807EACF21EB9898AE79B9768766E4FAA04A2D4A34,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,667C2F778E0616E611BD0C14B8A600C5884551701A949EF0EBFD72D452D64E844160BCFC3F466ECB8FACD19ADE57D8699D74E7207D78C6AEDC3799B52A8E0598,FALSE,public key not on the curve +6,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9935554D1AA5F0374E5CDAACB3925035C7C169B27C4426DF0A6B19AF3BAEAB138,FALSE,incorrect R residuosity +7,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,10AC49A6A2EBF604189C5F40FC75AF2D42D77DE9A2782709B1EB4EAF1CFE9108D7003B703A3499D5E29529D39BA040A44955127140F81A8A89A96F992AC0FE79,FALSE,negated message +8,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,667C2F778E0616E611BD0C14B8A600C5884551701A949EF0EBFD72D452D64E84BE9F4303C0B9913470532E6521A827951D39F5C631CFD98CE39AC4D7A5A83BA9,FALSE,negated s value +9,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,000000000000000000000000000000000000000000000000000000000000000099D2F0EBC2996808208633CD9926BF7EC3DAB73DAAD36E85B3040A698E6D1CE0,FALSE,sG - eP is infinite. Test fails in single verification if jacobi(y(inf)) is defined as 1 and x(inf) as 0 +10,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,000000000000000000000000000000000000000000000000000000000000000124E81D89F01304695CE943F7D5EBD00EF726A0864B4FF33895B4E86BEADC5456,FALSE,sG - eP is infinite. Test fails in single verification if jacobi(y(inf)) is defined as 1 and x(inf) as 1 +11,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,4A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1D4160BCFC3F466ECB8FACD19ADE57D8699D74E7207D78C6AEDC3799B52A8E0598,FALSE,sig[0:32] is not an X coordinate on the curve +12,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F4160BCFC3F466ECB8FACD19ADE57D8699D74E7207D78C6AEDC3799B52A8E0598,FALSE,sig[0:32] is equal to field size +13,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,667C2F778E0616E611BD0C14B8A600C5884551701A949EF0EBFD72D452D64E84FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141,FALSE,sig[32:64] is equal to curve order diff --git a/bip-schnorr/test-vectors.py b/bip-schnorr/test-vectors.py index 45c8b1c..52e3b05 100644 --- a/bip-schnorr/test-vectors.py +++ b/bip-schnorr/test-vectors.py @@ -26,7 +26,7 @@ def vector1(): return (bytes_from_int(seckey), pubkey, msg, sig, "TRUE", None) def vector2(): - seckey = 0xC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B14E5C7 + seckey = 0xC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B14E5C9 msg = bytes_from_int(0x5E2D58D8B3BCDF1ABADEC7829054F90DDA9805AAB56C77333024B9D0A508B75C) sig = schnorr_sign(msg, seckey) @@ -53,7 +53,7 @@ def schnorr_sign_fixed_nonce(msg, seckey0, k): P = point_mul(G, seckey0) seckey = seckey0 if (jacobi(P[1]) == 1) else n - seckey0 R = point_mul(G, k) - e = int_from_bytes(hash_sha256(bytes_from_point(R) + bytes_from_point(P) + msg)) % n + e = int_from_bytes(tagged_hash("BIPSchnorr", bytes_from_point(R) + bytes_from_point(P) + msg)) % n return bytes_from_point(R) + bytes_from_int((k + e * seckey) % n) # Creates a singature with a small x(R) by using k = 1/2 diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 51fd45d..6d05610 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -41,7 +41,7 @@ As a result we choose this combination of technologies: * Taproot's advantages become apparent under the assumption that most applications involve outputs that could be spent by all parties agreeing. That's where '''Schnorr''' signatures come in, as they permit [https://eprint.iacr.org/2018/068 key aggregation]: a public key can be constructed from multiple participant public keys, and which requires cooperation between all participants to sign for. Such multi-party public keys and signatures are indistinguishable from their single-party equivalents. This means that under this Taproot assumption, the all-parties-agree case can be handled using the key-based spending path, which is both private and efficient using Taproot. This can be generalized to arbitrary M-of-N policies, as Schnorr signatures support threshold signing, at the cost of more complex setup protocols. * As Schnorr signatures also permit '''batch validation''', allowing multiple signatures to be validated together more efficiently than validating each one independently, we make sure all parts of the design are compatible with this. * Where unused bits appear as a result of the above changes, they are reserved for mechanisms for '''future extensions'''. As a result, every script in the Merkle tree has an associated version such that new script versions can be introduced with a soft fork while remaining compatible with bip-taproot. Additionally, future soft forks can make use of the currently unused annex in the witness (see [[#Rationale]]). -* While the core semantics of the '''signature hashing algorithm''' are not changed, a number of improvements are included in this proposal. The new signature hashing algorithm fixes the verification capabilities of offline signing devices by including amount and scriptPubKey in the digest, avoids unnecessary hashing, introduces '''tagged hashes''' and defines a default sighash byte. +* While the core semantics of the '''signature hashing algorithm''' are not changed, a number of improvements are included in this proposal. The new signature hashing algorithm fixes the verification capabilities of offline signing devices by including amount and scriptPubKey in the digest, avoids unnecessary hashing, uses '''tagged hashes''' and defines a default sighash byte. Not included in this proposal are additional features like new sighash modes or opcodes that can be included with no loss in effectiveness as a future extension. Also not included is cross-input aggregation, as it [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-March/015838.html interacts] in complex ways with upgrade mechanisms and solutions to that are still [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-October/016461.html in flux]. @@ -49,7 +49,9 @@ Not included in this proposal are additional features like new sighash modes or This section specifies the Taproot consensus rules. Validity is defined by exclusion: a block or transaction is valid if no condition exists that marks it failed. -The notation below follows that of bip-schnorr including the notion of tagged hashes. +The notation below follows that of bip-schnorr. +This includes the notion of tagged hashes which make collisions with existing uses of hash functions in Bitcoin infeasible. +The reason is that so far nowhere in the Bitcoin protocol are hashes used where the input of SHA256 starts with two (non-double) SHA256 hashes. === Script validation rules === -- cgit v1.2.3 From cc962bf84f44a1ac07bdb8c269aee07abde551d4 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Tue, 27 Aug 2019 15:13:08 +0000 Subject: Address sipa's comments --- bip-schnorr.mediawiki | 2 +- bip-taproot.mediawiki | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index ad0b9cf..e96ee44 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -56,7 +56,7 @@ encodings and operations. We choose the ''R''-option to support batch verification. -'''Key prefixing''' When using the verification rule above directly, it is possible for a third party to convert a signature ''(R,s)'' for key ''P'' into a signature ''(R,s + ahash(R || m))'' for key ''P + aG'' and the same message, for any integer ''a''. This is not a concern for Bitcoin currently, as all signature hashes indirectly commit to the public keys. However, this may change with proposals such as SIGHASH_NOINPUT ([https://github.com/bitcoin/bips/blob/master/bip-0118.mediawiki BIP 118]), or when the signature scheme is used for other purposes—especially in combination with schemes like [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki BIP32]'s unhardened derivation. To combat this, we choose ''key prefixed''A limitation of committing to the public key (rather than to a short hash of it, or not at all) is that it removes the ability for public key recovery or verifying signatures against a short public key hash. These constructions are generally incompatible with batch verification. Schnorr signatures; changing the equation to ''sG = R + hash(R || P || m)P''. +'''Key prefixing''' When using the verification rule above directly, it is possible for a third party to convert a signature ''(R,s)'' for key ''P'' into a signature ''(R,s + a⋅hash(R || m))'' for key ''P + aG'' and the same message, for any integer ''a''. This is not a concern for Bitcoin currently, as all signature hashes indirectly commit to the public keys. However, this may change with proposals such as SIGHASH_NOINPUT ([https://github.com/bitcoin/bips/blob/master/bip-0118.mediawiki BIP 118]), or when the signature scheme is used for other purposes—especially in combination with schemes like [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki BIP32]'s unhardened derivation. To combat this, we choose ''key prefixed''A limitation of committing to the public key (rather than to a short hash of it, or not at all) is that it removes the ability for public key recovery or verifying signatures against a short public key hash. These constructions are generally incompatible with batch verification. Schnorr signatures; changing the equation to ''sG = R + hash(R || P || m)P''. '''Encoding R and public key point P''' There exist several possibilities for encoding elliptic curve points: # Encoding the full X and Y coordinates of ''P'' and ''R'', resulting in a 64-byte public key and a 96-byte signature. diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 6d05610..769f13d 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -41,7 +41,7 @@ As a result we choose this combination of technologies: * Taproot's advantages become apparent under the assumption that most applications involve outputs that could be spent by all parties agreeing. That's where '''Schnorr''' signatures come in, as they permit [https://eprint.iacr.org/2018/068 key aggregation]: a public key can be constructed from multiple participant public keys, and which requires cooperation between all participants to sign for. Such multi-party public keys and signatures are indistinguishable from their single-party equivalents. This means that under this Taproot assumption, the all-parties-agree case can be handled using the key-based spending path, which is both private and efficient using Taproot. This can be generalized to arbitrary M-of-N policies, as Schnorr signatures support threshold signing, at the cost of more complex setup protocols. * As Schnorr signatures also permit '''batch validation''', allowing multiple signatures to be validated together more efficiently than validating each one independently, we make sure all parts of the design are compatible with this. * Where unused bits appear as a result of the above changes, they are reserved for mechanisms for '''future extensions'''. As a result, every script in the Merkle tree has an associated version such that new script versions can be introduced with a soft fork while remaining compatible with bip-taproot. Additionally, future soft forks can make use of the currently unused annex in the witness (see [[#Rationale]]). -* While the core semantics of the '''signature hashing algorithm''' are not changed, a number of improvements are included in this proposal. The new signature hashing algorithm fixes the verification capabilities of offline signing devices by including amount and scriptPubKey in the digest, avoids unnecessary hashing, uses '''tagged hashes''' and defines a default sighash byte. +* While the core semantics of the '''signature hashing algorithm''' are not changed, a number of improvements are included in this proposal. The new signature hashing algorithm fixes the verification capabilities of offline signing devices by including amount and scriptPubKey in the digest, avoids unnecessary hashing, uses '''tagged hashes''''''Why use tagged hashes?''' So far, nowhere in the Bitcoin protocol are hashes used where the input of SHA256 starts with two (non-double) SHA256 hashes, making collisions with existing uses of hash functions infeasible. (according to bip-schnorr) and defines a default sighash byte. Not included in this proposal are additional features like new sighash modes or opcodes that can be included with no loss in effectiveness as a future extension. Also not included is cross-input aggregation, as it [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-March/015838.html interacts] in complex ways with upgrade mechanisms and solutions to that are still [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-October/016461.html in flux]. @@ -50,8 +50,6 @@ Not included in this proposal are additional features like new sighash modes or This section specifies the Taproot consensus rules. Validity is defined by exclusion: a block or transaction is valid if no condition exists that marks it failed. The notation below follows that of bip-schnorr. -This includes the notion of tagged hashes which make collisions with existing uses of hash functions in Bitcoin infeasible. -The reason is that so far nowhere in the Bitcoin protocol are hashes used where the input of SHA256 starts with two (non-double) SHA256 hashes. === Script validation rules === -- cgit v1.2.3 From 8fd629c3f9c94c48b3d049ec50d1cbba22b02d3c Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Thu, 29 Aug 2019 20:46:47 +0000 Subject: Fix privkey negation in taproot_sign_key --- bip-taproot.mediawiki | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 769f13d..d720be1 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -200,10 +200,10 @@ See the code below: def taproot_sign_key(script_tree, internal_privkey, hash_type): + _, h = taproot_tree_helper(script_tree) internal_pubkey, is_y_qresidue = internal_privkey.pubkey_gen() - if is_y_qresidue: + if not is_y_qresidue: internal_privkey = internal_privkey.negate() - _, h = taproot_tree_helper(script_tree) t = tagged_hash("TapTweak", internal_pubkey.get_bytes() + h) output_privkey = internal_privkey.tweak_add(t) sig = output_privkey.schnorr_sign(sighash(hash_type)) -- cgit v1.2.3 From efa556aa063c9222a9185cb8a9110ff191614f08 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Thu, 22 Aug 2019 10:11:10 +1000 Subject: public keys aren't identical --- bip-schnorr.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index e96ee44..b921b18 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -40,7 +40,7 @@ made: [[File:bip-schnorr/speedup-batch.png|frame|This graph shows the ratio between the time it takes to verify ''n'' signatures individually and to verify a batch of ''n'' signatures. This ratio goes up logarithmically with the number of signatures, or in other words: the total time to verify ''n'' signatures grows with ''O(n / log n)''.]] -By reusing the same curve as Bitcoin has used for ECDSA, private and public keys remain identical for Schnorr signatures, and we avoid introducing new assumptions about elliptic curve group security. +By reusing the same curve as Bitcoin has used for ECDSA, we are able to retain existing mechanisms for choosing private and public keys, and we avoid introducing new assumptions about elliptic curve group security. == Description == -- cgit v1.2.3 From a3f74a204e55d708e40f35761b1ea9b302cb195b Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Thu, 22 Aug 2019 10:20:12 +1000 Subject: pk not p --- bip-schnorr.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index b921b18..4de2596 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -87,7 +87,7 @@ For example, without tagged hashing a bip-schnorr signature could also be valid This proposal suggests to include the tag by prefixing the hashed data with ''SHA256(tag) || SHA256(tag)''. Because this is a 64-byte long context-specific constant, optimized implementations are possible (identical to SHA256 itself, but with a modified initial state). Using SHA256 of the tag name itself is reasonably simple and efficient for implementations that don't choose to use the optimization. -'''Final scheme''' As a result, our final scheme ends up using public key ''pk'' which is the X coordinate of a point ''P'' on the curve whose Y coordinate is a quadratic residue and signatures ''(r,s)'' where ''r'' is the X coordinate of a point ''R'' whose Y coordinate is a quadratic residue. The signature satisfies ''sG = R + tagged_hash(r || p || m)P''. +'''Final scheme''' As a result, our final scheme ends up using public key ''pk'' which is the X coordinate of a point ''P'' on the curve whose Y coordinate is a quadratic residue and signatures ''(r,s)'' where ''r'' is the X coordinate of a point ''R'' whose Y coordinate is a quadratic residue. The signature satisfies ''sG = R + tagged_hash(r || pk || m)P''. === Specification === -- cgit v1.2.3 From 4e13ec730162131802dda081569cea009ea7eb4c Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Thu, 22 Aug 2019 11:06:19 +1000 Subject: make secret key a 32-byte array called sk, introduce pubkey() --- bip-schnorr.mediawiki | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 4de2596..8e53403 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -117,13 +117,16 @@ The following convention is used, with constants as defined for secp256k1: ** The function ''point(x)'', where ''x'' is a 32-byte array, returns the point ''P = lift_x(int(x))''. ** The function ''hashtag(x)'' where ''tag'' is a UTF-8 encoded tag name and ''x'' is a byte array returns the 32-byte hash ''SHA256(SHA256(tag) || SHA256(tag) || x)''. ** The function ''jacobi(x)'', where ''x'' is an integer, returns the [https://en.wikipedia.org/wiki/Jacobi_symbol Jacobi symbol] of ''x / p''. It is equal to ''x(p-1)/2 mod p'' ([https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion])For points ''P'' on the secp256k1 curve it holds that ''jacobi(y(P)) ≠ 0''.. +** The function ''pubkey(x)'', where ''x'' is a 32-byte array, returns ''bytes(dG)'' where ''d = int(x) mod n''. -=== Public Key Generation === +==== Public Key Generation ==== Input: -* The secret key ''d'': an integer in the range ''1..n-1'' chosen uniformly at random. +* The secret key ''sk'': a 32-byte array, generated uniformly at random -The public key corresponding to secret key ''d'' is ''bytes(dG)''. +To generate the corresponding public key: +* Fail if ''int(sk) = 0'' or ''int(sk) >= n'' +* The public key corresponding to secret key ''sk'' is ''pubkey(sk)''. Alternatively, the public key can be created according to [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki BIP32] which describes the derivation of 33-byte compressed public keys. In order to translate such public keys into bip-schnorr compatible keys, the first byte must be dropped. @@ -165,11 +168,13 @@ All provided signatures are valid with overwhelming probability if and only if t ==== Signing ==== Input: -* The secret key ''d' '': an integer in the range ''1..n-1'' +* The secret key ''sk'': a 32-byte array * The message ''m'': a 32-byte array -To sign ''m'' for public key ''bytes(dG)'': -* Let ''P = dG'' +To sign ''m'' for public key ''pubkey(sk)'': +* Let ''d' = int(sk)'' +* Fail if ''d' = 0'' or ''d' >= n'' +* Let ''P = d'G'' * Let ''d = d' '' if ''jacobi(y(P)) = 1'', otherwise let ''d = n - d' ''. * Let ''k' = int(hashBIPSchnorrDerive(bytes(d) || m)) mod n''Note that in general, taking the output of a hash function modulo the curve order will produce an unacceptably biased result. However, for the secp256k1 curve, the order is sufficiently close to ''2256'' that this bias is not observable (''1 - n / 2256'' is around ''1.27 * 2-128'').. * Fail if ''k' = 0''. -- cgit v1.2.3 From 8ffea86023048b674c8c540c80ff1ee24ec18bee Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Fri, 23 Aug 2019 15:19:28 +1000 Subject: use p for taproot internal key --- bip-taproot.mediawiki | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index d720be1..7d58b16 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -64,7 +64,7 @@ The following rules only apply when such an output is being spent. Any other out * If there are at least two witness elements left, script path spending is used: ** Call the second-to-last stack element ''s'', the script. ** The last stack element is called the control block ''c'', and must have length ''33 + 32m'', for a value of ''m'' that is an integer between 0 and 32, inclusive. Fail if it does not have such a length. -** Let ''P = point(c[1:33])'' where ''point'' is defined as in bip-schnorr. Fail if this point is not on the curve. +** Let ''p = c[1:33]'' and let ''P = point(p)'' where ''point'' is defined as in bip-schnorr. Fail if this point is not on the curve. ** Let ''l = c[0] & 0xfe'', the leaf version'''What is the purpose of the first byte of the control block?''' The first byte of the control block has three distinct functions: * The low bit is used to denote whether the ''Q'' point's Y coordinate is a quadratic residue.'''Why is the quadratic residuosity of the output public key's Y coordinate required in a script path spend?''' The ''point'' function always constructs a point with Y coordinate having that property, but because ''Q'' is constructed by adding the taproot tweak to the internal public key ''P'', it cannot easily be guaranteed that ''Q'' in fact has such a Y coordinate. We can not ignore the Y coordinate because it would prevent batch verification. Trying out multiple internal keys until there's such a ''Q'' is possible but undesirable and unnecessary since this information about the Y coordinate only consumes an unused bit. * By keeping the top two bits set to true, it can be guaranteed that scripts can be recognized without knowledge of the UTXO being spent, simplifying analysis. This is because such values cannot occur as first byte of the final stack element in either P2WPKH or P2WSH spends. @@ -76,13 +76,13 @@ The following rules only apply when such an output is being spent. Any other out *** Let ''kj+1 depend on whether ''kj < ej'' (lexicographically)'''Why are child elements sorted before hashing in the Merkle tree?''' By doing so, it is not necessary to reveal the left/right directions along with the hashes in revealed Merkle branches. This is possible because we do not actually care about the position of specific scripts in the tree; only that they are actually committed to.: **** If ''kj < ej'': ''kj+1 = hashTapBranch(kj || ej)'''''Why not use a more efficient hash construction for inner Merkle nodes?''' The chosen construction does require two invocations of the SHA256 compression functions, one of which can be avoided in theory (see BIP98). However, it seems preferable to stick to constructions that can be implemented using standard cryptographic primitives, both for implementation simplicity and analyzability. If necessary, a significant part of the second compression function can be optimized out by [https://github.com/bitcoin/bitcoin/pull/13191 specialization] for 64-byte inputs.. **** If ''kj ≥ ej'': ''kj+1 = hashTapBranch(ej || kj)''. -** Let ''t = hashTapTweak(bytes(P) || km) = hashTapTweak(c[1:33] || km)''. +** Let ''t = hashTapTweak(p || km)''. ** If ''t ≥ 0xFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141'' (order of secp256k1), fail. ** Let ''Q = point(q) if (c[0] & 1) = 1 and -point(q) otherwise''. Fail if this point is not on the curve. ** If ''Q ≠ P + int(t)G'', fail. ** Execute the script, according to the applicable script rules'''What are the applicable script rules in script path spends?''' Bip-tapscript specifies validity rules that apply if the leaf version is ''0xc0'', but future proposals can introduce rules for other leaf versions., using the witness stack elements excluding the script ''s'', the control block ''c'', and the annex ''a'' if present, as initial stack. -''q'' is referred to as ''taproot output key'' and ''c[1:33]'' as ''taproot internal key''. +''q'' is referred to as ''taproot output key'' and ''p'' as ''taproot internal key''. === Signature validation rules === -- cgit v1.2.3 From 0d04e41e2f5a588300e5c6603f40e5538e1e0e54 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Fri, 23 Aug 2019 15:42:00 +1000 Subject: key gen, verify, sign in intro --- bip-schnorr.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 8e53403..9c80cd5 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -91,7 +91,7 @@ This proposal suggests to include the tag by prefixing the hashed data with ''SH === Specification === -We first describe the verification algorithm, and then the signature algorithm. +We first describe the key generation algorithm, then the verification algorithm, and then the signature algorithm. The following convention is used, with constants as defined for secp256k1: * Lowercase variables represent integers or byte arrays. -- cgit v1.2.3 From 4491902569315b375f5bd41e66d0a21a4e570852 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Sat, 24 Aug 2019 15:08:05 +1000 Subject: note about pubkey collision --- bip-schnorr.mediawiki | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 9c80cd5..bb2f9dc 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -128,6 +128,8 @@ To generate the corresponding public key: * Fail if ''int(sk) = 0'' or ''int(sk) >= n'' * The public key corresponding to secret key ''sk'' is ''pubkey(sk)''. +Note that the two secret keys ''sk'' and ''bytes(n-int(sk))'' will generate the same public key. + Alternatively, the public key can be created according to [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki BIP32] which describes the derivation of 33-byte compressed public keys. In order to translate such public keys into bip-schnorr compatible keys, the first byte must be dropped. -- cgit v1.2.3 From 29037bd1230d235129f4673ddac5db845b294bb5 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Sun, 8 Sep 2019 16:38:55 +0200 Subject: Add a footnote about 32-byte security --- bip-schnorr.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index bb2f9dc..de55ded 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -79,7 +79,7 @@ For ''P'' the speed of signing and verification does not significantly differ be It is important to not mix up the 32-byte bip-schnorr public key format and other existing public key formats (e.g. encodings used in Bitcoin's ECDSA). Concretely, a verifier should only accept 32-byte public keys and not, for example, convert a 33-byte public key by throwing away the first byte. Otherwise, two public keys would be valid for a single signature which can result in subtle malleability issues (although this type of malleability already exists in the case of ECDSA signatures). -Implicit Y coordinates are not a reduction in security when expressed as the number of elliptic curve operations an attacker is expected to perform to compute the secret key. An attacker can normalize any given public key to a point whose Y coordinate is a quadratic residue by negating the point if necessary. This is just a subtraction of field elements and not an elliptic curve operation. +Implicit Y coordinates are not a reduction in security when expressed as the number of elliptic curve operations an attacker is expected to perform to compute the secret key. An attacker can normalize any given public key to a point whose Y coordinate is a quadratic residue by negating the point if necessary. This is just a subtraction of field elements and not an elliptic curve operationThis can be formalized by a simple reduction that reduces an attack on Schnorr signatures with implicit Y coordinates to an attack to Schnorr signatures with explicit Y coordinates. The reduction works by reencoding public keys and negating the result of the hash function, which is modeled as random oracle, whenever the challenge public key has an explicit Y coordinate that is not a quadratic residue.. '''Tagged Hashes''' Cryptographic hash functions are used for multiple purposes in the specification below and in Bitcoin in general. To make sure hashes used in one context can't be reinterpreted in another one, hash functions can be tweaked with a context-dependent tag name, in such a way that collisions across contexts can be assumed to be infeasible. Such collisions obviously can not be ruled out completely, but only for schemes using tagging with a unique name. As for other schemes collisions are at least less likely with tagging than without. -- cgit v1.2.3 From 204b7f13a0cb3d33506a7369e1f131d9f30e98d2 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Wed, 5 Jun 2019 13:59:09 +0000 Subject: Prescribe that a taproot output key should always have a taproot commitment --- bip-taproot.mediawiki | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 7d58b16..bd9de86 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -162,6 +162,18 @@ Satisfying any of these conditions is sufficient to spend the output. * When deciding between scripts with conditionals (OP_IF etc.) and splitting them up into multiple scripts (each corresponding to one execution path through the original script), it is generally preferable to pick the latter. * When a single condition requires signatures with multiple keys, key aggregation techniques like MuSig can be used to combine them into a single key. The details are out of scope for this document, but note that this may complicate the signing procedure. * If one or more of the spending conditions consist of just a single key (after aggregation), the most likely one should be made the internal key. If no such condition exists, it may be worthwhile adding one that consists of an aggregation of all keys participating in all scripts combined; effectively adding an "everyone agrees" branch. If that is inacceptable, pick as internal key a point with unknown discrete logarithm. One example of such a point is ''H = point(0x0250929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0)'' which is [https://github.com/ElementsProject/secp256k1-zkp/blob/11af7015de624b010424273be3d91f117f172c82/src/modules/rangeproof/main_impl.h#L16 constructed] by taking the hash of the standard uncompressed encoding of secp256k1 generator ''G'' as X coordinate. In order to avoid leaking the information that key path spending is not possible it is recommended to pick a fresh integer ''r'' in the range ''0...n-1'' uniformly at random and use ''H + rG'' as internal key. It is possible to prove that this internal key is does not have a known discrete logarithm with respect to ''G'' by revealing ''r'' to a verifier who can then reconstruct how the internal key was created. +* If the spending conditions do not require a script path, the output key should commit to an unspendable script path instead of having no script path. This can be achieved by computing the output key point as ''Q = P + int(hashTapTweak(bytes(P)))G''. '''Why should the output key always have a taproot commitment, even if there is no script path?''' +If the taproot output key is an aggregate of keys, there is the possibility for a malicious party to add a script path without being noticed by the other parties. +This allows to bypass the multiparty policy and to steal the coin. +MuSig key aggregation does not have this issue because it already causes the internal key to be randomized. + +The attack works as follows: Assume Alice and Mallory want to aggregate their keys into a taproot output key without a script path. +In order to prevent key cancellation and related attacks they use [https://eprint.iacr.org/2018/483.pdf MSDL-pop] instead of MuSig. +The MSDL-pop protocol requires all parties to provide a proof of possession of their corresponding private key and the aggregated key is just the sum of the individual keys. +After Mallory receives Alice's key ''A'', Mallory creates ''M = M0 + int(t)G'' where ''M0'' is Mallory's original key and ''t'' allows a script path spend with internal key ''P = A + M0'' and a script that only contains Mallory's key. +Mallory sends a proof of possession of ''M'' to Alice and both parties compute output key ''Q = A + M = P + int(t)G''. +Alice will not be able to notice the script path, but Mallory can unilaterally spend any coin with output key ''Q''. + * The remaining scripts should be organized into the leaves of a binary tree. This can be a balanced tree if each of the conditions these scripts correspond to are equally likely. If probabilities for each condition are known, consider constructing the tree as a Huffman tree. '''Computing the output script''' Once the spending conditions are split into an internal key internal_pubkey and a binary tree whose leaves are (leaf_version, script) tuples, the following Python3 algorithm can be used to compute the output script. In the code below, ser_script prefixes its input with a CCompactSize-encoded length. Public key objects hold 32-byte public keys according to bip-schnorr, have a method get_bytes to get the byte array and a method tweak_add which returns a new public key corresponding to the sum of the public key point and a multiple of the secp256k1 generator (similar to BIP32's derivation). The second return value of tweak_add is a boolean indicating the quadratic residuosity of the Y coordinate of the resulting point. tagged_hash computes the tagged hash according to bip-schnorr. @@ -184,7 +196,11 @@ def taproot_output_script(internal_pubkey, script_tree): script_tree is either: - a (leaf_version, script) tuple (leaf_version is 0xc0 for bip-tapscript scripts) - a list of two elements, each with the same structure as script_tree itself""" - _, h = taproot_tree_helper(script_tree) + - None + if script_tree is None: + h = b'' + else: + _, h = taproot_tree_helper(script_tree) t = tagged_hash("TapTweak", internal_pubkey.get_bytes() + h) assert int.from_bytes(t, 'big') < SECP256K1_ORDER output_pubkey, _ = internal_pubkey.tweak_add(t) -- cgit v1.2.3 From 2b987b57112af9767f888ed65b17c894ee4b34a6 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Sun, 8 Sep 2019 16:38:15 +0200 Subject: Rework Applications section --- bip-schnorr.mediawiki | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index de55ded..f88660e 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -8,17 +8,17 @@ Post-History: 2018-07-06: https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-July/016203.html [bitcoin-dev] Schnorr signatures BIP -==Introduction== +== Introduction == -===Abstract=== +=== Abstract === This document proposes a standard for 64-byte Schnorr signatures over the elliptic curve ''secp256k1''. -===Copyright=== +=== Copyright === This document is licensed under the 2-clause BSD license. -===Motivation=== +=== Motivation === Bitcoin has traditionally used [https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm ECDSA] signatures over the [http://www.secg.org/sec2-v2.pdf secp256k1 curve] for authenticating @@ -205,13 +205,13 @@ Many techniques are known for optimizing elliptic curve implementations. Several There are several interesting applications beyond simple signatures. While recent academic papers claim that they are also possible with ECDSA, consensus support for Schnorr signature verification would significantly simplify the constructions. -===Multisignatures and Threshold Signatures=== +=== Multisignatures and Threshold Signatures === -By means of an interactive scheme such as [https://eprint.iacr.org/2018/068 MuSig], participants can produce a combined public key which they can jointly sign for. This allows n-of-n multisignatures which, from a verifier's perspective, are no different from ordinary signatures, giving improved privacy and efficiency versus ''CHECKMULTISIG'' or other means. +By means of an interactive scheme such as [https://eprint.iacr.org/2018/068 MuSig], participants can aggregate their public keys into a single public key which they can jointly sign for. This allows n-of-n multisignatures which, from a verifier's perspective, are no different from ordinary signatures, giving improved privacy and efficiency versus ''CHECKMULTISIG'' or other means. -Further, by combining Schnorr signatures with [https://link.springer.com/content/pdf/10.1007/3-540-46766-1_9.pdf Pedersen Secret Sharing], it is possible to obtain [http://cacr.uwaterloo.ca/techreports/2001/corr2001-13.ps an interactive threshold signature scheme] that ensures that signatures can only be produced by arbitrary but predetermined sets of signers. For example, k-of-n threshold signatures can be realized this way. Furthermore, it is possible to replace the combination of participant keys in this scheme with MuSig, though the security of that combination still needs analysis. +Moreover, Schnorr signatures are compatible with [https://web.archive.org/web/20031003232851/http://www.research.ibm.com/security/dkg.ps distributed key generation], which enables interactive threshold signatures schemes, e.g., the schemes described by [http://cacr.uwaterloo.ca/techreports/2001/corr2001-13.ps Stinson and Strobl (2001)] or [https://web.archive.org/web/20060911151529/http://theory.lcs.mit.edu/~stasio/Papers/gjkr03.pdf Genaro, Jarecki and Krawczyk (2003)]. These protocols make it possible to realize k-of-n threshold signatures, which ensure that any subset of size k of the set of n signers can sign but no subset of size less than k can produce a valid Schnorr signature. However, the practicality of the existing schemes is limited: most schemes in the literature have been proven secure only for the case k < n/2, are not secure when used concurrently in multiple sessions, or require a reliable broadcast mechanism to be secure. Further research is necessary to improve this situation. -===Adaptor Signatures=== +=== Adaptor Signatures === [https://download.wpsoftware.net/bitcoin/wizardry/mw-slides/2018-05-18-l2/slides.pdf Adaptor signatures] can be produced by a signer by offsetting his public nonce with a known point ''T = tG'', but not offsetting his secret nonce. A correct signature (or partial signature, as individual signers' contributions to a multisignature are called) on the same message with same nonce will then be equal to the adaptor signature offset by ''t'', meaning that learning ''t'' is equivalent to learning a correct signature. @@ -219,12 +219,11 @@ This can be used to enable atomic swaps or even [https://eprint.iacr.org/2018/47 Adaptor signatures, beyond the efficiency and privacy benefits of encoding script semantics into constant-sized signatures, have additional benefits over traditional hash-based payment channels. Specifically, the secret values ''t'' may be reblinded between hops, allowing long chains of transactions to be made atomic while even the participants cannot identify which transactions are part of the chain. Also, because the secret values are chosen at signing time, rather than key generation time, existing outputs may be repurposed for different applications without recourse to the blockchain, even multiple times. -===Blind Signatures=== +=== Blind Signatures === -Schnorr signatures admit a very [https://www.math.uni-frankfurt.de/~dmst/research/papers/schnorr.blind_sigs_attack.2001.pdf simple '''blind signature''' construction] which is a signature that a signer produces at the behest of another party without learning what he has signed. -These can for example be used in [https://github.com/jonasnick/scriptless-scripts/blob/blind-swaps/md/partially-blind-swap.md Partially Blind Atomic Swaps], a construction to enable transferring of coins, mediated by an untrusted escrow agent, without connecting the transactors in the public blockchain transaction graph. +A blind signature protocol is an interactive protocol that enables a signer to sign a message at the behest of another party without learning the signer learning any information about the signed message or the signature. Schnorr signatures admit a very [https://www.math.uni-frankfurt.de/~dmst/research/papers/schnorr.blind_sigs_attack.2001.pdf simple blind signature scheme] which is however insecure because it's vulnerable to [https://www.iacr.org/archive/crypto2002/24420288/24420288.pdf Wagner's attack]. A known mitigation is to let the signer abort a signing session with a certain probability, and the resulting scheme can be [https://eprint.iacr.org/2019/877 proven secure under non-standard cryptographic assumptions]. -While the traditional Schnorr blind signatures are vulnerable to [https://www.iacr.org/archive/crypto2002/24420288/24420288.pdf Wagner's attack], there are [https://www.math.uni-frankfurt.de/~dmst/teaching/SS2012/Vorlesung/EBS5.pdf a number of mitigations] which allow them to be usable in practice without any known attacks. Nevertheless, more analysis is required to be confident about the security of the blind signature scheme. +Blind Schnorr signatures could for example be used in [https://github.com/jonasnick/scriptless-scripts/blob/blind-swaps/md/partially-blind-swap.md Partially Blind Atomic Swaps], a construction to enable transferring of coins, mediated by an untrusted escrow agent, without connecting the transactors in the public blockchain transaction graph. == Test Vectors and Reference Code == -- cgit v1.2.3 From a5112f9f01e6fd63e6985e63e655ea54d2e69cab Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Fri, 10 May 2019 12:11:07 +0000 Subject: Move plain public key in output rationale to design section Rebased by Pieter Wuille --- bip-taproot.mediawiki | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index bd9de86..d92f955 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -42,6 +42,7 @@ As a result we choose this combination of technologies: * As Schnorr signatures also permit '''batch validation''', allowing multiple signatures to be validated together more efficiently than validating each one independently, we make sure all parts of the design are compatible with this. * Where unused bits appear as a result of the above changes, they are reserved for mechanisms for '''future extensions'''. As a result, every script in the Merkle tree has an associated version such that new script versions can be introduced with a soft fork while remaining compatible with bip-taproot. Additionally, future soft forks can make use of the currently unused annex in the witness (see [[#Rationale]]). * While the core semantics of the '''signature hashing algorithm''' are not changed, a number of improvements are included in this proposal. The new signature hashing algorithm fixes the verification capabilities of offline signing devices by including amount and scriptPubKey in the digest, avoids unnecessary hashing, uses '''tagged hashes''''''Why use tagged hashes?''' So far, nowhere in the Bitcoin protocol are hashes used where the input of SHA256 starts with two (non-double) SHA256 hashes, making collisions with existing uses of hash functions infeasible. (according to bip-schnorr) and defines a default sighash byte. +* The '''public key is directly included in the output''' in contrast to typical earlier constructions which store a hash of the public key or script in the output. This has the same cost for senders and is more space efficient overall if the key-based spending path is taken. '''Why is the public key directly included in the output?''' While typical earlier constructions store a hash of a script or a public key in the output, this is rather wasteful when a public key is always involved. To guarantee batch verifiability, ''q'' must be known to every verifier, and thus only revealing its hash as an output would imply adding an additional 32 bytes to the witness. Furthermore, to maintain [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2016-January/012198.html 128-bit collision security] for outputs, a 256-bit hash would be required anyway, which is comparable in size (and thus in cost for senders) to revealing the public key directly. While the usage of public key hashes is often said to protect against ECDLP breaks or quantum computers, this protection is very weak at best: transactions are not protected while being confirmed, and a very [https://twitter.com/pwuille/status/1108097835365339136 large portion] of the currency's supply is not under such protection regardless. Actual resistance to such systems can be introduced by relying on different cryptographic assumptions, but this proposal focuses on improvements that do not change the security model. Note that using P2SH-wrapped outputs only have 80-bit collision security. This is considered low, and is relevant whenever the output includes data from more than a single party (public keys, hashes, ...). . Not included in this proposal are additional features like new sighash modes or opcodes that can be included with no loss in effectiveness as a future extension. Also not included is cross-input aggregation, as it [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-March/015838.html interacts] in complex ways with upgrade mechanisms and solutions to that are still [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-October/016461.html in flux]. @@ -56,7 +57,7 @@ The notation below follows that of bip-schnorr. A Taproot output is a SegWit output (native or P2SH-nested, see [https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki BIP141]) with version number 1, and a 32-byte witness program. The following rules only apply when such an output is being spent. Any other outputs, including version 1 outputs with lengths other than 32 bytes, remain unencumbered. -* Let ''q'' be the 32-byte array containing the witness program (second push in scriptPubKey or P2SH redeemScript) which represents a public key according to bip-schnorr '''Why is the public key directly included in the output?''' While typical earlier constructions store a hash of a script or a public key in the output, this is rather wasteful when a public key is always involved. To guarantee batch verifiability, ''q'' must be known to every verifier, and thus only revealing its hash as an output would imply adding an additional 32 bytes to the witness. Furthermore, to maintain [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2016-January/012198.html 128-bit collision security] for outputs, a 256-bit hash would be required anyway, which is comparable in size (and thus in cost for senders) to revealing the public key directly. While the usage of public key hashes is often said to protect against ECDLP breaks or quantum computers, this protection is very weak at best: transactions are not protected while being confirmed, and a very [https://twitter.com/pwuille/status/1108097835365339136 large portion] of the currency's supply is not under such protection regardless. Actual resistance to such systems can be introduced by relying on different cryptographic assumptions, but this proposal focuses on improvements that do not change the security model. Note that using P2SH-wrapped outputs only have 80-bit collision security. This is considered low, and is relevant whenever the output includes data from more than a single party (public keys, hashes, ...). . +* Let ''q'' be the 32-byte array containing the witness program (second push in scriptPubKey or P2SH redeemScript) which represents a public key according to bip-schnorr. * Fail if the witness stack has 0 elements. * If there are at least two witness elements, and the first byte of the last element is 0x50'''Why is the first byte of the annex 0x50?''' Like the 0xc0-0xc1 constants, 0x50 is chosen as it could not be confused with a valid P2WPKH or P2WSH spending. As the control block's initial byte's lowest bit is used to indicate the public key's Y quadratic residuosity, each script version needs two subsequence byte values that are both not yet used in P2WPKH or P2WSH spending. To indicate the annex, only an "unpaired" available byte is necessary like 0x50. This choice maximizes the available options for future script versions., this last element is called ''annex'' ''a'''''What is the purpose of the annex?''' The annex is a reserved space for future extensions, such as indicating the validation costs of computationally expensive new opcodes in a way that is recognizable without knowing the outputs being spent. Until the meaning of this field is defined by another softfork, users SHOULD NOT include annex in transactions, or it may lead to PERMANENT FUND LOSS. and is removed from the witness stack. The annex (or the lack of thereof) is always covered by the transaction digest and contributes to transaction weight, but is otherwise ignored during taproot validation. * If there is exactly one element left in the witness stack, key path spending is used: -- cgit v1.2.3 From 8886eb40719f9c716cb00186b2c85582bc80546c Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 10 Sep 2019 16:24:07 -0700 Subject: Address some nits --- bip-schnorr.mediawiki | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index f88660e..39e7b43 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -221,9 +221,9 @@ Adaptor signatures, beyond the efficiency and privacy benefits of encoding scrip === Blind Signatures === -A blind signature protocol is an interactive protocol that enables a signer to sign a message at the behest of another party without learning the signer learning any information about the signed message or the signature. Schnorr signatures admit a very [https://www.math.uni-frankfurt.de/~dmst/research/papers/schnorr.blind_sigs_attack.2001.pdf simple blind signature scheme] which is however insecure because it's vulnerable to [https://www.iacr.org/archive/crypto2002/24420288/24420288.pdf Wagner's attack]. A known mitigation is to let the signer abort a signing session with a certain probability, and the resulting scheme can be [https://eprint.iacr.org/2019/877 proven secure under non-standard cryptographic assumptions]. +A blind signature protocol is an interactive protocol that enables a signer to sign a message at the behest of another party without learning any information about the signed message or the signature. Schnorr signatures admit a very [https://www.math.uni-frankfurt.de/~dmst/research/papers/schnorr.blind_sigs_attack.2001.pdf simple blind signature scheme] which is however insecure because it's vulnerable to [https://www.iacr.org/archive/crypto2002/24420288/24420288.pdf Wagner's attack]. A known mitigation is to let the signer abort a signing session with a certain probability, and the resulting scheme can be [https://eprint.iacr.org/2019/877 proven secure under non-standard cryptographic assumptions]. -Blind Schnorr signatures could for example be used in [https://github.com/jonasnick/scriptless-scripts/blob/blind-swaps/md/partially-blind-swap.md Partially Blind Atomic Swaps], a construction to enable transferring of coins, mediated by an untrusted escrow agent, without connecting the transactors in the public blockchain transaction graph. +Blind Schnorr signatures could for example be used in [https://github.com/ElementsProject/scriptless-scripts/blob/master/md/partially-blind-swap.md Partially Blind Atomic Swaps], a construction to enable transferring of coins, mediated by an untrusted escrow agent, without connecting the transactors in the public blockchain transaction graph. == Test Vectors and Reference Code == -- cgit v1.2.3 From 65a4f1deb8ea1aafdbb2c89332e3358db521cdd1 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Thu, 22 Aug 2019 12:26:57 +0000 Subject: Mention SHA256 block size Rebased by Pieter Wuille --- bip-schnorr.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 39e7b43..e1fe634 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -85,7 +85,7 @@ Implicit Y coordinates are not a reduction in security when expressed as the num For example, without tagged hashing a bip-schnorr signature could also be valid for a signature scheme where the only difference is that the arguments to the hash function are reordered. Worse, if the bip-schnorr nonce derivation function was copied or independently created, then the nonce could be accidentally reused in the other scheme leaking the private key. -This proposal suggests to include the tag by prefixing the hashed data with ''SHA256(tag) || SHA256(tag)''. Because this is a 64-byte long context-specific constant, optimized implementations are possible (identical to SHA256 itself, but with a modified initial state). Using SHA256 of the tag name itself is reasonably simple and efficient for implementations that don't choose to use the optimization. +This proposal suggests to include the tag by prefixing the hashed data with ''SHA256(tag) || SHA256(tag)''. Because this is a 64-byte long context-specific constant and the ''SHA256'' block size is also 64 bytes, optimized implementations are possible (identical to SHA256 itself, but with a modified initial state). Using SHA256 of the tag name itself is reasonably simple and efficient for implementations that don't choose to use the optimization. '''Final scheme''' As a result, our final scheme ends up using public key ''pk'' which is the X coordinate of a point ''P'' on the curve whose Y coordinate is a quadratic residue and signatures ''(r,s)'' where ''r'' is the X coordinate of a point ''R'' whose Y coordinate is a quadratic residue. The signature satisfies ''sG = R + tagged_hash(r || pk || m)P''. -- cgit v1.2.3 From b78b6de4fd432c735ee796574d5843f73dcd0bf7 Mon Sep 17 00:00:00 2001 From: Bryan Bishop Date: Mon, 16 Sep 2019 18:47:54 -0500 Subject: bip-taproot: fix small typo (is does not) --- bip-taproot.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index d92f955..76c23dc 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -162,7 +162,7 @@ Satisfying any of these conditions is sufficient to spend the output. '''Initial steps''' The first step is determining what the internal key and the organization of the rest of the scripts should be. The specifics are likely application dependent, but here are some general guidelines: * When deciding between scripts with conditionals (OP_IF etc.) and splitting them up into multiple scripts (each corresponding to one execution path through the original script), it is generally preferable to pick the latter. * When a single condition requires signatures with multiple keys, key aggregation techniques like MuSig can be used to combine them into a single key. The details are out of scope for this document, but note that this may complicate the signing procedure. -* If one or more of the spending conditions consist of just a single key (after aggregation), the most likely one should be made the internal key. If no such condition exists, it may be worthwhile adding one that consists of an aggregation of all keys participating in all scripts combined; effectively adding an "everyone agrees" branch. If that is inacceptable, pick as internal key a point with unknown discrete logarithm. One example of such a point is ''H = point(0x0250929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0)'' which is [https://github.com/ElementsProject/secp256k1-zkp/blob/11af7015de624b010424273be3d91f117f172c82/src/modules/rangeproof/main_impl.h#L16 constructed] by taking the hash of the standard uncompressed encoding of secp256k1 generator ''G'' as X coordinate. In order to avoid leaking the information that key path spending is not possible it is recommended to pick a fresh integer ''r'' in the range ''0...n-1'' uniformly at random and use ''H + rG'' as internal key. It is possible to prove that this internal key is does not have a known discrete logarithm with respect to ''G'' by revealing ''r'' to a verifier who can then reconstruct how the internal key was created. +* If one or more of the spending conditions consist of just a single key (after aggregation), the most likely one should be made the internal key. If no such condition exists, it may be worthwhile adding one that consists of an aggregation of all keys participating in all scripts combined; effectively adding an "everyone agrees" branch. If that is inacceptable, pick as internal key a point with unknown discrete logarithm. One example of such a point is ''H = point(0x0250929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0)'' which is [https://github.com/ElementsProject/secp256k1-zkp/blob/11af7015de624b010424273be3d91f117f172c82/src/modules/rangeproof/main_impl.h#L16 constructed] by taking the hash of the standard uncompressed encoding of secp256k1 generator ''G'' as X coordinate. In order to avoid leaking the information that key path spending is not possible it is recommended to pick a fresh integer ''r'' in the range ''0...n-1'' uniformly at random and use ''H + rG'' as internal key. It is possible to prove that this internal key does not have a known discrete logarithm with respect to ''G'' by revealing ''r'' to a verifier who can then reconstruct how the internal key was created. * If the spending conditions do not require a script path, the output key should commit to an unspendable script path instead of having no script path. This can be achieved by computing the output key point as ''Q = P + int(hashTapTweak(bytes(P)))G''. '''Why should the output key always have a taproot commitment, even if there is no script path?''' If the taproot output key is an aggregate of keys, there is the possibility for a malicious party to add a script path without being noticed by the other parties. This allows to bypass the multiparty policy and to steal the coin. -- cgit v1.2.3 From f5c728ff82ddeae65fdc7d60983586696b829bf5 Mon Sep 17 00:00:00 2001 From: JamesC Date: Mon, 16 Sep 2019 21:59:54 +0200 Subject: Removed reference to 0xc1 leaf version. No longer necessary with 32B pubkeys. --- bip-tapscript.mediawiki | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index af46afd..603990e 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -47,7 +47,7 @@ The rules below only apply when validating a transaction input for which all of * The transaction output is a '''segregated witness spend''' (i.e., either the scriptPubKey or BIP16 redeemScript is a witness program as defined in BIP141). * It is a '''taproot spend''' as defined in bip-taproot (i.e., the witness version is 1, the witness program is 32 bytes). * It is a '''script path spend''' as defined in bip-taproot (i.e., after removing the optional annex from the witness stack, two or more stack elements remain). -* The leaf version is ''0xc0'' (i.e. the first byte of the last witness element after removing the optional annex is ''0xc0'' or ''0xc1'')'''How is the ''0xc0'' constant chosen?''' Following the guidelines in bip-taproot, by choosing a value having the two top bits set, tapscript spends are identifiable even without access to the UTXO being spent., marking it as a '''tapscript spend'''. +* The leaf version is ''0xc0'' (i.e. the first byte of the last witness element after removing the optional annex is ''0xc0'')'''How is the ''0xc0'' constant chosen?''' Following the guidelines in bip-taproot, by choosing a value having the two top bits set, tapscript spends are identifiable even without access to the UTXO being spent., marking it as a '''tapscript spend'''. Validation of such inputs must be equivalent to performing the following steps in the specified order. # If the input is invalid due to BIP16, BIP141, or bip-taproot, fail. @@ -142,4 +142,3 @@ This rule limits worst-case validation costs in tapscript similar to the ''sigop ==Acknowledgements== This document is the result of many discussions and contains contributions by Jonas Nick, Anthony Towns, and others. - -- cgit v1.2.3 From 8ea6798a9d0893aec95f0cc90d9f4d45f3471d09 Mon Sep 17 00:00:00 2001 From: Elichai Turkel Date: Mon, 23 Sep 2019 02:06:14 +0300 Subject: Euler's Criterion prime only nit --- bip-schnorr.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index e1fe634..0473a29 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -116,7 +116,7 @@ The following convention is used, with constants as defined for secp256k1: *** Return the unique point ''P'' such that ''x(P) = x'' and ''y(P) = y''. ** The function ''point(x)'', where ''x'' is a 32-byte array, returns the point ''P = lift_x(int(x))''. ** The function ''hashtag(x)'' where ''tag'' is a UTF-8 encoded tag name and ''x'' is a byte array returns the 32-byte hash ''SHA256(SHA256(tag) || SHA256(tag) || x)''. -** The function ''jacobi(x)'', where ''x'' is an integer, returns the [https://en.wikipedia.org/wiki/Jacobi_symbol Jacobi symbol] of ''x / p''. It is equal to ''x(p-1)/2 mod p'' ([https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion])For points ''P'' on the secp256k1 curve it holds that ''jacobi(y(P)) ≠ 0''.. +** The function ''jacobi(x)'', where ''x'' is an integer, returns the [https://en.wikipedia.org/wiki/Jacobi_symbol Jacobi symbol] of ''x / p''. Since ''p'' is prime, it is equal to ''x(p-1)/2 mod p'' ([https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion])For points ''P'' on the secp256k1 curve it holds that ''jacobi(y(P)) ≠ 0''.. ** The function ''pubkey(x)'', where ''x'' is a 32-byte array, returns ''bytes(dG)'' where ''d = int(x) mod n''. ==== Public Key Generation ==== -- cgit v1.2.3 From 972136beb6ca36e4387a2358240cafe22dcb21dc Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 20 Sep 2019 16:14:25 -0700 Subject: Remove P2SH support --- bip-taproot.mediawiki | 22 ++++++++++------------ bip-tapscript.mediawiki | 13 ++++++------- 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 76c23dc..0823c6b 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -54,10 +54,10 @@ The notation below follows that of bip-schnorr. === Script validation rules === -A Taproot output is a SegWit output (native or P2SH-nested, see [https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki BIP141]) with version number 1, and a 32-byte witness program. -The following rules only apply when such an output is being spent. Any other outputs, including version 1 outputs with lengths other than 32 bytes, remain unencumbered. +A Taproot output is a native SegWit output (see [https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki BIP141]) with version number 1, and a 32-byte witness program. +The following rules only apply when such an output is being spent. Any other outputs, including version 1 outputs with lengths other than 32 bytes, or P2SH-wrapped version 1 outputs, remain unencumbered. -* Let ''q'' be the 32-byte array containing the witness program (second push in scriptPubKey or P2SH redeemScript) which represents a public key according to bip-schnorr. +* Let ''q'' be the 32-byte array containing the witness program (the second push in the scriptPubKey) which represents a public key according to bip-schnorr. * Fail if the witness stack has 0 elements. * If there are at least two witness elements, and the first byte of the last element is 0x50'''Why is the first byte of the annex 0x50?''' Like the 0xc0-0xc1 constants, 0x50 is chosen as it could not be confused with a valid P2WPKH or P2WSH spending. As the control block's initial byte's lowest bit is used to indicate the public key's Y quadratic residuosity, each script version needs two subsequence byte values that are both not yet used in P2WPKH or P2WSH spending. To indicate the annex, only an "unpaired" available byte is necessary like 0x50. This choice maximizes the available options for future script versions., this last element is called ''annex'' ''a'''''What is the purpose of the annex?''' The annex is a reserved space for future extensions, such as indicating the validation costs of computationally expensive new opcodes in a way that is recognizable without knowing the outputs being spent. Until the meaning of this field is defined by another softfork, users SHOULD NOT include annex in transactions, or it may lead to PERMANENT FUND LOSS. and is removed from the witness stack. The annex (or the lack of thereof) is always covered by the transaction digest and contributes to transaction weight, but is otherwise ignored during taproot validation. * If there is exactly one element left in the witness stack, key path spending is used: @@ -126,10 +126,9 @@ As the message for signature verification, transaction digest is ''hashTapS *** sha_outputs (32): the SHA256 of the serialization of all outputs in CTxOut format. * Data about this input: ** spend_type (1): -*** Bit-0 is set if the scriptPubKey being spent is P2SH (opposed to "native segwit"). -*** Bit-1 is set if an annex is present (the original witness stack has two or more witness elements, and the first byte of the last element is 0x50). +*** Bit 0 is set if an annex is present (the original witness stack has two or more witness elements, and the first byte of the last element is 0x50). *** The other bits are unset. -** scriptPubKey (24 or 35): scriptPubKey of the previous output spent by this input, serialized as script inside CTxOut. The size is 24-byte for P2SH-embedded segwit, or 35-byte for native segwit. +** scriptPubKey (35): scriptPubKey of the previous output spent by this input, serialized as script inside CTxOut. Its size is always 35 bytes. ** If the SIGHASH_ANYONECANPAY flag is set: *** outpoint (36): the COutPoint of this input (32-byte hash + 4-byte little-endian). *** amount (8): value of the previous output spent by this input. @@ -142,11 +141,11 @@ As the message for signature verification, transaction digest is ''hashTapS ** If the SIGHASH_SINGLE flag is set: *** sha_single_output (32): the SHA256 of the corresponding output in CTxOut format. -The total number of bytes hashed is at most ''209'''''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''176 - is_anyonecanpay * 50 - is_none * 32 - is_p2sh_spending * 11 + has_annex * 32''.. +The total number of bytes hashed is at most ''209'''''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''176 - is_anyonecanpay * 50 - is_none * 32 + has_annex * 32''.. In summary, the semantics of the BIP143 sighash types remain unchanged, except the following: # The way and order of serialization is changed.'''Why is the serialization in the transaction digest changed?''' Hashes that go into the digest and the digest itself are now computed with a single SHA256 invocation instead of double SHA256. There is no expected security improvement by doubling SHA256 because this only protects against length-extension attacks against SHA256 which are not a concern for transaction digests because there is no secret data. Therefore doubling SHA256 is a waste of resources. The digest computation now follows a logical order with transaction level data first, then input data and output data. This allows to efficiently cache the transaction part of the digest across different inputs using the SHA256 midstate. Additionally, digest computation avoids unnecessary hashing as opposed to BIP143 digests in which parts may be set zero and before hashing them. Despite that, collisions are made impossible by committing to the length of the data (implicit in hash_type and spend_type) before the variable length data. -# The digest commits to the scriptPubKey'''Why does the transaction digest commit to the scriptPubKey?''' This prevents lying to offline signing devices about the type of output being spent, even when the actually executed script (scriptCode in BIP143) is correct. Without committing to the scriptPubKey an attacker can fool the device into overpaying fees by asking it to sign for a P2SH wrapped segwit output but actually using it to spend a native segwit output.. +# The digest commits to the scriptPubKey'''Why does the transaction digest commit to the scriptPubKey?''' This prevents lying to offline signing devices about output being spent, even when the actually executed script (scriptCode in BIP143) is correct. This means it's possible to compactly prove to a hardware wallet what (unused) execution paths existed.. # If the SIGHASH_ANYONECANPAY flag is not set, the digest commits to the amounts of ''all'' transaction inputs.'''Why does the transaction digest commit to the amounts of all transaction inputs?''' This eliminates the possibility to lie to offline signing devices about the fee of a transaction. # The digest commits to all input nSequence if SIGHASH_NONE or SIGHASH_SINGLE are set (unless SIGHASH_ANYONECANPAY is set as well).'''Why does the transaction digest commit to all input nSequence if SIGHASH_SINGLE or SIGHASH_NONE are set?''' Because setting them already makes the digest commit to the prevouts part of all transaction inputs, it is not useful to treat the nSequence any different. Moreover, this change makes nSequence consistent with the view that SIGHASH_SINGLE and SIGHASH_NONE only modify the digest with respect to transaction outputs and not inputs. # The digest commits to taproot-specific data epoch, spend_type and annex (if present). @@ -208,7 +207,7 @@ def taproot_output_script(internal_pubkey, script_tree): return bytes([0x51, 0x20]) + output_pubkey.get_bytes() -The function taproot_output_script returns a byte array with the scriptPubKey. It can be P2SH wrapped if desired (see BIP141). +The function taproot_output_script returns a byte array with the scriptPubKey (see BIP141). [[File:bip-taproot/tree.png|frame|This diagram shows the hashing structure to obtain the tweak from an internal key ''P'' and a Merkle tree consisting of 5 script leaves. ''A'', ''B'', ''C'' and ''E'' are ''TapLeaf'' hashes similar to ''D'' and ''AB'' is a ''TapBranch'' hash. Note that when ''CDE'' is computed ''E'' is hashed first because ''E'' is less than ''CD''.]] @@ -229,7 +228,7 @@ def taproot_sign_key(script_tree, internal_privkey, hash_type): return [sig] -This function returns the witness stack necessary, and assumes a tweak_add method on private keys, and a sighash function to compute the signature hash as defined above (for simplicity, the snippet above ignores passing information like the transaction, the input position, P2SH or not, ... to the sighashing code). +This function returns the witness stack necessary, and assumes a tweak_add method on private keys, and a sighash function to compute the signature hash as defined above (for simplicity, the snippet above ignores passing information like the transaction, the input position, ... to the sighashing code). '''Spending using one of the scripts''' A Taproot output can be spent by satisfying any of the scripts used in its construction. To do so, a witness stack consisting of the script's inputs, plus the script itself and the control block are necessary. See the code below: @@ -282,8 +281,7 @@ Non-upgraded nodes, however, will consider all SegWit version 1 witness programs They are strongly encouraged to upgrade in order to fully validate the new programs. Non-upgraded wallets can receive and send bitcoin from non-upgraded and upgraded wallets using SegWit version 0 programs, traditional pay-to-pubkey-hash, etc. -Depending on the implementation non-upgraded wallets may be able to send to Segwit version 1 programs if they support sending to BIP173 Bech32 addresses and non-standardness of these outputs does not prevent transaction broadcasting. -Non-upgraded wallets can send bitcoin to upgraded wallets using Segwit version 1 programs nested in BIP16 P2SH. +Depending on the implementation non-upgraded wallets may be able to send to Segwit version 1 programs if they support sending to BIP173 Bech32 addresses. == Acknowledgements == diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index 603990e..0f4fdf5 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -44,8 +44,8 @@ Additionally, the new tapscript OP_SUCCESS opcodes allow introducin ==Specification== The rules below only apply when validating a transaction input for which all of the conditions below are true: -* The transaction output is a '''segregated witness spend''' (i.e., either the scriptPubKey or BIP16 redeemScript is a witness program as defined in BIP141). -* It is a '''taproot spend''' as defined in bip-taproot (i.e., the witness version is 1, the witness program is 32 bytes). +* The transaction output is a '''segregated witness spend''' (i.e., the scriptPubKey is a witness program as defined in BIP141). +* It is a '''taproot spend''' as defined in bip-taproot (i.e., the witness version is 1, the witness program is 32 bytes, and it is not P2SH wrapped). * It is a '''script path spend''' as defined in bip-taproot (i.e., after removing the optional annex from the witness stack, two or more stack elements remain). * The leaf version is ''0xc0'' (i.e. the first byte of the last witness element after removing the optional annex is ''0xc0'')'''How is the ''0xc0'' constant chosen?''' Following the guidelines in bip-taproot, by choosing a value having the two top bits set, tapscript spends are identifiable even without access to the UTXO being spent., marking it as a '''tapscript spend'''. @@ -103,10 +103,9 @@ These opcodes count toward the 201 non-push opcodes limit. As the message for signature opcodes signature verification, transaction digest has the same definition as in bip-taproot, except the following: -The one-byte spend_type has a different value, specificially at bit-2: -* Bit-0 is set if the scriptPubKey being spent is P2SH (opposed to "native segwit"). -* Bit-1 is set if an annex is present (the original witness stack has at least two witness elements, and the first byte of the last element is 0x50). -* Bit-2 is set. +The one-byte spend_type has a different value, specificially at bit 1: +* Bit 0 is set if an annex is present (the original witness stack has at least two witness elements, and the first byte of the last element is 0x50). +* Bit 1 is set. * The other bits are unset. As additional pieces of data, added at the end of the input to the ''hashTapSighash'' function: @@ -114,7 +113,7 @@ As additional pieces of data, added at the end of the input to the ''hashTa * key_version (1): a constant value 0x00 representing the current version of public keys in the tapscript signature opcode execution. * codeseparator_position (2): the opcode position of the last executed OP_CODESEPARATOR before the currently executed signature opcode, with the value in little endian (or 0xffff if none executed). The first opcode in a script has a position of 0. A multi-byte push opcode is counted as one opcode, regardless of the size of data being pushed. -The total number of bytes hashed is at most ''244'''''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''211 - is_anyonecanpay * 50 - is_none * 32 - is_p2sh_spending * 11 + has_annex * 32''.. +The total number of bytes hashed is at most ''244'''''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''211 - is_anyonecanpay * 50 - is_none * 32 + has_annex * 32''.. In summary, the semantics of the BIP143 sighash types remain unchanged, except the following: # The exceptions mentioned in bip-taproot. -- cgit v1.2.3 From 499106c57b88b159966bc4d0f56a8e5b85e8dc78 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 20 Sep 2019 19:38:03 -0700 Subject: Rework resource limits section --- bip-tapscript.mediawiki | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index 0f4fdf5..f4aaf34 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -61,18 +61,18 @@ Validation of such inputs must be equivalent to performing the following steps i # If the size of any element in the '''initial stack''' as defined in bip-taproot (i.e., the witness stack after removing both the optional annex and the two last stack elements after that) is bigger than 520 bytes, fail. # If the tapscript is bigger than 10000 bytes, fail. # The tapscript is executed according to the rules in the following section, with the initial stack as input. -## If execution fails for any reason (including the 201 non-push opcode limit), fail. +## If execution fails for any reason, fail. ## If the execution results in anything but exactly one element on the stack which evaluates to true with CastToBool(), fail. # If this step is reached without encountering a failure, validation succeeds. ===Script execution=== The execution rules for tapscript are based on those for P2WSH according to BIP141, including the OP_CHECKLOCKTIMEVERIFY and OP_CHECKSEQUENCEVERIFY opcodes defined in BIP65 and BIP112, but with the following modifications: -* '''Disabled script opcodes''' The following script opcodes are disabled in tapscript: OP_CHECKMULTISIG and OP_CHECKMULTISIGVERIFY. The disabled opcodes behave in the same way as OP_RETURN, by failing and terminating the script immediately when executed, and being ignored when found in unexecuted branch. While being ignored, they are still counted towards the 201 non-push opcodes limit. +* '''Disabled script opcodes''' The following script opcodes are disabled in tapscript: OP_CHECKMULTISIG and OP_CHECKMULTISIGVERIFY. The disabled opcodes behave in the same way as OP_RETURN, by failing and terminating the script immediately when executed, and being ignored when found in unexecuted branch. * '''Consensus-enforced MINIMALIF''' The MINIMALIF rules, which are only a standardness rule in P2WSH, are consensus enforced in tapscript. This means that the input argument to the OP_IF and OP_NOTIF opcodes must be either exactly 0 (the empty vector) or exactly 1 (the one-byte vector with value 1)'''Why make MINIMALIF consensus?''' This makes it considerably easier to write non-malleable scripts that take branch information from the stack.. * '''OP_SUCCESSx opcodes''' As listed above, some opcodes are renamed to OP_SUCCESSx, and make the script unconditionally valid. * '''Signature opcodes'''. The OP_CHECKSIG and OP_CHECKSIGVERIFY are modified to operate on Schnorr public keys and signatures (see bip-schnorr) instead of ECDSA, and a new opcode OP_CHECKSIGADD is added. -** The opcode 186 (0xba) is named as OP_CHECKSIGADD. '''OP_CHECKSIGADD''' This opcode is added to compensate for the loss of OP_CHECKMULTISIG-like opcodes, which are incompatible with batch verification. OP_CHECKSIGADD is functionally equivalent to OP_ROT OP_SWAP OP_CHECKSIG OP_ADD, but is only counted as one opcode towards the 201 non-push opcodes limit. All CScriptNum-related behaviours of OP_ADD are also applicable to OP_CHECKSIGADD.'''Comparison of CHECKMULTISIG and CHECKSIG''' A CHECKMULTISIG script m ... n CHECKMULTISIG with witness 0 ... can be rewritten as script CHECKSIG ... CHECKSIGADD m NUMEQUAL with witness ... . Every witness element w_i is either a signature corresponding to the public key with the same index or an empty vector. A similar CHECKMULTISIGVERIFY script can be translated to bip-tapscript by replacing NUMEQUAL with NUMEQUALVERIFY. Alternatively, an m-of-n multisig policy can be implemented by splitting the script into several leaves of the Merkle tree, each implementing an m-of-m policy using CHECKSIGVERIFY ... CHECKSIGVERIFY CHECKSIG. If the setting allows the participants to interactively collaborate while signing, multisig policies can be realized with [https://eprint.iacr.org/2018/068 MuSig] for m-of-m and with [http://cacr.uwaterloo.ca/techreports/2001/corr2001-13.ps threshold signatures] using verifiable secret sharing for m-of-n. +** The opcode 186 (0xba) is named as OP_CHECKSIGADD. '''OP_CHECKSIGADD''' This opcode is added to compensate for the loss of OP_CHECKMULTISIG-like opcodes, which are incompatible with batch verification. OP_CHECKSIGADD is functionally equivalent to OP_ROT OP_SWAP OP_CHECKSIG OP_ADD, but only takes 1 byte. All CScriptNum-related behaviours of OP_ADD are also applicable to OP_CHECKSIGADD.'''Comparison of CHECKMULTISIG and CHECKSIG''' A CHECKMULTISIG script m ... n CHECKMULTISIG with witness 0 ... can be rewritten as script CHECKSIG ... CHECKSIGADD m NUMEQUAL with witness ... . Every witness element w_i is either a signature corresponding to the public key with the same index or an empty vector. A similar CHECKMULTISIGVERIFY script can be translated to bip-tapscript by replacing NUMEQUAL with NUMEQUALVERIFY. Alternatively, an m-of-n multisig policy can be implemented by splitting the script into several leaves of the Merkle tree, each implementing an m-of-m policy using CHECKSIGVERIFY ... CHECKSIGVERIFY CHECKSIG. If the setting allows the participants to interactively collaborate while signing, multisig policies can be realized with [https://eprint.iacr.org/2018/068 MuSig] for m-of-m and with [http://cacr.uwaterloo.ca/techreports/2001/corr2001-13.ps threshold signatures] using verifiable secret sharing for m-of-n. ===Rules for signature opcodes=== @@ -97,8 +97,6 @@ The following rules apply to OP_CHECKSIG, OP_CHECKSIGVERIFYOP_CHECKSIG, a 1-byte value 0x01 is pushed onto the stack. *** For OP_CHECKSIGADD, a CScriptNum with value of n + 1 is pushed onto the stack. -These opcodes count toward the 201 non-push opcodes limit. - ===Transaction digest=== As the message for signature opcodes signature verification, transaction digest has the same definition as in bip-taproot, except the following: @@ -121,16 +119,14 @@ In summary, the semantics of the BIP143 sighash types remain unchanged, except t # The digest commits to the executed script through the tapleaf_hash which includes the leaf version and script instead of scriptCode. This implies that this commitment is unaffected by OP_CODESEPARATOR. # The digest commits to the opcode position of the last executed OP_CODESEPARATOR.'''Why does the transaction digest commit to the position of the last executed OP_CODESEPARATOR?''' This allows continuing to use OP_CODESEPARATOR to sign the executed path of the script. Because the codeseparator_position is the last input to the digest, the SHA256 midstate can be efficiently cached for multiple OP_CODESEPARATORs in a single script. In contrast, the BIP143 handling of OP_CODESEPARATOR is to commit to the executed script only from the last executed OP_CODESEPARATOR onwards which requires unnecessary rehashing of the script. It should be noted that the one known OP_CODESEPARATOR use case of saving a second public key push in a script by sharing the first one between two code branches can be most likely expressed even cheaper by moving each branch into a separate taproot leaf. -===Signature opcodes limitation=== - -In addition to the 201 non-push opcodes limit, the use of signature opcodes is subject to further limitations. - -* input_witness_weight is defined as the size of the serialized input witness associated to a particular transaction input. As defined in BIP141, a serialized input witness includes CCompactSize tags indicating the number of elements and size of each element, and contents of each element. input_witness_weight is the total size of the said CCompactSize tags and element contents. -* sigops_passed is defined as the total number of successfully executed signature opcodes, which have non-zero signature size and do not fail and terminate the script. For the avoidance of doubt, passing signature opcodes with unknown type public key and non-zero size signature are also counted towards sigops_passed. -* If 50 * (sigops_passed - 1) is greater than input_witness_weight, the script MUST fail and terminate immediately. +===Resource limits=== -This rule limits worst-case validation costs in tapscript similar to the ''sigops limit'' that only applies to legacy and P2WSH scripts'''The tapscript sigop limit''' The signature opcode limit protects against scripts which are slow to verify due to excessively many signature operations. In tapscript the number of signature opcodes does not count towards the BIP141 or legacy sigop limit. The old sigop limit makes transaction selection in block construction unnecessarily difficult because it is a second constraint in addition to weight. Instead, the number of tapscript signature opcodes is limited by witness weight. Additionally, the limit applies to the transaction input instead of the block and only actually executed signature opcodes are counted. Tapscript execution allows one signature opcode per 50 witness weight units plus one free signature opcode. The tapscript signature opcode limit allows to add new signature opcodes like CHECKSIGFROMSTACK to count towards the limit through a soft fork. Even if in the future new opcodes are introduced which change normal script cost there is need to stuff the witness with meaningless data. In that case the taproot annex can be used to add weight to the witness without increasing the actual witness size. -'''Parameter choice of the sigop limit''' Regular witnesses are unaffected by the limit as their weight is composed of public key and (SIGHASH_ALL) signature pairs with ''33 + 65'' weight units each (which includes a 1 weight unit CCompactSize tag). This is also the case if public keys are reused in the script because a signature's weight alone is 65 or 66 weight units. However, the limit increases the fees of abnormal scripts with duplicate signatures (and public keys) by requiring additional weight. The weight per sigop factor 50 corresponds to the ratio of BIP141 block limits: 4 mega weight units divided by 80,000 sigops. The "free" signature opcode permitted by the limit exists to account for the weight of the non-witness parts of the transaction input.. +In addition to changing the semantics of a number of opcodes, there are also some changes to the resource limitations: +* '''Script size limit''' The maximum script size of 10000 bytes does not apply. Their size is only implicitly limited by the limits on transaction and block size.'''Why is a limit on script size no longer needed?''' Since there is no scriptCode directly included in the signature hash (only indirectly through a precomputable tapleaf hash), the CPU time spent on a signature check is no longer proportional to the size of the script being executed. +* '''Non-push opcodes limit''' The maximum non-push opcodes limit of 201 per script does not apply.'''Why is a limit on the number of opcodes no longer needed?''' An opcode limit only helps to the extent that it can prevent data structures from growing unboundedly during execution (both because of memory usage, and because of time that may grow in proportion to the size of those structures. The size of stack and altstack is already independently limited. Using O(1) logic for OP_IF, OP_NOTIF, OP_ELSE, and OP_ENDIF like suggested [https://bitslog.com/2017/04/17/new-quadratic-delays-in-bitcoin-scripts/ here] and implemented [https://github.com/bitcoin/bitcoin/pull/16902 here] the only other instance can be avoided as well. +* '''Sigops limit''' The sigops in tapscripts do not count towards the block-wide limit of 80000 (weighted). Instead, there is a per-script sigops ''budget''. The budget equals 50 + the total serialized size in bytes of the transaction input's witness (including the CCompactSize prefix). Executing a signature opcode (OP_CHECKSIG, OP_CHECKSIGVERIFY, or OP_CHECKSIGADD) with a non-empty signature decrements the budget by 50. If that brings the budget below zero, the script fails immediately. Signature opcodes with unknown public key type and non-empty signature are also counted.'''The tapscript sigop limit''' The signature opcode limit protects against scripts which are slow to verify due to excessively many signature operations. In tapscript the number of signature opcodes does not count towards the BIP141 or legacy sigop limit. The old sigop limit makes transaction selection in block construction unnecessarily difficult because it is a second constraint in addition to weight. Instead, the number of tapscript signature opcodes is limited by witness weight. Additionally, the limit applies to the transaction input instead of the block and only actually executed signature opcodes are counted. Tapscript execution allows one signature opcode per 50 witness weight units plus one free signature opcode.'''Parameter choice of the sigop limit''' Regular witnesses are unaffected by the limit as their weight is composed of public key and (SIGHASH_ALL) signature pairs with ''33 + 65'' weight units each (which includes a 1 weight unit CCompactSize tag). This is also the case if public keys are reused in the script because a signature's weight alone is 65 or 66 weight units. However, the limit increases the fees of abnormal scripts with duplicate signatures (and public keys) by requiring additional weight. The weight per sigop factor 50 corresponds to the ratio of BIP141 block limits: 4 mega weight units divided by 80,000 sigops. The "free" signature opcode permitted by the limit exists to account for the weight of the non-witness parts of the transaction input.'''Why are only signature opcodes counted toward the budget, and not for example hashing opcodes or other expensive operations?''' It turns out that the CPU cost per witness byte for verification of a script consisting of the maximum density of signature checking opcodes (taking the 50 WU/sigop limit into account) is already very close to that of scripts packed with other opcodes, including hashing opcodes (taking the 520 byte stack element limit into account) and OP_ROLL (taking the 1000 stack element limit into account). That said, the construction is very flexible, and allows adding new signature opcodes like CHECKSIGFROMSTACK to count towards the limit through a soft fork. Even if in the future new opcodes are introduced which change normal script cost there is no need to stuff the witness with meaningless data. Instead, the taproot annex can be used to add weight to the witness without increasing the actual witness size.. +* '''Stack + altstack element count limit''' The existing limit of 1000 elements in the stack and altstack together after every executed opcode remains. It is extended to also apply to the size of initial stack. +* '''Stack element size limit''' The existing limit of maximum 520 bytes per stack element remains, both in the initial stack and in push opcodes. ==Rationale== -- cgit v1.2.3 From 4087834c73c013eb38dc896e09d2602a60dee2af Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 20 Sep 2019 15:01:57 -0700 Subject: Move/reword tagged hashes motivation --- bip-taproot.mediawiki | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 0823c6b..7a81949 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -41,7 +41,7 @@ As a result we choose this combination of technologies: * Taproot's advantages become apparent under the assumption that most applications involve outputs that could be spent by all parties agreeing. That's where '''Schnorr''' signatures come in, as they permit [https://eprint.iacr.org/2018/068 key aggregation]: a public key can be constructed from multiple participant public keys, and which requires cooperation between all participants to sign for. Such multi-party public keys and signatures are indistinguishable from their single-party equivalents. This means that under this Taproot assumption, the all-parties-agree case can be handled using the key-based spending path, which is both private and efficient using Taproot. This can be generalized to arbitrary M-of-N policies, as Schnorr signatures support threshold signing, at the cost of more complex setup protocols. * As Schnorr signatures also permit '''batch validation''', allowing multiple signatures to be validated together more efficiently than validating each one independently, we make sure all parts of the design are compatible with this. * Where unused bits appear as a result of the above changes, they are reserved for mechanisms for '''future extensions'''. As a result, every script in the Merkle tree has an associated version such that new script versions can be introduced with a soft fork while remaining compatible with bip-taproot. Additionally, future soft forks can make use of the currently unused annex in the witness (see [[#Rationale]]). -* While the core semantics of the '''signature hashing algorithm''' are not changed, a number of improvements are included in this proposal. The new signature hashing algorithm fixes the verification capabilities of offline signing devices by including amount and scriptPubKey in the digest, avoids unnecessary hashing, uses '''tagged hashes''''''Why use tagged hashes?''' So far, nowhere in the Bitcoin protocol are hashes used where the input of SHA256 starts with two (non-double) SHA256 hashes, making collisions with existing uses of hash functions infeasible. (according to bip-schnorr) and defines a default sighash byte. +* While the core semantics of the '''signature hashing algorithm''' are not changed, a number of improvements are included in this proposal. The new signature hashing algorithm fixes the verification capabilities of offline signing devices by including amount and scriptPubKey in the digest, avoids unnecessary hashing, uses '''tagged hashes''' and defines a default sighash byte. * The '''public key is directly included in the output''' in contrast to typical earlier constructions which store a hash of the public key or script in the output. This has the same cost for senders and is more space efficient overall if the key-based spending path is taken. '''Why is the public key directly included in the output?''' While typical earlier constructions store a hash of a script or a public key in the output, this is rather wasteful when a public key is always involved. To guarantee batch verifiability, ''q'' must be known to every verifier, and thus only revealing its hash as an output would imply adding an additional 32 bytes to the witness. Furthermore, to maintain [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2016-January/012198.html 128-bit collision security] for outputs, a 256-bit hash would be required anyway, which is comparable in size (and thus in cost for senders) to revealing the public key directly. While the usage of public key hashes is often said to protect against ECDLP breaks or quantum computers, this protection is very weak at best: transactions are not protected while being confirmed, and a very [https://twitter.com/pwuille/status/1108097835365339136 large portion] of the currency's supply is not under such protection regardless. Actual resistance to such systems can be introduced by relying on different cryptographic assumptions, but this proposal focuses on improvements that do not change the security model. Note that using P2SH-wrapped outputs only have 80-bit collision security. This is considered low, and is relevant whenever the output includes data from more than a single party (public keys, hashes, ...). . Not included in this proposal are additional features like new sighash modes or opcodes that can be included with no loss in effectiveness as a future extension. Also not included is cross-input aggregation, as it [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-March/015838.html interacts] in complex ways with upgrade mechanisms and solutions to that are still [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-October/016461.html in flux]. @@ -50,7 +50,7 @@ Not included in this proposal are additional features like new sighash modes or This section specifies the Taproot consensus rules. Validity is defined by exclusion: a block or transaction is valid if no condition exists that marks it failed. -The notation below follows that of bip-schnorr. +The notation below follows that of bip-schnorr. This includes the ''hashtag(x)'' notation to refer to ''SHA256(SHA256(tag) || SHA256(tag) || x)''. To the best of the authors' knowledge, no existing use of SHA256 in Bitcoin feeds it a message that starts with two single SHA256 outputs, making collisions between ''hashtag'' with other hashes extremely unlikely. === Script validation rules === -- cgit v1.2.3 From 2202615b7ccc9799006ddea51dd575256f9b6dd6 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 23 Sep 2019 13:24:33 -0700 Subject: Fixups --- bip-tapscript.mediawiki | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index f4aaf34..a40cfc8 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -59,7 +59,6 @@ Validation of such inputs must be equivalent to performing the following steps i * Given that OP_SUCCESSx even causes potentially unparseable scripts to pass, it can be used to introduce multi-byte opcodes, or even a completely new scripting language when prefixed with a specific OP_SUCCESSx opcode.. ## If any push opcode fails to decode because it would extend past the end of the tapscript, fail. # If the size of any element in the '''initial stack''' as defined in bip-taproot (i.e., the witness stack after removing both the optional annex and the two last stack elements after that) is bigger than 520 bytes, fail. -# If the tapscript is bigger than 10000 bytes, fail. # The tapscript is executed according to the rules in the following section, with the initial stack as input. ## If execution fails for any reason, fail. ## If the execution results in anything but exactly one element on the stack which evaluates to true with CastToBool(), fail. @@ -92,7 +91,7 @@ The following rules apply to OP_CHECKSIG, OP_CHECKSIGVERIFYOP_CHECKSIGVERIFY, the script MUST fail and terminate immediately. *** For OP_CHECKSIG, an empty vector is pushed onto the stack, and execution continues with the next opcode. *** For OP_CHECKSIGADD, a CScriptNum with value n is pushed onto the stack, and execution continues with the next opcode. -** If the signature is not the empty vector, the sigops_passed counter is incremented (see further) +** If the signature is not the empty vector, the opcode is counted towards the sigops budget (see further). *** For OP_CHECKSIGVERIFY, execution continues without any further changes to the stack. *** For OP_CHECKSIG, a 1-byte value 0x01 is pushed onto the stack. *** For OP_CHECKSIGADD, a CScriptNum with value of n + 1 is pushed onto the stack. -- cgit v1.2.3 From 7c6ee49c03a3653704857585c16ecd8dfd209ca8 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Wed, 25 Sep 2019 14:02:42 +1000 Subject: typo --- bip-tapscript.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index a40cfc8..1d3e6fa 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -100,7 +100,7 @@ The following rules apply to OP_CHECKSIG, OP_CHECKSIGVERIFYspend_type has a different value, specificially at bit 1: +The one-byte spend_type has a different value, specifically at bit 1: * Bit 0 is set if an annex is present (the original witness stack has at least two witness elements, and the first byte of the last element is 0x50). * Bit 1 is set. * The other bits are unset. -- cgit v1.2.3 From cf8233d39e1ec7bef0d6b1d26ff5d60563ef4604 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Wed, 25 Sep 2019 14:14:14 +1000 Subject: separate p2sh wrapped security rationale --- bip-taproot.mediawiki | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 7a81949..64d8b94 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -42,7 +42,7 @@ As a result we choose this combination of technologies: * As Schnorr signatures also permit '''batch validation''', allowing multiple signatures to be validated together more efficiently than validating each one independently, we make sure all parts of the design are compatible with this. * Where unused bits appear as a result of the above changes, they are reserved for mechanisms for '''future extensions'''. As a result, every script in the Merkle tree has an associated version such that new script versions can be introduced with a soft fork while remaining compatible with bip-taproot. Additionally, future soft forks can make use of the currently unused annex in the witness (see [[#Rationale]]). * While the core semantics of the '''signature hashing algorithm''' are not changed, a number of improvements are included in this proposal. The new signature hashing algorithm fixes the verification capabilities of offline signing devices by including amount and scriptPubKey in the digest, avoids unnecessary hashing, uses '''tagged hashes''' and defines a default sighash byte. -* The '''public key is directly included in the output''' in contrast to typical earlier constructions which store a hash of the public key or script in the output. This has the same cost for senders and is more space efficient overall if the key-based spending path is taken. '''Why is the public key directly included in the output?''' While typical earlier constructions store a hash of a script or a public key in the output, this is rather wasteful when a public key is always involved. To guarantee batch verifiability, ''q'' must be known to every verifier, and thus only revealing its hash as an output would imply adding an additional 32 bytes to the witness. Furthermore, to maintain [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2016-January/012198.html 128-bit collision security] for outputs, a 256-bit hash would be required anyway, which is comparable in size (and thus in cost for senders) to revealing the public key directly. While the usage of public key hashes is often said to protect against ECDLP breaks or quantum computers, this protection is very weak at best: transactions are not protected while being confirmed, and a very [https://twitter.com/pwuille/status/1108097835365339136 large portion] of the currency's supply is not under such protection regardless. Actual resistance to such systems can be introduced by relying on different cryptographic assumptions, but this proposal focuses on improvements that do not change the security model. Note that using P2SH-wrapped outputs only have 80-bit collision security. This is considered low, and is relevant whenever the output includes data from more than a single party (public keys, hashes, ...). . +* The '''public key is directly included in the output''' in contrast to typical earlier constructions which store a hash of the public key or script in the output. This has the same cost for senders and is more space efficient overall if the key-based spending path is taken. '''Why is the public key directly included in the output?''' While typical earlier constructions store a hash of a script or a public key in the output, this is rather wasteful when a public key is always involved. To guarantee batch verifiability, ''q'' must be known to every verifier, and thus only revealing its hash as an output would imply adding an additional 32 bytes to the witness. Furthermore, to maintain [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2016-January/012198.html 128-bit collision security] for outputs, a 256-bit hash would be required anyway, which is comparable in size (and thus in cost for senders) to revealing the public key directly. While the usage of public key hashes is often said to protect against ECDLP breaks or quantum computers, this protection is very weak at best: transactions are not protected while being confirmed, and a very [https://twitter.com/pwuille/status/1108097835365339136 large portion] of the currency's supply is not under such protection regardless. Actual resistance to such systems can be introduced by relying on different cryptographic assumptions, but this proposal focuses on improvements that do not change the security model. Not included in this proposal are additional features like new sighash modes or opcodes that can be included with no loss in effectiveness as a future extension. Also not included is cross-input aggregation, as it [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-March/015838.html interacts] in complex ways with upgrade mechanisms and solutions to that are still [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-October/016461.html in flux]. @@ -55,7 +55,7 @@ The notation below follows that of bip-schnorr. This includes the ''hashtag === Script validation rules === A Taproot output is a native SegWit output (see [https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki BIP141]) with version number 1, and a 32-byte witness program. -The following rules only apply when such an output is being spent. Any other outputs, including version 1 outputs with lengths other than 32 bytes, or P2SH-wrapped version 1 outputs, remain unencumbered. +The following rules only apply when such an output is being spent. Any other outputs, including version 1 outputs with lengths other than 32 bytes, or P2SH-wrapped version 1 outputs'''Why is P2SH-wrapping not supported?''' Using P2SH-wrapped outputs only provides 80-bit collision security due to the use of a 160-bit hash. This is considered low, and becomes a security risk whenever the output includes data from more than a single party (public keys, hashes, ...)., remain unencumbered. * Let ''q'' be the 32-byte array containing the witness program (the second push in the scriptPubKey) which represents a public key according to bip-schnorr. * Fail if the witness stack has 0 elements. -- cgit v1.2.3 From 1c8bdd75a59a204b63c07e34633e0f53bb1a679e Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Wed, 25 Sep 2019 21:02:43 +0000 Subject: Remove 0xc1 --- bip-taproot.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 64d8b94..75eacca 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -59,7 +59,7 @@ The following rules only apply when such an output is being spent. Any other out * Let ''q'' be the 32-byte array containing the witness program (the second push in the scriptPubKey) which represents a public key according to bip-schnorr. * Fail if the witness stack has 0 elements. -* If there are at least two witness elements, and the first byte of the last element is 0x50'''Why is the first byte of the annex 0x50?''' Like the 0xc0-0xc1 constants, 0x50 is chosen as it could not be confused with a valid P2WPKH or P2WSH spending. As the control block's initial byte's lowest bit is used to indicate the public key's Y quadratic residuosity, each script version needs two subsequence byte values that are both not yet used in P2WPKH or P2WSH spending. To indicate the annex, only an "unpaired" available byte is necessary like 0x50. This choice maximizes the available options for future script versions., this last element is called ''annex'' ''a'''''What is the purpose of the annex?''' The annex is a reserved space for future extensions, such as indicating the validation costs of computationally expensive new opcodes in a way that is recognizable without knowing the outputs being spent. Until the meaning of this field is defined by another softfork, users SHOULD NOT include annex in transactions, or it may lead to PERMANENT FUND LOSS. and is removed from the witness stack. The annex (or the lack of thereof) is always covered by the transaction digest and contributes to transaction weight, but is otherwise ignored during taproot validation. +* If there are at least two witness elements, and the first byte of the last element is 0x50'''Why is the first byte of the annex 0x50?''' Like the 0xc0 constant, 0x50 is chosen as it could not be confused with a valid P2WPKH or P2WSH spending. As the control block's initial byte's lowest bit is used to indicate the public key's Y quadratic residuosity, each script version needs two subsequence byte values that are both not yet used in P2WPKH or P2WSH spending. To indicate the annex, only an "unpaired" available byte is necessary like 0x50. This choice maximizes the available options for future script versions., this last element is called ''annex'' ''a'''''What is the purpose of the annex?''' The annex is a reserved space for future extensions, such as indicating the validation costs of computationally expensive new opcodes in a way that is recognizable without knowing the outputs being spent. Until the meaning of this field is defined by another softfork, users SHOULD NOT include annex in transactions, or it may lead to PERMANENT FUND LOSS. and is removed from the witness stack. The annex (or the lack of thereof) is always covered by the transaction digest and contributes to transaction weight, but is otherwise ignored during taproot validation. * If there is exactly one element left in the witness stack, key path spending is used: ** The single witness stack element is interpreted as the signature and must be valid (see the next section) for the public key ''q'' and taproot transaction digest (to be defined hereinafter) as message. Fail if it is not. Otherwise pass. * If there are at least two witness elements left, script path spending is used: -- cgit v1.2.3 From 05cc92b9adbe1eac754ca8c25ba022759b20975f Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Thu, 26 Sep 2019 21:18:53 +0000 Subject: Add x() and y() functions for points to bip-schnorr --- bip-schnorr/reference.py | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/bip-schnorr/reference.py b/bip-schnorr/reference.py index 95e9e53..bd12212 100644 --- a/bip-schnorr/reference.py +++ b/bip-schnorr/reference.py @@ -11,19 +11,25 @@ def tagged_hash(tag, msg): tag_hash = hashlib.sha256(tag.encode()).digest() return hashlib.sha256(tag_hash + tag_hash + msg).digest() +def x(P): + return P[0] + +def y(P): + return P[1] + def point_add(P1, P2): if (P1 is None): return P2 if (P2 is None): return P1 - if (P1[0] == P2[0] and P1[1] != P2[1]): + if (x(P1) == x(P2) and y(P1) != y(P2)): return None if (P1 == P2): - lam = (3 * P1[0] * P1[0] * pow(2 * P1[1], p - 2, p)) % p + lam = (3 * x(P1) * x(P1) * pow(2 * y(P1), p - 2, p)) % p else: - lam = ((P2[1] - P1[1]) * pow(P2[0] - P1[0], p - 2, p)) % p - x3 = (lam * lam - P1[0] - P2[0]) % p - return (x3, (lam * (P1[0] - x3) - P1[1]) % p) + lam = ((y(P2) - y(P1)) * pow(x(P2) - x(P1), p - 2, p)) % p + x3 = (lam * lam - x(P1) - x(P2)) % p + return (x3, (lam * (x(P1) - x3) - y(P1)) % p) def point_mul(P, n): R = None @@ -37,7 +43,7 @@ def bytes_from_int(x): return x.to_bytes(32, byteorder="big") def bytes_from_point(P): - return bytes_from_int(P[0]) + return bytes_from_int(x(P)) def point_from_bytes(b): x = int_from_bytes(b) @@ -66,12 +72,12 @@ def schnorr_sign(msg, seckey0): if not (1 <= seckey0 <= n - 1): raise ValueError('The secret key must be an integer in the range 1..n-1.') P = point_mul(G, seckey0) - seckey = seckey0 if (jacobi(P[1]) == 1) else n - seckey0 + seckey = seckey0 if (jacobi(y(P)) == 1) else n - seckey0 k0 = int_from_bytes(tagged_hash("BIPSchnorrDerive", bytes_from_int(seckey) + msg)) % n if k0 == 0: raise RuntimeError('Failure. This happens only with negligible probability.') R = point_mul(G, k0) - k = n - k0 if (jacobi(R[1]) != 1) else k0 + k = n - k0 if (jacobi(y(R)) != 1) else k0 e = int_from_bytes(tagged_hash("BIPSchnorr", bytes_from_point(R) + bytes_from_point(P) + msg)) % n return bytes_from_point(R) + bytes_from_int((k + e * seckey) % n) @@ -91,7 +97,7 @@ def schnorr_verify(msg, pubkey, sig): return False e = int_from_bytes(tagged_hash("BIPSchnorr", sig[0:32] + pubkey + msg)) % n R = point_add(point_mul(G, s), point_mul(P, n - e)) - if R is None or jacobi(R[1]) != 1 or R[0] != r: + if R is None or jacobi(y(R)) != 1 or x(R) != r: return False return True -- cgit v1.2.3 From fe8f5f68caa9c8da00fcd2cff4a02303766097c1 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Fri, 27 Sep 2019 09:00:37 +0000 Subject: Standardize on secret key in bip-schnorr --- bip-schnorr.mediawiki | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 0473a29..5ae6e87 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -26,7 +26,7 @@ transactions. These are [http://www.secg.org/sec1-v2.pdf standardized], but have compared to [https://en.wikipedia.org/wiki/Schnorr_signature Schnorr signatures] over the same curve: * '''Security proof''': The security of Schnorr signatures is easily [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf provable] in the random oracle model assuming the elliptic curve discrete logarithm problem (ECDLP) is hard. Such a proof does not exist for ECDSA. -* '''Non-malleability''': ECDSA signatures are inherently malleable; a third party without access to the private key can alter an existing valid signature for a given public key and message into another signature that is valid for the same key and message. This issue is discussed in [https://github.com/bitcoin/bips/blob/master/bip-0062.mediawiki BIP62] and [https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki BIP66]. On the other hand, Schnorr signatures are provably non-malleableMore precisely they are '' '''strongly''' unforgeable under chosen message attacks '' (SUF-CMA), which informally means that without knowledge of the secret key but given a valid signature of a message, it is not possible to come up with a second valid signature for the same message. A security proof in the random oracle model can be found for example in [https://eprint.iacr.org/2016/191 a paper by Kiltz, Masny and Pan], which essentially restates [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf the original security proof of Schnorr signatures by Pointcheval and Stern] more explicitly. These proofs are for the Schnorr signature variant using ''(e,s)'' instead of ''(R,s)'' (see Design above). Since we use a unique encoding of ''R'', there is an efficiently computable bijection that maps ''(R, s)'' to ''(e, s)'', which allows to convert a successful SUF-CMA attacker for the ''(e, s)'' variant to a successful SUF-CMA attacker for the ''(r, s)'' variant (and vice-versa). Furthermore, the aforementioned proofs consider a variant of Schnorr signatures without key prefixing (see Design above), but it can be verified that the proofs are also correct for the variant with key prefixing. As a result, the aforementioned security proofs apply to the variant of Schnorr signatures proposed in this document.. +* '''Non-malleability''': ECDSA signatures are inherently malleable; a third party without access to the secret key can alter an existing valid signature for a given public key and message into another signature that is valid for the same key and message. This issue is discussed in [https://github.com/bitcoin/bips/blob/master/bip-0062.mediawiki BIP62] and [https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki BIP66]. On the other hand, Schnorr signatures are provably non-malleableMore precisely they are '' '''strongly''' unforgeable under chosen message attacks '' (SUF-CMA), which informally means that without knowledge of the secret key but given a valid signature of a message, it is not possible to come up with a second valid signature for the same message. A security proof in the random oracle model can be found for example in [https://eprint.iacr.org/2016/191 a paper by Kiltz, Masny and Pan], which essentially restates [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf the original security proof of Schnorr signatures by Pointcheval and Stern] more explicitly. These proofs are for the Schnorr signature variant using ''(e,s)'' instead of ''(R,s)'' (see Design above). Since we use a unique encoding of ''R'', there is an efficiently computable bijection that maps ''(R, s)'' to ''(e, s)'', which allows to convert a successful SUF-CMA attacker for the ''(e, s)'' variant to a successful SUF-CMA attacker for the ''(r, s)'' variant (and vice-versa). Furthermore, the aforementioned proofs consider a variant of Schnorr signatures without key prefixing (see Design above), but it can be verified that the proofs are also correct for the variant with key prefixing. As a result, the aforementioned security proofs apply to the variant of Schnorr signatures proposed in this document.. * '''Linearity''': Schnorr signatures have the remarkable property that multiple parties can collaborate to produce a signature that is valid for the sum of their public keys. This is the building block for various higher-level constructions that improve efficiency and privacy, such as multisignatures and others (see Applications below). For all these advantages, there are virtually no disadvantages, apart @@ -40,7 +40,7 @@ made: [[File:bip-schnorr/speedup-batch.png|frame|This graph shows the ratio between the time it takes to verify ''n'' signatures individually and to verify a batch of ''n'' signatures. This ratio goes up logarithmically with the number of signatures, or in other words: the total time to verify ''n'' signatures grows with ''O(n / log n)''.]] -By reusing the same curve as Bitcoin has used for ECDSA, we are able to retain existing mechanisms for choosing private and public keys, and we avoid introducing new assumptions about elliptic curve group security. +By reusing the same curve as Bitcoin has used for ECDSA, we are able to retain existing mechanisms for choosing secret and public keys, and we avoid introducing new assumptions about elliptic curve group security. == Description == @@ -83,7 +83,7 @@ Implicit Y coordinates are not a reduction in security when expressed as the num '''Tagged Hashes''' Cryptographic hash functions are used for multiple purposes in the specification below and in Bitcoin in general. To make sure hashes used in one context can't be reinterpreted in another one, hash functions can be tweaked with a context-dependent tag name, in such a way that collisions across contexts can be assumed to be infeasible. Such collisions obviously can not be ruled out completely, but only for schemes using tagging with a unique name. As for other schemes collisions are at least less likely with tagging than without. -For example, without tagged hashing a bip-schnorr signature could also be valid for a signature scheme where the only difference is that the arguments to the hash function are reordered. Worse, if the bip-schnorr nonce derivation function was copied or independently created, then the nonce could be accidentally reused in the other scheme leaking the private key. +For example, without tagged hashing a bip-schnorr signature could also be valid for a signature scheme where the only difference is that the arguments to the hash function are reordered. Worse, if the bip-schnorr nonce derivation function was copied or independently created, then the nonce could be accidentally reused in the other scheme leaking the secret key. This proposal suggests to include the tag by prefixing the hashed data with ''SHA256(tag) || SHA256(tag)''. Because this is a 64-byte long context-specific constant and the ''SHA256'' block size is also 64 bytes, optimized implementations are possible (identical to SHA256 itself, but with a modified initial state). Using SHA256 of the tag name itself is reasonably simple and efficient for implementations that don't choose to use the optimization. -- cgit v1.2.3 From e1d7da3796c3c35508f85bc226b97c1ef7269eb9 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Fri, 27 Sep 2019 09:56:21 +0000 Subject: Add is_quad function to bip-schnorr reference code --- bip-schnorr/reference.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/bip-schnorr/reference.py b/bip-schnorr/reference.py index bd12212..016ce97 100644 --- a/bip-schnorr/reference.py +++ b/bip-schnorr/reference.py @@ -62,6 +62,9 @@ def hash_sha256(b): def jacobi(x): return pow(x, (p - 1) // 2, p) +def is_quad(x): + return jacobi(x) == 1 + def pubkey_gen(seckey): P = point_mul(G, seckey) return bytes_from_point(P) @@ -72,12 +75,12 @@ def schnorr_sign(msg, seckey0): if not (1 <= seckey0 <= n - 1): raise ValueError('The secret key must be an integer in the range 1..n-1.') P = point_mul(G, seckey0) - seckey = seckey0 if (jacobi(y(P)) == 1) else n - seckey0 + seckey = seckey0 if is_quad(y(P)) else n - seckey0 k0 = int_from_bytes(tagged_hash("BIPSchnorrDerive", bytes_from_int(seckey) + msg)) % n if k0 == 0: raise RuntimeError('Failure. This happens only with negligible probability.') R = point_mul(G, k0) - k = n - k0 if (jacobi(y(R)) != 1) else k0 + k = n - k0 if not is_quad(y(R)) else k0 e = int_from_bytes(tagged_hash("BIPSchnorr", bytes_from_point(R) + bytes_from_point(P) + msg)) % n return bytes_from_point(R) + bytes_from_int((k + e * seckey) % n) @@ -97,7 +100,7 @@ def schnorr_verify(msg, pubkey, sig): return False e = int_from_bytes(tagged_hash("BIPSchnorr", sig[0:32] + pubkey + msg)) % n R = point_add(point_mul(G, s), point_mul(P, n - e)) - if R is None or jacobi(y(R)) != 1 or x(R) != r: + if R is None or not is_quad(y(R)) or x(R) != r: return False return True -- cgit v1.2.3 From afa5519ade7d1b90d91fb725bf37eecd38cc4eb3 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Fri, 27 Sep 2019 15:34:55 +0000 Subject: Add taproot_tweak_pubkey and taproot_tweak_privkey functions to bip-taproot wallet section --- bip-taproot.mediawiki | 57 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 35 insertions(+), 22 deletions(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 75eacca..8abf6e1 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -169,14 +169,37 @@ MuSig key aggregation does not have this issue because it already causes the int The attack works as follows: Assume Alice and Mallory want to aggregate their keys into a taproot output key without a script path. In order to prevent key cancellation and related attacks they use [https://eprint.iacr.org/2018/483.pdf MSDL-pop] instead of MuSig. -The MSDL-pop protocol requires all parties to provide a proof of possession of their corresponding private key and the aggregated key is just the sum of the individual keys. +The MSDL-pop protocol requires all parties to provide a proof of possession of their corresponding secret key and the aggregated key is just the sum of the individual keys. After Mallory receives Alice's key ''A'', Mallory creates ''M = M0 + int(t)G'' where ''M0'' is Mallory's original key and ''t'' allows a script path spend with internal key ''P = A + M0'' and a script that only contains Mallory's key. Mallory sends a proof of possession of ''M'' to Alice and both parties compute output key ''Q = A + M = P + int(t)G''. Alice will not be able to notice the script path, but Mallory can unilaterally spend any coin with output key ''Q''. * The remaining scripts should be organized into the leaves of a binary tree. This can be a balanced tree if each of the conditions these scripts correspond to are equally likely. If probabilities for each condition are known, consider constructing the tree as a Huffman tree. -'''Computing the output script''' Once the spending conditions are split into an internal key internal_pubkey and a binary tree whose leaves are (leaf_version, script) tuples, the following Python3 algorithm can be used to compute the output script. In the code below, ser_script prefixes its input with a CCompactSize-encoded length. Public key objects hold 32-byte public keys according to bip-schnorr, have a method get_bytes to get the byte array and a method tweak_add which returns a new public key corresponding to the sum of the public key point and a multiple of the secp256k1 generator (similar to BIP32's derivation). The second return value of tweak_add is a boolean indicating the quadratic residuosity of the Y coordinate of the resulting point. tagged_hash computes the tagged hash according to bip-schnorr. +'''Computing the output script''' Once the spending conditions are split into an internal key internal_pubkey and a binary tree whose leaves are (leaf_version, script) tuples, the output script can be computed using the following Python3 algorithms with helper functions from the bip-schnorr reference code for integer conversion, point multiplication and tagged hashes. + +First, we define taproot_tweak_pubkey for 32-byte bip-schnorr public key arrays. +In addition to the tweaked public key byte array, the function returns a boolean for the quadratic residuosity of the tweaked points' Y coordinate modulo the secp256k1 field order. +This will be required for spending the output with a script path. +In order to allow spending with the key path, we define taproot_tweak_seckey to compute the secret key for a tweaked public key. +For any byte string h it holds that taproot_tweak_pubkey(pubkey_gen(seckey), h)[0] == pubkey_gen(taproot_tweak_seckey(seckey, h)). + + +def taproot_tweak_pubkey(pubkey, h): + t = int_from_bytes(tagged_hash("TapTweak", pubkey + h)) + assert t < SECP256K1_ORDER + Q = point_mul(point(pubkey), t) + return bytes_from_int(x(Q)), is_quad(y(Q)) + +def taproot_tweak_seckey(seckey0, h): + P = point_mul(G, int_from_bytes(seckey0)) + seckey = SECP256K1_ORDER - seckey0 if not is_quad(y(R)) else seckey + t = int_from_bytes(tagged_hash("TapTweak", bytes_from_int(x(P)) + h)) + return (seckey + t) % SECP256K1_ORDER + + +The following function, taproot_output_script, returns a byte array with the scriptPubKey (see BIP141). +ser_script refers to a function that prefixes its input with a CCompactSize-encoded length. def taproot_tree_helper(script_tree): @@ -201,34 +224,25 @@ def taproot_output_script(internal_pubkey, script_tree): h = b'' else: _, h = taproot_tree_helper(script_tree) - t = tagged_hash("TapTweak", internal_pubkey.get_bytes() + h) - assert int.from_bytes(t, 'big') < SECP256K1_ORDER - output_pubkey, _ = internal_pubkey.tweak_add(t) - return bytes([0x51, 0x20]) + output_pubkey.get_bytes() + output_pubkey, _ = taproot_tweak_pubkey(internal_pubkey, h) + return bytes([0x51, 0x20]) + output_pubkey -The function taproot_output_script returns a byte array with the scriptPubKey (see BIP141). - [[File:bip-taproot/tree.png|frame|This diagram shows the hashing structure to obtain the tweak from an internal key ''P'' and a Merkle tree consisting of 5 script leaves. ''A'', ''B'', ''C'' and ''E'' are ''TapLeaf'' hashes similar to ''D'' and ''AB'' is a ''TapBranch'' hash. Note that when ''CDE'' is computed ''E'' is hashed first because ''E'' is less than ''CD''.]] -'''Spending using the key path''' A Taproot output can be spent with the private key corresponding to the internal_pubkey. To do so, a witness stack consists of a single element: a bip-schnorr signature on the signature hash as defined above, with the private key tweaked by the same t as in the above snippet. In the code below, internal_privkey has a method pubkey_gen that returns a public key according to bip-schnorr and a boolean indicating the quadratic residuosity of the Y coordinate of the underlying point. -See the code below: +'''Spending using the key path''' A Taproot output can be spent with the secret key corresponding to the internal_pubkey. To do so, a witness stack consists of a single element: a bip-schnorr signature on the signature hash as defined above, with the secret key tweaked by the same h as in the above snippet. See the code below: -def taproot_sign_key(script_tree, internal_privkey, hash_type): +def taproot_sign_key(script_tree, internal_seckey, hash_type): _, h = taproot_tree_helper(script_tree) - internal_pubkey, is_y_qresidue = internal_privkey.pubkey_gen() - if not is_y_qresidue: - internal_privkey = internal_privkey.negate() - t = tagged_hash("TapTweak", internal_pubkey.get_bytes() + h) - output_privkey = internal_privkey.tweak_add(t) - sig = output_privkey.schnorr_sign(sighash(hash_type)) + output_seckey = taproot_tweak_seckey(internal_seckey, h) + sig = schnorr_sign(sighash(hash_type), output_seckey) if hash_type != 0: sig += bytes([hash_type]) return [sig] -This function returns the witness stack necessary, and assumes a tweak_add method on private keys, and a sighash function to compute the signature hash as defined above (for simplicity, the snippet above ignores passing information like the transaction, the input position, ... to the sighashing code). +This function returns the witness stack necessary and a sighash function to compute the signature hash as defined above (for simplicity, the snippet above ignores passing information like the transaction, the input position, ... to the sighashing code). '''Spending using one of the scripts''' A Taproot output can be spent by satisfying any of the scripts used in its construction. To do so, a witness stack consisting of the script's inputs, plus the script itself and the control block are necessary. See the code below: @@ -236,10 +250,9 @@ This function returns the witness stack necessary, and assumes a tweak_add def taproot_sign_script(internal_pubkey, script_tree, script_num, inputs): info, h = taproot_tree_helper(script_tree) (leaf_version, script), path = info[script_num] - t = tagged_hash("TapTweak", internal_pubkey.get_bytes() + h) - _, is_y_qresidue = internal_pubkey.tweak_add(t) - output_pubkey_tag = 0 if is_y_qresidue else 1 - pubkey_data = bytes([output_pubkey_tag + leaf_version]) + internal_pubkey.get_bytes() + _, is_y_quad = taproot_tweak_pubkey(internal_pubkey, t) + output_pubkey_tag = 0 if is_y_quad else 1 + pubkey_data = bytes([output_pubkey_tag + leaf_version]) + internal_pubkey return inputs + [script, pubkey_data + path] -- cgit v1.2.3 From d112f5b0352f404e2cfebd6f3d9bf030c6894917 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Mon, 30 Sep 2019 11:15:23 +0000 Subject: Replace taproot_tweak_pubkey assertion with exception and add it to taproot_tweak_seckey too --- bip-taproot.mediawiki | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 8abf6e1..ba54689 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -187,7 +187,8 @@ For any byte string h it holds that taproot_tweak_pubkey(pubk def taproot_tweak_pubkey(pubkey, h): t = int_from_bytes(tagged_hash("TapTweak", pubkey + h)) - assert t < SECP256K1_ORDER + if t >= SECP256K1_ORDER: + raise ValueError Q = point_mul(point(pubkey), t) return bytes_from_int(x(Q)), is_quad(y(Q)) @@ -195,6 +196,8 @@ def taproot_tweak_seckey(seckey0, h): P = point_mul(G, int_from_bytes(seckey0)) seckey = SECP256K1_ORDER - seckey0 if not is_quad(y(R)) else seckey t = int_from_bytes(tagged_hash("TapTweak", bytes_from_int(x(P)) + h)) + if t >= SECP256K1_ORDER: + raise ValueError return (seckey + t) % SECP256K1_ORDER -- cgit v1.2.3 From e0e422a5cad47653a092b175dfb1878fef021b0b Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Thu, 3 Oct 2019 11:21:24 +0200 Subject: Link to Schnorr's paper instead of Wikipedia --- bip-schnorr.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 5ae6e87..b0c7e02 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -23,7 +23,7 @@ This document is licensed under the 2-clause BSD license. Bitcoin has traditionally used [https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm ECDSA] signatures over the [http://www.secg.org/sec2-v2.pdf secp256k1 curve] for authenticating transactions. These are [http://www.secg.org/sec1-v2.pdf standardized], but have a number of downsides -compared to [https://en.wikipedia.org/wiki/Schnorr_signature Schnorr signatures] over the same curve: +compared to [http://publikationen.ub.uni-frankfurt.de/opus4/files/4280/schnorr.pdf Schnorr signatures] over the same curve: * '''Security proof''': The security of Schnorr signatures is easily [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf provable] in the random oracle model assuming the elliptic curve discrete logarithm problem (ECDLP) is hard. Such a proof does not exist for ECDSA. * '''Non-malleability''': ECDSA signatures are inherently malleable; a third party without access to the secret key can alter an existing valid signature for a given public key and message into another signature that is valid for the same key and message. This issue is discussed in [https://github.com/bitcoin/bips/blob/master/bip-0062.mediawiki BIP62] and [https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki BIP66]. On the other hand, Schnorr signatures are provably non-malleableMore precisely they are '' '''strongly''' unforgeable under chosen message attacks '' (SUF-CMA), which informally means that without knowledge of the secret key but given a valid signature of a message, it is not possible to come up with a second valid signature for the same message. A security proof in the random oracle model can be found for example in [https://eprint.iacr.org/2016/191 a paper by Kiltz, Masny and Pan], which essentially restates [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf the original security proof of Schnorr signatures by Pointcheval and Stern] more explicitly. These proofs are for the Schnorr signature variant using ''(e,s)'' instead of ''(R,s)'' (see Design above). Since we use a unique encoding of ''R'', there is an efficiently computable bijection that maps ''(R, s)'' to ''(e, s)'', which allows to convert a successful SUF-CMA attacker for the ''(e, s)'' variant to a successful SUF-CMA attacker for the ''(r, s)'' variant (and vice-versa). Furthermore, the aforementioned proofs consider a variant of Schnorr signatures without key prefixing (see Design above), but it can be verified that the proofs are also correct for the variant with key prefixing. As a result, the aforementioned security proofs apply to the variant of Schnorr signatures proposed in this document.. -- cgit v1.2.3 From 78bb31c3bf1aa9459643653e07715d597df4a24f Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Thu, 26 Sep 2019 21:12:21 +0000 Subject: Accept seckey in the form of bytes and not int in the reference BIP-schnorr code to match the spec. --- bip-schnorr/reference.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/bip-schnorr/reference.py b/bip-schnorr/reference.py index 016ce97..e5d9557 100644 --- a/bip-schnorr/reference.py +++ b/bip-schnorr/reference.py @@ -66,12 +66,16 @@ def is_quad(x): return jacobi(x) == 1 def pubkey_gen(seckey): - P = point_mul(G, seckey) + x = int_from_bytes(seckey) + if not (1 <= x <= n - 1): + raise ValueError('The secret key must be an integer in the range 1..n-1.') + P = point_mul(G, x) return bytes_from_point(P) def schnorr_sign(msg, seckey0): if len(msg) != 32: raise ValueError('The message must be a 32-byte array.') + seckey0 = int_from_bytes(seckey0) if not (1 <= seckey0 <= n - 1): raise ValueError('The secret key must be an integer in the range 1..n-1.') P = point_mul(G, seckey0) @@ -122,7 +126,7 @@ def test_vectors(): result = result == 'TRUE' print('\nTest vector #%-3i: ' % int(index)) if seckey != '': - seckey = int(seckey, 16) + seckey = bytes.fromhex(seckey) pubkey_actual = pubkey_gen(seckey) if pubkey != pubkey_actual: print(' * Failed key generation.') -- cgit v1.2.3 From d9a30c954f24cd77f7695d31755ab18ab32deaa7 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 23 Sep 2019 22:48:12 -0700 Subject: Extend codeseparator_position from 16 to 32 bits --- bip-tapscript.mediawiki | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index 1d3e6fa..b88e9c9 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -108,9 +108,9 @@ The one-byte spend_type has a different value, specifically at bit As additional pieces of data, added at the end of the input to the ''hashTapSighash'' function: * tapleaf_hash (32): the tapleaf hash as defined in bip-taproot * key_version (1): a constant value 0x00 representing the current version of public keys in the tapscript signature opcode execution. -* codeseparator_position (2): the opcode position of the last executed OP_CODESEPARATOR before the currently executed signature opcode, with the value in little endian (or 0xffff if none executed). The first opcode in a script has a position of 0. A multi-byte push opcode is counted as one opcode, regardless of the size of data being pushed. +* codeseparator_position (4): the opcode position of the last executed OP_CODESEPARATOR before the currently executed signature opcode, with the value in little endian (or 0xffffffff if none executed). The first opcode in a script has a position of 0. A multi-byte push opcode is counted as one opcode, regardless of the size of data being pushed. -The total number of bytes hashed is at most ''244'''''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''211 - is_anyonecanpay * 50 - is_none * 32 + has_annex * 32''.. +The total number of bytes hashed is at most ''246'''''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''213 - is_anyonecanpay * 50 - is_none * 32 + has_annex * 32''.. In summary, the semantics of the BIP143 sighash types remain unchanged, except the following: # The exceptions mentioned in bip-taproot. -- cgit v1.2.3 From 79f9fc4cc84446fd1002edf7988c6daeb98d9fb5 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 24 Sep 2019 10:36:41 -0700 Subject: Extend input_index from 16 to 32 bits --- bip-taproot.mediawiki | 4 ++-- bip-tapscript.mediawiki | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index ba54689..4827956 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -134,14 +134,14 @@ As the message for signature verification, transaction digest is ''hashTapS *** amount (8): value of the previous output spent by this input. *** nSequence (4): nSequence of this input. ** If the SIGHASH_ANYONECANPAY flag is not set: -*** input_index (2): index of this input in the transaction input vector. Index of the first input is 0. +*** input_index (4): index of this input in the transaction input vector. Index of the first input is 0. ** If the bit-1 of spend_type is set: *** sha_annex (32): the SHA256 of (compact_size(size of annex) || annex). * Data about this output: ** If the SIGHASH_SINGLE flag is set: *** sha_single_output (32): the SHA256 of the corresponding output in CTxOut format. -The total number of bytes hashed is at most ''209'''''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''176 - is_anyonecanpay * 50 - is_none * 32 + has_annex * 32''.. +The total number of bytes hashed is at most ''211'''''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''178 - is_anyonecanpay * 50 - is_none * 32 + has_annex * 32''.. In summary, the semantics of the BIP143 sighash types remain unchanged, except the following: # The way and order of serialization is changed.'''Why is the serialization in the transaction digest changed?''' Hashes that go into the digest and the digest itself are now computed with a single SHA256 invocation instead of double SHA256. There is no expected security improvement by doubling SHA256 because this only protects against length-extension attacks against SHA256 which are not a concern for transaction digests because there is no secret data. Therefore doubling SHA256 is a waste of resources. The digest computation now follows a logical order with transaction level data first, then input data and output data. This allows to efficiently cache the transaction part of the digest across different inputs using the SHA256 midstate. Additionally, digest computation avoids unnecessary hashing as opposed to BIP143 digests in which parts may be set zero and before hashing them. Despite that, collisions are made impossible by committing to the length of the data (implicit in hash_type and spend_type) before the variable length data. diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index b88e9c9..da5dc18 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -110,7 +110,7 @@ As additional pieces of data, added at the end of the input to the ''hashTa * key_version (1): a constant value 0x00 representing the current version of public keys in the tapscript signature opcode execution. * codeseparator_position (4): the opcode position of the last executed OP_CODESEPARATOR before the currently executed signature opcode, with the value in little endian (or 0xffffffff if none executed). The first opcode in a script has a position of 0. A multi-byte push opcode is counted as one opcode, regardless of the size of data being pushed. -The total number of bytes hashed is at most ''246'''''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''213 - is_anyonecanpay * 50 - is_none * 32 + has_annex * 32''.. +The total number of bytes hashed is at most ''248'''''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''215 - is_anyonecanpay * 50 - is_none * 32 + has_annex * 32''.. In summary, the semantics of the BIP143 sighash types remain unchanged, except the following: # The exceptions mentioned in bip-taproot. -- cgit v1.2.3 From fb486d7e13153c3d4180dcf396db6d715463b135 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 7 Oct 2019 14:37:41 -0700 Subject: Fix formula --- bip-taproot.mediawiki | 2 +- bip-tapscript.mediawiki | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 4827956..5058255 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -141,7 +141,7 @@ As the message for signature verification, transaction digest is ''hashTapS ** If the SIGHASH_SINGLE flag is set: *** sha_single_output (32): the SHA256 of the corresponding output in CTxOut format. -The total number of bytes hashed is at most ''211'''''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''178 - is_anyonecanpay * 50 - is_none * 32 + has_annex * 32''.. +The total number of bytes hashed is at most ''211'''''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''178 - is_anyonecanpay * 52 - is_none * 32 + has_annex * 32''.. In summary, the semantics of the BIP143 sighash types remain unchanged, except the following: # The way and order of serialization is changed.'''Why is the serialization in the transaction digest changed?''' Hashes that go into the digest and the digest itself are now computed with a single SHA256 invocation instead of double SHA256. There is no expected security improvement by doubling SHA256 because this only protects against length-extension attacks against SHA256 which are not a concern for transaction digests because there is no secret data. Therefore doubling SHA256 is a waste of resources. The digest computation now follows a logical order with transaction level data first, then input data and output data. This allows to efficiently cache the transaction part of the digest across different inputs using the SHA256 midstate. Additionally, digest computation avoids unnecessary hashing as opposed to BIP143 digests in which parts may be set zero and before hashing them. Despite that, collisions are made impossible by committing to the length of the data (implicit in hash_type and spend_type) before the variable length data. diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index da5dc18..a31774f 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -110,7 +110,7 @@ As additional pieces of data, added at the end of the input to the ''hashTa * key_version (1): a constant value 0x00 representing the current version of public keys in the tapscript signature opcode execution. * codeseparator_position (4): the opcode position of the last executed OP_CODESEPARATOR before the currently executed signature opcode, with the value in little endian (or 0xffffffff if none executed). The first opcode in a script has a position of 0. A multi-byte push opcode is counted as one opcode, regardless of the size of data being pushed. -The total number of bytes hashed is at most ''248'''''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''215 - is_anyonecanpay * 50 - is_none * 32 + has_annex * 32''.. +The total number of bytes hashed is at most ''248'''''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''215 - is_anyonecanpay * 52 - is_none * 32 + has_annex * 32''.. In summary, the semantics of the BIP143 sighash types remain unchanged, except the following: # The exceptions mentioned in bip-taproot. -- cgit v1.2.3 From c93e2985185fb730f098d3d1face57c58a7c18e7 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 8 Oct 2019 18:37:58 -0700 Subject: Increase max Merkle path length --- bip-taproot.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 5058255..4f84c28 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -64,7 +64,7 @@ The following rules only apply when such an output is being spent. Any other out ** The single witness stack element is interpreted as the signature and must be valid (see the next section) for the public key ''q'' and taproot transaction digest (to be defined hereinafter) as message. Fail if it is not. Otherwise pass. * If there are at least two witness elements left, script path spending is used: ** Call the second-to-last stack element ''s'', the script. -** The last stack element is called the control block ''c'', and must have length ''33 + 32m'', for a value of ''m'' that is an integer between 0 and 32, inclusive. Fail if it does not have such a length. +** The last stack element is called the control block ''c'', and must have length ''33 + 32m'', for a value of ''m'' that is an integer between 0 and 128'''Why is the Merkle path length limited to 128?''' The optimally space-efficient Merkle tree can be constructed based on the probabilities of the scripts in the leaves, using the Huffman algorithm. This algorithm will construct branches with lengths approximately equal to ''log2(1/probability)'', but to have branches longer than 128 you would need to have scripts with an execution chance below 1 in ''2128''. As that is our security bound, scripts that truly have such a low chance can probably be removed entirely., inclusive. Fail if it does not have such a length. ** Let ''p = c[1:33]'' and let ''P = point(p)'' where ''point'' is defined as in bip-schnorr. Fail if this point is not on the curve. ** Let ''l = c[0] & 0xfe'', the leaf version'''What is the purpose of the first byte of the control block?''' The first byte of the control block has three distinct functions: * The low bit is used to denote whether the ''Q'' point's Y coordinate is a quadratic residue.'''Why is the quadratic residuosity of the output public key's Y coordinate required in a script path spend?''' The ''point'' function always constructs a point with Y coordinate having that property, but because ''Q'' is constructed by adding the taproot tweak to the internal public key ''P'', it cannot easily be guaranteed that ''Q'' in fact has such a Y coordinate. We can not ignore the Y coordinate because it would prevent batch verification. Trying out multiple internal keys until there's such a ''Q'' is possible but undesirable and unnecessary since this information about the Y coordinate only consumes an unused bit. -- cgit v1.2.3 From 276d9d338b21e48dcb40c4e4c0a5d9f8ff5a20a1 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Wed, 9 Oct 2019 12:12:55 -0700 Subject: Small fix: 0xc1 is possible as first control block byte --- bip-tapscript.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index a31774f..a325573 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -47,7 +47,7 @@ The rules below only apply when validating a transaction input for which all of * The transaction output is a '''segregated witness spend''' (i.e., the scriptPubKey is a witness program as defined in BIP141). * It is a '''taproot spend''' as defined in bip-taproot (i.e., the witness version is 1, the witness program is 32 bytes, and it is not P2SH wrapped). * It is a '''script path spend''' as defined in bip-taproot (i.e., after removing the optional annex from the witness stack, two or more stack elements remain). -* The leaf version is ''0xc0'' (i.e. the first byte of the last witness element after removing the optional annex is ''0xc0'')'''How is the ''0xc0'' constant chosen?''' Following the guidelines in bip-taproot, by choosing a value having the two top bits set, tapscript spends are identifiable even without access to the UTXO being spent., marking it as a '''tapscript spend'''. +* The leaf version is ''0xc0'' (i.e. the first byte of the last witness element after removing the optional annex is ''0xc0'' or ''0xc1'')'''How is the ''0xc0'' constant chosen?''' Following the guidelines in bip-taproot, by choosing a value having the two top bits set, tapscript spends are identifiable even without access to the UTXO being spent., marking it as a '''tapscript spend'''. Validation of such inputs must be equivalent to performing the following steps in the specified order. # If the input is invalid due to BIP16, BIP141, or bip-taproot, fail. -- cgit v1.2.3 From 406bc17c1630a8f05bfd2037578f040a6e34bc46 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 14 Oct 2019 17:55:19 -0700 Subject: Small fixes from review with real-or-random --- bip-schnorr.mediawiki | 76 +++++++++++++++++++++++++-------------------------- 1 file changed, 37 insertions(+), 39 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index b0c7e02..7843510 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -40,7 +40,7 @@ made: [[File:bip-schnorr/speedup-batch.png|frame|This graph shows the ratio between the time it takes to verify ''n'' signatures individually and to verify a batch of ''n'' signatures. This ratio goes up logarithmically with the number of signatures, or in other words: the total time to verify ''n'' signatures grows with ''O(n / log n)''.]] -By reusing the same curve as Bitcoin has used for ECDSA, we are able to retain existing mechanisms for choosing secret and public keys, and we avoid introducing new assumptions about elliptic curve group security. +By reusing the same curve as Bitcoin uses for ECDSA, we are able to retain existing mechanisms for choosing secret and public keys, and we avoid introducing new assumptions about elliptic curve group security. == Description == @@ -75,9 +75,9 @@ In the case of ''R'' the third option is slower at signing time but a bit faster for elliptic curve operations). The two other options require a possibly expensive conversion to affine coordinates first. This would even be the case if the sign or oddness were explicitly coded (option 2 in the previous design choice). We therefore choose option 3. -For ''P'' the speed of signing and verification does not significantly differ between any of the three options because affine coordinates of the point have to be computed anyway. For consistency resons we choose the same option as for ''R''. The signing algorithm ensures that the signature is valid under the correct public key by negating the secret key if necessary. +For ''P'' the speed of signing and verification does not significantly differ between any of the three options because affine coordinates of the point have to be computed anyway. For consistency reasons we choose the same option as for ''R''. The signing algorithm ensures that the signature is valid under the correct public key by negating the secret key if necessary. -It is important to not mix up the 32-byte bip-schnorr public key format and other existing public key formats (e.g. encodings used in Bitcoin's ECDSA). Concretely, a verifier should only accept 32-byte public keys and not, for example, convert a 33-byte public key by throwing away the first byte. Otherwise, two public keys would be valid for a single signature which can result in subtle malleability issues (although this type of malleability already exists in the case of ECDSA signatures). +It is important not to mix up the 32-byte bip-schnorr public key format and other existing public key formats (e.g. encodings used in Bitcoin's ECDSA). Concretely, a verifier should only accept 32-byte public keys and not, for example, convert a 33-byte public key by throwing away the first byte. Otherwise, two public keys would be valid for a single signature which can result in subtle malleability issues (although this type of malleability already exists in the case of ECDSA signatures). Implicit Y coordinates are not a reduction in security when expressed as the number of elliptic curve operations an attacker is expected to perform to compute the secret key. An attacker can normalize any given public key to a point whose Y coordinate is a quadratic residue by negating the point if necessary. This is just a subtraction of field elements and not an elliptic curve operationThis can be formalized by a simple reduction that reduces an attack on Schnorr signatures with implicit Y coordinates to an attack to Schnorr signatures with explicit Y coordinates. The reduction works by reencoding public keys and negating the result of the hash function, which is modeled as random oracle, whenever the challenge public key has an explicit Y coordinate that is not a quadratic residue.. @@ -91,9 +91,7 @@ This proposal suggests to include the tag by prefixing the hashed data with ''SH === Specification === -We first describe the key generation algorithm, then the verification algorithm, and then the signature algorithm. - -The following convention is used, with constants as defined for secp256k1: +The following conventions are used, with constants as defined for [http://www.secg.org/sec2-v2.pdf secp256k1]: * Lowercase variables represent integers or byte arrays. ** The constant ''p'' refers to the field size, ''0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F''. ** The constant ''n'' refers to the curve order, ''0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141''. @@ -108,12 +106,12 @@ The following convention is used, with constants as defined for secp256k1: ** The function ''x[i:j]'', where ''x'' is a byte array, returns a ''(j - i)''-byte array with a copy of the ''i''-th byte (inclusive) to the ''j''-th byte (exclusive) of ''x''. ** The function ''bytes(x)'', where ''x'' is an integer, returns the 32-byte encoding of ''x'', most significant byte first. ** The function ''bytes(P)'', where ''P'' is a point, returns ''bytes(x(P))'. -** The function ''int(x)'', where ''x'' is a 32-byte array, returns the 256-bit unsigned integer whose most significant byte encoding is ''x''. +** The function ''int(x)'', where ''x'' is a 32-byte array, returns the 256-bit unsigned integer whose most significant byte first encoding is ''x''. ** The function ''lift_x(x)'', where ''x'' is an integer in range ''0..p-1'', returns the point ''P'' for which ''x(P) = x'' and ''y(P)'' is a quadratic residue modulo ''p'', or fails if no such point existsGiven an candidate X coordinate ''x'' in the range ''0..p-1'', there exist either exactly two or exactly zero valid Y coordinates. If no valid Y coordinate exists, then ''x'' is not a valid X coordinate either, i.e., no point ''P'' exists for which ''x(P) = x''. Given a candidate ''x'', the valid Y coordinates are the square roots of ''c = x3 + 7 mod p'' and they can be computed as ''y = ±c(p+1)/4 mod p'' (see [https://en.wikipedia.org/wiki/Quadratic_residue#Prime_or_prime_power_modulus Quadratic residue]) if they exist, which can be checked by squaring and comparing with ''c''. Due to [https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion] it then holds that ''c(p-1)/2 = 1 mod p''. The same criterion applied to ''y'' results in ''y(p-1)/2 mod p = ±c((p+1)/4)((p-1)/2) mod p = ±1 mod p''. Therefore ''y = +c(p+1)/4 mod p'' is a quadratic residue and ''-y mod p'' is not.. The function ''lift_x(x)'' is equivalent to the following pseudocode: *** Let ''c = x3 + 7 mod p''. *** Let ''y = c(p+1)/4 mod p''. *** Fail if ''c ≠ y2 mod p''. -*** Return the unique point ''P'' such that ''x(P) = x'' and ''y(P) = y''. +*** Return the unique point ''P'' such that ''x(P) = x'' and ''y(P) = y'', or fail if no such point exists. ** The function ''point(x)'', where ''x'' is a 32-byte array, returns the point ''P = lift_x(int(x))''. ** The function ''hashtag(x)'' where ''tag'' is a UTF-8 encoded tag name and ''x'' is a byte array returns the 32-byte hash ''SHA256(SHA256(tag) || SHA256(tag) || x)''. ** The function ''jacobi(x)'', where ''x'' is an integer, returns the [https://en.wikipedia.org/wiki/Jacobi_symbol Jacobi symbol] of ''x / p''. Since ''p'' is prime, it is equal to ''x(p-1)/2 mod p'' ([https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion])For points ''P'' on the secp256k1 curve it holds that ''jacobi(y(P)) ≠ 0''.. @@ -125,7 +123,7 @@ Input: * The secret key ''sk'': a 32-byte array, generated uniformly at random To generate the corresponding public key: -* Fail if ''int(sk) = 0'' or ''int(sk) >= n'' +* Fail if ''int(sk) = 0'' or ''int(sk) ≥ n'' * The public key corresponding to secret key ''sk'' is ''pubkey(sk)''. Note that the two secret keys ''sk'' and ''bytes(n-int(sk))'' will generate the same public key. @@ -133,6 +131,29 @@ Note that the two secret keys ''sk'' and ''bytes(n-int(sk))'' will generate the Alternatively, the public key can be created according to [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki BIP32] which describes the derivation of 33-byte compressed public keys. In order to translate such public keys into bip-schnorr compatible keys, the first byte must be dropped. +==== Signing ==== + +Input: +* The secret key ''sk'': a 32-byte array +* The message ''m'': a 32-byte array + +To sign ''m'' for public key ''pubkey(sk)'': +* Let ''d' = int(sk)'' +* Fail if ''d' = 0'' or ''d' ≥ n'' +* Let ''P = d'G'' +* Let ''d = d' '' if ''jacobi(y(P)) = 1'', otherwise let ''d = n - d' ''. +* Let ''k' = int(hashBIPSchnorrDerive(bytes(d) || m)) mod n''Note that in general, taking the output of a hash function modulo the curve order will produce an unacceptably biased result. However, for the secp256k1 curve, the order is sufficiently close to ''2256'' that this bias is not observable (''1 - n / 2256'' is around ''1.27 * 2-128'').. +* Fail if ''k' = 0''. +* Let ''R = k'G''. +* Let ''k = k' '' if ''jacobi(y(R)) = 1'', otherwise let ''k = n - k' ''. +* Let ''e = int(hashBIPSchnorr(bytes(R) || bytes(P) || m)) mod n''. +* The signature is ''bytes(R) || bytes((k + ed) mod n)''. + +'''Above deterministic derivation of ''R'' is designed specifically for this signing algorithm and may not be secure when used in other signature schemes.''' +For example, using the same derivation in the MuSig multi-signature scheme leaks the secret key (see the [https://eprint.iacr.org/2018/068 MuSig paper] for details). + +Note that this is not a ''unique signature'' scheme: while this algorithm will always produce the same signature for a given message and public key, ''k'' (and hence ''R'') may be generated in other ways (such as by a CSPRNG) producing a different, but still valid, signature. + ==== Verification ==== Input: @@ -161,35 +182,12 @@ All provided signatures are valid with overwhelming probability if and only if t * Generate ''u-1'' random integers ''a2...u'' in the range ''1...n-1''. They are generated deterministically using a [https://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator CSPRNG] seeded by a cryptographic hash of all inputs of the algorithm, i.e. ''seed = seed_hash(pk1..pku || m1..mu || sig1..sigu )''. A safe choice is to instantiate ''seed_hash'' with SHA256 and use [https://tools.ietf.org/html/rfc8439 ChaCha20] with key ''seed'' as a CSPRNG to generate 256-bit integers, skipping integers not in the range ''1...n-1''. * For ''i = 1 .. u'': ** Let ''Pi = point(pki)''; fail if ''point(pki)'' fails. -** Let ''r = int(sigi[0:32])''; fail if ''r ≥ p''. +** Let ''ri = int(sigi[0:32])''; fail if ''ri ≥ p''. ** Let ''si = int(sigi[32:64])''; fail if ''si ≥ n''. -** Let ''ei = int(hashBIPSchnorr(bytes(r) || bytes(Pi) || mi)) mod n''. -** Let ''Ri = lift_x(r)''; fail if ''lift_x(r)'' fails. +** Let ''ei = int(hashBIPSchnorr(bytes(ri) || bytes(Pi) || mi)) mod n''. +** Let ''Ri = lift_x(ri)''; fail if ''lift_x(ri)'' fails. * Fail if ''(s1 + a2s2 + ... + ausu)G ≠ R1 + a2R2 + ... + auRu + e1P1 + (a2e2)P2 + ... + (aueu)Pu''. -==== Signing ==== - -Input: -* The secret key ''sk'': a 32-byte array -* The message ''m'': a 32-byte array - -To sign ''m'' for public key ''pubkey(sk)'': -* Let ''d' = int(sk)'' -* Fail if ''d' = 0'' or ''d' >= n'' -* Let ''P = d'G'' -* Let ''d = d' '' if ''jacobi(y(P)) = 1'', otherwise let ''d = n - d' ''. -* Let ''k' = int(hashBIPSchnorrDerive(bytes(d) || m)) mod n''Note that in general, taking the output of a hash function modulo the curve order will produce an unacceptably biased result. However, for the secp256k1 curve, the order is sufficiently close to ''2256'' that this bias is not observable (''1 - n / 2256'' is around ''1.27 * 2-128'').. -* Fail if ''k' = 0''. -* Let ''R = k'G''. -* Let ''k = k' '' if ''jacobi(y(R)) = 1'', otherwise let ''k = n - k' ''. -* Let ''e = int(hashBIPSchnorr(bytes(R) || bytes(P) || m)) mod n''. -* The signature is ''bytes(R) || bytes((k + ed) mod n)''. - -'''Above deterministic derivation of ''R'' is designed specifically for this signing algorithm and may not be secure when used in other signature schemes.''' -For example, using the same derivation in the MuSig multi-signature scheme leaks the secret key (see the [https://eprint.iacr.org/2018/068 MuSig paper] for details). - -Note that this is not a ''unique signature'' scheme: while this algorithm will always produce the same signature for a given message and public key, ''k'' (and hence ''R'') may be generated in other ways (such as by a CSPRNG) producing a different, but still valid, signature. - === Optimizations === Many techniques are known for optimizing elliptic curve implementations. Several of them apply here, but are out of scope for this document. Two are listed below however, as they are relevant to the design decisions: @@ -198,7 +196,7 @@ Many techniques are known for optimizing elliptic curve implementations. Several '''Jacobian coordinates''' Elliptic Curve operations can be implemented more efficiently by using [https://en.wikibooks.org/wiki/Cryptography/Prime_Curve/Jacobian_Coordinates Jacobian coordinates]. Elliptic Curve operations implemented this way avoid many intermediate modular inverses (which are computationally expensive), and the scheme proposed in this document is in fact designed to not need any inversions at all for verification. When operating on a point ''P'' with Jacobian coordinates ''(x,y,z)'' which is not the point at infinity and for which ''x(P)'' is defined as ''x / z2'' and ''y(P)'' is defined as ''y / z3'': * ''jacobi(y(P))'' can be implemented as ''jacobi(yz mod p)''. -* ''x(P) ≠ r'' can be implemented as ''x ≠ z2r mod p''. +* ''x(P) ≠ r'' can be implemented as ''(0 ≤ r < p) and (x ≠ z2r mod p)''. == Applications == @@ -207,9 +205,9 @@ While recent academic papers claim that they are also possible with ECDSA, conse === Multisignatures and Threshold Signatures === -By means of an interactive scheme such as [https://eprint.iacr.org/2018/068 MuSig], participants can aggregate their public keys into a single public key which they can jointly sign for. This allows n-of-n multisignatures which, from a verifier's perspective, are no different from ordinary signatures, giving improved privacy and efficiency versus ''CHECKMULTISIG'' or other means. +By means of an interactive scheme such as [https://eprint.iacr.org/2018/068 MuSig], participants can aggregate their public keys into a single public key which they can jointly sign for. This allows ''n''-of-''n'' multisignatures which, from a verifier's perspective, are no different from ordinary signatures, giving improved privacy and efficiency versus ''CHECKMULTISIG'' or other means. -Moreover, Schnorr signatures are compatible with [https://web.archive.org/web/20031003232851/http://www.research.ibm.com/security/dkg.ps distributed key generation], which enables interactive threshold signatures schemes, e.g., the schemes described by [http://cacr.uwaterloo.ca/techreports/2001/corr2001-13.ps Stinson and Strobl (2001)] or [https://web.archive.org/web/20060911151529/http://theory.lcs.mit.edu/~stasio/Papers/gjkr03.pdf Genaro, Jarecki and Krawczyk (2003)]. These protocols make it possible to realize k-of-n threshold signatures, which ensure that any subset of size k of the set of n signers can sign but no subset of size less than k can produce a valid Schnorr signature. However, the practicality of the existing schemes is limited: most schemes in the literature have been proven secure only for the case k < n/2, are not secure when used concurrently in multiple sessions, or require a reliable broadcast mechanism to be secure. Further research is necessary to improve this situation. +Moreover, Schnorr signatures are compatible with [https://web.archive.org/web/20031003232851/http://www.research.ibm.com/security/dkg.ps distributed key generation], which enables interactive threshold signatures schemes, e.g., the schemes described by [http://cacr.uwaterloo.ca/techreports/2001/corr2001-13.ps Stinson and Strobl (2001)] or [https://web.archive.org/web/20060911151529/http://theory.lcs.mit.edu/~stasio/Papers/gjkr03.pdf Genaro, Jarecki and Krawczyk (2003)]. These protocols make it possible to realize ''k''-of-''n'' threshold signatures, which ensure that any subset of size ''k'' of the set of ''n'' signers can sign but no subset of size less than ''k'' can produce a valid Schnorr signature. However, the practicality of the existing schemes is limited: most schemes in the literature have been proven secure only for the case ''k-1 < n/2'', are not secure when used concurrently in multiple sessions, or require a reliable broadcast mechanism to be secure. Further research is necessary to improve this situation. === Adaptor Signatures === @@ -227,7 +225,7 @@ Blind Schnorr signatures could for example be used in [https://github.com/Elemen == Test Vectors and Reference Code == -For development and testing purposes, we provide a [[bip-schnorr/test-vectors.csv|collection of test vectors in CSV format]] and a naive but highly inefficient and non-constant time [[bip-schnorr/reference.py|pure Python 3.7 reference implementation of the signing and verification algorithm]]. +For development and testing purposes, we provide a [[bip-schnorr/test-vectors.csv|collection of test vectors in CSV format]] and a naive, highly inefficient, and non-constant time [[bip-schnorr/reference.py|pure Python 3.7 reference implementation of the signing and verification algorithm]]. The reference implementation is for demonstration purposes only and not to be used in production environments. == Footnotes == -- cgit v1.2.3 From 9b9fab9a03920a65fc8956870db4d1227dcfb28e Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 15 Oct 2019 09:30:06 -0700 Subject: HTTPS links where possible --- bip-schnorr.mediawiki | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 7843510..2674959 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -21,8 +21,8 @@ This document is licensed under the 2-clause BSD license. === Motivation === Bitcoin has traditionally used -[https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm ECDSA] signatures over the [http://www.secg.org/sec2-v2.pdf secp256k1 curve] for authenticating -transactions. These are [http://www.secg.org/sec1-v2.pdf standardized], but have a number of downsides +[https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm ECDSA] signatures over the [https://www.secg.org/sec2-v2.pdf secp256k1 curve] for authenticating +transactions. These are [https://www.secg.org/sec1-v2.pdf standardized], but have a number of downsides compared to [http://publikationen.ub.uni-frankfurt.de/opus4/files/4280/schnorr.pdf Schnorr signatures] over the same curve: * '''Security proof''': The security of Schnorr signatures is easily [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf provable] in the random oracle model assuming the elliptic curve discrete logarithm problem (ECDLP) is hard. Such a proof does not exist for ECDSA. @@ -91,7 +91,7 @@ This proposal suggests to include the tag by prefixing the hashed data with ''SH === Specification === -The following conventions are used, with constants as defined for [http://www.secg.org/sec2-v2.pdf secp256k1]: +The following conventions are used, with constants as defined for [https://www.secg.org/sec2-v2.pdf secp256k1]: * Lowercase variables represent integers or byte arrays. ** The constant ''p'' refers to the field size, ''0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F''. ** The constant ''n'' refers to the curve order, ''0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141''. -- cgit v1.2.3 From 7f5926703a162b8dd18e1d4e024be0c73eeebef2 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 15 Oct 2019 10:34:41 -0700 Subject: Use is_square/is_positive and introduce algorithm names --- bip-schnorr.mediawiki | 56 ++++++++++++++++++++++++++++----------------------- 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 2674959..af279c7 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -68,9 +68,9 @@ Using the first option would be slightly more efficient for verification (around '''Implicit Y coordinates''' In order to support efficient verification and batch verification, the Y coordinate of ''P'' and of ''R'' cannot be ambiguous (every valid X coordinate has two possible Y coordinates). We have a choice between several options for symmetry breaking: # Implicitly choosing the Y coordinate that is in the lower half. # Implicitly choosing the Y coordinate that is evenSince ''p'' is odd, negation modulo ''p'' will map even numbers to odd numbers and the other way around. This means that for a valid X coordinate, one of the corresponding Y coordinates will be even, and the other will be odd.. -# Implicitly choosing the Y coordinate that is a quadratic residue (has a square root modulo the field size)A product of two numbers is a quadratic residue when either both or none of the factors are quadratic residues. As ''-1'' is not a quadratic residue, and the two Y coordinates corresponding to a given X coordinate are each other's negation, this means exactly one of the two must be a quadratic residue.. +# Implicitly choosing the Y coordinate that is a quadratic residue (has a square root modulo the field size, or "is square" for short)A product of two numbers is a quadratic residue when either both or none of the factors are quadratic residues. As ''-1'' is not a quadratic residue, and the two Y coordinates corresponding to a given X coordinate are each other's negation, this means exactly one of the two must be a quadratic residue.. -In the case of ''R'' the third option is slower at signing time but a bit faster to verify, as it is possible to directly compute whether the Y coordinate is a quadratic residue when the points are represented in +In the case of ''R'' the third option is slower at signing time but a bit faster to verify, as it is possible to directly compute whether the Y coordinate is square when the points are represented in [https://en.wikibooks.org/wiki/Cryptography/Prime_Curve/Jacobian_Coordinates Jacobian coordinates] (a common optimization to avoid modular inverses for elliptic curve operations). The two other options require a possibly expensive conversion to affine coordinates first. This would even be the case if the sign or oddness were explicitly coded (option 2 in the previous design choice). We therefore choose option 3. @@ -79,7 +79,7 @@ For ''P'' the speed of signing and verification does not significantly differ be It is important not to mix up the 32-byte bip-schnorr public key format and other existing public key formats (e.g. encodings used in Bitcoin's ECDSA). Concretely, a verifier should only accept 32-byte public keys and not, for example, convert a 33-byte public key by throwing away the first byte. Otherwise, two public keys would be valid for a single signature which can result in subtle malleability issues (although this type of malleability already exists in the case of ECDSA signatures). -Implicit Y coordinates are not a reduction in security when expressed as the number of elliptic curve operations an attacker is expected to perform to compute the secret key. An attacker can normalize any given public key to a point whose Y coordinate is a quadratic residue by negating the point if necessary. This is just a subtraction of field elements and not an elliptic curve operationThis can be formalized by a simple reduction that reduces an attack on Schnorr signatures with implicit Y coordinates to an attack to Schnorr signatures with explicit Y coordinates. The reduction works by reencoding public keys and negating the result of the hash function, which is modeled as random oracle, whenever the challenge public key has an explicit Y coordinate that is not a quadratic residue.. +Implicit Y coordinates are not a reduction in security when expressed as the number of elliptic curve operations an attacker is expected to perform to compute the secret key. An attacker can normalize any given public key to a point whose Y coordinate is square by negating the point if necessary. This is just a subtraction of field elements and not an elliptic curve operationThis can be formalized by a simple reduction that reduces an attack on Schnorr signatures with implicit Y coordinates to an attack to Schnorr signatures with explicit Y coordinates. The reduction works by reencoding public keys and negating the result of the hash function, which is modeled as random oracle, whenever the challenge public key has an explicit Y coordinate that is not square.. '''Tagged Hashes''' Cryptographic hash functions are used for multiple purposes in the specification below and in Bitcoin in general. To make sure hashes used in one context can't be reinterpreted in another one, hash functions can be tweaked with a context-dependent tag name, in such a way that collisions across contexts can be assumed to be infeasible. Such collisions obviously can not be ruled out completely, but only for schemes using tagging with a unique name. As for other schemes collisions are at least less likely with tagging than without. @@ -87,7 +87,7 @@ For example, without tagged hashing a bip-schnorr signature could also be valid This proposal suggests to include the tag by prefixing the hashed data with ''SHA256(tag) || SHA256(tag)''. Because this is a 64-byte long context-specific constant and the ''SHA256'' block size is also 64 bytes, optimized implementations are possible (identical to SHA256 itself, but with a modified initial state). Using SHA256 of the tag name itself is reasonably simple and efficient for implementations that don't choose to use the optimization. -'''Final scheme''' As a result, our final scheme ends up using public key ''pk'' which is the X coordinate of a point ''P'' on the curve whose Y coordinate is a quadratic residue and signatures ''(r,s)'' where ''r'' is the X coordinate of a point ''R'' whose Y coordinate is a quadratic residue. The signature satisfies ''sG = R + tagged_hash(r || pk || m)P''. +'''Final scheme''' As a result, our final scheme ends up using public key ''pk'' which is the X coordinate of a point ''P'' on the curve whose Y coordinate is square and signatures ''(r,s)'' where ''r'' is the X coordinate of a point ''R'' whose Y coordinate is square. The signature satisfies ''sG = R + tagged_hash(r || pk || m)P''. === Specification === @@ -100,33 +100,34 @@ The following conventions are used, with constants as defined for [https://www.s ** ''x(P)'' and ''y(P)'' are integers in the range ''0..p-1'' and refer to the X and Y coordinates of a point ''P'' (assuming it is not infinity). ** The constant ''G'' refers to the generator, for which ''x(G) = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798'' and ''y(G) = 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8''. ** Addition of points refers to the usual [https://en.wikipedia.org/wiki/Elliptic_curve#The_group_law elliptic curve group operation]. -** [https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication Multiplication of an integer and a point] refers to the repeated application of the group operation. +** [https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication Multiplication (⋅) of an integer and a point] refers to the repeated application of the group operation. * Functions and operations: ** ''||'' refers to byte array concatenation. ** The function ''x[i:j]'', where ''x'' is a byte array, returns a ''(j - i)''-byte array with a copy of the ''i''-th byte (inclusive) to the ''j''-th byte (exclusive) of ''x''. ** The function ''bytes(x)'', where ''x'' is an integer, returns the 32-byte encoding of ''x'', most significant byte first. ** The function ''bytes(P)'', where ''P'' is a point, returns ''bytes(x(P))'. ** The function ''int(x)'', where ''x'' is a 32-byte array, returns the 256-bit unsigned integer whose most significant byte first encoding is ''x''. -** The function ''lift_x(x)'', where ''x'' is an integer in range ''0..p-1'', returns the point ''P'' for which ''x(P) = x'' and ''y(P)'' is a quadratic residue modulo ''p'', or fails if no such point existsGiven an candidate X coordinate ''x'' in the range ''0..p-1'', there exist either exactly two or exactly zero valid Y coordinates. If no valid Y coordinate exists, then ''x'' is not a valid X coordinate either, i.e., no point ''P'' exists for which ''x(P) = x''. Given a candidate ''x'', the valid Y coordinates are the square roots of ''c = x3 + 7 mod p'' and they can be computed as ''y = ±c(p+1)/4 mod p'' (see [https://en.wikipedia.org/wiki/Quadratic_residue#Prime_or_prime_power_modulus Quadratic residue]) if they exist, which can be checked by squaring and comparing with ''c''. Due to [https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion] it then holds that ''c(p-1)/2 = 1 mod p''. The same criterion applied to ''y'' results in ''y(p-1)/2 mod p = ±c((p+1)/4)((p-1)/2) mod p = ±1 mod p''. Therefore ''y = +c(p+1)/4 mod p'' is a quadratic residue and ''-y mod p'' is not.. The function ''lift_x(x)'' is equivalent to the following pseudocode: +** The function ''is_square(x)'', where ''x'' is an integer, returns whether or not ''x'' is a quadratic residue modulo ''p''. Since ''p'' is prime, it is equivalent to the Legendre symbol ''(x / p) = x(p-1)/2 mod p'' being equal to ''1'' (see [https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion])For points ''P'' on the secp256k1 curve it holds that ''x(p-1)/2 ≠ 0 mod p''.. +** The function ''is_positive(P)'', where ''P'' is a point, is defined as ''not infinite(P) and is_square(y(P))''For points ''P'' on the secp256k1 curve it holds that ''is_positive(P) = not is_positive(-P)''.. +** The function ''lift_x(x)'', where ''x'' is an integer in range ''0..p-1'', returns the point ''P'' for which ''x(P) = x'' and ''is_positive(P)'', or fails if no such point existsGiven an candidate X coordinate ''x'' in the range ''0..p-1'', there exist either exactly two or exactly zero valid Y coordinates. If no valid Y coordinate exists, then ''x'' is not a valid X coordinate either, i.e., no point ''P'' exists for which ''x(P) = x''. Given a candidate ''x'', the valid Y coordinates are the square roots of ''c = x3 + 7 mod p'' and they can be computed as ''y = ±c(p+1)/4 mod p'' (see [https://en.wikipedia.org/wiki/Quadratic_residue#Prime_or_prime_power_modulus Quadratic residue]) if they exist, which can be checked by squaring and comparing with ''c''. Due to [https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion] it then holds that ''c(p-1)/2 = 1 mod p''. The same criterion applied to ''y'' results in ''y(p-1)/2 mod p = ±c((p+1)/4)((p-1)/2) mod p = ±1 mod p''. Therefore ''y = +c(p+1)/4 mod p'' is a quadratic residue and ''-y mod p'' is not.. The function ''lift_x(x)'' is equivalent to the following pseudocode: *** Let ''c = x3 + 7 mod p''. *** Let ''y = c(p+1)/4 mod p''. *** Fail if ''c ≠ y2 mod p''. *** Return the unique point ''P'' such that ''x(P) = x'' and ''y(P) = y'', or fail if no such point exists. ** The function ''point(x)'', where ''x'' is a 32-byte array, returns the point ''P = lift_x(int(x))''. ** The function ''hashtag(x)'' where ''tag'' is a UTF-8 encoded tag name and ''x'' is a byte array returns the 32-byte hash ''SHA256(SHA256(tag) || SHA256(tag) || x)''. -** The function ''jacobi(x)'', where ''x'' is an integer, returns the [https://en.wikipedia.org/wiki/Jacobi_symbol Jacobi symbol] of ''x / p''. Since ''p'' is prime, it is equal to ''x(p-1)/2 mod p'' ([https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion])For points ''P'' on the secp256k1 curve it holds that ''jacobi(y(P)) ≠ 0''.. -** The function ''pubkey(x)'', where ''x'' is a 32-byte array, returns ''bytes(dG)'' where ''d = int(x) mod n''. ==== Public Key Generation ==== Input: * The secret key ''sk'': a 32-byte array, generated uniformly at random -To generate the corresponding public key: -* Fail if ''int(sk) = 0'' or ''int(sk) ≥ n'' -* The public key corresponding to secret key ''sk'' is ''pubkey(sk)''. +The algorithm ''PubKey(sk)'' is defined as: +* Let ''d = int(sk)''. +* Fail if ''d = 0'' or ''d ≥ n''. +* Return ''bytes(d⋅G)''. -Note that the two secret keys ''sk'' and ''bytes(n-int(sk))'' will generate the same public key. +Note that ''PubKey(sk) = PubKey(bytes(n - int(sk))'', so every public key has two corresponding private keys. Alternatively, the public key can be created according to [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki BIP32] which describes the derivation of 33-byte compressed public keys. In order to translate such public keys into bip-schnorr compatible keys, the first byte must be dropped. @@ -137,19 +138,19 @@ Input: * The secret key ''sk'': a 32-byte array * The message ''m'': a 32-byte array -To sign ''m'' for public key ''pubkey(sk)'': +The algorithm ''Sign(sk,m)'' is defined as: * Let ''d' = int(sk)'' * Fail if ''d' = 0'' or ''d' ≥ n'' * Let ''P = d'G'' -* Let ''d = d' '' if ''jacobi(y(P)) = 1'', otherwise let ''d = n - d' ''. +* Let ''d = d' '' if ''is_positive(P)'', otherwise let ''d = n - d' ''. * Let ''k' = int(hashBIPSchnorrDerive(bytes(d) || m)) mod n''Note that in general, taking the output of a hash function modulo the curve order will produce an unacceptably biased result. However, for the secp256k1 curve, the order is sufficiently close to ''2256'' that this bias is not observable (''1 - n / 2256'' is around ''1.27 * 2-128'').. * Fail if ''k' = 0''. * Let ''R = k'G''. -* Let ''k = k' '' if ''jacobi(y(R)) = 1'', otherwise let ''k = n - k' ''. +* Let ''k = k' '' if ''is_positive(R)'', otherwise let ''k = n - k' ''. * Let ''e = int(hashBIPSchnorr(bytes(R) || bytes(P) || m)) mod n''. -* The signature is ''bytes(R) || bytes((k + ed) mod n)''. +* Return the signature ''bytes(R) || bytes((k + ed) mod n)''. -'''Above deterministic derivation of ''R'' is designed specifically for this signing algorithm and may not be secure when used in other signature schemes.''' +'''Above deterministic derivation of ''R'' is designed specifically for this signing algorithm and may not be secure when used in other signature schemes or for other curves.''' For example, using the same derivation in the MuSig multi-signature scheme leaks the secret key (see the [https://eprint.iacr.org/2018/068 MuSig paper] for details). Note that this is not a ''unique signature'' scheme: while this algorithm will always produce the same signature for a given message and public key, ''k'' (and hence ''R'') may be generated in other ways (such as by a CSPRNG) producing a different, but still valid, signature. @@ -161,14 +162,16 @@ Input: * The message ''m'': a 32-byte array * A signature ''sig'': a 64-byte array -The signature is valid if and only if the algorithm below does not fail. +The algorithm ''Verify(pk,m,sig)'' is defined as: * Let ''P = point(pk)''; fail if ''point(pk)'' fails. * Let ''r = int(sig[0:32])''; fail if ''r ≥ p''. * Let ''s = int(sig[32:64])''; fail if ''s ≥ n''. * Let ''e = int(hashBIPSchnorr(bytes(r) || bytes(P) || m)) mod n''. -* Let ''R = sG - eP''. -* Fail if ''infinite(R)''. -* Fail if ''jacobi(y(R)) ≠ 1'' or ''x(R) ≠ r''. +* Let ''R = s⋅G - e⋅P''. +* Fail if ''not is_positive(R)'' or ''x(R) ≠ r''. +* Return success iff no failure occurred before reaching this point. + +For every valid secret key ''sk'' and message ''m'', ''Verify(PubKey(sk),m,Sign(sk,m))'' will succeed. ==== Batch Verification ==== @@ -178,7 +181,7 @@ Input: * The messages ''m1..u'': ''u'' 32-byte arrays * The signatures ''sig1..u'': ''u'' 64-byte arrays -All provided signatures are valid with overwhelming probability if and only if the algorithm below does not fail. +The algorithm ''BatchVerify(pk1..u,m1..u,sig1..u)'' is defined as: * Generate ''u-1'' random integers ''a2...u'' in the range ''1...n-1''. They are generated deterministically using a [https://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator CSPRNG] seeded by a cryptographic hash of all inputs of the algorithm, i.e. ''seed = seed_hash(pk1..pku || m1..mu || sig1..sigu )''. A safe choice is to instantiate ''seed_hash'' with SHA256 and use [https://tools.ietf.org/html/rfc8439 ChaCha20] with key ''seed'' as a CSPRNG to generate 256-bit integers, skipping integers not in the range ''1...n-1''. * For ''i = 1 .. u'': ** Let ''Pi = point(pki)''; fail if ''point(pki)'' fails. @@ -186,16 +189,19 @@ All provided signatures are valid with overwhelming probability if and only if t ** Let ''si = int(sigi[32:64])''; fail if ''si ≥ n''. ** Let ''ei = int(hashBIPSchnorr(bytes(ri) || bytes(Pi) || mi)) mod n''. ** Let ''Ri = lift_x(ri)''; fail if ''lift_x(ri)'' fails. -* Fail if ''(s1 + a2s2 + ... + ausu)G ≠ R1 + a2R2 + ... + auRu + e1P1 + (a2e2)P2 + ... + (aueu)Pu''. +* Fail if ''(s1 + a2s2 + ... + ausu)⋅G ≠ R1 + a2⋅R2 + ... + au⋅Ru + e1⋅P1 + (a2e2)⋅P2 + ... + (aueu)⋅Pu''. +* Return success iff no failure occurred before reaching this point. + +With overwhelming probability, ''BatchVerify(pk1..u,m1..u,sig1..u) = Verify(pk1,m1,sig1) and Verify(pk2,m2,sig2) and ... and Verify(pku,mu,sigu)''. If all signatures are valid it will always succeed. If one or more signatures are invalid, it will succeed with probability ''2-n''. === Optimizations === Many techniques are known for optimizing elliptic curve implementations. Several of them apply here, but are out of scope for this document. Two are listed below however, as they are relevant to the design decisions: -'''Jacobi symbol''' The function ''jacobi(x)'' is defined as above, but can be computed more efficiently using an [https://en.wikipedia.org/wiki/Jacobi_symbol#Calculating_the_Jacobi_symbol extended GCD algorithm]. +'''Quadratic residue testing''' The function ''is_square(x)'' is defined as above, but can be computed more efficiently using an [https://en.wikipedia.org/wiki/Jacobi_symbol#Calculating_the_Jacobi_symbol extended GCD algorithm]. '''Jacobian coordinates''' Elliptic Curve operations can be implemented more efficiently by using [https://en.wikibooks.org/wiki/Cryptography/Prime_Curve/Jacobian_Coordinates Jacobian coordinates]. Elliptic Curve operations implemented this way avoid many intermediate modular inverses (which are computationally expensive), and the scheme proposed in this document is in fact designed to not need any inversions at all for verification. When operating on a point ''P'' with Jacobian coordinates ''(x,y,z)'' which is not the point at infinity and for which ''x(P)'' is defined as ''x / z2'' and ''y(P)'' is defined as ''y / z3'': -* ''jacobi(y(P))'' can be implemented as ''jacobi(yz mod p)''. +* ''is_positive(P)'' can be implemented as ''is_square(yz mod p)''. * ''x(P) ≠ r'' can be implemented as ''(0 ≤ r < p) and (x ≠ z2r mod p)''. == Applications == -- cgit v1.2.3 From 0d4191bae5facdb7b4ae20ab5f7afc98f7e84877 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 15 Oct 2019 12:11:17 -0700 Subject: Formulate claims about BatchVerify more accurately --- bip-schnorr.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index af279c7..b7bd541 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -192,7 +192,7 @@ The algorithm ''BatchVerify(pk1..u,m1..u,sig1..u1 + a2s2 + ... + ausu)⋅G ≠ R1 + a2⋅R2 + ... + au⋅Ru + e1⋅P1 + (a2e2)⋅P2 + ... + (aueu)⋅Pu''. * Return success iff no failure occurred before reaching this point. -With overwhelming probability, ''BatchVerify(pk1..u,m1..u,sig1..u) = Verify(pk1,m1,sig1) and Verify(pk2,m2,sig2) and ... and Verify(pku,mu,sigu)''. If all signatures are valid it will always succeed. If one or more signatures are invalid, it will succeed with probability ''2-n''. +If all individual signatures are valid (i.e., ''Verify'' would return success for them), ''BatchVerify'' will always return success. If at least one signature is invalid, ''BatchVerify'' will return success with at most a negligable probability. === Optimizations === -- cgit v1.2.3 From e29d82dc88333d265390bff55c1b52a4bc47aeb9 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 15 Oct 2019 12:22:31 -0700 Subject: Apply suggestions from code review Co-Authored-By: Tim Ruffing --- bip-schnorr.mediawiki | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index b7bd541..f63e3ae 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -68,9 +68,9 @@ Using the first option would be slightly more efficient for verification (around '''Implicit Y coordinates''' In order to support efficient verification and batch verification, the Y coordinate of ''P'' and of ''R'' cannot be ambiguous (every valid X coordinate has two possible Y coordinates). We have a choice between several options for symmetry breaking: # Implicitly choosing the Y coordinate that is in the lower half. # Implicitly choosing the Y coordinate that is evenSince ''p'' is odd, negation modulo ''p'' will map even numbers to odd numbers and the other way around. This means that for a valid X coordinate, one of the corresponding Y coordinates will be even, and the other will be odd.. -# Implicitly choosing the Y coordinate that is a quadratic residue (has a square root modulo the field size, or "is square" for short)A product of two numbers is a quadratic residue when either both or none of the factors are quadratic residues. As ''-1'' is not a quadratic residue, and the two Y coordinates corresponding to a given X coordinate are each other's negation, this means exactly one of the two must be a quadratic residue.. +# Implicitly choosing the Y coordinate that is a quadratic residue (has a square root modulo the field size, or "is a square" for short)A product of two numbers is a square when either both or none of the factors are squares. As ''-1'' is not a square, and the two Y coordinates corresponding to a given X coordinate are each other's negation, this means exactly one of the two must be a square.. -In the case of ''R'' the third option is slower at signing time but a bit faster to verify, as it is possible to directly compute whether the Y coordinate is square when the points are represented in +In the case of ''R'' the third option is slower at signing time but a bit faster to verify, as it is possible to directly compute whether the Y coordinate is a square when the points are represented in [https://en.wikibooks.org/wiki/Cryptography/Prime_Curve/Jacobian_Coordinates Jacobian coordinates] (a common optimization to avoid modular inverses for elliptic curve operations). The two other options require a possibly expensive conversion to affine coordinates first. This would even be the case if the sign or oddness were explicitly coded (option 2 in the previous design choice). We therefore choose option 3. @@ -79,7 +79,7 @@ For ''P'' the speed of signing and verification does not significantly differ be It is important not to mix up the 32-byte bip-schnorr public key format and other existing public key formats (e.g. encodings used in Bitcoin's ECDSA). Concretely, a verifier should only accept 32-byte public keys and not, for example, convert a 33-byte public key by throwing away the first byte. Otherwise, two public keys would be valid for a single signature which can result in subtle malleability issues (although this type of malleability already exists in the case of ECDSA signatures). -Implicit Y coordinates are not a reduction in security when expressed as the number of elliptic curve operations an attacker is expected to perform to compute the secret key. An attacker can normalize any given public key to a point whose Y coordinate is square by negating the point if necessary. This is just a subtraction of field elements and not an elliptic curve operationThis can be formalized by a simple reduction that reduces an attack on Schnorr signatures with implicit Y coordinates to an attack to Schnorr signatures with explicit Y coordinates. The reduction works by reencoding public keys and negating the result of the hash function, which is modeled as random oracle, whenever the challenge public key has an explicit Y coordinate that is not square.. +Implicit Y coordinates are not a reduction in security when expressed as the number of elliptic curve operations an attacker is expected to perform to compute the secret key. An attacker can normalize any given public key to a point whose Y coordinate is a square by negating the point if necessary. This is just a subtraction of field elements and not an elliptic curve operationThis can be formalized by a simple reduction that reduces an attack on Schnorr signatures with implicit Y coordinates to an attack to Schnorr signatures with explicit Y coordinates. The reduction works by reencoding public keys and negating the result of the hash function, which is modeled as random oracle, whenever the challenge public key has an explicit Y coordinate that is not a square.. '''Tagged Hashes''' Cryptographic hash functions are used for multiple purposes in the specification below and in Bitcoin in general. To make sure hashes used in one context can't be reinterpreted in another one, hash functions can be tweaked with a context-dependent tag name, in such a way that collisions across contexts can be assumed to be infeasible. Such collisions obviously can not be ruled out completely, but only for schemes using tagging with a unique name. As for other schemes collisions are at least less likely with tagging than without. @@ -87,7 +87,7 @@ For example, without tagged hashing a bip-schnorr signature could also be valid This proposal suggests to include the tag by prefixing the hashed data with ''SHA256(tag) || SHA256(tag)''. Because this is a 64-byte long context-specific constant and the ''SHA256'' block size is also 64 bytes, optimized implementations are possible (identical to SHA256 itself, but with a modified initial state). Using SHA256 of the tag name itself is reasonably simple and efficient for implementations that don't choose to use the optimization. -'''Final scheme''' As a result, our final scheme ends up using public key ''pk'' which is the X coordinate of a point ''P'' on the curve whose Y coordinate is square and signatures ''(r,s)'' where ''r'' is the X coordinate of a point ''R'' whose Y coordinate is square. The signature satisfies ''sG = R + tagged_hash(r || pk || m)P''. +'''Final scheme''' As a result, our final scheme ends up using public key ''pk'' which is the X coordinate of a point ''P'' on the curve whose Y coordinate is a square and signatures ''(r,s)'' where ''r'' is the X coordinate of a point ''R'' whose Y coordinate is a square. The signature satisfies ''sG = R + tagged_hash(r || pk || m)P''. === Specification === @@ -138,10 +138,10 @@ Input: * The secret key ''sk'': a 32-byte array * The message ''m'': a 32-byte array -The algorithm ''Sign(sk,m)'' is defined as: +The algorithm ''Sign(sk, m)'' is defined as: * Let ''d' = int(sk)'' * Fail if ''d' = 0'' or ''d' ≥ n'' -* Let ''P = d'G'' + * Let ''P = d'⋅G'' * Let ''d = d' '' if ''is_positive(P)'', otherwise let ''d = n - d' ''. * Let ''k' = int(hashBIPSchnorrDerive(bytes(d) || m)) mod n''Note that in general, taking the output of a hash function modulo the curve order will produce an unacceptably biased result. However, for the secp256k1 curve, the order is sufficiently close to ''2256'' that this bias is not observable (''1 - n / 2256'' is around ''1.27 * 2-128'').. * Fail if ''k' = 0''. @@ -162,7 +162,7 @@ Input: * The message ''m'': a 32-byte array * A signature ''sig'': a 64-byte array -The algorithm ''Verify(pk,m,sig)'' is defined as: +The algorithm ''Verify(pk, m, sig)'' is defined as: * Let ''P = point(pk)''; fail if ''point(pk)'' fails. * Let ''r = int(sig[0:32])''; fail if ''r ≥ p''. * Let ''s = int(sig[32:64])''; fail if ''s ≥ n''. @@ -181,7 +181,7 @@ Input: * The messages ''m1..u'': ''u'' 32-byte arrays * The signatures ''sig1..u'': ''u'' 64-byte arrays -The algorithm ''BatchVerify(pk1..u,m1..u,sig1..u)'' is defined as: +The algorithm ''BatchVerify(pk1..u, m1..u, sig1..u)'' is defined as: * Generate ''u-1'' random integers ''a2...u'' in the range ''1...n-1''. They are generated deterministically using a [https://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator CSPRNG] seeded by a cryptographic hash of all inputs of the algorithm, i.e. ''seed = seed_hash(pk1..pku || m1..mu || sig1..sigu )''. A safe choice is to instantiate ''seed_hash'' with SHA256 and use [https://tools.ietf.org/html/rfc8439 ChaCha20] with key ''seed'' as a CSPRNG to generate 256-bit integers, skipping integers not in the range ''1...n-1''. * For ''i = 1 .. u'': ** Let ''Pi = point(pki)''; fail if ''point(pki)'' fails. @@ -198,7 +198,7 @@ If all individual signatures are valid (i.e., ''Verify'' would return success fo Many techniques are known for optimizing elliptic curve implementations. Several of them apply here, but are out of scope for this document. Two are listed below however, as they are relevant to the design decisions: -'''Quadratic residue testing''' The function ''is_square(x)'' is defined as above, but can be computed more efficiently using an [https://en.wikipedia.org/wiki/Jacobi_symbol#Calculating_the_Jacobi_symbol extended GCD algorithm]. +'''Squareness testing''' The function ''is_square(x)'' is defined as above, but can be computed more efficiently using an [https://en.wikipedia.org/wiki/Jacobi_symbol#Calculating_the_Jacobi_symbol extended GCD algorithm]. '''Jacobian coordinates''' Elliptic Curve operations can be implemented more efficiently by using [https://en.wikibooks.org/wiki/Cryptography/Prime_Curve/Jacobian_Coordinates Jacobian coordinates]. Elliptic Curve operations implemented this way avoid many intermediate modular inverses (which are computationally expensive), and the scheme proposed in this document is in fact designed to not need any inversions at all for verification. When operating on a point ''P'' with Jacobian coordinates ''(x,y,z)'' which is not the point at infinity and for which ''x(P)'' is defined as ''x / z2'' and ''y(P)'' is defined as ''y / z3'': * ''is_positive(P)'' can be implemented as ''is_square(yz mod p)''. -- cgit v1.2.3 From 281df660b95de712a846cb3462cccb131073bc45 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 15 Oct 2019 12:24:07 -0700 Subject: Prefix infinite with is_ --- bip-schnorr.mediawiki | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index f63e3ae..dbc474b 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -96,7 +96,7 @@ The following conventions are used, with constants as defined for [https://www.s ** The constant ''p'' refers to the field size, ''0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F''. ** The constant ''n'' refers to the curve order, ''0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141''. * Uppercase variables refer to points on the curve with equation ''y2 = x3 + 7'' over the integers modulo ''p''. -** ''infinite(P)'' returns whether or not ''P'' is the point at infinity. +** ''is_infinite(P)'' returns whether or not ''P'' is the point at infinity. ** ''x(P)'' and ''y(P)'' are integers in the range ''0..p-1'' and refer to the X and Y coordinates of a point ''P'' (assuming it is not infinity). ** The constant ''G'' refers to the generator, for which ''x(G) = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798'' and ''y(G) = 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8''. ** Addition of points refers to the usual [https://en.wikipedia.org/wiki/Elliptic_curve#The_group_law elliptic curve group operation]. @@ -108,7 +108,7 @@ The following conventions are used, with constants as defined for [https://www.s ** The function ''bytes(P)'', where ''P'' is a point, returns ''bytes(x(P))'. ** The function ''int(x)'', where ''x'' is a 32-byte array, returns the 256-bit unsigned integer whose most significant byte first encoding is ''x''. ** The function ''is_square(x)'', where ''x'' is an integer, returns whether or not ''x'' is a quadratic residue modulo ''p''. Since ''p'' is prime, it is equivalent to the Legendre symbol ''(x / p) = x(p-1)/2 mod p'' being equal to ''1'' (see [https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion])For points ''P'' on the secp256k1 curve it holds that ''x(p-1)/2 ≠ 0 mod p''.. -** The function ''is_positive(P)'', where ''P'' is a point, is defined as ''not infinite(P) and is_square(y(P))''For points ''P'' on the secp256k1 curve it holds that ''is_positive(P) = not is_positive(-P)''.. +** The function ''is_positive(P)'', where ''P'' is a point, is defined as ''not is_infinite(P) and is_square(y(P))''For points ''P'' on the secp256k1 curve it holds that ''is_positive(P) = not is_positive(-P)''.. ** The function ''lift_x(x)'', where ''x'' is an integer in range ''0..p-1'', returns the point ''P'' for which ''x(P) = x'' and ''is_positive(P)'', or fails if no such point existsGiven an candidate X coordinate ''x'' in the range ''0..p-1'', there exist either exactly two or exactly zero valid Y coordinates. If no valid Y coordinate exists, then ''x'' is not a valid X coordinate either, i.e., no point ''P'' exists for which ''x(P) = x''. Given a candidate ''x'', the valid Y coordinates are the square roots of ''c = x3 + 7 mod p'' and they can be computed as ''y = ±c(p+1)/4 mod p'' (see [https://en.wikipedia.org/wiki/Quadratic_residue#Prime_or_prime_power_modulus Quadratic residue]) if they exist, which can be checked by squaring and comparing with ''c''. Due to [https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion] it then holds that ''c(p-1)/2 = 1 mod p''. The same criterion applied to ''y'' results in ''y(p-1)/2 mod p = ±c((p+1)/4)((p-1)/2) mod p = ±1 mod p''. Therefore ''y = +c(p+1)/4 mod p'' is a quadratic residue and ''-y mod p'' is not.. The function ''lift_x(x)'' is equivalent to the following pseudocode: *** Let ''c = x3 + 7 mod p''. *** Let ''y = c(p+1)/4 mod p''. -- cgit v1.2.3 From 96a199ac8c6a457723ec37534c0db673e20716ee Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 15 Oct 2019 12:26:21 -0700 Subject: Drop other curve comment --- bip-schnorr.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index dbc474b..5dd5305 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -150,7 +150,7 @@ The algorithm ''Sign(sk, m)'' is defined as: * Let ''e = int(hashBIPSchnorr(bytes(R) || bytes(P) || m)) mod n''. * Return the signature ''bytes(R) || bytes((k + ed) mod n)''. -'''Above deterministic derivation of ''R'' is designed specifically for this signing algorithm and may not be secure when used in other signature schemes or for other curves.''' +'''Above deterministic derivation of ''R'' is designed specifically for this signing algorithm and may not be secure when used in other signature schemes.''' For example, using the same derivation in the MuSig multi-signature scheme leaks the secret key (see the [https://eprint.iacr.org/2018/068 MuSig paper] for details). Note that this is not a ''unique signature'' scheme: while this algorithm will always produce the same signature for a given message and public key, ''k'' (and hence ''R'') may be generated in other ways (such as by a CSPRNG) producing a different, but still valid, signature. -- cgit v1.2.3 From 565ac4f7175e4c25b92a5b5c933d0fa461263b7e Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 15 Oct 2019 12:29:52 -0700 Subject: Typo --- bip-schnorr.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 5dd5305..c936ed3 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -192,7 +192,7 @@ The algorithm ''BatchVerify(pk1..u, m1..u, sig1..u1 + a2s2 + ... + ausu)⋅G ≠ R1 + a2⋅R2 + ... + au⋅Ru + e1⋅P1 + (a2e2)⋅P2 + ... + (aueu)⋅Pu''. * Return success iff no failure occurred before reaching this point. -If all individual signatures are valid (i.e., ''Verify'' would return success for them), ''BatchVerify'' will always return success. If at least one signature is invalid, ''BatchVerify'' will return success with at most a negligable probability. +If all individual signatures are valid (i.e., ''Verify'' would return success for them), ''BatchVerify'' will always return success. If at least one signature is invalid, ''BatchVerify'' will return success with at most a negligible probability. === Optimizations === -- cgit v1.2.3 From bc4e8f28b8f3f27e46ea1a70fc0ffa398ab51aff Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Tue, 15 Oct 2019 16:02:09 -0700 Subject: bip-schnorr: more on provable security I'll try to get a link to the CCS paper that does not have a paywall... --- bip-schnorr.mediawiki | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index c936ed3..d7ac9b1 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -25,8 +25,8 @@ Bitcoin has traditionally used transactions. These are [https://www.secg.org/sec1-v2.pdf standardized], but have a number of downsides compared to [http://publikationen.ub.uni-frankfurt.de/opus4/files/4280/schnorr.pdf Schnorr signatures] over the same curve: -* '''Security proof''': The security of Schnorr signatures is easily [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf provable] in the random oracle model assuming the elliptic curve discrete logarithm problem (ECDLP) is hard. Such a proof does not exist for ECDSA. -* '''Non-malleability''': ECDSA signatures are inherently malleable; a third party without access to the secret key can alter an existing valid signature for a given public key and message into another signature that is valid for the same key and message. This issue is discussed in [https://github.com/bitcoin/bips/blob/master/bip-0062.mediawiki BIP62] and [https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki BIP66]. On the other hand, Schnorr signatures are provably non-malleableMore precisely they are '' '''strongly''' unforgeable under chosen message attacks '' (SUF-CMA), which informally means that without knowledge of the secret key but given a valid signature of a message, it is not possible to come up with a second valid signature for the same message. A security proof in the random oracle model can be found for example in [https://eprint.iacr.org/2016/191 a paper by Kiltz, Masny and Pan], which essentially restates [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf the original security proof of Schnorr signatures by Pointcheval and Stern] more explicitly. These proofs are for the Schnorr signature variant using ''(e,s)'' instead of ''(R,s)'' (see Design above). Since we use a unique encoding of ''R'', there is an efficiently computable bijection that maps ''(R, s)'' to ''(e, s)'', which allows to convert a successful SUF-CMA attacker for the ''(e, s)'' variant to a successful SUF-CMA attacker for the ''(r, s)'' variant (and vice-versa). Furthermore, the aforementioned proofs consider a variant of Schnorr signatures without key prefixing (see Design above), but it can be verified that the proofs are also correct for the variant with key prefixing. As a result, the aforementioned security proofs apply to the variant of Schnorr signatures proposed in this document.. +* '''Provable security''': Schnorr signatures are provably secure. In more detail, they are ''strongly unforgeable under chosen message attack (SUF-CMA)''Informally, this means that without knowledge of the secret key but given valid signatures of arbitrary messages, it is not possible to come up with further valid signatures. [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf in the random oracle model assuming the hardness of the elliptic curve discrete logarithm problem (ECDLP)] and [http://www.neven.org/papers/schnorr.pdf in the generic group model assuming prefix assuming variants of preimage and second preimage resistance of the used hash function]A detailed security proof in the random oracle model, which essentially restates [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf the original security proof by Pointcheval and Stern] more explicitly, can be found in [https://eprint.iacr.org/2016/191 a paper by Kiltz, Masny and Pan]. All these security proofs assume a variant of Schnorr signatures that use ''(e,s)'' instead of ''(R,s)'' (see Design above). Since we use a unique encoding of ''R'', there is an efficiently computable bijection that maps ''(R, s)'' to ''(e, s)'', which allows to convert a successful SUF-CMA attacker for the ''(e, s)'' variant to a successful SUF-CMA attacker for the ''(r, s)'' variant (and vice-versa). Furthermore, the proofs consider a variant of Schnorr signatures without key prefixing (see Design above), but it can be verified that the proofs are also correct for the variant with key prefixing. As a result, all the aforementioned security proofs apply to the variant of Schnorr signatures proposed in this document.. The [https://dl.acm.org/citation.cfm?id=2978413 best known security proof for ECDSA] relies on stronger assumptions. +* '''Non-malleability''': The SUF-CMA security of Schnorr signatures implies that they are non-malleable. On the other hand, ECDSA signatures are inherently malleable; a third party without access to the secret key can alter an existing valid signature for a given public key and message into another signature that is valid for the same key and message. This issue is discussed in [https://github.com/bitcoin/bips/blob/master/bip-0062.mediawiki BIP62] and [https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki BIP66]. * '''Linearity''': Schnorr signatures have the remarkable property that multiple parties can collaborate to produce a signature that is valid for the sum of their public keys. This is the building block for various higher-level constructions that improve efficiency and privacy, such as multisignatures and others (see Applications below). For all these advantages, there are virtually no disadvantages, apart -- cgit v1.2.3 From a7ee6c30faae3e6f4062152f0e910abd3f446a86 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Tue, 15 Oct 2019 16:21:40 -0700 Subject: bip-schnorr: more on (e,s) --- bip-schnorr.mediawiki | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index d7ac9b1..1876469 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -25,7 +25,7 @@ Bitcoin has traditionally used transactions. These are [https://www.secg.org/sec1-v2.pdf standardized], but have a number of downsides compared to [http://publikationen.ub.uni-frankfurt.de/opus4/files/4280/schnorr.pdf Schnorr signatures] over the same curve: -* '''Provable security''': Schnorr signatures are provably secure. In more detail, they are ''strongly unforgeable under chosen message attack (SUF-CMA)''Informally, this means that without knowledge of the secret key but given valid signatures of arbitrary messages, it is not possible to come up with further valid signatures. [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf in the random oracle model assuming the hardness of the elliptic curve discrete logarithm problem (ECDLP)] and [http://www.neven.org/papers/schnorr.pdf in the generic group model assuming prefix assuming variants of preimage and second preimage resistance of the used hash function]A detailed security proof in the random oracle model, which essentially restates [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf the original security proof by Pointcheval and Stern] more explicitly, can be found in [https://eprint.iacr.org/2016/191 a paper by Kiltz, Masny and Pan]. All these security proofs assume a variant of Schnorr signatures that use ''(e,s)'' instead of ''(R,s)'' (see Design above). Since we use a unique encoding of ''R'', there is an efficiently computable bijection that maps ''(R, s)'' to ''(e, s)'', which allows to convert a successful SUF-CMA attacker for the ''(e, s)'' variant to a successful SUF-CMA attacker for the ''(r, s)'' variant (and vice-versa). Furthermore, the proofs consider a variant of Schnorr signatures without key prefixing (see Design above), but it can be verified that the proofs are also correct for the variant with key prefixing. As a result, all the aforementioned security proofs apply to the variant of Schnorr signatures proposed in this document.. The [https://dl.acm.org/citation.cfm?id=2978413 best known security proof for ECDSA] relies on stronger assumptions. +* '''Provable security''': Schnorr signatures are provably secure. In more detail, they are ''strongly unforgeable under chosen message attack (SUF-CMA)''Informally, this means that without knowledge of the secret key but given valid signatures of arbitrary messages, it is not possible to come up with further valid signatures. [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf in the random oracle model assuming the hardness of the elliptic curve discrete logarithm problem (ECDLP)] and [http://www.neven.org/papers/schnorr.pdf in the generic group model assuming variants of preimage and second preimage resistance of the used hash function]A detailed security proof in the random oracle model, which essentially restates [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf the original security proof by Pointcheval and Stern] more explicitly, can be found in [https://eprint.iacr.org/2016/191 a paper by Kiltz, Masny and Pan]. All these security proofs assume a variant of Schnorr signatures that use ''(e,s)'' instead of ''(R,s)'' (see Design above). Since we use a unique encoding of ''R'', there is an efficiently computable bijection that maps ''(R,s)'' to ''(e,s)'', which allows to convert a successful SUF-CMA attacker for the ''(e,s)'' variant to a successful SUF-CMA attacker for the ''(r,s)'' variant (and vice-versa). Furthermore, the proofs consider a variant of Schnorr signatures without key prefixing (see Design above), but it can be verified that the proofs are also correct for the variant with key prefixing. As a result, all the aforementioned security proofs apply to the variant of Schnorr signatures proposed in this document.. The [https://dl.acm.org/citation.cfm?id=2978413 best known security proof for ECDSA] relies on stronger assumptions. * '''Non-malleability''': The SUF-CMA security of Schnorr signatures implies that they are non-malleable. On the other hand, ECDSA signatures are inherently malleable; a third party without access to the secret key can alter an existing valid signature for a given public key and message into another signature that is valid for the same key and message. This issue is discussed in [https://github.com/bitcoin/bips/blob/master/bip-0062.mediawiki BIP62] and [https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki BIP66]. * '''Linearity''': Schnorr signatures have the remarkable property that multiple parties can collaborate to produce a signature that is valid for the sum of their public keys. This is the building block for various higher-level constructions that improve efficiency and privacy, such as multisignatures and others (see Applications below). @@ -38,8 +38,6 @@ made: * '''Public key encoding''': Instead of using ''compressed'' 33-byte encodings of elliptic curve points which are common in Bitcoin today, public keys in this proposal are encoded as 32 bytes. * '''Batch verification''': The specific formulation of ECDSA signatures that is standardized cannot be verified more efficiently in batch compared to individually, unless additional witness data is added. Changing the signature scheme offers an opportunity to avoid this. -[[File:bip-schnorr/speedup-batch.png|frame|This graph shows the ratio between the time it takes to verify ''n'' signatures individually and to verify a batch of ''n'' signatures. This ratio goes up logarithmically with the number of signatures, or in other words: the total time to verify ''n'' signatures grows with ''O(n / log n)''.]] - By reusing the same curve as Bitcoin uses for ECDSA, we are able to retain existing mechanisms for choosing secret and public keys, and we avoid introducing new assumptions about elliptic curve group security. == Description == @@ -50,13 +48,15 @@ encodings and operations. === Design === -'''Schnorr signature variant''' Elliptic Curve Schnorr signatures for message ''m'' and public key ''P'' generally involve a point ''R'', integers ''e'' and ''s'' picked by the signer, and generator ''G'' which satisfy ''e = hash(R || m)'' and ''sG = R + eP''. Two formulations exist, depending on whether the signer reveals ''e'' or ''R'': -# Signatures are ''(e,s)'' that satisfy ''e = hash(sG - eP || m)''. This avoids minor complexity introduced by the encoding of the point ''R'' in the signature (see paragraphs "Encoding the sign of R" and "Implicit Y coordinate" further below in this subsection). -# Signatures are ''(R,s)'' that satisfy ''sG = R + hash(R || m)P''. This supports batch verification, as there are no elliptic curve operations inside the hashes. +'''Schnorr signature variant''' Elliptic Curve Schnorr signatures for message ''m'' and public key ''P'' generally involve a point ''R'', integers ''e'' and ''s'' picked by the signer, and generator ''G'' which satisfy ''e = hash(R || m)'' and ''s⋅G = R + e⋅P''. Two formulations exist, depending on whether the signer reveals ''e'' or ''R'': +# Signatures are ''(e,s)'' that satisfy ''e = hash(s⋅G - e⋅P || m)''. This supports more compact signatures, since [http://www.neven.org/papers/schnorr.pdf the hash ''e'' can be made as small as 16 bytes without sacrificing security], whereas an encoding of ''R'' inherently needs about 32 bytes. Moreover, this variant avoids minor complexity introduced by the encoding of the point ''R'' in the signature (see paragraphs "Encoding the sign of R" and "Implicit Y coordinate" further below in this subsection). +# Signatures are ''(R,s)'' that satisfy ''s⋅G = R + hash(R || m)⋅P''. This supports batch verification, as there are no elliptic curve operations inside the hashes. Batch verification enables significant speedups. + +[[File:bip-schnorr/speedup-batch.png|center|frame|This graph shows the ratio between the time it takes to verify ''n'' signatures individually and to verify a batch of ''n'' signatures. This ratio goes up logarithmically with the number of signatures, or in other words: the total time to verify ''n'' signatures grows with ''O(n / log n)''.]] We choose the ''R''-option to support batch verification. -'''Key prefixing''' When using the verification rule above directly, it is possible for a third party to convert a signature ''(R,s)'' for key ''P'' into a signature ''(R,s + a⋅hash(R || m))'' for key ''P + aG'' and the same message, for any integer ''a''. This is not a concern for Bitcoin currently, as all signature hashes indirectly commit to the public keys. However, this may change with proposals such as SIGHASH_NOINPUT ([https://github.com/bitcoin/bips/blob/master/bip-0118.mediawiki BIP 118]), or when the signature scheme is used for other purposes—especially in combination with schemes like [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki BIP32]'s unhardened derivation. To combat this, we choose ''key prefixed''A limitation of committing to the public key (rather than to a short hash of it, or not at all) is that it removes the ability for public key recovery or verifying signatures against a short public key hash. These constructions are generally incompatible with batch verification. Schnorr signatures; changing the equation to ''sG = R + hash(R || P || m)P''. +'''Key prefixing''' When using the verification rule above directly, it is possible for a third party to convert a signature ''(R,s)'' for key ''P'' into a signature ''(R,s + a⋅hash(R || m))'' for key ''P + a⋅G'' and the same message, for any integer ''a''. This is not a concern for Bitcoin currently, as all signature hashes indirectly commit to the public keys. However, this may change with proposals such as SIGHASH_NOINPUT ([https://github.com/bitcoin/bips/blob/master/bip-0118.mediawiki BIP 118]), or when the signature scheme is used for other purposes—especially in combination with schemes like [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki BIP32]'s unhardened derivation. To combat this, we choose ''key prefixed''A limitation of committing to the public key (rather than to a short hash of it, or not at all) is that it removes the ability for public key recovery or verifying signatures against a short public key hash. These constructions are generally incompatible with batch verification. Schnorr signatures; changing the equation to ''s⋅G = R + hash(R || P || m)⋅P''. '''Encoding R and public key point P''' There exist several possibilities for encoding elliptic curve points: # Encoding the full X and Y coordinates of ''P'' and ''R'', resulting in a 64-byte public key and a 96-byte signature. @@ -87,7 +87,7 @@ For example, without tagged hashing a bip-schnorr signature could also be valid This proposal suggests to include the tag by prefixing the hashed data with ''SHA256(tag) || SHA256(tag)''. Because this is a 64-byte long context-specific constant and the ''SHA256'' block size is also 64 bytes, optimized implementations are possible (identical to SHA256 itself, but with a modified initial state). Using SHA256 of the tag name itself is reasonably simple and efficient for implementations that don't choose to use the optimization. -'''Final scheme''' As a result, our final scheme ends up using public key ''pk'' which is the X coordinate of a point ''P'' on the curve whose Y coordinate is a square and signatures ''(r,s)'' where ''r'' is the X coordinate of a point ''R'' whose Y coordinate is a square. The signature satisfies ''sG = R + tagged_hash(r || pk || m)P''. +'''Final scheme''' As a result, our final scheme ends up using public key ''pk'' which is the X coordinate of a point ''P'' on the curve whose Y coordinate is a square and signatures ''(r,s)'' where ''r'' is the X coordinate of a point ''R'' whose Y coordinate is a square. The signature satisfies ''s⋅G = R + tagged_hash(r || pk || m)⋅P''. === Specification === @@ -141,7 +141,7 @@ Input: The algorithm ''Sign(sk, m)'' is defined as: * Let ''d' = int(sk)'' * Fail if ''d' = 0'' or ''d' ≥ n'' - * Let ''P = d'⋅G'' +* Let ''P = d'⋅G'' * Let ''d = d' '' if ''is_positive(P)'', otherwise let ''d = n - d' ''. * Let ''k' = int(hashBIPSchnorrDerive(bytes(d) || m)) mod n''Note that in general, taking the output of a hash function modulo the curve order will produce an unacceptably biased result. However, for the secp256k1 curve, the order is sufficiently close to ''2256'' that this bias is not observable (''1 - n / 2256'' is around ''1.27 * 2-128'').. * Fail if ''k' = 0''. -- cgit v1.2.3 From aef148ffc622330ea1308c53b154aeeadd22ef10 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 15 Oct 2019 15:21:08 -0700 Subject: Explain that MuSig needs key prefixing --- bip-schnorr.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 1876469..4fede9d 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -56,7 +56,7 @@ encodings and operations. We choose the ''R''-option to support batch verification. -'''Key prefixing''' When using the verification rule above directly, it is possible for a third party to convert a signature ''(R,s)'' for key ''P'' into a signature ''(R,s + a⋅hash(R || m))'' for key ''P + a⋅G'' and the same message, for any integer ''a''. This is not a concern for Bitcoin currently, as all signature hashes indirectly commit to the public keys. However, this may change with proposals such as SIGHASH_NOINPUT ([https://github.com/bitcoin/bips/blob/master/bip-0118.mediawiki BIP 118]), or when the signature scheme is used for other purposes—especially in combination with schemes like [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki BIP32]'s unhardened derivation. To combat this, we choose ''key prefixed''A limitation of committing to the public key (rather than to a short hash of it, or not at all) is that it removes the ability for public key recovery or verifying signatures against a short public key hash. These constructions are generally incompatible with batch verification. Schnorr signatures; changing the equation to ''s⋅G = R + hash(R || P || m)⋅P''. +'''Key prefixing''' When using the verification rule above directly, it is possible for a third party to convert a signature ''(R, s)'' for key ''P'' into a signature ''(R, s + a⋅hash(R || m))'' for key ''P + a⋅G'' and the same message, for any integer ''a''. To combat this, we choose ''key prefixed''A limitation of committing to the public key (rather than to a short hash of it, or not at all) is that it removes the ability for public key recovery or verifying signatures against a short public key hash. These constructions are generally incompatible with batch verification. Schnorr signatures; changing the equation to ''s⋅G = R + hash(R || P || m)⋅P''. Key prefixing also seems to be a requirement for the security proof of the MuSig multisignature scheme (see below, under applications). It is not strictly necessary to do this explicitly for Bitcoin currently, as all signature hashes indirectly commit to the public keys already. However, this may change with proposals such as SIGHASH_NOINPUT ([https://github.com/bitcoin/bips/blob/master/bip-0118.mediawiki BIP 118]), or when the signature scheme is used for other purposes—especially in combination with schemes like [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki BIP32]'s unhardened derivation. '''Encoding R and public key point P''' There exist several possibilities for encoding elliptic curve points: # Encoding the full X and Y coordinates of ''P'' and ''R'', resulting in a 64-byte public key and a 96-byte signature. -- cgit v1.2.3 From 20f9901809de4850da8d25f0913c65e77b7fd754 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 15 Oct 2019 17:28:52 -0700 Subject: Update bip-schnorr.mediawiki Co-Authored-By: Tim Ruffing --- bip-schnorr.mediawiki | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 4fede9d..12a7379 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -49,14 +49,14 @@ encodings and operations. === Design === '''Schnorr signature variant''' Elliptic Curve Schnorr signatures for message ''m'' and public key ''P'' generally involve a point ''R'', integers ''e'' and ''s'' picked by the signer, and generator ''G'' which satisfy ''e = hash(R || m)'' and ''s⋅G = R + e⋅P''. Two formulations exist, depending on whether the signer reveals ''e'' or ''R'': -# Signatures are ''(e,s)'' that satisfy ''e = hash(s⋅G - e⋅P || m)''. This supports more compact signatures, since [http://www.neven.org/papers/schnorr.pdf the hash ''e'' can be made as small as 16 bytes without sacrificing security], whereas an encoding of ''R'' inherently needs about 32 bytes. Moreover, this variant avoids minor complexity introduced by the encoding of the point ''R'' in the signature (see paragraphs "Encoding the sign of R" and "Implicit Y coordinate" further below in this subsection). -# Signatures are ''(R,s)'' that satisfy ''s⋅G = R + hash(R || m)⋅P''. This supports batch verification, as there are no elliptic curve operations inside the hashes. Batch verification enables significant speedups. +# Signatures are ''(e, s)'' that satisfy ''e = hash(s⋅G - e⋅P || m)''. This supports more compact signatures, since [http://www.neven.org/papers/schnorr.pdf the hash ''e'' can be made as small as 16 bytes without sacrificing security], whereas an encoding of ''R'' inherently needs about 32 bytes. Moreover, this variant avoids minor complexity introduced by the encoding of the point ''R'' in the signature (see paragraphs "Encoding the sign of R" and "Implicit Y coordinate" further below in this subsection). +# Signatures are ''(R, s)'' that satisfy ''s⋅G = R + hash(R || m)⋅P''. This supports batch verification, as there are no elliptic curve operations inside the hashes. Batch verification enables significant speedups. [[File:bip-schnorr/speedup-batch.png|center|frame|This graph shows the ratio between the time it takes to verify ''n'' signatures individually and to verify a batch of ''n'' signatures. This ratio goes up logarithmically with the number of signatures, or in other words: the total time to verify ''n'' signatures grows with ''O(n / log n)''.]] We choose the ''R''-option to support batch verification. -'''Key prefixing''' When using the verification rule above directly, it is possible for a third party to convert a signature ''(R, s)'' for key ''P'' into a signature ''(R, s + a⋅hash(R || m))'' for key ''P + a⋅G'' and the same message, for any integer ''a''. To combat this, we choose ''key prefixed''A limitation of committing to the public key (rather than to a short hash of it, or not at all) is that it removes the ability for public key recovery or verifying signatures against a short public key hash. These constructions are generally incompatible with batch verification. Schnorr signatures; changing the equation to ''s⋅G = R + hash(R || P || m)⋅P''. Key prefixing also seems to be a requirement for the security proof of the MuSig multisignature scheme (see below, under applications). It is not strictly necessary to do this explicitly for Bitcoin currently, as all signature hashes indirectly commit to the public keys already. However, this may change with proposals such as SIGHASH_NOINPUT ([https://github.com/bitcoin/bips/blob/master/bip-0118.mediawiki BIP 118]), or when the signature scheme is used for other purposes—especially in combination with schemes like [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki BIP32]'s unhardened derivation. +'''Key prefixing''' When using the verification rule above directly, it is possible for a third party to convert a signature ''(R, s)'' for key ''P'' into a signature ''(R, s + a⋅hash(R || m))'' for key ''P + a⋅G'' and the same message, for any integer ''a''. To combat this, we choose ''key prefixed''A limitation of committing to the public key (rather than to a short hash of it, or not at all) is that it removes the ability for public key recovery or verifying signatures against a short public key hash. These constructions are generally incompatible with batch verification. Schnorr signatures; changing the equation to ''s⋅G = R + hash(R || P || m)⋅P''. Key prefixing also seems to be a requirement for the security proof of the MuSig multisignature scheme (see Applications below). It is not strictly necessary to do this explicitly for Bitcoin currently, as all signature hashes indirectly commit to the public keys already. However, this may change with proposals such as SIGHASH_NOINPUT ([https://github.com/bitcoin/bips/blob/master/bip-0118.mediawiki BIP 118]), or when the signature scheme is used for other purposes—especially in combination with schemes like [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki BIP32]'s unhardened derivation. '''Encoding R and public key point P''' There exist several possibilities for encoding elliptic curve points: # Encoding the full X and Y coordinates of ''P'' and ''R'', resulting in a 64-byte public key and a 96-byte signature. -- cgit v1.2.3 From 7a7ab111c9b171d7627a879682efcd4351de7f37 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 15 Oct 2019 16:03:19 -0700 Subject: Clarify interaction x-only keys with verification --- bip-schnorr.mediawiki | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 12a7379..4ee167d 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -77,8 +77,6 @@ expensive conversion to affine coordinates first. This would even be the case if For ''P'' the speed of signing and verification does not significantly differ between any of the three options because affine coordinates of the point have to be computed anyway. For consistency reasons we choose the same option as for ''R''. The signing algorithm ensures that the signature is valid under the correct public key by negating the secret key if necessary. -It is important not to mix up the 32-byte bip-schnorr public key format and other existing public key formats (e.g. encodings used in Bitcoin's ECDSA). Concretely, a verifier should only accept 32-byte public keys and not, for example, convert a 33-byte public key by throwing away the first byte. Otherwise, two public keys would be valid for a single signature which can result in subtle malleability issues (although this type of malleability already exists in the case of ECDSA signatures). - Implicit Y coordinates are not a reduction in security when expressed as the number of elliptic curve operations an attacker is expected to perform to compute the secret key. An attacker can normalize any given public key to a point whose Y coordinate is a square by negating the point if necessary. This is just a subtraction of field elements and not an elliptic curve operationThis can be formalized by a simple reduction that reduces an attack on Schnorr signatures with implicit Y coordinates to an attack to Schnorr signatures with explicit Y coordinates. The reduction works by reencoding public keys and negating the result of the hash function, which is modeled as random oracle, whenever the challenge public key has an explicit Y coordinate that is not a square.. '''Tagged Hashes''' Cryptographic hash functions are used for multiple purposes in the specification below and in Bitcoin in general. To make sure hashes used in one context can't be reinterpreted in another one, hash functions can be tweaked with a context-dependent tag name, in such a way that collisions across contexts can be assumed to be infeasible. Such collisions obviously can not be ruled out completely, but only for schemes using tagging with a unique name. As for other schemes collisions are at least less likely with tagging than without. @@ -173,6 +171,8 @@ The algorithm ''Verify(pk, m, sig)'' is defined as: For every valid secret key ''sk'' and message ''m'', ''Verify(PubKey(sk),m,Sign(sk,m))'' will succeed. +Note that the correctness of verification relies on the fact that ''point(pk)'' always returns a positive point (i.e., with a square Y coordinate). A hypothetical verification algorithm that treats points as public keys, and takes the point ''P'' directly as input would fail any time a negative point is used. While it is possible to correct for this by negating negative points before further processing, this would result in a scheme where every (message, signature) pair is valid for two public keys (a type of malleability that exists for ECDSA as well, but we don't wish to retain). We avoid these problems by treating just the X coordinate as public key. + ==== Batch Verification ==== Input: -- cgit v1.2.3 From 23c1c3ed8b954497c0ec6ec1f69ed14b5abcf092 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 15 Oct 2019 17:54:04 -0700 Subject: More on key generation --- bip-schnorr.mediawiki | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 4ee167d..fd77d22 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -125,10 +125,9 @@ The algorithm ''PubKey(sk)'' is defined as: * Fail if ''d = 0'' or ''d ≥ n''. * Return ''bytes(d⋅G)''. -Note that ''PubKey(sk) = PubKey(bytes(n - int(sk))'', so every public key has two corresponding private keys. +Note that we use a very different public key format (32 bytes) than the ones used by existing systems (which typically use elliptic curve points as public keys, or 33-byte or 65-byte encodings of them). A side effect is that ''PubKey(sk) = PubKey(bytes(n - int(sk))'', so every public key has two corresponding private keys. -Alternatively, the public key can be created according to [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki BIP32] which describes the derivation of 33-byte compressed public keys. -In order to translate such public keys into bip-schnorr compatible keys, the first byte must be dropped. +As an alternative to generating keys randomly, it is also possible and safe to repurpose existing key generation algorithms for ECDSA in a compatible way. The private keys constructed by such an algorithm can be used as ''sk'' directly. The public keys constructed by such an algorithm (assuming they use the 33-byte compressed encoding) need to be converted by dropping the first byte. Specifically, [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki BIP32] and schemes built on top of it remain usable. ==== Signing ==== -- cgit v1.2.3 From feffc4e34d89d03433dad60348c6acbc73392063 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Fri, 18 Oct 2019 13:41:00 +1000 Subject: annex is bit 0 of spend_type --- bip-taproot.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 4f84c28..1b8ed0c 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -135,7 +135,7 @@ As the message for signature verification, transaction digest is ''hashTapS *** nSequence (4): nSequence of this input. ** If the SIGHASH_ANYONECANPAY flag is not set: *** input_index (4): index of this input in the transaction input vector. Index of the first input is 0. -** If the bit-1 of spend_type is set: +** If bit 0 of spend_type is set: *** sha_annex (32): the SHA256 of (compact_size(size of annex) || annex). * Data about this output: ** If the SIGHASH_SINGLE flag is set: -- cgit v1.2.3 From 09e3f637b52eb2e14c58a8c2ca0618a8f4162d0f Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Mon, 21 Oct 2019 13:27:01 +0200 Subject: Change reference for ECDSA proofs Refer to Manuel Fersch's dissertation for provable security of ECDSA. It's freely accessible and multiple results put well in context. --- bip-schnorr.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index fd77d22..14f8610 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -25,7 +25,7 @@ Bitcoin has traditionally used transactions. These are [https://www.secg.org/sec1-v2.pdf standardized], but have a number of downsides compared to [http://publikationen.ub.uni-frankfurt.de/opus4/files/4280/schnorr.pdf Schnorr signatures] over the same curve: -* '''Provable security''': Schnorr signatures are provably secure. In more detail, they are ''strongly unforgeable under chosen message attack (SUF-CMA)''Informally, this means that without knowledge of the secret key but given valid signatures of arbitrary messages, it is not possible to come up with further valid signatures. [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf in the random oracle model assuming the hardness of the elliptic curve discrete logarithm problem (ECDLP)] and [http://www.neven.org/papers/schnorr.pdf in the generic group model assuming variants of preimage and second preimage resistance of the used hash function]A detailed security proof in the random oracle model, which essentially restates [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf the original security proof by Pointcheval and Stern] more explicitly, can be found in [https://eprint.iacr.org/2016/191 a paper by Kiltz, Masny and Pan]. All these security proofs assume a variant of Schnorr signatures that use ''(e,s)'' instead of ''(R,s)'' (see Design above). Since we use a unique encoding of ''R'', there is an efficiently computable bijection that maps ''(R,s)'' to ''(e,s)'', which allows to convert a successful SUF-CMA attacker for the ''(e,s)'' variant to a successful SUF-CMA attacker for the ''(r,s)'' variant (and vice-versa). Furthermore, the proofs consider a variant of Schnorr signatures without key prefixing (see Design above), but it can be verified that the proofs are also correct for the variant with key prefixing. As a result, all the aforementioned security proofs apply to the variant of Schnorr signatures proposed in this document.. The [https://dl.acm.org/citation.cfm?id=2978413 best known security proof for ECDSA] relies on stronger assumptions. +* '''Provable security''': Schnorr signatures are provably secure. In more detail, they are ''strongly unforgeable under chosen message attack (SUF-CMA)''Informally, this means that without knowledge of the secret key but given valid signatures of arbitrary messages, it is not possible to come up with further valid signatures. [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf in the random oracle model assuming the hardness of the elliptic curve discrete logarithm problem (ECDLP)] and [http://www.neven.org/papers/schnorr.pdf in the generic group model assuming variants of preimage and second preimage resistance of the used hash function]A detailed security proof in the random oracle model, which essentially restates [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf the original security proof by Pointcheval and Stern] more explicitly, can be found in [https://eprint.iacr.org/2016/191 a paper by Kiltz, Masny and Pan]. All these security proofs assume a variant of Schnorr signatures that use ''(e,s)'' instead of ''(R,s)'' (see Design above). Since we use a unique encoding of ''R'', there is an efficiently computable bijection that maps ''(R,s)'' to ''(e,s)'', which allows to convert a successful SUF-CMA attacker for the ''(e,s)'' variant to a successful SUF-CMA attacker for the ''(r,s)'' variant (and vice-versa). Furthermore, the proofs consider a variant of Schnorr signatures without key prefixing (see Design above), but it can be verified that the proofs are also correct for the variant with key prefixing. As a result, all the aforementioned security proofs apply to the variant of Schnorr signatures proposed in this document.. In contrast, the [https://nbn-resolving.de/urn:nbn:de:hbz:294-60803 best known results for the provable security of ECDSA] rely on stronger assumptions. * '''Non-malleability''': The SUF-CMA security of Schnorr signatures implies that they are non-malleable. On the other hand, ECDSA signatures are inherently malleable; a third party without access to the secret key can alter an existing valid signature for a given public key and message into another signature that is valid for the same key and message. This issue is discussed in [https://github.com/bitcoin/bips/blob/master/bip-0062.mediawiki BIP62] and [https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki BIP66]. * '''Linearity''': Schnorr signatures have the remarkable property that multiple parties can collaborate to produce a signature that is valid for the sum of their public keys. This is the building block for various higher-level constructions that improve efficiency and privacy, such as multisignatures and others (see Applications below). -- cgit v1.2.3 From 3595c30acd59068b8a3d5150bc74157950c59b19 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 21 Oct 2019 16:16:47 -0700 Subject: Improve section on alternatives to OP_CHECKMULTISIG --- bip-tapscript.mediawiki | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index a325573..91ed97c 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -71,7 +71,11 @@ The execution rules for tapscript are based on those for P2WSH according to BIP1 * '''Consensus-enforced MINIMALIF''' The MINIMALIF rules, which are only a standardness rule in P2WSH, are consensus enforced in tapscript. This means that the input argument to the OP_IF and OP_NOTIF opcodes must be either exactly 0 (the empty vector) or exactly 1 (the one-byte vector with value 1)'''Why make MINIMALIF consensus?''' This makes it considerably easier to write non-malleable scripts that take branch information from the stack.. * '''OP_SUCCESSx opcodes''' As listed above, some opcodes are renamed to OP_SUCCESSx, and make the script unconditionally valid. * '''Signature opcodes'''. The OP_CHECKSIG and OP_CHECKSIGVERIFY are modified to operate on Schnorr public keys and signatures (see bip-schnorr) instead of ECDSA, and a new opcode OP_CHECKSIGADD is added. -** The opcode 186 (0xba) is named as OP_CHECKSIGADD. '''OP_CHECKSIGADD''' This opcode is added to compensate for the loss of OP_CHECKMULTISIG-like opcodes, which are incompatible with batch verification. OP_CHECKSIGADD is functionally equivalent to OP_ROT OP_SWAP OP_CHECKSIG OP_ADD, but only takes 1 byte. All CScriptNum-related behaviours of OP_ADD are also applicable to OP_CHECKSIGADD.'''Comparison of CHECKMULTISIG and CHECKSIG''' A CHECKMULTISIG script m ... n CHECKMULTISIG with witness 0 ... can be rewritten as script CHECKSIG ... CHECKSIGADD m NUMEQUAL with witness ... . Every witness element w_i is either a signature corresponding to the public key with the same index or an empty vector. A similar CHECKMULTISIGVERIFY script can be translated to bip-tapscript by replacing NUMEQUAL with NUMEQUALVERIFY. Alternatively, an m-of-n multisig policy can be implemented by splitting the script into several leaves of the Merkle tree, each implementing an m-of-m policy using CHECKSIGVERIFY ... CHECKSIGVERIFY CHECKSIG. If the setting allows the participants to interactively collaborate while signing, multisig policies can be realized with [https://eprint.iacr.org/2018/068 MuSig] for m-of-m and with [http://cacr.uwaterloo.ca/techreports/2001/corr2001-13.ps threshold signatures] using verifiable secret sharing for m-of-n. +** The opcode 186 (0xba) is named as OP_CHECKSIGADD. '''OP_CHECKSIGADD''' This opcode is added to compensate for the loss of OP_CHECKMULTISIG-like opcodes, which are incompatible with batch verification. OP_CHECKSIGADD is functionally equivalent to OP_ROT OP_SWAP OP_CHECKSIG OP_ADD, but only takes 1 byte. All CScriptNum-related behaviours of OP_ADD are also applicable to OP_CHECKSIGADD.'''Alternatives to CHECKMULTISIG''' There are multiple ways of implementing a threshold ''k''-of-''n'' policy using Taproot and Tapscript: +* '''Using a single OP_CHECKSIGADD-based script''' A CHECKMULTISIG script m ... n CHECKMULTISIG with witness 0 ... can be rewritten as script CHECKSIG ... CHECKSIGADD m NUMEQUAL with witness ... . Every witness element w_i is either a signature corresponding to the public key with the same index or an empty vector. A similar CHECKMULTISIGVERIFY script can be translated to bip-tapscript by replacing NUMEQUAL with NUMEQUALVERIFY. This approach has very similar characteristics to the existing OP_CHECKMULTISIG-based scripts. +* '''Using a ''k''-of-''k'' script for every combination''' A ''k''-of-''n'' policy can be implemented by splitting the script into several leaves of the Merkle tree, each implementing a ''k''-of-''k'' policy using CHECKSIGVERIFY ... CHECKSIGVERIFY CHECKSIG. This may be preferable for privacy reasons over the previous approach, as it only exposes the participating public keys, but it is only more cost effective for small values of ''k'' (1-of-''n'' for any ''n'', 2-of-''n'' for ''n ≥ 6'', 3-of-''n'' for ''n ≥ 9'', ...). Furthermore, the signatures here depend on the branch used, which means signers need to be aware of which other signers will be participating, or produce signatures for each of the tree leaves. +* '''Using an aggregated public key for every combination''' Instead of building a tree where every leaf consists of ''k'' public keys, it is possible instead build a tree where every leaf contains a single ''aggregate'' of those ''k'' keys using [https://eprint.iacr.org/2018/068 MuSig]. This approach is far more efficient, but does require a 3-round interactive signing protocol to jointly produce the (single) signature. +* '''Native Schnorr threshold signatures''' Multisig policies can also be realized with [http://cacr.uwaterloo.ca/techreports/2001/corr2001-13.ps threshold signatures] using verifiable secret sharing. This results in outputs and inputs that are indistinguishable from single-key payments, but at the cost of needing an interactive protocol (and associated backup procedures) before determining the address to send to. ===Rules for signature opcodes=== -- cgit v1.2.3 From 2059b9e35a39cf34655e8b6f2c3e550004b5a997 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 22 Oct 2019 11:15:36 -0700 Subject: Address aj comments --- bip-tapscript.mediawiki | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index 91ed97c..34d7e48 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -72,8 +72,8 @@ The execution rules for tapscript are based on those for P2WSH according to BIP1 * '''OP_SUCCESSx opcodes''' As listed above, some opcodes are renamed to OP_SUCCESSx, and make the script unconditionally valid. * '''Signature opcodes'''. The OP_CHECKSIG and OP_CHECKSIGVERIFY are modified to operate on Schnorr public keys and signatures (see bip-schnorr) instead of ECDSA, and a new opcode OP_CHECKSIGADD is added. ** The opcode 186 (0xba) is named as OP_CHECKSIGADD. '''OP_CHECKSIGADD''' This opcode is added to compensate for the loss of OP_CHECKMULTISIG-like opcodes, which are incompatible with batch verification. OP_CHECKSIGADD is functionally equivalent to OP_ROT OP_SWAP OP_CHECKSIG OP_ADD, but only takes 1 byte. All CScriptNum-related behaviours of OP_ADD are also applicable to OP_CHECKSIGADD.'''Alternatives to CHECKMULTISIG''' There are multiple ways of implementing a threshold ''k''-of-''n'' policy using Taproot and Tapscript: -* '''Using a single OP_CHECKSIGADD-based script''' A CHECKMULTISIG script m ... n CHECKMULTISIG with witness 0 ... can be rewritten as script CHECKSIG ... CHECKSIGADD m NUMEQUAL with witness ... . Every witness element w_i is either a signature corresponding to the public key with the same index or an empty vector. A similar CHECKMULTISIGVERIFY script can be translated to bip-tapscript by replacing NUMEQUAL with NUMEQUALVERIFY. This approach has very similar characteristics to the existing OP_CHECKMULTISIG-based scripts. -* '''Using a ''k''-of-''k'' script for every combination''' A ''k''-of-''n'' policy can be implemented by splitting the script into several leaves of the Merkle tree, each implementing a ''k''-of-''k'' policy using CHECKSIGVERIFY ... CHECKSIGVERIFY CHECKSIG. This may be preferable for privacy reasons over the previous approach, as it only exposes the participating public keys, but it is only more cost effective for small values of ''k'' (1-of-''n'' for any ''n'', 2-of-''n'' for ''n ≥ 6'', 3-of-''n'' for ''n ≥ 9'', ...). Furthermore, the signatures here depend on the branch used, which means signers need to be aware of which other signers will be participating, or produce signatures for each of the tree leaves. +* '''Using a single OP_CHECKSIGADD-based script''' A CHECKMULTISIG script m ... n CHECKMULTISIG with witness 0 ... can be rewritten as script CHECKSIG ... CHECKSIGADD m NUMEQUAL with witness ... . Every witness element w_i is either a signature corresponding to pubkey_i or an empty vector. A similar CHECKMULTISIGVERIFY script can be translated to bip-tapscript by replacing NUMEQUAL with NUMEQUALVERIFY. This approach has very similar characteristics to the existing OP_CHECKMULTISIG-based scripts. +* '''Using a ''k''-of-''k'' script for every combination''' A ''k''-of-''n'' policy can be implemented by splitting the script into several leaves of the Merkle tree, each implementing a ''k''-of-''k'' policy using CHECKSIGVERIFY ... CHECKSIGVERIFY CHECKSIG. This may be preferable for privacy reasons over the previous approach, as it only exposes the participating public keys, but it is only more cost effective for small values of ''k'' (1-of-''n'' for any ''n'', 2-of-''n'' for ''n ≥ 6'', 3-of-''n'' for ''n ≥ 9'', ...). Furthermore, the signatures here commit to the branch used, which means signers need to be aware of which other signers will be participating, or produce signatures for each of the tree leaves. * '''Using an aggregated public key for every combination''' Instead of building a tree where every leaf consists of ''k'' public keys, it is possible instead build a tree where every leaf contains a single ''aggregate'' of those ''k'' keys using [https://eprint.iacr.org/2018/068 MuSig]. This approach is far more efficient, but does require a 3-round interactive signing protocol to jointly produce the (single) signature. * '''Native Schnorr threshold signatures''' Multisig policies can also be realized with [http://cacr.uwaterloo.ca/techreports/2001/corr2001-13.ps threshold signatures] using verifiable secret sharing. This results in outputs and inputs that are indistinguishable from single-key payments, but at the cost of needing an interactive protocol (and associated backup procedures) before determining the address to send to. -- cgit v1.2.3 From fc0a4ef542715c9e5841636fd0d9645df9534f5c Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 22 Oct 2019 11:46:31 -0700 Subject: Explain why CMS is not turned into SUCCESSx --- bip-tapscript.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index 34d7e48..f0f0ebf 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -67,7 +67,7 @@ Validation of such inputs must be equivalent to performing the following steps i ===Script execution=== The execution rules for tapscript are based on those for P2WSH according to BIP141, including the OP_CHECKLOCKTIMEVERIFY and OP_CHECKSEQUENCEVERIFY opcodes defined in BIP65 and BIP112, but with the following modifications: -* '''Disabled script opcodes''' The following script opcodes are disabled in tapscript: OP_CHECKMULTISIG and OP_CHECKMULTISIGVERIFY. The disabled opcodes behave in the same way as OP_RETURN, by failing and terminating the script immediately when executed, and being ignored when found in unexecuted branch. +* '''Disabled script opcodes''' The following script opcodes are disabled in tapscript: OP_CHECKMULTISIG and OP_CHECKMULTISIGVERIFY'''Why are OP_CHECKMULTISIG and OP_CHECKMULTISIGVERIFY disabled, and not turned into OP_SUCCESSx?''' This is a precaution to make sure people who accidentally keep using OP_CHECKMULTISIG in Tapscript notice a problem immediately. It also avoids the complication of script disassemblers needing to become context-dependent.. The disabled opcodes behave in the same way as OP_RETURN, by failing and terminating the script immediately when executed, and being ignored when found in unexecuted branch. * '''Consensus-enforced MINIMALIF''' The MINIMALIF rules, which are only a standardness rule in P2WSH, are consensus enforced in tapscript. This means that the input argument to the OP_IF and OP_NOTIF opcodes must be either exactly 0 (the empty vector) or exactly 1 (the one-byte vector with value 1)'''Why make MINIMALIF consensus?''' This makes it considerably easier to write non-malleable scripts that take branch information from the stack.. * '''OP_SUCCESSx opcodes''' As listed above, some opcodes are renamed to OP_SUCCESSx, and make the script unconditionally valid. * '''Signature opcodes'''. The OP_CHECKSIG and OP_CHECKSIGVERIFY are modified to operate on Schnorr public keys and signatures (see bip-schnorr) instead of ECDSA, and a new opcode OP_CHECKSIGADD is added. -- cgit v1.2.3 From 1695f073d3c9f6f3ea838fd1356adbd036d30bdd Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Thu, 24 Oct 2019 14:48:24 -0700 Subject: Elaborate on default and alternative signing --- bip-schnorr.mediawiki | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 14f8610..44b2c84 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -129,7 +129,7 @@ Note that we use a very different public key format (32 bytes) than the ones use As an alternative to generating keys randomly, it is also possible and safe to repurpose existing key generation algorithms for ECDSA in a compatible way. The private keys constructed by such an algorithm can be used as ''sk'' directly. The public keys constructed by such an algorithm (assuming they use the 33-byte compressed encoding) need to be converted by dropping the first byte. Specifically, [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki BIP32] and schemes built on top of it remain usable. -==== Signing ==== +==== Default Signing ==== Input: * The secret key ''sk'': a 32-byte array @@ -147,10 +147,15 @@ The algorithm ''Sign(sk, m)'' is defined as: * Let ''e = int(hashBIPSchnorr(bytes(R) || bytes(P) || m)) mod n''. * Return the signature ''bytes(R) || bytes((k + ed) mod n)''. -'''Above deterministic derivation of ''R'' is designed specifically for this signing algorithm and may not be secure when used in other signature schemes.''' -For example, using the same derivation in the MuSig multi-signature scheme leaks the secret key (see the [https://eprint.iacr.org/2018/068 MuSig paper] for details). +==== Alternative Signing ==== -Note that this is not a ''unique signature'' scheme: while this algorithm will always produce the same signature for a given message and public key, ''k'' (and hence ''R'') may be generated in other ways (such as by a CSPRNG) producing a different, but still valid, signature. +It should be noted that various alternative signing algorithms can be used to produce equally valid signatures. The algorithm in the previous section will always produce the same signature for a given message and public key, but the ''k'' value (and hence ''R'') may be generated in other ways, producing a different, but still valid, signature (in other words, it is not a ''unique'' signature scheme). + +'''Synthetic nonces''' When actual randomness is available, it can be appended to the input to ''hashBIPSchnorrDerive''s, after ''d'' and ''m''. This may improve protection against [https://moderncrypto.org/mail-archive/curves/2017/000925.html fault injection attacks]. + +'''Nonce exfiltration protection''' It is possible to strengthen the nonce generation algorithm using a second device. In this case, the second device contributes randomness which the actual signer provably incorporates into its nonce. This prevents certain attacks where the signer device is compromised and intentionally tries to leak the private key through its nonce selection. + +'''Multisignatures''' This signature scheme is compatible with various types of multisignature and threshold schemes, where a single public key requires holders of multiple private keys to participate in signing. One example is [https://eprint.iacr.org/2018/068 MuSig], which provides a way to aggregate multiple public keys into a single one, which all of the corresponding private keys need to sign for. It is important to note that multisignature signing schemes in general ''cannot'' be used with the nonce generation from the default signing algorithm above (or any deterministic nonce algorithm). ==== Verification ==== -- cgit v1.2.3 From 83cebb5326b8fbebb39fb34f77a755b3a9dfe942 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 25 Oct 2019 10:18:17 -0700 Subject: Update bip-schnorr.mediawiki Co-Authored-By: Tim Ruffing --- bip-schnorr.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 44b2c84..f8d0f47 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -151,7 +151,7 @@ The algorithm ''Sign(sk, m)'' is defined as: It should be noted that various alternative signing algorithms can be used to produce equally valid signatures. The algorithm in the previous section will always produce the same signature for a given message and public key, but the ''k'' value (and hence ''R'') may be generated in other ways, producing a different, but still valid, signature (in other words, it is not a ''unique'' signature scheme). -'''Synthetic nonces''' When actual randomness is available, it can be appended to the input to ''hashBIPSchnorrDerive''s, after ''d'' and ''m''. This may improve protection against [https://moderncrypto.org/mail-archive/curves/2017/000925.html fault injection attacks]. +'''Synthetic nonces''' When a random number generator (RNG) is available, 32 bytes of RNG output can be appended to the input to ''hashBIPSchnorrDerive''. This will changes the corresponding line in the signing algorithm to ''k' = int(hashBIPSchnorrDerive(bytes(d) || m || get_32_bytes_from_rng())) mod n'', where ''get_32_bytes_from_rng()'' is the call the RNG. Adding RNG output may improve protection against [https://moderncrypto.org/mail-archive/curves/2017/000925.html fault injection attacks and side-channel attacks]. It is safe to add randomness from a low-quality randomness source, i.e., an RNG with low entropy. '''Nonce exfiltration protection''' It is possible to strengthen the nonce generation algorithm using a second device. In this case, the second device contributes randomness which the actual signer provably incorporates into its nonce. This prevents certain attacks where the signer device is compromised and intentionally tries to leak the private key through its nonce selection. -- cgit v1.2.3 From 9c1670f3456ef7b6fee20eca19ba922d9a1967fa Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 25 Oct 2019 10:18:29 -0700 Subject: Update bip-schnorr.mediawiki Co-Authored-By: Tim Ruffing --- bip-schnorr.mediawiki | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index f8d0f47..6830ec7 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -155,7 +155,8 @@ It should be noted that various alternative signing algorithms can be used to pr '''Nonce exfiltration protection''' It is possible to strengthen the nonce generation algorithm using a second device. In this case, the second device contributes randomness which the actual signer provably incorporates into its nonce. This prevents certain attacks where the signer device is compromised and intentionally tries to leak the private key through its nonce selection. -'''Multisignatures''' This signature scheme is compatible with various types of multisignature and threshold schemes, where a single public key requires holders of multiple private keys to participate in signing. One example is [https://eprint.iacr.org/2018/068 MuSig], which provides a way to aggregate multiple public keys into a single one, which all of the corresponding private keys need to sign for. It is important to note that multisignature signing schemes in general ''cannot'' be used with the nonce generation from the default signing algorithm above (or any deterministic nonce algorithm). +'''Multisignatures''' This signature scheme is compatible with various types of multisignature and threshold schemes such as [https://eprint.iacr.org/2018/068 MuSig], where a single public key requires holders of multiple private keys to participate in signing (see Applications below). +'''It is important to note that multisignature signing schemes in general are insecure with the nonce generation from the default signing algorithm above (or any deterministic nonce algorithm).''' ==== Verification ==== -- cgit v1.2.3 From dbbe690c8ad0aa02ca87b1942b322c08fbe3cdd4 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Thu, 24 Oct 2019 11:12:59 -0700 Subject: Consistently mention resource limits in bip-tapscript --- bip-tapscript.mediawiki | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index f0f0ebf..9044c71 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -52,13 +52,13 @@ The rules below only apply when validating a transaction input for which all of Validation of such inputs must be equivalent to performing the following steps in the specified order. # If the input is invalid due to BIP16, BIP141, or bip-taproot, fail. # The script as defined in bip-taproot (i.e., the penultimate witness stack element after removing the optional annex) is called the '''tapscript''' and is decoded into opcodes, one by one: -## If any opcode numbered ''80, 98, 126-129, 131-134, 137-138, 141-142, 149-153, 187-254'' is encountered, validation succeeds (none of the rules below apply). This is true even if later bytes in the tapscript would fail to decode otherwise. These opcodes are renamed to OP_SUCCESS80, ..., OP_SUCCESS254, and collectively known as OP_SUCCESSx'''OP_SUCCESSx''' OP_SUCCESSx is a mechanism to upgrade the Script system. Using an OP_SUCCESSx before its meaning is defined by a softfork is insecure and leads to fund loss. The inclusion of OP_SUCCESSx in a script will pass it unconditionally. It precedes any script execution rules to avoid the difficulties in specifying various edge cases, for example: OP_SUCCESSx being the 202nd opcode, OP_SUCCESSx after too many signature opcodes, or even scripts with conditionals lacking OP_ENDIF. The mere existence of an OP_SUCCESSx anywhere in the script will guarantee a pass for all such cases. OP_SUCCESSx are similar to the OP_RETURN in very early bitcoin versions (v0.1 up to and including v0.3.5). The original OP_RETURN terminates script execution immediately, and return pass or fail based on the top stack element at the moment of termination. This was one of a major design flaws in the original bitcoin protocol as it permitted unconditional third party theft by placing an OP_RETURN in scriptSig. This is not a concern in the present proposal since it is not possible for a third party to inject an OP_SUCCESSx to the validation process, as the OP_SUCCESSx is part of the script (and thus committed to be the taproot output), implying the consent of the coin owner. OP_SUCCESSx can be used for a variety of upgrade possibilities: +## If any opcode numbered ''80, 98, 126-129, 131-134, 137-138, 141-142, 149-153, 187-254'' is encountered, validation succeeds (none of the rules below apply). This is true even if later bytes in the tapscript would fail to decode otherwise. These opcodes are renamed to OP_SUCCESS80, ..., OP_SUCCESS254, and collectively known as OP_SUCCESSx'''OP_SUCCESSx''' OP_SUCCESSx is a mechanism to upgrade the Script system. Using an OP_SUCCESSx before its meaning is defined by a softfork is insecure and leads to fund loss. The inclusion of OP_SUCCESSx in a script will pass it unconditionally. It precedes any script execution rules to avoid the difficulties in specifying various edge cases, for example: OP_SUCCESSx in a script with an input stack larger than 1000 elements, OP_SUCCESSx after too many signature opcodes, or even scripts with conditionals lacking OP_ENDIF. The mere existence of an OP_SUCCESSx anywhere in the script will guarantee a pass for all such cases. OP_SUCCESSx are similar to the OP_RETURN in very early bitcoin versions (v0.1 up to and including v0.3.5). The original OP_RETURN terminates script execution immediately, and return pass or fail based on the top stack element at the moment of termination. This was one of a major design flaws in the original bitcoin protocol as it permitted unconditional third party theft by placing an OP_RETURN in scriptSig. This is not a concern in the present proposal since it is not possible for a third party to inject an OP_SUCCESSx to the validation process, as the OP_SUCCESSx is part of the script (and thus committed to be the taproot output), implying the consent of the coin owner. OP_SUCCESSx can be used for a variety of upgrade possibilities: * An OP_SUCCESSx could be turned into a functional opcode through a softfork. Unlike OP_NOPx-derived opcodes which only have read-only access to the stack, OP_SUCCESSx may also write to the stack. Any rule changes to an OP_SUCCESSx-containing script may only turn a valid script into an invalid one, and this is always achievable with softforks. * Since OP_SUCCESSx precedes size check of initial stack and push opcodes, an OP_SUCCESSx-derived opcode requiring stack elements bigger than 520 bytes may uplift the limit in a softfork. * OP_SUCCESSx may also redefine the behavior of existing opcodes so they could work together with the new opcode. For example, if an OP_SUCCESSx-derived opcode works with 64-bit integers, it may also allow the existing arithmetic opcodes in the ''same script'' to do the same. * Given that OP_SUCCESSx even causes potentially unparseable scripts to pass, it can be used to introduce multi-byte opcodes, or even a completely new scripting language when prefixed with a specific OP_SUCCESSx opcode.. ## If any push opcode fails to decode because it would extend past the end of the tapscript, fail. -# If the size of any element in the '''initial stack''' as defined in bip-taproot (i.e., the witness stack after removing both the optional annex and the two last stack elements after that) is bigger than 520 bytes, fail. +# If the '''initial stack''' as defined in bip-taproot (i.e., the witness stack after removing both the optional annex and the two last stack elements after that) violates any resource limits (stack size, and size of the elements in the stack; see "Resource Limits" below), fail. Note that this check can be bypassed using OP_SUCCESSx. # The tapscript is executed according to the rules in the following section, with the initial stack as input. ## If execution fails for any reason, fail. ## If the execution results in anything but exactly one element on the stack which evaluates to true with CastToBool(), fail. -- cgit v1.2.3 From 7c00346cf2bff0c203d82c739cca915c87ad22de Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Wed, 30 Oct 2019 01:27:26 +0100 Subject: typos --- bip-schnorr.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 6830ec7..3d85754 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -151,7 +151,7 @@ The algorithm ''Sign(sk, m)'' is defined as: It should be noted that various alternative signing algorithms can be used to produce equally valid signatures. The algorithm in the previous section will always produce the same signature for a given message and public key, but the ''k'' value (and hence ''R'') may be generated in other ways, producing a different, but still valid, signature (in other words, it is not a ''unique'' signature scheme). -'''Synthetic nonces''' When a random number generator (RNG) is available, 32 bytes of RNG output can be appended to the input to ''hashBIPSchnorrDerive''. This will changes the corresponding line in the signing algorithm to ''k' = int(hashBIPSchnorrDerive(bytes(d) || m || get_32_bytes_from_rng())) mod n'', where ''get_32_bytes_from_rng()'' is the call the RNG. Adding RNG output may improve protection against [https://moderncrypto.org/mail-archive/curves/2017/000925.html fault injection attacks and side-channel attacks]. It is safe to add randomness from a low-quality randomness source, i.e., an RNG with low entropy. +'''Synthetic nonces''' When a random number generator (RNG) is available, 32 bytes of RNG output can be appended to the input to ''hashBIPSchnorrDerive''. This will change the corresponding line in the signing algorithm to ''k' = int(hashBIPSchnorrDerive(bytes(d) || m || get_32_bytes_from_rng())) mod n'', where ''get_32_bytes_from_rng()'' is the call to the RNG. Adding RNG output may improve protection against [https://moderncrypto.org/mail-archive/curves/2017/000925.html fault injection attacks and side-channel attacks]. It is safe to add randomness from a low-quality randomness source, i.e., an RNG with low entropy. '''Nonce exfiltration protection''' It is possible to strengthen the nonce generation algorithm using a second device. In this case, the second device contributes randomness which the actual signer provably incorporates into its nonce. This prevents certain attacks where the signer device is compromised and intentionally tries to leak the private key through its nonce selection. -- cgit v1.2.3 From d87c5c8801932d5363d5cfc02d7f9f65c5e48f1a Mon Sep 17 00:00:00 2001 From: Dmitry Petukhov Date: Mon, 4 Nov 2019 19:15:12 +0500 Subject: use bytes() instead of b'' - avoid markdown issue Currently github markdown renders `b''` inside `` tags incorrectly. This makes `h = b''` show as `h = b` and creates some confusion. The issue can be avoided by using bytes() to create empty byte array --- bip-taproot.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 1b8ed0c..460ce12 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -224,7 +224,7 @@ def taproot_output_script(internal_pubkey, script_tree): - a list of two elements, each with the same structure as script_tree itself""" - None if script_tree is None: - h = b'' + h = bytes() else: _, h = taproot_tree_helper(script_tree) output_pubkey, _ = taproot_tweak_pubkey(internal_pubkey, h) -- cgit v1.2.3 From 0f9ab0cec993b3fde587c3eda20c7a18327ede92 Mon Sep 17 00:00:00 2001 From: Dmitry Petukhov Date: Mon, 4 Nov 2019 17:46:00 +0500 Subject: fix docstring in taproot_output_script the final "-None" line in the docstring of `taproot_output_script` example function was actually outside of the docstring --- bip-taproot.mediawiki | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 460ce12..fd25b77 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -221,8 +221,9 @@ def taproot_output_script(internal_pubkey, script_tree): """Given a internal public key and a tree of scripts, compute the output script. script_tree is either: - a (leaf_version, script) tuple (leaf_version is 0xc0 for bip-tapscript scripts) - - a list of two elements, each with the same structure as script_tree itself""" + - a list of two elements, each with the same structure as script_tree itself - None + """ if script_tree is None: h = bytes() else: -- cgit v1.2.3 From ae7122822ac3cd51415f35149ac60e611c3abc40 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 4 Nov 2019 11:56:48 -0800 Subject: Settle on notation: is_square(y), has_square_y(P) --- bip-schnorr.mediawiki | 14 +++++++------- bip-schnorr/reference.py | 17 ++++++++++------- bip-schnorr/test-vectors.py | 19 +++++++++---------- bip-taproot.mediawiki | 14 +++++++------- 4 files changed, 33 insertions(+), 31 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 3d85754..61414f5 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -106,8 +106,8 @@ The following conventions are used, with constants as defined for [https://www.s ** The function ''bytes(P)'', where ''P'' is a point, returns ''bytes(x(P))'. ** The function ''int(x)'', where ''x'' is a 32-byte array, returns the 256-bit unsigned integer whose most significant byte first encoding is ''x''. ** The function ''is_square(x)'', where ''x'' is an integer, returns whether or not ''x'' is a quadratic residue modulo ''p''. Since ''p'' is prime, it is equivalent to the Legendre symbol ''(x / p) = x(p-1)/2 mod p'' being equal to ''1'' (see [https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion])For points ''P'' on the secp256k1 curve it holds that ''x(p-1)/2 ≠ 0 mod p''.. -** The function ''is_positive(P)'', where ''P'' is a point, is defined as ''not is_infinite(P) and is_square(y(P))''For points ''P'' on the secp256k1 curve it holds that ''is_positive(P) = not is_positive(-P)''.. -** The function ''lift_x(x)'', where ''x'' is an integer in range ''0..p-1'', returns the point ''P'' for which ''x(P) = x'' and ''is_positive(P)'', or fails if no such point existsGiven an candidate X coordinate ''x'' in the range ''0..p-1'', there exist either exactly two or exactly zero valid Y coordinates. If no valid Y coordinate exists, then ''x'' is not a valid X coordinate either, i.e., no point ''P'' exists for which ''x(P) = x''. Given a candidate ''x'', the valid Y coordinates are the square roots of ''c = x3 + 7 mod p'' and they can be computed as ''y = ±c(p+1)/4 mod p'' (see [https://en.wikipedia.org/wiki/Quadratic_residue#Prime_or_prime_power_modulus Quadratic residue]) if they exist, which can be checked by squaring and comparing with ''c''. Due to [https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion] it then holds that ''c(p-1)/2 = 1 mod p''. The same criterion applied to ''y'' results in ''y(p-1)/2 mod p = ±c((p+1)/4)((p-1)/2) mod p = ±1 mod p''. Therefore ''y = +c(p+1)/4 mod p'' is a quadratic residue and ''-y mod p'' is not.. The function ''lift_x(x)'' is equivalent to the following pseudocode: +** The function ''has_square_y(P)'', where ''P'' is a point, is defined as ''not is_infinite(P) and is_square(y(P))''For points ''P'' on the secp256k1 curve it holds that ''has_square_y(P) = not has_square_y(-P)''.. +** The function ''lift_x(x)'', where ''x'' is an integer in range ''0..p-1'', returns the point ''P'' for which ''x(P) = x'' and ''has_square_y(P)'', or fails if no such point existsGiven an candidate X coordinate ''x'' in the range ''0..p-1'', there exist either exactly two or exactly zero valid Y coordinates. If no valid Y coordinate exists, then ''x'' is not a valid X coordinate either, i.e., no point ''P'' exists for which ''x(P) = x''. Given a candidate ''x'', the valid Y coordinates are the square roots of ''c = x3 + 7 mod p'' and they can be computed as ''y = ±c(p+1)/4 mod p'' (see [https://en.wikipedia.org/wiki/Quadratic_residue#Prime_or_prime_power_modulus Quadratic residue]) if they exist, which can be checked by squaring and comparing with ''c''. Due to [https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion] it then holds that ''c(p-1)/2 = 1 mod p''. The same criterion applied to ''y'' results in ''y(p-1)/2 mod p = ±c((p+1)/4)((p-1)/2) mod p = ±1 mod p''. Therefore ''y = +c(p+1)/4 mod p'' is a quadratic residue and ''-y mod p'' is not.. The function ''lift_x(x)'' is equivalent to the following pseudocode: *** Let ''c = x3 + 7 mod p''. *** Let ''y = c(p+1)/4 mod p''. *** Fail if ''c ≠ y2 mod p''. @@ -139,11 +139,11 @@ The algorithm ''Sign(sk, m)'' is defined as: * Let ''d' = int(sk)'' * Fail if ''d' = 0'' or ''d' ≥ n'' * Let ''P = d'⋅G'' -* Let ''d = d' '' if ''is_positive(P)'', otherwise let ''d = n - d' ''. +* Let ''d = d' '' if ''has_square_y(P)'', otherwise let ''d = n - d' ''. * Let ''k' = int(hashBIPSchnorrDerive(bytes(d) || m)) mod n''Note that in general, taking the output of a hash function modulo the curve order will produce an unacceptably biased result. However, for the secp256k1 curve, the order is sufficiently close to ''2256'' that this bias is not observable (''1 - n / 2256'' is around ''1.27 * 2-128'').. * Fail if ''k' = 0''. * Let ''R = k'G''. -* Let ''k = k' '' if ''is_positive(R)'', otherwise let ''k = n - k' ''. +* Let ''k = k' '' if ''has_square_y(R)'', otherwise let ''k = n - k' ''. * Let ''e = int(hashBIPSchnorr(bytes(R) || bytes(P) || m)) mod n''. * Return the signature ''bytes(R) || bytes((k + ed) mod n)''. @@ -171,12 +171,12 @@ The algorithm ''Verify(pk, m, sig)'' is defined as: * Let ''s = int(sig[32:64])''; fail if ''s ≥ n''. * Let ''e = int(hashBIPSchnorr(bytes(r) || bytes(P) || m)) mod n''. * Let ''R = s⋅G - e⋅P''. -* Fail if ''not is_positive(R)'' or ''x(R) ≠ r''. +* Fail if ''not has_square_y(R)'' or ''x(R) ≠ r''. * Return success iff no failure occurred before reaching this point. For every valid secret key ''sk'' and message ''m'', ''Verify(PubKey(sk),m,Sign(sk,m))'' will succeed. -Note that the correctness of verification relies on the fact that ''point(pk)'' always returns a positive point (i.e., with a square Y coordinate). A hypothetical verification algorithm that treats points as public keys, and takes the point ''P'' directly as input would fail any time a negative point is used. While it is possible to correct for this by negating negative points before further processing, this would result in a scheme where every (message, signature) pair is valid for two public keys (a type of malleability that exists for ECDSA as well, but we don't wish to retain). We avoid these problems by treating just the X coordinate as public key. +Note that the correctness of verification relies on the fact that ''point(pk)'' always returns a point with a square Y coordinate. A hypothetical verification algorithm that treats points as public keys, and takes the point ''P'' directly as input would fail any time a point with non-square Y is used. While it is possible to correct for this by negating points with non-square Y coordinate before further processing, this would result in a scheme where every (message, signature) pair is valid for two public keys (a type of malleability that exists for ECDSA as well, but we don't wish to retain). We avoid these problems by treating just the X coordinate as public key. ==== Batch Verification ==== @@ -206,7 +206,7 @@ Many techniques are known for optimizing elliptic curve implementations. Several '''Squareness testing''' The function ''is_square(x)'' is defined as above, but can be computed more efficiently using an [https://en.wikipedia.org/wiki/Jacobi_symbol#Calculating_the_Jacobi_symbol extended GCD algorithm]. '''Jacobian coordinates''' Elliptic Curve operations can be implemented more efficiently by using [https://en.wikibooks.org/wiki/Cryptography/Prime_Curve/Jacobian_Coordinates Jacobian coordinates]. Elliptic Curve operations implemented this way avoid many intermediate modular inverses (which are computationally expensive), and the scheme proposed in this document is in fact designed to not need any inversions at all for verification. When operating on a point ''P'' with Jacobian coordinates ''(x,y,z)'' which is not the point at infinity and for which ''x(P)'' is defined as ''x / z2'' and ''y(P)'' is defined as ''y / z3'': -* ''is_positive(P)'' can be implemented as ''is_square(yz mod p)''. +* ''has_square_y(P)'' can be implemented as ''is_square(yz mod p)''. * ''x(P) ≠ r'' can be implemented as ''(0 ≤ r < p) and (x ≠ z2r mod p)''. == Applications == diff --git a/bip-schnorr/reference.py b/bip-schnorr/reference.py index e5d9557..7de37c2 100644 --- a/bip-schnorr/reference.py +++ b/bip-schnorr/reference.py @@ -11,6 +11,9 @@ def tagged_hash(tag, msg): tag_hash = hashlib.sha256(tag.encode()).digest() return hashlib.sha256(tag_hash + tag_hash + msg).digest() +def is_infinity(P): + return P is None + def x(P): return P[0] @@ -59,11 +62,11 @@ def int_from_bytes(b): def hash_sha256(b): return hashlib.sha256(b).digest() -def jacobi(x): - return pow(x, (p - 1) // 2, p) +def is_square(x): + return pow(x, (p - 1) // 2, p) == 1 -def is_quad(x): - return jacobi(x) == 1 +def has_square_y(P): + return not is_infinity(P) and is_square(y(P)) def pubkey_gen(seckey): x = int_from_bytes(seckey) @@ -79,12 +82,12 @@ def schnorr_sign(msg, seckey0): if not (1 <= seckey0 <= n - 1): raise ValueError('The secret key must be an integer in the range 1..n-1.') P = point_mul(G, seckey0) - seckey = seckey0 if is_quad(y(P)) else n - seckey0 + seckey = seckey0 if has_square_y(P) else n - seckey0 k0 = int_from_bytes(tagged_hash("BIPSchnorrDerive", bytes_from_int(seckey) + msg)) % n if k0 == 0: raise RuntimeError('Failure. This happens only with negligible probability.') R = point_mul(G, k0) - k = n - k0 if not is_quad(y(R)) else k0 + k = n - k0 if not has_square_y(R) else k0 e = int_from_bytes(tagged_hash("BIPSchnorr", bytes_from_point(R) + bytes_from_point(P) + msg)) % n return bytes_from_point(R) + bytes_from_int((k + e * seckey) % n) @@ -104,7 +107,7 @@ def schnorr_verify(msg, pubkey, sig): return False e = int_from_bytes(tagged_hash("BIPSchnorr", sig[0:32] + pubkey + msg)) % n R = point_add(point_mul(G, s), point_mul(P, n - e)) - if R is None or not is_quad(y(R)) or x(R) != r: + if R is None or not has_square_y(R) or x(R) != r: return False return True diff --git a/bip-schnorr/test-vectors.py b/bip-schnorr/test-vectors.py index 52e3b05..768d9f1 100644 --- a/bip-schnorr/test-vectors.py +++ b/bip-schnorr/test-vectors.py @@ -30,10 +30,10 @@ def vector2(): msg = bytes_from_int(0x5E2D58D8B3BCDF1ABADEC7829054F90DDA9805AAB56C77333024B9D0A508B75C) sig = schnorr_sign(msg, seckey) - # This singature vector would not verify if the implementer checked the - # jacobi symbol of the X coordinate of R instead of the Y coordinate. + # This signature vector would not verify if the implementer checked the + # squareness of the X coordinate of R instead of the Y coordinate. R = point_from_bytes(sig[0:32]) - assert(jacobi(R[0]) != 1) + assert(not is_square(R[0])) return (bytes_from_int(seckey), pubkey_gen(seckey), msg, sig, "TRUE", None) @@ -43,15 +43,14 @@ def vector3(): sig = schnorr_sign(msg, seckey) return (bytes_from_int(seckey), pubkey_gen(seckey), msg, sig, "TRUE", "test fails if msg is reduced modulo p or n") -# Signs with a given nonce. Results in an invalid signature if y(kG) is not a -# quadratic residue. +# Signs with a given nonce. Results in an invalid signature if y(kG) is not a square def schnorr_sign_fixed_nonce(msg, seckey0, k): if len(msg) != 32: raise ValueError('The message must be a 32-byte array.') if not (1 <= seckey0 <= n - 1): raise ValueError('The secret key must be an integer in the range 1..n-1.') P = point_mul(G, seckey0) - seckey = seckey0 if (jacobi(P[1]) == 1) else n - seckey0 + seckey = seckey0 if has_square_y(P) else n - seckey0 R = point_mul(G, k) e = int_from_bytes(tagged_hash("BIPSchnorr", bytes_from_point(R) + bytes_from_point(P) + msg)) % n return bytes_from_point(R) + bytes_from_int((k + e * seckey) % n) @@ -84,9 +83,9 @@ def vector6(): k = 3 sig = schnorr_sign_fixed_nonce(msg, seckey, k) - # Y coordinate of R is not a quadratic residue + # Y coordinate of R is not a square R = point_mul(G, k) - assert(jacobi(R[1]) != 1) + assert(not has_square_y(R)) return (None, pubkey_gen(seckey), msg, sig, "FALSE", "incorrect R residuosity") @@ -121,7 +120,7 @@ def vector9(): sig = schnorr_sign_fixed_nonce(msg, seckey, k) bytes_from_point.__code__ = bytes_from_point_tmp - return (None, pubkey_gen(seckey), msg, sig, "FALSE", "sG - eP is infinite. Test fails in single verification if jacobi(y(inf)) is defined as 1 and x(inf) as 0") + return (None, pubkey_gen(seckey), msg, sig, "FALSE", "sG - eP is infinite. Test fails in single verification if has_square_y(inf) is defined as true and x(inf) as 0") def bytes_from_point_inf1(P): if P == None: @@ -140,7 +139,7 @@ def vector10(): sig = schnorr_sign_fixed_nonce(msg, seckey, k) bytes_from_point.__code__ = bytes_from_point_tmp - return (None, pubkey_gen(seckey), msg, sig, "FALSE", "sG - eP is infinite. Test fails in single verification if jacobi(y(inf)) is defined as 1 and x(inf) as 1") + return (None, pubkey_gen(seckey), msg, sig, "FALSE", "sG - eP is infinite. Test fails in single verification if has_square_y(inf) is defined as true and x(inf) as 1") # It's cryptographically impossible to create a test vector that fails if run # in an implementation which merely misses the check that sig[0:32] is an X diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index fd25b77..0e27724 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -59,7 +59,7 @@ The following rules only apply when such an output is being spent. Any other out * Let ''q'' be the 32-byte array containing the witness program (the second push in the scriptPubKey) which represents a public key according to bip-schnorr. * Fail if the witness stack has 0 elements. -* If there are at least two witness elements, and the first byte of the last element is 0x50'''Why is the first byte of the annex 0x50?''' Like the 0xc0 constant, 0x50 is chosen as it could not be confused with a valid P2WPKH or P2WSH spending. As the control block's initial byte's lowest bit is used to indicate the public key's Y quadratic residuosity, each script version needs two subsequence byte values that are both not yet used in P2WPKH or P2WSH spending. To indicate the annex, only an "unpaired" available byte is necessary like 0x50. This choice maximizes the available options for future script versions., this last element is called ''annex'' ''a'''''What is the purpose of the annex?''' The annex is a reserved space for future extensions, such as indicating the validation costs of computationally expensive new opcodes in a way that is recognizable without knowing the outputs being spent. Until the meaning of this field is defined by another softfork, users SHOULD NOT include annex in transactions, or it may lead to PERMANENT FUND LOSS. and is removed from the witness stack. The annex (or the lack of thereof) is always covered by the transaction digest and contributes to transaction weight, but is otherwise ignored during taproot validation. +* If there are at least two witness elements, and the first byte of the last element is 0x50'''Why is the first byte of the annex 0x50?''' Like the 0xc0 constant, 0x50 is chosen as it could not be confused with a valid P2WPKH or P2WSH spending. As the control block's initial byte's lowest bit is used to indicate the public key's Y squareness, each script version needs two subsequence byte values that are both not yet used in P2WPKH or P2WSH spending. To indicate the annex, only an "unpaired" available byte is necessary like 0x50. This choice maximizes the available options for future script versions., this last element is called ''annex'' ''a'''''What is the purpose of the annex?''' The annex is a reserved space for future extensions, such as indicating the validation costs of computationally expensive new opcodes in a way that is recognizable without knowing the outputs being spent. Until the meaning of this field is defined by another softfork, users SHOULD NOT include annex in transactions, or it may lead to PERMANENT FUND LOSS. and is removed from the witness stack. The annex (or the lack of thereof) is always covered by the transaction digest and contributes to transaction weight, but is otherwise ignored during taproot validation. * If there is exactly one element left in the witness stack, key path spending is used: ** The single witness stack element is interpreted as the signature and must be valid (see the next section) for the public key ''q'' and taproot transaction digest (to be defined hereinafter) as message. Fail if it is not. Otherwise pass. * If there are at least two witness elements left, script path spending is used: @@ -67,7 +67,7 @@ The following rules only apply when such an output is being spent. Any other out ** The last stack element is called the control block ''c'', and must have length ''33 + 32m'', for a value of ''m'' that is an integer between 0 and 128'''Why is the Merkle path length limited to 128?''' The optimally space-efficient Merkle tree can be constructed based on the probabilities of the scripts in the leaves, using the Huffman algorithm. This algorithm will construct branches with lengths approximately equal to ''log2(1/probability)'', but to have branches longer than 128 you would need to have scripts with an execution chance below 1 in ''2128''. As that is our security bound, scripts that truly have such a low chance can probably be removed entirely., inclusive. Fail if it does not have such a length. ** Let ''p = c[1:33]'' and let ''P = point(p)'' where ''point'' is defined as in bip-schnorr. Fail if this point is not on the curve. ** Let ''l = c[0] & 0xfe'', the leaf version'''What is the purpose of the first byte of the control block?''' The first byte of the control block has three distinct functions: -* The low bit is used to denote whether the ''Q'' point's Y coordinate is a quadratic residue.'''Why is the quadratic residuosity of the output public key's Y coordinate required in a script path spend?''' The ''point'' function always constructs a point with Y coordinate having that property, but because ''Q'' is constructed by adding the taproot tweak to the internal public key ''P'', it cannot easily be guaranteed that ''Q'' in fact has such a Y coordinate. We can not ignore the Y coordinate because it would prevent batch verification. Trying out multiple internal keys until there's such a ''Q'' is possible but undesirable and unnecessary since this information about the Y coordinate only consumes an unused bit. +* The low bit is used to denote whether the ''has_square_y(Q)'' holds.'''Why is the squareness of the output public key's Y coordinate required in a script path spend?''' The ''point'' function always constructs a point with Y coordinate having that property, but because ''Q'' is constructed by adding the taproot tweak to the internal public key ''P'', it cannot easily be guaranteed that ''Q'' in fact has such a Y coordinate. We can not ignore the Y coordinate because it would prevent batch verification. Trying out multiple internal keys until there's such a ''Q'' is possible but undesirable and unnecessary since this information about the Y coordinate only consumes an unused bit. * By keeping the top two bits set to true, it can be guaranteed that scripts can be recognized without knowledge of the UTXO being spent, simplifying analysis. This is because such values cannot occur as first byte of the final stack element in either P2WPKH or P2WSH spends. * The remaining five bits are used for introducing new script versions that are not observable unless actually executed. . @@ -179,7 +179,7 @@ Alice will not be able to notice the script path, but Mallory can unilaterally s '''Computing the output script''' Once the spending conditions are split into an internal key internal_pubkey and a binary tree whose leaves are (leaf_version, script) tuples, the output script can be computed using the following Python3 algorithms with helper functions from the bip-schnorr reference code for integer conversion, point multiplication and tagged hashes. First, we define taproot_tweak_pubkey for 32-byte bip-schnorr public key arrays. -In addition to the tweaked public key byte array, the function returns a boolean for the quadratic residuosity of the tweaked points' Y coordinate modulo the secp256k1 field order. +In addition to the tweaked public key byte array, the function returns a boolean for the squareness of the tweaked points' Y coordinate modulo the secp256k1 field order. This will be required for spending the output with a script path. In order to allow spending with the key path, we define taproot_tweak_seckey to compute the secret key for a tweaked public key. For any byte string h it holds that taproot_tweak_pubkey(pubkey_gen(seckey), h)[0] == pubkey_gen(taproot_tweak_seckey(seckey, h)). @@ -190,11 +190,11 @@ def taproot_tweak_pubkey(pubkey, h): if t >= SECP256K1_ORDER: raise ValueError Q = point_mul(point(pubkey), t) - return bytes_from_int(x(Q)), is_quad(y(Q)) + return bytes_from_int(x(Q)), has_square_y(Q) def taproot_tweak_seckey(seckey0, h): P = point_mul(G, int_from_bytes(seckey0)) - seckey = SECP256K1_ORDER - seckey0 if not is_quad(y(R)) else seckey + seckey = SECP256K1_ORDER - seckey0 if not has_square_y(R) else seckey t = int_from_bytes(tagged_hash("TapTweak", bytes_from_int(x(P)) + h)) if t >= SECP256K1_ORDER: raise ValueError @@ -254,8 +254,8 @@ This function returns the witness stack necessary and a sighash fun def taproot_sign_script(internal_pubkey, script_tree, script_num, inputs): info, h = taproot_tree_helper(script_tree) (leaf_version, script), path = info[script_num] - _, is_y_quad = taproot_tweak_pubkey(internal_pubkey, t) - output_pubkey_tag = 0 if is_y_quad else 1 + _, is_y_square = taproot_tweak_pubkey(internal_pubkey, t) + output_pubkey_tag = 0 if is_y_square else 1 pubkey_data = bytes([output_pubkey_tag + leaf_version]) + internal_pubkey return inputs + [script, pubkey_data + path] -- cgit v1.2.3 From fdf6e897d9a3b806cbc0f43750de0c1e80ecbcdb Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Fri, 1 Nov 2019 14:44:02 +0000 Subject: Fix test vector generation code after changing schnorrsig_sign api --- bip-schnorr/test-vectors.py | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/bip-schnorr/test-vectors.py b/bip-schnorr/test-vectors.py index 768d9f1..16b82f7 100644 --- a/bip-schnorr/test-vectors.py +++ b/bip-schnorr/test-vectors.py @@ -2,7 +2,7 @@ import sys from reference import * def vector0(): - seckey = 1 + seckey = bytes_from_int(1) msg = bytes_from_int(0) sig = schnorr_sign(msg, seckey) pubkey = pubkey_gen(seckey) @@ -11,10 +11,10 @@ def vector0(): pubkey_point = point_from_bytes(pubkey) assert(pubkey_point[1] & 1 == 0) - return (bytes_from_int(seckey), pubkey, msg, sig, "TRUE", None) + return (seckey, pubkey, msg, sig, "TRUE", None) def vector1(): - seckey = 0xB7E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEF + seckey = bytes_from_int(0xB7E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEF) msg = bytes_from_int(0x243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89) sig = schnorr_sign(msg, seckey) pubkey = pubkey_gen(seckey) @@ -23,10 +23,10 @@ def vector1(): pubkey_point = point_from_bytes(pubkey) assert(pubkey_point[1] & 1 == 1) - return (bytes_from_int(seckey), pubkey, msg, sig, "TRUE", None) + return (seckey, pubkey, msg, sig, "TRUE", None) def vector2(): - seckey = 0xC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B14E5C9 + seckey = bytes_from_int(0xC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B14E5C9) msg = bytes_from_int(0x5E2D58D8B3BCDF1ABADEC7829054F90DDA9805AAB56C77333024B9D0A508B75C) sig = schnorr_sign(msg, seckey) @@ -35,18 +35,19 @@ def vector2(): R = point_from_bytes(sig[0:32]) assert(not is_square(R[0])) - return (bytes_from_int(seckey), pubkey_gen(seckey), msg, sig, "TRUE", None) + return (seckey, pubkey_gen(seckey), msg, sig, "TRUE", None) def vector3(): - seckey = 0x0B432B2677937381AEF05BB02A66ECD012773062CF3FA2549E44F58ED2401710 + seckey = bytes_from_int(0x0B432B2677937381AEF05BB02A66ECD012773062CF3FA2549E44F58ED2401710) msg = bytes_from_int(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) sig = schnorr_sign(msg, seckey) - return (bytes_from_int(seckey), pubkey_gen(seckey), msg, sig, "TRUE", "test fails if msg is reduced modulo p or n") + return (seckey, pubkey_gen(seckey), msg, sig, "TRUE", "test fails if msg is reduced modulo p or n") # Signs with a given nonce. Results in an invalid signature if y(kG) is not a square def schnorr_sign_fixed_nonce(msg, seckey0, k): if len(msg) != 32: raise ValueError('The message must be a 32-byte array.') + seckey0 = int_from_bytes(seckey0) if not (1 <= seckey0 <= n - 1): raise ValueError('The secret key must be an integer in the range 1..n-1.') P = point_mul(G, seckey0) @@ -58,12 +59,12 @@ def schnorr_sign_fixed_nonce(msg, seckey0, k): # Creates a singature with a small x(R) by using k = 1/2 def vector4(): one_half = 0x7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0 - seckey = 0x763758E5CBEEDEE4F7D3FC86F531C36578933228998226672F13C4F0EBE855EB + seckey = bytes_from_int(0x763758E5CBEEDEE4F7D3FC86F531C36578933228998226672F13C4F0EBE855EB) msg = bytes_from_int(0x4DF3C3F68FCC83B27E9D42C90431A72499F17875C81A599B566C9889B9696703) sig = schnorr_sign_fixed_nonce(msg, seckey, one_half) return (None, pubkey_gen(seckey), msg, sig, "TRUE", None) -default_seckey = 0xB7E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEF +default_seckey = bytes_from_int(0xB7E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEF) default_msg = bytes_from_int(0x243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89) def vector5(): -- cgit v1.2.3 From 82129e720d808dd7bffe76e507ba7a10ebf80d7e Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Fri, 1 Nov 2019 14:50:26 +0000 Subject: Adjust test vector generation code to latest terminology --- bip-schnorr/test-vectors.csv | 6 +++--- bip-schnorr/test-vectors.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/bip-schnorr/test-vectors.csv b/bip-schnorr/test-vectors.csv index 7ca6600..9cd0d83 100644 --- a/bip-schnorr/test-vectors.csv +++ b/bip-schnorr/test-vectors.csv @@ -5,11 +5,11 @@ index,secret key,public key,message,signature,verification result,comment 3,0B432B2677937381AEF05BB02A66ECD012773062CF3FA2549E44F58ED2401710,25D1DFF95105F5253C4022F628A996AD3A0D95FBF21D468A1B33F8C160D8F517,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,8BD2C11604B0A87A443FCC2E5D90E5328F934161B18864FB48CE10CB59B45FB9B5B2A0F129BD88F5BDC05D5C21E5C57176B913002335784F9777A24BD317CD36,TRUE,test fails if msg is reduced modulo p or n 4,,D69C3509BB99E412E68B0FE8544E72837DFA30746D8BE2AA65975F29D22DC7B9,4DF3C3F68FCC83B27E9D42C90431A72499F17875C81A599B566C9889B9696703,00000000000000000000003B78CE563F89A0ED9414F5AA28AD0D96D6795F9C63EE374AC7FAE927D334CCB190F6FB8FD27A2DDC639CCEE46D43F113A4035A2C7F,TRUE, 5,,EEFDEA4CDB677750A420FEE807EACF21EB9898AE79B9768766E4FAA04A2D4A34,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,667C2F778E0616E611BD0C14B8A600C5884551701A949EF0EBFD72D452D64E844160BCFC3F466ECB8FACD19ADE57D8699D74E7207D78C6AEDC3799B52A8E0598,FALSE,public key not on the curve -6,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9935554D1AA5F0374E5CDAACB3925035C7C169B27C4426DF0A6B19AF3BAEAB138,FALSE,incorrect R residuosity +6,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9935554D1AA5F0374E5CDAACB3925035C7C169B27C4426DF0A6B19AF3BAEAB138,FALSE,has_square_y(R) is false 7,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,10AC49A6A2EBF604189C5F40FC75AF2D42D77DE9A2782709B1EB4EAF1CFE9108D7003B703A3499D5E29529D39BA040A44955127140F81A8A89A96F992AC0FE79,FALSE,negated message 8,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,667C2F778E0616E611BD0C14B8A600C5884551701A949EF0EBFD72D452D64E84BE9F4303C0B9913470532E6521A827951D39F5C631CFD98CE39AC4D7A5A83BA9,FALSE,negated s value -9,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,000000000000000000000000000000000000000000000000000000000000000099D2F0EBC2996808208633CD9926BF7EC3DAB73DAAD36E85B3040A698E6D1CE0,FALSE,sG - eP is infinite. Test fails in single verification if jacobi(y(inf)) is defined as 1 and x(inf) as 0 -10,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,000000000000000000000000000000000000000000000000000000000000000124E81D89F01304695CE943F7D5EBD00EF726A0864B4FF33895B4E86BEADC5456,FALSE,sG - eP is infinite. Test fails in single verification if jacobi(y(inf)) is defined as 1 and x(inf) as 1 +9,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,000000000000000000000000000000000000000000000000000000000000000099D2F0EBC2996808208633CD9926BF7EC3DAB73DAAD36E85B3040A698E6D1CE0,FALSE,sG - eP is infinite. Test fails in single verification if has_square_y(inf) is defined as true and x(inf) as 0 +10,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,000000000000000000000000000000000000000000000000000000000000000124E81D89F01304695CE943F7D5EBD00EF726A0864B4FF33895B4E86BEADC5456,FALSE,sG - eP is infinite. Test fails in single verification if has_square_y(inf) is defined as true and x(inf) as 1 11,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,4A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1D4160BCFC3F466ECB8FACD19ADE57D8699D74E7207D78C6AEDC3799B52A8E0598,FALSE,sig[0:32] is not an X coordinate on the curve 12,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F4160BCFC3F466ECB8FACD19ADE57D8699D74E7207D78C6AEDC3799B52A8E0598,FALSE,sig[0:32] is equal to field size 13,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,667C2F778E0616E611BD0C14B8A600C5884551701A949EF0EBFD72D452D64E84FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141,FALSE,sig[32:64] is equal to curve order diff --git a/bip-schnorr/test-vectors.py b/bip-schnorr/test-vectors.py index 16b82f7..dca700c 100644 --- a/bip-schnorr/test-vectors.py +++ b/bip-schnorr/test-vectors.py @@ -88,7 +88,7 @@ def vector6(): R = point_mul(G, k) assert(not has_square_y(R)) - return (None, pubkey_gen(seckey), msg, sig, "FALSE", "incorrect R residuosity") + return (None, pubkey_gen(seckey), msg, sig, "FALSE", "has_square_y(R) is false") def vector7(): seckey = default_seckey -- cgit v1.2.3 From a6d2d42aa2c6c689932ca5364a01df94378c9c9e Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Fri, 1 Nov 2019 16:14:57 +0000 Subject: Check infinity in is_positive --- bip-schnorr/reference.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/bip-schnorr/reference.py b/bip-schnorr/reference.py index 7de37c2..4ac93ee 100644 --- a/bip-schnorr/reference.py +++ b/bip-schnorr/reference.py @@ -3,6 +3,9 @@ import binascii p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F n = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 + +# Points are tuples X and Y coordinates and the point at infinity is +# represented by the None keyword. G = (0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798, 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8) # This implementation can be sped up by storing the midstate after hashing -- cgit v1.2.3 From 301fef36de8fff2a8d692f86fbde137f93bff14d Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Sat, 2 Nov 2019 12:17:17 +0000 Subject: Make more clear that signing function in test vectors generation code isn't intended to be used anywhere else --- bip-schnorr/test-vectors.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/bip-schnorr/test-vectors.py b/bip-schnorr/test-vectors.py index dca700c..da7aec6 100644 --- a/bip-schnorr/test-vectors.py +++ b/bip-schnorr/test-vectors.py @@ -43,8 +43,10 @@ def vector3(): sig = schnorr_sign(msg, seckey) return (seckey, pubkey_gen(seckey), msg, sig, "TRUE", "test fails if msg is reduced modulo p or n") -# Signs with a given nonce. Results in an invalid signature if y(kG) is not a square -def schnorr_sign_fixed_nonce(msg, seckey0, k): +# Signs with a given nonce. This can be INSECURE and is only INTENDED FOR +# GENERATING TEST VECTORS. Results in an invalid signature if y(kG) is not +# square. +def insecure_schnorr_sign_fixed_nonce(msg, seckey0, k): if len(msg) != 32: raise ValueError('The message must be a 32-byte array.') seckey0 = int_from_bytes(seckey0) @@ -61,7 +63,7 @@ def vector4(): one_half = 0x7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0 seckey = bytes_from_int(0x763758E5CBEEDEE4F7D3FC86F531C36578933228998226672F13C4F0EBE855EB) msg = bytes_from_int(0x4DF3C3F68FCC83B27E9D42C90431A72499F17875C81A599B566C9889B9696703) - sig = schnorr_sign_fixed_nonce(msg, seckey, one_half) + sig = insecure_schnorr_sign_fixed_nonce(msg, seckey, one_half) return (None, pubkey_gen(seckey), msg, sig, "TRUE", None) default_seckey = bytes_from_int(0xB7E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEF) @@ -82,7 +84,7 @@ def vector6(): seckey = default_seckey msg = default_msg k = 3 - sig = schnorr_sign_fixed_nonce(msg, seckey, k) + sig = insecure_schnorr_sign_fixed_nonce(msg, seckey, k) # Y coordinate of R is not a square R = point_mul(G, k) @@ -118,7 +120,7 @@ def vector9(): k = 0 bytes_from_point_tmp = bytes_from_point.__code__ bytes_from_point.__code__ = bytes_from_point_inf0.__code__ - sig = schnorr_sign_fixed_nonce(msg, seckey, k) + sig = insecure_schnorr_sign_fixed_nonce(msg, seckey, k) bytes_from_point.__code__ = bytes_from_point_tmp return (None, pubkey_gen(seckey), msg, sig, "FALSE", "sG - eP is infinite. Test fails in single verification if has_square_y(inf) is defined as true and x(inf) as 0") @@ -137,7 +139,7 @@ def vector10(): k = 0 bytes_from_point_tmp = bytes_from_point.__code__ bytes_from_point.__code__ = bytes_from_point_inf1.__code__ - sig = schnorr_sign_fixed_nonce(msg, seckey, k) + sig = insecure_schnorr_sign_fixed_nonce(msg, seckey, k) bytes_from_point.__code__ = bytes_from_point_tmp return (None, pubkey_gen(seckey), msg, sig, "FALSE", "sG - eP is infinite. Test fails in single verification if has_square_y(inf) is defined as true and x(inf) as 1") -- cgit v1.2.3 From c9196eeef41b896af9d5fd5eb3823004770fccf0 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Sat, 2 Nov 2019 12:19:17 +0000 Subject: Fix typo in reference code comment --- bip-schnorr/reference.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-schnorr/reference.py b/bip-schnorr/reference.py index 4ac93ee..79be690 100644 --- a/bip-schnorr/reference.py +++ b/bip-schnorr/reference.py @@ -4,7 +4,7 @@ import binascii p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F n = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 -# Points are tuples X and Y coordinates and the point at infinity is +# Points are tuples of X and Y coordinates and the point at infinity is # represented by the None keyword. G = (0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798, 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8) -- cgit v1.2.3 From 9b5ba158c1ee8fc87b6c21de8af58754a7ea3069 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Wed, 23 Oct 2019 17:26:45 +0200 Subject: improve rationale for key prefixing --- bip-schnorr.mediawiki | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 61414f5..31a5904 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -56,7 +56,11 @@ encodings and operations. We choose the ''R''-option to support batch verification. -'''Key prefixing''' When using the verification rule above directly, it is possible for a third party to convert a signature ''(R, s)'' for key ''P'' into a signature ''(R, s + a⋅hash(R || m))'' for key ''P + a⋅G'' and the same message, for any integer ''a''. To combat this, we choose ''key prefixed''A limitation of committing to the public key (rather than to a short hash of it, or not at all) is that it removes the ability for public key recovery or verifying signatures against a short public key hash. These constructions are generally incompatible with batch verification. Schnorr signatures; changing the equation to ''s⋅G = R + hash(R || P || m)⋅P''. Key prefixing also seems to be a requirement for the security proof of the MuSig multisignature scheme (see Applications below). It is not strictly necessary to do this explicitly for Bitcoin currently, as all signature hashes indirectly commit to the public keys already. However, this may change with proposals such as SIGHASH_NOINPUT ([https://github.com/bitcoin/bips/blob/master/bip-0118.mediawiki BIP 118]), or when the signature scheme is used for other purposes—especially in combination with schemes like [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki BIP32]'s unhardened derivation. +'''Key prefixing''' Using the verification rule above directly makes Schnorr signatures vulnerable to "related-key attacks" in which a third party can convert a signature ''(R, s)'' for public key ''P'' into a signature ''(R, s + a⋅hash(R || m))'' for public key ''P + a⋅G'' and the same message ''m'', for any given additive tweak ''a'' to the signing key. This would render signatures insecure when keys are generated using [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#public-parent-key--public-child-key BIP32's unhardened derivation] and other methods that rely on additive tweaks to existing keys such as Taproot. + +To protect against these attacks, we choose ''key prefixed''A limitation of committing to the public key (rather than to a short hash of it, or not at all) is that it removes the ability for public key recovery or verifying signatures against a short public key hash. These constructions are generally incompatible with batch verification. Schnorr signatures; changing the equation to ''s⋅G = R + hash(R || P || m)⋅P''. [https://eprint.iacr.org/2015/1135.pdf It can be shown] that key prefixing protects against related-key attacks with additive tweaks. In general, key prefixing increases robustness in multi-user settings, e.g., it seems to be a requirement for proving the MuSig multisignature scheme secure (see Applications below). + +We note that key prefixing is not strictly necessary for transaction signatures as used in Bitcoin currently, because signed transactions indirectly commit to the public keys already, i.e., ''m'' contains a commitment to ''pk''. However, this indirect commitment should not relied upon because it may change with proposals such as SIGHASH_NOINPUT ([https://github.com/bitcoin/bips/blob/master/bip-0118.mediawiki BIP118]), and would render the signature scheme unsuitable for other purposes than signing transactions, e.g., [https://bitcoin.org/en/developer-reference#signmessage signing ordinary messages]. '''Encoding R and public key point P''' There exist several possibilities for encoding elliptic curve points: # Encoding the full X and Y coordinates of ''P'' and ''R'', resulting in a 64-byte public key and a 96-byte signature. -- cgit v1.2.3 From c8281deec64dcd06b49efd278c322f13f7b13de7 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Mon, 4 Nov 2019 12:53:37 +0000 Subject: Fix point_from_bytes accepting out-of-range pubkeys and add test vector --- bip-schnorr/reference.py | 2 ++ bip-schnorr/test-vectors.py | 26 +++++++++++++++++++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/bip-schnorr/reference.py b/bip-schnorr/reference.py index 79be690..f2a944f 100644 --- a/bip-schnorr/reference.py +++ b/bip-schnorr/reference.py @@ -53,6 +53,8 @@ def bytes_from_point(P): def point_from_bytes(b): x = int_from_bytes(b) + if x >= p: + return None y_sq = (pow(x, 3, p) + 7) % p y = pow(y_sq, (p + 1) // 4, p) if pow(y, 2, p) != y_sq: diff --git a/bip-schnorr/test-vectors.py b/bip-schnorr/test-vectors.py index da7aec6..195b61b 100644 --- a/bip-schnorr/test-vectors.py +++ b/bip-schnorr/test-vectors.py @@ -69,12 +69,14 @@ def vector4(): default_seckey = bytes_from_int(0xB7E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEF) default_msg = bytes_from_int(0x243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89) +# Public key is not on the curve def vector5(): + # This creates a dummy signature that doesn't have anything to do with the + # public key. seckey = default_seckey msg = default_msg sig = schnorr_sign(msg, seckey) - # Public key is not on the curve pubkey = bytes_from_int(0xEEFDEA4CDB677750A420FEE807EACF21EB9898AE79B9768766E4FAA04A2D4A34) assert(point_from_bytes(pubkey) is None) @@ -185,6 +187,27 @@ def vector13(): return (None, pubkey_gen(seckey), msg, sig, "FALSE", "sig[32:64] is equal to curve order") +# Test out of range pubkey +# It's cryptographically impossible to create a test vector that fails if run +# in an implementation which accepts out of range pubkeys because we can't find +# a secret key for such a public key and therefore can not create a signature. +# This test vector just increases test coverage. +def vector14(): + # This creates a dummy signature that doesn't have anything to do with the + # public key. + seckey = default_seckey + msg = default_msg + sig = schnorr_sign(msg, seckey) + + pubkey_int = p + 1 + pubkey = bytes_from_int(pubkey_int) + assert(point_from_bytes(pubkey) is None) + # If an implementation would reduce a given public key modulo p then the + # pubkey would be valid + assert(point_from_bytes(bytes_from_int(pubkey_int % p)) is not None) + + return (None, pubkey, msg, sig, "FALSE", "public key is not a valid X coordinate because it exceeds the field size") + vectors = [ vector0(), vector1(), @@ -200,6 +223,7 @@ vectors = [ vector11(), vector12(), vector13(), + vector14() ] # Converts the byte strings of a test vector into hex strings -- cgit v1.2.3 From fe74ab65dbc119e75eac2c9e25812410e32c4cb0 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Tue, 5 Nov 2019 10:14:23 +0000 Subject: Update test-vectors.csv --- bip-schnorr/test-vectors.csv | 1 + 1 file changed, 1 insertion(+) diff --git a/bip-schnorr/test-vectors.csv b/bip-schnorr/test-vectors.csv index 9cd0d83..3970803 100644 --- a/bip-schnorr/test-vectors.csv +++ b/bip-schnorr/test-vectors.csv @@ -13,3 +13,4 @@ index,secret key,public key,message,signature,verification result,comment 11,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,4A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1D4160BCFC3F466ECB8FACD19ADE57D8699D74E7207D78C6AEDC3799B52A8E0598,FALSE,sig[0:32] is not an X coordinate on the curve 12,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F4160BCFC3F466ECB8FACD19ADE57D8699D74E7207D78C6AEDC3799B52A8E0598,FALSE,sig[0:32] is equal to field size 13,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,667C2F778E0616E611BD0C14B8A600C5884551701A949EF0EBFD72D452D64E84FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141,FALSE,sig[32:64] is equal to curve order +14,,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC30,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,667C2F778E0616E611BD0C14B8A600C5884551701A949EF0EBFD72D452D64E844160BCFC3F466ECB8FACD19ADE57D8699D74E7207D78C6AEDC3799B52A8E0598,FALSE,public key is not a valid X coordinate because it exceeds the field size -- cgit v1.2.3 From 3d97967b97831dc268b39bc8b667d6aace0dc56a Mon Sep 17 00:00:00 2001 From: Max Hillebrand <30683012+MaxHillebrand@users.noreply.github.com> Date: Wed, 6 Nov 2019 05:58:11 +0100 Subject: fix: script spend, not key spend For the key spend the script tree depth is not revealed, it is only done for script spends. This sentence makes sense only for the script spend. --- bip-taproot.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 0e27724..d408357 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -268,7 +268,7 @@ A key path spend could be a "normal" payment from a single- or multi-signature w A script path spend leaks that there is a script path and that the key path was not applicable - for example because the involved parties failed to reach agreement. Moreover, the depth of a script in the Merkle root leaks information including the minimum depth of the tree, which suggests specific wallet software that created the output and helps clustering. -Therefore, the privacy of key spends can be improved by deviating from the optimal tree determined by the probability distribution over the leaves. +Therefore, the privacy of script spends can be improved by deviating from the optimal tree determined by the probability distribution over the leaves. Just like other existing output types, taproot outputs should never reuse keys. This does not only apply to the particular leaf that was used to spend an output but to all leaves committed to in the output. -- cgit v1.2.3 From 4774e4d1e8d856567ad2de9a39b2b3a29f35422a Mon Sep 17 00:00:00 2001 From: Fabian Jahr Date: Tue, 5 Nov 2019 14:53:16 +0100 Subject: Link design section of BIP Schnorr in Specification --- bip-taproot.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index d408357..d8f51ca 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -50,7 +50,7 @@ Not included in this proposal are additional features like new sighash modes or This section specifies the Taproot consensus rules. Validity is defined by exclusion: a block or transaction is valid if no condition exists that marks it failed. -The notation below follows that of bip-schnorr. This includes the ''hashtag(x)'' notation to refer to ''SHA256(SHA256(tag) || SHA256(tag) || x)''. To the best of the authors' knowledge, no existing use of SHA256 in Bitcoin feeds it a message that starts with two single SHA256 outputs, making collisions between ''hashtag'' with other hashes extremely unlikely. +The notation below follows that of [https://github.com/sipa/bips/blob/bip-schnorr/bip-schnorr.mediawiki#design bip-schnorr]. This includes the ''hashtag(x)'' notation to refer to ''SHA256(SHA256(tag) || SHA256(tag) || x)''. To the best of the authors' knowledge, no existing use of SHA256 in Bitcoin feeds it a message that starts with two single SHA256 outputs, making collisions between ''hashtag'' with other hashes extremely unlikely. === Script validation rules === -- cgit v1.2.3 From e9e23e474f758e9e38e30a71773e15e6bdd3e775 Mon Sep 17 00:00:00 2001 From: codeShark149 Date: Wed, 6 Nov 2019 23:48:29 +0530 Subject: Internal pubkey calculation fixed in taproot_tweak_pubkey() --- bip-taproot.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index d8f51ca..298df18 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -189,7 +189,7 @@ def taproot_tweak_pubkey(pubkey, h): t = int_from_bytes(tagged_hash("TapTweak", pubkey + h)) if t >= SECP256K1_ORDER: raise ValueError - Q = point_mul(point(pubkey), t) + Q = point_add(point(pubkey), point_mul(G, t)) return bytes_from_int(x(Q)), has_square_y(Q) def taproot_tweak_seckey(seckey0, h): -- cgit v1.2.3 From 32f364c85c347783d435817142acf35b4ae7db44 Mon Sep 17 00:00:00 2001 From: LaurentMT Date: Mon, 11 Nov 2019 01:20:28 +0100 Subject: Fxied typo in taproot_sign_script() --- bip-taproot.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 298df18..b20dd09 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -254,7 +254,7 @@ This function returns the witness stack necessary and a sighash fun def taproot_sign_script(internal_pubkey, script_tree, script_num, inputs): info, h = taproot_tree_helper(script_tree) (leaf_version, script), path = info[script_num] - _, is_y_square = taproot_tweak_pubkey(internal_pubkey, t) + _, is_y_square = taproot_tweak_pubkey(internal_pubkey, h) output_pubkey_tag = 0 if is_y_square else 1 pubkey_data = bytes([output_pubkey_tag + leaf_version]) + internal_pubkey return inputs + [script, pubkey_data + path] -- cgit v1.2.3 From b5eb53451f3de6e472cbbcb8621699ccc7775cb8 Mon Sep 17 00:00:00 2001 From: Agis Anastasopoulos Date: Mon, 11 Nov 2019 12:39:53 +0200 Subject: Fix typo --- bip-taproot.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index b20dd09..7d646ea 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -302,7 +302,7 @@ Depending on the implementation non-upgraded wallets may be able to send to Segw == Acknowledgements == -This document is the result of discussions around script and signature improvements with many people, and had direct constributions from Jonas Nick, Anthony Towns, Greg Maxwell, and others. It further builds on top of earlier published proposals such as Taproot by Greg Maxwell, and Merkle branch constructions by Russell O'Connor, Johnson Lau, and Mark Friedenbach. +This document is the result of discussions around script and signature improvements with many people, and had direct contributions from Jonas Nick, Anthony Towns, Greg Maxwell, and others. It further builds on top of earlier published proposals such as Taproot by Greg Maxwell, and Merkle branch constructions by Russell O'Connor, Johnson Lau, and Mark Friedenbach. Thanks to Arik Sosman for suggesting to sort Merkle node children before hashes, removing the need to transfer the position in the tree. -- cgit v1.2.3 From 43fbb032352b1836ea2d5f11a4d8221da35e1029 Mon Sep 17 00:00:00 2001 From: Gregory Sanders Date: Mon, 11 Nov 2019 15:32:57 -0500 Subject: BIP16 has no relation to bip-taproot/tapscript Previously did. --- bip-tapscript.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index 9044c71..3e0ccc8 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -50,7 +50,7 @@ The rules below only apply when validating a transaction input for which all of * The leaf version is ''0xc0'' (i.e. the first byte of the last witness element after removing the optional annex is ''0xc0'' or ''0xc1'')'''How is the ''0xc0'' constant chosen?''' Following the guidelines in bip-taproot, by choosing a value having the two top bits set, tapscript spends are identifiable even without access to the UTXO being spent., marking it as a '''tapscript spend'''. Validation of such inputs must be equivalent to performing the following steps in the specified order. -# If the input is invalid due to BIP16, BIP141, or bip-taproot, fail. +# If the input is invalid due to BIP141 or bip-taproot, fail. # The script as defined in bip-taproot (i.e., the penultimate witness stack element after removing the optional annex) is called the '''tapscript''' and is decoded into opcodes, one by one: ## If any opcode numbered ''80, 98, 126-129, 131-134, 137-138, 141-142, 149-153, 187-254'' is encountered, validation succeeds (none of the rules below apply). This is true even if later bytes in the tapscript would fail to decode otherwise. These opcodes are renamed to OP_SUCCESS80, ..., OP_SUCCESS254, and collectively known as OP_SUCCESSx'''OP_SUCCESSx''' OP_SUCCESSx is a mechanism to upgrade the Script system. Using an OP_SUCCESSx before its meaning is defined by a softfork is insecure and leads to fund loss. The inclusion of OP_SUCCESSx in a script will pass it unconditionally. It precedes any script execution rules to avoid the difficulties in specifying various edge cases, for example: OP_SUCCESSx in a script with an input stack larger than 1000 elements, OP_SUCCESSx after too many signature opcodes, or even scripts with conditionals lacking OP_ENDIF. The mere existence of an OP_SUCCESSx anywhere in the script will guarantee a pass for all such cases. OP_SUCCESSx are similar to the OP_RETURN in very early bitcoin versions (v0.1 up to and including v0.3.5). The original OP_RETURN terminates script execution immediately, and return pass or fail based on the top stack element at the moment of termination. This was one of a major design flaws in the original bitcoin protocol as it permitted unconditional third party theft by placing an OP_RETURN in scriptSig. This is not a concern in the present proposal since it is not possible for a third party to inject an OP_SUCCESSx to the validation process, as the OP_SUCCESSx is part of the script (and thus committed to be the taproot output), implying the consent of the coin owner. OP_SUCCESSx can be used for a variety of upgrade possibilities: * An OP_SUCCESSx could be turned into a functional opcode through a softfork. Unlike OP_NOPx-derived opcodes which only have read-only access to the stack, OP_SUCCESSx may also write to the stack. Any rule changes to an OP_SUCCESSx-containing script may only turn a valid script into an invalid one, and this is always achievable with softforks. -- cgit v1.2.3 From 4e88d4fae7c79abc2acd35f036daceacd8122da8 Mon Sep 17 00:00:00 2001 From: Orfeas Stefanos Thyfronitis Litos Date: Wed, 13 Nov 2019 14:00:03 +0000 Subject: Replace R with P in taproot_tweak_seckey --- bip-taproot.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 7d646ea..de266b9 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -194,7 +194,7 @@ def taproot_tweak_pubkey(pubkey, h): def taproot_tweak_seckey(seckey0, h): P = point_mul(G, int_from_bytes(seckey0)) - seckey = SECP256K1_ORDER - seckey0 if not has_square_y(R) else seckey + seckey = SECP256K1_ORDER - seckey0 if not has_square_y(P) else seckey t = int_from_bytes(tagged_hash("TapTweak", bytes_from_int(x(P)) + h)) if t >= SECP256K1_ORDER: raise ValueError -- cgit v1.2.3 From 758be14a2b1c61d7042d708564bed69ebfc66b62 Mon Sep 17 00:00:00 2001 From: Gregory Sanders Date: Fri, 15 Nov 2019 13:46:35 -0500 Subject: remind reader where [:] is defined in addition to `point`. This caused confusion for one reader who expected inclusive at end of range. --- bip-taproot.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index de266b9..7ae422b 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -65,7 +65,7 @@ The following rules only apply when such an output is being spent. Any other out * If there are at least two witness elements left, script path spending is used: ** Call the second-to-last stack element ''s'', the script. ** The last stack element is called the control block ''c'', and must have length ''33 + 32m'', for a value of ''m'' that is an integer between 0 and 128'''Why is the Merkle path length limited to 128?''' The optimally space-efficient Merkle tree can be constructed based on the probabilities of the scripts in the leaves, using the Huffman algorithm. This algorithm will construct branches with lengths approximately equal to ''log2(1/probability)'', but to have branches longer than 128 you would need to have scripts with an execution chance below 1 in ''2128''. As that is our security bound, scripts that truly have such a low chance can probably be removed entirely., inclusive. Fail if it does not have such a length. -** Let ''p = c[1:33]'' and let ''P = point(p)'' where ''point'' is defined as in bip-schnorr. Fail if this point is not on the curve. +** Let ''p = c[1:33]'' and let ''P = point(p)'' where ''point'' and ''[:]'' are defined as in bip-schnorr. Fail if this point is not on the curve. ** Let ''l = c[0] & 0xfe'', the leaf version'''What is the purpose of the first byte of the control block?''' The first byte of the control block has three distinct functions: * The low bit is used to denote whether the ''has_square_y(Q)'' holds.'''Why is the squareness of the output public key's Y coordinate required in a script path spend?''' The ''point'' function always constructs a point with Y coordinate having that property, but because ''Q'' is constructed by adding the taproot tweak to the internal public key ''P'', it cannot easily be guaranteed that ''Q'' in fact has such a Y coordinate. We can not ignore the Y coordinate because it would prevent batch verification. Trying out multiple internal keys until there's such a ''Q'' is possible but undesirable and unnecessary since this information about the Y coordinate only consumes an unused bit. * By keeping the top two bits set to true, it can be guaranteed that scripts can be recognized without knowledge of the UTXO being spent, simplifying analysis. This is because such values cannot occur as first byte of the final stack element in either P2WPKH or P2WSH spends. -- cgit v1.2.3 From b80ebbf2876a40e3999b8d2c027bff40dda781f2 Mon Sep 17 00:00:00 2001 From: Devrandom Date: Wed, 13 Nov 2019 18:46:05 +0100 Subject: clarify 211 hash bytes and non-reuse of keys --- bip-taproot.mediawiki | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 7ae422b..6619789 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -141,7 +141,7 @@ As the message for signature verification, transaction digest is ''hashTapS ** If the SIGHASH_SINGLE flag is set: *** sha_single_output (32): the SHA256 of the corresponding output in CTxOut format. -The total number of bytes hashed is at most ''211'''''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''178 - is_anyonecanpay * 52 - is_none * 32 + has_annex * 32''.. +The total number of bytes hashed at top level is at most ''211'''''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''178 - is_anyonecanpay * 52 - is_none * 32 + has_annex * 32''.. Sub-hashes, such as `sha_prevouts`, may be cached across signatures of the same transaction. In summary, the semantics of the BIP143 sighash types remain unchanged, except the following: # The way and order of serialization is changed.'''Why is the serialization in the transaction digest changed?''' Hashes that go into the digest and the digest itself are now computed with a single SHA256 invocation instead of double SHA256. There is no expected security improvement by doubling SHA256 because this only protects against length-extension attacks against SHA256 which are not a concern for transaction digests because there is no secret data. Therefore doubling SHA256 is a waste of resources. The digest computation now follows a logical order with transaction level data first, then input data and output data. This allows to efficiently cache the transaction part of the digest across different inputs using the SHA256 midstate. Additionally, digest computation avoids unnecessary hashing as opposed to BIP143 digests in which parts may be set zero and before hashing them. Despite that, collisions are made impossible by committing to the length of the data (implicit in hash_type and spend_type) before the variable length data. @@ -270,7 +270,7 @@ A script path spend leaks that there is a script path and that the key path was Moreover, the depth of a script in the Merkle root leaks information including the minimum depth of the tree, which suggests specific wallet software that created the output and helps clustering. Therefore, the privacy of script spends can be improved by deviating from the optimal tree determined by the probability distribution over the leaves. -Just like other existing output types, taproot outputs should never reuse keys. +Just like other existing output types, taproot outputs should never reuse keys, for privacy reasons. This does not only apply to the particular leaf that was used to spend an output but to all leaves committed to in the output. If leaves were reused, it could happen that spending a different output would reuse the same Merkle branches in the Merkle proof. Using fresh keys implies that taproot output construction does not need to take special measures to randomizing leaf positions because they are already randomized due to the branch-sorting Merkle tree construction used in taproot. -- cgit v1.2.3 From ac33640bf5f694b8493751aa30fd1f5dd563fdca Mon Sep 17 00:00:00 2001 From: Dev Random Date: Thu, 14 Nov 2019 10:55:32 -0800 Subject: tweak 211 bytes text --- bip-taproot.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 6619789..a17cb2e 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -141,7 +141,7 @@ As the message for signature verification, transaction digest is ''hashTapS ** If the SIGHASH_SINGLE flag is set: *** sha_single_output (32): the SHA256 of the corresponding output in CTxOut format. -The total number of bytes hashed at top level is at most ''211'''''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''178 - is_anyonecanpay * 52 - is_none * 32 + has_annex * 32''.. Sub-hashes, such as `sha_prevouts`, may be cached across signatures of the same transaction. +The total number of bytes hashed is at most ''211'' (excluding sub-hashes such as `sha_prevouts`)'''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''178 - is_anyonecanpay * 52 - is_none * 32 + has_annex * 32''.. Sub-hashes may be cached across signatures of the same transaction. In summary, the semantics of the BIP143 sighash types remain unchanged, except the following: # The way and order of serialization is changed.'''Why is the serialization in the transaction digest changed?''' Hashes that go into the digest and the digest itself are now computed with a single SHA256 invocation instead of double SHA256. There is no expected security improvement by doubling SHA256 because this only protects against length-extension attacks against SHA256 which are not a concern for transaction digests because there is no secret data. Therefore doubling SHA256 is a waste of resources. The digest computation now follows a logical order with transaction level data first, then input data and output data. This allows to efficiently cache the transaction part of the digest across different inputs using the SHA256 midstate. Additionally, digest computation avoids unnecessary hashing as opposed to BIP143 digests in which parts may be set zero and before hashing them. Despite that, collisions are made impossible by committing to the length of the data (implicit in hash_type and spend_type) before the variable length data. -- cgit v1.2.3 From 4bc42d0f009a789e4ff24d20f4ac55415d8f67db Mon Sep 17 00:00:00 2001 From: Anthony Date: Mon, 11 Nov 2019 13:40:42 -0500 Subject: ADD: Require Schnorr BIP for Taproot Per https://github.com/bitcoin/bips/blob/master/bip-0001.mediawiki: "BIPs may have a Requires header, indicating the BIP numbers that this BIP depends on" --- bip-taproot.mediawiki | 1 + 1 file changed, 1 insertion(+) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index a17cb2e..0fbb7ed 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -9,6 +9,7 @@ Type: Standards Track Created: License: BSD-3-Clause + Requires: BIP-Schnorr ==Introduction== -- cgit v1.2.3 From 662361cc44a617dbd5199963304e9779c69ab67d Mon Sep 17 00:00:00 2001 From: Anthony Date: Tue, 12 Nov 2019 14:08:09 -0500 Subject: ADD: Require Schnorr and Taproot BIPs for Tapscript https://github.com/sipa/bips/pull/135#issuecomment-552754867 --- bip-tapscript.mediawiki | 1 + 1 file changed, 1 insertion(+) diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index 3e0ccc8..7ff8da7 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -9,6 +9,7 @@ Type: Standards Track Created: License: BSD-3-Clause + Requires: BIP-Schnorr, BIP-Taproot ==Introduction== -- cgit v1.2.3 From b2aed3e3fe8f06d3cfd8dd6747cfee127a4f9701 Mon Sep 17 00:00:00 2001 From: Anthony Date: Tue, 12 Nov 2019 15:47:39 -0500 Subject: FIX: BIPs should be specified as lowercase to match filenames --- bip-taproot.mediawiki | 2 +- bip-tapscript.mediawiki | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 0fbb7ed..42ad126 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -9,7 +9,7 @@ Type: Standards Track Created: License: BSD-3-Clause - Requires: BIP-Schnorr + Requires: bip-schnorr ==Introduction== diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index 7ff8da7..644e92e 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -9,7 +9,7 @@ Type: Standards Track Created: License: BSD-3-Clause - Requires: BIP-Schnorr, BIP-Taproot + Requires: bip-schnorr, bip-taproot ==Introduction== -- cgit v1.2.3 From ba7dd5769758a953853200899289121b52ffb2a2 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Mon, 11 Nov 2019 20:09:55 +0200 Subject: G refers to secp256k1 base point rather generator --- bip-schnorr.mediawiki | 4 ++-- bip-taproot.mediawiki | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 31a5904..cff066e 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -48,7 +48,7 @@ encodings and operations. === Design === -'''Schnorr signature variant''' Elliptic Curve Schnorr signatures for message ''m'' and public key ''P'' generally involve a point ''R'', integers ''e'' and ''s'' picked by the signer, and generator ''G'' which satisfy ''e = hash(R || m)'' and ''s⋅G = R + e⋅P''. Two formulations exist, depending on whether the signer reveals ''e'' or ''R'': +'''Schnorr signature variant''' Elliptic Curve Schnorr signatures for message ''m'' and public key ''P'' generally involve a point ''R'', integers ''e'' and ''s'' picked by the signer, and the base point ''G'' which satisfy ''e = hash(R || m)'' and ''s⋅G = R + e⋅P''. Two formulations exist, depending on whether the signer reveals ''e'' or ''R'': # Signatures are ''(e, s)'' that satisfy ''e = hash(s⋅G - e⋅P || m)''. This supports more compact signatures, since [http://www.neven.org/papers/schnorr.pdf the hash ''e'' can be made as small as 16 bytes without sacrificing security], whereas an encoding of ''R'' inherently needs about 32 bytes. Moreover, this variant avoids minor complexity introduced by the encoding of the point ''R'' in the signature (see paragraphs "Encoding the sign of R" and "Implicit Y coordinate" further below in this subsection). # Signatures are ''(R, s)'' that satisfy ''s⋅G = R + hash(R || m)⋅P''. This supports batch verification, as there are no elliptic curve operations inside the hashes. Batch verification enables significant speedups. @@ -100,7 +100,7 @@ The following conventions are used, with constants as defined for [https://www.s * Uppercase variables refer to points on the curve with equation ''y2 = x3 + 7'' over the integers modulo ''p''. ** ''is_infinite(P)'' returns whether or not ''P'' is the point at infinity. ** ''x(P)'' and ''y(P)'' are integers in the range ''0..p-1'' and refer to the X and Y coordinates of a point ''P'' (assuming it is not infinity). -** The constant ''G'' refers to the generator, for which ''x(G) = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798'' and ''y(G) = 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8''. +** The constant ''G'' refers to the base point, for which ''x(G) = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798'' and ''y(G) = 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8''. ** Addition of points refers to the usual [https://en.wikipedia.org/wiki/Elliptic_curve#The_group_law elliptic curve group operation]. ** [https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication Multiplication (⋅) of an integer and a point] refers to the repeated application of the group operation. * Functions and operations: diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 42ad126..6a8c8bb 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -162,7 +162,7 @@ Satisfying any of these conditions is sufficient to spend the output. '''Initial steps''' The first step is determining what the internal key and the organization of the rest of the scripts should be. The specifics are likely application dependent, but here are some general guidelines: * When deciding between scripts with conditionals (OP_IF etc.) and splitting them up into multiple scripts (each corresponding to one execution path through the original script), it is generally preferable to pick the latter. * When a single condition requires signatures with multiple keys, key aggregation techniques like MuSig can be used to combine them into a single key. The details are out of scope for this document, but note that this may complicate the signing procedure. -* If one or more of the spending conditions consist of just a single key (after aggregation), the most likely one should be made the internal key. If no such condition exists, it may be worthwhile adding one that consists of an aggregation of all keys participating in all scripts combined; effectively adding an "everyone agrees" branch. If that is inacceptable, pick as internal key a point with unknown discrete logarithm. One example of such a point is ''H = point(0x0250929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0)'' which is [https://github.com/ElementsProject/secp256k1-zkp/blob/11af7015de624b010424273be3d91f117f172c82/src/modules/rangeproof/main_impl.h#L16 constructed] by taking the hash of the standard uncompressed encoding of secp256k1 generator ''G'' as X coordinate. In order to avoid leaking the information that key path spending is not possible it is recommended to pick a fresh integer ''r'' in the range ''0...n-1'' uniformly at random and use ''H + rG'' as internal key. It is possible to prove that this internal key does not have a known discrete logarithm with respect to ''G'' by revealing ''r'' to a verifier who can then reconstruct how the internal key was created. +* If one or more of the spending conditions consist of just a single key (after aggregation), the most likely one should be made the internal key. If no such condition exists, it may be worthwhile adding one that consists of an aggregation of all keys participating in all scripts combined; effectively adding an "everyone agrees" branch. If that is inacceptable, pick as internal key a point with unknown discrete logarithm. One example of such a point is ''H = point(0x0250929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0)'' which is [https://github.com/ElementsProject/secp256k1-zkp/blob/11af7015de624b010424273be3d91f117f172c82/src/modules/rangeproof/main_impl.h#L16 constructed] by taking the hash of the standard uncompressed encoding of the [https://www.secg.org/sec2-v2.pdf secp256k1] base point ''G'' as X coordinate. In order to avoid leaking the information that key path spending is not possible it is recommended to pick a fresh integer ''r'' in the range ''0...n-1'' uniformly at random and use ''H + rG'' as internal key. It is possible to prove that this internal key does not have a known discrete logarithm with respect to ''G'' by revealing ''r'' to a verifier who can then reconstruct how the internal key was created. * If the spending conditions do not require a script path, the output key should commit to an unspendable script path instead of having no script path. This can be achieved by computing the output key point as ''Q = P + int(hashTapTweak(bytes(P)))G''. '''Why should the output key always have a taproot commitment, even if there is no script path?''' If the taproot output key is an aggregate of keys, there is the possibility for a malicious party to add a script path without being noticed by the other parties. This allows to bypass the multiparty policy and to steal the coin. -- cgit v1.2.3 From 4f67ed25c7704d38c16c7d81a65da2dc663b7729 Mon Sep 17 00:00:00 2001 From: Adam Gibson Date: Tue, 12 Nov 2019 11:41:27 +0000 Subject: Add clarification of semantics of 0x00 hash type --- bip-taproot.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 6a8c8bb..7b23ea9 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -101,7 +101,7 @@ The following rules apply: ==== hash_type ==== -hash_type is an 8-bit unsigned value. The SIGHASH encodings from the legacy script system are used, including SIGHASH_ALL, SIGHASH_NONE, SIGHASH_SINGLE, and SIGHASH_ANYONECANPAY +hash_type is an 8-bit unsigned value. The SIGHASH encodings from the legacy script system are used, including SIGHASH_ALL, SIGHASH_NONE, SIGHASH_SINGLE, and SIGHASH_ANYONECANPAY. Use of the default hash_type = 0x00 results in signing over the whole transaction just as for SIGHASH_ALL. The following use of hash_type are invalid, and fail execution: -- cgit v1.2.3 From daff462f9d23d7b7db96137fbdff91ba9a8f594e Mon Sep 17 00:00:00 2001 From: Orfeas Stefanos Thyfronitis Litos Date: Wed, 13 Nov 2019 17:20:09 +0000 Subject: Add links to unlinked BIPs Only first mention of each BIP is made into a link --- bip-taproot.mediawiki | 6 +++--- bip-tapscript.mediawiki | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 7b23ea9..93aefbe 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -76,7 +76,7 @@ The following rules only apply when such an output is being spent. Any other out ** For ''j'' in ''[0,1,...,m-1]'': *** Let ''ej = c[33+32j:65+32j]''. *** Let ''kj+1 depend on whether ''kj < ej'' (lexicographically)'''Why are child elements sorted before hashing in the Merkle tree?''' By doing so, it is not necessary to reveal the left/right directions along with the hashes in revealed Merkle branches. This is possible because we do not actually care about the position of specific scripts in the tree; only that they are actually committed to.: -**** If ''kj < ej'': ''kj+1 = hashTapBranch(kj || ej)'''''Why not use a more efficient hash construction for inner Merkle nodes?''' The chosen construction does require two invocations of the SHA256 compression functions, one of which can be avoided in theory (see BIP98). However, it seems preferable to stick to constructions that can be implemented using standard cryptographic primitives, both for implementation simplicity and analyzability. If necessary, a significant part of the second compression function can be optimized out by [https://github.com/bitcoin/bitcoin/pull/13191 specialization] for 64-byte inputs.. +**** If ''kj < ej'': ''kj+1 = hashTapBranch(kj || ej)'''''Why not use a more efficient hash construction for inner Merkle nodes?''' The chosen construction does require two invocations of the SHA256 compression functions, one of which can be avoided in theory (see [https://github.com/bitcoin/bips/blob/master/bip-0098.mediawiki BIP98]). However, it seems preferable to stick to constructions that can be implemented using standard cryptographic primitives, both for implementation simplicity and analyzability. If necessary, a significant part of the second compression function can be optimized out by [https://github.com/bitcoin/bitcoin/pull/13191 specialization] for 64-byte inputs.. **** If ''kj ≥ ej'': ''kj+1 = hashTapBranch(ej || kj)''. ** Let ''t = hashTapTweak(p || km)''. ** If ''t ≥ 0xFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141'' (order of secp256k1), fail. @@ -144,7 +144,7 @@ As the message for signature verification, transaction digest is ''hashTapS The total number of bytes hashed is at most ''211'' (excluding sub-hashes such as `sha_prevouts`)'''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''178 - is_anyonecanpay * 52 - is_none * 32 + has_annex * 32''.. Sub-hashes may be cached across signatures of the same transaction. -In summary, the semantics of the BIP143 sighash types remain unchanged, except the following: +In summary, the semantics of the [https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki BIP143] sighash types remain unchanged, except the following: # The way and order of serialization is changed.'''Why is the serialization in the transaction digest changed?''' Hashes that go into the digest and the digest itself are now computed with a single SHA256 invocation instead of double SHA256. There is no expected security improvement by doubling SHA256 because this only protects against length-extension attacks against SHA256 which are not a concern for transaction digests because there is no secret data. Therefore doubling SHA256 is a waste of resources. The digest computation now follows a logical order with transaction level data first, then input data and output data. This allows to efficiently cache the transaction part of the digest across different inputs using the SHA256 midstate. Additionally, digest computation avoids unnecessary hashing as opposed to BIP143 digests in which parts may be set zero and before hashing them. Despite that, collisions are made impossible by committing to the length of the data (implicit in hash_type and spend_type) before the variable length data. # The digest commits to the scriptPubKey'''Why does the transaction digest commit to the scriptPubKey?''' This prevents lying to offline signing devices about output being spent, even when the actually executed script (scriptCode in BIP143) is correct. This means it's possible to compactly prove to a hardware wallet what (unused) execution paths existed.. # If the SIGHASH_ANYONECANPAY flag is not set, the digest commits to the amounts of ''all'' transaction inputs.'''Why does the transaction digest commit to the amounts of all transaction inputs?''' This eliminates the possibility to lie to offline signing devices about the fee of a transaction. @@ -299,7 +299,7 @@ Non-upgraded nodes, however, will consider all SegWit version 1 witness programs They are strongly encouraged to upgrade in order to fully validate the new programs. Non-upgraded wallets can receive and send bitcoin from non-upgraded and upgraded wallets using SegWit version 0 programs, traditional pay-to-pubkey-hash, etc. -Depending on the implementation non-upgraded wallets may be able to send to Segwit version 1 programs if they support sending to BIP173 Bech32 addresses. +Depending on the implementation non-upgraded wallets may be able to send to Segwit version 1 programs if they support sending to [https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki BIP173] Bech32 addresses. == Acknowledgements == diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index 644e92e..37e217b 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -45,7 +45,7 @@ Additionally, the new tapscript OP_SUCCESS opcodes allow introducin ==Specification== The rules below only apply when validating a transaction input for which all of the conditions below are true: -* The transaction output is a '''segregated witness spend''' (i.e., the scriptPubKey is a witness program as defined in BIP141). +* The transaction output is a '''segregated witness spend''' (i.e., the scriptPubKey is a witness program as defined in [https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki BIP141]). * It is a '''taproot spend''' as defined in bip-taproot (i.e., the witness version is 1, the witness program is 32 bytes, and it is not P2SH wrapped). * It is a '''script path spend''' as defined in bip-taproot (i.e., after removing the optional annex from the witness stack, two or more stack elements remain). * The leaf version is ''0xc0'' (i.e. the first byte of the last witness element after removing the optional annex is ''0xc0'' or ''0xc1'')'''How is the ''0xc0'' constant chosen?''' Following the guidelines in bip-taproot, by choosing a value having the two top bits set, tapscript spends are identifiable even without access to the UTXO being spent., marking it as a '''tapscript spend'''. @@ -67,7 +67,7 @@ Validation of such inputs must be equivalent to performing the following steps i ===Script execution=== -The execution rules for tapscript are based on those for P2WSH according to BIP141, including the OP_CHECKLOCKTIMEVERIFY and OP_CHECKSEQUENCEVERIFY opcodes defined in BIP65 and BIP112, but with the following modifications: +The execution rules for tapscript are based on those for P2WSH according to BIP141, including the OP_CHECKLOCKTIMEVERIFY and OP_CHECKSEQUENCEVERIFY opcodes defined in [https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki BIP65] and [https://github.com/bitcoin/bips/blob/master/bip-0112.mediawiki BIP112], but with the following modifications: * '''Disabled script opcodes''' The following script opcodes are disabled in tapscript: OP_CHECKMULTISIG and OP_CHECKMULTISIGVERIFY'''Why are OP_CHECKMULTISIG and OP_CHECKMULTISIGVERIFY disabled, and not turned into OP_SUCCESSx?''' This is a precaution to make sure people who accidentally keep using OP_CHECKMULTISIG in Tapscript notice a problem immediately. It also avoids the complication of script disassemblers needing to become context-dependent.. The disabled opcodes behave in the same way as OP_RETURN, by failing and terminating the script immediately when executed, and being ignored when found in unexecuted branch. * '''Consensus-enforced MINIMALIF''' The MINIMALIF rules, which are only a standardness rule in P2WSH, are consensus enforced in tapscript. This means that the input argument to the OP_IF and OP_NOTIF opcodes must be either exactly 0 (the empty vector) or exactly 1 (the one-byte vector with value 1)'''Why make MINIMALIF consensus?''' This makes it considerably easier to write non-malleable scripts that take branch information from the stack.. * '''OP_SUCCESSx opcodes''' As listed above, some opcodes are renamed to OP_SUCCESSx, and make the script unconditionally valid. @@ -117,7 +117,7 @@ As additional pieces of data, added at the end of the input to the ''hashTa The total number of bytes hashed is at most ''248'''''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''215 - is_anyonecanpay * 52 - is_none * 32 + has_annex * 32''.. -In summary, the semantics of the BIP143 sighash types remain unchanged, except the following: +In summary, the semantics of the [https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki BIP143] sighash types remain unchanged, except the following: # The exceptions mentioned in bip-taproot. # The digest commits to taproot-specific data key_version.'''Why does the transaction digest commit to the key_version?''' This is for future extensions that define unknown public key types, making sure signatures can't be moved from one key type to another. # The digest commits to the executed script through the tapleaf_hash which includes the leaf version and script instead of scriptCode. This implies that this commitment is unaffected by OP_CODESEPARATOR. -- cgit v1.2.3 From 28f67764ec3d5286e723f25ddaaa217f43157b69 Mon Sep 17 00:00:00 2001 From: Jon Atack Date: Tue, 12 Nov 2019 22:37:47 +0100 Subject: bip-taproot: clarify bip-schnorr reference code - update the paragraph in question to more clearly convey that the helper functions, and not the Python3 example code, are from the bip-schnorr reference code - add a link to the reference code in https://github.com/sipa/bips/blob/bip-schnorr/bip-schnorr/reference.py --- bip-taproot.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 93aefbe..1119785 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -177,7 +177,7 @@ Alice will not be able to notice the script path, but Mallory can unilaterally s * The remaining scripts should be organized into the leaves of a binary tree. This can be a balanced tree if each of the conditions these scripts correspond to are equally likely. If probabilities for each condition are known, consider constructing the tree as a Huffman tree. -'''Computing the output script''' Once the spending conditions are split into an internal key internal_pubkey and a binary tree whose leaves are (leaf_version, script) tuples, the output script can be computed using the following Python3 algorithms with helper functions from the bip-schnorr reference code for integer conversion, point multiplication and tagged hashes. +'''Computing the output script''' Once the spending conditions are split into an internal key internal_pubkey and a binary tree whose leaves are (leaf_version, script) tuples, the output script can be computed using the Python3 algorithms below. These algorithms take advantage of helper functions from the [https://github.com/sipa/bips/blob/bip-schnorr/bip-schnorr/reference.py bip-schnorr reference code] for integer conversion, point multiplication, and tagged hashes. First, we define taproot_tweak_pubkey for 32-byte bip-schnorr public key arrays. In addition to the tweaked public key byte array, the function returns a boolean for the squareness of the tweaked points' Y coordinate modulo the secp256k1 field order. -- cgit v1.2.3 From 769a17b3b93779aabb7cc51d0090b8101db3ef05 Mon Sep 17 00:00:00 2001 From: Thomas Kerin Date: Mon, 11 Nov 2019 02:41:15 +0000 Subject: tapscript: fix minor typo --- bip-tapscript.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index 37e217b..d4cd5da 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -53,7 +53,7 @@ The rules below only apply when validating a transaction input for which all of Validation of such inputs must be equivalent to performing the following steps in the specified order. # If the input is invalid due to BIP141 or bip-taproot, fail. # The script as defined in bip-taproot (i.e., the penultimate witness stack element after removing the optional annex) is called the '''tapscript''' and is decoded into opcodes, one by one: -## If any opcode numbered ''80, 98, 126-129, 131-134, 137-138, 141-142, 149-153, 187-254'' is encountered, validation succeeds (none of the rules below apply). This is true even if later bytes in the tapscript would fail to decode otherwise. These opcodes are renamed to OP_SUCCESS80, ..., OP_SUCCESS254, and collectively known as OP_SUCCESSx'''OP_SUCCESSx''' OP_SUCCESSx is a mechanism to upgrade the Script system. Using an OP_SUCCESSx before its meaning is defined by a softfork is insecure and leads to fund loss. The inclusion of OP_SUCCESSx in a script will pass it unconditionally. It precedes any script execution rules to avoid the difficulties in specifying various edge cases, for example: OP_SUCCESSx in a script with an input stack larger than 1000 elements, OP_SUCCESSx after too many signature opcodes, or even scripts with conditionals lacking OP_ENDIF. The mere existence of an OP_SUCCESSx anywhere in the script will guarantee a pass for all such cases. OP_SUCCESSx are similar to the OP_RETURN in very early bitcoin versions (v0.1 up to and including v0.3.5). The original OP_RETURN terminates script execution immediately, and return pass or fail based on the top stack element at the moment of termination. This was one of a major design flaws in the original bitcoin protocol as it permitted unconditional third party theft by placing an OP_RETURN in scriptSig. This is not a concern in the present proposal since it is not possible for a third party to inject an OP_SUCCESSx to the validation process, as the OP_SUCCESSx is part of the script (and thus committed to be the taproot output), implying the consent of the coin owner. OP_SUCCESSx can be used for a variety of upgrade possibilities: +## If any opcode numbered ''80, 98, 126-129, 131-134, 137-138, 141-142, 149-153, 187-254'' is encountered, validation succeeds (none of the rules below apply). This is true even if later bytes in the tapscript would fail to decode otherwise. These opcodes are renamed to OP_SUCCESS80, ..., OP_SUCCESS254, and collectively known as OP_SUCCESSx'''OP_SUCCESSx''' OP_SUCCESSx is a mechanism to upgrade the Script system. Using an OP_SUCCESSx before its meaning is defined by a softfork is insecure and leads to fund loss. The inclusion of OP_SUCCESSx in a script will pass it unconditionally. It precedes any script execution rules to avoid the difficulties in specifying various edge cases, for example: OP_SUCCESSx in a script with an input stack larger than 1000 elements, OP_SUCCESSx after too many signature opcodes, or even scripts with conditionals lacking OP_ENDIF. The mere existence of an OP_SUCCESSx anywhere in the script will guarantee a pass for all such cases. OP_SUCCESSx are similar to the OP_RETURN in very early bitcoin versions (v0.1 up to and including v0.3.5). The original OP_RETURN terminates script execution immediately, and return pass or fail based on the top stack element at the moment of termination. This was one of a major design flaws in the original bitcoin protocol as it permitted unconditional third party theft by placing an OP_RETURN in scriptSig. This is not a concern in the present proposal since it is not possible for a third party to inject an OP_SUCCESSx to the validation process, as the OP_SUCCESSx is part of the script (and thus committed to by the taproot output), implying the consent of the coin owner. OP_SUCCESSx can be used for a variety of upgrade possibilities: * An OP_SUCCESSx could be turned into a functional opcode through a softfork. Unlike OP_NOPx-derived opcodes which only have read-only access to the stack, OP_SUCCESSx may also write to the stack. Any rule changes to an OP_SUCCESSx-containing script may only turn a valid script into an invalid one, and this is always achievable with softforks. * Since OP_SUCCESSx precedes size check of initial stack and push opcodes, an OP_SUCCESSx-derived opcode requiring stack elements bigger than 520 bytes may uplift the limit in a softfork. * OP_SUCCESSx may also redefine the behavior of existing opcodes so they could work together with the new opcode. For example, if an OP_SUCCESSx-derived opcode works with 64-bit integers, it may also allow the existing arithmetic opcodes in the ''same script'' to do the same. -- cgit v1.2.3 From 54384a5710b4bf167dfe6ac5c9cca131f4c954f7 Mon Sep 17 00:00:00 2001 From: Max Hillebrand <30683012+MaxHillebrand@users.noreply.github.com> Date: Mon, 18 Nov 2019 14:56:29 +0800 Subject: make clear it's script branch In this context we are talking about the script branch, not the Merkle tree branch, right? If so, then this should clear things up a little. --- bip-tapscript.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index d4cd5da..c80433d 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -68,7 +68,7 @@ Validation of such inputs must be equivalent to performing the following steps i ===Script execution=== The execution rules for tapscript are based on those for P2WSH according to BIP141, including the OP_CHECKLOCKTIMEVERIFY and OP_CHECKSEQUENCEVERIFY opcodes defined in [https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki BIP65] and [https://github.com/bitcoin/bips/blob/master/bip-0112.mediawiki BIP112], but with the following modifications: -* '''Disabled script opcodes''' The following script opcodes are disabled in tapscript: OP_CHECKMULTISIG and OP_CHECKMULTISIGVERIFY'''Why are OP_CHECKMULTISIG and OP_CHECKMULTISIGVERIFY disabled, and not turned into OP_SUCCESSx?''' This is a precaution to make sure people who accidentally keep using OP_CHECKMULTISIG in Tapscript notice a problem immediately. It also avoids the complication of script disassemblers needing to become context-dependent.. The disabled opcodes behave in the same way as OP_RETURN, by failing and terminating the script immediately when executed, and being ignored when found in unexecuted branch. +* '''Disabled script opcodes''' The following script opcodes are disabled in tapscript: OP_CHECKMULTISIG and OP_CHECKMULTISIGVERIFY'''Why are OP_CHECKMULTISIG and OP_CHECKMULTISIGVERIFY disabled, and not turned into OP_SUCCESSx?''' This is a precaution to make sure people who accidentally keep using OP_CHECKMULTISIG in Tapscript notice a problem immediately. It also avoids the complication of script disassemblers needing to become context-dependent.. The disabled opcodes behave in the same way as OP_RETURN, by failing and terminating the script immediately when executed, and being ignored when found in unexecuted branch of the script. * '''Consensus-enforced MINIMALIF''' The MINIMALIF rules, which are only a standardness rule in P2WSH, are consensus enforced in tapscript. This means that the input argument to the OP_IF and OP_NOTIF opcodes must be either exactly 0 (the empty vector) or exactly 1 (the one-byte vector with value 1)'''Why make MINIMALIF consensus?''' This makes it considerably easier to write non-malleable scripts that take branch information from the stack.. * '''OP_SUCCESSx opcodes''' As listed above, some opcodes are renamed to OP_SUCCESSx, and make the script unconditionally valid. * '''Signature opcodes'''. The OP_CHECKSIG and OP_CHECKSIGVERIFY are modified to operate on Schnorr public keys and signatures (see bip-schnorr) instead of ECDSA, and a new opcode OP_CHECKSIGADD is added. -- cgit v1.2.3 From e72fffa02834c46fa99362dabc7c53804955d55d Mon Sep 17 00:00:00 2001 From: Orfeas Stefanos Thyfronitis Litos Date: Mon, 18 Nov 2019 14:42:56 +0000 Subject: Fix typo in schnorr, footnote 2 --- bip-schnorr.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index cff066e..861369c 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -25,7 +25,7 @@ Bitcoin has traditionally used transactions. These are [https://www.secg.org/sec1-v2.pdf standardized], but have a number of downsides compared to [http://publikationen.ub.uni-frankfurt.de/opus4/files/4280/schnorr.pdf Schnorr signatures] over the same curve: -* '''Provable security''': Schnorr signatures are provably secure. In more detail, they are ''strongly unforgeable under chosen message attack (SUF-CMA)''Informally, this means that without knowledge of the secret key but given valid signatures of arbitrary messages, it is not possible to come up with further valid signatures. [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf in the random oracle model assuming the hardness of the elliptic curve discrete logarithm problem (ECDLP)] and [http://www.neven.org/papers/schnorr.pdf in the generic group model assuming variants of preimage and second preimage resistance of the used hash function]A detailed security proof in the random oracle model, which essentially restates [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf the original security proof by Pointcheval and Stern] more explicitly, can be found in [https://eprint.iacr.org/2016/191 a paper by Kiltz, Masny and Pan]. All these security proofs assume a variant of Schnorr signatures that use ''(e,s)'' instead of ''(R,s)'' (see Design above). Since we use a unique encoding of ''R'', there is an efficiently computable bijection that maps ''(R,s)'' to ''(e,s)'', which allows to convert a successful SUF-CMA attacker for the ''(e,s)'' variant to a successful SUF-CMA attacker for the ''(r,s)'' variant (and vice-versa). Furthermore, the proofs consider a variant of Schnorr signatures without key prefixing (see Design above), but it can be verified that the proofs are also correct for the variant with key prefixing. As a result, all the aforementioned security proofs apply to the variant of Schnorr signatures proposed in this document.. In contrast, the [https://nbn-resolving.de/urn:nbn:de:hbz:294-60803 best known results for the provable security of ECDSA] rely on stronger assumptions. +* '''Provable security''': Schnorr signatures are provably secure. In more detail, they are ''strongly unforgeable under chosen message attack (SUF-CMA)''Informally, this means that without knowledge of the secret key but given valid signatures of arbitrary messages, it is not possible to come up with further valid signatures. [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf in the random oracle model assuming the hardness of the elliptic curve discrete logarithm problem (ECDLP)] and [http://www.neven.org/papers/schnorr.pdf in the generic group model assuming variants of preimage and second preimage resistance of the used hash function]A detailed security proof in the random oracle model, which essentially restates [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf the original security proof by Pointcheval and Stern] more explicitly, can be found in [https://eprint.iacr.org/2016/191 a paper by Kiltz, Masny and Pan]. All these security proofs assume a variant of Schnorr signatures that use ''(e,s)'' instead of ''(R,s)'' (see Design above). Since we use a unique encoding of ''R'', there is an efficiently computable bijection that maps ''(R,s)'' to ''(e,s)'', which allows to convert a successful SUF-CMA attacker for the ''(e,s)'' variant to a successful SUF-CMA attacker for the ''(R,s)'' variant (and vice-versa). Furthermore, the proofs consider a variant of Schnorr signatures without key prefixing (see Design above), but it can be verified that the proofs are also correct for the variant with key prefixing. As a result, all the aforementioned security proofs apply to the variant of Schnorr signatures proposed in this document.. In contrast, the [https://nbn-resolving.de/urn:nbn:de:hbz:294-60803 best known results for the provable security of ECDSA] rely on stronger assumptions. * '''Non-malleability''': The SUF-CMA security of Schnorr signatures implies that they are non-malleable. On the other hand, ECDSA signatures are inherently malleable; a third party without access to the secret key can alter an existing valid signature for a given public key and message into another signature that is valid for the same key and message. This issue is discussed in [https://github.com/bitcoin/bips/blob/master/bip-0062.mediawiki BIP62] and [https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki BIP66]. * '''Linearity''': Schnorr signatures have the remarkable property that multiple parties can collaborate to produce a signature that is valid for the sum of their public keys. This is the building block for various higher-level constructions that improve efficiency and privacy, such as multisignatures and others (see Applications below). -- cgit v1.2.3 From 1661efc99930c56ccaa24c959f4fe799fcafdaab Mon Sep 17 00:00:00 2001 From: Orfeas Stefanos Thyfronitis Litos Date: Mon, 18 Nov 2019 17:00:39 +0000 Subject: Add missing quote --- bip-schnorr.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 861369c..3d6a957 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -107,7 +107,7 @@ The following conventions are used, with constants as defined for [https://www.s ** ''||'' refers to byte array concatenation. ** The function ''x[i:j]'', where ''x'' is a byte array, returns a ''(j - i)''-byte array with a copy of the ''i''-th byte (inclusive) to the ''j''-th byte (exclusive) of ''x''. ** The function ''bytes(x)'', where ''x'' is an integer, returns the 32-byte encoding of ''x'', most significant byte first. -** The function ''bytes(P)'', where ''P'' is a point, returns ''bytes(x(P))'. +** The function ''bytes(P)'', where ''P'' is a point, returns ''bytes(x(P))''. ** The function ''int(x)'', where ''x'' is a 32-byte array, returns the 256-bit unsigned integer whose most significant byte first encoding is ''x''. ** The function ''is_square(x)'', where ''x'' is an integer, returns whether or not ''x'' is a quadratic residue modulo ''p''. Since ''p'' is prime, it is equivalent to the Legendre symbol ''(x / p) = x(p-1)/2 mod p'' being equal to ''1'' (see [https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion])For points ''P'' on the secp256k1 curve it holds that ''x(p-1)/2 ≠ 0 mod p''.. ** The function ''has_square_y(P)'', where ''P'' is a point, is defined as ''not is_infinite(P) and is_square(y(P))''For points ''P'' on the secp256k1 curve it holds that ''has_square_y(P) = not has_square_y(-P)''.. -- cgit v1.2.3 From 7a434d4d769a4e0c2fd9684bf474f192264f182f Mon Sep 17 00:00:00 2001 From: Dmitry Petukhov Date: Thu, 21 Nov 2019 14:25:53 +0500 Subject: Add missing dots that denote multiplication MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Throughout the document, elliptic curve multiplication is denoted with dots, as in `d'⋅G` as opposed to `d'G`. This is not the case in one place in the 'Default Signing' section, and one place in 'Adaptor Signatures' section Missing dots are added for consistency. --- bip-schnorr.mediawiki | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 3d6a957..5e4bd47 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -146,7 +146,7 @@ The algorithm ''Sign(sk, m)'' is defined as: * Let ''d = d' '' if ''has_square_y(P)'', otherwise let ''d = n - d' ''. * Let ''k' = int(hashBIPSchnorrDerive(bytes(d) || m)) mod n''Note that in general, taking the output of a hash function modulo the curve order will produce an unacceptably biased result. However, for the secp256k1 curve, the order is sufficiently close to ''2256'' that this bias is not observable (''1 - n / 2256'' is around ''1.27 * 2-128'').. * Fail if ''k' = 0''. -* Let ''R = k'G''. +* Let ''R = k'⋅G''. * Let ''k = k' '' if ''has_square_y(R)'', otherwise let ''k = n - k' ''. * Let ''e = int(hashBIPSchnorr(bytes(R) || bytes(P) || m)) mod n''. * Return the signature ''bytes(R) || bytes((k + ed) mod n)''. @@ -226,7 +226,7 @@ Moreover, Schnorr signatures are compatible with [https://web.archive.org/web/20 === Adaptor Signatures === -[https://download.wpsoftware.net/bitcoin/wizardry/mw-slides/2018-05-18-l2/slides.pdf Adaptor signatures] can be produced by a signer by offsetting his public nonce with a known point ''T = tG'', but not offsetting his secret nonce. +[https://download.wpsoftware.net/bitcoin/wizardry/mw-slides/2018-05-18-l2/slides.pdf Adaptor signatures] can be produced by a signer by offsetting his public nonce with a known point ''T = t⋅G'', but not offsetting his secret nonce. A correct signature (or partial signature, as individual signers' contributions to a multisignature are called) on the same message with same nonce will then be equal to the adaptor signature offset by ''t'', meaning that learning ''t'' is equivalent to learning a correct signature. This can be used to enable atomic swaps or even [https://eprint.iacr.org/2018/472 general payment channels] in which the atomicity of disjoint transactions is ensured using the signatures themselves, rather than Bitcoin script support. The resulting transactions will appear to verifiers to be no different from ordinary single-signer transactions, except perhaps for the inclusion of locktime refund logic. -- cgit v1.2.3 From 3e5a79af88816d1e224c08d82656f24b8a7be5c7 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Fri, 22 Nov 2019 20:35:54 +0000 Subject: Rename is_y_square to is_negated in taproot signing --- bip-taproot.mediawiki | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 1119785..a8106fc 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -68,7 +68,7 @@ The following rules only apply when such an output is being spent. Any other out ** The last stack element is called the control block ''c'', and must have length ''33 + 32m'', for a value of ''m'' that is an integer between 0 and 128'''Why is the Merkle path length limited to 128?''' The optimally space-efficient Merkle tree can be constructed based on the probabilities of the scripts in the leaves, using the Huffman algorithm. This algorithm will construct branches with lengths approximately equal to ''log2(1/probability)'', but to have branches longer than 128 you would need to have scripts with an execution chance below 1 in ''2128''. As that is our security bound, scripts that truly have such a low chance can probably be removed entirely., inclusive. Fail if it does not have such a length. ** Let ''p = c[1:33]'' and let ''P = point(p)'' where ''point'' and ''[:]'' are defined as in bip-schnorr. Fail if this point is not on the curve. ** Let ''l = c[0] & 0xfe'', the leaf version'''What is the purpose of the first byte of the control block?''' The first byte of the control block has three distinct functions: -* The low bit is used to denote whether the ''has_square_y(Q)'' holds.'''Why is the squareness of the output public key's Y coordinate required in a script path spend?''' The ''point'' function always constructs a point with Y coordinate having that property, but because ''Q'' is constructed by adding the taproot tweak to the internal public key ''P'', it cannot easily be guaranteed that ''Q'' in fact has such a Y coordinate. We can not ignore the Y coordinate because it would prevent batch verification. Trying out multiple internal keys until there's such a ''Q'' is possible but undesirable and unnecessary since this information about the Y coordinate only consumes an unused bit. +* The low bit is used to denote whether the point represented by public key ''q'' is negated before verifying the taproot tweak.'''Why is it necessary to reveal a bit to indicate if the point represented by the output public key is negated in a script path spend?''' The ''point'' function (defined in bip-schnorr) always constructs a point with a square Y coordinate, but because ''Q'' is constructed by adding the taproot tweak to the internal public key ''P'', it cannot easily be guaranteed that ''Q'' in fact has such a Y coordinate. Therefore, before verifying the taproot tweak the original point is restored by negating if necessary. We can not ignore the Y coordinate because it would prevent batch verification. Trying out multiple internal keys until there's such a ''Q'' is possible but undesirable and unnecessary since this information about the Y coordinate only consumes an unused bit. * By keeping the top two bits set to true, it can be guaranteed that scripts can be recognized without knowledge of the UTXO being spent, simplifying analysis. This is because such values cannot occur as first byte of the final stack element in either P2WPKH or P2WSH spends. * The remaining five bits are used for introducing new script versions that are not observable unless actually executed. . @@ -180,7 +180,7 @@ Alice will not be able to notice the script path, but Mallory can unilaterally s '''Computing the output script''' Once the spending conditions are split into an internal key internal_pubkey and a binary tree whose leaves are (leaf_version, script) tuples, the output script can be computed using the Python3 algorithms below. These algorithms take advantage of helper functions from the [https://github.com/sipa/bips/blob/bip-schnorr/bip-schnorr/reference.py bip-schnorr reference code] for integer conversion, point multiplication, and tagged hashes. First, we define taproot_tweak_pubkey for 32-byte bip-schnorr public key arrays. -In addition to the tweaked public key byte array, the function returns a boolean for the squareness of the tweaked points' Y coordinate modulo the secp256k1 field order. +In addition to the tweaked public key byte array, the function returns a boolean indicating whether the public key represents the tweaked point or its negation. This will be required for spending the output with a script path. In order to allow spending with the key path, we define taproot_tweak_seckey to compute the secret key for a tweaked public key. For any byte string h it holds that taproot_tweak_pubkey(pubkey_gen(seckey), h)[0] == pubkey_gen(taproot_tweak_seckey(seckey, h)). @@ -191,7 +191,8 @@ def taproot_tweak_pubkey(pubkey, h): if t >= SECP256K1_ORDER: raise ValueError Q = point_add(point(pubkey), point_mul(G, t)) - return bytes_from_int(x(Q)), has_square_y(Q) + is_negated = not has_square_y(Q) + return bytes_from_int(x(Q)), is_negated def taproot_tweak_seckey(seckey0, h): P = point_mul(G, int_from_bytes(seckey0)) @@ -255,8 +256,8 @@ This function returns the witness stack necessary and a sighash fun def taproot_sign_script(internal_pubkey, script_tree, script_num, inputs): info, h = taproot_tree_helper(script_tree) (leaf_version, script), path = info[script_num] - _, is_y_square = taproot_tweak_pubkey(internal_pubkey, h) - output_pubkey_tag = 0 if is_y_square else 1 + _, is_negated = taproot_tweak_pubkey(internal_pubkey, h) + output_pubkey_tag = 0 if is_negated else 1 pubkey_data = bytes([output_pubkey_tag + leaf_version]) + internal_pubkey return inputs + [script, pubkey_data + path] -- cgit v1.2.3 From 79c515eb9e8b2a924c7a7f40be3c4257fa52daff Mon Sep 17 00:00:00 2001 From: stefanwouldgo Date: Tue, 19 Nov 2019 10:10:34 +0100 Subject: grammar typo fix: inserted "be" --- bip-schnorr.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 5e4bd47..bd87974 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -60,7 +60,7 @@ We choose the ''R''-option to support batch verification. To protect against these attacks, we choose ''key prefixed''A limitation of committing to the public key (rather than to a short hash of it, or not at all) is that it removes the ability for public key recovery or verifying signatures against a short public key hash. These constructions are generally incompatible with batch verification. Schnorr signatures; changing the equation to ''s⋅G = R + hash(R || P || m)⋅P''. [https://eprint.iacr.org/2015/1135.pdf It can be shown] that key prefixing protects against related-key attacks with additive tweaks. In general, key prefixing increases robustness in multi-user settings, e.g., it seems to be a requirement for proving the MuSig multisignature scheme secure (see Applications below). -We note that key prefixing is not strictly necessary for transaction signatures as used in Bitcoin currently, because signed transactions indirectly commit to the public keys already, i.e., ''m'' contains a commitment to ''pk''. However, this indirect commitment should not relied upon because it may change with proposals such as SIGHASH_NOINPUT ([https://github.com/bitcoin/bips/blob/master/bip-0118.mediawiki BIP118]), and would render the signature scheme unsuitable for other purposes than signing transactions, e.g., [https://bitcoin.org/en/developer-reference#signmessage signing ordinary messages]. +We note that key prefixing is not strictly necessary for transaction signatures as used in Bitcoin currently, because signed transactions indirectly commit to the public keys already, i.e., ''m'' contains a commitment to ''pk''. However, this indirect commitment should not be relied upon because it may change with proposals such as SIGHASH_NOINPUT ([https://github.com/bitcoin/bips/blob/master/bip-0118.mediawiki BIP118]), and would render the signature scheme unsuitable for other purposes than signing transactions, e.g., [https://bitcoin.org/en/developer-reference#signmessage signing ordinary messages]. '''Encoding R and public key point P''' There exist several possibilities for encoding elliptic curve points: # Encoding the full X and Y coordinates of ''P'' and ''R'', resulting in a 64-byte public key and a 96-byte signature. -- cgit v1.2.3 From 55a31518b9786066d674c985ef0e6d7fcdda7908 Mon Sep 17 00:00:00 2001 From: Orfeas Stefanos Thyfronitis Litos Date: Mon, 25 Nov 2019 12:25:19 +0000 Subject: Rephrase "previous design choice" to "list above" --- bip-schnorr.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index bd87974..c0769b0 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -77,7 +77,7 @@ Using the first option would be slightly more efficient for verification (around In the case of ''R'' the third option is slower at signing time but a bit faster to verify, as it is possible to directly compute whether the Y coordinate is a square when the points are represented in [https://en.wikibooks.org/wiki/Cryptography/Prime_Curve/Jacobian_Coordinates Jacobian coordinates] (a common optimization to avoid modular inverses for elliptic curve operations). The two other options require a possibly -expensive conversion to affine coordinates first. This would even be the case if the sign or oddness were explicitly coded (option 2 in the previous design choice). We therefore choose option 3. +expensive conversion to affine coordinates first. This would even be the case if the sign or oddness were explicitly coded (option 2 in the list above). We therefore choose option 3. For ''P'' the speed of signing and verification does not significantly differ between any of the three options because affine coordinates of the point have to be computed anyway. For consistency reasons we choose the same option as for ''R''. The signing algorithm ensures that the signature is valid under the correct public key by negating the secret key if necessary. -- cgit v1.2.3 From fe03882a72b70640df99e732d14371d89c101fd4 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sat, 23 Nov 2019 21:27:44 +0200 Subject: Fix paragraph naming and typo --- bip-schnorr.mediawiki | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index c0769b0..c71449a 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -49,7 +49,7 @@ encodings and operations. === Design === '''Schnorr signature variant''' Elliptic Curve Schnorr signatures for message ''m'' and public key ''P'' generally involve a point ''R'', integers ''e'' and ''s'' picked by the signer, and the base point ''G'' which satisfy ''e = hash(R || m)'' and ''s⋅G = R + e⋅P''. Two formulations exist, depending on whether the signer reveals ''e'' or ''R'': -# Signatures are ''(e, s)'' that satisfy ''e = hash(s⋅G - e⋅P || m)''. This supports more compact signatures, since [http://www.neven.org/papers/schnorr.pdf the hash ''e'' can be made as small as 16 bytes without sacrificing security], whereas an encoding of ''R'' inherently needs about 32 bytes. Moreover, this variant avoids minor complexity introduced by the encoding of the point ''R'' in the signature (see paragraphs "Encoding the sign of R" and "Implicit Y coordinate" further below in this subsection). +# Signatures are ''(e, s)'' that satisfy ''e = hash(s⋅G - e⋅P || m)''. This supports more compact signatures, since [http://www.neven.org/papers/schnorr.pdf the hash ''e'' can be made as small as 16 bytes without sacrificing security], whereas an encoding of ''R'' inherently needs about 32 bytes. Moreover, this variant avoids minor complexity introduced by the encoding of the point ''R'' in the signature (see paragraphs "Encoding R and public key point P" and "Implicit Y coordinates" further below in this subsection). # Signatures are ''(R, s)'' that satisfy ''s⋅G = R + hash(R || m)⋅P''. This supports batch verification, as there are no elliptic curve operations inside the hashes. Batch verification enables significant speedups. [[File:bip-schnorr/speedup-batch.png|center|frame|This graph shows the ratio between the time it takes to verify ''n'' signatures individually and to verify a batch of ''n'' signatures. This ratio goes up logarithmically with the number of signatures, or in other words: the total time to verify ''n'' signatures grows with ''O(n / log n)''.]] @@ -58,7 +58,7 @@ We choose the ''R''-option to support batch verification. '''Key prefixing''' Using the verification rule above directly makes Schnorr signatures vulnerable to "related-key attacks" in which a third party can convert a signature ''(R, s)'' for public key ''P'' into a signature ''(R, s + a⋅hash(R || m))'' for public key ''P + a⋅G'' and the same message ''m'', for any given additive tweak ''a'' to the signing key. This would render signatures insecure when keys are generated using [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#public-parent-key--public-child-key BIP32's unhardened derivation] and other methods that rely on additive tweaks to existing keys such as Taproot. -To protect against these attacks, we choose ''key prefixed''A limitation of committing to the public key (rather than to a short hash of it, or not at all) is that it removes the ability for public key recovery or verifying signatures against a short public key hash. These constructions are generally incompatible with batch verification. Schnorr signatures; changing the equation to ''s⋅G = R + hash(R || P || m)⋅P''. [https://eprint.iacr.org/2015/1135.pdf It can be shown] that key prefixing protects against related-key attacks with additive tweaks. In general, key prefixing increases robustness in multi-user settings, e.g., it seems to be a requirement for proving the MuSig multisignature scheme secure (see Applications below). +To protect against these attacks, we choose ''key prefixed''A limitation of committing to the public key (rather than to a short hash of it, or not at all) is that it removes the ability for public key recovery or verifying signatures against a short public key hash. These constructions are generally incompatible with batch verification. Schnorr signatures; changing the equation to ''s⋅G = R + hash(R || P || m)⋅P''. [https://eprint.iacr.org/2015/1135.pdf It can be shown] that key prefixing protects against related-key attacks with additive tweaks. In general, key prefixing increases robustness in multi-user settings, e.g., it seems to be a requirement for proving the MuSig multisignature scheme secure (see Applications below). We note that key prefixing is not strictly necessary for transaction signatures as used in Bitcoin currently, because signed transactions indirectly commit to the public keys already, i.e., ''m'' contains a commitment to ''pk''. However, this indirect commitment should not be relied upon because it may change with proposals such as SIGHASH_NOINPUT ([https://github.com/bitcoin/bips/blob/master/bip-0118.mediawiki BIP118]), and would render the signature scheme unsuitable for other purposes than signing transactions, e.g., [https://bitcoin.org/en/developer-reference#signmessage signing ordinary messages]. @@ -111,7 +111,7 @@ The following conventions are used, with constants as defined for [https://www.s ** The function ''int(x)'', where ''x'' is a 32-byte array, returns the 256-bit unsigned integer whose most significant byte first encoding is ''x''. ** The function ''is_square(x)'', where ''x'' is an integer, returns whether or not ''x'' is a quadratic residue modulo ''p''. Since ''p'' is prime, it is equivalent to the Legendre symbol ''(x / p) = x(p-1)/2 mod p'' being equal to ''1'' (see [https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion])For points ''P'' on the secp256k1 curve it holds that ''x(p-1)/2 ≠ 0 mod p''.. ** The function ''has_square_y(P)'', where ''P'' is a point, is defined as ''not is_infinite(P) and is_square(y(P))''For points ''P'' on the secp256k1 curve it holds that ''has_square_y(P) = not has_square_y(-P)''.. -** The function ''lift_x(x)'', where ''x'' is an integer in range ''0..p-1'', returns the point ''P'' for which ''x(P) = x'' and ''has_square_y(P)'', or fails if no such point existsGiven an candidate X coordinate ''x'' in the range ''0..p-1'', there exist either exactly two or exactly zero valid Y coordinates. If no valid Y coordinate exists, then ''x'' is not a valid X coordinate either, i.e., no point ''P'' exists for which ''x(P) = x''. Given a candidate ''x'', the valid Y coordinates are the square roots of ''c = x3 + 7 mod p'' and they can be computed as ''y = ±c(p+1)/4 mod p'' (see [https://en.wikipedia.org/wiki/Quadratic_residue#Prime_or_prime_power_modulus Quadratic residue]) if they exist, which can be checked by squaring and comparing with ''c''. Due to [https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion] it then holds that ''c(p-1)/2 = 1 mod p''. The same criterion applied to ''y'' results in ''y(p-1)/2 mod p = ±c((p+1)/4)((p-1)/2) mod p = ±1 mod p''. Therefore ''y = +c(p+1)/4 mod p'' is a quadratic residue and ''-y mod p'' is not.. The function ''lift_x(x)'' is equivalent to the following pseudocode: +** The function ''lift_x(x)'', where ''x'' is an integer in range ''0..p-1'', returns the point ''P'' for which ''x(P) = x'' and ''has_square_y(P)'', or fails if no such point existsGiven a candidate X coordinate ''x'' in the range ''0..p-1'', there exist either exactly two or exactly zero valid Y coordinates. If no valid Y coordinate exists, then ''x'' is not a valid X coordinate either, i.e., no point ''P'' exists for which ''x(P) = x''. Given a candidate ''x'', the valid Y coordinates are the square roots of ''c = x3 + 7 mod p'' and they can be computed as ''y = ±c(p+1)/4 mod p'' (see [https://en.wikipedia.org/wiki/Quadratic_residue#Prime_or_prime_power_modulus Quadratic residue]) if they exist, which can be checked by squaring and comparing with ''c''. Due to [https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion] it then holds that ''c(p-1)/2 = 1 mod p''. The same criterion applied to ''y'' results in ''y(p-1)/2 mod p = ±c((p+1)/4)((p-1)/2) mod p = ±1 mod p''. Therefore ''y = +c(p+1)/4 mod p'' is a quadratic residue and ''-y mod p'' is not.. The function ''lift_x(x)'' is equivalent to the following pseudocode: *** Let ''c = x3 + 7 mod p''. *** Let ''y = c(p+1)/4 mod p''. *** Fail if ''c ≠ y2 mod p''. @@ -159,7 +159,7 @@ It should be noted that various alternative signing algorithms can be used to pr '''Nonce exfiltration protection''' It is possible to strengthen the nonce generation algorithm using a second device. In this case, the second device contributes randomness which the actual signer provably incorporates into its nonce. This prevents certain attacks where the signer device is compromised and intentionally tries to leak the private key through its nonce selection. -'''Multisignatures''' This signature scheme is compatible with various types of multisignature and threshold schemes such as [https://eprint.iacr.org/2018/068 MuSig], where a single public key requires holders of multiple private keys to participate in signing (see Applications below). +'''Multisignatures''' This signature scheme is compatible with various types of multisignature and threshold schemes such as [https://eprint.iacr.org/2018/068 MuSig], where a single public key requires holders of multiple private keys to participate in signing (see Applications below). '''It is important to note that multisignature signing schemes in general are insecure with the nonce generation from the default signing algorithm above (or any deterministic nonce algorithm).''' ==== Verification ==== -- cgit v1.2.3 From 5235781ea56b0554c667b57daa5338eee8cc7e3c Mon Sep 17 00:00:00 2001 From: andrewtoth Date: Fri, 29 Nov 2019 03:57:00 +0000 Subject: Add missing closing parenthesis and comma --- bip-tapscript.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index c80433d..450e63c 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -127,7 +127,7 @@ In summary, the semantics of the [https://github.com/bitcoin/bips/blob/master/bi In addition to changing the semantics of a number of opcodes, there are also some changes to the resource limitations: * '''Script size limit''' The maximum script size of 10000 bytes does not apply. Their size is only implicitly limited by the limits on transaction and block size.'''Why is a limit on script size no longer needed?''' Since there is no scriptCode directly included in the signature hash (only indirectly through a precomputable tapleaf hash), the CPU time spent on a signature check is no longer proportional to the size of the script being executed. -* '''Non-push opcodes limit''' The maximum non-push opcodes limit of 201 per script does not apply.'''Why is a limit on the number of opcodes no longer needed?''' An opcode limit only helps to the extent that it can prevent data structures from growing unboundedly during execution (both because of memory usage, and because of time that may grow in proportion to the size of those structures. The size of stack and altstack is already independently limited. Using O(1) logic for OP_IF, OP_NOTIF, OP_ELSE, and OP_ENDIF like suggested [https://bitslog.com/2017/04/17/new-quadratic-delays-in-bitcoin-scripts/ here] and implemented [https://github.com/bitcoin/bitcoin/pull/16902 here] the only other instance can be avoided as well. +* '''Non-push opcodes limit''' The maximum non-push opcodes limit of 201 per script does not apply.'''Why is a limit on the number of opcodes no longer needed?''' An opcode limit only helps to the extent that it can prevent data structures from growing unboundedly during execution (both because of memory usage, and because of time that may grow in proportion to the size of those structures). The size of stack and altstack is already independently limited. Using O(1) logic for OP_IF, OP_NOTIF, OP_ELSE, and OP_ENDIF as suggested [https://bitslog.com/2017/04/17/new-quadratic-delays-in-bitcoin-scripts/ here] and implemented [https://github.com/bitcoin/bitcoin/pull/16902 here], the only other instance can be avoided as well. * '''Sigops limit''' The sigops in tapscripts do not count towards the block-wide limit of 80000 (weighted). Instead, there is a per-script sigops ''budget''. The budget equals 50 + the total serialized size in bytes of the transaction input's witness (including the CCompactSize prefix). Executing a signature opcode (OP_CHECKSIG, OP_CHECKSIGVERIFY, or OP_CHECKSIGADD) with a non-empty signature decrements the budget by 50. If that brings the budget below zero, the script fails immediately. Signature opcodes with unknown public key type and non-empty signature are also counted.'''The tapscript sigop limit''' The signature opcode limit protects against scripts which are slow to verify due to excessively many signature operations. In tapscript the number of signature opcodes does not count towards the BIP141 or legacy sigop limit. The old sigop limit makes transaction selection in block construction unnecessarily difficult because it is a second constraint in addition to weight. Instead, the number of tapscript signature opcodes is limited by witness weight. Additionally, the limit applies to the transaction input instead of the block and only actually executed signature opcodes are counted. Tapscript execution allows one signature opcode per 50 witness weight units plus one free signature opcode.'''Parameter choice of the sigop limit''' Regular witnesses are unaffected by the limit as their weight is composed of public key and (SIGHASH_ALL) signature pairs with ''33 + 65'' weight units each (which includes a 1 weight unit CCompactSize tag). This is also the case if public keys are reused in the script because a signature's weight alone is 65 or 66 weight units. However, the limit increases the fees of abnormal scripts with duplicate signatures (and public keys) by requiring additional weight. The weight per sigop factor 50 corresponds to the ratio of BIP141 block limits: 4 mega weight units divided by 80,000 sigops. The "free" signature opcode permitted by the limit exists to account for the weight of the non-witness parts of the transaction input.'''Why are only signature opcodes counted toward the budget, and not for example hashing opcodes or other expensive operations?''' It turns out that the CPU cost per witness byte for verification of a script consisting of the maximum density of signature checking opcodes (taking the 50 WU/sigop limit into account) is already very close to that of scripts packed with other opcodes, including hashing opcodes (taking the 520 byte stack element limit into account) and OP_ROLL (taking the 1000 stack element limit into account). That said, the construction is very flexible, and allows adding new signature opcodes like CHECKSIGFROMSTACK to count towards the limit through a soft fork. Even if in the future new opcodes are introduced which change normal script cost there is no need to stuff the witness with meaningless data. Instead, the taproot annex can be used to add weight to the witness without increasing the actual witness size.. * '''Stack + altstack element count limit''' The existing limit of 1000 elements in the stack and altstack together after every executed opcode remains. It is extended to also apply to the size of initial stack. * '''Stack element size limit''' The existing limit of maximum 520 bytes per stack element remains, both in the initial stack and in push opcodes. -- cgit v1.2.3 From c7175e8005a0eb1022e68f5d96105f0cdccc6def Mon Sep 17 00:00:00 2001 From: andrewtoth Date: Fri, 29 Nov 2019 04:01:53 +0000 Subject: Update bip-tapscript.mediawiki --- bip-tapscript.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index 450e63c..4336f9c 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -127,7 +127,7 @@ In summary, the semantics of the [https://github.com/bitcoin/bips/blob/master/bi In addition to changing the semantics of a number of opcodes, there are also some changes to the resource limitations: * '''Script size limit''' The maximum script size of 10000 bytes does not apply. Their size is only implicitly limited by the limits on transaction and block size.'''Why is a limit on script size no longer needed?''' Since there is no scriptCode directly included in the signature hash (only indirectly through a precomputable tapleaf hash), the CPU time spent on a signature check is no longer proportional to the size of the script being executed. -* '''Non-push opcodes limit''' The maximum non-push opcodes limit of 201 per script does not apply.'''Why is a limit on the number of opcodes no longer needed?''' An opcode limit only helps to the extent that it can prevent data structures from growing unboundedly during execution (both because of memory usage, and because of time that may grow in proportion to the size of those structures). The size of stack and altstack is already independently limited. Using O(1) logic for OP_IF, OP_NOTIF, OP_ELSE, and OP_ENDIF as suggested [https://bitslog.com/2017/04/17/new-quadratic-delays-in-bitcoin-scripts/ here] and implemented [https://github.com/bitcoin/bitcoin/pull/16902 here], the only other instance can be avoided as well. +* '''Non-push opcodes limit''' The maximum non-push opcodes limit of 201 per script does not apply.'''Why is a limit on the number of opcodes no longer needed?''' An opcode limit only helps to the extent that it can prevent data structures from growing unboundedly during execution (both because of memory usage, and because of time that may grow in proportion to the size of those structures). The size of stack and altstack is already independently limited. By using O(1) logic for OP_IF, OP_NOTIF, OP_ELSE, and OP_ENDIF as suggested [https://bitslog.com/2017/04/17/new-quadratic-delays-in-bitcoin-scripts/ here] and implemented [https://github.com/bitcoin/bitcoin/pull/16902 here], the only other instance can be avoided as well. * '''Sigops limit''' The sigops in tapscripts do not count towards the block-wide limit of 80000 (weighted). Instead, there is a per-script sigops ''budget''. The budget equals 50 + the total serialized size in bytes of the transaction input's witness (including the CCompactSize prefix). Executing a signature opcode (OP_CHECKSIG, OP_CHECKSIGVERIFY, or OP_CHECKSIGADD) with a non-empty signature decrements the budget by 50. If that brings the budget below zero, the script fails immediately. Signature opcodes with unknown public key type and non-empty signature are also counted.'''The tapscript sigop limit''' The signature opcode limit protects against scripts which are slow to verify due to excessively many signature operations. In tapscript the number of signature opcodes does not count towards the BIP141 or legacy sigop limit. The old sigop limit makes transaction selection in block construction unnecessarily difficult because it is a second constraint in addition to weight. Instead, the number of tapscript signature opcodes is limited by witness weight. Additionally, the limit applies to the transaction input instead of the block and only actually executed signature opcodes are counted. Tapscript execution allows one signature opcode per 50 witness weight units plus one free signature opcode.'''Parameter choice of the sigop limit''' Regular witnesses are unaffected by the limit as their weight is composed of public key and (SIGHASH_ALL) signature pairs with ''33 + 65'' weight units each (which includes a 1 weight unit CCompactSize tag). This is also the case if public keys are reused in the script because a signature's weight alone is 65 or 66 weight units. However, the limit increases the fees of abnormal scripts with duplicate signatures (and public keys) by requiring additional weight. The weight per sigop factor 50 corresponds to the ratio of BIP141 block limits: 4 mega weight units divided by 80,000 sigops. The "free" signature opcode permitted by the limit exists to account for the weight of the non-witness parts of the transaction input.'''Why are only signature opcodes counted toward the budget, and not for example hashing opcodes or other expensive operations?''' It turns out that the CPU cost per witness byte for verification of a script consisting of the maximum density of signature checking opcodes (taking the 50 WU/sigop limit into account) is already very close to that of scripts packed with other opcodes, including hashing opcodes (taking the 520 byte stack element limit into account) and OP_ROLL (taking the 1000 stack element limit into account). That said, the construction is very flexible, and allows adding new signature opcodes like CHECKSIGFROMSTACK to count towards the limit through a soft fork. Even if in the future new opcodes are introduced which change normal script cost there is no need to stuff the witness with meaningless data. Instead, the taproot annex can be used to add weight to the witness without increasing the actual witness size.. * '''Stack + altstack element count limit''' The existing limit of 1000 elements in the stack and altstack together after every executed opcode remains. It is extended to also apply to the size of initial stack. * '''Stack element size limit''' The existing limit of maximum 520 bytes per stack element remains, both in the initial stack and in push opcodes. -- cgit v1.2.3 From 2aa865c33eeae0859132c0e86b9194ca471fa4aa Mon Sep 17 00:00:00 2001 From: Orfeas Litos Date: Tue, 26 Nov 2019 12:39:34 +0000 Subject: Replace "both are not" with "neither is" --- bip-taproot.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index a8106fc..ea198fc 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -123,7 +123,7 @@ As the message for signature verification, transaction digest is ''hashTapS *** sha_prevouts (32): the SHA256 of the serialization of all input outpoints. *** sha_amounts (32): the SHA256 of the serialization of all input amounts. *** sha_sequences (32): the SHA256 of the serialization of all input nSequence. -** If both the SIGHASH_NONE and SIGHASH_SINGLE flags are not set: +** If neither the SIGHASH_NONE nor the SIGHASH_SINGLE flag is set: *** sha_outputs (32): the SHA256 of the serialization of all outputs in CTxOut format. * Data about this input: ** spend_type (1): -- cgit v1.2.3 From 18d1774d81253453d101c9a7e79e21ab4c96e331 Mon Sep 17 00:00:00 2001 From: Kalle Rosenbaum Date: Mon, 9 Dec 2019 21:20:40 +0100 Subject: Nits --- bip-schnorr.mediawiki | 2 +- bip-taproot.mediawiki | 8 ++++---- bip-tapscript.mediawiki | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index c71449a..0697902 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -36,7 +36,7 @@ made: * '''Signature encoding''': Instead of using [https://en.wikipedia.org/wiki/X.690#DER_encoding DER]-encoding for signatures (which are variable size, and up to 72 bytes), we can use a simple fixed 64-byte format. * '''Public key encoding''': Instead of using ''compressed'' 33-byte encodings of elliptic curve points which are common in Bitcoin today, public keys in this proposal are encoded as 32 bytes. -* '''Batch verification''': The specific formulation of ECDSA signatures that is standardized cannot be verified more efficiently in batch compared to individually, unless additional witness data is added. Changing the signature scheme offers an opportunity to avoid this. +* '''Batch verification''': The specific formulation of ECDSA signatures that is standardized cannot be verified more efficiently in batch compared to individually, unless additional witness data is added. Changing the signature scheme offers an opportunity to address this. By reusing the same curve as Bitcoin uses for ECDSA, we are able to retain existing mechanisms for choosing secret and public keys, and we avoid introducing new assumptions about elliptic curve group security. diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index ea198fc..7f2f443 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -30,7 +30,7 @@ Combining all these ideas in a single proposal would be an extensive change, be ==Design== -This proposal focuses on improvements to privacy, efficiency, and flexibility of Bitcoin's smart contracts, subject to two restrictions: +This proposal focuses on improvements to privacy, efficiency, and flexibility of Bitcoin's scripting capabilities, subject to two restrictions: * Not adding any new strong security assumptions * Not combining into the proposal any functionality which could be simply implemented independently. @@ -39,11 +39,11 @@ Specifically, it seeks to minimize how much information about the spendability c As a result we choose this combination of technologies: * '''Merkle branches''' let us only reveal the actually executed part of the script to the blockchain, as opposed to all possible ways a script can be executed. Among the various known mechanisms for implementing this, one where the Merkle tree becomes part of the script's structure directly maximizes the space savings, so that approach is chosen. * '''Taproot''' on top of that lets us merge the traditionally separate pay-to-pubkey and pay-to-scripthash policies, making all outputs spendable by either a key or (optionally) a script, and indistinguishable from each other. As long as the key-based spending path is used for spending, it is not revealed whether a script path was permitted as well, resulting in space savings and an increase in scripting privacy at spending time. -* Taproot's advantages become apparent under the assumption that most applications involve outputs that could be spent by all parties agreeing. That's where '''Schnorr''' signatures come in, as they permit [https://eprint.iacr.org/2018/068 key aggregation]: a public key can be constructed from multiple participant public keys, and which requires cooperation between all participants to sign for. Such multi-party public keys and signatures are indistinguishable from their single-party equivalents. This means that under this Taproot assumption, the all-parties-agree case can be handled using the key-based spending path, which is both private and efficient using Taproot. This can be generalized to arbitrary M-of-N policies, as Schnorr signatures support threshold signing, at the cost of more complex setup protocols. +* Taproot's advantages become apparent under the assumption that most applications involve outputs that could be spent by all parties agreeing. That's where '''Schnorr''' signatures come in, as they permit [https://eprint.iacr.org/2018/068 key aggregation]: a public key can be constructed from multiple participant public keys, and which requires cooperation between all participants to sign for. Such multi-party public keys and signatures are indistinguishable from their single-party equivalents. This means that the all-parties-agree case can be handled using the key-based spending path, which is efficient and (under the Taproot assumption) private using taproot. This can be generalized to arbitrary M-of-N policies, as Schnorr signatures support threshold signing, at the cost of more complex setup protocols. * As Schnorr signatures also permit '''batch validation''', allowing multiple signatures to be validated together more efficiently than validating each one independently, we make sure all parts of the design are compatible with this. * Where unused bits appear as a result of the above changes, they are reserved for mechanisms for '''future extensions'''. As a result, every script in the Merkle tree has an associated version such that new script versions can be introduced with a soft fork while remaining compatible with bip-taproot. Additionally, future soft forks can make use of the currently unused annex in the witness (see [[#Rationale]]). * While the core semantics of the '''signature hashing algorithm''' are not changed, a number of improvements are included in this proposal. The new signature hashing algorithm fixes the verification capabilities of offline signing devices by including amount and scriptPubKey in the digest, avoids unnecessary hashing, uses '''tagged hashes''' and defines a default sighash byte. -* The '''public key is directly included in the output''' in contrast to typical earlier constructions which store a hash of the public key or script in the output. This has the same cost for senders and is more space efficient overall if the key-based spending path is taken. '''Why is the public key directly included in the output?''' While typical earlier constructions store a hash of a script or a public key in the output, this is rather wasteful when a public key is always involved. To guarantee batch verifiability, ''q'' must be known to every verifier, and thus only revealing its hash as an output would imply adding an additional 32 bytes to the witness. Furthermore, to maintain [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2016-January/012198.html 128-bit collision security] for outputs, a 256-bit hash would be required anyway, which is comparable in size (and thus in cost for senders) to revealing the public key directly. While the usage of public key hashes is often said to protect against ECDLP breaks or quantum computers, this protection is very weak at best: transactions are not protected while being confirmed, and a very [https://twitter.com/pwuille/status/1108097835365339136 large portion] of the currency's supply is not under such protection regardless. Actual resistance to such systems can be introduced by relying on different cryptographic assumptions, but this proposal focuses on improvements that do not change the security model. +* The '''public key is directly included in the output''' in contrast to typical earlier constructions which store a hash of the public key or script in the output. This has the same cost for senders and is more space efficient overall if the key-based spending path is taken. '''Why is the public key directly included in the output?''' While typical earlier constructions store a hash of a script or a public key in the output, this is rather wasteful when a public key is always involved. To guarantee batch verifiability, the public key must be known to every verifier, and thus only revealing its hash as an output would imply adding an additional 32 bytes to the witness. Furthermore, to maintain [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2016-January/012198.html 128-bit collision security] for outputs, a 256-bit hash would be required anyway, which is comparable in size (and thus in cost for senders) to revealing the public key directly. While the usage of public key hashes is often said to protect against ECDLP breaks or quantum computers, this protection is very weak at best: transactions are not protected while being confirmed, and a very [https://twitter.com/pwuille/status/1108097835365339136 large portion] of the currency's supply is not under such protection regardless. Actual resistance to such systems can be introduced by relying on different cryptographic assumptions, but this proposal focuses on improvements that do not change the security model. Not included in this proposal are additional features like new sighash modes or opcodes that can be included with no loss in effectiveness as a future extension. Also not included is cross-input aggregation, as it [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-March/015838.html interacts] in complex ways with upgrade mechanisms and solutions to that are still [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-October/016461.html in flux]. @@ -114,7 +114,7 @@ The following use of hash_type are invalid, and fail execution: As the message for signature verification, transaction digest is ''hashTapSighash'' of the following values (size in byte) serialized. Numerical values in 2, 4, or 8-byte are encoded in little-endian. * Control: -** epoch (1): always 0. '''What's the purpose of the epoch?''' The epoch can be increased to allow securely creating a new transaction digest algorithms with large changes to the structure or interpretation of hash_type if needed. +** epoch (1): always 0. '''What's the purpose of the epoch?''' The epoch can be increased to allow securely creating a new transaction digest algorithm with large changes to the structure or interpretation of hash_type if needed. ** hash_type (1). * Transaction data: ** nVersion (4): the nVersion of the transaction. diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index 4336f9c..a1302ec 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -45,7 +45,7 @@ Additionally, the new tapscript OP_SUCCESS opcodes allow introducin ==Specification== The rules below only apply when validating a transaction input for which all of the conditions below are true: -* The transaction output is a '''segregated witness spend''' (i.e., the scriptPubKey is a witness program as defined in [https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki BIP141]). +* The transaction input is a '''segregated witness spend''' (i.e., the scriptPubKey contains a witness program as defined in [https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki BIP141]). * It is a '''taproot spend''' as defined in bip-taproot (i.e., the witness version is 1, the witness program is 32 bytes, and it is not P2SH wrapped). * It is a '''script path spend''' as defined in bip-taproot (i.e., after removing the optional annex from the witness stack, two or more stack elements remain). * The leaf version is ''0xc0'' (i.e. the first byte of the last witness element after removing the optional annex is ''0xc0'' or ''0xc1'')'''How is the ''0xc0'' constant chosen?''' Following the guidelines in bip-taproot, by choosing a value having the two top bits set, tapscript spends are identifiable even without access to the UTXO being spent., marking it as a '''tapscript spend'''. -- cgit v1.2.3 From 98983e177f20a1c3725eef43f6e21e00f95ac423 Mon Sep 17 00:00:00 2001 From: Kalle Rosenbaum Date: Tue, 10 Dec 2019 22:01:43 +0100 Subject: Fix @jonasnick's comment --- bip-taproot.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 7f2f443..882a377 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -39,7 +39,7 @@ Specifically, it seeks to minimize how much information about the spendability c As a result we choose this combination of technologies: * '''Merkle branches''' let us only reveal the actually executed part of the script to the blockchain, as opposed to all possible ways a script can be executed. Among the various known mechanisms for implementing this, one where the Merkle tree becomes part of the script's structure directly maximizes the space savings, so that approach is chosen. * '''Taproot''' on top of that lets us merge the traditionally separate pay-to-pubkey and pay-to-scripthash policies, making all outputs spendable by either a key or (optionally) a script, and indistinguishable from each other. As long as the key-based spending path is used for spending, it is not revealed whether a script path was permitted as well, resulting in space savings and an increase in scripting privacy at spending time. -* Taproot's advantages become apparent under the assumption that most applications involve outputs that could be spent by all parties agreeing. That's where '''Schnorr''' signatures come in, as they permit [https://eprint.iacr.org/2018/068 key aggregation]: a public key can be constructed from multiple participant public keys, and which requires cooperation between all participants to sign for. Such multi-party public keys and signatures are indistinguishable from their single-party equivalents. This means that the all-parties-agree case can be handled using the key-based spending path, which is efficient and (under the Taproot assumption) private using taproot. This can be generalized to arbitrary M-of-N policies, as Schnorr signatures support threshold signing, at the cost of more complex setup protocols. +* Taproot's advantages become apparent under the assumption that most applications involve outputs that could be spent by all parties agreeing. That's where '''Schnorr''' signatures come in, as they permit [https://eprint.iacr.org/2018/068 key aggregation]: a public key can be constructed from multiple participant public keys, and which requires cooperation between all participants to sign for. Such multi-party public keys and signatures are indistinguishable from their single-party equivalents. This means that with taproot most applications can use the key-based spending path, which is both efficient and private. This can be generalized to arbitrary M-of-N policies, as Schnorr signatures support threshold signing, at the cost of more complex setup protocols. * As Schnorr signatures also permit '''batch validation''', allowing multiple signatures to be validated together more efficiently than validating each one independently, we make sure all parts of the design are compatible with this. * Where unused bits appear as a result of the above changes, they are reserved for mechanisms for '''future extensions'''. As a result, every script in the Merkle tree has an associated version such that new script versions can be introduced with a soft fork while remaining compatible with bip-taproot. Additionally, future soft forks can make use of the currently unused annex in the witness (see [[#Rationale]]). * While the core semantics of the '''signature hashing algorithm''' are not changed, a number of improvements are included in this proposal. The new signature hashing algorithm fixes the verification capabilities of offline signing devices by including amount and scriptPubKey in the digest, avoids unnecessary hashing, uses '''tagged hashes''' and defines a default sighash byte. -- cgit v1.2.3 From 5a25adc4908d1849444821b795a25eb69fdd4f9c Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Fri, 29 Nov 2019 15:42:46 +0000 Subject: Fix bip-schnorr footnote 7 by specifying that we're referring to P's y coordinate and not some undefined 'x' --- bip-schnorr.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 0697902..379bc94 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -109,7 +109,7 @@ The following conventions are used, with constants as defined for [https://www.s ** The function ''bytes(x)'', where ''x'' is an integer, returns the 32-byte encoding of ''x'', most significant byte first. ** The function ''bytes(P)'', where ''P'' is a point, returns ''bytes(x(P))''. ** The function ''int(x)'', where ''x'' is a 32-byte array, returns the 256-bit unsigned integer whose most significant byte first encoding is ''x''. -** The function ''is_square(x)'', where ''x'' is an integer, returns whether or not ''x'' is a quadratic residue modulo ''p''. Since ''p'' is prime, it is equivalent to the Legendre symbol ''(x / p) = x(p-1)/2 mod p'' being equal to ''1'' (see [https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion])For points ''P'' on the secp256k1 curve it holds that ''x(p-1)/2 ≠ 0 mod p''.. +** The function ''is_square(x)'', where ''x'' is an integer, returns whether or not ''x'' is a quadratic residue modulo ''p''. Since ''p'' is prime, it is equivalent to the Legendre symbol ''(x / p) = x(p-1)/2 mod p'' being equal to ''1'' (see [https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion])For points ''P'' on the secp256k1 curve it holds that ''y(P)(p-1)/2 ≠ 0 mod p''.. ** The function ''has_square_y(P)'', where ''P'' is a point, is defined as ''not is_infinite(P) and is_square(y(P))''For points ''P'' on the secp256k1 curve it holds that ''has_square_y(P) = not has_square_y(-P)''.. ** The function ''lift_x(x)'', where ''x'' is an integer in range ''0..p-1'', returns the point ''P'' for which ''x(P) = x'' and ''has_square_y(P)'', or fails if no such point existsGiven a candidate X coordinate ''x'' in the range ''0..p-1'', there exist either exactly two or exactly zero valid Y coordinates. If no valid Y coordinate exists, then ''x'' is not a valid X coordinate either, i.e., no point ''P'' exists for which ''x(P) = x''. Given a candidate ''x'', the valid Y coordinates are the square roots of ''c = x3 + 7 mod p'' and they can be computed as ''y = ±c(p+1)/4 mod p'' (see [https://en.wikipedia.org/wiki/Quadratic_residue#Prime_or_prime_power_modulus Quadratic residue]) if they exist, which can be checked by squaring and comparing with ''c''. Due to [https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion] it then holds that ''c(p-1)/2 = 1 mod p''. The same criterion applied to ''y'' results in ''y(p-1)/2 mod p = ±c((p+1)/4)((p-1)/2) mod p = ±1 mod p''. Therefore ''y = +c(p+1)/4 mod p'' is a quadratic residue and ''-y mod p'' is not.. The function ''lift_x(x)'' is equivalent to the following pseudocode: *** Let ''c = x3 + 7 mod p''. -- cgit v1.2.3 From 708aeadf85e983c85dac95ec4e0932cacac8a79d Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Fri, 29 Nov 2019 15:47:33 +0000 Subject: Replace references to Euler's criterion with Legendre symbol in bip-schnorr --- bip-schnorr.mediawiki | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 379bc94..ce5abde 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -109,9 +109,9 @@ The following conventions are used, with constants as defined for [https://www.s ** The function ''bytes(x)'', where ''x'' is an integer, returns the 32-byte encoding of ''x'', most significant byte first. ** The function ''bytes(P)'', where ''P'' is a point, returns ''bytes(x(P))''. ** The function ''int(x)'', where ''x'' is a 32-byte array, returns the 256-bit unsigned integer whose most significant byte first encoding is ''x''. -** The function ''is_square(x)'', where ''x'' is an integer, returns whether or not ''x'' is a quadratic residue modulo ''p''. Since ''p'' is prime, it is equivalent to the Legendre symbol ''(x / p) = x(p-1)/2 mod p'' being equal to ''1'' (see [https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion])For points ''P'' on the secp256k1 curve it holds that ''y(P)(p-1)/2 ≠ 0 mod p''.. +** The function ''is_square(x)'', where ''x'' is an integer, returns whether or not ''x'' is a quadratic residue modulo ''p''. Since ''p'' is prime, it is equivalent to the [https://en.wikipedia.org/wiki/Legendre_symbol Legendre symbol] ''(x / p) = x(p-1)/2 mod p'' being equal to ''1''For points ''P'' on the secp256k1 curve it holds that ''y(P)(p-1)/2 ≠ 0 mod p''.. ** The function ''has_square_y(P)'', where ''P'' is a point, is defined as ''not is_infinite(P) and is_square(y(P))''For points ''P'' on the secp256k1 curve it holds that ''has_square_y(P) = not has_square_y(-P)''.. -** The function ''lift_x(x)'', where ''x'' is an integer in range ''0..p-1'', returns the point ''P'' for which ''x(P) = x'' and ''has_square_y(P)'', or fails if no such point existsGiven a candidate X coordinate ''x'' in the range ''0..p-1'', there exist either exactly two or exactly zero valid Y coordinates. If no valid Y coordinate exists, then ''x'' is not a valid X coordinate either, i.e., no point ''P'' exists for which ''x(P) = x''. Given a candidate ''x'', the valid Y coordinates are the square roots of ''c = x3 + 7 mod p'' and they can be computed as ''y = ±c(p+1)/4 mod p'' (see [https://en.wikipedia.org/wiki/Quadratic_residue#Prime_or_prime_power_modulus Quadratic residue]) if they exist, which can be checked by squaring and comparing with ''c''. Due to [https://en.wikipedia.org/wiki/Euler%27s_criterion Euler's criterion] it then holds that ''c(p-1)/2 = 1 mod p''. The same criterion applied to ''y'' results in ''y(p-1)/2 mod p = ±c((p+1)/4)((p-1)/2) mod p = ±1 mod p''. Therefore ''y = +c(p+1)/4 mod p'' is a quadratic residue and ''-y mod p'' is not.. The function ''lift_x(x)'' is equivalent to the following pseudocode: +** The function ''lift_x(x)'', where ''x'' is an integer in range ''0..p-1'', returns the point ''P'' for which ''x(P) = x'' and ''has_square_y(P)'', or fails if no such point existsGiven a candidate X coordinate ''x'' in the range ''0..p-1'', there exist either exactly two or exactly zero valid Y coordinates. If no valid Y coordinate exists, then ''x'' is not a valid X coordinate either, i.e., no point ''P'' exists for which ''x(P) = x''. Given a candidate ''x'', the valid Y coordinates are the square roots of ''c = x3 + 7 mod p'' and they can be computed as ''y = ±c(p+1)/4 mod p'' (see [https://en.wikipedia.org/wiki/Quadratic_residue#Prime_or_prime_power_modulus Quadratic residue]) if they exist, which can be checked by squaring and comparing with ''c''. The [https://en.wikipedia.org/wiki/Legendre_symbol Legendre symbol] ''( c / p)'' is ''c(p-1)/2 = 1 mod p''. The Legendre symbol ''( y / p )'' is ''y(p-1)/2 mod p = ±c((p+1)/4)((p-1)/2) mod p = ±1 mod p''. Therefore ''y = +c(p+1)/4 mod p'' is a quadratic residue and ''-y mod p'' is not.. The function ''lift_x(x)'' is equivalent to the following pseudocode: *** Let ''c = x3 + 7 mod p''. *** Let ''y = c(p+1)/4 mod p''. *** Fail if ''c ≠ y2 mod p''. -- cgit v1.2.3 From 1f5bdb304e1fb76618926d3ae84970c7555d0d14 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Wed, 4 Dec 2019 19:26:06 +0000 Subject: Improve clarity of footnotes for lift_x --- bip-schnorr.mediawiki | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index ce5abde..1b89d51 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -72,7 +72,7 @@ Using the first option would be slightly more efficient for verification (around '''Implicit Y coordinates''' In order to support efficient verification and batch verification, the Y coordinate of ''P'' and of ''R'' cannot be ambiguous (every valid X coordinate has two possible Y coordinates). We have a choice between several options for symmetry breaking: # Implicitly choosing the Y coordinate that is in the lower half. # Implicitly choosing the Y coordinate that is evenSince ''p'' is odd, negation modulo ''p'' will map even numbers to odd numbers and the other way around. This means that for a valid X coordinate, one of the corresponding Y coordinates will be even, and the other will be odd.. -# Implicitly choosing the Y coordinate that is a quadratic residue (has a square root modulo the field size, or "is a square" for short)A product of two numbers is a square when either both or none of the factors are squares. As ''-1'' is not a square, and the two Y coordinates corresponding to a given X coordinate are each other's negation, this means exactly one of the two must be a square.. +# Implicitly choosing the Y coordinate that is a quadratic residue (has a square root modulo the field size, or "is a square" for short)A product of two numbers is a square when either both or none of the factors are squares. As ''-1'' is not a square modulo secp256k1's field size ''p'', and the two Y coordinates corresponding to a given X coordinate are each other's negation, this means exactly one of the two must be a square.. In the case of ''R'' the third option is slower at signing time but a bit faster to verify, as it is possible to directly compute whether the Y coordinate is a square when the points are represented in [https://en.wikibooks.org/wiki/Cryptography/Prime_Curve/Jacobian_Coordinates Jacobian coordinates] (a common optimization to avoid modular inverses @@ -111,7 +111,11 @@ The following conventions are used, with constants as defined for [https://www.s ** The function ''int(x)'', where ''x'' is a 32-byte array, returns the 256-bit unsigned integer whose most significant byte first encoding is ''x''. ** The function ''is_square(x)'', where ''x'' is an integer, returns whether or not ''x'' is a quadratic residue modulo ''p''. Since ''p'' is prime, it is equivalent to the [https://en.wikipedia.org/wiki/Legendre_symbol Legendre symbol] ''(x / p) = x(p-1)/2 mod p'' being equal to ''1''For points ''P'' on the secp256k1 curve it holds that ''y(P)(p-1)/2 ≠ 0 mod p''.. ** The function ''has_square_y(P)'', where ''P'' is a point, is defined as ''not is_infinite(P) and is_square(y(P))''For points ''P'' on the secp256k1 curve it holds that ''has_square_y(P) = not has_square_y(-P)''.. -** The function ''lift_x(x)'', where ''x'' is an integer in range ''0..p-1'', returns the point ''P'' for which ''x(P) = x'' and ''has_square_y(P)'', or fails if no such point existsGiven a candidate X coordinate ''x'' in the range ''0..p-1'', there exist either exactly two or exactly zero valid Y coordinates. If no valid Y coordinate exists, then ''x'' is not a valid X coordinate either, i.e., no point ''P'' exists for which ''x(P) = x''. Given a candidate ''x'', the valid Y coordinates are the square roots of ''c = x3 + 7 mod p'' and they can be computed as ''y = ±c(p+1)/4 mod p'' (see [https://en.wikipedia.org/wiki/Quadratic_residue#Prime_or_prime_power_modulus Quadratic residue]) if they exist, which can be checked by squaring and comparing with ''c''. The [https://en.wikipedia.org/wiki/Legendre_symbol Legendre symbol] ''( c / p)'' is ''c(p-1)/2 = 1 mod p''. The Legendre symbol ''( y / p )'' is ''y(p-1)/2 mod p = ±c((p+1)/4)((p-1)/2) mod p = ±1 mod p''. Therefore ''y = +c(p+1)/4 mod p'' is a quadratic residue and ''-y mod p'' is not.. The function ''lift_x(x)'' is equivalent to the following pseudocode: +** The function ''lift_x(x)'', where ''x'' is an integer in range ''0..p-1'', returns the point ''P'' for which ''x(P) = x'' + Given a candidate X coordinate ''x'' in the range ''0..p-1'', there exist either exactly two or exactly zero valid Y coordinates. If no valid Y coordinate exists, then ''x'' is not a valid X coordinate either, i.e., no point ''P'' exists for which ''x(P) = x''. The valid Y coordinates for a given candidate ''x'' are the square roots of ''c = x3 + 7 mod p'' and they can be computed as ''y = ±c(p+1)/4 mod p'' (see [https://en.wikipedia.org/wiki/Quadratic_residue#Prime_or_prime_power_modulus Quadratic residue]) if they exist, which can be checked by squaring and comparing with ''c''. + and ''has_square_y(P)'' + If ''P := lift_x(x)'' does not fail, then ''y := y(P) = c(p+1)/4 mod p'' is square. Proof: If ''lift_x'' does not fail, ''y'' is a square root of ''c'' and therefore the [https://en.wikipedia.org/wiki/Legendre_symbol Legendre symbol] ''(c / p)'' is ''c(p-1)/2 = 1 mod p''. Because the Legendre symbol ''(y / p)'' is ''y(p-1)/2 mod p = c((p+1)/4)((p-1)/2) mod p = 1((p+1)/4) mod p = 1 mod p'', ''y'' is square. +, or fails if no such point exists. The function ''lift_x(x)'' is equivalent to the following pseudocode: *** Let ''c = x3 + 7 mod p''. *** Let ''y = c(p+1)/4 mod p''. *** Fail if ''c ≠ y2 mod p''. -- cgit v1.2.3 From 66e2931de2f5779847cc47cf9f430908474cf4e6 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Fri, 29 Nov 2019 16:32:44 +0000 Subject: Clarify bip-taproot digest difference to bip143 regarding sub-hashes --- bip-taproot.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 882a377..491dd4b 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -145,7 +145,7 @@ As the message for signature verification, transaction digest is ''hashTapS The total number of bytes hashed is at most ''211'' (excluding sub-hashes such as `sha_prevouts`)'''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''178 - is_anyonecanpay * 52 - is_none * 32 + has_annex * 32''.. Sub-hashes may be cached across signatures of the same transaction. In summary, the semantics of the [https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki BIP143] sighash types remain unchanged, except the following: -# The way and order of serialization is changed.'''Why is the serialization in the transaction digest changed?''' Hashes that go into the digest and the digest itself are now computed with a single SHA256 invocation instead of double SHA256. There is no expected security improvement by doubling SHA256 because this only protects against length-extension attacks against SHA256 which are not a concern for transaction digests because there is no secret data. Therefore doubling SHA256 is a waste of resources. The digest computation now follows a logical order with transaction level data first, then input data and output data. This allows to efficiently cache the transaction part of the digest across different inputs using the SHA256 midstate. Additionally, digest computation avoids unnecessary hashing as opposed to BIP143 digests in which parts may be set zero and before hashing them. Despite that, collisions are made impossible by committing to the length of the data (implicit in hash_type and spend_type) before the variable length data. +# The way and order of serialization is changed.'''Why is the serialization in the transaction digest changed?''' Hashes that go into the digest and the digest itself are now computed with a single SHA256 invocation instead of double SHA256. There is no expected security improvement by doubling SHA256 because this only protects against length-extension attacks against SHA256 which are not a concern for transaction digests because there is no secret data. Therefore doubling SHA256 is a waste of resources. The digest computation now follows a logical order with transaction level data first, then input data and output data. This allows to efficiently cache the transaction part of the digest across different inputs using the SHA256 midstate. Additionally, sub-hashes can be skipped when calculating the digest (for example `sha_prevouts` if SIGHASH_ANYONECANPAY is set) instead of setting them to zero and then hashing them as in BIP143. Despite that, collisions are made impossible by committing to the length of the data (implicit in hash_type and spend_type) before the variable length data. # The digest commits to the scriptPubKey'''Why does the transaction digest commit to the scriptPubKey?''' This prevents lying to offline signing devices about output being spent, even when the actually executed script (scriptCode in BIP143) is correct. This means it's possible to compactly prove to a hardware wallet what (unused) execution paths existed.. # If the SIGHASH_ANYONECANPAY flag is not set, the digest commits to the amounts of ''all'' transaction inputs.'''Why does the transaction digest commit to the amounts of all transaction inputs?''' This eliminates the possibility to lie to offline signing devices about the fee of a transaction. # The digest commits to all input nSequence if SIGHASH_NONE or SIGHASH_SINGLE are set (unless SIGHASH_ANYONECANPAY is set as well).'''Why does the transaction digest commit to all input nSequence if SIGHASH_SINGLE or SIGHASH_NONE are set?''' Because setting them already makes the digest commit to the prevouts part of all transaction inputs, it is not useful to treat the nSequence any different. Moreover, this change makes nSequence consistent with the view that SIGHASH_SINGLE and SIGHASH_NONE only modify the digest with respect to transaction outputs and not inputs. -- cgit v1.2.3 From 5918b4666c4c4fbf54a2ef8550877f02328a2afc Mon Sep 17 00:00:00 2001 From: Orfeas Litos Date: Tue, 26 Nov 2019 12:43:34 +0000 Subject: Mention hash_type malleability would change wtxid --- bip-taproot.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 491dd4b..dc59c51 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -93,7 +93,7 @@ The following rules apply: * If the signature is not 64'''Why permit two signature lengths?''' By making the most common type of hash_type implicit, a byte can often be saved. or 65 bytes, fail. * If the signature size is 65 bytes: ** If the final byte is not a valid hash_type (defined hereinafter), fail. -** If the final byte is 0x00, fail'''Why can the hash_type not be 0x00 in 65-byte signatures?''' Permitting that would enable malleating 64-byte signatures into 65-byte ones, resulting a different fee rate than the creator intended. +** If the final byte is 0x00, fail'''Why can the hash_type not be 0x00 in 65-byte signatures?''' Permitting that would enable malleating 64-byte signatures into 65-byte ones, resulting in a different `wtxid` and a different fee rate than the creator intended. ** If the first 64 bytes are not a valid signature according to bip-schnorr for the public key and message set to the transaction digest with hash_type set as the final byte, fail. * If the signature size is 64 bytes: ** If it is not a valid signature according to bip-schnorr for the public key and the hash_type = 0x00 transaction digest as message, fail. -- cgit v1.2.3 From ca472ed663d32039448560b36ecf1e6467ba4347 Mon Sep 17 00:00:00 2001 From: Orfeas Stefanos Thyfronitis Litos Date: Tue, 26 Nov 2019 15:30:12 +0000 Subject: Mention that miners could malleate signatures --- bip-taproot.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index dc59c51..ba8d048 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -93,7 +93,7 @@ The following rules apply: * If the signature is not 64'''Why permit two signature lengths?''' By making the most common type of hash_type implicit, a byte can often be saved. or 65 bytes, fail. * If the signature size is 65 bytes: ** If the final byte is not a valid hash_type (defined hereinafter), fail. -** If the final byte is 0x00, fail'''Why can the hash_type not be 0x00 in 65-byte signatures?''' Permitting that would enable malleating 64-byte signatures into 65-byte ones, resulting in a different `wtxid` and a different fee rate than the creator intended. +** If the final byte is 0x00, fail'''Why can the hash_type not be 0x00 in 65-byte signatures?''' Permitting that would enable malleating (by third parties, including miners) 64-byte signatures into 65-byte ones, resulting in a different `wtxid` and a different fee rate than the creator intended. ** If the first 64 bytes are not a valid signature according to bip-schnorr for the public key and message set to the transaction digest with hash_type set as the final byte, fail. * If the signature size is 64 bytes: ** If it is not a valid signature according to bip-schnorr for the public key and the hash_type = 0x00 transaction digest as message, fail. -- cgit v1.2.3 From 79738f2410c8f263265d9dc4d7602dc8dea84713 Mon Sep 17 00:00:00 2001 From: Orfeas Stefanos Thyfronitis Litos Date: Mon, 18 Nov 2019 16:46:10 +0000 Subject: Link to proof sketch of security of implicit Y Thanks to @ajtowns for providing the link --- bip-schnorr.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 1b89d51..3925f07 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -81,7 +81,7 @@ expensive conversion to affine coordinates first. This would even be the case if For ''P'' the speed of signing and verification does not significantly differ between any of the three options because affine coordinates of the point have to be computed anyway. For consistency reasons we choose the same option as for ''R''. The signing algorithm ensures that the signature is valid under the correct public key by negating the secret key if necessary. -Implicit Y coordinates are not a reduction in security when expressed as the number of elliptic curve operations an attacker is expected to perform to compute the secret key. An attacker can normalize any given public key to a point whose Y coordinate is a square by negating the point if necessary. This is just a subtraction of field elements and not an elliptic curve operationThis can be formalized by a simple reduction that reduces an attack on Schnorr signatures with implicit Y coordinates to an attack to Schnorr signatures with explicit Y coordinates. The reduction works by reencoding public keys and negating the result of the hash function, which is modeled as random oracle, whenever the challenge public key has an explicit Y coordinate that is not a square.. +Implicit Y coordinates are not a reduction in security when expressed as the number of elliptic curve operations an attacker is expected to perform to compute the secret key. An attacker can normalize any given public key to a point whose Y coordinate is a square by negating the point if necessary. This is just a subtraction of field elements and not an elliptic curve operationThis can be formalized by a simple reduction that reduces an attack on Schnorr signatures with implicit Y coordinates to an attack to Schnorr signatures with explicit Y coordinates. The reduction works by reencoding public keys and negating the result of the hash function, which is modeled as random oracle, whenever the challenge public key has an explicit Y coordinate that is not a square. A proof sketch can be found [here](https://medium.com/blockstream/reducing-bitcoin-transaction-sizes-with-x-only-pubkeys-f86476af05d7). '''Tagged Hashes''' Cryptographic hash functions are used for multiple purposes in the specification below and in Bitcoin in general. To make sure hashes used in one context can't be reinterpreted in another one, hash functions can be tweaked with a context-dependent tag name, in such a way that collisions across contexts can be assumed to be infeasible. Such collisions obviously can not be ruled out completely, but only for schemes using tagging with a unique name. As for other schemes collisions are at least less likely with tagging than without. -- cgit v1.2.3 From a65101ff6d803feb582c8f21788fe5341cbff07d Mon Sep 17 00:00:00 2001 From: Orfeas Stefanos Thyfronitis Litos Date: Mon, 25 Nov 2019 16:43:05 +0000 Subject: Replace signing with signature before validation --- bip-tapscript.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index a1302ec..4146f24 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -89,7 +89,7 @@ The following rules apply to OP_CHECKSIG, OP_CHECKSIGVERIFYn is larger than 4 bytes, the script MUST fail and terminate immediately. * If the public key size is zero, the script MUST fail and terminate immediately. * If the public key size is 32 bytes, it is considered to be a public key as described in bip-schnorr: -** If the signature is not the empty vector, the signature is validated according to the bip-taproot signing validation rules against the public key and the tapscript transaction digest (to be defined hereinafter) as message. Validation failure MUST cause the script to fail and terminate immediately. +** If the signature is not the empty vector, the signature is validated according to the bip-taproot signature validation rules against the public key and the tapscript transaction digest (to be defined hereinafter) as message. Validation failure MUST cause the script to fail and terminate immediately. * If the public key size is not zero and not 32 bytes, the public key is of an ''unknown public key type'''''Unknown public key types''' allow adding new signature validation rules through softforks. A softfork could add actual signature validation which either passes or makes the script fail and terminate immediately. This way, new SIGHASH modes can be added, as well as [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-December/016549.html NOINPUT-tagged public keys] and a public key constant which is replaced by the taproot internal key for signature validation. and no actual signature verification is applied. During script execution of signature opcodes they behave exactly as known public key types except that signature validation is considered to be successful. * If the script did not fail and terminate before this step, regardless of the public key type: ** If the signature is the empty vector: -- cgit v1.2.3 From 8baf6f5952d4a1fe1020de075ab93179e6236a55 Mon Sep 17 00:00:00 2001 From: stefanwouldgo Date: Thu, 28 Nov 2019 13:41:28 +0100 Subject: fix singular/plural ambiguity --- bip-taproot.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index ba8d048..d3e2222 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -114,7 +114,7 @@ The following use of hash_type are invalid, and fail execution: As the message for signature verification, transaction digest is ''hashTapSighash'' of the following values (size in byte) serialized. Numerical values in 2, 4, or 8-byte are encoded in little-endian. * Control: -** epoch (1): always 0. '''What's the purpose of the epoch?''' The epoch can be increased to allow securely creating a new transaction digest algorithm with large changes to the structure or interpretation of hash_type if needed. +** epoch (1): always 0. '''What's the purpose of the epoch?''' The epoch can be increased to allow securely creating new transaction digest algorithms with large changes to the structure or interpretation of hash_type if needed. ** hash_type (1). * Transaction data: ** nVersion (4): the nVersion of the transaction. -- cgit v1.2.3 From 37bf225ea458cdfb289315958a1b3d225bdab6b3 Mon Sep 17 00:00:00 2001 From: Orfeas Stefanos Thyfronitis Litos Date: Fri, 22 Nov 2019 11:41:36 +0000 Subject: Replace BIP66 link with BIP146 BIP66 does not mention the inherent ECDSA malleability, but BIP146 does --- bip-schnorr.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 3925f07..1f53de7 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -26,7 +26,7 @@ transactions. These are [https://www.secg.org/sec1-v2.pdf standardized], but hav compared to [http://publikationen.ub.uni-frankfurt.de/opus4/files/4280/schnorr.pdf Schnorr signatures] over the same curve: * '''Provable security''': Schnorr signatures are provably secure. In more detail, they are ''strongly unforgeable under chosen message attack (SUF-CMA)''Informally, this means that without knowledge of the secret key but given valid signatures of arbitrary messages, it is not possible to come up with further valid signatures. [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf in the random oracle model assuming the hardness of the elliptic curve discrete logarithm problem (ECDLP)] and [http://www.neven.org/papers/schnorr.pdf in the generic group model assuming variants of preimage and second preimage resistance of the used hash function]A detailed security proof in the random oracle model, which essentially restates [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf the original security proof by Pointcheval and Stern] more explicitly, can be found in [https://eprint.iacr.org/2016/191 a paper by Kiltz, Masny and Pan]. All these security proofs assume a variant of Schnorr signatures that use ''(e,s)'' instead of ''(R,s)'' (see Design above). Since we use a unique encoding of ''R'', there is an efficiently computable bijection that maps ''(R,s)'' to ''(e,s)'', which allows to convert a successful SUF-CMA attacker for the ''(e,s)'' variant to a successful SUF-CMA attacker for the ''(R,s)'' variant (and vice-versa). Furthermore, the proofs consider a variant of Schnorr signatures without key prefixing (see Design above), but it can be verified that the proofs are also correct for the variant with key prefixing. As a result, all the aforementioned security proofs apply to the variant of Schnorr signatures proposed in this document.. In contrast, the [https://nbn-resolving.de/urn:nbn:de:hbz:294-60803 best known results for the provable security of ECDSA] rely on stronger assumptions. -* '''Non-malleability''': The SUF-CMA security of Schnorr signatures implies that they are non-malleable. On the other hand, ECDSA signatures are inherently malleable; a third party without access to the secret key can alter an existing valid signature for a given public key and message into another signature that is valid for the same key and message. This issue is discussed in [https://github.com/bitcoin/bips/blob/master/bip-0062.mediawiki BIP62] and [https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki BIP66]. +* '''Non-malleability''': The SUF-CMA security of Schnorr signatures implies that they are non-malleable. On the other hand, ECDSA signatures are inherently malleable; a third party without access to the secret key can alter an existing valid signature for a given public key and message into another signature that is valid for the same key and message. This issue is discussed in [https://github.com/bitcoin/bips/blob/master/bip-0062.mediawiki BIP62] and [https://github.com/bitcoin/bips/blob/master/bip-0146.mediawiki BIP146]. * '''Linearity''': Schnorr signatures have the remarkable property that multiple parties can collaborate to produce a signature that is valid for the sum of their public keys. This is the building block for various higher-level constructions that improve efficiency and privacy, such as multisignatures and others (see Applications below). For all these advantages, there are virtually no disadvantages, apart -- cgit v1.2.3 From da3837639fd987e5d25a0abb209700c3d7ff55ed Mon Sep 17 00:00:00 2001 From: Orfeas Stefanos Thyfronitis Litos Date: Mon, 25 Nov 2019 16:25:24 +0000 Subject: Typo: max bytes hashed for sig is 210 --- bip-taproot.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index d3e2222..0fa4194 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -142,7 +142,7 @@ As the message for signature verification, transaction digest is ''hashTapS ** If the SIGHASH_SINGLE flag is set: *** sha_single_output (32): the SHA256 of the corresponding output in CTxOut format. -The total number of bytes hashed is at most ''211'' (excluding sub-hashes such as `sha_prevouts`)'''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''178 - is_anyonecanpay * 52 - is_none * 32 + has_annex * 32''.. Sub-hashes may be cached across signatures of the same transaction. +The total number of bytes hashed is at most ''210'' (excluding sub-hashes such as `sha_prevouts`)'''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''178 - is_anyonecanpay * 52 - is_none * 32 + has_annex * 32''.. Sub-hashes may be cached across signatures of the same transaction. In summary, the semantics of the [https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki BIP143] sighash types remain unchanged, except the following: # The way and order of serialization is changed.'''Why is the serialization in the transaction digest changed?''' Hashes that go into the digest and the digest itself are now computed with a single SHA256 invocation instead of double SHA256. There is no expected security improvement by doubling SHA256 because this only protects against length-extension attacks against SHA256 which are not a concern for transaction digests because there is no secret data. Therefore doubling SHA256 is a waste of resources. The digest computation now follows a logical order with transaction level data first, then input data and output data. This allows to efficiently cache the transaction part of the digest across different inputs using the SHA256 midstate. Additionally, sub-hashes can be skipped when calculating the digest (for example `sha_prevouts` if SIGHASH_ANYONECANPAY is set) instead of setting them to zero and then hashing them as in BIP143. Despite that, collisions are made impossible by committing to the length of the data (implicit in hash_type and spend_type) before the variable length data. -- cgit v1.2.3 From 773133fb4a086c41256d505d744d2764597bd222 Mon Sep 17 00:00:00 2001 From: Orfeas Stefanos Thyfronitis Litos Date: Mon, 25 Nov 2019 16:50:11 +0000 Subject: Typo: script signature max bytes unhashed are 247 --- bip-tapscript.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index 4146f24..50f9d5e 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -115,7 +115,7 @@ As additional pieces of data, added at the end of the input to the ''hashTa * key_version (1): a constant value 0x00 representing the current version of public keys in the tapscript signature opcode execution. * codeseparator_position (4): the opcode position of the last executed OP_CODESEPARATOR before the currently executed signature opcode, with the value in little endian (or 0xffffffff if none executed). The first opcode in a script has a position of 0. A multi-byte push opcode is counted as one opcode, regardless of the size of data being pushed. -The total number of bytes hashed is at most ''248'''''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''215 - is_anyonecanpay * 52 - is_none * 32 + has_annex * 32''.. +The total number of bytes hashed is at most ''247'''''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''215 - is_anyonecanpay * 52 - is_none * 32 + has_annex * 32''.. In summary, the semantics of the [https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki BIP143] sighash types remain unchanged, except the following: # The exceptions mentioned in bip-taproot. -- cgit v1.2.3 From 966eadca3a8f5ea118ca98e45cf37f165b399f0a Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Wed, 11 Dec 2019 15:33:39 +0200 Subject: Fix reference formatting --- bip-schnorr.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 1f53de7..4cfe6b4 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -81,7 +81,7 @@ expensive conversion to affine coordinates first. This would even be the case if For ''P'' the speed of signing and verification does not significantly differ between any of the three options because affine coordinates of the point have to be computed anyway. For consistency reasons we choose the same option as for ''R''. The signing algorithm ensures that the signature is valid under the correct public key by negating the secret key if necessary. -Implicit Y coordinates are not a reduction in security when expressed as the number of elliptic curve operations an attacker is expected to perform to compute the secret key. An attacker can normalize any given public key to a point whose Y coordinate is a square by negating the point if necessary. This is just a subtraction of field elements and not an elliptic curve operationThis can be formalized by a simple reduction that reduces an attack on Schnorr signatures with implicit Y coordinates to an attack to Schnorr signatures with explicit Y coordinates. The reduction works by reencoding public keys and negating the result of the hash function, which is modeled as random oracle, whenever the challenge public key has an explicit Y coordinate that is not a square. A proof sketch can be found [here](https://medium.com/blockstream/reducing-bitcoin-transaction-sizes-with-x-only-pubkeys-f86476af05d7). +Implicit Y coordinates are not a reduction in security when expressed as the number of elliptic curve operations an attacker is expected to perform to compute the secret key. An attacker can normalize any given public key to a point whose Y coordinate is a square by negating the point if necessary. This is just a subtraction of field elements and not an elliptic curve operationThis can be formalized by a simple reduction that reduces an attack on Schnorr signatures with implicit Y coordinates to an attack to Schnorr signatures with explicit Y coordinates. The reduction works by reencoding public keys and negating the result of the hash function, which is modeled as random oracle, whenever the challenge public key has an explicit Y coordinate that is not a square. A proof sketch can be found [https://medium.com/blockstream/reducing-bitcoin-transaction-sizes-with-x-only-pubkeys-f86476af05d7 here].. '''Tagged Hashes''' Cryptographic hash functions are used for multiple purposes in the specification below and in Bitcoin in general. To make sure hashes used in one context can't be reinterpreted in another one, hash functions can be tweaked with a context-dependent tag name, in such a way that collisions across contexts can be assumed to be infeasible. Such collisions obviously can not be ruled out completely, but only for schemes using tagging with a unique name. As for other schemes collisions are at least less likely with tagging than without. -- cgit v1.2.3 From ad6bb6c1ff5a88b0f91f9363964cf39581d650ad Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Thu, 12 Dec 2019 22:49:21 +0100 Subject: Clarify why we don't want short hashes This is supposed to supersede https://github.com/sipa/bips/pull/158. I tried to say this carefully. I don't think that multiparty signing is in general broken with short hashes. For example the attack in #158 could be avoided by letting everybody not only commit to the nonce but also to the message. It's just that using a collision-resistant hash just eliminates the problem entirely... --- bip-schnorr.mediawiki | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 4cfe6b4..a5f7c59 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -49,12 +49,12 @@ encodings and operations. === Design === '''Schnorr signature variant''' Elliptic Curve Schnorr signatures for message ''m'' and public key ''P'' generally involve a point ''R'', integers ''e'' and ''s'' picked by the signer, and the base point ''G'' which satisfy ''e = hash(R || m)'' and ''s⋅G = R + e⋅P''. Two formulations exist, depending on whether the signer reveals ''e'' or ''R'': -# Signatures are ''(e, s)'' that satisfy ''e = hash(s⋅G - e⋅P || m)''. This supports more compact signatures, since [http://www.neven.org/papers/schnorr.pdf the hash ''e'' can be made as small as 16 bytes without sacrificing security], whereas an encoding of ''R'' inherently needs about 32 bytes. Moreover, this variant avoids minor complexity introduced by the encoding of the point ''R'' in the signature (see paragraphs "Encoding R and public key point P" and "Implicit Y coordinates" further below in this subsection). -# Signatures are ''(R, s)'' that satisfy ''s⋅G = R + hash(R || m)⋅P''. This supports batch verification, as there are no elliptic curve operations inside the hashes. Batch verification enables significant speedups. +# Signatures are pairs ''(e, s)'' that satisfy ''e = hash(s⋅G - e⋅P || m)''. This variant avoids minor complexity introduced by the encoding of the point ''R'' in the signature (see paragraphs "Encoding R and public key point P" and "Implicit Y coordinates" further below in this subsection). Moreover, revealing ''e'' instead of ''R'' allows for potentially shorter signatures: Whereas an encoding of ''R'' inherently needs about 32 bytes, the hash ''e'' can be tuned to be shorter than 32 bytes, and [http://www.neven.org/papers/schnorr.pdf a short hash of only 16 bytes suffices to provide SUF-CMA security at the target security level of 128 bits]. However, a major drawback of this optimization is that finding collisions in a short hash function is easy. This complicates the implementation of secure signing protocols in scenarios in which a group of mutually distrusting signers work together to produce a single joint signature (see Applications below). In these scenarios, which are not captured by the SUF-CMA model due its assumption of a single honest signer, a promising attack strategy for malicious co-signers is to find a collision in the hash function in order to obtain a valid signature on a message that an honest co-signer did not intent to sign. +# Signatures are pairs ''(R, s)'' that satisfy ''s⋅G = R + hash(R || m)⋅P''. This supports batch verification, as there are no elliptic curve operations inside the hashes. Batch verification enables significant speedups. [[File:bip-schnorr/speedup-batch.png|center|frame|This graph shows the ratio between the time it takes to verify ''n'' signatures individually and to verify a batch of ''n'' signatures. This ratio goes up logarithmically with the number of signatures, or in other words: the total time to verify ''n'' signatures grows with ''O(n / log n)''.]] -We choose the ''R''-option to support batch verification. +Since we would like to avoid the fragility that comes with short hashes, the ''e'' variant does not provide significant advantages. We choose the ''R''-option, which supports batch verification. '''Key prefixing''' Using the verification rule above directly makes Schnorr signatures vulnerable to "related-key attacks" in which a third party can convert a signature ''(R, s)'' for public key ''P'' into a signature ''(R, s + a⋅hash(R || m))'' for public key ''P + a⋅G'' and the same message ''m'', for any given additive tweak ''a'' to the signing key. This would render signatures insecure when keys are generated using [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#public-parent-key--public-child-key BIP32's unhardened derivation] and other methods that rely on additive tweaks to existing keys such as Taproot. -- cgit v1.2.3 From d199b6dff658adb26662813e2672a91c4480767a Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Fri, 13 Dec 2019 13:25:16 +0000 Subject: Replace private key with secret key --- bip-schnorr.mediawiki | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index a5f7c59..e1b3ed2 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -133,9 +133,9 @@ The algorithm ''PubKey(sk)'' is defined as: * Fail if ''d = 0'' or ''d ≥ n''. * Return ''bytes(d⋅G)''. -Note that we use a very different public key format (32 bytes) than the ones used by existing systems (which typically use elliptic curve points as public keys, or 33-byte or 65-byte encodings of them). A side effect is that ''PubKey(sk) = PubKey(bytes(n - int(sk))'', so every public key has two corresponding private keys. +Note that we use a very different public key format (32 bytes) than the ones used by existing systems (which typically use elliptic curve points as public keys, or 33-byte or 65-byte encodings of them). A side effect is that ''PubKey(sk) = PubKey(bytes(n - int(sk))'', so every public key has two corresponding secret keys. -As an alternative to generating keys randomly, it is also possible and safe to repurpose existing key generation algorithms for ECDSA in a compatible way. The private keys constructed by such an algorithm can be used as ''sk'' directly. The public keys constructed by such an algorithm (assuming they use the 33-byte compressed encoding) need to be converted by dropping the first byte. Specifically, [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki BIP32] and schemes built on top of it remain usable. +As an alternative to generating keys randomly, it is also possible and safe to repurpose existing key generation algorithms for ECDSA in a compatible way. The secret keys constructed by such an algorithm can be used as ''sk'' directly. The public keys constructed by such an algorithm (assuming they use the 33-byte compressed encoding) need to be converted by dropping the first byte. Specifically, [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki BIP32] and schemes built on top of it remain usable. ==== Default Signing ==== @@ -161,9 +161,9 @@ It should be noted that various alternative signing algorithms can be used to pr '''Synthetic nonces''' When a random number generator (RNG) is available, 32 bytes of RNG output can be appended to the input to ''hashBIPSchnorrDerive''. This will change the corresponding line in the signing algorithm to ''k' = int(hashBIPSchnorrDerive(bytes(d) || m || get_32_bytes_from_rng())) mod n'', where ''get_32_bytes_from_rng()'' is the call to the RNG. Adding RNG output may improve protection against [https://moderncrypto.org/mail-archive/curves/2017/000925.html fault injection attacks and side-channel attacks]. It is safe to add randomness from a low-quality randomness source, i.e., an RNG with low entropy. -'''Nonce exfiltration protection''' It is possible to strengthen the nonce generation algorithm using a second device. In this case, the second device contributes randomness which the actual signer provably incorporates into its nonce. This prevents certain attacks where the signer device is compromised and intentionally tries to leak the private key through its nonce selection. +'''Nonce exfiltration protection''' It is possible to strengthen the nonce generation algorithm using a second device. In this case, the second device contributes randomness which the actual signer provably incorporates into its nonce. This prevents certain attacks where the signer device is compromised and intentionally tries to leak the secret key through its nonce selection. -'''Multisignatures''' This signature scheme is compatible with various types of multisignature and threshold schemes such as [https://eprint.iacr.org/2018/068 MuSig], where a single public key requires holders of multiple private keys to participate in signing (see Applications below). +'''Multisignatures''' This signature scheme is compatible with various types of multisignature and threshold schemes such as [https://eprint.iacr.org/2018/068 MuSig], where a single public key requires holders of multiple secret keys to participate in signing (see Applications below). '''It is important to note that multisignature signing schemes in general are insecure with the nonce generation from the default signing algorithm above (or any deterministic nonce algorithm).''' ==== Verification ==== -- cgit v1.2.3 From 687ec4ba8e378e4d5a049cb3846e55b24bca071d Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Thu, 12 Dec 2019 16:23:20 -0800 Subject: Low-S ECDSA is non-malleable under nonstandard assumptions --- bip-schnorr.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index e1b3ed2..36652c3 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -26,7 +26,7 @@ transactions. These are [https://www.secg.org/sec1-v2.pdf standardized], but hav compared to [http://publikationen.ub.uni-frankfurt.de/opus4/files/4280/schnorr.pdf Schnorr signatures] over the same curve: * '''Provable security''': Schnorr signatures are provably secure. In more detail, they are ''strongly unforgeable under chosen message attack (SUF-CMA)''Informally, this means that without knowledge of the secret key but given valid signatures of arbitrary messages, it is not possible to come up with further valid signatures. [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf in the random oracle model assuming the hardness of the elliptic curve discrete logarithm problem (ECDLP)] and [http://www.neven.org/papers/schnorr.pdf in the generic group model assuming variants of preimage and second preimage resistance of the used hash function]A detailed security proof in the random oracle model, which essentially restates [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf the original security proof by Pointcheval and Stern] more explicitly, can be found in [https://eprint.iacr.org/2016/191 a paper by Kiltz, Masny and Pan]. All these security proofs assume a variant of Schnorr signatures that use ''(e,s)'' instead of ''(R,s)'' (see Design above). Since we use a unique encoding of ''R'', there is an efficiently computable bijection that maps ''(R,s)'' to ''(e,s)'', which allows to convert a successful SUF-CMA attacker for the ''(e,s)'' variant to a successful SUF-CMA attacker for the ''(R,s)'' variant (and vice-versa). Furthermore, the proofs consider a variant of Schnorr signatures without key prefixing (see Design above), but it can be verified that the proofs are also correct for the variant with key prefixing. As a result, all the aforementioned security proofs apply to the variant of Schnorr signatures proposed in this document.. In contrast, the [https://nbn-resolving.de/urn:nbn:de:hbz:294-60803 best known results for the provable security of ECDSA] rely on stronger assumptions. -* '''Non-malleability''': The SUF-CMA security of Schnorr signatures implies that they are non-malleable. On the other hand, ECDSA signatures are inherently malleable; a third party without access to the secret key can alter an existing valid signature for a given public key and message into another signature that is valid for the same key and message. This issue is discussed in [https://github.com/bitcoin/bips/blob/master/bip-0062.mediawiki BIP62] and [https://github.com/bitcoin/bips/blob/master/bip-0146.mediawiki BIP146]. +* '''Non-malleability''': The SUF-CMA security of Schnorr signatures implies that they are non-malleable. On the other hand, ECDSA signatures are inherently malleableIf ''(r,s)'' is a valid ECDSA signature for a given message and key, then ''(r,n-s)'' is also valid for the same message and key. If ECDSA is restricted to only permit one of the two variants (as Bitcoin does through a policy rule on the network), it can be [https://nbn-resolving.de/urn:nbn:de:hbz:294-60803 proven] non-malleable under stronger than usual assumptions.; a third party without access to the secret key can alter an existing valid signature for a given public key and message into another signature that is valid for the same key and message. This issue is discussed in [https://github.com/bitcoin/bips/blob/master/bip-0062.mediawiki BIP62] and [https://github.com/bitcoin/bips/blob/master/bip-0146.mediawiki BIP146]. * '''Linearity''': Schnorr signatures have the remarkable property that multiple parties can collaborate to produce a signature that is valid for the sum of their public keys. This is the building block for various higher-level constructions that improve efficiency and privacy, such as multisignatures and others (see Applications below). For all these advantages, there are virtually no disadvantages, apart -- cgit v1.2.3 From 3c1f46637253e20b2f12dcaecfb88881f792a4cf Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Thu, 12 Dec 2019 19:53:08 -0800 Subject: Completely specified --- bip-schnorr.mediawiki | 1 + 1 file changed, 1 insertion(+) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 36652c3..542ed0c 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -37,6 +37,7 @@ made: * '''Signature encoding''': Instead of using [https://en.wikipedia.org/wiki/X.690#DER_encoding DER]-encoding for signatures (which are variable size, and up to 72 bytes), we can use a simple fixed 64-byte format. * '''Public key encoding''': Instead of using ''compressed'' 33-byte encodings of elliptic curve points which are common in Bitcoin today, public keys in this proposal are encoded as 32 bytes. * '''Batch verification''': The specific formulation of ECDSA signatures that is standardized cannot be verified more efficiently in batch compared to individually, unless additional witness data is added. Changing the signature scheme offers an opportunity to address this. +* '''Completely specified''': To be safe for usage in consensus systems, the verification algorithm must be completely specified at the byte level. This guarantees that nobody can construct a signature that is valid to some verifiers but not all. This is traditionally not a requirement for digital signature schemes, and the lack of exact specification for the DER parsing of ECDSA signatures has caused problems for Bitcoin [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2015-July/009697.html in the past], needing [https://github.com/bitcoin/bips/blob/master/bip-0146.mediawiki BIP66] to address it. In this document we aim to meet this property by design. For batch verification, which is inherently non-deterministic as the verifier can choose their batches, this property implies that the outcome of verification may only differ from individual verifications with negligible probability, even to an attacker who intentionally tries to make batch- and non-batch verification differ. By reusing the same curve as Bitcoin uses for ECDSA, we are able to retain existing mechanisms for choosing secret and public keys, and we avoid introducing new assumptions about elliptic curve group security. -- cgit v1.2.3 From 3cc2d8ed6df2334594c28c948455505458b10fe4 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Fri, 13 Dec 2019 12:11:50 +0100 Subject: Mention that we don't change the hash function --- bip-schnorr.mediawiki | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 542ed0c..20d605f 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -21,7 +21,7 @@ This document is licensed under the 2-clause BSD license. === Motivation === Bitcoin has traditionally used -[https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm ECDSA] signatures over the [https://www.secg.org/sec2-v2.pdf secp256k1 curve] for authenticating +[https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm ECDSA] signatures over the [https://www.secg.org/sec2-v2.pdf secp256k1 curve] and with [https://en.wikipedia.org/wiki/SHA-2 SHA256] hashes for authenticating transactions. These are [https://www.secg.org/sec1-v2.pdf standardized], but have a number of downsides compared to [http://publikationen.ub.uni-frankfurt.de/opus4/files/4280/schnorr.pdf Schnorr signatures] over the same curve: @@ -39,7 +39,7 @@ made: * '''Batch verification''': The specific formulation of ECDSA signatures that is standardized cannot be verified more efficiently in batch compared to individually, unless additional witness data is added. Changing the signature scheme offers an opportunity to address this. * '''Completely specified''': To be safe for usage in consensus systems, the verification algorithm must be completely specified at the byte level. This guarantees that nobody can construct a signature that is valid to some verifiers but not all. This is traditionally not a requirement for digital signature schemes, and the lack of exact specification for the DER parsing of ECDSA signatures has caused problems for Bitcoin [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2015-July/009697.html in the past], needing [https://github.com/bitcoin/bips/blob/master/bip-0146.mediawiki BIP66] to address it. In this document we aim to meet this property by design. For batch verification, which is inherently non-deterministic as the verifier can choose their batches, this property implies that the outcome of verification may only differ from individual verifications with negligible probability, even to an attacker who intentionally tries to make batch- and non-batch verification differ. -By reusing the same curve as Bitcoin uses for ECDSA, we are able to retain existing mechanisms for choosing secret and public keys, and we avoid introducing new assumptions about elliptic curve group security. +By reusing the same curve and hash function as Bitcoin has used for ECDSA, we are able to retain existing mechanisms for choosing private and public keys, and we avoid introducing new assumptions about the security of elliptic curves and hash functions. == Description == -- cgit v1.2.3 From 0dd7489dfd4652ca46c5a00d783cadb32b85ac8d Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Fri, 13 Dec 2019 15:28:15 +0100 Subject: Update bip-schnorr.mediawiki --- bip-schnorr.mediawiki | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 20d605f..e133b2f 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -21,7 +21,7 @@ This document is licensed under the 2-clause BSD license. === Motivation === Bitcoin has traditionally used -[https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm ECDSA] signatures over the [https://www.secg.org/sec2-v2.pdf secp256k1 curve] and with [https://en.wikipedia.org/wiki/SHA-2 SHA256] hashes for authenticating +[https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm ECDSA] signatures over the [https://www.secg.org/sec2-v2.pdf secp256k1 curve] with [https://en.wikipedia.org/wiki/SHA-2 SHA256] hashes for authenticating transactions. These are [https://www.secg.org/sec1-v2.pdf standardized], but have a number of downsides compared to [http://publikationen.ub.uni-frankfurt.de/opus4/files/4280/schnorr.pdf Schnorr signatures] over the same curve: @@ -39,7 +39,7 @@ made: * '''Batch verification''': The specific formulation of ECDSA signatures that is standardized cannot be verified more efficiently in batch compared to individually, unless additional witness data is added. Changing the signature scheme offers an opportunity to address this. * '''Completely specified''': To be safe for usage in consensus systems, the verification algorithm must be completely specified at the byte level. This guarantees that nobody can construct a signature that is valid to some verifiers but not all. This is traditionally not a requirement for digital signature schemes, and the lack of exact specification for the DER parsing of ECDSA signatures has caused problems for Bitcoin [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2015-July/009697.html in the past], needing [https://github.com/bitcoin/bips/blob/master/bip-0146.mediawiki BIP66] to address it. In this document we aim to meet this property by design. For batch verification, which is inherently non-deterministic as the verifier can choose their batches, this property implies that the outcome of verification may only differ from individual verifications with negligible probability, even to an attacker who intentionally tries to make batch- and non-batch verification differ. -By reusing the same curve and hash function as Bitcoin has used for ECDSA, we are able to retain existing mechanisms for choosing private and public keys, and we avoid introducing new assumptions about the security of elliptic curves and hash functions. +By reusing the same curve and hash function as Bitcoin uses for ECDSA, we are able to retain existing mechanisms for choosing secret and public keys, and we avoid introducing new assumptions about the security of elliptic curves and hash functions. == Description == -- cgit v1.2.3 From 9c76bb457f90a499aa894ae6d4c00f05e5329d55 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Wed, 11 Dec 2019 19:00:29 -0800 Subject: Linearity makes sign-for-sum-of-keys easier, not possible entirely. I'm sure it's possible to construct a complex MPC that can sign for the sum of keys under ECDSA as well. --- bip-schnorr.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index e133b2f..8d750e4 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -27,7 +27,7 @@ compared to [http://publikationen.ub.uni-frankfurt.de/opus4/files/4280/schnorr.p * '''Provable security''': Schnorr signatures are provably secure. In more detail, they are ''strongly unforgeable under chosen message attack (SUF-CMA)''Informally, this means that without knowledge of the secret key but given valid signatures of arbitrary messages, it is not possible to come up with further valid signatures. [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf in the random oracle model assuming the hardness of the elliptic curve discrete logarithm problem (ECDLP)] and [http://www.neven.org/papers/schnorr.pdf in the generic group model assuming variants of preimage and second preimage resistance of the used hash function]A detailed security proof in the random oracle model, which essentially restates [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf the original security proof by Pointcheval and Stern] more explicitly, can be found in [https://eprint.iacr.org/2016/191 a paper by Kiltz, Masny and Pan]. All these security proofs assume a variant of Schnorr signatures that use ''(e,s)'' instead of ''(R,s)'' (see Design above). Since we use a unique encoding of ''R'', there is an efficiently computable bijection that maps ''(R,s)'' to ''(e,s)'', which allows to convert a successful SUF-CMA attacker for the ''(e,s)'' variant to a successful SUF-CMA attacker for the ''(R,s)'' variant (and vice-versa). Furthermore, the proofs consider a variant of Schnorr signatures without key prefixing (see Design above), but it can be verified that the proofs are also correct for the variant with key prefixing. As a result, all the aforementioned security proofs apply to the variant of Schnorr signatures proposed in this document.. In contrast, the [https://nbn-resolving.de/urn:nbn:de:hbz:294-60803 best known results for the provable security of ECDSA] rely on stronger assumptions. * '''Non-malleability''': The SUF-CMA security of Schnorr signatures implies that they are non-malleable. On the other hand, ECDSA signatures are inherently malleableIf ''(r,s)'' is a valid ECDSA signature for a given message and key, then ''(r,n-s)'' is also valid for the same message and key. If ECDSA is restricted to only permit one of the two variants (as Bitcoin does through a policy rule on the network), it can be [https://nbn-resolving.de/urn:nbn:de:hbz:294-60803 proven] non-malleable under stronger than usual assumptions.; a third party without access to the secret key can alter an existing valid signature for a given public key and message into another signature that is valid for the same key and message. This issue is discussed in [https://github.com/bitcoin/bips/blob/master/bip-0062.mediawiki BIP62] and [https://github.com/bitcoin/bips/blob/master/bip-0146.mediawiki BIP146]. -* '''Linearity''': Schnorr signatures have the remarkable property that multiple parties can collaborate to produce a signature that is valid for the sum of their public keys. This is the building block for various higher-level constructions that improve efficiency and privacy, such as multisignatures and others (see Applications below). +* '''Linearity''': Schnorr signatures have the remarkable property that multiple parties can easily collaborate to produce a signature that is valid for the sum of their public keys. This is the building block for various higher-level constructions that improve efficiency and privacy, such as multisignatures and others (see Applications below). For all these advantages, there are virtually no disadvantages, apart from not being standardized. This document seeks to change that. As we -- cgit v1.2.3 From 2c8feb1cbb2e5d5fb9090743afe32e7b42c046fa Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 13 Dec 2019 18:35:10 -0500 Subject: Update bip-schnorr.mediawiki Co-Authored-By: Tim Ruffing --- bip-schnorr.mediawiki | 2 +- bip-schnorr/__pycache__/reference.cpython-36.pyc | Bin 0 -> 5278 bytes 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 bip-schnorr/__pycache__/reference.cpython-36.pyc diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 8d750e4..e4b38f6 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -27,7 +27,7 @@ compared to [http://publikationen.ub.uni-frankfurt.de/opus4/files/4280/schnorr.p * '''Provable security''': Schnorr signatures are provably secure. In more detail, they are ''strongly unforgeable under chosen message attack (SUF-CMA)''Informally, this means that without knowledge of the secret key but given valid signatures of arbitrary messages, it is not possible to come up with further valid signatures. [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf in the random oracle model assuming the hardness of the elliptic curve discrete logarithm problem (ECDLP)] and [http://www.neven.org/papers/schnorr.pdf in the generic group model assuming variants of preimage and second preimage resistance of the used hash function]A detailed security proof in the random oracle model, which essentially restates [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf the original security proof by Pointcheval and Stern] more explicitly, can be found in [https://eprint.iacr.org/2016/191 a paper by Kiltz, Masny and Pan]. All these security proofs assume a variant of Schnorr signatures that use ''(e,s)'' instead of ''(R,s)'' (see Design above). Since we use a unique encoding of ''R'', there is an efficiently computable bijection that maps ''(R,s)'' to ''(e,s)'', which allows to convert a successful SUF-CMA attacker for the ''(e,s)'' variant to a successful SUF-CMA attacker for the ''(R,s)'' variant (and vice-versa). Furthermore, the proofs consider a variant of Schnorr signatures without key prefixing (see Design above), but it can be verified that the proofs are also correct for the variant with key prefixing. As a result, all the aforementioned security proofs apply to the variant of Schnorr signatures proposed in this document.. In contrast, the [https://nbn-resolving.de/urn:nbn:de:hbz:294-60803 best known results for the provable security of ECDSA] rely on stronger assumptions. * '''Non-malleability''': The SUF-CMA security of Schnorr signatures implies that they are non-malleable. On the other hand, ECDSA signatures are inherently malleableIf ''(r,s)'' is a valid ECDSA signature for a given message and key, then ''(r,n-s)'' is also valid for the same message and key. If ECDSA is restricted to only permit one of the two variants (as Bitcoin does through a policy rule on the network), it can be [https://nbn-resolving.de/urn:nbn:de:hbz:294-60803 proven] non-malleable under stronger than usual assumptions.; a third party without access to the secret key can alter an existing valid signature for a given public key and message into another signature that is valid for the same key and message. This issue is discussed in [https://github.com/bitcoin/bips/blob/master/bip-0062.mediawiki BIP62] and [https://github.com/bitcoin/bips/blob/master/bip-0146.mediawiki BIP146]. -* '''Linearity''': Schnorr signatures have the remarkable property that multiple parties can easily collaborate to produce a signature that is valid for the sum of their public keys. This is the building block for various higher-level constructions that improve efficiency and privacy, such as multisignatures and others (see Applications below). +* '''Linearity''': Schnorr signatures provide a simple and efficient method that enables multiple collaborating parties to produce a signature that is valid for the sum of their public keys. This is the building block for various higher-level constructions that improve efficiency and privacy, such as multisignatures and others (see Applications below). For all these advantages, there are virtually no disadvantages, apart from not being standardized. This document seeks to change that. As we diff --git a/bip-schnorr/__pycache__/reference.cpython-36.pyc b/bip-schnorr/__pycache__/reference.cpython-36.pyc new file mode 100644 index 0000000..cce1e04 Binary files /dev/null and b/bip-schnorr/__pycache__/reference.cpython-36.pyc differ -- cgit v1.2.3 From 734a859b278270e0080005269c2f55ac465fe64d Mon Sep 17 00:00:00 2001 From: Matthew Zipkin Date: Sun, 15 Dec 2019 10:32:33 -0500 Subject: bip-taproot: example from diagram --- bip-taproot.mediawiki | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 0fa4194..dedc5ab 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -236,6 +236,20 @@ def taproot_output_script(internal_pubkey, script_tree): [[File:bip-taproot/tree.png|frame|This diagram shows the hashing structure to obtain the tweak from an internal key ''P'' and a Merkle tree consisting of 5 script leaves. ''A'', ''B'', ''C'' and ''E'' are ''TapLeaf'' hashes similar to ''D'' and ''AB'' is a ''TapBranch'' hash. Note that when ''CDE'' is computed ''E'' is hashed first because ''E'' is less than ''CD''.]] +To spend this output using script ''D'', the control block would contain the following data in this order: + + + +The TapTweak would then be computed as described in [[#script-validation-rules]] like so: + + +D = tagged_hash("TapLeaf", bytes([leaf_version]) + ser_script(script)) +CD = tagged_hash("TapBranch", C + D) +CDE = tagged_hash("TapBranch", E + CD) +ABCDE = tagged_hash("TapBranch", AB + CDE) +TapTweak = tagged_hash("TapTweak", p + ABCDE) + + '''Spending using the key path''' A Taproot output can be spent with the secret key corresponding to the internal_pubkey. To do so, a witness stack consists of a single element: a bip-schnorr signature on the signature hash as defined above, with the secret key tweaked by the same h as in the above snippet. See the code below: -- cgit v1.2.3 From 84161e187d7f6f14f6baf2582eb0e62d93451966 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sat, 14 Dec 2019 16:28:44 -0800 Subject: Improve and restructure motivation and design --- bip-taproot.mediawiki | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index dedc5ab..6d49b87 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -24,17 +24,13 @@ This document is licensed under the 3-clause BSD license. ===Motivation=== -A number of related ideas for improving Bitcoin's scripting capabilities have been previously proposed: Schnorr signatures (bip-schnorr), Merkle branches ("MAST", [https://github.com/bitcoin/bips/blob/master/bip-0114.mediawiki BIP114], [https://github.com/bitcoin/bips/blob/master/bip-0117.mediawiki BIP117]), new sighash modes ([https://github.com/bitcoin/bips/blob/master/bip-0118.mediawiki BIP118]), new opcodes like CHECKSIGFROMSTACK, [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-January/015614.html Taproot], [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-February/015700.html Graftroot], [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-July/016249.html G'root], and [https://bitcointalk.org/index.php?topic=1377298.0 cross-input aggregation]. - -Combining all these ideas in a single proposal would be an extensive change, be hard to review, and likely miss new discoveries that otherwise could have been made along the way. Some of these ideas are also less mature than others. On the other hand, separating them all into independent proposals would reduce the efficiency and privacy gains to be had, and complicate analysis of their interactions. It seems preferable to focus on one goal set at a time, and combine interacting technologies to achieve them. +This proposal aims to improve privacy, efficiency, and flexibility of Bitcoin's scripting capabilities without adding new security assumptions. Specifically, it seeks to minimize how much information about the spendability conditions of a transaction output is revealed on chain at creation or spending time and to add a number of upgrade mechanisms, while fixing a few minor but long-standing issues. ==Design== -This proposal focuses on improvements to privacy, efficiency, and flexibility of Bitcoin's scripting capabilities, subject to two restrictions: -* Not adding any new strong security assumptions -* Not combining into the proposal any functionality which could be simply implemented independently. +A number of related ideas for improving Bitcoin's scripting capabilities have been previously proposed: Schnorr signatures (bip-schnorr), Merkle branches ("MAST", [https://github.com/bitcoin/bips/blob/master/bip-0114.mediawiki BIP114], [https://github.com/bitcoin/bips/blob/master/bip-0117.mediawiki BIP117]), new sighash modes ([https://github.com/bitcoin/bips/blob/master/bip-0118.mediawiki BIP118]), new opcodes like CHECKSIGFROMSTACK, [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-January/015614.html Taproot], [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-February/015700.html Graftroot], [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-July/016249.html G'root], and [https://bitcointalk.org/index.php?topic=1377298.0 cross-input aggregation]. -Specifically, it seeks to minimize how much information about the spendability conditions of a transaction output is revealed on chain at creation or spending time. To avoid reducing the effectiveness of future improvements a number of upgrade mechanisms are also included, as well as fixes for minor but long-standing issues. +Combining all these ideas in a single proposal would be an extensive change, be hard to review, and likely miss new discoveries that otherwise could have been made along the way. Not all are equally mature as well. For example, cross-input aggregation [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-March/015838.html interacts] in complex ways with upgrade mechanisms, and solutions to that are still [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-October/016461.html in flux]. On the other hand, separating them all into independent upgrades would reduce the efficiency and privacy gains to be had, and wallet and service providers may not be inclined to go through many incremental updates. Therefore, we're faced with a tradeoff between functionality and scope creep. In this design we strike a balance by focusing on the structural script improvements offered by Taproot and Merkle branches, as well as changes necessary to make them usable and efficient. For things like sighashes and opcodes we include fixes for known problems, but exclude new features that can be added independently with no downsides. As a result we choose this combination of technologies: * '''Merkle branches''' let us only reveal the actually executed part of the script to the blockchain, as opposed to all possible ways a script can be executed. Among the various known mechanisms for implementing this, one where the Merkle tree becomes part of the script's structure directly maximizes the space savings, so that approach is chosen. @@ -45,7 +41,6 @@ As a result we choose this combination of technologies: * While the core semantics of the '''signature hashing algorithm''' are not changed, a number of improvements are included in this proposal. The new signature hashing algorithm fixes the verification capabilities of offline signing devices by including amount and scriptPubKey in the digest, avoids unnecessary hashing, uses '''tagged hashes''' and defines a default sighash byte. * The '''public key is directly included in the output''' in contrast to typical earlier constructions which store a hash of the public key or script in the output. This has the same cost for senders and is more space efficient overall if the key-based spending path is taken. '''Why is the public key directly included in the output?''' While typical earlier constructions store a hash of a script or a public key in the output, this is rather wasteful when a public key is always involved. To guarantee batch verifiability, the public key must be known to every verifier, and thus only revealing its hash as an output would imply adding an additional 32 bytes to the witness. Furthermore, to maintain [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2016-January/012198.html 128-bit collision security] for outputs, a 256-bit hash would be required anyway, which is comparable in size (and thus in cost for senders) to revealing the public key directly. While the usage of public key hashes is often said to protect against ECDLP breaks or quantum computers, this protection is very weak at best: transactions are not protected while being confirmed, and a very [https://twitter.com/pwuille/status/1108097835365339136 large portion] of the currency's supply is not under such protection regardless. Actual resistance to such systems can be introduced by relying on different cryptographic assumptions, but this proposal focuses on improvements that do not change the security model. -Not included in this proposal are additional features like new sighash modes or opcodes that can be included with no loss in effectiveness as a future extension. Also not included is cross-input aggregation, as it [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-March/015838.html interacts] in complex ways with upgrade mechanisms and solutions to that are still [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-October/016461.html in flux]. == Specification == -- cgit v1.2.3 From 94e9c0925a3e132581f6cb6d44923ce3dc540b45 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sat, 14 Dec 2019 16:28:58 -0800 Subject: Add an informal summary of the design --- bip-taproot.mediawiki | 1 + 1 file changed, 1 insertion(+) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 6d49b87..f436497 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -41,6 +41,7 @@ As a result we choose this combination of technologies: * While the core semantics of the '''signature hashing algorithm''' are not changed, a number of improvements are included in this proposal. The new signature hashing algorithm fixes the verification capabilities of offline signing devices by including amount and scriptPubKey in the digest, avoids unnecessary hashing, uses '''tagged hashes''' and defines a default sighash byte. * The '''public key is directly included in the output''' in contrast to typical earlier constructions which store a hash of the public key or script in the output. This has the same cost for senders and is more space efficient overall if the key-based spending path is taken. '''Why is the public key directly included in the output?''' While typical earlier constructions store a hash of a script or a public key in the output, this is rather wasteful when a public key is always involved. To guarantee batch verifiability, the public key must be known to every verifier, and thus only revealing its hash as an output would imply adding an additional 32 bytes to the witness. Furthermore, to maintain [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2016-January/012198.html 128-bit collision security] for outputs, a 256-bit hash would be required anyway, which is comparable in size (and thus in cost for senders) to revealing the public key directly. While the usage of public key hashes is often said to protect against ECDLP breaks or quantum computers, this protection is very weak at best: transactions are not protected while being confirmed, and a very [https://twitter.com/pwuille/status/1108097835365339136 large portion] of the currency's supply is not under such protection regardless. Actual resistance to such systems can be introduced by relying on different cryptographic assumptions, but this proposal focuses on improvements that do not change the security model. +Informally, the resulting design is as follows. A new witness version is added (1), whose programs consist of 32-byte encodings of points ''Q''. ''Q'' is computed as ''P + hash(P||m)G'' for a public key ''P'', and the root ''m'' of a Merkle tree whose leaves consist of a version number and a script. These outputs can be spent directly by providing a signature for ''Q'', or indirectly by revealing ''P'', the script and leaf version, inputs that satisfy the script, and a Merkle path that proves ''Q'' committed to that leaf. All hashes in this construction (the hash for computing ''Q'' from ''P'', the hashes inside the Merkle tree's inner nodes, and the signature hashes used) are tagged to guarantee domain separation. == Specification == -- cgit v1.2.3 From 460163ee0b1268834f707154f6d4056da001ece9 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sun, 15 Dec 2019 14:44:39 -0800 Subject: Add rationale on security assumptions --- bip-taproot.mediawiki | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index f436497..2abb185 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -24,7 +24,7 @@ This document is licensed under the 3-clause BSD license. ===Motivation=== -This proposal aims to improve privacy, efficiency, and flexibility of Bitcoin's scripting capabilities without adding new security assumptions. Specifically, it seeks to minimize how much information about the spendability conditions of a transaction output is revealed on chain at creation or spending time and to add a number of upgrade mechanisms, while fixing a few minor but long-standing issues. +This proposal aims to improve privacy, efficiency, and flexibility of Bitcoin's scripting capabilities without adding new security assumptions'''What does not adding security assumptions mean?''' Unforgeability of signatures is a necessary requirement to prevent theft. At least when treating script execution as a digital signature scheme itself, unforgeability can be [https://github.com/apoelstra/taproot proven] in the Random Oracle Model assuming the Discrete Logarithm problem is hard. A [https://nbn-resolving.de/urn:nbn:de:hbz:294-60803 proof] for unforgeability of ECDSA in the current script system needs non-standard assumptions on top of that. Note that it is hard in general to model exactly what security for script means, as it depends on the policies and protocols used by wallet software.. Specifically, it seeks to minimize how much information about the spendability conditions of a transaction output is revealed on chain at creation or spending time and to add a number of upgrade mechanisms, while fixing a few minor but long-standing issues. ==Design== @@ -41,7 +41,7 @@ As a result we choose this combination of technologies: * While the core semantics of the '''signature hashing algorithm''' are not changed, a number of improvements are included in this proposal. The new signature hashing algorithm fixes the verification capabilities of offline signing devices by including amount and scriptPubKey in the digest, avoids unnecessary hashing, uses '''tagged hashes''' and defines a default sighash byte. * The '''public key is directly included in the output''' in contrast to typical earlier constructions which store a hash of the public key or script in the output. This has the same cost for senders and is more space efficient overall if the key-based spending path is taken. '''Why is the public key directly included in the output?''' While typical earlier constructions store a hash of a script or a public key in the output, this is rather wasteful when a public key is always involved. To guarantee batch verifiability, the public key must be known to every verifier, and thus only revealing its hash as an output would imply adding an additional 32 bytes to the witness. Furthermore, to maintain [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2016-January/012198.html 128-bit collision security] for outputs, a 256-bit hash would be required anyway, which is comparable in size (and thus in cost for senders) to revealing the public key directly. While the usage of public key hashes is often said to protect against ECDLP breaks or quantum computers, this protection is very weak at best: transactions are not protected while being confirmed, and a very [https://twitter.com/pwuille/status/1108097835365339136 large portion] of the currency's supply is not under such protection regardless. Actual resistance to such systems can be introduced by relying on different cryptographic assumptions, but this proposal focuses on improvements that do not change the security model. -Informally, the resulting design is as follows. A new witness version is added (1), whose programs consist of 32-byte encodings of points ''Q''. ''Q'' is computed as ''P + hash(P||m)G'' for a public key ''P'', and the root ''m'' of a Merkle tree whose leaves consist of a version number and a script. These outputs can be spent directly by providing a signature for ''Q'', or indirectly by revealing ''P'', the script and leaf version, inputs that satisfy the script, and a Merkle path that proves ''Q'' committed to that leaf. All hashes in this construction (the hash for computing ''Q'' from ''P'', the hashes inside the Merkle tree's inner nodes, and the signature hashes used) are tagged to guarantee domain separation. +Informally, the resulting design is as follows: a new witness version is added (version 1), whose programs consist of 32-byte encodings of points ''Q''. ''Q'' is computed as ''P + hash(P||m)G'' for a public key ''P'', and the root ''m'' of a Merkle tree whose leaves consist of a version number and a script. These outputs can be spent directly by providing a signature for ''Q'', or indirectly by revealing ''P'', the script and leaf version, inputs that satisfy the script, and a Merkle path that proves ''Q'' committed to that leaf. All hashes in this construction (the hash for computing ''Q'' from ''P'', the hashes inside the Merkle tree's inner nodes, and the signature hashes used) are tagged to guarantee domain separation. == Specification == -- cgit v1.2.3 From 32c0f50d7bae4fc8c1eebc4fb8d05acff863cb88 Mon Sep 17 00:00:00 2001 From: stefanwouldgo Date: Thu, 28 Nov 2019 14:48:20 +0100 Subject: more precise wording on limits there are no tx or block size limits (post-Segwit), just block weight limit better wording --- bip-tapscript.mediawiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index 50f9d5e..e802430 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -126,7 +126,7 @@ In summary, the semantics of the [https://github.com/bitcoin/bips/blob/master/bi ===Resource limits=== In addition to changing the semantics of a number of opcodes, there are also some changes to the resource limitations: -* '''Script size limit''' The maximum script size of 10000 bytes does not apply. Their size is only implicitly limited by the limits on transaction and block size.'''Why is a limit on script size no longer needed?''' Since there is no scriptCode directly included in the signature hash (only indirectly through a precomputable tapleaf hash), the CPU time spent on a signature check is no longer proportional to the size of the script being executed. +* '''Script size limit''' The maximum script size of 10000 bytes does not apply. Their size is only implicitly bounded by the block weight limit.'''Why is a limit on script size no longer needed?''' Since there is no scriptCode directly included in the signature hash (only indirectly through a precomputable tapleaf hash), the CPU time spent on a signature check is no longer proportional to the size of the script being executed. * '''Non-push opcodes limit''' The maximum non-push opcodes limit of 201 per script does not apply.'''Why is a limit on the number of opcodes no longer needed?''' An opcode limit only helps to the extent that it can prevent data structures from growing unboundedly during execution (both because of memory usage, and because of time that may grow in proportion to the size of those structures). The size of stack and altstack is already independently limited. By using O(1) logic for OP_IF, OP_NOTIF, OP_ELSE, and OP_ENDIF as suggested [https://bitslog.com/2017/04/17/new-quadratic-delays-in-bitcoin-scripts/ here] and implemented [https://github.com/bitcoin/bitcoin/pull/16902 here], the only other instance can be avoided as well. * '''Sigops limit''' The sigops in tapscripts do not count towards the block-wide limit of 80000 (weighted). Instead, there is a per-script sigops ''budget''. The budget equals 50 + the total serialized size in bytes of the transaction input's witness (including the CCompactSize prefix). Executing a signature opcode (OP_CHECKSIG, OP_CHECKSIGVERIFY, or OP_CHECKSIGADD) with a non-empty signature decrements the budget by 50. If that brings the budget below zero, the script fails immediately. Signature opcodes with unknown public key type and non-empty signature are also counted.'''The tapscript sigop limit''' The signature opcode limit protects against scripts which are slow to verify due to excessively many signature operations. In tapscript the number of signature opcodes does not count towards the BIP141 or legacy sigop limit. The old sigop limit makes transaction selection in block construction unnecessarily difficult because it is a second constraint in addition to weight. Instead, the number of tapscript signature opcodes is limited by witness weight. Additionally, the limit applies to the transaction input instead of the block and only actually executed signature opcodes are counted. Tapscript execution allows one signature opcode per 50 witness weight units plus one free signature opcode.'''Parameter choice of the sigop limit''' Regular witnesses are unaffected by the limit as their weight is composed of public key and (SIGHASH_ALL) signature pairs with ''33 + 65'' weight units each (which includes a 1 weight unit CCompactSize tag). This is also the case if public keys are reused in the script because a signature's weight alone is 65 or 66 weight units. However, the limit increases the fees of abnormal scripts with duplicate signatures (and public keys) by requiring additional weight. The weight per sigop factor 50 corresponds to the ratio of BIP141 block limits: 4 mega weight units divided by 80,000 sigops. The "free" signature opcode permitted by the limit exists to account for the weight of the non-witness parts of the transaction input.'''Why are only signature opcodes counted toward the budget, and not for example hashing opcodes or other expensive operations?''' It turns out that the CPU cost per witness byte for verification of a script consisting of the maximum density of signature checking opcodes (taking the 50 WU/sigop limit into account) is already very close to that of scripts packed with other opcodes, including hashing opcodes (taking the 520 byte stack element limit into account) and OP_ROLL (taking the 1000 stack element limit into account). That said, the construction is very flexible, and allows adding new signature opcodes like CHECKSIGFROMSTACK to count towards the limit through a soft fork. Even if in the future new opcodes are introduced which change normal script cost there is no need to stuff the witness with meaningless data. Instead, the taproot annex can be used to add weight to the witness without increasing the actual witness size.. * '''Stack + altstack element count limit''' The existing limit of 1000 elements in the stack and altstack together after every executed opcode remains. It is extended to also apply to the size of initial stack. -- cgit v1.2.3 From f4297500367073c2b44dca1313cba1ca2794a37c Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 17 Dec 2019 17:27:22 -0800 Subject: Update authors --- bip-schnorr.mediawiki | 2 ++ bip-taproot.mediawiki | 2 ++ bip-tapscript.mediawiki | 2 ++ 3 files changed, 6 insertions(+) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index e4b38f6..b20fb48 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -2,6 +2,8 @@ BIP: ? Title: Schnorr Signatures for secp256k1 Author: Pieter Wuille + Jonas Nick + Tim Ruffing Status: Draft Type: Informational License: BSD-2-Clause diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 2abb185..7b75fa0 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -3,6 +3,8 @@ Layer: Consensus (soft fork) Title: Taproot: SegWit version 1 output spending rules Author: Pieter Wuille + Jonas Nick + Anthony Towns Comments-Summary: No comments yet. Comments-URI: Status: Draft diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index e802430..60d48d6 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -3,6 +3,8 @@ Layer: Consensus (soft fork) Title: Validation of Taproot Scripts Author: Pieter Wuille + Jonas Nick + Anthony Towns Comments-Summary: No comments yet. Comments-URI: Status: Draft -- cgit v1.2.3 From 92e3d6ca87b658895d9df6a5f75b6cd9e9574704 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 17 Dec 2019 17:27:36 -0800 Subject: Update Post-History field for taproot/tapscript --- bip-taproot.mediawiki | 1 + bip-tapscript.mediawiki | 1 + 2 files changed, 2 insertions(+) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 7b75fa0..6090a71 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -12,6 +12,7 @@ Created: License: BSD-3-Clause Requires: bip-schnorr + Post-History: 2019-05-06: https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2019-May/016914.html [bitcoin-dev] Taproot proposal ==Introduction== diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index 60d48d6..759d0d8 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -12,6 +12,7 @@ Created: License: BSD-3-Clause Requires: bip-schnorr, bip-taproot + Post-History: 2019-05-06: https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2019-May/016914.html [bitcoin-dev] Taproot proposal ==Introduction== -- cgit v1.2.3 From 41f8993a4b568988c8a93aacd1d40ba764d68dd3 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Tue, 31 Dec 2019 14:26:50 +0100 Subject: Clarify nonce generation - Separate nonce generation into getting a random byte string and converting it to a suitable scalar ... - ... to make clear that the byte string can be generated differently. - Make the warning a little bit more prominent and improve writing --- bip-schnorr.mediawiki | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index b20fb48..084b33f 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -151,7 +151,8 @@ The algorithm ''Sign(sk, m)'' is defined as: * Fail if ''d' = 0'' or ''d' ≥ n'' * Let ''P = d'⋅G'' * Let ''d = d' '' if ''has_square_y(P)'', otherwise let ''d = n - d' ''. -* Let ''k' = int(hashBIPSchnorrDerive(bytes(d) || m)) mod n''Note that in general, taking the output of a hash function modulo the curve order will produce an unacceptably biased result. However, for the secp256k1 curve, the order is sufficiently close to ''2256'' that this bias is not observable (''1 - n / 2256'' is around ''1.27 * 2-128'').. +* Let ''rand = hashBIPSchnorrDerive(bytes(d) || m)''. +* Let ''k' = int(rand) mod n''Note that in general, taking a uniformly random 256-bit integer modulo the curve order will produce an unacceptably biased result. However, for the secp256k1 curve, the order is sufficiently close to ''2256'' that this bias is not observable (''1 - n / 2256'' is around ''1.27 * 2-128'').. * Fail if ''k' = 0''. * Let ''R = k'⋅G''. * Let ''k = k' '' if ''has_square_y(R)'', otherwise let ''k = n - k' ''. @@ -160,14 +161,14 @@ The algorithm ''Sign(sk, m)'' is defined as: ==== Alternative Signing ==== -It should be noted that various alternative signing algorithms can be used to produce equally valid signatures. The algorithm in the previous section will always produce the same signature for a given message and public key, but the ''k'' value (and hence ''R'') may be generated in other ways, producing a different, but still valid, signature (in other words, it is not a ''unique'' signature scheme). +It should be noted that various alternative signing algorithms can be used to produce equally valid signatures. The algorithm in the previous section is deterministic, i.e., it will always produce the same signature for a given message and secret key. This method does not need a random number generator (RNG) at signing time and is thus trivially robust against failures of RNGs. Alternatively the 32-byte ''rand'' value may be generated in other ways, producing a different but still valid signature (in other words, this is not a ''unique'' signature scheme). '''No matter which method is used to generate the ''rand'' value, the value must be a fresh uniformly random 32-byte string which is not even partially predictable for the attacker.''' -'''Synthetic nonces''' When a random number generator (RNG) is available, 32 bytes of RNG output can be appended to the input to ''hashBIPSchnorrDerive''. This will change the corresponding line in the signing algorithm to ''k' = int(hashBIPSchnorrDerive(bytes(d) || m || get_32_bytes_from_rng())) mod n'', where ''get_32_bytes_from_rng()'' is the call to the RNG. Adding RNG output may improve protection against [https://moderncrypto.org/mail-archive/curves/2017/000925.html fault injection attacks and side-channel attacks]. It is safe to add randomness from a low-quality randomness source, i.e., an RNG with low entropy. +'''Synthetic nonces''' For instance when a RNG is available, 32 bytes of RNG output can be appended to the input to ''hashBIPSchnorrDerive''. This will change the corresponding line in the signing algorithm to ''rand = hashBIPSchnorrDerive(bytes(d) || m || get_32_bytes_from_rng())'', where ''get_32_bytes_from_rng()'' is the call to the RNG. Adding RNG output may improve protection against [https://moderncrypto.org/mail-archive/curves/2017/000925.html fault injection attacks and side-channel attacks], and it is safe to add the output of a low-entropy RNG. '''Nonce exfiltration protection''' It is possible to strengthen the nonce generation algorithm using a second device. In this case, the second device contributes randomness which the actual signer provably incorporates into its nonce. This prevents certain attacks where the signer device is compromised and intentionally tries to leak the secret key through its nonce selection. '''Multisignatures''' This signature scheme is compatible with various types of multisignature and threshold schemes such as [https://eprint.iacr.org/2018/068 MuSig], where a single public key requires holders of multiple secret keys to participate in signing (see Applications below). -'''It is important to note that multisignature signing schemes in general are insecure with the nonce generation from the default signing algorithm above (or any deterministic nonce algorithm).''' +'''It is important to note that multisignature signing schemes in general are insecure with the ''rand'' generation from the default signing algorithm above (or any other deterministic method).''' ==== Verification ==== -- cgit v1.2.3 From ff8a36200bc270b574916e00fcc33ce8cdd807cb Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 7 Jan 2020 13:17:13 -0800 Subject: Redefine leaf versions to be incrementally increasing from 0 --- bip-taproot.mediawiki | 20 ++++++++++---------- bip-tapscript.mediawiki | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 6090a71..2b91da8 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -59,19 +59,19 @@ The following rules only apply when such an output is being spent. Any other out * Let ''q'' be the 32-byte array containing the witness program (the second push in the scriptPubKey) which represents a public key according to bip-schnorr. * Fail if the witness stack has 0 elements. -* If there are at least two witness elements, and the first byte of the last element is 0x50'''Why is the first byte of the annex 0x50?''' Like the 0xc0 constant, 0x50 is chosen as it could not be confused with a valid P2WPKH or P2WSH spending. As the control block's initial byte's lowest bit is used to indicate the public key's Y squareness, each script version needs two subsequence byte values that are both not yet used in P2WPKH or P2WSH spending. To indicate the annex, only an "unpaired" available byte is necessary like 0x50. This choice maximizes the available options for future script versions., this last element is called ''annex'' ''a'''''What is the purpose of the annex?''' The annex is a reserved space for future extensions, such as indicating the validation costs of computationally expensive new opcodes in a way that is recognizable without knowing the outputs being spent. Until the meaning of this field is defined by another softfork, users SHOULD NOT include annex in transactions, or it may lead to PERMANENT FUND LOSS. and is removed from the witness stack. The annex (or the lack of thereof) is always covered by the transaction digest and contributes to transaction weight, but is otherwise ignored during taproot validation. +* If there are at least two witness elements, and the first byte of the last element is 0x50'''Why is the first byte of the annex 0x50?''' Like the choice to always set the top two bits of the control block's first byte the, 0x50 is chosen as it could not be confused with a valid P2WPKH or P2WSH spending. As the control block's initial byte's lowest bit is used to indicate the public key's Y squareness, each leaf version needs two subsequent byte values that are both not yet used in P2WPKH or P2WSH spending. To indicate the annex, only an "unpaired" available byte is necessary like 0x50. This choice maximizes the available options for future script versions., this last element is called ''annex'' ''a'''''What is the purpose of the annex?''' The annex is a reserved space for future extensions, such as indicating the validation costs of computationally expensive new opcodes in a way that is recognizable without knowing the scriptPubKey of the output being spent. Until the meaning of this field is defined by another softfork, users SHOULD NOT include annex in transactions, or it may lead to PERMANENT FUND LOSS. and is removed from the witness stack. The annex (or the lack of thereof) is always covered by the transaction digest and contributes to transaction weight, but is otherwise ignored during taproot validation. * If there is exactly one element left in the witness stack, key path spending is used: ** The single witness stack element is interpreted as the signature and must be valid (see the next section) for the public key ''q'' and taproot transaction digest (to be defined hereinafter) as message. Fail if it is not. Otherwise pass. * If there are at least two witness elements left, script path spending is used: ** Call the second-to-last stack element ''s'', the script. ** The last stack element is called the control block ''c'', and must have length ''33 + 32m'', for a value of ''m'' that is an integer between 0 and 128'''Why is the Merkle path length limited to 128?''' The optimally space-efficient Merkle tree can be constructed based on the probabilities of the scripts in the leaves, using the Huffman algorithm. This algorithm will construct branches with lengths approximately equal to ''log2(1/probability)'', but to have branches longer than 128 you would need to have scripts with an execution chance below 1 in ''2128''. As that is our security bound, scripts that truly have such a low chance can probably be removed entirely., inclusive. Fail if it does not have such a length. ** Let ''p = c[1:33]'' and let ''P = point(p)'' where ''point'' and ''[:]'' are defined as in bip-schnorr. Fail if this point is not on the curve. -** Let ''l = c[0] & 0xfe'', the leaf version'''What is the purpose of the first byte of the control block?''' The first byte of the control block has three distinct functions: +** Call ''(c[0] ^ 0xc0) >> 1'' the leaf version'''What is the purpose of the first byte of the control block?''' The first byte of the control block has three distinct functions: * The low bit is used to denote whether the point represented by public key ''q'' is negated before verifying the taproot tweak.'''Why is it necessary to reveal a bit to indicate if the point represented by the output public key is negated in a script path spend?''' The ''point'' function (defined in bip-schnorr) always constructs a point with a square Y coordinate, but because ''Q'' is constructed by adding the taproot tweak to the internal public key ''P'', it cannot easily be guaranteed that ''Q'' in fact has such a Y coordinate. Therefore, before verifying the taproot tweak the original point is restored by negating if necessary. We can not ignore the Y coordinate because it would prevent batch verification. Trying out multiple internal keys until there's such a ''Q'' is possible but undesirable and unnecessary since this information about the Y coordinate only consumes an unused bit. -* By keeping the top two bits set to true, it can be guaranteed that scripts can be recognized without knowledge of the UTXO being spent, simplifying analysis. This is because such values cannot occur as first byte of the final stack element in either P2WPKH or P2WSH spends. -* The remaining five bits are used for introducing new script versions that are not observable unless actually executed. +* Some types of static analysis may benefit from the ability to analyse spends without access to the output being spent. We achieve that for leaf versions 0 to 31 via flipping the top two bits of the first byte of the control block and observing that this ensures they can be distinguished from P2WPKH and P2WSH spends -- as for P2WPKH, the last witness stack item is a public key, whose first byte is either 0x02 or 0x03, and for P2WSH, the last item is a script, and scripts must contain valid opcodes, but no value ≥ 0xc0 is a valid opcode. +* The remaining five bits encode the leaf version, which can be used for introducing new script versions that are not observable unless actually executed. . -** Let ''k0 = hashTapLeaf(l || compact_size(size of s) || s)''; also call it the ''tapleaf hash''. +** Let ''k0 = hashTapLeaf(c[0] & 0xfe || compact_size(size of s) || s)''; also call it the ''tapleaf hash''. ** For ''j'' in ''[0,1,...,m-1]'': *** Let ''ej = c[33+32j:65+32j]''. *** Let ''kj+1 depend on whether ''kj < ej'' (lexicographically)'''Why are child elements sorted before hashing in the Merkle tree?''' By doing so, it is not necessary to reveal the left/right directions along with the hashes in revealed Merkle branches. This is possible because we do not actually care about the position of specific scripts in the tree; only that they are actually committed to.: @@ -81,7 +81,7 @@ The following rules only apply when such an output is being spent. Any other out ** If ''t ≥ 0xFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141'' (order of secp256k1), fail. ** Let ''Q = point(q) if (c[0] & 1) = 1 and -point(q) otherwise''. Fail if this point is not on the curve. ** If ''Q ≠ P + int(t)G'', fail. -** Execute the script, according to the applicable script rules'''What are the applicable script rules in script path spends?''' Bip-tapscript specifies validity rules that apply if the leaf version is ''0xc0'', but future proposals can introduce rules for other leaf versions., using the witness stack elements excluding the script ''s'', the control block ''c'', and the annex ''a'' if present, as initial stack. +** Execute the script, according to the applicable script rules'''What are the applicable script rules in script path spends?''' Bip-tapscript specifies validity rules that apply if the leaf version is 0, but future proposals can introduce rules for other leaf versions., using the witness stack elements excluding the script ''s'', the control block ''c'', and the annex ''a'' if present, as initial stack. ''q'' is referred to as ''taproot output key'' and ''p'' as ''taproot internal key''. @@ -209,7 +209,7 @@ The following function, taproot_output_script, returns a byte array def taproot_tree_helper(script_tree): if isinstance(script_tree, tuple): leaf_version, script = script_tree - h = tagged_hash("TapLeaf", bytes([leaf_version]) + ser_script(script)) + h = tagged_hash("TapLeaf", bytes([(2 * leaf_version) ^ 0xc0]) + ser_script(script)) return ([((leaf_version, script), bytes())], h) left, left_h = taproot_tree_helper(script_tree[0]) right, right_h = taproot_tree_helper(script_tree[1]) @@ -221,8 +221,8 @@ def taproot_tree_helper(script_tree): def taproot_output_script(internal_pubkey, script_tree): """Given a internal public key and a tree of scripts, compute the output script. script_tree is either: - - a (leaf_version, script) tuple (leaf_version is 0xc0 for bip-tapscript scripts) - - a list of two elements, each with the same structure as script_tree itself + - a (leaf_version, script) tuple (leaf_version is 0 for bip-tapscript scripts) + - a list of two elements, each with the same structure as script_tree itself""" - None """ if script_tree is None: @@ -271,7 +271,7 @@ def taproot_sign_script(internal_pubkey, script_tree, script_num, inputs): (leaf_version, script), path = info[script_num] _, is_negated = taproot_tweak_pubkey(internal_pubkey, h) output_pubkey_tag = 0 if is_negated else 1 - pubkey_data = bytes([output_pubkey_tag + leaf_version]) + internal_pubkey + pubkey_data = bytes([output_pubkey_tag ^ (2 * leaf_version) ^ 0xc0]) + internal_pubkey return inputs + [script, pubkey_data + path] diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index 759d0d8..120a617 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -51,7 +51,7 @@ The rules below only apply when validating a transaction input for which all of * The transaction input is a '''segregated witness spend''' (i.e., the scriptPubKey contains a witness program as defined in [https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki BIP141]). * It is a '''taproot spend''' as defined in bip-taproot (i.e., the witness version is 1, the witness program is 32 bytes, and it is not P2SH wrapped). * It is a '''script path spend''' as defined in bip-taproot (i.e., after removing the optional annex from the witness stack, two or more stack elements remain). -* The leaf version is ''0xc0'' (i.e. the first byte of the last witness element after removing the optional annex is ''0xc0'' or ''0xc1'')'''How is the ''0xc0'' constant chosen?''' Following the guidelines in bip-taproot, by choosing a value having the two top bits set, tapscript spends are identifiable even without access to the UTXO being spent., marking it as a '''tapscript spend'''. +* The leaf version is 0 (i.e. the first byte of the last witness element after removing the optional annex is ''0xc0'' or ''0xc1''), marking it as a '''tapscript spend'''. Validation of such inputs must be equivalent to performing the following steps in the specified order. # If the input is invalid due to BIP141 or bip-taproot, fail. -- cgit v1.2.3 From 1e99e205a84b73b4d95870aae09d9d81140065e0 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Fri, 10 Jan 2020 21:42:34 +1000 Subject: go back to leaf_version but different rationale --- bip-taproot.mediawiki | 24 ++++++++++-------------- bip-tapscript.mediawiki | 2 +- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 2b91da8..7d2318e 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -59,19 +59,15 @@ The following rules only apply when such an output is being spent. Any other out * Let ''q'' be the 32-byte array containing the witness program (the second push in the scriptPubKey) which represents a public key according to bip-schnorr. * Fail if the witness stack has 0 elements. -* If there are at least two witness elements, and the first byte of the last element is 0x50'''Why is the first byte of the annex 0x50?''' Like the choice to always set the top two bits of the control block's first byte the, 0x50 is chosen as it could not be confused with a valid P2WPKH or P2WSH spending. As the control block's initial byte's lowest bit is used to indicate the public key's Y squareness, each leaf version needs two subsequent byte values that are both not yet used in P2WPKH or P2WSH spending. To indicate the annex, only an "unpaired" available byte is necessary like 0x50. This choice maximizes the available options for future script versions., this last element is called ''annex'' ''a'''''What is the purpose of the annex?''' The annex is a reserved space for future extensions, such as indicating the validation costs of computationally expensive new opcodes in a way that is recognizable without knowing the scriptPubKey of the output being spent. Until the meaning of this field is defined by another softfork, users SHOULD NOT include annex in transactions, or it may lead to PERMANENT FUND LOSS. and is removed from the witness stack. The annex (or the lack of thereof) is always covered by the transaction digest and contributes to transaction weight, but is otherwise ignored during taproot validation. +* If there are at least two witness elements, and the first byte of the last element is 0x50'''Why is the first byte of the annex 0x50?''' The 0x50 is chosen as it could not be confused with a valid P2WPKH or P2WSH spending. As the control block's initial byte's lowest bit is used to indicate the public key's Y squareness, each leaf version needs an even byte value and the immediately following odd byte value that are both not yet used in P2WPKH or P2WSH spending. To indicate the annex, only an "unpaired" available byte is necessary like 0x50. This choice maximizes the available options for future script versions., this last element is called ''annex'' ''a'''''What is the purpose of the annex?''' The annex is a reserved space for future extensions, such as indicating the validation costs of computationally expensive new opcodes in a way that is recognizable without knowing the scriptPubKey of the output being spent. Until the meaning of this field is defined by another softfork, users SHOULD NOT include annex in transactions, or it may lead to PERMANENT FUND LOSS. and is removed from the witness stack. The annex (or the lack of thereof) is always covered by the transaction digest and contributes to transaction weight, but is otherwise ignored during taproot validation. * If there is exactly one element left in the witness stack, key path spending is used: ** The single witness stack element is interpreted as the signature and must be valid (see the next section) for the public key ''q'' and taproot transaction digest (to be defined hereinafter) as message. Fail if it is not. Otherwise pass. * If there are at least two witness elements left, script path spending is used: ** Call the second-to-last stack element ''s'', the script. ** The last stack element is called the control block ''c'', and must have length ''33 + 32m'', for a value of ''m'' that is an integer between 0 and 128'''Why is the Merkle path length limited to 128?''' The optimally space-efficient Merkle tree can be constructed based on the probabilities of the scripts in the leaves, using the Huffman algorithm. This algorithm will construct branches with lengths approximately equal to ''log2(1/probability)'', but to have branches longer than 128 you would need to have scripts with an execution chance below 1 in ''2128''. As that is our security bound, scripts that truly have such a low chance can probably be removed entirely., inclusive. Fail if it does not have such a length. ** Let ''p = c[1:33]'' and let ''P = point(p)'' where ''point'' and ''[:]'' are defined as in bip-schnorr. Fail if this point is not on the curve. -** Call ''(c[0] ^ 0xc0) >> 1'' the leaf version'''What is the purpose of the first byte of the control block?''' The first byte of the control block has three distinct functions: -* The low bit is used to denote whether the point represented by public key ''q'' is negated before verifying the taproot tweak.'''Why is it necessary to reveal a bit to indicate if the point represented by the output public key is negated in a script path spend?''' The ''point'' function (defined in bip-schnorr) always constructs a point with a square Y coordinate, but because ''Q'' is constructed by adding the taproot tweak to the internal public key ''P'', it cannot easily be guaranteed that ''Q'' in fact has such a Y coordinate. Therefore, before verifying the taproot tweak the original point is restored by negating if necessary. We can not ignore the Y coordinate because it would prevent batch verification. Trying out multiple internal keys until there's such a ''Q'' is possible but undesirable and unnecessary since this information about the Y coordinate only consumes an unused bit. -* Some types of static analysis may benefit from the ability to analyse spends without access to the output being spent. We achieve that for leaf versions 0 to 31 via flipping the top two bits of the first byte of the control block and observing that this ensures they can be distinguished from P2WPKH and P2WSH spends -- as for P2WPKH, the last witness stack item is a public key, whose first byte is either 0x02 or 0x03, and for P2WSH, the last item is a script, and scripts must contain valid opcodes, but no value ≥ 0xc0 is a valid opcode. -* The remaining five bits encode the leaf version, which can be used for introducing new script versions that are not observable unless actually executed. -. -** Let ''k0 = hashTapLeaf(c[0] & 0xfe || compact_size(size of s) || s)''; also call it the ''tapleaf hash''. +** Let ''v = c[0] & 0xfe'' and call it the ''leaf version'''''What constraints are there on the leaf version?''' First, the leaf version cannot be odd as ''c[0] & 0xfe'' will always be even, and cannot be ''0x50'' as that would result in ambiguity with the annex. In addition, in order to support some forms of static analysis that rely on being able to identify script spends without access to the output being spent, it is recommended to avoid using any leaf versions that would conflict with a valid first byte of either a valid P2WPKH pubkey or a valid P2WSH script (that is, both ''v'' and ''v | 1'' should be an undefined, invalid or disabled opcode or an opcode that is not valid as the first opcode). The values that comply to this rule are the 32 even values between ''0xc0'' and ''0xfe'' and also ''0x66'', ''0x7e'', ''0x80'', ''0x84'', ''0x96'', ''0x98'', ''0xba'', ''0xbc'', ''0xbe''. Note also that this constraint implies that leaf versions should be shared amongst different witness versions, as knowing the witness version requires access to the output being spent.. +** Let ''k0 = hashTapLeaf(v || compact_size(size of s) || s)''; also call it the ''tapleaf hash''. ** For ''j'' in ''[0,1,...,m-1]'': *** Let ''ej = c[33+32j:65+32j]''. *** Let ''kj+1 depend on whether ''kj < ej'' (lexicographically)'''Why are child elements sorted before hashing in the Merkle tree?''' By doing so, it is not necessary to reveal the left/right directions along with the hashes in revealed Merkle branches. This is possible because we do not actually care about the position of specific scripts in the tree; only that they are actually committed to.: @@ -79,9 +75,9 @@ The following rules only apply when such an output is being spent. Any other out **** If ''kj ≥ ej'': ''kj+1 = hashTapBranch(ej || kj)''. ** Let ''t = hashTapTweak(p || km)''. ** If ''t ≥ 0xFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141'' (order of secp256k1), fail. -** Let ''Q = point(q) if (c[0] & 1) = 1 and -point(q) otherwise''. Fail if this point is not on the curve. +** Let ''Q = point(q) if (c[0] & 1) = 1 and -point(q) otherwise'''''Why is it necessary to reveal a bit to indicate if the point represented by the output public key is negated in a script path spend?''' The ''point'' function (defined in bip-schnorr) always constructs a point with a square Y coordinate, but because ''Q'' is constructed by adding the taproot tweak to the internal public key ''P'', it cannot easily be guaranteed that ''Q'' in fact has such a Y coordinate. Therefore, before verifying the taproot tweak the original point is restored by negating if necessary. We can not ignore the Y coordinate because it would prevent batch verification. Trying out multiple internal keys until there's such a ''Q'' is possible but undesirable and unnecessary since this information about the Y coordinate only consumes an unused bit.. Fail if this point is not on the curve. ** If ''Q ≠ P + int(t)G'', fail. -** Execute the script, according to the applicable script rules'''What are the applicable script rules in script path spends?''' Bip-tapscript specifies validity rules that apply if the leaf version is 0, but future proposals can introduce rules for other leaf versions., using the witness stack elements excluding the script ''s'', the control block ''c'', and the annex ''a'' if present, as initial stack. +** Execute the script, according to the applicable script rules'''What are the applicable script rules in script path spends?''' Bip-tapscript specifies validity rules that apply for leaf version 0xc0, but future proposals can introduce rules for other leaf versions., using the witness stack elements excluding the script ''s'', the control block ''c'', and the annex ''a'' if present, as initial stack. ''q'' is referred to as ''taproot output key'' and ''p'' as ''taproot internal key''. @@ -209,7 +205,7 @@ The following function, taproot_output_script, returns a byte array def taproot_tree_helper(script_tree): if isinstance(script_tree, tuple): leaf_version, script = script_tree - h = tagged_hash("TapLeaf", bytes([(2 * leaf_version) ^ 0xc0]) + ser_script(script)) + h = tagged_hash("TapLeaf", bytes([leaf_version]) + ser_script(script)) return ([((leaf_version, script), bytes())], h) left, left_h = taproot_tree_helper(script_tree[0]) right, right_h = taproot_tree_helper(script_tree[1]) @@ -221,8 +217,8 @@ def taproot_tree_helper(script_tree): def taproot_output_script(internal_pubkey, script_tree): """Given a internal public key and a tree of scripts, compute the output script. script_tree is either: - - a (leaf_version, script) tuple (leaf_version is 0 for bip-tapscript scripts) - - a list of two elements, each with the same structure as script_tree itself""" + - a (leaf_version, script) tuple (leaf_version is 0xc0 for bip-tapscript scripts) + - a list of two elements, each with the same structure as script_tree itself - None """ if script_tree is None: @@ -237,7 +233,7 @@ def taproot_output_script(internal_pubkey, script_tree): To spend this output using script ''D'', the control block would contain the following data in this order: - + The TapTweak would then be computed as described in [[#script-validation-rules]] like so: @@ -271,7 +267,7 @@ def taproot_sign_script(internal_pubkey, script_tree, script_num, inputs): (leaf_version, script), path = info[script_num] _, is_negated = taproot_tweak_pubkey(internal_pubkey, h) output_pubkey_tag = 0 if is_negated else 1 - pubkey_data = bytes([output_pubkey_tag ^ (2 * leaf_version) ^ 0xc0]) + internal_pubkey + pubkey_data = bytes([output_pubkey_tag + leaf_version]) + internal_pubkey return inputs + [script, pubkey_data + path] diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index 120a617..e9c4278 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -51,7 +51,7 @@ The rules below only apply when validating a transaction input for which all of * The transaction input is a '''segregated witness spend''' (i.e., the scriptPubKey contains a witness program as defined in [https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki BIP141]). * It is a '''taproot spend''' as defined in bip-taproot (i.e., the witness version is 1, the witness program is 32 bytes, and it is not P2SH wrapped). * It is a '''script path spend''' as defined in bip-taproot (i.e., after removing the optional annex from the witness stack, two or more stack elements remain). -* The leaf version is 0 (i.e. the first byte of the last witness element after removing the optional annex is ''0xc0'' or ''0xc1''), marking it as a '''tapscript spend'''. +* The leaf version is ''0xc0'' (i.e. the first byte of the last witness element after removing the optional annex is ''0xc0'' or ''0xc1''), marking it as a '''tapscript spend'''. Validation of such inputs must be equivalent to performing the following steps in the specified order. # If the input is invalid due to BIP141 or bip-taproot, fail. -- cgit v1.2.3 From cd8ea889875e6072db5b39821ac4f3fa0e139cb5 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 13 Jan 2020 07:27:18 -0800 Subject: Delete precompiled file --- bip-schnorr/__pycache__/reference.cpython-36.pyc | Bin 5278 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 bip-schnorr/__pycache__/reference.cpython-36.pyc diff --git a/bip-schnorr/__pycache__/reference.cpython-36.pyc b/bip-schnorr/__pycache__/reference.cpython-36.pyc deleted file mode 100644 index cce1e04..0000000 Binary files a/bip-schnorr/__pycache__/reference.cpython-36.pyc and /dev/null differ -- cgit v1.2.3 From d9ec5f43da4d6f79b96d585204e6652cca7016b4 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 13 Jan 2020 14:39:32 -0800 Subject: Update acknowledgements, remove authors --- bip-schnorr.mediawiki | 2 +- bip-taproot.mediawiki | 5 ++--- bip-tapscript.mediawiki | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki index 084b33f..fbfd408 100644 --- a/bip-schnorr.mediawiki +++ b/bip-schnorr.mediawiki @@ -257,4 +257,4 @@ The reference implementation is for demonstration purposes only and not to be us == Acknowledgements == -This document is the result of many discussions around Schnorr based signatures over the years, and had input from Johnson Lau, Greg Maxwell, Jonas Nick, Andrew Poelstra, Tim Ruffing, Rusty Russell, and Anthony Towns. +This document is the result of many discussions around Schnorr based signatures over the years, and had input from Johnson Lau, Greg Maxwell, Andrew Poelstra, Rusty Russell, and Anthony Towns. The authors further wish to thank all those who provided valuable feedback and reviews, including the participants of the [https://github.com/ajtowns/taproot-review structured reviews]. diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 7d2318e..d11f936 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -313,7 +313,6 @@ Depending on the implementation non-upgraded wallets may be able to send to Segw == Acknowledgements == -This document is the result of discussions around script and signature improvements with many people, and had direct contributions from Jonas Nick, Anthony Towns, Greg Maxwell, and others. It further builds on top of earlier published proposals such as Taproot by Greg Maxwell, and Merkle branch constructions by Russell O'Connor, Johnson Lau, and Mark Friedenbach. - -Thanks to Arik Sosman for suggesting to sort Merkle node children before hashes, removing the need to transfer the position in the tree. +This document is the result of discussions around script and signature improvements with many people, and had direct contributions from Greg Maxwell and others. It further builds on top of earlier published proposals such as Taproot by Greg Maxwell, and Merkle branch constructions by Russell O'Connor, Johnson Lau, and Mark Friedenbach. +The authors wish the thank Arik Sosman for suggesting to sort Merkle node children before hashes, removing the need to transfer the position in the tree, as well as all those who provided valuable feedback and reviews, including the participants of the [https://github.com/ajtowns/taproot-review structured reviews]. diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index e9c4278..ed729c7 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -143,4 +143,4 @@ In addition to changing the semantics of a number of opcodes, there are also som ==Acknowledgements== -This document is the result of many discussions and contains contributions by Jonas Nick, Anthony Towns, and others. +This document is the result of many discussions and contains contributions by a number of people. The authors wish to thank all those who provided valuable feedback and reviews, including the participants of the [https://github.com/ajtowns/taproot-review structured reviews]. -- cgit v1.2.3 From 57ed6cb342a36209b9ab479ed9084e47c287af33 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 13 Jan 2020 14:10:26 -0800 Subject: Abstract out common signature message calculation --- bip-taproot.mediawiki | 87 +++++++++++++++++++++++-------------------------- bip-tapscript.mediawiki | 32 ++++++++---------- 2 files changed, 53 insertions(+), 66 deletions(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index d11f936..8a51747 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -83,68 +83,61 @@ The following rules only apply when such an output is being spent. Any other out === Signature validation rules === -The following rules apply: +We first define a reusable common signature message calculation function, followed by the actual signature validation as it's used in key path spending. -* If the signature is not 64'''Why permit two signature lengths?''' By making the most common type of hash_type implicit, a byte can often be saved. or 65 bytes, fail. -* If the signature size is 65 bytes: -** If the final byte is not a valid hash_type (defined hereinafter), fail. -** If the final byte is 0x00, fail'''Why can the hash_type not be 0x00 in 65-byte signatures?''' Permitting that would enable malleating (by third parties, including miners) 64-byte signatures into 65-byte ones, resulting in a different `wtxid` and a different fee rate than the creator intended. -** If the first 64 bytes are not a valid signature according to bip-schnorr for the public key and message set to the transaction digest with hash_type set as the final byte, fail. -* If the signature size is 64 bytes: -** If it is not a valid signature according to bip-schnorr for the public key and the hash_type = 0x00 transaction digest as message, fail. -* Otherwise the signature is valid. +==== Common signature message ==== -==== hash_type ==== - -hash_type is an 8-bit unsigned value. The SIGHASH encodings from the legacy script system are used, including SIGHASH_ALL, SIGHASH_NONE, SIGHASH_SINGLE, and SIGHASH_ANYONECANPAY. Use of the default hash_type = 0x00 results in signing over the whole transaction just as for SIGHASH_ALL. - -The following use of hash_type are invalid, and fail execution: +The function ''SigMsg(hash_type, ext_flag)'' computes the message being signed as a byte array. It is implicitly also a function of the spending transaction and the outputs it spends, but these are not listed to keep notation simple. +The parameter ''hash_type'' is an 8-bit unsigned value. The SIGHASH encodings from the legacy script system are reused, including SIGHASH_ALL, SIGHASH_NONE, SIGHASH_SINGLE, and SIGHASH_ANYONECANPAY, plus a default ''hash_type'' (0) which results in signing over the whole transaction just as for SIGHASH_ALL. The following restrictions apply, which cause validation failure if violated: +* Using any undefined ''hash_type'' (not ''0x00'', ''0x01'', ''0x02'', ''0x03'', ''0x81'', ''0x82'', or ''0x83'''''Why reject unknown ''hash_type'' values?''' By doing so, it is easier to reason about the worst case amount of signature hashing an implementation with adequate caching must perform.). * Using SIGHASH_SINGLE without a "corresponding output" (an output with the same index as the input being verified). -* Using any hash_type value that is not 0x00, 0x01, 0x02, 0x03, 0x81, 0x82, or 0x83'''Why reject unknown hash_type values?''' By doing so, it is easier to reason about the worst case amount of signature hashing an implementation with adequate caching must perform.. -* The signature has 65 bytes, and hash_type is 0x00. -==== Transaction digest ==== +The parameter ''ext_flag'' is an integer in range 0-127, and is used for indicating the presence of extensions. -As the message for signature verification, transaction digest is ''hashTapSighash'' of the following values (size in byte) serialized. Numerical values in 2, 4, or 8-byte are encoded in little-endian. +If the parameters take acceptable values, the message is the concatenation of the following data, in order(with byte size of each item listed in parentheses). Numerical values in 2, 4, or 8-byte are encoded in little-endian. * Control: -** epoch (1): always 0. '''What's the purpose of the epoch?''' The epoch can be increased to allow securely creating new transaction digest algorithms with large changes to the structure or interpretation of hash_type if needed. -** hash_type (1). +** ''hash_type'' (1). * Transaction data: -** nVersion (4): the nVersion of the transaction. -** nLockTime (4): the nLockTime of the transaction. -** If the SIGHASH_ANYONECANPAY flag is not set: -*** sha_prevouts (32): the SHA256 of the serialization of all input outpoints. -*** sha_amounts (32): the SHA256 of the serialization of all input amounts. -*** sha_sequences (32): the SHA256 of the serialization of all input nSequence. -** If neither the SIGHASH_NONE nor the SIGHASH_SINGLE flag is set: -*** sha_outputs (32): the SHA256 of the serialization of all outputs in CTxOut format. +** ''nVersion'' (4): the ''nVersion'' of the transaction. +** ''nLockTime'' (4): the ''nLockTime'' of the transaction. +** If the ''hash_type & 0x80'' does not equal SIGHASH_ANYONECANPAY: +*** ''sha_prevouts'' (32): the SHA256 of the serialization of all input outpoints. +*** ''sha_amounts'' (32): the SHA256 of the serialization of all input amounts. +*** ''sha_sequences'' (32): the SHA256 of the serialization of all input ''nSequence''. +** If ''hash_type & 3'' does not equal SIGHASH_NONE or SIGHASH_SINGLE: +*** ''sha_outputs'' (32): the SHA256 of the serialization of all outputs in CTxOut format. * Data about this input: -** spend_type (1): -*** Bit 0 is set if an annex is present (the original witness stack has two or more witness elements, and the first byte of the last element is 0x50). -*** The other bits are unset. -** scriptPubKey (35): scriptPubKey of the previous output spent by this input, serialized as script inside CTxOut. Its size is always 35 bytes. -** If the SIGHASH_ANYONECANPAY flag is set: -*** outpoint (36): the COutPoint of this input (32-byte hash + 4-byte little-endian). -*** amount (8): value of the previous output spent by this input. -*** nSequence (4): nSequence of this input. -** If the SIGHASH_ANYONECANPAY flag is not set: -*** input_index (4): index of this input in the transaction input vector. Index of the first input is 0. -** If bit 0 of spend_type is set: -*** sha_annex (32): the SHA256 of (compact_size(size of annex) || annex). +** ''spend_type'' (1): equal to ''(ext_flag * 2) + annex_present'', where ''annex_present'' is 0 if no annex is present, or 1 otherwise (the original witness stack has two or more witness elements, and the first byte of the last element is ''0x50'') +** ''scriptPubKey'' (35): ''scriptPubKey'' of the previous output spent by this input, serialized as script inside CTxOut. Its size is always 35 bytes. +** If ''hash_type & 0x80'' equals SIGHASH_ANYONECANPAY: +*** ''outpoint'' (36): the COutPoint of this input (32-byte hash + 4-byte little-endian). +*** ''amount'' (8): value of the previous output spent by this input. +*** ''nSequence'' (4): ''nSequence'' of this input. +** If ''hash_type & 0x80'' does not equal SIGHASH_ANYONECANPAY: +*** ''input_index'' (4): index of this input in the transaction input vector. Index of the first input is 0. +** If an annex is present (the lowest bit of ''spend_type'' is set): +*** ''sha_annex'' (32): the SHA256 of ''(compact_size(size of annex) || annex)'', where ''annex'' includes the mandatory ''0x50'' prefix. * Data about this output: -** If the SIGHASH_SINGLE flag is set: -*** sha_single_output (32): the SHA256 of the corresponding output in CTxOut format. +** If ''hash_type & 3'' equals SIGHASH_SINGLE: +*** ''sha_single_output'' (32): the SHA256 of the corresponding output in CTxOut format. -The total number of bytes hashed is at most ''210'' (excluding sub-hashes such as `sha_prevouts`)'''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''178 - is_anyonecanpay * 52 - is_none * 32 + has_annex * 32''.. Sub-hashes may be cached across signatures of the same transaction. +The total length of ''SigMsg()'' is at most ''209'' bytes'''What is the output length of ''SigMsg()''?''' The total length of ''SigMsg()'' can be computed using the following formula: ''177 - is_anyonecanpay * 52 - is_none * 32 + has_annex * 32''.. Note that this does not include the size of sub-hashes such as ''sha_prevouts'', which may be cached across signatures of the same transaction. In summary, the semantics of the [https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki BIP143] sighash types remain unchanged, except the following: -# The way and order of serialization is changed.'''Why is the serialization in the transaction digest changed?''' Hashes that go into the digest and the digest itself are now computed with a single SHA256 invocation instead of double SHA256. There is no expected security improvement by doubling SHA256 because this only protects against length-extension attacks against SHA256 which are not a concern for transaction digests because there is no secret data. Therefore doubling SHA256 is a waste of resources. The digest computation now follows a logical order with transaction level data first, then input data and output data. This allows to efficiently cache the transaction part of the digest across different inputs using the SHA256 midstate. Additionally, sub-hashes can be skipped when calculating the digest (for example `sha_prevouts` if SIGHASH_ANYONECANPAY is set) instead of setting them to zero and then hashing them as in BIP143. Despite that, collisions are made impossible by committing to the length of the data (implicit in hash_type and spend_type) before the variable length data. -# The digest commits to the scriptPubKey'''Why does the transaction digest commit to the scriptPubKey?''' This prevents lying to offline signing devices about output being spent, even when the actually executed script (scriptCode in BIP143) is correct. This means it's possible to compactly prove to a hardware wallet what (unused) execution paths existed.. +# The way and order of serialization is changed.'''Why is the serialization in the transaction digest changed?''' Hashes that go into the digest and the digest itself are now computed with a single SHA256 invocation instead of double SHA256. There is no expected security improvement by doubling SHA256 because this only protects against length-extension attacks against SHA256 which are not a concern for transaction digests because there is no secret data. Therefore doubling SHA256 is a waste of resources. The digest computation now follows a logical order with transaction level data first, then input data and output data. This allows to efficiently cache the transaction part of the digest across different inputs using the SHA256 midstate. Additionally, sub-hashes can be skipped when calculating the digest (for example `sha_prevouts` if SIGHASH_ANYONECANPAY is set) instead of setting them to zero and then hashing them as in BIP143. Despite that, collisions are made impossible by committing to the length of the data (implicit in ''hash_type'' and ''spend_type'') before the variable length data. +# The digest commits to the ''scriptPubKey'''''Why does the transaction digest commit to the ''scriptPubKey''?''' This prevents lying to offline signing devices about output being spent, even when the actually executed script (''scriptCode'' in BIP143) is correct. This means it's possible to compactly prove to a hardware wallet what (unused) execution paths existed.. # If the SIGHASH_ANYONECANPAY flag is not set, the digest commits to the amounts of ''all'' transaction inputs.'''Why does the transaction digest commit to the amounts of all transaction inputs?''' This eliminates the possibility to lie to offline signing devices about the fee of a transaction. -# The digest commits to all input nSequence if SIGHASH_NONE or SIGHASH_SINGLE are set (unless SIGHASH_ANYONECANPAY is set as well).'''Why does the transaction digest commit to all input nSequence if SIGHASH_SINGLE or SIGHASH_NONE are set?''' Because setting them already makes the digest commit to the prevouts part of all transaction inputs, it is not useful to treat the nSequence any different. Moreover, this change makes nSequence consistent with the view that SIGHASH_SINGLE and SIGHASH_NONE only modify the digest with respect to transaction outputs and not inputs. -# The digest commits to taproot-specific data epoch, spend_type and annex (if present). +# The digest commits to all input ''nSequence'' if SIGHASH_NONE or SIGHASH_SINGLE are set (unless SIGHASH_ANYONECANPAY is set as well).'''Why does the transaction digest commit to all input ''nSequence'' if SIGHASH_SINGLE or SIGHASH_NONE are set?''' Because setting them already makes the digest commit to the prevouts part of all transaction inputs, it is not useful to treat the ''nSequence'' any different. Moreover, this change makes ''nSequence'' consistent with the view that SIGHASH_SINGLE and SIGHASH_NONE only modify the digest with respect to transaction outputs and not inputs. +# The message includes commitments to the taproot-specific data ''spend_type'' and ''annex'' (if present). + +==== Taproot key path spending signature validation ==== + +To validate a signature ''sig'' with public key ''q'': +* If the ''sig'' is 64 bytes long, return ''Verify(q, hashTapSigHash(0x00 || SigMsg(0x00, 0)), sig)'''''Why is the input to ''hashTapSigHash'' prefixed with 0x00?''' This prefix is called the sighash epoch, and allows reusing the ''hashTapSigHash'' tagged hash in future extensions that make invasive changes to how hashing is performed. An alternative is switching to a different tag, but supporting a growing number of tags may become undesirable., where ''Verify'' is defined in bip-schnorr. +* If the ''sig'' is 65 bytes long, return ''sig[64] ≠ 0x00'''Why can the hash_type not be 0x00 in 65-byte signatures?''' Permitting that would enable malleating (by third parties, including miners) 64-byte signatures into 65-byte ones, resulting in a different `wtxid` and a different fee rate than the creator intended and Verify(q, hashTapSighash(0x00 || SigMsg(sig[64], 0)), sig[0:64])''. +* Otherwise, fail'''Why permit two signature lengths?''' By making the most common type of hash_type implicit, a byte can often be saved.. == Constructing and spending Taproot outputs == diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index ed729c7..3bbe8f3 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -92,7 +92,7 @@ The following rules apply to OP_CHECKSIG, OP_CHECKSIGVERIFYn is larger than 4 bytes, the script MUST fail and terminate immediately. * If the public key size is zero, the script MUST fail and terminate immediately. * If the public key size is 32 bytes, it is considered to be a public key as described in bip-schnorr: -** If the signature is not the empty vector, the signature is validated according to the bip-taproot signature validation rules against the public key and the tapscript transaction digest (to be defined hereinafter) as message. Validation failure MUST cause the script to fail and terminate immediately. +** If the signature is not the empty vector, the signature is validated against the public key (see the next subsection). * If the public key size is not zero and not 32 bytes, the public key is of an ''unknown public key type'''''Unknown public key types''' allow adding new signature validation rules through softforks. A softfork could add actual signature validation which either passes or makes the script fail and terminate immediately. This way, new SIGHASH modes can be added, as well as [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-December/016549.html NOINPUT-tagged public keys] and a public key constant which is replaced by the taproot internal key for signature validation. and no actual signature verification is applied. During script execution of signature opcodes they behave exactly as known public key types except that signature validation is considered to be successful. * If the script did not fail and terminate before this step, regardless of the public key type: ** If the signature is the empty vector: @@ -104,26 +104,20 @@ The following rules apply to OP_CHECKSIG, OP_CHECKSIGVERIFYOP_CHECKSIG, a 1-byte value 0x01 is pushed onto the stack. *** For OP_CHECKSIGADD, a CScriptNum with value of n + 1 is pushed onto the stack. -===Transaction digest=== +===Signature validation=== -As the message for signature opcodes signature verification, transaction digest has the same definition as in bip-taproot, except the following: +To validate a signature ''sig'' with public key ''p'': +* Compute the tapscript message extension ''ext'', consisting of: +** ''tapleaf_hash'' (32): the tapleaf hash as defined in bip-taproot +** ''key_version'' (1): a constant value ''0x00'' representing the current version of public keys in the tapscript signature opcode execution. +** ''codesep_pos'' (4): the opcode position of the last executed OP_CODESEPARATOR before the currently executed signature opcode, with the value in little endian (or ''0xffffffff'' if none executed). The first opcode in a script has a position of 0. A multi-byte push opcode is counted as one opcode, regardless of the size of data being pushed. +* If the ''sig'' is 64 bytes long, return ''Verify(q, hashTapSigHash(0x00 || SigMsg(0x00, 1) || ext), sig)'', where ''Verify'' is defined in bip-schnorr. +* If the ''sig'' is 65 bytes long, return ''sig[64] ≠ 0x00 and Verify(q, hashTapSighash(0x00 || SigMsg(sig[64], 0) || ext), sig[0:64])''. +* Otherwise, fail. -The one-byte spend_type has a different value, specifically at bit 1: -* Bit 0 is set if an annex is present (the original witness stack has at least two witness elements, and the first byte of the last element is 0x50). -* Bit 1 is set. -* The other bits are unset. - -As additional pieces of data, added at the end of the input to the ''hashTapSighash'' function: -* tapleaf_hash (32): the tapleaf hash as defined in bip-taproot -* key_version (1): a constant value 0x00 representing the current version of public keys in the tapscript signature opcode execution. -* codeseparator_position (4): the opcode position of the last executed OP_CODESEPARATOR before the currently executed signature opcode, with the value in little endian (or 0xffffffff if none executed). The first opcode in a script has a position of 0. A multi-byte push opcode is counted as one opcode, regardless of the size of data being pushed. - -The total number of bytes hashed is at most ''247'''''What is the number of bytes hashed for the signature hash?''' The total size of the input to ''hashTapSighash'' (excluding the initial 64-byte hash tag) can be computed using the following formula: ''215 - is_anyonecanpay * 52 - is_none * 32 + has_annex * 32''.. - -In summary, the semantics of the [https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki BIP143] sighash types remain unchanged, except the following: -# The exceptions mentioned in bip-taproot. -# The digest commits to taproot-specific data key_version.'''Why does the transaction digest commit to the key_version?''' This is for future extensions that define unknown public key types, making sure signatures can't be moved from one key type to another. -# The digest commits to the executed script through the tapleaf_hash which includes the leaf version and script instead of scriptCode. This implies that this commitment is unaffected by OP_CODESEPARATOR. +In summary, the semantics of signature validation is identical to bip-taproot, except the following: +# The digest commits to tapscript-specific data ''key_version''.'''Why does the transaction digest commit to the ''key_version''?''' This is for future extensions that define unknown public key types, making sure signatures can't be moved from one key type to another. +# The digest commits to the executed script through the ''tapleaf_hash'' which includes the leaf version and script instead of ''scriptCode''. This implies that this commitment is unaffected by OP_CODESEPARATOR. # The digest commits to the opcode position of the last executed OP_CODESEPARATOR.'''Why does the transaction digest commit to the position of the last executed OP_CODESEPARATOR?''' This allows continuing to use OP_CODESEPARATOR to sign the executed path of the script. Because the codeseparator_position is the last input to the digest, the SHA256 midstate can be efficiently cached for multiple OP_CODESEPARATORs in a single script. In contrast, the BIP143 handling of OP_CODESEPARATOR is to commit to the executed script only from the last executed OP_CODESEPARATOR onwards which requires unnecessary rehashing of the script. It should be noted that the one known OP_CODESEPARATOR use case of saving a second public key push in a script by sharing the first one between two code branches can be most likely expressed even cheaper by moving each branch into a separate taproot leaf. ===Resource limits=== -- cgit v1.2.3 From 1faa4b19bcfaec44a964a665f68a5bdaba85337e Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sun, 19 Jan 2020 14:05:36 -0800 Subject: Rename BIPs --- bip-0340.mediawiki | 260 ++++++++++++++++++++++++++++++++++++ bip-0340/reference.py | 169 +++++++++++++++++++++++ bip-0340/test-vectors.csv | 16 +++ bip-0340/test-vectors.py | 241 +++++++++++++++++++++++++++++++++ bip-0341.mediawiki | 311 +++++++++++++++++++++++++++++++++++++++++++ bip-0341/tree.png | Bin 0 -> 78937 bytes bip-0342.mediawiki | 140 +++++++++++++++++++ bip-schnorr.mediawiki | 260 ------------------------------------ bip-schnorr/reference.py | 169 ----------------------- bip-schnorr/test-vectors.csv | 16 --- bip-schnorr/test-vectors.py | 241 --------------------------------- bip-taproot.mediawiki | 311 ------------------------------------------- bip-taproot/tree.png | Bin 78937 -> 0 bytes bip-tapscript.mediawiki | 140 ------------------- 14 files changed, 1137 insertions(+), 1137 deletions(-) create mode 100644 bip-0340.mediawiki create mode 100644 bip-0340/reference.py create mode 100644 bip-0340/test-vectors.csv create mode 100644 bip-0340/test-vectors.py create mode 100644 bip-0341.mediawiki create mode 100644 bip-0341/tree.png create mode 100644 bip-0342.mediawiki delete mode 100644 bip-schnorr.mediawiki delete mode 100644 bip-schnorr/reference.py delete mode 100644 bip-schnorr/test-vectors.csv delete mode 100644 bip-schnorr/test-vectors.py delete mode 100644 bip-taproot.mediawiki delete mode 100644 bip-taproot/tree.png delete mode 100644 bip-tapscript.mediawiki diff --git a/bip-0340.mediawiki b/bip-0340.mediawiki new file mode 100644 index 0000000..6a431fe --- /dev/null +++ b/bip-0340.mediawiki @@ -0,0 +1,260 @@ +
+  BIP: 340
+  Title: Schnorr Signatures for secp256k1
+  Author: Pieter Wuille 
+          Jonas Nick 
+          Tim Ruffing 
+  Status: Draft
+  Type: Informational
+  License: BSD-2-Clause
+  Post-History: 2018-07-06: https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-July/016203.html [bitcoin-dev] Schnorr signatures BIP
+
+ +== Introduction == + +=== Abstract === + +This document proposes a standard for 64-byte Schnorr signatures over the elliptic curve ''secp256k1''. + +=== Copyright === + +This document is licensed under the 2-clause BSD license. + +=== Motivation === + +Bitcoin has traditionally used +[https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm ECDSA] signatures over the [https://www.secg.org/sec2-v2.pdf secp256k1 curve] with [https://en.wikipedia.org/wiki/SHA-2 SHA256] hashes for authenticating +transactions. These are [https://www.secg.org/sec1-v2.pdf standardized], but have a number of downsides +compared to [http://publikationen.ub.uni-frankfurt.de/opus4/files/4280/schnorr.pdf Schnorr signatures] over the same curve: + +* '''Provable security''': Schnorr signatures are provably secure. In more detail, they are ''strongly unforgeable under chosen message attack (SUF-CMA)''Informally, this means that without knowledge of the secret key but given valid signatures of arbitrary messages, it is not possible to come up with further valid signatures. [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf in the random oracle model assuming the hardness of the elliptic curve discrete logarithm problem (ECDLP)] and [http://www.neven.org/papers/schnorr.pdf in the generic group model assuming variants of preimage and second preimage resistance of the used hash function]A detailed security proof in the random oracle model, which essentially restates [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf the original security proof by Pointcheval and Stern] more explicitly, can be found in [https://eprint.iacr.org/2016/191 a paper by Kiltz, Masny and Pan]. All these security proofs assume a variant of Schnorr signatures that use ''(e,s)'' instead of ''(R,s)'' (see Design above). Since we use a unique encoding of ''R'', there is an efficiently computable bijection that maps ''(R,s)'' to ''(e,s)'', which allows to convert a successful SUF-CMA attacker for the ''(e,s)'' variant to a successful SUF-CMA attacker for the ''(R,s)'' variant (and vice-versa). Furthermore, the proofs consider a variant of Schnorr signatures without key prefixing (see Design above), but it can be verified that the proofs are also correct for the variant with key prefixing. As a result, all the aforementioned security proofs apply to the variant of Schnorr signatures proposed in this document.. In contrast, the [https://nbn-resolving.de/urn:nbn:de:hbz:294-60803 best known results for the provable security of ECDSA] rely on stronger assumptions. +* '''Non-malleability''': The SUF-CMA security of Schnorr signatures implies that they are non-malleable. On the other hand, ECDSA signatures are inherently malleableIf ''(r,s)'' is a valid ECDSA signature for a given message and key, then ''(r,n-s)'' is also valid for the same message and key. If ECDSA is restricted to only permit one of the two variants (as Bitcoin does through a policy rule on the network), it can be [https://nbn-resolving.de/urn:nbn:de:hbz:294-60803 proven] non-malleable under stronger than usual assumptions.; a third party without access to the secret key can alter an existing valid signature for a given public key and message into another signature that is valid for the same key and message. This issue is discussed in [bip-0062.mediawiki BIP62] and [bip-0146.mediawiki BIP146]. +* '''Linearity''': Schnorr signatures provide a simple and efficient method that enables multiple collaborating parties to produce a signature that is valid for the sum of their public keys. This is the building block for various higher-level constructions that improve efficiency and privacy, such as multisignatures and others (see Applications below). + +For all these advantages, there are virtually no disadvantages, apart +from not being standardized. This document seeks to change that. As we +propose a new standard, a number of improvements not specific to Schnorr signatures can be +made: + +* '''Signature encoding''': Instead of using [https://en.wikipedia.org/wiki/X.690#DER_encoding DER]-encoding for signatures (which are variable size, and up to 72 bytes), we can use a simple fixed 64-byte format. +* '''Public key encoding''': Instead of using ''compressed'' 33-byte encodings of elliptic curve points which are common in Bitcoin today, public keys in this proposal are encoded as 32 bytes. +* '''Batch verification''': The specific formulation of ECDSA signatures that is standardized cannot be verified more efficiently in batch compared to individually, unless additional witness data is added. Changing the signature scheme offers an opportunity to address this. +* '''Completely specified''': To be safe for usage in consensus systems, the verification algorithm must be completely specified at the byte level. This guarantees that nobody can construct a signature that is valid to some verifiers but not all. This is traditionally not a requirement for digital signature schemes, and the lack of exact specification for the DER parsing of ECDSA signatures has caused problems for Bitcoin [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2015-July/009697.html in the past], needing [https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki BIP66] to address it. In this document we aim to meet this property by design. For batch verification, which is inherently non-deterministic as the verifier can choose their batches, this property implies that the outcome of verification may only differ from individual verifications with negligible probability, even to an attacker who intentionally tries to make batch- and non-batch verification differ. + +By reusing the same curve and hash function as Bitcoin uses for ECDSA, we are able to retain existing mechanisms for choosing secret and public keys, and we avoid introducing new assumptions about the security of elliptic curves and hash functions. + +== Description == + +We first build up the algebraic formulation of the signature scheme by +going through the design choices. Afterwards, we specify the exact +encodings and operations. + +=== Design === + +'''Schnorr signature variant''' Elliptic Curve Schnorr signatures for message ''m'' and public key ''P'' generally involve a point ''R'', integers ''e'' and ''s'' picked by the signer, and the base point ''G'' which satisfy ''e = hash(R || m)'' and ''s⋅G = R + e⋅P''. Two formulations exist, depending on whether the signer reveals ''e'' or ''R'': +# Signatures are pairs ''(e, s)'' that satisfy ''e = hash(s⋅G - e⋅P || m)''. This variant avoids minor complexity introduced by the encoding of the point ''R'' in the signature (see paragraphs "Encoding R and public key point P" and "Implicit Y coordinates" further below in this subsection). Moreover, revealing ''e'' instead of ''R'' allows for potentially shorter signatures: Whereas an encoding of ''R'' inherently needs about 32 bytes, the hash ''e'' can be tuned to be shorter than 32 bytes, and [http://www.neven.org/papers/schnorr.pdf a short hash of only 16 bytes suffices to provide SUF-CMA security at the target security level of 128 bits]. However, a major drawback of this optimization is that finding collisions in a short hash function is easy. This complicates the implementation of secure signing protocols in scenarios in which a group of mutually distrusting signers work together to produce a single joint signature (see Applications below). In these scenarios, which are not captured by the SUF-CMA model due its assumption of a single honest signer, a promising attack strategy for malicious co-signers is to find a collision in the hash function in order to obtain a valid signature on a message that an honest co-signer did not intent to sign. +# Signatures are pairs ''(R, s)'' that satisfy ''s⋅G = R + hash(R || m)⋅P''. This supports batch verification, as there are no elliptic curve operations inside the hashes. Batch verification enables significant speedups. + +[[File:bip-0340/speedup-batch.png|center|frame|This graph shows the ratio between the time it takes to verify ''n'' signatures individually and to verify a batch of ''n'' signatures. This ratio goes up logarithmically with the number of signatures, or in other words: the total time to verify ''n'' signatures grows with ''O(n / log n)''.]] + +Since we would like to avoid the fragility that comes with short hashes, the ''e'' variant does not provide significant advantages. We choose the ''R''-option, which supports batch verification. + +'''Key prefixing''' Using the verification rule above directly makes Schnorr signatures vulnerable to "related-key attacks" in which a third party can convert a signature ''(R, s)'' for public key ''P'' into a signature ''(R, s + a⋅hash(R || m))'' for public key ''P + a⋅G'' and the same message ''m'', for any given additive tweak ''a'' to the signing key. This would render signatures insecure when keys are generated using [bip-0032.mediawiki#public-parent-key--public-child-key BIP32's unhardened derivation] and other methods that rely on additive tweaks to existing keys such as Taproot. + +To protect against these attacks, we choose ''key prefixed''A limitation of committing to the public key (rather than to a short hash of it, or not at all) is that it removes the ability for public key recovery or verifying signatures against a short public key hash. These constructions are generally incompatible with batch verification. Schnorr signatures; changing the equation to ''s⋅G = R + hash(R || P || m)⋅P''. [https://eprint.iacr.org/2015/1135.pdf It can be shown] that key prefixing protects against related-key attacks with additive tweaks. In general, key prefixing increases robustness in multi-user settings, e.g., it seems to be a requirement for proving the MuSig multisignature scheme secure (see Applications below). + +We note that key prefixing is not strictly necessary for transaction signatures as used in Bitcoin currently, because signed transactions indirectly commit to the public keys already, i.e., ''m'' contains a commitment to ''pk''. However, this indirect commitment should not be relied upon because it may change with proposals such as SIGHASH_NOINPUT ([bip-0118.mediawiki BIP118]), and would render the signature scheme unsuitable for other purposes than signing transactions, e.g., [https://bitcoin.org/en/developer-reference#signmessage signing ordinary messages]. + +'''Encoding R and public key point P''' There exist several possibilities for encoding elliptic curve points: +# Encoding the full X and Y coordinates of ''P'' and ''R'', resulting in a 64-byte public key and a 96-byte signature. +# Encoding the full X coordinate and one bit of the Y coordinate to determine one of the two possible Y coordinates. This would result in 33-byte public keys and 65-byte signatures. +# Encoding only the X coordinate, resulting in 32-byte public keys and 64-byte signatures. + +Using the first option would be slightly more efficient for verification (around 10%), but we prioritize compactness, and therefore choose option 3. + +'''Implicit Y coordinates''' In order to support efficient verification and batch verification, the Y coordinate of ''P'' and of ''R'' cannot be ambiguous (every valid X coordinate has two possible Y coordinates). We have a choice between several options for symmetry breaking: +# Implicitly choosing the Y coordinate that is in the lower half. +# Implicitly choosing the Y coordinate that is evenSince ''p'' is odd, negation modulo ''p'' will map even numbers to odd numbers and the other way around. This means that for a valid X coordinate, one of the corresponding Y coordinates will be even, and the other will be odd.. +# Implicitly choosing the Y coordinate that is a quadratic residue (has a square root modulo the field size, or "is a square" for short)A product of two numbers is a square when either both or none of the factors are squares. As ''-1'' is not a square modulo secp256k1's field size ''p'', and the two Y coordinates corresponding to a given X coordinate are each other's negation, this means exactly one of the two must be a square.. + +In the case of ''R'' the third option is slower at signing time but a bit faster to verify, as it is possible to directly compute whether the Y coordinate is a square when the points are represented in +[https://en.wikibooks.org/wiki/Cryptography/Prime_Curve/Jacobian_Coordinates Jacobian coordinates] (a common optimization to avoid modular inverses +for elliptic curve operations). The two other options require a possibly +expensive conversion to affine coordinates first. This would even be the case if the sign or oddness were explicitly coded (option 2 in the list above). We therefore choose option 3. + +For ''P'' the speed of signing and verification does not significantly differ between any of the three options because affine coordinates of the point have to be computed anyway. For consistency reasons we choose the same option as for ''R''. The signing algorithm ensures that the signature is valid under the correct public key by negating the secret key if necessary. + +Implicit Y coordinates are not a reduction in security when expressed as the number of elliptic curve operations an attacker is expected to perform to compute the secret key. An attacker can normalize any given public key to a point whose Y coordinate is a square by negating the point if necessary. This is just a subtraction of field elements and not an elliptic curve operationThis can be formalized by a simple reduction that reduces an attack on Schnorr signatures with implicit Y coordinates to an attack to Schnorr signatures with explicit Y coordinates. The reduction works by reencoding public keys and negating the result of the hash function, which is modeled as random oracle, whenever the challenge public key has an explicit Y coordinate that is not a square. A proof sketch can be found [https://medium.com/blockstream/reducing-bitcoin-transaction-sizes-with-x-only-pubkeys-f86476af05d7 here].. + +'''Tagged Hashes''' Cryptographic hash functions are used for multiple purposes in the specification below and in Bitcoin in general. To make sure hashes used in one context can't be reinterpreted in another one, hash functions can be tweaked with a context-dependent tag name, in such a way that collisions across contexts can be assumed to be infeasible. Such collisions obviously can not be ruled out completely, but only for schemes using tagging with a unique name. As for other schemes collisions are at least less likely with tagging than without. + +For example, without tagged hashing a BIP340 signature could also be valid for a signature scheme where the only difference is that the arguments to the hash function are reordered. Worse, if the BIP340 nonce derivation function was copied or independently created, then the nonce could be accidentally reused in the other scheme leaking the secret key. + +This proposal suggests to include the tag by prefixing the hashed data with ''SHA256(tag) || SHA256(tag)''. Because this is a 64-byte long context-specific constant and the ''SHA256'' block size is also 64 bytes, optimized implementations are possible (identical to SHA256 itself, but with a modified initial state). Using SHA256 of the tag name itself is reasonably simple and efficient for implementations that don't choose to use the optimization. + +'''Final scheme''' As a result, our final scheme ends up using public key ''pk'' which is the X coordinate of a point ''P'' on the curve whose Y coordinate is a square and signatures ''(r,s)'' where ''r'' is the X coordinate of a point ''R'' whose Y coordinate is a square. The signature satisfies ''s⋅G = R + tagged_hash(r || pk || m)⋅P''. + +=== Specification === + +The following conventions are used, with constants as defined for [https://www.secg.org/sec2-v2.pdf secp256k1]: +* Lowercase variables represent integers or byte arrays. +** The constant ''p'' refers to the field size, ''0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F''. +** The constant ''n'' refers to the curve order, ''0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141''. +* Uppercase variables refer to points on the curve with equation ''y2 = x3 + 7'' over the integers modulo ''p''. +** ''is_infinite(P)'' returns whether or not ''P'' is the point at infinity. +** ''x(P)'' and ''y(P)'' are integers in the range ''0..p-1'' and refer to the X and Y coordinates of a point ''P'' (assuming it is not infinity). +** The constant ''G'' refers to the base point, for which ''x(G) = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798'' and ''y(G) = 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8''. +** Addition of points refers to the usual [https://en.wikipedia.org/wiki/Elliptic_curve#The_group_law elliptic curve group operation]. +** [https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication Multiplication (⋅) of an integer and a point] refers to the repeated application of the group operation. +* Functions and operations: +** ''||'' refers to byte array concatenation. +** The function ''x[i:j]'', where ''x'' is a byte array, returns a ''(j - i)''-byte array with a copy of the ''i''-th byte (inclusive) to the ''j''-th byte (exclusive) of ''x''. +** The function ''bytes(x)'', where ''x'' is an integer, returns the 32-byte encoding of ''x'', most significant byte first. +** The function ''bytes(P)'', where ''P'' is a point, returns ''bytes(x(P))''. +** The function ''int(x)'', where ''x'' is a 32-byte array, returns the 256-bit unsigned integer whose most significant byte first encoding is ''x''. +** The function ''is_square(x)'', where ''x'' is an integer, returns whether or not ''x'' is a quadratic residue modulo ''p''. Since ''p'' is prime, it is equivalent to the [https://en.wikipedia.org/wiki/Legendre_symbol Legendre symbol] ''(x / p) = x(p-1)/2 mod p'' being equal to ''1''For points ''P'' on the secp256k1 curve it holds that ''y(P)(p-1)/2 ≠ 0 mod p''.. +** The function ''has_square_y(P)'', where ''P'' is a point, is defined as ''not is_infinite(P) and is_square(y(P))''For points ''P'' on the secp256k1 curve it holds that ''has_square_y(P) = not has_square_y(-P)''.. +** The function ''lift_x(x)'', where ''x'' is an integer in range ''0..p-1'', returns the point ''P'' for which ''x(P) = x'' + Given a candidate X coordinate ''x'' in the range ''0..p-1'', there exist either exactly two or exactly zero valid Y coordinates. If no valid Y coordinate exists, then ''x'' is not a valid X coordinate either, i.e., no point ''P'' exists for which ''x(P) = x''. The valid Y coordinates for a given candidate ''x'' are the square roots of ''c = x3 + 7 mod p'' and they can be computed as ''y = ±c(p+1)/4 mod p'' (see [https://en.wikipedia.org/wiki/Quadratic_residue#Prime_or_prime_power_modulus Quadratic residue]) if they exist, which can be checked by squaring and comparing with ''c''. + and ''has_square_y(P)'' + If ''P := lift_x(x)'' does not fail, then ''y := y(P) = c(p+1)/4 mod p'' is square. Proof: If ''lift_x'' does not fail, ''y'' is a square root of ''c'' and therefore the [https://en.wikipedia.org/wiki/Legendre_symbol Legendre symbol] ''(c / p)'' is ''c(p-1)/2 = 1 mod p''. Because the Legendre symbol ''(y / p)'' is ''y(p-1)/2 mod p = c((p+1)/4)((p-1)/2) mod p = 1((p+1)/4) mod p = 1 mod p'', ''y'' is square. +, or fails if no such point exists. The function ''lift_x(x)'' is equivalent to the following pseudocode: +*** Let ''c = x3 + 7 mod p''. +*** Let ''y = c(p+1)/4 mod p''. +*** Fail if ''c ≠ y2 mod p''. +*** Return the unique point ''P'' such that ''x(P) = x'' and ''y(P) = y'', or fail if no such point exists. +** The function ''point(x)'', where ''x'' is a 32-byte array, returns the point ''P = lift_x(int(x))''. +** The function ''hashtag(x)'' where ''tag'' is a UTF-8 encoded tag name and ''x'' is a byte array returns the 32-byte hash ''SHA256(SHA256(tag) || SHA256(tag) || x)''. + +==== Public Key Generation ==== + +Input: +* The secret key ''sk'': a 32-byte array, generated uniformly at random + +The algorithm ''PubKey(sk)'' is defined as: +* Let ''d = int(sk)''. +* Fail if ''d = 0'' or ''d ≥ n''. +* Return ''bytes(d⋅G)''. + +Note that we use a very different public key format (32 bytes) than the ones used by existing systems (which typically use elliptic curve points as public keys, or 33-byte or 65-byte encodings of them). A side effect is that ''PubKey(sk) = PubKey(bytes(n - int(sk))'', so every public key has two corresponding secret keys. + +As an alternative to generating keys randomly, it is also possible and safe to repurpose existing key generation algorithms for ECDSA in a compatible way. The secret keys constructed by such an algorithm can be used as ''sk'' directly. The public keys constructed by such an algorithm (assuming they use the 33-byte compressed encoding) need to be converted by dropping the first byte. Specifically, [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki BIP32] and schemes built on top of it remain usable. + +==== Default Signing ==== + +Input: +* The secret key ''sk'': a 32-byte array +* The message ''m'': a 32-byte array + +The algorithm ''Sign(sk, m)'' is defined as: +* Let ''d' = int(sk)'' +* Fail if ''d' = 0'' or ''d' ≥ n'' +* Let ''P = d'⋅G'' +* Let ''d = d' '' if ''has_square_y(P)'', otherwise let ''d = n - d' ''. +* Let ''rand = hashBIPSchnorrDerive(bytes(d) || m)''. +* Let ''k' = int(rand) mod n''Note that in general, taking a uniformly random 256-bit integer modulo the curve order will produce an unacceptably biased result. However, for the secp256k1 curve, the order is sufficiently close to ''2256'' that this bias is not observable (''1 - n / 2256'' is around ''1.27 * 2-128'').. +* Fail if ''k' = 0''. +* Let ''R = k'⋅G''. +* Let ''k = k' '' if ''has_square_y(R)'', otherwise let ''k = n - k' ''. +* Let ''e = int(hashBIPSchnorr(bytes(R) || bytes(P) || m)) mod n''. +* Return the signature ''bytes(R) || bytes((k + ed) mod n)''. + +==== Alternative Signing ==== + +It should be noted that various alternative signing algorithms can be used to produce equally valid signatures. The algorithm in the previous section is deterministic, i.e., it will always produce the same signature for a given message and secret key. This method does not need a random number generator (RNG) at signing time and is thus trivially robust against failures of RNGs. Alternatively the 32-byte ''rand'' value may be generated in other ways, producing a different but still valid signature (in other words, this is not a ''unique'' signature scheme). '''No matter which method is used to generate the ''rand'' value, the value must be a fresh uniformly random 32-byte string which is not even partially predictable for the attacker.''' + +'''Synthetic nonces''' For instance when a RNG is available, 32 bytes of RNG output can be appended to the input to ''hashBIPSchnorrDerive''. This will change the corresponding line in the signing algorithm to ''rand = hashBIPSchnorrDerive(bytes(d) || m || get_32_bytes_from_rng())'', where ''get_32_bytes_from_rng()'' is the call to the RNG. Adding RNG output may improve protection against [https://moderncrypto.org/mail-archive/curves/2017/000925.html fault injection attacks and side-channel attacks], and it is safe to add the output of a low-entropy RNG. + +'''Nonce exfiltration protection''' It is possible to strengthen the nonce generation algorithm using a second device. In this case, the second device contributes randomness which the actual signer provably incorporates into its nonce. This prevents certain attacks where the signer device is compromised and intentionally tries to leak the secret key through its nonce selection. + +'''Multisignatures''' This signature scheme is compatible with various types of multisignature and threshold schemes such as [https://eprint.iacr.org/2018/068 MuSig], where a single public key requires holders of multiple secret keys to participate in signing (see Applications below). +'''It is important to note that multisignature signing schemes in general are insecure with the ''rand'' generation from the default signing algorithm above (or any other deterministic method).''' + +==== Verification ==== + +Input: +* The public key ''pk'': a 32-byte array +* The message ''m'': a 32-byte array +* A signature ''sig'': a 64-byte array + +The algorithm ''Verify(pk, m, sig)'' is defined as: +* Let ''P = point(pk)''; fail if ''point(pk)'' fails. +* Let ''r = int(sig[0:32])''; fail if ''r ≥ p''. +* Let ''s = int(sig[32:64])''; fail if ''s ≥ n''. +* Let ''e = int(hashBIPSchnorr(bytes(r) || bytes(P) || m)) mod n''. +* Let ''R = s⋅G - e⋅P''. +* Fail if ''not has_square_y(R)'' or ''x(R) ≠ r''. +* Return success iff no failure occurred before reaching this point. + +For every valid secret key ''sk'' and message ''m'', ''Verify(PubKey(sk),m,Sign(sk,m))'' will succeed. + +Note that the correctness of verification relies on the fact that ''point(pk)'' always returns a point with a square Y coordinate. A hypothetical verification algorithm that treats points as public keys, and takes the point ''P'' directly as input would fail any time a point with non-square Y is used. While it is possible to correct for this by negating points with non-square Y coordinate before further processing, this would result in a scheme where every (message, signature) pair is valid for two public keys (a type of malleability that exists for ECDSA as well, but we don't wish to retain). We avoid these problems by treating just the X coordinate as public key. + +==== Batch Verification ==== + +Input: +* The number ''u'' of signatures +* The public keys ''pk1..u'': ''u'' 32-byte arrays +* The messages ''m1..u'': ''u'' 32-byte arrays +* The signatures ''sig1..u'': ''u'' 64-byte arrays + +The algorithm ''BatchVerify(pk1..u, m1..u, sig1..u)'' is defined as: +* Generate ''u-1'' random integers ''a2...u'' in the range ''1...n-1''. They are generated deterministically using a [https://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator CSPRNG] seeded by a cryptographic hash of all inputs of the algorithm, i.e. ''seed = seed_hash(pk1..pku || m1..mu || sig1..sigu )''. A safe choice is to instantiate ''seed_hash'' with SHA256 and use [https://tools.ietf.org/html/rfc8439 ChaCha20] with key ''seed'' as a CSPRNG to generate 256-bit integers, skipping integers not in the range ''1...n-1''. +* For ''i = 1 .. u'': +** Let ''Pi = point(pki)''; fail if ''point(pki)'' fails. +** Let ''ri = int(sigi[0:32])''; fail if ''ri ≥ p''. +** Let ''si = int(sigi[32:64])''; fail if ''si ≥ n''. +** Let ''ei = int(hashBIPSchnorr(bytes(ri) || bytes(Pi) || mi)) mod n''. +** Let ''Ri = lift_x(ri)''; fail if ''lift_x(ri)'' fails. +* Fail if ''(s1 + a2s2 + ... + ausu)⋅G ≠ R1 + a2⋅R2 + ... + au⋅Ru + e1⋅P1 + (a2e2)⋅P2 + ... + (aueu)⋅Pu''. +* Return success iff no failure occurred before reaching this point. + +If all individual signatures are valid (i.e., ''Verify'' would return success for them), ''BatchVerify'' will always return success. If at least one signature is invalid, ''BatchVerify'' will return success with at most a negligible probability. + +=== Optimizations === + +Many techniques are known for optimizing elliptic curve implementations. Several of them apply here, but are out of scope for this document. Two are listed below however, as they are relevant to the design decisions: + +'''Squareness testing''' The function ''is_square(x)'' is defined as above, but can be computed more efficiently using an [https://en.wikipedia.org/wiki/Jacobi_symbol#Calculating_the_Jacobi_symbol extended GCD algorithm]. + +'''Jacobian coordinates''' Elliptic Curve operations can be implemented more efficiently by using [https://en.wikibooks.org/wiki/Cryptography/Prime_Curve/Jacobian_Coordinates Jacobian coordinates]. Elliptic Curve operations implemented this way avoid many intermediate modular inverses (which are computationally expensive), and the scheme proposed in this document is in fact designed to not need any inversions at all for verification. When operating on a point ''P'' with Jacobian coordinates ''(x,y,z)'' which is not the point at infinity and for which ''x(P)'' is defined as ''x / z2'' and ''y(P)'' is defined as ''y / z3'': +* ''has_square_y(P)'' can be implemented as ''is_square(yz mod p)''. +* ''x(P) ≠ r'' can be implemented as ''(0 ≤ r < p) and (x ≠ z2r mod p)''. + +== Applications == + +There are several interesting applications beyond simple signatures. +While recent academic papers claim that they are also possible with ECDSA, consensus support for Schnorr signature verification would significantly simplify the constructions. + +=== Multisignatures and Threshold Signatures === + +By means of an interactive scheme such as [https://eprint.iacr.org/2018/068 MuSig], participants can aggregate their public keys into a single public key which they can jointly sign for. This allows ''n''-of-''n'' multisignatures which, from a verifier's perspective, are no different from ordinary signatures, giving improved privacy and efficiency versus ''CHECKMULTISIG'' or other means. + +Moreover, Schnorr signatures are compatible with [https://web.archive.org/web/20031003232851/http://www.research.ibm.com/security/dkg.ps distributed key generation], which enables interactive threshold signatures schemes, e.g., the schemes described by [http://cacr.uwaterloo.ca/techreports/2001/corr2001-13.ps Stinson and Strobl (2001)] or [https://web.archive.org/web/20060911151529/http://theory.lcs.mit.edu/~stasio/Papers/gjkr03.pdf Genaro, Jarecki and Krawczyk (2003)]. These protocols make it possible to realize ''k''-of-''n'' threshold signatures, which ensure that any subset of size ''k'' of the set of ''n'' signers can sign but no subset of size less than ''k'' can produce a valid Schnorr signature. However, the practicality of the existing schemes is limited: most schemes in the literature have been proven secure only for the case ''k-1 < n/2'', are not secure when used concurrently in multiple sessions, or require a reliable broadcast mechanism to be secure. Further research is necessary to improve this situation. + +=== Adaptor Signatures === + +[https://download.wpsoftware.net/bitcoin/wizardry/mw-slides/2018-05-18-l2/slides.pdf Adaptor signatures] can be produced by a signer by offsetting his public nonce with a known point ''T = t⋅G'', but not offsetting his secret nonce. +A correct signature (or partial signature, as individual signers' contributions to a multisignature are called) on the same message with same nonce will then be equal to the adaptor signature offset by ''t'', meaning that learning ''t'' is equivalent to learning a correct signature. +This can be used to enable atomic swaps or even [https://eprint.iacr.org/2018/472 general payment channels] in which the atomicity of disjoint transactions is ensured using the signatures themselves, rather than Bitcoin script support. The resulting transactions will appear to verifiers to be no different from ordinary single-signer transactions, except perhaps for the inclusion of locktime refund logic. + +Adaptor signatures, beyond the efficiency and privacy benefits of encoding script semantics into constant-sized signatures, have additional benefits over traditional hash-based payment channels. Specifically, the secret values ''t'' may be reblinded between hops, allowing long chains of transactions to be made atomic while even the participants cannot identify which transactions are part of the chain. Also, because the secret values are chosen at signing time, rather than key generation time, existing outputs may be repurposed for different applications without recourse to the blockchain, even multiple times. + +=== Blind Signatures === + +A blind signature protocol is an interactive protocol that enables a signer to sign a message at the behest of another party without learning any information about the signed message or the signature. Schnorr signatures admit a very [https://www.math.uni-frankfurt.de/~dmst/research/papers/schnorr.blind_sigs_attack.2001.pdf simple blind signature scheme] which is however insecure because it's vulnerable to [https://www.iacr.org/archive/crypto2002/24420288/24420288.pdf Wagner's attack]. A known mitigation is to let the signer abort a signing session with a certain probability, and the resulting scheme can be [https://eprint.iacr.org/2019/877 proven secure under non-standard cryptographic assumptions]. + +Blind Schnorr signatures could for example be used in [https://github.com/ElementsProject/scriptless-scripts/blob/master/md/partially-blind-swap.md Partially Blind Atomic Swaps], a construction to enable transferring of coins, mediated by an untrusted escrow agent, without connecting the transactors in the public blockchain transaction graph. + +== Test Vectors and Reference Code == + +For development and testing purposes, we provide a [[bip-0340/test-vectors.csv|collection of test vectors in CSV format]] and a naive, highly inefficient, and non-constant time [[bip-0340/reference.py|pure Python 3.7 reference implementation of the signing and verification algorithm]]. +The reference implementation is for demonstration purposes only and not to be used in production environments. + +== Footnotes == + + + +== Acknowledgements == + +This document is the result of many discussions around Schnorr based signatures over the years, and had input from Johnson Lau, Greg Maxwell, Andrew Poelstra, Rusty Russell, and Anthony Towns. The authors further wish to thank all those who provided valuable feedback and reviews, including the participants of the [https://github.com/ajtowns/taproot-review structured reviews]. diff --git a/bip-0340/reference.py b/bip-0340/reference.py new file mode 100644 index 0000000..f2a944f --- /dev/null +++ b/bip-0340/reference.py @@ -0,0 +1,169 @@ +import hashlib +import binascii + +p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F +n = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 + +# Points are tuples of X and Y coordinates and the point at infinity is +# represented by the None keyword. +G = (0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798, 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8) + +# This implementation can be sped up by storing the midstate after hashing +# tag_hash instead of rehashing it all the time. +def tagged_hash(tag, msg): + tag_hash = hashlib.sha256(tag.encode()).digest() + return hashlib.sha256(tag_hash + tag_hash + msg).digest() + +def is_infinity(P): + return P is None + +def x(P): + return P[0] + +def y(P): + return P[1] + +def point_add(P1, P2): + if (P1 is None): + return P2 + if (P2 is None): + return P1 + if (x(P1) == x(P2) and y(P1) != y(P2)): + return None + if (P1 == P2): + lam = (3 * x(P1) * x(P1) * pow(2 * y(P1), p - 2, p)) % p + else: + lam = ((y(P2) - y(P1)) * pow(x(P2) - x(P1), p - 2, p)) % p + x3 = (lam * lam - x(P1) - x(P2)) % p + return (x3, (lam * (x(P1) - x3) - y(P1)) % p) + +def point_mul(P, n): + R = None + for i in range(256): + if ((n >> i) & 1): + R = point_add(R, P) + P = point_add(P, P) + return R + +def bytes_from_int(x): + return x.to_bytes(32, byteorder="big") + +def bytes_from_point(P): + return bytes_from_int(x(P)) + +def point_from_bytes(b): + x = int_from_bytes(b) + if x >= p: + return None + y_sq = (pow(x, 3, p) + 7) % p + y = pow(y_sq, (p + 1) // 4, p) + if pow(y, 2, p) != y_sq: + return None + return [x, y] + +def int_from_bytes(b): + return int.from_bytes(b, byteorder="big") + +def hash_sha256(b): + return hashlib.sha256(b).digest() + +def is_square(x): + return pow(x, (p - 1) // 2, p) == 1 + +def has_square_y(P): + return not is_infinity(P) and is_square(y(P)) + +def pubkey_gen(seckey): + x = int_from_bytes(seckey) + if not (1 <= x <= n - 1): + raise ValueError('The secret key must be an integer in the range 1..n-1.') + P = point_mul(G, x) + return bytes_from_point(P) + +def schnorr_sign(msg, seckey0): + if len(msg) != 32: + raise ValueError('The message must be a 32-byte array.') + seckey0 = int_from_bytes(seckey0) + if not (1 <= seckey0 <= n - 1): + raise ValueError('The secret key must be an integer in the range 1..n-1.') + P = point_mul(G, seckey0) + seckey = seckey0 if has_square_y(P) else n - seckey0 + k0 = int_from_bytes(tagged_hash("BIPSchnorrDerive", bytes_from_int(seckey) + msg)) % n + if k0 == 0: + raise RuntimeError('Failure. This happens only with negligible probability.') + R = point_mul(G, k0) + k = n - k0 if not has_square_y(R) else k0 + e = int_from_bytes(tagged_hash("BIPSchnorr", bytes_from_point(R) + bytes_from_point(P) + msg)) % n + return bytes_from_point(R) + bytes_from_int((k + e * seckey) % n) + +def schnorr_verify(msg, pubkey, sig): + if len(msg) != 32: + raise ValueError('The message must be a 32-byte array.') + if len(pubkey) != 32: + raise ValueError('The public key must be a 32-byte array.') + if len(sig) != 64: + raise ValueError('The signature must be a 64-byte array.') + P = point_from_bytes(pubkey) + if (P is None): + return False + r = int_from_bytes(sig[0:32]) + s = int_from_bytes(sig[32:64]) + if (r >= p or s >= n): + return False + e = int_from_bytes(tagged_hash("BIPSchnorr", sig[0:32] + pubkey + msg)) % n + R = point_add(point_mul(G, s), point_mul(P, n - e)) + if R is None or not has_square_y(R) or x(R) != r: + return False + return True + +# +# The following code is only used to verify the test vectors. +# +import csv + +def test_vectors(): + all_passed = True + with open('test-vectors.csv', newline='') as csvfile: + reader = csv.reader(csvfile) + reader.__next__() + for row in reader: + (index, seckey, pubkey, msg, sig, result, comment) = row + pubkey = bytes.fromhex(pubkey) + msg = bytes.fromhex(msg) + sig = bytes.fromhex(sig) + result = result == 'TRUE' + print('\nTest vector #%-3i: ' % int(index)) + if seckey != '': + seckey = bytes.fromhex(seckey) + pubkey_actual = pubkey_gen(seckey) + if pubkey != pubkey_actual: + print(' * Failed key generation.') + print(' Expected key:', pubkey.hex().upper()) + print(' Actual key:', pubkey_actual.hex().upper()) + sig_actual = schnorr_sign(msg, seckey) + if sig == sig_actual: + print(' * Passed signing test.') + else: + print(' * Failed signing test.') + print(' Expected signature:', sig.hex().upper()) + print(' Actual signature:', sig_actual.hex().upper()) + all_passed = False + result_actual = schnorr_verify(msg, pubkey, sig) + if result == result_actual: + print(' * Passed verification test.') + else: + print(' * Failed verification test.') + print(' Expected verification result:', result) + print(' Actual verification result:', result_actual) + if comment: + print(' Comment:', comment) + all_passed = False + print() + if all_passed: + print('All test vectors passed.') + else: + print('Some test vectors failed.') + return all_passed + +if __name__ == '__main__': + test_vectors() diff --git a/bip-0340/test-vectors.csv b/bip-0340/test-vectors.csv new file mode 100644 index 0000000..3970803 --- /dev/null +++ b/bip-0340/test-vectors.csv @@ -0,0 +1,16 @@ +index,secret key,public key,message,signature,verification result,comment +0,0000000000000000000000000000000000000000000000000000000000000001,79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798,0000000000000000000000000000000000000000000000000000000000000000,528F745793E8472C0329742A463F59E58F3A3F1A4AC09C28F6F8514D4D0322A258BD08398F82CF67B812AB2C7717CE566F877C2F8795C846146978E8F04782AE,TRUE, +1,B7E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEF,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,667C2F778E0616E611BD0C14B8A600C5884551701A949EF0EBFD72D452D64E844160BCFC3F466ECB8FACD19ADE57D8699D74E7207D78C6AEDC3799B52A8E0598,TRUE, +2,C90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B14E5C9,DD308AFEC5777E13121FA72B9CC1B7CC0139715309B086C960E18FD969774EB8,5E2D58D8B3BCDF1ABADEC7829054F90DDA9805AAB56C77333024B9D0A508B75C,2D941B38E32624BF0AC7669C0971B990994AF6F9B18426BF4F4E7EC10E6CDF386CF646C6DDAFCFA7F1993EEB2E4D66416AEAD1DDAE2F22D63CAD901412D116C6,TRUE, +3,0B432B2677937381AEF05BB02A66ECD012773062CF3FA2549E44F58ED2401710,25D1DFF95105F5253C4022F628A996AD3A0D95FBF21D468A1B33F8C160D8F517,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,8BD2C11604B0A87A443FCC2E5D90E5328F934161B18864FB48CE10CB59B45FB9B5B2A0F129BD88F5BDC05D5C21E5C57176B913002335784F9777A24BD317CD36,TRUE,test fails if msg is reduced modulo p or n +4,,D69C3509BB99E412E68B0FE8544E72837DFA30746D8BE2AA65975F29D22DC7B9,4DF3C3F68FCC83B27E9D42C90431A72499F17875C81A599B566C9889B9696703,00000000000000000000003B78CE563F89A0ED9414F5AA28AD0D96D6795F9C63EE374AC7FAE927D334CCB190F6FB8FD27A2DDC639CCEE46D43F113A4035A2C7F,TRUE, +5,,EEFDEA4CDB677750A420FEE807EACF21EB9898AE79B9768766E4FAA04A2D4A34,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,667C2F778E0616E611BD0C14B8A600C5884551701A949EF0EBFD72D452D64E844160BCFC3F466ECB8FACD19ADE57D8699D74E7207D78C6AEDC3799B52A8E0598,FALSE,public key not on the curve +6,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9935554D1AA5F0374E5CDAACB3925035C7C169B27C4426DF0A6B19AF3BAEAB138,FALSE,has_square_y(R) is false +7,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,10AC49A6A2EBF604189C5F40FC75AF2D42D77DE9A2782709B1EB4EAF1CFE9108D7003B703A3499D5E29529D39BA040A44955127140F81A8A89A96F992AC0FE79,FALSE,negated message +8,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,667C2F778E0616E611BD0C14B8A600C5884551701A949EF0EBFD72D452D64E84BE9F4303C0B9913470532E6521A827951D39F5C631CFD98CE39AC4D7A5A83BA9,FALSE,negated s value +9,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,000000000000000000000000000000000000000000000000000000000000000099D2F0EBC2996808208633CD9926BF7EC3DAB73DAAD36E85B3040A698E6D1CE0,FALSE,sG - eP is infinite. Test fails in single verification if has_square_y(inf) is defined as true and x(inf) as 0 +10,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,000000000000000000000000000000000000000000000000000000000000000124E81D89F01304695CE943F7D5EBD00EF726A0864B4FF33895B4E86BEADC5456,FALSE,sG - eP is infinite. Test fails in single verification if has_square_y(inf) is defined as true and x(inf) as 1 +11,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,4A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1D4160BCFC3F466ECB8FACD19ADE57D8699D74E7207D78C6AEDC3799B52A8E0598,FALSE,sig[0:32] is not an X coordinate on the curve +12,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F4160BCFC3F466ECB8FACD19ADE57D8699D74E7207D78C6AEDC3799B52A8E0598,FALSE,sig[0:32] is equal to field size +13,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,667C2F778E0616E611BD0C14B8A600C5884551701A949EF0EBFD72D452D64E84FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141,FALSE,sig[32:64] is equal to curve order +14,,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC30,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,667C2F778E0616E611BD0C14B8A600C5884551701A949EF0EBFD72D452D64E844160BCFC3F466ECB8FACD19ADE57D8699D74E7207D78C6AEDC3799B52A8E0598,FALSE,public key is not a valid X coordinate because it exceeds the field size diff --git a/bip-0340/test-vectors.py b/bip-0340/test-vectors.py new file mode 100644 index 0000000..195b61b --- /dev/null +++ b/bip-0340/test-vectors.py @@ -0,0 +1,241 @@ +import sys +from reference import * + +def vector0(): + seckey = bytes_from_int(1) + msg = bytes_from_int(0) + sig = schnorr_sign(msg, seckey) + pubkey = pubkey_gen(seckey) + + # The point reconstructed from the public key has an even Y coordinate. + pubkey_point = point_from_bytes(pubkey) + assert(pubkey_point[1] & 1 == 0) + + return (seckey, pubkey, msg, sig, "TRUE", None) + +def vector1(): + seckey = bytes_from_int(0xB7E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEF) + msg = bytes_from_int(0x243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89) + sig = schnorr_sign(msg, seckey) + pubkey = pubkey_gen(seckey) + + # The point reconstructed from the public key has an odd Y coordinate. + pubkey_point = point_from_bytes(pubkey) + assert(pubkey_point[1] & 1 == 1) + + return (seckey, pubkey, msg, sig, "TRUE", None) + +def vector2(): + seckey = bytes_from_int(0xC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B14E5C9) + msg = bytes_from_int(0x5E2D58D8B3BCDF1ABADEC7829054F90DDA9805AAB56C77333024B9D0A508B75C) + sig = schnorr_sign(msg, seckey) + + # This signature vector would not verify if the implementer checked the + # squareness of the X coordinate of R instead of the Y coordinate. + R = point_from_bytes(sig[0:32]) + assert(not is_square(R[0])) + + return (seckey, pubkey_gen(seckey), msg, sig, "TRUE", None) + +def vector3(): + seckey = bytes_from_int(0x0B432B2677937381AEF05BB02A66ECD012773062CF3FA2549E44F58ED2401710) + msg = bytes_from_int(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) + sig = schnorr_sign(msg, seckey) + return (seckey, pubkey_gen(seckey), msg, sig, "TRUE", "test fails if msg is reduced modulo p or n") + +# Signs with a given nonce. This can be INSECURE and is only INTENDED FOR +# GENERATING TEST VECTORS. Results in an invalid signature if y(kG) is not +# square. +def insecure_schnorr_sign_fixed_nonce(msg, seckey0, k): + if len(msg) != 32: + raise ValueError('The message must be a 32-byte array.') + seckey0 = int_from_bytes(seckey0) + if not (1 <= seckey0 <= n - 1): + raise ValueError('The secret key must be an integer in the range 1..n-1.') + P = point_mul(G, seckey0) + seckey = seckey0 if has_square_y(P) else n - seckey0 + R = point_mul(G, k) + e = int_from_bytes(tagged_hash("BIPSchnorr", bytes_from_point(R) + bytes_from_point(P) + msg)) % n + return bytes_from_point(R) + bytes_from_int((k + e * seckey) % n) + +# Creates a singature with a small x(R) by using k = 1/2 +def vector4(): + one_half = 0x7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0 + seckey = bytes_from_int(0x763758E5CBEEDEE4F7D3FC86F531C36578933228998226672F13C4F0EBE855EB) + msg = bytes_from_int(0x4DF3C3F68FCC83B27E9D42C90431A72499F17875C81A599B566C9889B9696703) + sig = insecure_schnorr_sign_fixed_nonce(msg, seckey, one_half) + return (None, pubkey_gen(seckey), msg, sig, "TRUE", None) + +default_seckey = bytes_from_int(0xB7E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEF) +default_msg = bytes_from_int(0x243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89) + +# Public key is not on the curve +def vector5(): + # This creates a dummy signature that doesn't have anything to do with the + # public key. + seckey = default_seckey + msg = default_msg + sig = schnorr_sign(msg, seckey) + + pubkey = bytes_from_int(0xEEFDEA4CDB677750A420FEE807EACF21EB9898AE79B9768766E4FAA04A2D4A34) + assert(point_from_bytes(pubkey) is None) + + return (None, pubkey, msg, sig, "FALSE", "public key not on the curve") + +def vector6(): + seckey = default_seckey + msg = default_msg + k = 3 + sig = insecure_schnorr_sign_fixed_nonce(msg, seckey, k) + + # Y coordinate of R is not a square + R = point_mul(G, k) + assert(not has_square_y(R)) + + return (None, pubkey_gen(seckey), msg, sig, "FALSE", "has_square_y(R) is false") + +def vector7(): + seckey = default_seckey + msg = int_from_bytes(default_msg) + neg_msg = bytes_from_int(n - msg) + sig = schnorr_sign(neg_msg, seckey) + return (None, pubkey_gen(seckey), bytes_from_int(msg), sig, "FALSE", "negated message") + +def vector8(): + seckey = default_seckey + msg = default_msg + sig = schnorr_sign(msg, seckey) + sig = sig[0:32] + bytes_from_int(n - int_from_bytes(sig[32:64])) + return (None, pubkey_gen(seckey), msg, sig, "FALSE", "negated s value") + +def bytes_from_point_inf0(P): + if P == None: + return bytes_from_int(0) + return bytes_from_int(P[0]) + +def vector9(): + seckey = default_seckey + msg = default_msg + + # Override bytes_from_point in schnorr_sign to allow creating a signature + # with k = 0. + k = 0 + bytes_from_point_tmp = bytes_from_point.__code__ + bytes_from_point.__code__ = bytes_from_point_inf0.__code__ + sig = insecure_schnorr_sign_fixed_nonce(msg, seckey, k) + bytes_from_point.__code__ = bytes_from_point_tmp + + return (None, pubkey_gen(seckey), msg, sig, "FALSE", "sG - eP is infinite. Test fails in single verification if has_square_y(inf) is defined as true and x(inf) as 0") + +def bytes_from_point_inf1(P): + if P == None: + return bytes_from_int(1) + return bytes_from_int(P[0]) + +def vector10(): + seckey = default_seckey + msg = default_msg + + # Override bytes_from_point in schnorr_sign to allow creating a signature + # with k = 0. + k = 0 + bytes_from_point_tmp = bytes_from_point.__code__ + bytes_from_point.__code__ = bytes_from_point_inf1.__code__ + sig = insecure_schnorr_sign_fixed_nonce(msg, seckey, k) + bytes_from_point.__code__ = bytes_from_point_tmp + + return (None, pubkey_gen(seckey), msg, sig, "FALSE", "sG - eP is infinite. Test fails in single verification if has_square_y(inf) is defined as true and x(inf) as 1") + +# It's cryptographically impossible to create a test vector that fails if run +# in an implementation which merely misses the check that sig[0:32] is an X +# coordinate on the curve. This test vector just increases test coverage. +def vector11(): + seckey = default_seckey + msg = default_msg + sig = schnorr_sign(msg, seckey) + + # Replace R's X coordinate with an X coordinate that's not on the curve + x_not_on_curve = bytes_from_int(0x4A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1D) + assert(point_from_bytes(x_not_on_curve) is None) + sig = x_not_on_curve + sig[32:64] + + return (None, pubkey_gen(seckey), msg, sig, "FALSE", "sig[0:32] is not an X coordinate on the curve") + +# It's cryptographically impossible to create a test vector that fails if run +# in an implementation which merely misses the check that sig[0:32] is smaller +# than the field size. This test vector just increases test coverage. +def vector12(): + seckey = default_seckey + msg = default_msg + sig = schnorr_sign(msg, seckey) + + # Replace R's X coordinate with an X coordinate that's equal to field size + sig = bytes_from_int(p) + sig[32:64] + + return (None, pubkey_gen(seckey), msg, sig, "FALSE", "sig[0:32] is equal to field size") + +# It's cryptographically impossible to create a test vector that fails if run +# in an implementation which merely misses the check that sig[32:64] is smaller +# than the curve order. This test vector just increases test coverage. +def vector13(): + seckey = default_seckey + msg = default_msg + sig = schnorr_sign(msg, seckey) + + # Replace s with a number that's equal to the curve order + sig = sig[0:32] + bytes_from_int(n) + + return (None, pubkey_gen(seckey), msg, sig, "FALSE", "sig[32:64] is equal to curve order") + +# Test out of range pubkey +# It's cryptographically impossible to create a test vector that fails if run +# in an implementation which accepts out of range pubkeys because we can't find +# a secret key for such a public key and therefore can not create a signature. +# This test vector just increases test coverage. +def vector14(): + # This creates a dummy signature that doesn't have anything to do with the + # public key. + seckey = default_seckey + msg = default_msg + sig = schnorr_sign(msg, seckey) + + pubkey_int = p + 1 + pubkey = bytes_from_int(pubkey_int) + assert(point_from_bytes(pubkey) is None) + # If an implementation would reduce a given public key modulo p then the + # pubkey would be valid + assert(point_from_bytes(bytes_from_int(pubkey_int % p)) is not None) + + return (None, pubkey, msg, sig, "FALSE", "public key is not a valid X coordinate because it exceeds the field size") + +vectors = [ + vector0(), + vector1(), + vector2(), + vector3(), + vector4(), + vector5(), + vector6(), + vector7(), + vector8(), + vector9(), + vector10(), + vector11(), + vector12(), + vector13(), + vector14() + ] + +# Converts the byte strings of a test vector into hex strings +def bytes_to_hex(seckey, pubkey, msg, sig, result, comment): + return (seckey.hex().upper() if seckey is not None else None, pubkey.hex().upper(), msg.hex().upper(), sig.hex().upper(), result, comment) + +vectors = list(map(lambda vector: bytes_to_hex(vector[0], vector[1], vector[2], vector[3], vector[4], vector[5]), vectors)) + +def print_csv(vectors): + writer = csv.writer(sys.stdout) + writer.writerow(("index", "secret key", "public key", "message", "signature", "verification result", "comment")) + for (i,v) in enumerate(vectors): + writer.writerow((i,)+v) + +print_csv(vectors) diff --git a/bip-0341.mediawiki b/bip-0341.mediawiki new file mode 100644 index 0000000..a0d2375 --- /dev/null +++ b/bip-0341.mediawiki @@ -0,0 +1,311 @@ +
+  BIP: 341
+  Layer: Consensus (soft fork)
+  Title: Taproot: SegWit version 1 output spending rules
+  Author: Pieter Wuille 
+          Jonas Nick 
+          Anthony Towns 
+  Comments-Summary: No comments yet.
+  Comments-URI:
+  Status: Draft
+  Type: Standards Track
+  Created:
+  License: BSD-3-Clause
+  Requires: 340
+  Post-History: 2019-05-06: https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2019-May/016914.html [bitcoin-dev] Taproot proposal
+
+ +==Introduction== + +===Abstract=== + +This document proposes a new SegWit version 1 output type, with spending rules based on Taproot, Schnorr signatures, and Merkle branches. + +===Copyright=== + +This document is licensed under the 3-clause BSD license. + +===Motivation=== + +This proposal aims to improve privacy, efficiency, and flexibility of Bitcoin's scripting capabilities without adding new security assumptions'''What does not adding security assumptions mean?''' Unforgeability of signatures is a necessary requirement to prevent theft. At least when treating script execution as a digital signature scheme itself, unforgeability can be [https://github.com/apoelstra/taproot proven] in the Random Oracle Model assuming the Discrete Logarithm problem is hard. A [https://nbn-resolving.de/urn:nbn:de:hbz:294-60803 proof] for unforgeability of ECDSA in the current script system needs non-standard assumptions on top of that. Note that it is hard in general to model exactly what security for script means, as it depends on the policies and protocols used by wallet software.. Specifically, it seeks to minimize how much information about the spendability conditions of a transaction output is revealed on chain at creation or spending time and to add a number of upgrade mechanisms, while fixing a few minor but long-standing issues. + +==Design== + +A number of related ideas for improving Bitcoin's scripting capabilities have been previously proposed: Schnorr signatures ([https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki BIP340), Merkle branches ("MAST", [bip-0114.mediawiki BIP114], [bip-0117.mediawiki BIP117]), new sighash modes ([bip-0118.mediawiki BIP118]), new opcodes like CHECKSIGFROMSTACK, [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-January/015614.html Taproot], [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-February/015700.html Graftroot], [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-July/016249.html G'root], and [https://bitcointalk.org/index.php?topic=1377298.0 cross-input aggregation]. + +Combining all these ideas in a single proposal would be an extensive change, be hard to review, and likely miss new discoveries that otherwise could have been made along the way. Not all are equally mature as well. For example, cross-input aggregation [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-March/015838.html interacts] in complex ways with upgrade mechanisms, and solutions to that are still [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-October/016461.html in flux]. On the other hand, separating them all into independent upgrades would reduce the efficiency and privacy gains to be had, and wallet and service providers may not be inclined to go through many incremental updates. Therefore, we're faced with a tradeoff between functionality and scope creep. In this design we strike a balance by focusing on the structural script improvements offered by Taproot and Merkle branches, as well as changes necessary to make them usable and efficient. For things like sighashes and opcodes we include fixes for known problems, but exclude new features that can be added independently with no downsides. + +As a result we choose this combination of technologies: +* '''Merkle branches''' let us only reveal the actually executed part of the script to the blockchain, as opposed to all possible ways a script can be executed. Among the various known mechanisms for implementing this, one where the Merkle tree becomes part of the script's structure directly maximizes the space savings, so that approach is chosen. +* '''Taproot''' on top of that lets us merge the traditionally separate pay-to-pubkey and pay-to-scripthash policies, making all outputs spendable by either a key or (optionally) a script, and indistinguishable from each other. As long as the key-based spending path is used for spending, it is not revealed whether a script path was permitted as well, resulting in space savings and an increase in scripting privacy at spending time. +* Taproot's advantages become apparent under the assumption that most applications involve outputs that could be spent by all parties agreeing. That's where '''Schnorr''' signatures come in, as they permit [https://eprint.iacr.org/2018/068 key aggregation]: a public key can be constructed from multiple participant public keys, and which requires cooperation between all participants to sign for. Such multi-party public keys and signatures are indistinguishable from their single-party equivalents. This means that with taproot most applications can use the key-based spending path, which is both efficient and private. This can be generalized to arbitrary M-of-N policies, as Schnorr signatures support threshold signing, at the cost of more complex setup protocols. +* As Schnorr signatures also permit '''batch validation''', allowing multiple signatures to be validated together more efficiently than validating each one independently, we make sure all parts of the design are compatible with this. +* Where unused bits appear as a result of the above changes, they are reserved for mechanisms for '''future extensions'''. As a result, every script in the Merkle tree has an associated version such that new script versions can be introduced with a soft fork while remaining compatible with BIP 341. Additionally, future soft forks can make use of the currently unused annex in the witness (see [[#Rationale]]). +* While the core semantics of the '''signature hashing algorithm''' are not changed, a number of improvements are included in this proposal. The new signature hashing algorithm fixes the verification capabilities of offline signing devices by including amount and scriptPubKey in the signature message, avoids unnecessary hashing, uses '''tagged hashes''' and defines a default sighash byte. +* The '''public key is directly included in the output''' in contrast to typical earlier constructions which store a hash of the public key or script in the output. This has the same cost for senders and is more space efficient overall if the key-based spending path is taken. '''Why is the public key directly included in the output?''' While typical earlier constructions store a hash of a script or a public key in the output, this is rather wasteful when a public key is always involved. To guarantee batch verifiability, the public key must be known to every verifier, and thus only revealing its hash as an output would imply adding an additional 32 bytes to the witness. Furthermore, to maintain [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2016-January/012198.html 128-bit collision security] for outputs, a 256-bit hash would be required anyway, which is comparable in size (and thus in cost for senders) to revealing the public key directly. While the usage of public key hashes is often said to protect against ECDLP breaks or quantum computers, this protection is very weak at best: transactions are not protected while being confirmed, and a very [https://twitter.com/pwuille/status/1108097835365339136 large portion] of the currency's supply is not under such protection regardless. Actual resistance to such systems can be introduced by relying on different cryptographic assumptions, but this proposal focuses on improvements that do not change the security model. + +Informally, the resulting design is as follows: a new witness version is added (version 1), whose programs consist of 32-byte encodings of points ''Q''. ''Q'' is computed as ''P + hash(P||m)G'' for a public key ''P'', and the root ''m'' of a Merkle tree whose leaves consist of a version number and a script. These outputs can be spent directly by providing a signature for ''Q'', or indirectly by revealing ''P'', the script and leaf version, inputs that satisfy the script, and a Merkle path that proves ''Q'' committed to that leaf. All hashes in this construction (the hash for computing ''Q'' from ''P'', the hashes inside the Merkle tree's inner nodes, and the signature hashes used) are tagged to guarantee domain separation. + +== Specification == + +This section specifies the Taproot consensus rules. Validity is defined by exclusion: a block or transaction is valid if no condition exists that marks it failed. + +The notation below follows that of [bip-0340.mediawiki#design BIP340]. This includes the ''hashtag(x)'' notation to refer to ''SHA256(SHA256(tag) || SHA256(tag) || x)''. To the best of the authors' knowledge, no existing use of SHA256 in Bitcoin feeds it a message that starts with two single SHA256 outputs, making collisions between ''hashtag'' with other hashes extremely unlikely. + +=== Script validation rules === + +A Taproot output is a native SegWit output (see [bip-0141.mediawiki BIP141]) with version number 1, and a 32-byte witness program. +The following rules only apply when such an output is being spent. Any other outputs, including version 1 outputs with lengths other than 32 bytes, or P2SH-wrapped version 1 outputs'''Why is P2SH-wrapping not supported?''' Using P2SH-wrapped outputs only provides 80-bit collision security due to the use of a 160-bit hash. This is considered low, and becomes a security risk whenever the output includes data from more than a single party (public keys, hashes, ...)., remain unencumbered. + +* Let ''q'' be the 32-byte array containing the witness program (the second push in the scriptPubKey) which represents a public key according to [bip-0340.mediawiki#design BIP340]. +* Fail if the witness stack has 0 elements. +* If there are at least two witness elements, and the first byte of the last element is 0x50'''Why is the first byte of the annex 0x50?''' The 0x50 is chosen as it could not be confused with a valid P2WPKH or P2WSH spending. As the control block's initial byte's lowest bit is used to indicate the public key's Y squareness, each leaf version needs an even byte value and the immediately following odd byte value that are both not yet used in P2WPKH or P2WSH spending. To indicate the annex, only an "unpaired" available byte is necessary like 0x50. This choice maximizes the available options for future script versions., this last element is called ''annex'' ''a'''''What is the purpose of the annex?''' The annex is a reserved space for future extensions, such as indicating the validation costs of computationally expensive new opcodes in a way that is recognizable without knowing the scriptPubKey of the output being spent. Until the meaning of this field is defined by another softfork, users SHOULD NOT include annex in transactions, or it may lead to PERMANENT FUND LOSS. and is removed from the witness stack. The annex (or the lack of thereof) is always covered by the signature and contributes to transaction weight, but is otherwise ignored during taproot validation. +* If there is exactly one element left in the witness stack, key path spending is used: +** The single witness stack element is interpreted as the signature and must be valid (see the next section) for the public key ''q'' (see the next subsection). +* If there are at least two witness elements left, script path spending is used: +** Call the second-to-last stack element ''s'', the script. +** The last stack element is called the control block ''c'', and must have length ''33 + 32m'', for a value of ''m'' that is an integer between 0 and 128'''Why is the Merkle path length limited to 128?''' The optimally space-efficient Merkle tree can be constructed based on the probabilities of the scripts in the leaves, using the Huffman algorithm. This algorithm will construct branches with lengths approximately equal to ''log2(1/probability)'', but to have branches longer than 128 you would need to have scripts with an execution chance below 1 in ''2128''. As that is our security bound, scripts that truly have such a low chance can probably be removed entirely., inclusive. Fail if it does not have such a length. +** Let ''p = c[1:33]'' and let ''P = point(p)'' where ''point'' and ''[:]'' are defined as in [bip-0340.mediawiki#design BIP340]. Fail if this point is not on the curve. +** Let ''v = c[0] & 0xfe'' and call it the ''leaf version'''''What constraints are there on the leaf version?''' First, the leaf version cannot be odd as ''c[0] & 0xfe'' will always be even, and cannot be ''0x50'' as that would result in ambiguity with the annex. In addition, in order to support some forms of static analysis that rely on being able to identify script spends without access to the output being spent, it is recommended to avoid using any leaf versions that would conflict with a valid first byte of either a valid P2WPKH pubkey or a valid P2WSH script (that is, both ''v'' and ''v | 1'' should be an undefined, invalid or disabled opcode or an opcode that is not valid as the first opcode). The values that comply to this rule are the 32 even values between ''0xc0'' and ''0xfe'' and also ''0x66'', ''0x7e'', ''0x80'', ''0x84'', ''0x96'', ''0x98'', ''0xba'', ''0xbc'', ''0xbe''. Note also that this constraint implies that leaf versions should be shared amongst different witness versions, as knowing the witness version requires access to the output being spent.. +** Let ''k0 = hashTapLeaf(v || compact_size(size of s) || s)''; also call it the ''tapleaf hash''. +** For ''j'' in ''[0,1,...,m-1]'': +*** Let ''ej = c[33+32j:65+32j]''. +*** Let ''kj+1 depend on whether ''kj < ej'' (lexicographically)'''Why are child elements sorted before hashing in the Merkle tree?''' By doing so, it is not necessary to reveal the left/right directions along with the hashes in revealed Merkle branches. This is possible because we do not actually care about the position of specific scripts in the tree; only that they are actually committed to.: +**** If ''kj < ej'': ''kj+1 = hashTapBranch(kj || ej)'''''Why not use a more efficient hash construction for inner Merkle nodes?''' The chosen construction does require two invocations of the SHA256 compression functions, one of which can be avoided in theory (see [bip-0098.mediawiki BIP98]). However, it seems preferable to stick to constructions that can be implemented using standard cryptographic primitives, both for implementation simplicity and analyzability. If necessary, a significant part of the second compression function can be optimized out by [https://github.com/bitcoin/bitcoin/pull/13191 specialization] for 64-byte inputs.. +**** If ''kj ≥ ej'': ''kj+1 = hashTapBranch(ej || kj)''. +** Let ''t = hashTapTweak(p || km)''. +** If ''t ≥ 0xFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141'' (order of secp256k1), fail. +** Let ''Q = point(q) if (c[0] & 1) = 1 and -point(q) otherwise'''''Why is it necessary to reveal a bit to indicate if the point represented by the output public key is negated in a script path spend?''' The ''point'' function (defined in [bip-0340.mediawiki#design BIP340]) always constructs a point with a square Y coordinate, but because ''Q'' is constructed by adding the taproot tweak to the internal public key ''P'', it cannot easily be guaranteed that ''Q'' in fact has such a Y coordinate. Therefore, before verifying the taproot tweak the original point is restored by negating if necessary. We can not ignore the Y coordinate because it would prevent batch verification. Trying out multiple internal keys until there's such a ''Q'' is possible but undesirable and unnecessary since this information about the Y coordinate only consumes an unused bit.. Fail if this point is not on the curve. +** If ''Q ≠ P + int(t)G'', fail. +** Execute the script, according to the applicable script rules'''What are the applicable script rules in script path spends?''' [bip-0342.mediawiki#design BIP342] specifies validity rules that apply for leaf version 0xc0, but future proposals can introduce rules for other leaf versions., using the witness stack elements excluding the script ''s'', the control block ''c'', and the annex ''a'' if present, as initial stack. + +''q'' is referred to as ''taproot output key'' and ''p'' as ''taproot internal key''. + +=== Signature validation rules === + +We first define a reusable common signature message calculation function, followed by the actual signature validation as it's used in key path spending. + +==== Common signature message ==== + +The function ''SigMsg(hash_type, ext_flag)'' computes the message being signed as a byte array. It is implicitly also a function of the spending transaction and the outputs it spends, but these are not listed to keep notation simple. + +The parameter ''hash_type'' is an 8-bit unsigned value. The SIGHASH encodings from the legacy script system are reused, including SIGHASH_ALL, SIGHASH_NONE, SIGHASH_SINGLE, and SIGHASH_ANYONECANPAY, plus the default ''hash_type'' value ''0x00'' which results in signing over the whole transaction just as for SIGHASH_ALL. The following restrictions apply, which cause validation failure if violated: +* Using any undefined ''hash_type'' (not ''0x00'', ''0x01'', ''0x02'', ''0x03'', ''0x81'', ''0x82'', or ''0x83'''''Why reject unknown ''hash_type'' values?''' By doing so, it is easier to reason about the worst case amount of signature hashing an implementation with adequate caching must perform.). +* Using SIGHASH_SINGLE without a "corresponding output" (an output with the same index as the input being verified). + +The parameter ''ext_flag'' is an integer in range 0-127, and is used for indicating (in the message) that extensions are added at the end of the message'''What extensions use the ''ext_flag'' mechanism?''' [bip-0342.mediawiki#design BIP342] reuses the same common signature message algorithm, but adds BIP342-specific data at the end, which is indicated using ''ext_flag = 1''.. + +If the parameters take acceptable values, the message is the concatenation of the following data, in order(with byte size of each item listed in parentheses). Numerical values in 2, 4, or 8-byte are encoded in little-endian. + +* Control: +** ''hash_type'' (1). +* Transaction data: +** ''nVersion'' (4): the ''nVersion'' of the transaction. +** ''nLockTime'' (4): the ''nLockTime'' of the transaction. +** If the ''hash_type & 0x80'' does not equal SIGHASH_ANYONECANPAY: +*** ''sha_prevouts'' (32): the SHA256 of the serialization of all input outpoints. +*** ''sha_amounts'' (32): the SHA256 of the serialization of all input amounts. +*** ''sha_sequences'' (32): the SHA256 of the serialization of all input ''nSequence''. +** If ''hash_type & 3'' does not equal SIGHASH_NONE or SIGHASH_SINGLE: +*** ''sha_outputs'' (32): the SHA256 of the serialization of all outputs in CTxOut format. +* Data about this input: +** ''spend_type'' (1): equal to ''(ext_flag * 2) + annex_present'', where ''annex_present'' is 0 if no annex is present, or 1 otherwise (the original witness stack has two or more witness elements, and the first byte of the last element is ''0x50'') +** ''scriptPubKey'' (35): ''scriptPubKey'' of the previous output spent by this input, serialized as script inside CTxOut. Its size is always 35 bytes. +** If ''hash_type & 0x80'' equals SIGHASH_ANYONECANPAY: +*** ''outpoint'' (36): the COutPoint of this input (32-byte hash + 4-byte little-endian). +*** ''amount'' (8): value of the previous output spent by this input. +*** ''nSequence'' (4): ''nSequence'' of this input. +** If ''hash_type & 0x80'' does not equal SIGHASH_ANYONECANPAY: +*** ''input_index'' (4): index of this input in the transaction input vector. Index of the first input is 0. +** If an annex is present (the lowest bit of ''spend_type'' is set): +*** ''sha_annex'' (32): the SHA256 of ''(compact_size(size of annex) || annex)'', where ''annex'' includes the mandatory ''0x50'' prefix. +* Data about this output: +** If ''hash_type & 3'' equals SIGHASH_SINGLE: +*** ''sha_single_output'' (32): the SHA256 of the corresponding output in CTxOut format. + +The total length of ''SigMsg()'' is at most ''209'' bytes'''What is the output length of ''SigMsg()''?''' The total length of ''SigMsg()'' can be computed using the following formula: ''177 - is_anyonecanpay * 52 - is_none * 32 + has_annex * 32''.. Note that this does not include the size of sub-hashes such as ''sha_prevouts'', which may be cached across signatures of the same transaction. + +In summary, the semantics of the [bip-0143.mediawiki BIP143] sighash types remain unchanged, except the following: +# The way and order of serialization is changed.'''Why is the serialization in the signature message changed?''' Hashes that go into the signature message and the message itself are now computed with a single SHA256 invocation instead of double SHA256. There is no expected security improvement by doubling SHA256 because this only protects against length-extension attacks against SHA256 which are not a concern for signature messages because there is no secret data. Therefore doubling SHA256 is a waste of resources. The message computation now follows a logical order with transaction level data first, then input data and output data. This allows to efficiently cache the transaction part of the message across different inputs using the SHA256 midstate. Additionally, sub-hashes can be skipped when calculating the message (for example `sha_prevouts` if SIGHASH_ANYONECANPAY is set) instead of setting them to zero and then hashing them as in BIP143. Despite that, collisions are made impossible by committing to the length of the data (implicit in ''hash_type'' and ''spend_type'') before the variable length data. +# The signature message commits to the ''scriptPubKey'''''Why does the signature message commit to the ''scriptPubKey''?''' This prevents lying to offline signing devices about output being spent, even when the actually executed script (''scriptCode'' in BIP143) is correct. This means it's possible to compactly prove to a hardware wallet what (unused) execution paths existed.. +# If the SIGHASH_ANYONECANPAY flag is not set, the message commits to the amounts of ''all'' transaction inputs.'''Why does the signature message commit to the amounts of all transaction inputs?''' This eliminates the possibility to lie to offline signing devices about the fee of a transaction. +# The signature message commits to all input ''nSequence'' if SIGHASH_NONE or SIGHASH_SINGLE are set (unless SIGHASH_ANYONECANPAY is set as well).'''Why does the signature message commit to all input ''nSequence'' if SIGHASH_SINGLE or SIGHASH_NONE are set?''' Because setting them already makes the message commit to the prevouts part of all transaction inputs, it is not useful to treat the ''nSequence'' any different. Moreover, this change makes ''nSequence'' consistent with the view that SIGHASH_SINGLE and SIGHASH_NONE only modify the signature message with respect to transaction outputs and not inputs. +# The signature message includes commitments to the taproot-specific data ''spend_type'' and ''annex'' (if present). + +==== Taproot key path spending signature validation ==== + +To validate a signature ''sig'' with public key ''q'': +* If the ''sig'' is 64 bytes long, return ''Verify(q, hashTapSigHash(0x00 || SigMsg(0x00, 0)), sig)'''''Why is the input to ''hashTapSigHash'' prefixed with 0x00?''' This prefix is called the sighash epoch, and allows reusing the ''hashTapSigHash'' tagged hash in future signature algorithms that make invasive changes to how hashing is performed (as opposed to the ''ext_flag'' mechanism that is used for incremental extensions). An alternative is having them use a different tag, but supporting a growing number of tags may become undesirable., where ''Verify'' is defined in [bip-0340.mediawiki#design BIP340]. +* If the ''sig'' is 65 bytes long, return ''sig[64] ≠ 0x00'''Why can the hash_type not be 0x00 in 65-byte signatures?''' Permitting that would enable malleating (by third parties, including miners) 64-byte signatures into 65-byte ones, resulting in a different `wtxid` and a different fee rate than the creator intended and Verify(q, hashTapSighash(0x00 || SigMsg(sig[64], 0)), sig[0:64])''. +* Otherwise, fail'''Why permit two signature lengths?''' By making the most common type of hash_type implicit, a byte can often be saved.. + +== Constructing and spending Taproot outputs == + +This section discusses how to construct and spend Taproot outputs. It only affects wallet software that chooses to implement receiving and spending, +and is not consensus critical in any way. + +Conceptually, every Taproot output corresponds to a combination of a single public key condition (the internal key), and zero or more general conditions encoded in scripts organized in a tree. +Satisfying any of these conditions is sufficient to spend the output. + +'''Initial steps''' The first step is determining what the internal key and the organization of the rest of the scripts should be. The specifics are likely application dependent, but here are some general guidelines: +* When deciding between scripts with conditionals (OP_IF etc.) and splitting them up into multiple scripts (each corresponding to one execution path through the original script), it is generally preferable to pick the latter. +* When a single condition requires signatures with multiple keys, key aggregation techniques like MuSig can be used to combine them into a single key. The details are out of scope for this document, but note that this may complicate the signing procedure. +* If one or more of the spending conditions consist of just a single key (after aggregation), the most likely one should be made the internal key. If no such condition exists, it may be worthwhile adding one that consists of an aggregation of all keys participating in all scripts combined; effectively adding an "everyone agrees" branch. If that is inacceptable, pick as internal key a point with unknown discrete logarithm. One example of such a point is ''H = point(0x0250929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0)'' which is [https://github.com/ElementsProject/secp256k1-zkp/blob/11af7015de624b010424273be3d91f117f172c82/src/modules/rangeproof/main_impl.h#L16 constructed] by taking the hash of the standard uncompressed encoding of the [https://www.secg.org/sec2-v2.pdf secp256k1] base point ''G'' as X coordinate. In order to avoid leaking the information that key path spending is not possible it is recommended to pick a fresh integer ''r'' in the range ''0...n-1'' uniformly at random and use ''H + rG'' as internal key. It is possible to prove that this internal key does not have a known discrete logarithm with respect to ''G'' by revealing ''r'' to a verifier who can then reconstruct how the internal key was created. +* If the spending conditions do not require a script path, the output key should commit to an unspendable script path instead of having no script path. This can be achieved by computing the output key point as ''Q = P + int(hashTapTweak(bytes(P)))G''. '''Why should the output key always have a taproot commitment, even if there is no script path?''' +If the taproot output key is an aggregate of keys, there is the possibility for a malicious party to add a script path without being noticed by the other parties. +This allows to bypass the multiparty policy and to steal the coin. +MuSig key aggregation does not have this issue because it already causes the internal key to be randomized. + +The attack works as follows: Assume Alice and Mallory want to aggregate their keys into a taproot output key without a script path. +In order to prevent key cancellation and related attacks they use [https://eprint.iacr.org/2018/483.pdf MSDL-pop] instead of MuSig. +The MSDL-pop protocol requires all parties to provide a proof of possession of their corresponding secret key and the aggregated key is just the sum of the individual keys. +After Mallory receives Alice's key ''A'', Mallory creates ''M = M0 + int(t)G'' where ''M0'' is Mallory's original key and ''t'' allows a script path spend with internal key ''P = A + M0'' and a script that only contains Mallory's key. +Mallory sends a proof of possession of ''M'' to Alice and both parties compute output key ''Q = A + M = P + int(t)G''. +Alice will not be able to notice the script path, but Mallory can unilaterally spend any coin with output key ''Q''. + +* The remaining scripts should be organized into the leaves of a binary tree. This can be a balanced tree if each of the conditions these scripts correspond to are equally likely. If probabilities for each condition are known, consider constructing the tree as a Huffman tree. + +'''Computing the output script''' Once the spending conditions are split into an internal key internal_pubkey and a binary tree whose leaves are (leaf_version, script) tuples, the output script can be computed using the Python3 algorithms below. These algorithms take advantage of helper functions from the [bip-0340/referency.py BIP340 reference code] for integer conversion, point multiplication, and tagged hashes. + +First, we define taproot_tweak_pubkey for 32-byte [bip-0340.mediawiki#design BIP340] public key arrays. +In addition to the tweaked public key byte array, the function returns a boolean indicating whether the public key represents the tweaked point or its negation. +This will be required for spending the output with a script path. +In order to allow spending with the key path, we define taproot_tweak_seckey to compute the secret key for a tweaked public key. +For any byte string h it holds that taproot_tweak_pubkey(pubkey_gen(seckey), h)[0] == pubkey_gen(taproot_tweak_seckey(seckey, h)). + + +def taproot_tweak_pubkey(pubkey, h): + t = int_from_bytes(tagged_hash("TapTweak", pubkey + h)) + if t >= SECP256K1_ORDER: + raise ValueError + Q = point_add(point(pubkey), point_mul(G, t)) + is_negated = not has_square_y(Q) + return bytes_from_int(x(Q)), is_negated + +def taproot_tweak_seckey(seckey0, h): + P = point_mul(G, int_from_bytes(seckey0)) + seckey = SECP256K1_ORDER - seckey0 if not has_square_y(P) else seckey + t = int_from_bytes(tagged_hash("TapTweak", bytes_from_int(x(P)) + h)) + if t >= SECP256K1_ORDER: + raise ValueError + return (seckey + t) % SECP256K1_ORDER + + +The following function, taproot_output_script, returns a byte array with the scriptPubKey (see BIP141). +ser_script refers to a function that prefixes its input with a CCompactSize-encoded length. + + +def taproot_tree_helper(script_tree): + if isinstance(script_tree, tuple): + leaf_version, script = script_tree + h = tagged_hash("TapLeaf", bytes([leaf_version]) + ser_script(script)) + return ([((leaf_version, script), bytes())], h) + left, left_h = taproot_tree_helper(script_tree[0]) + right, right_h = taproot_tree_helper(script_tree[1]) + ret = [(l, c + right_h) for l, c in left] + [(l, c + left_h) for l, c in right] + if right_h < left_h: + left_h, right_h = right_h, left_h + return (ret, tagged_hash("TapBranch", left_h + right_h)) + +def taproot_output_script(internal_pubkey, script_tree): + """Given a internal public key and a tree of scripts, compute the output script. + script_tree is either: + - a (leaf_version, script) tuple (leaf_version is 0xc0 for [bip-0342.mediawiki#design BIP342] scripts) + - a list of two elements, each with the same structure as script_tree itself + - None + """ + if script_tree is None: + h = bytes() + else: + _, h = taproot_tree_helper(script_tree) + output_pubkey, _ = taproot_tweak_pubkey(internal_pubkey, h) + return bytes([0x51, 0x20]) + output_pubkey + + +[[File:bip-0342/tree.png|frame|This diagram shows the hashing structure to obtain the tweak from an internal key ''P'' and a Merkle tree consisting of 5 script leaves. ''A'', ''B'', ''C'' and ''E'' are ''TapLeaf'' hashes similar to ''D'' and ''AB'' is a ''TapBranch'' hash. Note that when ''CDE'' is computed ''E'' is hashed first because ''E'' is less than ''CD''.]] + +To spend this output using script ''D'', the control block would contain the following data in this order: + + + +The TapTweak would then be computed as described in [[#script-validation-rules]] like so: + + +D = tagged_hash("TapLeaf", bytes([leaf_version]) + ser_script(script)) +CD = tagged_hash("TapBranch", C + D) +CDE = tagged_hash("TapBranch", E + CD) +ABCDE = tagged_hash("TapBranch", AB + CDE) +TapTweak = tagged_hash("TapTweak", p + ABCDE) + + +'''Spending using the key path''' A Taproot output can be spent with the secret key corresponding to the internal_pubkey. To do so, a witness stack consists of a single element: a bip-schnorr signature on the signature hash as defined above, with the secret key tweaked by the same h as in the above snippet. See the code below: + + +def taproot_sign_key(script_tree, internal_seckey, hash_type): + _, h = taproot_tree_helper(script_tree) + output_seckey = taproot_tweak_seckey(internal_seckey, h) + sig = schnorr_sign(sighash(hash_type), output_seckey) + if hash_type != 0: + sig += bytes([hash_type]) + return [sig] + + +This function returns the witness stack necessary and a sighash function to compute the signature hash as defined above (for simplicity, the snippet above ignores passing information like the transaction, the input position, ... to the sighashing code). + +'''Spending using one of the scripts''' A Taproot output can be spent by satisfying any of the scripts used in its construction. To do so, a witness stack consisting of the script's inputs, plus the script itself and the control block are necessary. See the code below: + + +def taproot_sign_script(internal_pubkey, script_tree, script_num, inputs): + info, h = taproot_tree_helper(script_tree) + (leaf_version, script), path = info[script_num] + _, is_negated = taproot_tweak_pubkey(internal_pubkey, h) + output_pubkey_tag = 0 if is_negated else 1 + pubkey_data = bytes([output_pubkey_tag + leaf_version]) + internal_pubkey + return inputs + [script, pubkey_data + path] + + +== Security == + +Taproot improves the privacy of Bitcoin because instead of revealing all possible conditions for spending an output, only the satisfied spending condition has to be published. +Ideally, outputs are spent using the key path which prevents observers from learning the spending conditions of a coin. +A key path spend could be a "normal" payment from a single- or multi-signature wallet or the cooperative settlement of hidden multiparty contract. + +A script path spend leaks that there is a script path and that the key path was not applicable - for example because the involved parties failed to reach agreement. +Moreover, the depth of a script in the Merkle root leaks information including the minimum depth of the tree, which suggests specific wallet software that created the output and helps clustering. +Therefore, the privacy of script spends can be improved by deviating from the optimal tree determined by the probability distribution over the leaves. + +Just like other existing output types, taproot outputs should never reuse keys, for privacy reasons. +This does not only apply to the particular leaf that was used to spend an output but to all leaves committed to in the output. +If leaves were reused, it could happen that spending a different output would reuse the same Merkle branches in the Merkle proof. +Using fresh keys implies that taproot output construction does not need to take special measures to randomizing leaf positions because they are already randomized due to the branch-sorting Merkle tree construction used in taproot. +This does not avoid leaking information through the leaf depth and therefore only applies to balanced (sub-) trees. +In addition, every leaf should have a set of keys distinct from every other leaf. +The reason for this is to increase leaf entropy and prevent an observer from learning an undisclosed script using brute-force search. + +== Test vectors == + +Examples with creation transaction and spending transaction pairs, valid and invalid. + +Examples of preimage for sighashing for each of the sighash modes. + +== Rationale == + + + +== Deployment == + +TODO + +== Backwards compatibility == +As a soft fork, older software will continue to operate without modification. +Non-upgraded nodes, however, will consider all SegWit version 1 witness programs as anyone-can-spend scripts. +They are strongly encouraged to upgrade in order to fully validate the new programs. + +Non-upgraded wallets can receive and send bitcoin from non-upgraded and upgraded wallets using SegWit version 0 programs, traditional pay-to-pubkey-hash, etc. +Depending on the implementation non-upgraded wallets may be able to send to Segwit version 1 programs if they support sending to [https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki BIP173] Bech32 addresses. + +== Acknowledgements == + +This document is the result of discussions around script and signature improvements with many people, and had direct contributions from Greg Maxwell and others. It further builds on top of earlier published proposals such as Taproot by Greg Maxwell, and Merkle branch constructions by Russell O'Connor, Johnson Lau, and Mark Friedenbach. + +The authors wish the thank Arik Sosman for suggesting to sort Merkle node children before hashes, removing the need to transfer the position in the tree, as well as all those who provided valuable feedback and reviews, including the participants of the [https://github.com/ajtowns/taproot-review structured reviews]. diff --git a/bip-0341/tree.png b/bip-0341/tree.png new file mode 100644 index 0000000..af56eda Binary files /dev/null and b/bip-0341/tree.png differ diff --git a/bip-0342.mediawiki b/bip-0342.mediawiki new file mode 100644 index 0000000..d0b2ece --- /dev/null +++ b/bip-0342.mediawiki @@ -0,0 +1,140 @@ +
+  BIP: 342
+  Layer: Consensus (soft fork)
+  Title: Validation of Taproot Scripts
+  Author: Pieter Wuille 
+          Jonas Nick 
+          Anthony Towns 
+  Comments-Summary: No comments yet.
+  Comments-URI:
+  Status: Draft
+  Type: Standards Track
+  Created:
+  License: BSD-3-Clause
+  Requires: 340, 341
+  Post-History: 2019-05-06: https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2019-May/016914.html [bitcoin-dev] Taproot proposal
+
+ +==Introduction== + +===Abstract=== + +This document specifies the semantics of the initial scripting system under [bip-0341.mediawiki BIP341]. + +===Copyright=== + +This document is licensed under the 3-clause BSD license. + +===Motivation=== + +[bip-0341.mediawiki BIP341] proposes improvements to just the script structure, but some of its goals are incompatible with the semantics of certain opcodes within the scripting language itself. +While it is possible to deal with these in separate optional improvements, their impact is not guaranteed unless they are addressed simultaneously with [bip-0341.mediawiki BIP341] itself. + +Specifically, the goal is making '''Schnorr signatures''', '''batch validation''', and '''signature hash''' improvements available to spends that use the script system as well. + +==Design== + +In order to achieve these goals, signature opcodes OP_CHECKSIG and OP_CHECKSIGVERIFY are modified to verify Schnorr signatures as specified in [bip-0340.mediawiki BIP340] and to use a signature message algorithm based on the common message calculation in [bip-0341.mediawiki BIP341]. +The tapscript signature message also simplifies OP_CODESEPARATOR handling and makes it more efficient. + +The inefficient OP_CHECKMULTISIG and OP_CHECKMULTISIGVERIFY opcodes are disabled. +Instead, a new opcode OP_CHECKSIGADD is introduced to allow creating the same multisignature policies in a batch-verifiable way. +Tapscript uses a new, simpler signature opcode limit fixing complicated interactions with transaction weight. +Furthermore, a potential malleability vector is eliminated by requiring MINIMALIF. + +Tapscript can be upgraded through soft forks by defining unknown key types, for example to add new hash_types or signature algorithms. +Additionally, the new tapscript OP_SUCCESS opcodes allow introducing new opcodes more cleanly than through OP_NOP. + +==Specification== + +The rules below only apply when validating a transaction input for which all of the conditions below are true: +* The transaction input is a '''segregated witness spend''' (i.e., the scriptPubKey contains a witness program as defined in [bip-0141.mediawiki BIP141]). +* It is a '''taproot spend''' as defined in [bip-0341.mediawiki BIP341] (i.e., the witness version is 1, the witness program is 32 bytes, and it is not P2SH wrapped). +* It is a '''script path spend''' as defined in [bip-0341.mediawiki BIP341] (i.e., after removing the optional annex from the witness stack, two or more stack elements remain). +* The leaf version is ''0xc0'' (i.e. the first byte of the last witness element after removing the optional annex is ''0xc0'' or ''0xc1''), marking it as a '''tapscript spend'''. + +Validation of such inputs must be equivalent to performing the following steps in the specified order. +# If the input is invalid due to BIP141 or BIP341, fail. +# The script as defined in BIP341 (i.e., the penultimate witness stack element after removing the optional annex) is called the '''tapscript''' and is decoded into opcodes, one by one: +## If any opcode numbered ''80, 98, 126-129, 131-134, 137-138, 141-142, 149-153, 187-254'' is encountered, validation succeeds (none of the rules below apply). This is true even if later bytes in the tapscript would fail to decode otherwise. These opcodes are renamed to OP_SUCCESS80, ..., OP_SUCCESS254, and collectively known as OP_SUCCESSx'''OP_SUCCESSx''' OP_SUCCESSx is a mechanism to upgrade the Script system. Using an OP_SUCCESSx before its meaning is defined by a softfork is insecure and leads to fund loss. The inclusion of OP_SUCCESSx in a script will pass it unconditionally. It precedes any script execution rules to avoid the difficulties in specifying various edge cases, for example: OP_SUCCESSx in a script with an input stack larger than 1000 elements, OP_SUCCESSx after too many signature opcodes, or even scripts with conditionals lacking OP_ENDIF. The mere existence of an OP_SUCCESSx anywhere in the script will guarantee a pass for all such cases. OP_SUCCESSx are similar to the OP_RETURN in very early bitcoin versions (v0.1 up to and including v0.3.5). The original OP_RETURN terminates script execution immediately, and return pass or fail based on the top stack element at the moment of termination. This was one of a major design flaws in the original bitcoin protocol as it permitted unconditional third party theft by placing an OP_RETURN in scriptSig. This is not a concern in the present proposal since it is not possible for a third party to inject an OP_SUCCESSx to the validation process, as the OP_SUCCESSx is part of the script (and thus committed to by the taproot output), implying the consent of the coin owner. OP_SUCCESSx can be used for a variety of upgrade possibilities: +* An OP_SUCCESSx could be turned into a functional opcode through a softfork. Unlike OP_NOPx-derived opcodes which only have read-only access to the stack, OP_SUCCESSx may also write to the stack. Any rule changes to an OP_SUCCESSx-containing script may only turn a valid script into an invalid one, and this is always achievable with softforks. +* Since OP_SUCCESSx precedes size check of initial stack and push opcodes, an OP_SUCCESSx-derived opcode requiring stack elements bigger than 520 bytes may uplift the limit in a softfork. +* OP_SUCCESSx may also redefine the behavior of existing opcodes so they could work together with the new opcode. For example, if an OP_SUCCESSx-derived opcode works with 64-bit integers, it may also allow the existing arithmetic opcodes in the ''same script'' to do the same. +* Given that OP_SUCCESSx even causes potentially unparseable scripts to pass, it can be used to introduce multi-byte opcodes, or even a completely new scripting language when prefixed with a specific OP_SUCCESSx opcode.. +## If any push opcode fails to decode because it would extend past the end of the tapscript, fail. +# If the '''initial stack''' as defined in BIP341 (i.e., the witness stack after removing both the optional annex and the two last stack elements after that) violates any resource limits (stack size, and size of the elements in the stack; see "Resource Limits" below), fail. Note that this check can be bypassed using OP_SUCCESSx. +# The tapscript is executed according to the rules in the following section, with the initial stack as input. +## If execution fails for any reason, fail. +## If the execution results in anything but exactly one element on the stack which evaluates to true with CastToBool(), fail. +# If this step is reached without encountering a failure, validation succeeds. + +===Script execution=== + +The execution rules for tapscript are based on those for P2WSH according to BIP141, including the OP_CHECKLOCKTIMEVERIFY and OP_CHECKSEQUENCEVERIFY opcodes defined in [bip-0065.mediawiki BIP65] and [bip-0112.mediawiki BIP112], but with the following modifications: +* '''Disabled script opcodes''' The following script opcodes are disabled in tapscript: OP_CHECKMULTISIG and OP_CHECKMULTISIGVERIFY'''Why are OP_CHECKMULTISIG and OP_CHECKMULTISIGVERIFY disabled, and not turned into OP_SUCCESSx?''' This is a precaution to make sure people who accidentally keep using OP_CHECKMULTISIG in Tapscript notice a problem immediately. It also avoids the complication of script disassemblers needing to become context-dependent.. The disabled opcodes behave in the same way as OP_RETURN, by failing and terminating the script immediately when executed, and being ignored when found in unexecuted branch of the script. +* '''Consensus-enforced MINIMALIF''' The MINIMALIF rules, which are only a standardness rule in P2WSH, are consensus enforced in tapscript. This means that the input argument to the OP_IF and OP_NOTIF opcodes must be either exactly 0 (the empty vector) or exactly 1 (the one-byte vector with value 1)'''Why make MINIMALIF consensus?''' This makes it considerably easier to write non-malleable scripts that take branch information from the stack.. +* '''OP_SUCCESSx opcodes''' As listed above, some opcodes are renamed to OP_SUCCESSx, and make the script unconditionally valid. +* '''Signature opcodes'''. The OP_CHECKSIG and OP_CHECKSIGVERIFY are modified to operate on Schnorr public keys and signatures (see [bip-0340.mediawiki BIP340]) instead of ECDSA, and a new opcode OP_CHECKSIGADD is added. +** The opcode 186 (0xba) is named as OP_CHECKSIGADD. '''OP_CHECKSIGADD''' This opcode is added to compensate for the loss of OP_CHECKMULTISIG-like opcodes, which are incompatible with batch verification. OP_CHECKSIGADD is functionally equivalent to OP_ROT OP_SWAP OP_CHECKSIG OP_ADD, but only takes 1 byte. All CScriptNum-related behaviours of OP_ADD are also applicable to OP_CHECKSIGADD.'''Alternatives to CHECKMULTISIG''' There are multiple ways of implementing a threshold ''k''-of-''n'' policy using Taproot and Tapscript: +* '''Using a single OP_CHECKSIGADD-based script''' A CHECKMULTISIG script m ... n CHECKMULTISIG with witness 0 ... can be rewritten as script CHECKSIG ... CHECKSIGADD m NUMEQUAL with witness ... . Every witness element w_i is either a signature corresponding to pubkey_i or an empty vector. A similar CHECKMULTISIGVERIFY script can be translated to BIP342 by replacing NUMEQUAL with NUMEQUALVERIFY. This approach has very similar characteristics to the existing OP_CHECKMULTISIG-based scripts. +* '''Using a ''k''-of-''k'' script for every combination''' A ''k''-of-''n'' policy can be implemented by splitting the script into several leaves of the Merkle tree, each implementing a ''k''-of-''k'' policy using CHECKSIGVERIFY ... CHECKSIGVERIFY CHECKSIG. This may be preferable for privacy reasons over the previous approach, as it only exposes the participating public keys, but it is only more cost effective for small values of ''k'' (1-of-''n'' for any ''n'', 2-of-''n'' for ''n ≥ 6'', 3-of-''n'' for ''n ≥ 9'', ...). Furthermore, the signatures here commit to the branch used, which means signers need to be aware of which other signers will be participating, or produce signatures for each of the tree leaves. +* '''Using an aggregated public key for every combination''' Instead of building a tree where every leaf consists of ''k'' public keys, it is possible instead build a tree where every leaf contains a single ''aggregate'' of those ''k'' keys using [https://eprint.iacr.org/2018/068 MuSig]. This approach is far more efficient, but does require a 3-round interactive signing protocol to jointly produce the (single) signature. +* '''Native Schnorr threshold signatures''' Multisig policies can also be realized with [http://cacr.uwaterloo.ca/techreports/2001/corr2001-13.ps threshold signatures] using verifiable secret sharing. This results in outputs and inputs that are indistinguishable from single-key payments, but at the cost of needing an interactive protocol (and associated backup procedures) before determining the address to send to. + +===Rules for signature opcodes=== + +The following rules apply to OP_CHECKSIG, OP_CHECKSIGVERIFY, and OP_CHECKSIGADD. + +* For OP_CHECKSIGVERIFY and OP_CHECKSIG, the public key (top element) and a signature (second to top element) are popped from the stack. +** If fewer than 2 elements are on the stack, the script MUST fail and terminate immediately. +* For OP_CHECKSIGADD, the public key (top element), a CScriptNum n (second to top element), and a signature (third to top element) are popped from the stack. +** If fewer than 3 elements are on the stack, the script MUST fail and terminate immediately. +** If n is larger than 4 bytes, the script MUST fail and terminate immediately. +* If the public key size is zero, the script MUST fail and terminate immediately. +* If the public key size is 32 bytes, it is considered to be a public key as described in BIP340: +** If the signature is not the empty vector, the signature is validated against the public key (see the next subsection). Validation failure in this case immediately terminates script execution with failure. +* If the public key size is not zero and not 32 bytes, the public key is of an ''unknown public key type'''''Unknown public key types''' allow adding new signature validation rules through softforks. A softfork could add actual signature validation which either passes or makes the script fail and terminate immediately. This way, new SIGHASH modes can be added, as well as [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-December/016549.html NOINPUT-tagged public keys] and a public key constant which is replaced by the taproot internal key for signature validation. and no actual signature verification is applied. During script execution of signature opcodes they behave exactly as known public key types except that signature validation is considered to be successful. +* If the script did not fail and terminate before this step, regardless of the public key type: +** If the signature is the empty vector: +*** For OP_CHECKSIGVERIFY, the script MUST fail and terminate immediately. +*** For OP_CHECKSIG, an empty vector is pushed onto the stack, and execution continues with the next opcode. +*** For OP_CHECKSIGADD, a CScriptNum with value n is pushed onto the stack, and execution continues with the next opcode. +** If the signature is not the empty vector, the opcode is counted towards the sigops budget (see further). +*** For OP_CHECKSIGVERIFY, execution continues without any further changes to the stack. +*** For OP_CHECKSIG, a 1-byte value 0x01 is pushed onto the stack. +*** For OP_CHECKSIGADD, a CScriptNum with value of n + 1 is pushed onto the stack. + +===Signature validation=== + +To validate a signature ''sig'' with public key ''p'': +* Compute the tapscript message extension ''ext'', consisting of the concatenation of: +** ''tapleaf_hash'' (32): the tapleaf hash as defined in [bip-0341.mediawiki BIP341] +** ''key_version'' (1): a constant value ''0x00'' representing the current version of public keys in the tapscript signature opcode execution. +** ''codesep_pos'' (4): the opcode position of the last executed OP_CODESEPARATOR before the currently executed signature opcode, with the value in little endian (or ''0xffffffff'' if none executed). The first opcode in a script has a position of 0. A multi-byte push opcode is counted as one opcode, regardless of the size of data being pushed. +* If the ''sig'' is 64 bytes long, return ''Verify(p, hashTapSigHash(0x00 || SigMsg(0x00, 1) || ext), sig)'', where ''Verify'' is defined in [bip-0340.mediawiki BIP340]. +* If the ''sig'' is 65 bytes long, return ''sig[64] ≠ 0x00 and Verify(p, hashTapSighash(0x00 || SigMsg(sig[64], 1) || ext), sig[0:64])''. +* Otherwise, fail. + +In summary, the semantics of signature validation is identical to BIP340, except the following: +# The signature message includes the tapscript-specific data ''key_version''.'''Why does the signature message commit to the ''key_version''?''' This is for future extensions that define unknown public key types, making sure signatures can't be moved from one key type to another. +# The signature message commits to the executed script through the ''tapleaf_hash'' which includes the leaf version and script instead of ''scriptCode''. This implies that this commitment is unaffected by OP_CODESEPARATOR. +# The signature message includes the opcode position of the last executed OP_CODESEPARATOR.'''Why does the signature message include the position of the last executed OP_CODESEPARATOR?''' This allows continuing to use OP_CODESEPARATOR to sign the executed path of the script. Because the codeseparator_position is the last input to the hash, the SHA256 midstate can be efficiently cached for multiple OP_CODESEPARATORs in a single script. In contrast, the BIP143 handling of OP_CODESEPARATOR is to commit to the executed script only from the last executed OP_CODESEPARATOR onwards which requires unnecessary rehashing of the script. It should be noted that the one known OP_CODESEPARATOR use case of saving a second public key push in a script by sharing the first one between two code branches can be most likely expressed even cheaper by moving each branch into a separate taproot leaf. + +===Resource limits=== + +In addition to changing the semantics of a number of opcodes, there are also some changes to the resource limitations: +* '''Script size limit''' The maximum script size of 10000 bytes does not apply. Their size is only implicitly bounded by the block weight limit.'''Why is a limit on script size no longer needed?''' Since there is no scriptCode directly included in the signature hash (only indirectly through a precomputable tapleaf hash), the CPU time spent on a signature check is no longer proportional to the size of the script being executed. +* '''Non-push opcodes limit''' The maximum non-push opcodes limit of 201 per script does not apply.'''Why is a limit on the number of opcodes no longer needed?''' An opcode limit only helps to the extent that it can prevent data structures from growing unboundedly during execution (both because of memory usage, and because of time that may grow in proportion to the size of those structures). The size of stack and altstack is already independently limited. By using O(1) logic for OP_IF, OP_NOTIF, OP_ELSE, and OP_ENDIF as suggested [https://bitslog.com/2017/04/17/new-quadratic-delays-in-bitcoin-scripts/ here] and implemented [https://github.com/bitcoin/bitcoin/pull/16902 here], the only other instance can be avoided as well. +* '''Sigops limit''' The sigops in tapscripts do not count towards the block-wide limit of 80000 (weighted). Instead, there is a per-script sigops ''budget''. The budget equals 50 + the total serialized size in bytes of the transaction input's witness (including the CCompactSize prefix). Executing a signature opcode (OP_CHECKSIG, OP_CHECKSIGVERIFY, or OP_CHECKSIGADD) with a non-empty signature decrements the budget by 50. If that brings the budget below zero, the script fails immediately. Signature opcodes with unknown public key type and non-empty signature are also counted.'''The tapscript sigop limit''' The signature opcode limit protects against scripts which are slow to verify due to excessively many signature operations. In tapscript the number of signature opcodes does not count towards the BIP141 or legacy sigop limit. The old sigop limit makes transaction selection in block construction unnecessarily difficult because it is a second constraint in addition to weight. Instead, the number of tapscript signature opcodes is limited by witness weight. Additionally, the limit applies to the transaction input instead of the block and only actually executed signature opcodes are counted. Tapscript execution allows one signature opcode per 50 witness weight units plus one free signature opcode.'''Parameter choice of the sigop limit''' Regular witnesses are unaffected by the limit as their weight is composed of public key and (SIGHASH_ALL) signature pairs with ''33 + 65'' weight units each (which includes a 1 weight unit CCompactSize tag). This is also the case if public keys are reused in the script because a signature's weight alone is 65 or 66 weight units. However, the limit increases the fees of abnormal scripts with duplicate signatures (and public keys) by requiring additional weight. The weight per sigop factor 50 corresponds to the ratio of BIP141 block limits: 4 mega weight units divided by 80,000 sigops. The "free" signature opcode permitted by the limit exists to account for the weight of the non-witness parts of the transaction input.'''Why are only signature opcodes counted toward the budget, and not for example hashing opcodes or other expensive operations?''' It turns out that the CPU cost per witness byte for verification of a script consisting of the maximum density of signature checking opcodes (taking the 50 WU/sigop limit into account) is already very close to that of scripts packed with other opcodes, including hashing opcodes (taking the 520 byte stack element limit into account) and OP_ROLL (taking the 1000 stack element limit into account). That said, the construction is very flexible, and allows adding new signature opcodes like CHECKSIGFROMSTACK to count towards the limit through a soft fork. Even if in the future new opcodes are introduced which change normal script cost there is no need to stuff the witness with meaningless data. Instead, the taproot annex can be used to add weight to the witness without increasing the actual witness size.. +* '''Stack + altstack element count limit''' The existing limit of 1000 elements in the stack and altstack together after every executed opcode remains. It is extended to also apply to the size of initial stack. +* '''Stack element size limit''' The existing limit of maximum 520 bytes per stack element remains, both in the initial stack and in push opcodes. + +==Rationale== + + + +==Examples== + +==Acknowledgements== + +This document is the result of many discussions and contains contributions by a number of people. The authors wish to thank all those who provided valuable feedback and reviews, including the participants of the [https://github.com/ajtowns/taproot-review structured reviews]. diff --git a/bip-schnorr.mediawiki b/bip-schnorr.mediawiki deleted file mode 100644 index fbfd408..0000000 --- a/bip-schnorr.mediawiki +++ /dev/null @@ -1,260 +0,0 @@ -
-  BIP: ?
-  Title: Schnorr Signatures for secp256k1
-  Author: Pieter Wuille 
-          Jonas Nick 
-          Tim Ruffing 
-  Status: Draft
-  Type: Informational
-  License: BSD-2-Clause
-  Post-History: 2018-07-06: https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-July/016203.html [bitcoin-dev] Schnorr signatures BIP
-
- -== Introduction == - -=== Abstract === - -This document proposes a standard for 64-byte Schnorr signatures over the elliptic curve ''secp256k1''. - -=== Copyright === - -This document is licensed under the 2-clause BSD license. - -=== Motivation === - -Bitcoin has traditionally used -[https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm ECDSA] signatures over the [https://www.secg.org/sec2-v2.pdf secp256k1 curve] with [https://en.wikipedia.org/wiki/SHA-2 SHA256] hashes for authenticating -transactions. These are [https://www.secg.org/sec1-v2.pdf standardized], but have a number of downsides -compared to [http://publikationen.ub.uni-frankfurt.de/opus4/files/4280/schnorr.pdf Schnorr signatures] over the same curve: - -* '''Provable security''': Schnorr signatures are provably secure. In more detail, they are ''strongly unforgeable under chosen message attack (SUF-CMA)''Informally, this means that without knowledge of the secret key but given valid signatures of arbitrary messages, it is not possible to come up with further valid signatures. [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf in the random oracle model assuming the hardness of the elliptic curve discrete logarithm problem (ECDLP)] and [http://www.neven.org/papers/schnorr.pdf in the generic group model assuming variants of preimage and second preimage resistance of the used hash function]A detailed security proof in the random oracle model, which essentially restates [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf the original security proof by Pointcheval and Stern] more explicitly, can be found in [https://eprint.iacr.org/2016/191 a paper by Kiltz, Masny and Pan]. All these security proofs assume a variant of Schnorr signatures that use ''(e,s)'' instead of ''(R,s)'' (see Design above). Since we use a unique encoding of ''R'', there is an efficiently computable bijection that maps ''(R,s)'' to ''(e,s)'', which allows to convert a successful SUF-CMA attacker for the ''(e,s)'' variant to a successful SUF-CMA attacker for the ''(R,s)'' variant (and vice-versa). Furthermore, the proofs consider a variant of Schnorr signatures without key prefixing (see Design above), but it can be verified that the proofs are also correct for the variant with key prefixing. As a result, all the aforementioned security proofs apply to the variant of Schnorr signatures proposed in this document.. In contrast, the [https://nbn-resolving.de/urn:nbn:de:hbz:294-60803 best known results for the provable security of ECDSA] rely on stronger assumptions. -* '''Non-malleability''': The SUF-CMA security of Schnorr signatures implies that they are non-malleable. On the other hand, ECDSA signatures are inherently malleableIf ''(r,s)'' is a valid ECDSA signature for a given message and key, then ''(r,n-s)'' is also valid for the same message and key. If ECDSA is restricted to only permit one of the two variants (as Bitcoin does through a policy rule on the network), it can be [https://nbn-resolving.de/urn:nbn:de:hbz:294-60803 proven] non-malleable under stronger than usual assumptions.; a third party without access to the secret key can alter an existing valid signature for a given public key and message into another signature that is valid for the same key and message. This issue is discussed in [https://github.com/bitcoin/bips/blob/master/bip-0062.mediawiki BIP62] and [https://github.com/bitcoin/bips/blob/master/bip-0146.mediawiki BIP146]. -* '''Linearity''': Schnorr signatures provide a simple and efficient method that enables multiple collaborating parties to produce a signature that is valid for the sum of their public keys. This is the building block for various higher-level constructions that improve efficiency and privacy, such as multisignatures and others (see Applications below). - -For all these advantages, there are virtually no disadvantages, apart -from not being standardized. This document seeks to change that. As we -propose a new standard, a number of improvements not specific to Schnorr signatures can be -made: - -* '''Signature encoding''': Instead of using [https://en.wikipedia.org/wiki/X.690#DER_encoding DER]-encoding for signatures (which are variable size, and up to 72 bytes), we can use a simple fixed 64-byte format. -* '''Public key encoding''': Instead of using ''compressed'' 33-byte encodings of elliptic curve points which are common in Bitcoin today, public keys in this proposal are encoded as 32 bytes. -* '''Batch verification''': The specific formulation of ECDSA signatures that is standardized cannot be verified more efficiently in batch compared to individually, unless additional witness data is added. Changing the signature scheme offers an opportunity to address this. -* '''Completely specified''': To be safe for usage in consensus systems, the verification algorithm must be completely specified at the byte level. This guarantees that nobody can construct a signature that is valid to some verifiers but not all. This is traditionally not a requirement for digital signature schemes, and the lack of exact specification for the DER parsing of ECDSA signatures has caused problems for Bitcoin [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2015-July/009697.html in the past], needing [https://github.com/bitcoin/bips/blob/master/bip-0146.mediawiki BIP66] to address it. In this document we aim to meet this property by design. For batch verification, which is inherently non-deterministic as the verifier can choose their batches, this property implies that the outcome of verification may only differ from individual verifications with negligible probability, even to an attacker who intentionally tries to make batch- and non-batch verification differ. - -By reusing the same curve and hash function as Bitcoin uses for ECDSA, we are able to retain existing mechanisms for choosing secret and public keys, and we avoid introducing new assumptions about the security of elliptic curves and hash functions. - -== Description == - -We first build up the algebraic formulation of the signature scheme by -going through the design choices. Afterwards, we specify the exact -encodings and operations. - -=== Design === - -'''Schnorr signature variant''' Elliptic Curve Schnorr signatures for message ''m'' and public key ''P'' generally involve a point ''R'', integers ''e'' and ''s'' picked by the signer, and the base point ''G'' which satisfy ''e = hash(R || m)'' and ''s⋅G = R + e⋅P''. Two formulations exist, depending on whether the signer reveals ''e'' or ''R'': -# Signatures are pairs ''(e, s)'' that satisfy ''e = hash(s⋅G - e⋅P || m)''. This variant avoids minor complexity introduced by the encoding of the point ''R'' in the signature (see paragraphs "Encoding R and public key point P" and "Implicit Y coordinates" further below in this subsection). Moreover, revealing ''e'' instead of ''R'' allows for potentially shorter signatures: Whereas an encoding of ''R'' inherently needs about 32 bytes, the hash ''e'' can be tuned to be shorter than 32 bytes, and [http://www.neven.org/papers/schnorr.pdf a short hash of only 16 bytes suffices to provide SUF-CMA security at the target security level of 128 bits]. However, a major drawback of this optimization is that finding collisions in a short hash function is easy. This complicates the implementation of secure signing protocols in scenarios in which a group of mutually distrusting signers work together to produce a single joint signature (see Applications below). In these scenarios, which are not captured by the SUF-CMA model due its assumption of a single honest signer, a promising attack strategy for malicious co-signers is to find a collision in the hash function in order to obtain a valid signature on a message that an honest co-signer did not intent to sign. -# Signatures are pairs ''(R, s)'' that satisfy ''s⋅G = R + hash(R || m)⋅P''. This supports batch verification, as there are no elliptic curve operations inside the hashes. Batch verification enables significant speedups. - -[[File:bip-schnorr/speedup-batch.png|center|frame|This graph shows the ratio between the time it takes to verify ''n'' signatures individually and to verify a batch of ''n'' signatures. This ratio goes up logarithmically with the number of signatures, or in other words: the total time to verify ''n'' signatures grows with ''O(n / log n)''.]] - -Since we would like to avoid the fragility that comes with short hashes, the ''e'' variant does not provide significant advantages. We choose the ''R''-option, which supports batch verification. - -'''Key prefixing''' Using the verification rule above directly makes Schnorr signatures vulnerable to "related-key attacks" in which a third party can convert a signature ''(R, s)'' for public key ''P'' into a signature ''(R, s + a⋅hash(R || m))'' for public key ''P + a⋅G'' and the same message ''m'', for any given additive tweak ''a'' to the signing key. This would render signatures insecure when keys are generated using [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#public-parent-key--public-child-key BIP32's unhardened derivation] and other methods that rely on additive tweaks to existing keys such as Taproot. - -To protect against these attacks, we choose ''key prefixed''A limitation of committing to the public key (rather than to a short hash of it, or not at all) is that it removes the ability for public key recovery or verifying signatures against a short public key hash. These constructions are generally incompatible with batch verification. Schnorr signatures; changing the equation to ''s⋅G = R + hash(R || P || m)⋅P''. [https://eprint.iacr.org/2015/1135.pdf It can be shown] that key prefixing protects against related-key attacks with additive tweaks. In general, key prefixing increases robustness in multi-user settings, e.g., it seems to be a requirement for proving the MuSig multisignature scheme secure (see Applications below). - -We note that key prefixing is not strictly necessary for transaction signatures as used in Bitcoin currently, because signed transactions indirectly commit to the public keys already, i.e., ''m'' contains a commitment to ''pk''. However, this indirect commitment should not be relied upon because it may change with proposals such as SIGHASH_NOINPUT ([https://github.com/bitcoin/bips/blob/master/bip-0118.mediawiki BIP118]), and would render the signature scheme unsuitable for other purposes than signing transactions, e.g., [https://bitcoin.org/en/developer-reference#signmessage signing ordinary messages]. - -'''Encoding R and public key point P''' There exist several possibilities for encoding elliptic curve points: -# Encoding the full X and Y coordinates of ''P'' and ''R'', resulting in a 64-byte public key and a 96-byte signature. -# Encoding the full X coordinate and one bit of the Y coordinate to determine one of the two possible Y coordinates. This would result in 33-byte public keys and 65-byte signatures. -# Encoding only the X coordinate, resulting in 32-byte public keys and 64-byte signatures. - -Using the first option would be slightly more efficient for verification (around 10%), but we prioritize compactness, and therefore choose option 3. - -'''Implicit Y coordinates''' In order to support efficient verification and batch verification, the Y coordinate of ''P'' and of ''R'' cannot be ambiguous (every valid X coordinate has two possible Y coordinates). We have a choice between several options for symmetry breaking: -# Implicitly choosing the Y coordinate that is in the lower half. -# Implicitly choosing the Y coordinate that is evenSince ''p'' is odd, negation modulo ''p'' will map even numbers to odd numbers and the other way around. This means that for a valid X coordinate, one of the corresponding Y coordinates will be even, and the other will be odd.. -# Implicitly choosing the Y coordinate that is a quadratic residue (has a square root modulo the field size, or "is a square" for short)A product of two numbers is a square when either both or none of the factors are squares. As ''-1'' is not a square modulo secp256k1's field size ''p'', and the two Y coordinates corresponding to a given X coordinate are each other's negation, this means exactly one of the two must be a square.. - -In the case of ''R'' the third option is slower at signing time but a bit faster to verify, as it is possible to directly compute whether the Y coordinate is a square when the points are represented in -[https://en.wikibooks.org/wiki/Cryptography/Prime_Curve/Jacobian_Coordinates Jacobian coordinates] (a common optimization to avoid modular inverses -for elliptic curve operations). The two other options require a possibly -expensive conversion to affine coordinates first. This would even be the case if the sign or oddness were explicitly coded (option 2 in the list above). We therefore choose option 3. - -For ''P'' the speed of signing and verification does not significantly differ between any of the three options because affine coordinates of the point have to be computed anyway. For consistency reasons we choose the same option as for ''R''. The signing algorithm ensures that the signature is valid under the correct public key by negating the secret key if necessary. - -Implicit Y coordinates are not a reduction in security when expressed as the number of elliptic curve operations an attacker is expected to perform to compute the secret key. An attacker can normalize any given public key to a point whose Y coordinate is a square by negating the point if necessary. This is just a subtraction of field elements and not an elliptic curve operationThis can be formalized by a simple reduction that reduces an attack on Schnorr signatures with implicit Y coordinates to an attack to Schnorr signatures with explicit Y coordinates. The reduction works by reencoding public keys and negating the result of the hash function, which is modeled as random oracle, whenever the challenge public key has an explicit Y coordinate that is not a square. A proof sketch can be found [https://medium.com/blockstream/reducing-bitcoin-transaction-sizes-with-x-only-pubkeys-f86476af05d7 here].. - -'''Tagged Hashes''' Cryptographic hash functions are used for multiple purposes in the specification below and in Bitcoin in general. To make sure hashes used in one context can't be reinterpreted in another one, hash functions can be tweaked with a context-dependent tag name, in such a way that collisions across contexts can be assumed to be infeasible. Such collisions obviously can not be ruled out completely, but only for schemes using tagging with a unique name. As for other schemes collisions are at least less likely with tagging than without. - -For example, without tagged hashing a bip-schnorr signature could also be valid for a signature scheme where the only difference is that the arguments to the hash function are reordered. Worse, if the bip-schnorr nonce derivation function was copied or independently created, then the nonce could be accidentally reused in the other scheme leaking the secret key. - -This proposal suggests to include the tag by prefixing the hashed data with ''SHA256(tag) || SHA256(tag)''. Because this is a 64-byte long context-specific constant and the ''SHA256'' block size is also 64 bytes, optimized implementations are possible (identical to SHA256 itself, but with a modified initial state). Using SHA256 of the tag name itself is reasonably simple and efficient for implementations that don't choose to use the optimization. - -'''Final scheme''' As a result, our final scheme ends up using public key ''pk'' which is the X coordinate of a point ''P'' on the curve whose Y coordinate is a square and signatures ''(r,s)'' where ''r'' is the X coordinate of a point ''R'' whose Y coordinate is a square. The signature satisfies ''s⋅G = R + tagged_hash(r || pk || m)⋅P''. - -=== Specification === - -The following conventions are used, with constants as defined for [https://www.secg.org/sec2-v2.pdf secp256k1]: -* Lowercase variables represent integers or byte arrays. -** The constant ''p'' refers to the field size, ''0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F''. -** The constant ''n'' refers to the curve order, ''0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141''. -* Uppercase variables refer to points on the curve with equation ''y2 = x3 + 7'' over the integers modulo ''p''. -** ''is_infinite(P)'' returns whether or not ''P'' is the point at infinity. -** ''x(P)'' and ''y(P)'' are integers in the range ''0..p-1'' and refer to the X and Y coordinates of a point ''P'' (assuming it is not infinity). -** The constant ''G'' refers to the base point, for which ''x(G) = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798'' and ''y(G) = 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8''. -** Addition of points refers to the usual [https://en.wikipedia.org/wiki/Elliptic_curve#The_group_law elliptic curve group operation]. -** [https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication Multiplication (⋅) of an integer and a point] refers to the repeated application of the group operation. -* Functions and operations: -** ''||'' refers to byte array concatenation. -** The function ''x[i:j]'', where ''x'' is a byte array, returns a ''(j - i)''-byte array with a copy of the ''i''-th byte (inclusive) to the ''j''-th byte (exclusive) of ''x''. -** The function ''bytes(x)'', where ''x'' is an integer, returns the 32-byte encoding of ''x'', most significant byte first. -** The function ''bytes(P)'', where ''P'' is a point, returns ''bytes(x(P))''. -** The function ''int(x)'', where ''x'' is a 32-byte array, returns the 256-bit unsigned integer whose most significant byte first encoding is ''x''. -** The function ''is_square(x)'', where ''x'' is an integer, returns whether or not ''x'' is a quadratic residue modulo ''p''. Since ''p'' is prime, it is equivalent to the [https://en.wikipedia.org/wiki/Legendre_symbol Legendre symbol] ''(x / p) = x(p-1)/2 mod p'' being equal to ''1''For points ''P'' on the secp256k1 curve it holds that ''y(P)(p-1)/2 ≠ 0 mod p''.. -** The function ''has_square_y(P)'', where ''P'' is a point, is defined as ''not is_infinite(P) and is_square(y(P))''For points ''P'' on the secp256k1 curve it holds that ''has_square_y(P) = not has_square_y(-P)''.. -** The function ''lift_x(x)'', where ''x'' is an integer in range ''0..p-1'', returns the point ''P'' for which ''x(P) = x'' - Given a candidate X coordinate ''x'' in the range ''0..p-1'', there exist either exactly two or exactly zero valid Y coordinates. If no valid Y coordinate exists, then ''x'' is not a valid X coordinate either, i.e., no point ''P'' exists for which ''x(P) = x''. The valid Y coordinates for a given candidate ''x'' are the square roots of ''c = x3 + 7 mod p'' and they can be computed as ''y = ±c(p+1)/4 mod p'' (see [https://en.wikipedia.org/wiki/Quadratic_residue#Prime_or_prime_power_modulus Quadratic residue]) if they exist, which can be checked by squaring and comparing with ''c''. - and ''has_square_y(P)'' - If ''P := lift_x(x)'' does not fail, then ''y := y(P) = c(p+1)/4 mod p'' is square. Proof: If ''lift_x'' does not fail, ''y'' is a square root of ''c'' and therefore the [https://en.wikipedia.org/wiki/Legendre_symbol Legendre symbol] ''(c / p)'' is ''c(p-1)/2 = 1 mod p''. Because the Legendre symbol ''(y / p)'' is ''y(p-1)/2 mod p = c((p+1)/4)((p-1)/2) mod p = 1((p+1)/4) mod p = 1 mod p'', ''y'' is square. -, or fails if no such point exists. The function ''lift_x(x)'' is equivalent to the following pseudocode: -*** Let ''c = x3 + 7 mod p''. -*** Let ''y = c(p+1)/4 mod p''. -*** Fail if ''c ≠ y2 mod p''. -*** Return the unique point ''P'' such that ''x(P) = x'' and ''y(P) = y'', or fail if no such point exists. -** The function ''point(x)'', where ''x'' is a 32-byte array, returns the point ''P = lift_x(int(x))''. -** The function ''hashtag(x)'' where ''tag'' is a UTF-8 encoded tag name and ''x'' is a byte array returns the 32-byte hash ''SHA256(SHA256(tag) || SHA256(tag) || x)''. - -==== Public Key Generation ==== - -Input: -* The secret key ''sk'': a 32-byte array, generated uniformly at random - -The algorithm ''PubKey(sk)'' is defined as: -* Let ''d = int(sk)''. -* Fail if ''d = 0'' or ''d ≥ n''. -* Return ''bytes(d⋅G)''. - -Note that we use a very different public key format (32 bytes) than the ones used by existing systems (which typically use elliptic curve points as public keys, or 33-byte or 65-byte encodings of them). A side effect is that ''PubKey(sk) = PubKey(bytes(n - int(sk))'', so every public key has two corresponding secret keys. - -As an alternative to generating keys randomly, it is also possible and safe to repurpose existing key generation algorithms for ECDSA in a compatible way. The secret keys constructed by such an algorithm can be used as ''sk'' directly. The public keys constructed by such an algorithm (assuming they use the 33-byte compressed encoding) need to be converted by dropping the first byte. Specifically, [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki BIP32] and schemes built on top of it remain usable. - -==== Default Signing ==== - -Input: -* The secret key ''sk'': a 32-byte array -* The message ''m'': a 32-byte array - -The algorithm ''Sign(sk, m)'' is defined as: -* Let ''d' = int(sk)'' -* Fail if ''d' = 0'' or ''d' ≥ n'' -* Let ''P = d'⋅G'' -* Let ''d = d' '' if ''has_square_y(P)'', otherwise let ''d = n - d' ''. -* Let ''rand = hashBIPSchnorrDerive(bytes(d) || m)''. -* Let ''k' = int(rand) mod n''Note that in general, taking a uniformly random 256-bit integer modulo the curve order will produce an unacceptably biased result. However, for the secp256k1 curve, the order is sufficiently close to ''2256'' that this bias is not observable (''1 - n / 2256'' is around ''1.27 * 2-128'').. -* Fail if ''k' = 0''. -* Let ''R = k'⋅G''. -* Let ''k = k' '' if ''has_square_y(R)'', otherwise let ''k = n - k' ''. -* Let ''e = int(hashBIPSchnorr(bytes(R) || bytes(P) || m)) mod n''. -* Return the signature ''bytes(R) || bytes((k + ed) mod n)''. - -==== Alternative Signing ==== - -It should be noted that various alternative signing algorithms can be used to produce equally valid signatures. The algorithm in the previous section is deterministic, i.e., it will always produce the same signature for a given message and secret key. This method does not need a random number generator (RNG) at signing time and is thus trivially robust against failures of RNGs. Alternatively the 32-byte ''rand'' value may be generated in other ways, producing a different but still valid signature (in other words, this is not a ''unique'' signature scheme). '''No matter which method is used to generate the ''rand'' value, the value must be a fresh uniformly random 32-byte string which is not even partially predictable for the attacker.''' - -'''Synthetic nonces''' For instance when a RNG is available, 32 bytes of RNG output can be appended to the input to ''hashBIPSchnorrDerive''. This will change the corresponding line in the signing algorithm to ''rand = hashBIPSchnorrDerive(bytes(d) || m || get_32_bytes_from_rng())'', where ''get_32_bytes_from_rng()'' is the call to the RNG. Adding RNG output may improve protection against [https://moderncrypto.org/mail-archive/curves/2017/000925.html fault injection attacks and side-channel attacks], and it is safe to add the output of a low-entropy RNG. - -'''Nonce exfiltration protection''' It is possible to strengthen the nonce generation algorithm using a second device. In this case, the second device contributes randomness which the actual signer provably incorporates into its nonce. This prevents certain attacks where the signer device is compromised and intentionally tries to leak the secret key through its nonce selection. - -'''Multisignatures''' This signature scheme is compatible with various types of multisignature and threshold schemes such as [https://eprint.iacr.org/2018/068 MuSig], where a single public key requires holders of multiple secret keys to participate in signing (see Applications below). -'''It is important to note that multisignature signing schemes in general are insecure with the ''rand'' generation from the default signing algorithm above (or any other deterministic method).''' - -==== Verification ==== - -Input: -* The public key ''pk'': a 32-byte array -* The message ''m'': a 32-byte array -* A signature ''sig'': a 64-byte array - -The algorithm ''Verify(pk, m, sig)'' is defined as: -* Let ''P = point(pk)''; fail if ''point(pk)'' fails. -* Let ''r = int(sig[0:32])''; fail if ''r ≥ p''. -* Let ''s = int(sig[32:64])''; fail if ''s ≥ n''. -* Let ''e = int(hashBIPSchnorr(bytes(r) || bytes(P) || m)) mod n''. -* Let ''R = s⋅G - e⋅P''. -* Fail if ''not has_square_y(R)'' or ''x(R) ≠ r''. -* Return success iff no failure occurred before reaching this point. - -For every valid secret key ''sk'' and message ''m'', ''Verify(PubKey(sk),m,Sign(sk,m))'' will succeed. - -Note that the correctness of verification relies on the fact that ''point(pk)'' always returns a point with a square Y coordinate. A hypothetical verification algorithm that treats points as public keys, and takes the point ''P'' directly as input would fail any time a point with non-square Y is used. While it is possible to correct for this by negating points with non-square Y coordinate before further processing, this would result in a scheme where every (message, signature) pair is valid for two public keys (a type of malleability that exists for ECDSA as well, but we don't wish to retain). We avoid these problems by treating just the X coordinate as public key. - -==== Batch Verification ==== - -Input: -* The number ''u'' of signatures -* The public keys ''pk1..u'': ''u'' 32-byte arrays -* The messages ''m1..u'': ''u'' 32-byte arrays -* The signatures ''sig1..u'': ''u'' 64-byte arrays - -The algorithm ''BatchVerify(pk1..u, m1..u, sig1..u)'' is defined as: -* Generate ''u-1'' random integers ''a2...u'' in the range ''1...n-1''. They are generated deterministically using a [https://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator CSPRNG] seeded by a cryptographic hash of all inputs of the algorithm, i.e. ''seed = seed_hash(pk1..pku || m1..mu || sig1..sigu )''. A safe choice is to instantiate ''seed_hash'' with SHA256 and use [https://tools.ietf.org/html/rfc8439 ChaCha20] with key ''seed'' as a CSPRNG to generate 256-bit integers, skipping integers not in the range ''1...n-1''. -* For ''i = 1 .. u'': -** Let ''Pi = point(pki)''; fail if ''point(pki)'' fails. -** Let ''ri = int(sigi[0:32])''; fail if ''ri ≥ p''. -** Let ''si = int(sigi[32:64])''; fail if ''si ≥ n''. -** Let ''ei = int(hashBIPSchnorr(bytes(ri) || bytes(Pi) || mi)) mod n''. -** Let ''Ri = lift_x(ri)''; fail if ''lift_x(ri)'' fails. -* Fail if ''(s1 + a2s2 + ... + ausu)⋅G ≠ R1 + a2⋅R2 + ... + au⋅Ru + e1⋅P1 + (a2e2)⋅P2 + ... + (aueu)⋅Pu''. -* Return success iff no failure occurred before reaching this point. - -If all individual signatures are valid (i.e., ''Verify'' would return success for them), ''BatchVerify'' will always return success. If at least one signature is invalid, ''BatchVerify'' will return success with at most a negligible probability. - -=== Optimizations === - -Many techniques are known for optimizing elliptic curve implementations. Several of them apply here, but are out of scope for this document. Two are listed below however, as they are relevant to the design decisions: - -'''Squareness testing''' The function ''is_square(x)'' is defined as above, but can be computed more efficiently using an [https://en.wikipedia.org/wiki/Jacobi_symbol#Calculating_the_Jacobi_symbol extended GCD algorithm]. - -'''Jacobian coordinates''' Elliptic Curve operations can be implemented more efficiently by using [https://en.wikibooks.org/wiki/Cryptography/Prime_Curve/Jacobian_Coordinates Jacobian coordinates]. Elliptic Curve operations implemented this way avoid many intermediate modular inverses (which are computationally expensive), and the scheme proposed in this document is in fact designed to not need any inversions at all for verification. When operating on a point ''P'' with Jacobian coordinates ''(x,y,z)'' which is not the point at infinity and for which ''x(P)'' is defined as ''x / z2'' and ''y(P)'' is defined as ''y / z3'': -* ''has_square_y(P)'' can be implemented as ''is_square(yz mod p)''. -* ''x(P) ≠ r'' can be implemented as ''(0 ≤ r < p) and (x ≠ z2r mod p)''. - -== Applications == - -There are several interesting applications beyond simple signatures. -While recent academic papers claim that they are also possible with ECDSA, consensus support for Schnorr signature verification would significantly simplify the constructions. - -=== Multisignatures and Threshold Signatures === - -By means of an interactive scheme such as [https://eprint.iacr.org/2018/068 MuSig], participants can aggregate their public keys into a single public key which they can jointly sign for. This allows ''n''-of-''n'' multisignatures which, from a verifier's perspective, are no different from ordinary signatures, giving improved privacy and efficiency versus ''CHECKMULTISIG'' or other means. - -Moreover, Schnorr signatures are compatible with [https://web.archive.org/web/20031003232851/http://www.research.ibm.com/security/dkg.ps distributed key generation], which enables interactive threshold signatures schemes, e.g., the schemes described by [http://cacr.uwaterloo.ca/techreports/2001/corr2001-13.ps Stinson and Strobl (2001)] or [https://web.archive.org/web/20060911151529/http://theory.lcs.mit.edu/~stasio/Papers/gjkr03.pdf Genaro, Jarecki and Krawczyk (2003)]. These protocols make it possible to realize ''k''-of-''n'' threshold signatures, which ensure that any subset of size ''k'' of the set of ''n'' signers can sign but no subset of size less than ''k'' can produce a valid Schnorr signature. However, the practicality of the existing schemes is limited: most schemes in the literature have been proven secure only for the case ''k-1 < n/2'', are not secure when used concurrently in multiple sessions, or require a reliable broadcast mechanism to be secure. Further research is necessary to improve this situation. - -=== Adaptor Signatures === - -[https://download.wpsoftware.net/bitcoin/wizardry/mw-slides/2018-05-18-l2/slides.pdf Adaptor signatures] can be produced by a signer by offsetting his public nonce with a known point ''T = t⋅G'', but not offsetting his secret nonce. -A correct signature (or partial signature, as individual signers' contributions to a multisignature are called) on the same message with same nonce will then be equal to the adaptor signature offset by ''t'', meaning that learning ''t'' is equivalent to learning a correct signature. -This can be used to enable atomic swaps or even [https://eprint.iacr.org/2018/472 general payment channels] in which the atomicity of disjoint transactions is ensured using the signatures themselves, rather than Bitcoin script support. The resulting transactions will appear to verifiers to be no different from ordinary single-signer transactions, except perhaps for the inclusion of locktime refund logic. - -Adaptor signatures, beyond the efficiency and privacy benefits of encoding script semantics into constant-sized signatures, have additional benefits over traditional hash-based payment channels. Specifically, the secret values ''t'' may be reblinded between hops, allowing long chains of transactions to be made atomic while even the participants cannot identify which transactions are part of the chain. Also, because the secret values are chosen at signing time, rather than key generation time, existing outputs may be repurposed for different applications without recourse to the blockchain, even multiple times. - -=== Blind Signatures === - -A blind signature protocol is an interactive protocol that enables a signer to sign a message at the behest of another party without learning any information about the signed message or the signature. Schnorr signatures admit a very [https://www.math.uni-frankfurt.de/~dmst/research/papers/schnorr.blind_sigs_attack.2001.pdf simple blind signature scheme] which is however insecure because it's vulnerable to [https://www.iacr.org/archive/crypto2002/24420288/24420288.pdf Wagner's attack]. A known mitigation is to let the signer abort a signing session with a certain probability, and the resulting scheme can be [https://eprint.iacr.org/2019/877 proven secure under non-standard cryptographic assumptions]. - -Blind Schnorr signatures could for example be used in [https://github.com/ElementsProject/scriptless-scripts/blob/master/md/partially-blind-swap.md Partially Blind Atomic Swaps], a construction to enable transferring of coins, mediated by an untrusted escrow agent, without connecting the transactors in the public blockchain transaction graph. - -== Test Vectors and Reference Code == - -For development and testing purposes, we provide a [[bip-schnorr/test-vectors.csv|collection of test vectors in CSV format]] and a naive, highly inefficient, and non-constant time [[bip-schnorr/reference.py|pure Python 3.7 reference implementation of the signing and verification algorithm]]. -The reference implementation is for demonstration purposes only and not to be used in production environments. - -== Footnotes == - - - -== Acknowledgements == - -This document is the result of many discussions around Schnorr based signatures over the years, and had input from Johnson Lau, Greg Maxwell, Andrew Poelstra, Rusty Russell, and Anthony Towns. The authors further wish to thank all those who provided valuable feedback and reviews, including the participants of the [https://github.com/ajtowns/taproot-review structured reviews]. diff --git a/bip-schnorr/reference.py b/bip-schnorr/reference.py deleted file mode 100644 index f2a944f..0000000 --- a/bip-schnorr/reference.py +++ /dev/null @@ -1,169 +0,0 @@ -import hashlib -import binascii - -p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F -n = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - -# Points are tuples of X and Y coordinates and the point at infinity is -# represented by the None keyword. -G = (0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798, 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8) - -# This implementation can be sped up by storing the midstate after hashing -# tag_hash instead of rehashing it all the time. -def tagged_hash(tag, msg): - tag_hash = hashlib.sha256(tag.encode()).digest() - return hashlib.sha256(tag_hash + tag_hash + msg).digest() - -def is_infinity(P): - return P is None - -def x(P): - return P[0] - -def y(P): - return P[1] - -def point_add(P1, P2): - if (P1 is None): - return P2 - if (P2 is None): - return P1 - if (x(P1) == x(P2) and y(P1) != y(P2)): - return None - if (P1 == P2): - lam = (3 * x(P1) * x(P1) * pow(2 * y(P1), p - 2, p)) % p - else: - lam = ((y(P2) - y(P1)) * pow(x(P2) - x(P1), p - 2, p)) % p - x3 = (lam * lam - x(P1) - x(P2)) % p - return (x3, (lam * (x(P1) - x3) - y(P1)) % p) - -def point_mul(P, n): - R = None - for i in range(256): - if ((n >> i) & 1): - R = point_add(R, P) - P = point_add(P, P) - return R - -def bytes_from_int(x): - return x.to_bytes(32, byteorder="big") - -def bytes_from_point(P): - return bytes_from_int(x(P)) - -def point_from_bytes(b): - x = int_from_bytes(b) - if x >= p: - return None - y_sq = (pow(x, 3, p) + 7) % p - y = pow(y_sq, (p + 1) // 4, p) - if pow(y, 2, p) != y_sq: - return None - return [x, y] - -def int_from_bytes(b): - return int.from_bytes(b, byteorder="big") - -def hash_sha256(b): - return hashlib.sha256(b).digest() - -def is_square(x): - return pow(x, (p - 1) // 2, p) == 1 - -def has_square_y(P): - return not is_infinity(P) and is_square(y(P)) - -def pubkey_gen(seckey): - x = int_from_bytes(seckey) - if not (1 <= x <= n - 1): - raise ValueError('The secret key must be an integer in the range 1..n-1.') - P = point_mul(G, x) - return bytes_from_point(P) - -def schnorr_sign(msg, seckey0): - if len(msg) != 32: - raise ValueError('The message must be a 32-byte array.') - seckey0 = int_from_bytes(seckey0) - if not (1 <= seckey0 <= n - 1): - raise ValueError('The secret key must be an integer in the range 1..n-1.') - P = point_mul(G, seckey0) - seckey = seckey0 if has_square_y(P) else n - seckey0 - k0 = int_from_bytes(tagged_hash("BIPSchnorrDerive", bytes_from_int(seckey) + msg)) % n - if k0 == 0: - raise RuntimeError('Failure. This happens only with negligible probability.') - R = point_mul(G, k0) - k = n - k0 if not has_square_y(R) else k0 - e = int_from_bytes(tagged_hash("BIPSchnorr", bytes_from_point(R) + bytes_from_point(P) + msg)) % n - return bytes_from_point(R) + bytes_from_int((k + e * seckey) % n) - -def schnorr_verify(msg, pubkey, sig): - if len(msg) != 32: - raise ValueError('The message must be a 32-byte array.') - if len(pubkey) != 32: - raise ValueError('The public key must be a 32-byte array.') - if len(sig) != 64: - raise ValueError('The signature must be a 64-byte array.') - P = point_from_bytes(pubkey) - if (P is None): - return False - r = int_from_bytes(sig[0:32]) - s = int_from_bytes(sig[32:64]) - if (r >= p or s >= n): - return False - e = int_from_bytes(tagged_hash("BIPSchnorr", sig[0:32] + pubkey + msg)) % n - R = point_add(point_mul(G, s), point_mul(P, n - e)) - if R is None or not has_square_y(R) or x(R) != r: - return False - return True - -# -# The following code is only used to verify the test vectors. -# -import csv - -def test_vectors(): - all_passed = True - with open('test-vectors.csv', newline='') as csvfile: - reader = csv.reader(csvfile) - reader.__next__() - for row in reader: - (index, seckey, pubkey, msg, sig, result, comment) = row - pubkey = bytes.fromhex(pubkey) - msg = bytes.fromhex(msg) - sig = bytes.fromhex(sig) - result = result == 'TRUE' - print('\nTest vector #%-3i: ' % int(index)) - if seckey != '': - seckey = bytes.fromhex(seckey) - pubkey_actual = pubkey_gen(seckey) - if pubkey != pubkey_actual: - print(' * Failed key generation.') - print(' Expected key:', pubkey.hex().upper()) - print(' Actual key:', pubkey_actual.hex().upper()) - sig_actual = schnorr_sign(msg, seckey) - if sig == sig_actual: - print(' * Passed signing test.') - else: - print(' * Failed signing test.') - print(' Expected signature:', sig.hex().upper()) - print(' Actual signature:', sig_actual.hex().upper()) - all_passed = False - result_actual = schnorr_verify(msg, pubkey, sig) - if result == result_actual: - print(' * Passed verification test.') - else: - print(' * Failed verification test.') - print(' Expected verification result:', result) - print(' Actual verification result:', result_actual) - if comment: - print(' Comment:', comment) - all_passed = False - print() - if all_passed: - print('All test vectors passed.') - else: - print('Some test vectors failed.') - return all_passed - -if __name__ == '__main__': - test_vectors() diff --git a/bip-schnorr/test-vectors.csv b/bip-schnorr/test-vectors.csv deleted file mode 100644 index 3970803..0000000 --- a/bip-schnorr/test-vectors.csv +++ /dev/null @@ -1,16 +0,0 @@ -index,secret key,public key,message,signature,verification result,comment -0,0000000000000000000000000000000000000000000000000000000000000001,79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798,0000000000000000000000000000000000000000000000000000000000000000,528F745793E8472C0329742A463F59E58F3A3F1A4AC09C28F6F8514D4D0322A258BD08398F82CF67B812AB2C7717CE566F877C2F8795C846146978E8F04782AE,TRUE, -1,B7E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEF,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,667C2F778E0616E611BD0C14B8A600C5884551701A949EF0EBFD72D452D64E844160BCFC3F466ECB8FACD19ADE57D8699D74E7207D78C6AEDC3799B52A8E0598,TRUE, -2,C90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B14E5C9,DD308AFEC5777E13121FA72B9CC1B7CC0139715309B086C960E18FD969774EB8,5E2D58D8B3BCDF1ABADEC7829054F90DDA9805AAB56C77333024B9D0A508B75C,2D941B38E32624BF0AC7669C0971B990994AF6F9B18426BF4F4E7EC10E6CDF386CF646C6DDAFCFA7F1993EEB2E4D66416AEAD1DDAE2F22D63CAD901412D116C6,TRUE, -3,0B432B2677937381AEF05BB02A66ECD012773062CF3FA2549E44F58ED2401710,25D1DFF95105F5253C4022F628A996AD3A0D95FBF21D468A1B33F8C160D8F517,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,8BD2C11604B0A87A443FCC2E5D90E5328F934161B18864FB48CE10CB59B45FB9B5B2A0F129BD88F5BDC05D5C21E5C57176B913002335784F9777A24BD317CD36,TRUE,test fails if msg is reduced modulo p or n -4,,D69C3509BB99E412E68B0FE8544E72837DFA30746D8BE2AA65975F29D22DC7B9,4DF3C3F68FCC83B27E9D42C90431A72499F17875C81A599B566C9889B9696703,00000000000000000000003B78CE563F89A0ED9414F5AA28AD0D96D6795F9C63EE374AC7FAE927D334CCB190F6FB8FD27A2DDC639CCEE46D43F113A4035A2C7F,TRUE, -5,,EEFDEA4CDB677750A420FEE807EACF21EB9898AE79B9768766E4FAA04A2D4A34,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,667C2F778E0616E611BD0C14B8A600C5884551701A949EF0EBFD72D452D64E844160BCFC3F466ECB8FACD19ADE57D8699D74E7207D78C6AEDC3799B52A8E0598,FALSE,public key not on the curve -6,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9935554D1AA5F0374E5CDAACB3925035C7C169B27C4426DF0A6B19AF3BAEAB138,FALSE,has_square_y(R) is false -7,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,10AC49A6A2EBF604189C5F40FC75AF2D42D77DE9A2782709B1EB4EAF1CFE9108D7003B703A3499D5E29529D39BA040A44955127140F81A8A89A96F992AC0FE79,FALSE,negated message -8,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,667C2F778E0616E611BD0C14B8A600C5884551701A949EF0EBFD72D452D64E84BE9F4303C0B9913470532E6521A827951D39F5C631CFD98CE39AC4D7A5A83BA9,FALSE,negated s value -9,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,000000000000000000000000000000000000000000000000000000000000000099D2F0EBC2996808208633CD9926BF7EC3DAB73DAAD36E85B3040A698E6D1CE0,FALSE,sG - eP is infinite. Test fails in single verification if has_square_y(inf) is defined as true and x(inf) as 0 -10,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,000000000000000000000000000000000000000000000000000000000000000124E81D89F01304695CE943F7D5EBD00EF726A0864B4FF33895B4E86BEADC5456,FALSE,sG - eP is infinite. Test fails in single verification if has_square_y(inf) is defined as true and x(inf) as 1 -11,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,4A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1D4160BCFC3F466ECB8FACD19ADE57D8699D74E7207D78C6AEDC3799B52A8E0598,FALSE,sig[0:32] is not an X coordinate on the curve -12,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F4160BCFC3F466ECB8FACD19ADE57D8699D74E7207D78C6AEDC3799B52A8E0598,FALSE,sig[0:32] is equal to field size -13,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,667C2F778E0616E611BD0C14B8A600C5884551701A949EF0EBFD72D452D64E84FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141,FALSE,sig[32:64] is equal to curve order -14,,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC30,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,667C2F778E0616E611BD0C14B8A600C5884551701A949EF0EBFD72D452D64E844160BCFC3F466ECB8FACD19ADE57D8699D74E7207D78C6AEDC3799B52A8E0598,FALSE,public key is not a valid X coordinate because it exceeds the field size diff --git a/bip-schnorr/test-vectors.py b/bip-schnorr/test-vectors.py deleted file mode 100644 index 195b61b..0000000 --- a/bip-schnorr/test-vectors.py +++ /dev/null @@ -1,241 +0,0 @@ -import sys -from reference import * - -def vector0(): - seckey = bytes_from_int(1) - msg = bytes_from_int(0) - sig = schnorr_sign(msg, seckey) - pubkey = pubkey_gen(seckey) - - # The point reconstructed from the public key has an even Y coordinate. - pubkey_point = point_from_bytes(pubkey) - assert(pubkey_point[1] & 1 == 0) - - return (seckey, pubkey, msg, sig, "TRUE", None) - -def vector1(): - seckey = bytes_from_int(0xB7E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEF) - msg = bytes_from_int(0x243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89) - sig = schnorr_sign(msg, seckey) - pubkey = pubkey_gen(seckey) - - # The point reconstructed from the public key has an odd Y coordinate. - pubkey_point = point_from_bytes(pubkey) - assert(pubkey_point[1] & 1 == 1) - - return (seckey, pubkey, msg, sig, "TRUE", None) - -def vector2(): - seckey = bytes_from_int(0xC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B14E5C9) - msg = bytes_from_int(0x5E2D58D8B3BCDF1ABADEC7829054F90DDA9805AAB56C77333024B9D0A508B75C) - sig = schnorr_sign(msg, seckey) - - # This signature vector would not verify if the implementer checked the - # squareness of the X coordinate of R instead of the Y coordinate. - R = point_from_bytes(sig[0:32]) - assert(not is_square(R[0])) - - return (seckey, pubkey_gen(seckey), msg, sig, "TRUE", None) - -def vector3(): - seckey = bytes_from_int(0x0B432B2677937381AEF05BB02A66ECD012773062CF3FA2549E44F58ED2401710) - msg = bytes_from_int(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) - sig = schnorr_sign(msg, seckey) - return (seckey, pubkey_gen(seckey), msg, sig, "TRUE", "test fails if msg is reduced modulo p or n") - -# Signs with a given nonce. This can be INSECURE and is only INTENDED FOR -# GENERATING TEST VECTORS. Results in an invalid signature if y(kG) is not -# square. -def insecure_schnorr_sign_fixed_nonce(msg, seckey0, k): - if len(msg) != 32: - raise ValueError('The message must be a 32-byte array.') - seckey0 = int_from_bytes(seckey0) - if not (1 <= seckey0 <= n - 1): - raise ValueError('The secret key must be an integer in the range 1..n-1.') - P = point_mul(G, seckey0) - seckey = seckey0 if has_square_y(P) else n - seckey0 - R = point_mul(G, k) - e = int_from_bytes(tagged_hash("BIPSchnorr", bytes_from_point(R) + bytes_from_point(P) + msg)) % n - return bytes_from_point(R) + bytes_from_int((k + e * seckey) % n) - -# Creates a singature with a small x(R) by using k = 1/2 -def vector4(): - one_half = 0x7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0 - seckey = bytes_from_int(0x763758E5CBEEDEE4F7D3FC86F531C36578933228998226672F13C4F0EBE855EB) - msg = bytes_from_int(0x4DF3C3F68FCC83B27E9D42C90431A72499F17875C81A599B566C9889B9696703) - sig = insecure_schnorr_sign_fixed_nonce(msg, seckey, one_half) - return (None, pubkey_gen(seckey), msg, sig, "TRUE", None) - -default_seckey = bytes_from_int(0xB7E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEF) -default_msg = bytes_from_int(0x243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89) - -# Public key is not on the curve -def vector5(): - # This creates a dummy signature that doesn't have anything to do with the - # public key. - seckey = default_seckey - msg = default_msg - sig = schnorr_sign(msg, seckey) - - pubkey = bytes_from_int(0xEEFDEA4CDB677750A420FEE807EACF21EB9898AE79B9768766E4FAA04A2D4A34) - assert(point_from_bytes(pubkey) is None) - - return (None, pubkey, msg, sig, "FALSE", "public key not on the curve") - -def vector6(): - seckey = default_seckey - msg = default_msg - k = 3 - sig = insecure_schnorr_sign_fixed_nonce(msg, seckey, k) - - # Y coordinate of R is not a square - R = point_mul(G, k) - assert(not has_square_y(R)) - - return (None, pubkey_gen(seckey), msg, sig, "FALSE", "has_square_y(R) is false") - -def vector7(): - seckey = default_seckey - msg = int_from_bytes(default_msg) - neg_msg = bytes_from_int(n - msg) - sig = schnorr_sign(neg_msg, seckey) - return (None, pubkey_gen(seckey), bytes_from_int(msg), sig, "FALSE", "negated message") - -def vector8(): - seckey = default_seckey - msg = default_msg - sig = schnorr_sign(msg, seckey) - sig = sig[0:32] + bytes_from_int(n - int_from_bytes(sig[32:64])) - return (None, pubkey_gen(seckey), msg, sig, "FALSE", "negated s value") - -def bytes_from_point_inf0(P): - if P == None: - return bytes_from_int(0) - return bytes_from_int(P[0]) - -def vector9(): - seckey = default_seckey - msg = default_msg - - # Override bytes_from_point in schnorr_sign to allow creating a signature - # with k = 0. - k = 0 - bytes_from_point_tmp = bytes_from_point.__code__ - bytes_from_point.__code__ = bytes_from_point_inf0.__code__ - sig = insecure_schnorr_sign_fixed_nonce(msg, seckey, k) - bytes_from_point.__code__ = bytes_from_point_tmp - - return (None, pubkey_gen(seckey), msg, sig, "FALSE", "sG - eP is infinite. Test fails in single verification if has_square_y(inf) is defined as true and x(inf) as 0") - -def bytes_from_point_inf1(P): - if P == None: - return bytes_from_int(1) - return bytes_from_int(P[0]) - -def vector10(): - seckey = default_seckey - msg = default_msg - - # Override bytes_from_point in schnorr_sign to allow creating a signature - # with k = 0. - k = 0 - bytes_from_point_tmp = bytes_from_point.__code__ - bytes_from_point.__code__ = bytes_from_point_inf1.__code__ - sig = insecure_schnorr_sign_fixed_nonce(msg, seckey, k) - bytes_from_point.__code__ = bytes_from_point_tmp - - return (None, pubkey_gen(seckey), msg, sig, "FALSE", "sG - eP is infinite. Test fails in single verification if has_square_y(inf) is defined as true and x(inf) as 1") - -# It's cryptographically impossible to create a test vector that fails if run -# in an implementation which merely misses the check that sig[0:32] is an X -# coordinate on the curve. This test vector just increases test coverage. -def vector11(): - seckey = default_seckey - msg = default_msg - sig = schnorr_sign(msg, seckey) - - # Replace R's X coordinate with an X coordinate that's not on the curve - x_not_on_curve = bytes_from_int(0x4A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1D) - assert(point_from_bytes(x_not_on_curve) is None) - sig = x_not_on_curve + sig[32:64] - - return (None, pubkey_gen(seckey), msg, sig, "FALSE", "sig[0:32] is not an X coordinate on the curve") - -# It's cryptographically impossible to create a test vector that fails if run -# in an implementation which merely misses the check that sig[0:32] is smaller -# than the field size. This test vector just increases test coverage. -def vector12(): - seckey = default_seckey - msg = default_msg - sig = schnorr_sign(msg, seckey) - - # Replace R's X coordinate with an X coordinate that's equal to field size - sig = bytes_from_int(p) + sig[32:64] - - return (None, pubkey_gen(seckey), msg, sig, "FALSE", "sig[0:32] is equal to field size") - -# It's cryptographically impossible to create a test vector that fails if run -# in an implementation which merely misses the check that sig[32:64] is smaller -# than the curve order. This test vector just increases test coverage. -def vector13(): - seckey = default_seckey - msg = default_msg - sig = schnorr_sign(msg, seckey) - - # Replace s with a number that's equal to the curve order - sig = sig[0:32] + bytes_from_int(n) - - return (None, pubkey_gen(seckey), msg, sig, "FALSE", "sig[32:64] is equal to curve order") - -# Test out of range pubkey -# It's cryptographically impossible to create a test vector that fails if run -# in an implementation which accepts out of range pubkeys because we can't find -# a secret key for such a public key and therefore can not create a signature. -# This test vector just increases test coverage. -def vector14(): - # This creates a dummy signature that doesn't have anything to do with the - # public key. - seckey = default_seckey - msg = default_msg - sig = schnorr_sign(msg, seckey) - - pubkey_int = p + 1 - pubkey = bytes_from_int(pubkey_int) - assert(point_from_bytes(pubkey) is None) - # If an implementation would reduce a given public key modulo p then the - # pubkey would be valid - assert(point_from_bytes(bytes_from_int(pubkey_int % p)) is not None) - - return (None, pubkey, msg, sig, "FALSE", "public key is not a valid X coordinate because it exceeds the field size") - -vectors = [ - vector0(), - vector1(), - vector2(), - vector3(), - vector4(), - vector5(), - vector6(), - vector7(), - vector8(), - vector9(), - vector10(), - vector11(), - vector12(), - vector13(), - vector14() - ] - -# Converts the byte strings of a test vector into hex strings -def bytes_to_hex(seckey, pubkey, msg, sig, result, comment): - return (seckey.hex().upper() if seckey is not None else None, pubkey.hex().upper(), msg.hex().upper(), sig.hex().upper(), result, comment) - -vectors = list(map(lambda vector: bytes_to_hex(vector[0], vector[1], vector[2], vector[3], vector[4], vector[5]), vectors)) - -def print_csv(vectors): - writer = csv.writer(sys.stdout) - writer.writerow(("index", "secret key", "public key", "message", "signature", "verification result", "comment")) - for (i,v) in enumerate(vectors): - writer.writerow((i,)+v) - -print_csv(vectors) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki deleted file mode 100644 index ca66b3e..0000000 --- a/bip-taproot.mediawiki +++ /dev/null @@ -1,311 +0,0 @@ -
-  BIP: bip-taproot
-  Layer: Consensus (soft fork)
-  Title: Taproot: SegWit version 1 output spending rules
-  Author: Pieter Wuille 
-          Jonas Nick 
-          Anthony Towns 
-  Comments-Summary: No comments yet.
-  Comments-URI:
-  Status: Draft
-  Type: Standards Track
-  Created:
-  License: BSD-3-Clause
-  Requires: bip-schnorr
-  Post-History: 2019-05-06: https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2019-May/016914.html [bitcoin-dev] Taproot proposal
-
- -==Introduction== - -===Abstract=== - -This document proposes a new SegWit version 1 output type, with spending rules based on Taproot, Schnorr signatures, and Merkle branches. - -===Copyright=== - -This document is licensed under the 3-clause BSD license. - -===Motivation=== - -This proposal aims to improve privacy, efficiency, and flexibility of Bitcoin's scripting capabilities without adding new security assumptions'''What does not adding security assumptions mean?''' Unforgeability of signatures is a necessary requirement to prevent theft. At least when treating script execution as a digital signature scheme itself, unforgeability can be [https://github.com/apoelstra/taproot proven] in the Random Oracle Model assuming the Discrete Logarithm problem is hard. A [https://nbn-resolving.de/urn:nbn:de:hbz:294-60803 proof] for unforgeability of ECDSA in the current script system needs non-standard assumptions on top of that. Note that it is hard in general to model exactly what security for script means, as it depends on the policies and protocols used by wallet software.. Specifically, it seeks to minimize how much information about the spendability conditions of a transaction output is revealed on chain at creation or spending time and to add a number of upgrade mechanisms, while fixing a few minor but long-standing issues. - -==Design== - -A number of related ideas for improving Bitcoin's scripting capabilities have been previously proposed: Schnorr signatures (bip-schnorr), Merkle branches ("MAST", [https://github.com/bitcoin/bips/blob/master/bip-0114.mediawiki BIP114], [https://github.com/bitcoin/bips/blob/master/bip-0117.mediawiki BIP117]), new sighash modes ([https://github.com/bitcoin/bips/blob/master/bip-0118.mediawiki BIP118]), new opcodes like CHECKSIGFROMSTACK, [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-January/015614.html Taproot], [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-February/015700.html Graftroot], [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-July/016249.html G'root], and [https://bitcointalk.org/index.php?topic=1377298.0 cross-input aggregation]. - -Combining all these ideas in a single proposal would be an extensive change, be hard to review, and likely miss new discoveries that otherwise could have been made along the way. Not all are equally mature as well. For example, cross-input aggregation [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-March/015838.html interacts] in complex ways with upgrade mechanisms, and solutions to that are still [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-October/016461.html in flux]. On the other hand, separating them all into independent upgrades would reduce the efficiency and privacy gains to be had, and wallet and service providers may not be inclined to go through many incremental updates. Therefore, we're faced with a tradeoff between functionality and scope creep. In this design we strike a balance by focusing on the structural script improvements offered by Taproot and Merkle branches, as well as changes necessary to make them usable and efficient. For things like sighashes and opcodes we include fixes for known problems, but exclude new features that can be added independently with no downsides. - -As a result we choose this combination of technologies: -* '''Merkle branches''' let us only reveal the actually executed part of the script to the blockchain, as opposed to all possible ways a script can be executed. Among the various known mechanisms for implementing this, one where the Merkle tree becomes part of the script's structure directly maximizes the space savings, so that approach is chosen. -* '''Taproot''' on top of that lets us merge the traditionally separate pay-to-pubkey and pay-to-scripthash policies, making all outputs spendable by either a key or (optionally) a script, and indistinguishable from each other. As long as the key-based spending path is used for spending, it is not revealed whether a script path was permitted as well, resulting in space savings and an increase in scripting privacy at spending time. -* Taproot's advantages become apparent under the assumption that most applications involve outputs that could be spent by all parties agreeing. That's where '''Schnorr''' signatures come in, as they permit [https://eprint.iacr.org/2018/068 key aggregation]: a public key can be constructed from multiple participant public keys, and which requires cooperation between all participants to sign for. Such multi-party public keys and signatures are indistinguishable from their single-party equivalents. This means that with taproot most applications can use the key-based spending path, which is both efficient and private. This can be generalized to arbitrary M-of-N policies, as Schnorr signatures support threshold signing, at the cost of more complex setup protocols. -* As Schnorr signatures also permit '''batch validation''', allowing multiple signatures to be validated together more efficiently than validating each one independently, we make sure all parts of the design are compatible with this. -* Where unused bits appear as a result of the above changes, they are reserved for mechanisms for '''future extensions'''. As a result, every script in the Merkle tree has an associated version such that new script versions can be introduced with a soft fork while remaining compatible with bip-taproot. Additionally, future soft forks can make use of the currently unused annex in the witness (see [[#Rationale]]). -* While the core semantics of the '''signature hashing algorithm''' are not changed, a number of improvements are included in this proposal. The new signature hashing algorithm fixes the verification capabilities of offline signing devices by including amount and scriptPubKey in the signature message, avoids unnecessary hashing, uses '''tagged hashes''' and defines a default sighash byte. -* The '''public key is directly included in the output''' in contrast to typical earlier constructions which store a hash of the public key or script in the output. This has the same cost for senders and is more space efficient overall if the key-based spending path is taken. '''Why is the public key directly included in the output?''' While typical earlier constructions store a hash of a script or a public key in the output, this is rather wasteful when a public key is always involved. To guarantee batch verifiability, the public key must be known to every verifier, and thus only revealing its hash as an output would imply adding an additional 32 bytes to the witness. Furthermore, to maintain [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2016-January/012198.html 128-bit collision security] for outputs, a 256-bit hash would be required anyway, which is comparable in size (and thus in cost for senders) to revealing the public key directly. While the usage of public key hashes is often said to protect against ECDLP breaks or quantum computers, this protection is very weak at best: transactions are not protected while being confirmed, and a very [https://twitter.com/pwuille/status/1108097835365339136 large portion] of the currency's supply is not under such protection regardless. Actual resistance to such systems can be introduced by relying on different cryptographic assumptions, but this proposal focuses on improvements that do not change the security model. - -Informally, the resulting design is as follows: a new witness version is added (version 1), whose programs consist of 32-byte encodings of points ''Q''. ''Q'' is computed as ''P + hash(P||m)G'' for a public key ''P'', and the root ''m'' of a Merkle tree whose leaves consist of a version number and a script. These outputs can be spent directly by providing a signature for ''Q'', or indirectly by revealing ''P'', the script and leaf version, inputs that satisfy the script, and a Merkle path that proves ''Q'' committed to that leaf. All hashes in this construction (the hash for computing ''Q'' from ''P'', the hashes inside the Merkle tree's inner nodes, and the signature hashes used) are tagged to guarantee domain separation. - -== Specification == - -This section specifies the Taproot consensus rules. Validity is defined by exclusion: a block or transaction is valid if no condition exists that marks it failed. - -The notation below follows that of [https://github.com/sipa/bips/blob/bip-schnorr/bip-schnorr.mediawiki#design bip-schnorr]. This includes the ''hashtag(x)'' notation to refer to ''SHA256(SHA256(tag) || SHA256(tag) || x)''. To the best of the authors' knowledge, no existing use of SHA256 in Bitcoin feeds it a message that starts with two single SHA256 outputs, making collisions between ''hashtag'' with other hashes extremely unlikely. - -=== Script validation rules === - -A Taproot output is a native SegWit output (see [https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki BIP141]) with version number 1, and a 32-byte witness program. -The following rules only apply when such an output is being spent. Any other outputs, including version 1 outputs with lengths other than 32 bytes, or P2SH-wrapped version 1 outputs'''Why is P2SH-wrapping not supported?''' Using P2SH-wrapped outputs only provides 80-bit collision security due to the use of a 160-bit hash. This is considered low, and becomes a security risk whenever the output includes data from more than a single party (public keys, hashes, ...)., remain unencumbered. - -* Let ''q'' be the 32-byte array containing the witness program (the second push in the scriptPubKey) which represents a public key according to bip-schnorr. -* Fail if the witness stack has 0 elements. -* If there are at least two witness elements, and the first byte of the last element is 0x50'''Why is the first byte of the annex 0x50?''' The 0x50 is chosen as it could not be confused with a valid P2WPKH or P2WSH spending. As the control block's initial byte's lowest bit is used to indicate the public key's Y squareness, each leaf version needs an even byte value and the immediately following odd byte value that are both not yet used in P2WPKH or P2WSH spending. To indicate the annex, only an "unpaired" available byte is necessary like 0x50. This choice maximizes the available options for future script versions., this last element is called ''annex'' ''a'''''What is the purpose of the annex?''' The annex is a reserved space for future extensions, such as indicating the validation costs of computationally expensive new opcodes in a way that is recognizable without knowing the scriptPubKey of the output being spent. Until the meaning of this field is defined by another softfork, users SHOULD NOT include annex in transactions, or it may lead to PERMANENT FUND LOSS. and is removed from the witness stack. The annex (or the lack of thereof) is always covered by the signature and contributes to transaction weight, but is otherwise ignored during taproot validation. -* If there is exactly one element left in the witness stack, key path spending is used: -** The single witness stack element is interpreted as the signature and must be valid (see the next section) for the public key ''q'' (see the next subsection). -* If there are at least two witness elements left, script path spending is used: -** Call the second-to-last stack element ''s'', the script. -** The last stack element is called the control block ''c'', and must have length ''33 + 32m'', for a value of ''m'' that is an integer between 0 and 128'''Why is the Merkle path length limited to 128?''' The optimally space-efficient Merkle tree can be constructed based on the probabilities of the scripts in the leaves, using the Huffman algorithm. This algorithm will construct branches with lengths approximately equal to ''log2(1/probability)'', but to have branches longer than 128 you would need to have scripts with an execution chance below 1 in ''2128''. As that is our security bound, scripts that truly have such a low chance can probably be removed entirely., inclusive. Fail if it does not have such a length. -** Let ''p = c[1:33]'' and let ''P = point(p)'' where ''point'' and ''[:]'' are defined as in bip-schnorr. Fail if this point is not on the curve. -** Let ''v = c[0] & 0xfe'' and call it the ''leaf version'''''What constraints are there on the leaf version?''' First, the leaf version cannot be odd as ''c[0] & 0xfe'' will always be even, and cannot be ''0x50'' as that would result in ambiguity with the annex. In addition, in order to support some forms of static analysis that rely on being able to identify script spends without access to the output being spent, it is recommended to avoid using any leaf versions that would conflict with a valid first byte of either a valid P2WPKH pubkey or a valid P2WSH script (that is, both ''v'' and ''v | 1'' should be an undefined, invalid or disabled opcode or an opcode that is not valid as the first opcode). The values that comply to this rule are the 32 even values between ''0xc0'' and ''0xfe'' and also ''0x66'', ''0x7e'', ''0x80'', ''0x84'', ''0x96'', ''0x98'', ''0xba'', ''0xbc'', ''0xbe''. Note also that this constraint implies that leaf versions should be shared amongst different witness versions, as knowing the witness version requires access to the output being spent.. -** Let ''k0 = hashTapLeaf(v || compact_size(size of s) || s)''; also call it the ''tapleaf hash''. -** For ''j'' in ''[0,1,...,m-1]'': -*** Let ''ej = c[33+32j:65+32j]''. -*** Let ''kj+1 depend on whether ''kj < ej'' (lexicographically)'''Why are child elements sorted before hashing in the Merkle tree?''' By doing so, it is not necessary to reveal the left/right directions along with the hashes in revealed Merkle branches. This is possible because we do not actually care about the position of specific scripts in the tree; only that they are actually committed to.: -**** If ''kj < ej'': ''kj+1 = hashTapBranch(kj || ej)'''''Why not use a more efficient hash construction for inner Merkle nodes?''' The chosen construction does require two invocations of the SHA256 compression functions, one of which can be avoided in theory (see [https://github.com/bitcoin/bips/blob/master/bip-0098.mediawiki BIP98]). However, it seems preferable to stick to constructions that can be implemented using standard cryptographic primitives, both for implementation simplicity and analyzability. If necessary, a significant part of the second compression function can be optimized out by [https://github.com/bitcoin/bitcoin/pull/13191 specialization] for 64-byte inputs.. -**** If ''kj ≥ ej'': ''kj+1 = hashTapBranch(ej || kj)''. -** Let ''t = hashTapTweak(p || km)''. -** If ''t ≥ 0xFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141'' (order of secp256k1), fail. -** Let ''Q = point(q) if (c[0] & 1) = 1 and -point(q) otherwise'''''Why is it necessary to reveal a bit to indicate if the point represented by the output public key is negated in a script path spend?''' The ''point'' function (defined in bip-schnorr) always constructs a point with a square Y coordinate, but because ''Q'' is constructed by adding the taproot tweak to the internal public key ''P'', it cannot easily be guaranteed that ''Q'' in fact has such a Y coordinate. Therefore, before verifying the taproot tweak the original point is restored by negating if necessary. We can not ignore the Y coordinate because it would prevent batch verification. Trying out multiple internal keys until there's such a ''Q'' is possible but undesirable and unnecessary since this information about the Y coordinate only consumes an unused bit.. Fail if this point is not on the curve. -** If ''Q ≠ P + int(t)G'', fail. -** Execute the script, according to the applicable script rules'''What are the applicable script rules in script path spends?''' Bip-tapscript specifies validity rules that apply for leaf version 0xc0, but future proposals can introduce rules for other leaf versions., using the witness stack elements excluding the script ''s'', the control block ''c'', and the annex ''a'' if present, as initial stack. - -''q'' is referred to as ''taproot output key'' and ''p'' as ''taproot internal key''. - -=== Signature validation rules === - -We first define a reusable common signature message calculation function, followed by the actual signature validation as it's used in key path spending. - -==== Common signature message ==== - -The function ''SigMsg(hash_type, ext_flag)'' computes the message being signed as a byte array. It is implicitly also a function of the spending transaction and the outputs it spends, but these are not listed to keep notation simple. - -The parameter ''hash_type'' is an 8-bit unsigned value. The SIGHASH encodings from the legacy script system are reused, including SIGHASH_ALL, SIGHASH_NONE, SIGHASH_SINGLE, and SIGHASH_ANYONECANPAY, plus the default ''hash_type'' value ''0x00'' which results in signing over the whole transaction just as for SIGHASH_ALL. The following restrictions apply, which cause validation failure if violated: -* Using any undefined ''hash_type'' (not ''0x00'', ''0x01'', ''0x02'', ''0x03'', ''0x81'', ''0x82'', or ''0x83'''''Why reject unknown ''hash_type'' values?''' By doing so, it is easier to reason about the worst case amount of signature hashing an implementation with adequate caching must perform.). -* Using SIGHASH_SINGLE without a "corresponding output" (an output with the same index as the input being verified). - -The parameter ''ext_flag'' is an integer in range 0-127, and is used for indicating (in the message) that extensions are added at the end of the message'''What extensions use the ''ext_flag'' mechanism?''' Bip-tapscript reuses the same common signature message algorithm, but adds tapscript-specific data at the end, which is indicated using ''ext_flag = 1''.. - -If the parameters take acceptable values, the message is the concatenation of the following data, in order(with byte size of each item listed in parentheses). Numerical values in 2, 4, or 8-byte are encoded in little-endian. - -* Control: -** ''hash_type'' (1). -* Transaction data: -** ''nVersion'' (4): the ''nVersion'' of the transaction. -** ''nLockTime'' (4): the ''nLockTime'' of the transaction. -** If the ''hash_type & 0x80'' does not equal SIGHASH_ANYONECANPAY: -*** ''sha_prevouts'' (32): the SHA256 of the serialization of all input outpoints. -*** ''sha_amounts'' (32): the SHA256 of the serialization of all input amounts. -*** ''sha_sequences'' (32): the SHA256 of the serialization of all input ''nSequence''. -** If ''hash_type & 3'' does not equal SIGHASH_NONE or SIGHASH_SINGLE: -*** ''sha_outputs'' (32): the SHA256 of the serialization of all outputs in CTxOut format. -* Data about this input: -** ''spend_type'' (1): equal to ''(ext_flag * 2) + annex_present'', where ''annex_present'' is 0 if no annex is present, or 1 otherwise (the original witness stack has two or more witness elements, and the first byte of the last element is ''0x50'') -** ''scriptPubKey'' (35): ''scriptPubKey'' of the previous output spent by this input, serialized as script inside CTxOut. Its size is always 35 bytes. -** If ''hash_type & 0x80'' equals SIGHASH_ANYONECANPAY: -*** ''outpoint'' (36): the COutPoint of this input (32-byte hash + 4-byte little-endian). -*** ''amount'' (8): value of the previous output spent by this input. -*** ''nSequence'' (4): ''nSequence'' of this input. -** If ''hash_type & 0x80'' does not equal SIGHASH_ANYONECANPAY: -*** ''input_index'' (4): index of this input in the transaction input vector. Index of the first input is 0. -** If an annex is present (the lowest bit of ''spend_type'' is set): -*** ''sha_annex'' (32): the SHA256 of ''(compact_size(size of annex) || annex)'', where ''annex'' includes the mandatory ''0x50'' prefix. -* Data about this output: -** If ''hash_type & 3'' equals SIGHASH_SINGLE: -*** ''sha_single_output'' (32): the SHA256 of the corresponding output in CTxOut format. - -The total length of ''SigMsg()'' is at most ''209'' bytes'''What is the output length of ''SigMsg()''?''' The total length of ''SigMsg()'' can be computed using the following formula: ''177 - is_anyonecanpay * 52 - is_none * 32 + has_annex * 32''.. Note that this does not include the size of sub-hashes such as ''sha_prevouts'', which may be cached across signatures of the same transaction. - -In summary, the semantics of the [https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki BIP143] sighash types remain unchanged, except the following: -# The way and order of serialization is changed.'''Why is the serialization in the signature message changed?''' Hashes that go into the signature message and the message itself are now computed with a single SHA256 invocation instead of double SHA256. There is no expected security improvement by doubling SHA256 because this only protects against length-extension attacks against SHA256 which are not a concern for signature messages because there is no secret data. Therefore doubling SHA256 is a waste of resources. The message computation now follows a logical order with transaction level data first, then input data and output data. This allows to efficiently cache the transaction part of the message across different inputs using the SHA256 midstate. Additionally, sub-hashes can be skipped when calculating the message (for example `sha_prevouts` if SIGHASH_ANYONECANPAY is set) instead of setting them to zero and then hashing them as in BIP143. Despite that, collisions are made impossible by committing to the length of the data (implicit in ''hash_type'' and ''spend_type'') before the variable length data. -# The signature message commits to the ''scriptPubKey'''''Why does the signature message commit to the ''scriptPubKey''?''' This prevents lying to offline signing devices about output being spent, even when the actually executed script (''scriptCode'' in BIP143) is correct. This means it's possible to compactly prove to a hardware wallet what (unused) execution paths existed.. -# If the SIGHASH_ANYONECANPAY flag is not set, the message commits to the amounts of ''all'' transaction inputs.'''Why does the signature message commit to the amounts of all transaction inputs?''' This eliminates the possibility to lie to offline signing devices about the fee of a transaction. -# The signature message commits to all input ''nSequence'' if SIGHASH_NONE or SIGHASH_SINGLE are set (unless SIGHASH_ANYONECANPAY is set as well).'''Why does the signature message commit to all input ''nSequence'' if SIGHASH_SINGLE or SIGHASH_NONE are set?''' Because setting them already makes the message commit to the prevouts part of all transaction inputs, it is not useful to treat the ''nSequence'' any different. Moreover, this change makes ''nSequence'' consistent with the view that SIGHASH_SINGLE and SIGHASH_NONE only modify the signature message with respect to transaction outputs and not inputs. -# The signature message includes commitments to the taproot-specific data ''spend_type'' and ''annex'' (if present). - -==== Taproot key path spending signature validation ==== - -To validate a signature ''sig'' with public key ''q'': -* If the ''sig'' is 64 bytes long, return ''Verify(q, hashTapSigHash(0x00 || SigMsg(0x00, 0)), sig)'''''Why is the input to ''hashTapSigHash'' prefixed with 0x00?''' This prefix is called the sighash epoch, and allows reusing the ''hashTapSigHash'' tagged hash in future signature algorithms that make invasive changes to how hashing is performed (as opposed to the ''ext_flag'' mechanism that is used for incremental extensions). An alternative is having them use a different tag, but supporting a growing number of tags may become undesirable., where ''Verify'' is defined in bip-schnorr. -* If the ''sig'' is 65 bytes long, return ''sig[64] ≠ 0x00'''Why can the hash_type not be 0x00 in 65-byte signatures?''' Permitting that would enable malleating (by third parties, including miners) 64-byte signatures into 65-byte ones, resulting in a different `wtxid` and a different fee rate than the creator intended and Verify(q, hashTapSighash(0x00 || SigMsg(sig[64], 0)), sig[0:64])''. -* Otherwise, fail'''Why permit two signature lengths?''' By making the most common type of hash_type implicit, a byte can often be saved.. - -== Constructing and spending Taproot outputs == - -This section discusses how to construct and spend Taproot outputs. It only affects wallet software that chooses to implement receiving and spending, -and is not consensus critical in any way. - -Conceptually, every Taproot output corresponds to a combination of a single public key condition (the internal key), and zero or more general conditions encoded in scripts organized in a tree. -Satisfying any of these conditions is sufficient to spend the output. - -'''Initial steps''' The first step is determining what the internal key and the organization of the rest of the scripts should be. The specifics are likely application dependent, but here are some general guidelines: -* When deciding between scripts with conditionals (OP_IF etc.) and splitting them up into multiple scripts (each corresponding to one execution path through the original script), it is generally preferable to pick the latter. -* When a single condition requires signatures with multiple keys, key aggregation techniques like MuSig can be used to combine them into a single key. The details are out of scope for this document, but note that this may complicate the signing procedure. -* If one or more of the spending conditions consist of just a single key (after aggregation), the most likely one should be made the internal key. If no such condition exists, it may be worthwhile adding one that consists of an aggregation of all keys participating in all scripts combined; effectively adding an "everyone agrees" branch. If that is inacceptable, pick as internal key a point with unknown discrete logarithm. One example of such a point is ''H = point(0x0250929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0)'' which is [https://github.com/ElementsProject/secp256k1-zkp/blob/11af7015de624b010424273be3d91f117f172c82/src/modules/rangeproof/main_impl.h#L16 constructed] by taking the hash of the standard uncompressed encoding of the [https://www.secg.org/sec2-v2.pdf secp256k1] base point ''G'' as X coordinate. In order to avoid leaking the information that key path spending is not possible it is recommended to pick a fresh integer ''r'' in the range ''0...n-1'' uniformly at random and use ''H + rG'' as internal key. It is possible to prove that this internal key does not have a known discrete logarithm with respect to ''G'' by revealing ''r'' to a verifier who can then reconstruct how the internal key was created. -* If the spending conditions do not require a script path, the output key should commit to an unspendable script path instead of having no script path. This can be achieved by computing the output key point as ''Q = P + int(hashTapTweak(bytes(P)))G''. '''Why should the output key always have a taproot commitment, even if there is no script path?''' -If the taproot output key is an aggregate of keys, there is the possibility for a malicious party to add a script path without being noticed by the other parties. -This allows to bypass the multiparty policy and to steal the coin. -MuSig key aggregation does not have this issue because it already causes the internal key to be randomized. - -The attack works as follows: Assume Alice and Mallory want to aggregate their keys into a taproot output key without a script path. -In order to prevent key cancellation and related attacks they use [https://eprint.iacr.org/2018/483.pdf MSDL-pop] instead of MuSig. -The MSDL-pop protocol requires all parties to provide a proof of possession of their corresponding secret key and the aggregated key is just the sum of the individual keys. -After Mallory receives Alice's key ''A'', Mallory creates ''M = M0 + int(t)G'' where ''M0'' is Mallory's original key and ''t'' allows a script path spend with internal key ''P = A + M0'' and a script that only contains Mallory's key. -Mallory sends a proof of possession of ''M'' to Alice and both parties compute output key ''Q = A + M = P + int(t)G''. -Alice will not be able to notice the script path, but Mallory can unilaterally spend any coin with output key ''Q''. - -* The remaining scripts should be organized into the leaves of a binary tree. This can be a balanced tree if each of the conditions these scripts correspond to are equally likely. If probabilities for each condition are known, consider constructing the tree as a Huffman tree. - -'''Computing the output script''' Once the spending conditions are split into an internal key internal_pubkey and a binary tree whose leaves are (leaf_version, script) tuples, the output script can be computed using the Python3 algorithms below. These algorithms take advantage of helper functions from the [https://github.com/sipa/bips/blob/bip-schnorr/bip-schnorr/reference.py bip-schnorr reference code] for integer conversion, point multiplication, and tagged hashes. - -First, we define taproot_tweak_pubkey for 32-byte bip-schnorr public key arrays. -In addition to the tweaked public key byte array, the function returns a boolean indicating whether the public key represents the tweaked point or its negation. -This will be required for spending the output with a script path. -In order to allow spending with the key path, we define taproot_tweak_seckey to compute the secret key for a tweaked public key. -For any byte string h it holds that taproot_tweak_pubkey(pubkey_gen(seckey), h)[0] == pubkey_gen(taproot_tweak_seckey(seckey, h)). - - -def taproot_tweak_pubkey(pubkey, h): - t = int_from_bytes(tagged_hash("TapTweak", pubkey + h)) - if t >= SECP256K1_ORDER: - raise ValueError - Q = point_add(point(pubkey), point_mul(G, t)) - is_negated = not has_square_y(Q) - return bytes_from_int(x(Q)), is_negated - -def taproot_tweak_seckey(seckey0, h): - P = point_mul(G, int_from_bytes(seckey0)) - seckey = SECP256K1_ORDER - seckey0 if not has_square_y(P) else seckey - t = int_from_bytes(tagged_hash("TapTweak", bytes_from_int(x(P)) + h)) - if t >= SECP256K1_ORDER: - raise ValueError - return (seckey + t) % SECP256K1_ORDER - - -The following function, taproot_output_script, returns a byte array with the scriptPubKey (see BIP141). -ser_script refers to a function that prefixes its input with a CCompactSize-encoded length. - - -def taproot_tree_helper(script_tree): - if isinstance(script_tree, tuple): - leaf_version, script = script_tree - h = tagged_hash("TapLeaf", bytes([leaf_version]) + ser_script(script)) - return ([((leaf_version, script), bytes())], h) - left, left_h = taproot_tree_helper(script_tree[0]) - right, right_h = taproot_tree_helper(script_tree[1]) - ret = [(l, c + right_h) for l, c in left] + [(l, c + left_h) for l, c in right] - if right_h < left_h: - left_h, right_h = right_h, left_h - return (ret, tagged_hash("TapBranch", left_h + right_h)) - -def taproot_output_script(internal_pubkey, script_tree): - """Given a internal public key and a tree of scripts, compute the output script. - script_tree is either: - - a (leaf_version, script) tuple (leaf_version is 0xc0 for bip-tapscript scripts) - - a list of two elements, each with the same structure as script_tree itself - - None - """ - if script_tree is None: - h = bytes() - else: - _, h = taproot_tree_helper(script_tree) - output_pubkey, _ = taproot_tweak_pubkey(internal_pubkey, h) - return bytes([0x51, 0x20]) + output_pubkey - - -[[File:bip-taproot/tree.png|frame|This diagram shows the hashing structure to obtain the tweak from an internal key ''P'' and a Merkle tree consisting of 5 script leaves. ''A'', ''B'', ''C'' and ''E'' are ''TapLeaf'' hashes similar to ''D'' and ''AB'' is a ''TapBranch'' hash. Note that when ''CDE'' is computed ''E'' is hashed first because ''E'' is less than ''CD''.]] - -To spend this output using script ''D'', the control block would contain the following data in this order: - - - -The TapTweak would then be computed as described in [[#script-validation-rules]] like so: - - -D = tagged_hash("TapLeaf", bytes([leaf_version]) + ser_script(script)) -CD = tagged_hash("TapBranch", C + D) -CDE = tagged_hash("TapBranch", E + CD) -ABCDE = tagged_hash("TapBranch", AB + CDE) -TapTweak = tagged_hash("TapTweak", p + ABCDE) - - -'''Spending using the key path''' A Taproot output can be spent with the secret key corresponding to the internal_pubkey. To do so, a witness stack consists of a single element: a bip-schnorr signature on the signature hash as defined above, with the secret key tweaked by the same h as in the above snippet. See the code below: - - -def taproot_sign_key(script_tree, internal_seckey, hash_type): - _, h = taproot_tree_helper(script_tree) - output_seckey = taproot_tweak_seckey(internal_seckey, h) - sig = schnorr_sign(sighash(hash_type), output_seckey) - if hash_type != 0: - sig += bytes([hash_type]) - return [sig] - - -This function returns the witness stack necessary and a sighash function to compute the signature hash as defined above (for simplicity, the snippet above ignores passing information like the transaction, the input position, ... to the sighashing code). - -'''Spending using one of the scripts''' A Taproot output can be spent by satisfying any of the scripts used in its construction. To do so, a witness stack consisting of the script's inputs, plus the script itself and the control block are necessary. See the code below: - - -def taproot_sign_script(internal_pubkey, script_tree, script_num, inputs): - info, h = taproot_tree_helper(script_tree) - (leaf_version, script), path = info[script_num] - _, is_negated = taproot_tweak_pubkey(internal_pubkey, h) - output_pubkey_tag = 0 if is_negated else 1 - pubkey_data = bytes([output_pubkey_tag + leaf_version]) + internal_pubkey - return inputs + [script, pubkey_data + path] - - -== Security == - -Taproot improves the privacy of Bitcoin because instead of revealing all possible conditions for spending an output, only the satisfied spending condition has to be published. -Ideally, outputs are spent using the key path which prevents observers from learning the spending conditions of a coin. -A key path spend could be a "normal" payment from a single- or multi-signature wallet or the cooperative settlement of hidden multiparty contract. - -A script path spend leaks that there is a script path and that the key path was not applicable - for example because the involved parties failed to reach agreement. -Moreover, the depth of a script in the Merkle root leaks information including the minimum depth of the tree, which suggests specific wallet software that created the output and helps clustering. -Therefore, the privacy of script spends can be improved by deviating from the optimal tree determined by the probability distribution over the leaves. - -Just like other existing output types, taproot outputs should never reuse keys, for privacy reasons. -This does not only apply to the particular leaf that was used to spend an output but to all leaves committed to in the output. -If leaves were reused, it could happen that spending a different output would reuse the same Merkle branches in the Merkle proof. -Using fresh keys implies that taproot output construction does not need to take special measures to randomizing leaf positions because they are already randomized due to the branch-sorting Merkle tree construction used in taproot. -This does not avoid leaking information through the leaf depth and therefore only applies to balanced (sub-) trees. -In addition, every leaf should have a set of keys distinct from every other leaf. -The reason for this is to increase leaf entropy and prevent an observer from learning an undisclosed script using brute-force search. - -== Test vectors == - -Examples with creation transaction and spending transaction pairs, valid and invalid. - -Examples of preimage for sighashing for each of the sighash modes. - -== Rationale == - - - -== Deployment == - -TODO - -== Backwards compatibility == -As a soft fork, older software will continue to operate without modification. -Non-upgraded nodes, however, will consider all SegWit version 1 witness programs as anyone-can-spend scripts. -They are strongly encouraged to upgrade in order to fully validate the new programs. - -Non-upgraded wallets can receive and send bitcoin from non-upgraded and upgraded wallets using SegWit version 0 programs, traditional pay-to-pubkey-hash, etc. -Depending on the implementation non-upgraded wallets may be able to send to Segwit version 1 programs if they support sending to [https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki BIP173] Bech32 addresses. - -== Acknowledgements == - -This document is the result of discussions around script and signature improvements with many people, and had direct contributions from Greg Maxwell and others. It further builds on top of earlier published proposals such as Taproot by Greg Maxwell, and Merkle branch constructions by Russell O'Connor, Johnson Lau, and Mark Friedenbach. - -The authors wish the thank Arik Sosman for suggesting to sort Merkle node children before hashes, removing the need to transfer the position in the tree, as well as all those who provided valuable feedback and reviews, including the participants of the [https://github.com/ajtowns/taproot-review structured reviews]. diff --git a/bip-taproot/tree.png b/bip-taproot/tree.png deleted file mode 100644 index af56eda..0000000 Binary files a/bip-taproot/tree.png and /dev/null differ diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki deleted file mode 100644 index 82661ff..0000000 --- a/bip-tapscript.mediawiki +++ /dev/null @@ -1,140 +0,0 @@ -
-  BIP: bip-tapscript
-  Layer: Consensus (soft fork)
-  Title: Validation of Taproot Scripts
-  Author: Pieter Wuille 
-          Jonas Nick 
-          Anthony Towns 
-  Comments-Summary: No comments yet.
-  Comments-URI:
-  Status: Draft
-  Type: Standards Track
-  Created:
-  License: BSD-3-Clause
-  Requires: bip-schnorr, bip-taproot
-  Post-History: 2019-05-06: https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2019-May/016914.html [bitcoin-dev] Taproot proposal
-
- -==Introduction== - -===Abstract=== - -This document specifies the semantics of the initial scripting system under bip-taproot. - -===Copyright=== - -This document is licensed under the 3-clause BSD license. - -===Motivation=== - -Bip-taproot proposes improvements to just the script structure, but some of its goals are incompatible with the semantics of certain opcodes within the scripting language itself. -While it is possible to deal with these in separate optional improvements, their impact is not guaranteed unless they are addressed simultaneously with bip-taproot itself. - -Specifically, the goal is making '''Schnorr signatures''', '''batch validation''', and '''signature hash''' improvements available to spends that use the script system as well. - -==Design== - -In order to achieve these goals, signature opcodes OP_CHECKSIG and OP_CHECKSIGVERIFY are modified to verify Schnorr signatures as specified in bip-schnorr and to use a signature message algorithm based on the common message calculation in bip-taproot. -The tapscript signature message also simplifies OP_CODESEPARATOR handling and makes it more efficient. - -The inefficient OP_CHECKMULTISIG and OP_CHECKMULTISIGVERIFY opcodes are disabled. -Instead, a new opcode OP_CHECKSIGADD is introduced to allow creating the same multisignature policies in a batch-verifiable way. -Tapscript uses a new, simpler signature opcode limit fixing complicated interactions with transaction weight. -Furthermore, a potential malleability vector is eliminated by requiring MINIMALIF. - -Tapscript can be upgraded through soft forks by defining unknown key types, for example to add new hash_types or signature algorithms. -Additionally, the new tapscript OP_SUCCESS opcodes allow introducing new opcodes more cleanly than through OP_NOP. - -==Specification== - -The rules below only apply when validating a transaction input for which all of the conditions below are true: -* The transaction input is a '''segregated witness spend''' (i.e., the scriptPubKey contains a witness program as defined in [https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki BIP141]). -* It is a '''taproot spend''' as defined in bip-taproot (i.e., the witness version is 1, the witness program is 32 bytes, and it is not P2SH wrapped). -* It is a '''script path spend''' as defined in bip-taproot (i.e., after removing the optional annex from the witness stack, two or more stack elements remain). -* The leaf version is ''0xc0'' (i.e. the first byte of the last witness element after removing the optional annex is ''0xc0'' or ''0xc1''), marking it as a '''tapscript spend'''. - -Validation of such inputs must be equivalent to performing the following steps in the specified order. -# If the input is invalid due to BIP141 or bip-taproot, fail. -# The script as defined in bip-taproot (i.e., the penultimate witness stack element after removing the optional annex) is called the '''tapscript''' and is decoded into opcodes, one by one: -## If any opcode numbered ''80, 98, 126-129, 131-134, 137-138, 141-142, 149-153, 187-254'' is encountered, validation succeeds (none of the rules below apply). This is true even if later bytes in the tapscript would fail to decode otherwise. These opcodes are renamed to OP_SUCCESS80, ..., OP_SUCCESS254, and collectively known as OP_SUCCESSx'''OP_SUCCESSx''' OP_SUCCESSx is a mechanism to upgrade the Script system. Using an OP_SUCCESSx before its meaning is defined by a softfork is insecure and leads to fund loss. The inclusion of OP_SUCCESSx in a script will pass it unconditionally. It precedes any script execution rules to avoid the difficulties in specifying various edge cases, for example: OP_SUCCESSx in a script with an input stack larger than 1000 elements, OP_SUCCESSx after too many signature opcodes, or even scripts with conditionals lacking OP_ENDIF. The mere existence of an OP_SUCCESSx anywhere in the script will guarantee a pass for all such cases. OP_SUCCESSx are similar to the OP_RETURN in very early bitcoin versions (v0.1 up to and including v0.3.5). The original OP_RETURN terminates script execution immediately, and return pass or fail based on the top stack element at the moment of termination. This was one of a major design flaws in the original bitcoin protocol as it permitted unconditional third party theft by placing an OP_RETURN in scriptSig. This is not a concern in the present proposal since it is not possible for a third party to inject an OP_SUCCESSx to the validation process, as the OP_SUCCESSx is part of the script (and thus committed to by the taproot output), implying the consent of the coin owner. OP_SUCCESSx can be used for a variety of upgrade possibilities: -* An OP_SUCCESSx could be turned into a functional opcode through a softfork. Unlike OP_NOPx-derived opcodes which only have read-only access to the stack, OP_SUCCESSx may also write to the stack. Any rule changes to an OP_SUCCESSx-containing script may only turn a valid script into an invalid one, and this is always achievable with softforks. -* Since OP_SUCCESSx precedes size check of initial stack and push opcodes, an OP_SUCCESSx-derived opcode requiring stack elements bigger than 520 bytes may uplift the limit in a softfork. -* OP_SUCCESSx may also redefine the behavior of existing opcodes so they could work together with the new opcode. For example, if an OP_SUCCESSx-derived opcode works with 64-bit integers, it may also allow the existing arithmetic opcodes in the ''same script'' to do the same. -* Given that OP_SUCCESSx even causes potentially unparseable scripts to pass, it can be used to introduce multi-byte opcodes, or even a completely new scripting language when prefixed with a specific OP_SUCCESSx opcode.. -## If any push opcode fails to decode because it would extend past the end of the tapscript, fail. -# If the '''initial stack''' as defined in bip-taproot (i.e., the witness stack after removing both the optional annex and the two last stack elements after that) violates any resource limits (stack size, and size of the elements in the stack; see "Resource Limits" below), fail. Note that this check can be bypassed using OP_SUCCESSx. -# The tapscript is executed according to the rules in the following section, with the initial stack as input. -## If execution fails for any reason, fail. -## If the execution results in anything but exactly one element on the stack which evaluates to true with CastToBool(), fail. -# If this step is reached without encountering a failure, validation succeeds. - -===Script execution=== - -The execution rules for tapscript are based on those for P2WSH according to BIP141, including the OP_CHECKLOCKTIMEVERIFY and OP_CHECKSEQUENCEVERIFY opcodes defined in [https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki BIP65] and [https://github.com/bitcoin/bips/blob/master/bip-0112.mediawiki BIP112], but with the following modifications: -* '''Disabled script opcodes''' The following script opcodes are disabled in tapscript: OP_CHECKMULTISIG and OP_CHECKMULTISIGVERIFY'''Why are OP_CHECKMULTISIG and OP_CHECKMULTISIGVERIFY disabled, and not turned into OP_SUCCESSx?''' This is a precaution to make sure people who accidentally keep using OP_CHECKMULTISIG in Tapscript notice a problem immediately. It also avoids the complication of script disassemblers needing to become context-dependent.. The disabled opcodes behave in the same way as OP_RETURN, by failing and terminating the script immediately when executed, and being ignored when found in unexecuted branch of the script. -* '''Consensus-enforced MINIMALIF''' The MINIMALIF rules, which are only a standardness rule in P2WSH, are consensus enforced in tapscript. This means that the input argument to the OP_IF and OP_NOTIF opcodes must be either exactly 0 (the empty vector) or exactly 1 (the one-byte vector with value 1)'''Why make MINIMALIF consensus?''' This makes it considerably easier to write non-malleable scripts that take branch information from the stack.. -* '''OP_SUCCESSx opcodes''' As listed above, some opcodes are renamed to OP_SUCCESSx, and make the script unconditionally valid. -* '''Signature opcodes'''. The OP_CHECKSIG and OP_CHECKSIGVERIFY are modified to operate on Schnorr public keys and signatures (see bip-schnorr) instead of ECDSA, and a new opcode OP_CHECKSIGADD is added. -** The opcode 186 (0xba) is named as OP_CHECKSIGADD. '''OP_CHECKSIGADD''' This opcode is added to compensate for the loss of OP_CHECKMULTISIG-like opcodes, which are incompatible with batch verification. OP_CHECKSIGADD is functionally equivalent to OP_ROT OP_SWAP OP_CHECKSIG OP_ADD, but only takes 1 byte. All CScriptNum-related behaviours of OP_ADD are also applicable to OP_CHECKSIGADD.'''Alternatives to CHECKMULTISIG''' There are multiple ways of implementing a threshold ''k''-of-''n'' policy using Taproot and Tapscript: -* '''Using a single OP_CHECKSIGADD-based script''' A CHECKMULTISIG script m ... n CHECKMULTISIG with witness 0 ... can be rewritten as script CHECKSIG ... CHECKSIGADD m NUMEQUAL with witness ... . Every witness element w_i is either a signature corresponding to pubkey_i or an empty vector. A similar CHECKMULTISIGVERIFY script can be translated to bip-tapscript by replacing NUMEQUAL with NUMEQUALVERIFY. This approach has very similar characteristics to the existing OP_CHECKMULTISIG-based scripts. -* '''Using a ''k''-of-''k'' script for every combination''' A ''k''-of-''n'' policy can be implemented by splitting the script into several leaves of the Merkle tree, each implementing a ''k''-of-''k'' policy using CHECKSIGVERIFY ... CHECKSIGVERIFY CHECKSIG. This may be preferable for privacy reasons over the previous approach, as it only exposes the participating public keys, but it is only more cost effective for small values of ''k'' (1-of-''n'' for any ''n'', 2-of-''n'' for ''n ≥ 6'', 3-of-''n'' for ''n ≥ 9'', ...). Furthermore, the signatures here commit to the branch used, which means signers need to be aware of which other signers will be participating, or produce signatures for each of the tree leaves. -* '''Using an aggregated public key for every combination''' Instead of building a tree where every leaf consists of ''k'' public keys, it is possible instead build a tree where every leaf contains a single ''aggregate'' of those ''k'' keys using [https://eprint.iacr.org/2018/068 MuSig]. This approach is far more efficient, but does require a 3-round interactive signing protocol to jointly produce the (single) signature. -* '''Native Schnorr threshold signatures''' Multisig policies can also be realized with [http://cacr.uwaterloo.ca/techreports/2001/corr2001-13.ps threshold signatures] using verifiable secret sharing. This results in outputs and inputs that are indistinguishable from single-key payments, but at the cost of needing an interactive protocol (and associated backup procedures) before determining the address to send to. - -===Rules for signature opcodes=== - -The following rules apply to OP_CHECKSIG, OP_CHECKSIGVERIFY, and OP_CHECKSIGADD. - -* For OP_CHECKSIGVERIFY and OP_CHECKSIG, the public key (top element) and a signature (second to top element) are popped from the stack. -** If fewer than 2 elements are on the stack, the script MUST fail and terminate immediately. -* For OP_CHECKSIGADD, the public key (top element), a CScriptNum n (second to top element), and a signature (third to top element) are popped from the stack. -** If fewer than 3 elements are on the stack, the script MUST fail and terminate immediately. -** If n is larger than 4 bytes, the script MUST fail and terminate immediately. -* If the public key size is zero, the script MUST fail and terminate immediately. -* If the public key size is 32 bytes, it is considered to be a public key as described in bip-schnorr: -** If the signature is not the empty vector, the signature is validated against the public key (see the next subsection). Validation failure in this case immediately terminates script execution with failure. -* If the public key size is not zero and not 32 bytes, the public key is of an ''unknown public key type'''''Unknown public key types''' allow adding new signature validation rules through softforks. A softfork could add actual signature validation which either passes or makes the script fail and terminate immediately. This way, new SIGHASH modes can be added, as well as [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-December/016549.html NOINPUT-tagged public keys] and a public key constant which is replaced by the taproot internal key for signature validation. and no actual signature verification is applied. During script execution of signature opcodes they behave exactly as known public key types except that signature validation is considered to be successful. -* If the script did not fail and terminate before this step, regardless of the public key type: -** If the signature is the empty vector: -*** For OP_CHECKSIGVERIFY, the script MUST fail and terminate immediately. -*** For OP_CHECKSIG, an empty vector is pushed onto the stack, and execution continues with the next opcode. -*** For OP_CHECKSIGADD, a CScriptNum with value n is pushed onto the stack, and execution continues with the next opcode. -** If the signature is not the empty vector, the opcode is counted towards the sigops budget (see further). -*** For OP_CHECKSIGVERIFY, execution continues without any further changes to the stack. -*** For OP_CHECKSIG, a 1-byte value 0x01 is pushed onto the stack. -*** For OP_CHECKSIGADD, a CScriptNum with value of n + 1 is pushed onto the stack. - -===Signature validation=== - -To validate a signature ''sig'' with public key ''p'': -* Compute the tapscript message extension ''ext'', consisting of the concatenation of: -** ''tapleaf_hash'' (32): the tapleaf hash as defined in bip-taproot -** ''key_version'' (1): a constant value ''0x00'' representing the current version of public keys in the tapscript signature opcode execution. -** ''codesep_pos'' (4): the opcode position of the last executed OP_CODESEPARATOR before the currently executed signature opcode, with the value in little endian (or ''0xffffffff'' if none executed). The first opcode in a script has a position of 0. A multi-byte push opcode is counted as one opcode, regardless of the size of data being pushed. -* If the ''sig'' is 64 bytes long, return ''Verify(p, hashTapSigHash(0x00 || SigMsg(0x00, 1) || ext), sig)'', where ''Verify'' is defined in bip-schnorr. -* If the ''sig'' is 65 bytes long, return ''sig[64] ≠ 0x00 and Verify(p, hashTapSighash(0x00 || SigMsg(sig[64], 1) || ext), sig[0:64])''. -* Otherwise, fail. - -In summary, the semantics of signature validation is identical to bip-taproot, except the following: -# The signature message includes the tapscript-specific data ''key_version''.'''Why does the signature message commit to the ''key_version''?''' This is for future extensions that define unknown public key types, making sure signatures can't be moved from one key type to another. -# The signature message commits to the executed script through the ''tapleaf_hash'' which includes the leaf version and script instead of ''scriptCode''. This implies that this commitment is unaffected by OP_CODESEPARATOR. -# The signature message includes the opcode position of the last executed OP_CODESEPARATOR.'''Why does the signature message include the position of the last executed OP_CODESEPARATOR?''' This allows continuing to use OP_CODESEPARATOR to sign the executed path of the script. Because the codeseparator_position is the last input to the hash, the SHA256 midstate can be efficiently cached for multiple OP_CODESEPARATORs in a single script. In contrast, the BIP143 handling of OP_CODESEPARATOR is to commit to the executed script only from the last executed OP_CODESEPARATOR onwards which requires unnecessary rehashing of the script. It should be noted that the one known OP_CODESEPARATOR use case of saving a second public key push in a script by sharing the first one between two code branches can be most likely expressed even cheaper by moving each branch into a separate taproot leaf. - -===Resource limits=== - -In addition to changing the semantics of a number of opcodes, there are also some changes to the resource limitations: -* '''Script size limit''' The maximum script size of 10000 bytes does not apply. Their size is only implicitly bounded by the block weight limit.'''Why is a limit on script size no longer needed?''' Since there is no scriptCode directly included in the signature hash (only indirectly through a precomputable tapleaf hash), the CPU time spent on a signature check is no longer proportional to the size of the script being executed. -* '''Non-push opcodes limit''' The maximum non-push opcodes limit of 201 per script does not apply.'''Why is a limit on the number of opcodes no longer needed?''' An opcode limit only helps to the extent that it can prevent data structures from growing unboundedly during execution (both because of memory usage, and because of time that may grow in proportion to the size of those structures). The size of stack and altstack is already independently limited. By using O(1) logic for OP_IF, OP_NOTIF, OP_ELSE, and OP_ENDIF as suggested [https://bitslog.com/2017/04/17/new-quadratic-delays-in-bitcoin-scripts/ here] and implemented [https://github.com/bitcoin/bitcoin/pull/16902 here], the only other instance can be avoided as well. -* '''Sigops limit''' The sigops in tapscripts do not count towards the block-wide limit of 80000 (weighted). Instead, there is a per-script sigops ''budget''. The budget equals 50 + the total serialized size in bytes of the transaction input's witness (including the CCompactSize prefix). Executing a signature opcode (OP_CHECKSIG, OP_CHECKSIGVERIFY, or OP_CHECKSIGADD) with a non-empty signature decrements the budget by 50. If that brings the budget below zero, the script fails immediately. Signature opcodes with unknown public key type and non-empty signature are also counted.'''The tapscript sigop limit''' The signature opcode limit protects against scripts which are slow to verify due to excessively many signature operations. In tapscript the number of signature opcodes does not count towards the BIP141 or legacy sigop limit. The old sigop limit makes transaction selection in block construction unnecessarily difficult because it is a second constraint in addition to weight. Instead, the number of tapscript signature opcodes is limited by witness weight. Additionally, the limit applies to the transaction input instead of the block and only actually executed signature opcodes are counted. Tapscript execution allows one signature opcode per 50 witness weight units plus one free signature opcode.'''Parameter choice of the sigop limit''' Regular witnesses are unaffected by the limit as their weight is composed of public key and (SIGHASH_ALL) signature pairs with ''33 + 65'' weight units each (which includes a 1 weight unit CCompactSize tag). This is also the case if public keys are reused in the script because a signature's weight alone is 65 or 66 weight units. However, the limit increases the fees of abnormal scripts with duplicate signatures (and public keys) by requiring additional weight. The weight per sigop factor 50 corresponds to the ratio of BIP141 block limits: 4 mega weight units divided by 80,000 sigops. The "free" signature opcode permitted by the limit exists to account for the weight of the non-witness parts of the transaction input.'''Why are only signature opcodes counted toward the budget, and not for example hashing opcodes or other expensive operations?''' It turns out that the CPU cost per witness byte for verification of a script consisting of the maximum density of signature checking opcodes (taking the 50 WU/sigop limit into account) is already very close to that of scripts packed with other opcodes, including hashing opcodes (taking the 520 byte stack element limit into account) and OP_ROLL (taking the 1000 stack element limit into account). That said, the construction is very flexible, and allows adding new signature opcodes like CHECKSIGFROMSTACK to count towards the limit through a soft fork. Even if in the future new opcodes are introduced which change normal script cost there is no need to stuff the witness with meaningless data. Instead, the taproot annex can be used to add weight to the witness without increasing the actual witness size.. -* '''Stack + altstack element count limit''' The existing limit of 1000 elements in the stack and altstack together after every executed opcode remains. It is extended to also apply to the size of initial stack. -* '''Stack element size limit''' The existing limit of maximum 520 bytes per stack element remains, both in the initial stack and in push opcodes. - -==Rationale== - - - -==Examples== - -==Acknowledgements== - -This document is the result of many discussions and contains contributions by a number of people. The authors wish to thank all those who provided valuable feedback and reviews, including the participants of the [https://github.com/ajtowns/taproot-review structured reviews]. -- cgit v1.2.3 From eb641cbdb50a9991404cd633b5c4cb0139847238 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 14 Jan 2020 10:28:49 -0800 Subject: Address jonas' comments --- bip-taproot.mediawiki | 22 +++++++++++----------- bip-tapscript.mediawiki | 18 +++++++++--------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/bip-taproot.mediawiki b/bip-taproot.mediawiki index 8a51747..ca66b3e 100644 --- a/bip-taproot.mediawiki +++ b/bip-taproot.mediawiki @@ -41,7 +41,7 @@ As a result we choose this combination of technologies: * Taproot's advantages become apparent under the assumption that most applications involve outputs that could be spent by all parties agreeing. That's where '''Schnorr''' signatures come in, as they permit [https://eprint.iacr.org/2018/068 key aggregation]: a public key can be constructed from multiple participant public keys, and which requires cooperation between all participants to sign for. Such multi-party public keys and signatures are indistinguishable from their single-party equivalents. This means that with taproot most applications can use the key-based spending path, which is both efficient and private. This can be generalized to arbitrary M-of-N policies, as Schnorr signatures support threshold signing, at the cost of more complex setup protocols. * As Schnorr signatures also permit '''batch validation''', allowing multiple signatures to be validated together more efficiently than validating each one independently, we make sure all parts of the design are compatible with this. * Where unused bits appear as a result of the above changes, they are reserved for mechanisms for '''future extensions'''. As a result, every script in the Merkle tree has an associated version such that new script versions can be introduced with a soft fork while remaining compatible with bip-taproot. Additionally, future soft forks can make use of the currently unused annex in the witness (see [[#Rationale]]). -* While the core semantics of the '''signature hashing algorithm''' are not changed, a number of improvements are included in this proposal. The new signature hashing algorithm fixes the verification capabilities of offline signing devices by including amount and scriptPubKey in the digest, avoids unnecessary hashing, uses '''tagged hashes''' and defines a default sighash byte. +* While the core semantics of the '''signature hashing algorithm''' are not changed, a number of improvements are included in this proposal. The new signature hashing algorithm fixes the verification capabilities of offline signing devices by including amount and scriptPubKey in the signature message, avoids unnecessary hashing, uses '''tagged hashes''' and defines a default sighash byte. * The '''public key is directly included in the output''' in contrast to typical earlier constructions which store a hash of the public key or script in the output. This has the same cost for senders and is more space efficient overall if the key-based spending path is taken. '''Why is the public key directly included in the output?''' While typical earlier constructions store a hash of a script or a public key in the output, this is rather wasteful when a public key is always involved. To guarantee batch verifiability, the public key must be known to every verifier, and thus only revealing its hash as an output would imply adding an additional 32 bytes to the witness. Furthermore, to maintain [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2016-January/012198.html 128-bit collision security] for outputs, a 256-bit hash would be required anyway, which is comparable in size (and thus in cost for senders) to revealing the public key directly. While the usage of public key hashes is often said to protect against ECDLP breaks or quantum computers, this protection is very weak at best: transactions are not protected while being confirmed, and a very [https://twitter.com/pwuille/status/1108097835365339136 large portion] of the currency's supply is not under such protection regardless. Actual resistance to such systems can be introduced by relying on different cryptographic assumptions, but this proposal focuses on improvements that do not change the security model. Informally, the resulting design is as follows: a new witness version is added (version 1), whose programs consist of 32-byte encodings of points ''Q''. ''Q'' is computed as ''P + hash(P||m)G'' for a public key ''P'', and the root ''m'' of a Merkle tree whose leaves consist of a version number and a script. These outputs can be spent directly by providing a signature for ''Q'', or indirectly by revealing ''P'', the script and leaf version, inputs that satisfy the script, and a Merkle path that proves ''Q'' committed to that leaf. All hashes in this construction (the hash for computing ''Q'' from ''P'', the hashes inside the Merkle tree's inner nodes, and the signature hashes used) are tagged to guarantee domain separation. @@ -59,9 +59,9 @@ The following rules only apply when such an output is being spent. Any other out * Let ''q'' be the 32-byte array containing the witness program (the second push in the scriptPubKey) which represents a public key according to bip-schnorr. * Fail if the witness stack has 0 elements. -* If there are at least two witness elements, and the first byte of the last element is 0x50'''Why is the first byte of the annex 0x50?''' The 0x50 is chosen as it could not be confused with a valid P2WPKH or P2WSH spending. As the control block's initial byte's lowest bit is used to indicate the public key's Y squareness, each leaf version needs an even byte value and the immediately following odd byte value that are both not yet used in P2WPKH or P2WSH spending. To indicate the annex, only an "unpaired" available byte is necessary like 0x50. This choice maximizes the available options for future script versions., this last element is called ''annex'' ''a'''''What is the purpose of the annex?''' The annex is a reserved space for future extensions, such as indicating the validation costs of computationally expensive new opcodes in a way that is recognizable without knowing the scriptPubKey of the output being spent. Until the meaning of this field is defined by another softfork, users SHOULD NOT include annex in transactions, or it may lead to PERMANENT FUND LOSS. and is removed from the witness stack. The annex (or the lack of thereof) is always covered by the transaction digest and contributes to transaction weight, but is otherwise ignored during taproot validation. +* If there are at least two witness elements, and the first byte of the last element is 0x50'''Why is the first byte of the annex 0x50?''' The 0x50 is chosen as it could not be confused with a valid P2WPKH or P2WSH spending. As the control block's initial byte's lowest bit is used to indicate the public key's Y squareness, each leaf version needs an even byte value and the immediately following odd byte value that are both not yet used in P2WPKH or P2WSH spending. To indicate the annex, only an "unpaired" available byte is necessary like 0x50. This choice maximizes the available options for future script versions., this last element is called ''annex'' ''a'''''What is the purpose of the annex?''' The annex is a reserved space for future extensions, such as indicating the validation costs of computationally expensive new opcodes in a way that is recognizable without knowing the scriptPubKey of the output being spent. Until the meaning of this field is defined by another softfork, users SHOULD NOT include annex in transactions, or it may lead to PERMANENT FUND LOSS. and is removed from the witness stack. The annex (or the lack of thereof) is always covered by the signature and contributes to transaction weight, but is otherwise ignored during taproot validation. * If there is exactly one element left in the witness stack, key path spending is used: -** The single witness stack element is interpreted as the signature and must be valid (see the next section) for the public key ''q'' and taproot transaction digest (to be defined hereinafter) as message. Fail if it is not. Otherwise pass. +** The single witness stack element is interpreted as the signature and must be valid (see the next section) for the public key ''q'' (see the next subsection). * If there are at least two witness elements left, script path spending is used: ** Call the second-to-last stack element ''s'', the script. ** The last stack element is called the control block ''c'', and must have length ''33 + 32m'', for a value of ''m'' that is an integer between 0 and 128'''Why is the Merkle path length limited to 128?''' The optimally space-efficient Merkle tree can be constructed based on the probabilities of the scripts in the leaves, using the Huffman algorithm. This algorithm will construct branches with lengths approximately equal to ''log2(1/probability)'', but to have branches longer than 128 you would need to have scripts with an execution chance below 1 in ''2128''. As that is our security bound, scripts that truly have such a low chance can probably be removed entirely., inclusive. Fail if it does not have such a length. @@ -89,11 +89,11 @@ We first define a reusable common signature message calculation function, follow The function ''SigMsg(hash_type, ext_flag)'' computes the message being signed as a byte array. It is implicitly also a function of the spending transaction and the outputs it spends, but these are not listed to keep notation simple. -The parameter ''hash_type'' is an 8-bit unsigned value. The SIGHASH encodings from the legacy script system are reused, including SIGHASH_ALL, SIGHASH_NONE, SIGHASH_SINGLE, and SIGHASH_ANYONECANPAY, plus a default ''hash_type'' (0) which results in signing over the whole transaction just as for SIGHASH_ALL. The following restrictions apply, which cause validation failure if violated: +The parameter ''hash_type'' is an 8-bit unsigned value. The SIGHASH encodings from the legacy script system are reused, including SIGHASH_ALL, SIGHASH_NONE, SIGHASH_SINGLE, and SIGHASH_ANYONECANPAY, plus the default ''hash_type'' value ''0x00'' which results in signing over the whole transaction just as for SIGHASH_ALL. The following restrictions apply, which cause validation failure if violated: * Using any undefined ''hash_type'' (not ''0x00'', ''0x01'', ''0x02'', ''0x03'', ''0x81'', ''0x82'', or ''0x83'''''Why reject unknown ''hash_type'' values?''' By doing so, it is easier to reason about the worst case amount of signature hashing an implementation with adequate caching must perform.). * Using SIGHASH_SINGLE without a "corresponding output" (an output with the same index as the input being verified). -The parameter ''ext_flag'' is an integer in range 0-127, and is used for indicating the presence of extensions. +The parameter ''ext_flag'' is an integer in range 0-127, and is used for indicating (in the message) that extensions are added at the end of the message'''What extensions use the ''ext_flag'' mechanism?''' Bip-tapscript reuses the same common signature message algorithm, but adds tapscript-specific data at the end, which is indicated using ''ext_flag = 1''.. If the parameters take acceptable values, the message is the concatenation of the following data, in order(with byte size of each item listed in parentheses). Numerical values in 2, 4, or 8-byte are encoded in little-endian. @@ -126,16 +126,16 @@ If the parameters take acceptable values, the message is the concatenation of th The total length of ''SigMsg()'' is at most ''209'' bytes'''What is the output length of ''SigMsg()''?''' The total length of ''SigMsg()'' can be computed using the following formula: ''177 - is_anyonecanpay * 52 - is_none * 32 + has_annex * 32''.. Note that this does not include the size of sub-hashes such as ''sha_prevouts'', which may be cached across signatures of the same transaction. In summary, the semantics of the [https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki BIP143] sighash types remain unchanged, except the following: -# The way and order of serialization is changed.'''Why is the serialization in the transaction digest changed?''' Hashes that go into the digest and the digest itself are now computed with a single SHA256 invocation instead of double SHA256. There is no expected security improvement by doubling SHA256 because this only protects against length-extension attacks against SHA256 which are not a concern for transaction digests because there is no secret data. Therefore doubling SHA256 is a waste of resources. The digest computation now follows a logical order with transaction level data first, then input data and output data. This allows to efficiently cache the transaction part of the digest across different inputs using the SHA256 midstate. Additionally, sub-hashes can be skipped when calculating the digest (for example `sha_prevouts` if SIGHASH_ANYONECANPAY is set) instead of setting them to zero and then hashing them as in BIP143. Despite that, collisions are made impossible by committing to the length of the data (implicit in ''hash_type'' and ''spend_type'') before the variable length data. -# The digest commits to the ''scriptPubKey'''''Why does the transaction digest commit to the ''scriptPubKey''?''' This prevents lying to offline signing devices about output being spent, even when the actually executed script (''scriptCode'' in BIP143) is correct. This means it's possible to compactly prove to a hardware wallet what (unused) execution paths existed.. -# If the SIGHASH_ANYONECANPAY flag is not set, the digest commits to the amounts of ''all'' transaction inputs.'''Why does the transaction digest commit to the amounts of all transaction inputs?''' This eliminates the possibility to lie to offline signing devices about the fee of a transaction. -# The digest commits to all input ''nSequence'' if SIGHASH_NONE or SIGHASH_SINGLE are set (unless SIGHASH_ANYONECANPAY is set as well).'''Why does the transaction digest commit to all input ''nSequence'' if SIGHASH_SINGLE or SIGHASH_NONE are set?''' Because setting them already makes the digest commit to the prevouts part of all transaction inputs, it is not useful to treat the ''nSequence'' any different. Moreover, this change makes ''nSequence'' consistent with the view that SIGHASH_SINGLE and SIGHASH_NONE only modify the digest with respect to transaction outputs and not inputs. -# The message includes commitments to the taproot-specific data ''spend_type'' and ''annex'' (if present). +# The way and order of serialization is changed.'''Why is the serialization in the signature message changed?''' Hashes that go into the signature message and the message itself are now computed with a single SHA256 invocation instead of double SHA256. There is no expected security improvement by doubling SHA256 because this only protects against length-extension attacks against SHA256 which are not a concern for signature messages because there is no secret data. Therefore doubling SHA256 is a waste of resources. The message computation now follows a logical order with transaction level data first, then input data and output data. This allows to efficiently cache the transaction part of the message across different inputs using the SHA256 midstate. Additionally, sub-hashes can be skipped when calculating the message (for example `sha_prevouts` if SIGHASH_ANYONECANPAY is set) instead of setting them to zero and then hashing them as in BIP143. Despite that, collisions are made impossible by committing to the length of the data (implicit in ''hash_type'' and ''spend_type'') before the variable length data. +# The signature message commits to the ''scriptPubKey'''''Why does the signature message commit to the ''scriptPubKey''?''' This prevents lying to offline signing devices about output being spent, even when the actually executed script (''scriptCode'' in BIP143) is correct. This means it's possible to compactly prove to a hardware wallet what (unused) execution paths existed.. +# If the SIGHASH_ANYONECANPAY flag is not set, the message commits to the amounts of ''all'' transaction inputs.'''Why does the signature message commit to the amounts of all transaction inputs?''' This eliminates the possibility to lie to offline signing devices about the fee of a transaction. +# The signature message commits to all input ''nSequence'' if SIGHASH_NONE or SIGHASH_SINGLE are set (unless SIGHASH_ANYONECANPAY is set as well).'''Why does the signature message commit to all input ''nSequence'' if SIGHASH_SINGLE or SIGHASH_NONE are set?''' Because setting them already makes the message commit to the prevouts part of all transaction inputs, it is not useful to treat the ''nSequence'' any different. Moreover, this change makes ''nSequence'' consistent with the view that SIGHASH_SINGLE and SIGHASH_NONE only modify the signature message with respect to transaction outputs and not inputs. +# The signature message includes commitments to the taproot-specific data ''spend_type'' and ''annex'' (if present). ==== Taproot key path spending signature validation ==== To validate a signature ''sig'' with public key ''q'': -* If the ''sig'' is 64 bytes long, return ''Verify(q, hashTapSigHash(0x00 || SigMsg(0x00, 0)), sig)'''''Why is the input to ''hashTapSigHash'' prefixed with 0x00?''' This prefix is called the sighash epoch, and allows reusing the ''hashTapSigHash'' tagged hash in future extensions that make invasive changes to how hashing is performed. An alternative is switching to a different tag, but supporting a growing number of tags may become undesirable., where ''Verify'' is defined in bip-schnorr. +* If the ''sig'' is 64 bytes long, return ''Verify(q, hashTapSigHash(0x00 || SigMsg(0x00, 0)), sig)'''''Why is the input to ''hashTapSigHash'' prefixed with 0x00?''' This prefix is called the sighash epoch, and allows reusing the ''hashTapSigHash'' tagged hash in future signature algorithms that make invasive changes to how hashing is performed (as opposed to the ''ext_flag'' mechanism that is used for incremental extensions). An alternative is having them use a different tag, but supporting a growing number of tags may become undesirable., where ''Verify'' is defined in bip-schnorr. * If the ''sig'' is 65 bytes long, return ''sig[64] ≠ 0x00'''Why can the hash_type not be 0x00 in 65-byte signatures?''' Permitting that would enable malleating (by third parties, including miners) 64-byte signatures into 65-byte ones, resulting in a different `wtxid` and a different fee rate than the creator intended and Verify(q, hashTapSighash(0x00 || SigMsg(sig[64], 0)), sig[0:64])''. * Otherwise, fail'''Why permit two signature lengths?''' By making the most common type of hash_type implicit, a byte can often be saved.. diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki index 3bbe8f3..82661ff 100644 --- a/bip-tapscript.mediawiki +++ b/bip-tapscript.mediawiki @@ -34,8 +34,8 @@ Specifically, the goal is making '''Schnorr signatures''', '''batch validation'' ==Design== -In order to achieve these goals, signature opcodes OP_CHECKSIG and OP_CHECKSIGVERIFY are modified to verify Schnorr signatures as specified in bip-schnorr and to use a new transaction digest based on the taproot transaction digest. -The tapscript transaction digest also simplifies OP_CODESEPARATOR handling and makes it more efficient. +In order to achieve these goals, signature opcodes OP_CHECKSIG and OP_CHECKSIGVERIFY are modified to verify Schnorr signatures as specified in bip-schnorr and to use a signature message algorithm based on the common message calculation in bip-taproot. +The tapscript signature message also simplifies OP_CODESEPARATOR handling and makes it more efficient. The inefficient OP_CHECKMULTISIG and OP_CHECKMULTISIGVERIFY opcodes are disabled. Instead, a new opcode OP_CHECKSIGADD is introduced to allow creating the same multisignature policies in a batch-verifiable way. @@ -92,7 +92,7 @@ The following rules apply to OP_CHECKSIG, OP_CHECKSIGVERIFYn is larger than 4 bytes, the script MUST fail and terminate immediately. * If the public key size is zero, the script MUST fail and terminate immediately. * If the public key size is 32 bytes, it is considered to be a public key as described in bip-schnorr: -** If the signature is not the empty vector, the signature is validated against the public key (see the next subsection). +** If the signature is not the empty vector, the signature is validated against the public key (see the next subsection). Validation failure in this case immediately terminates script execution with failure. * If the public key size is not zero and not 32 bytes, the public key is of an ''unknown public key type'''''Unknown public key types''' allow adding new signature validation rules through softforks. A softfork could add actual signature validation which either passes or makes the script fail and terminate immediately. This way, new SIGHASH modes can be added, as well as [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-December/016549.html NOINPUT-tagged public keys] and a public key constant which is replaced by the taproot internal key for signature validation. and no actual signature verification is applied. During script execution of signature opcodes they behave exactly as known public key types except that signature validation is considered to be successful. * If the script did not fail and terminate before this step, regardless of the public key type: ** If the signature is the empty vector: @@ -107,18 +107,18 @@ The following rules apply to OP_CHECKSIG, OP_CHECKSIGVERIFYOP_CODESEPARATOR before the currently executed signature opcode, with the value in little endian (or ''0xffffffff'' if none executed). The first opcode in a script has a position of 0. A multi-byte push opcode is counted as one opcode, regardless of the size of data being pushed. -* If the ''sig'' is 64 bytes long, return ''Verify(q, hashTapSigHash(0x00 || SigMsg(0x00, 1) || ext), sig)'', where ''Verify'' is defined in bip-schnorr. -* If the ''sig'' is 65 bytes long, return ''sig[64] ≠ 0x00 and Verify(q, hashTapSighash(0x00 || SigMsg(sig[64], 0) || ext), sig[0:64])''. +* If the ''sig'' is 64 bytes long, return ''Verify(p, hashTapSigHash(0x00 || SigMsg(0x00, 1) || ext), sig)'', where ''Verify'' is defined in bip-schnorr. +* If the ''sig'' is 65 bytes long, return ''sig[64] ≠ 0x00 and Verify(p, hashTapSighash(0x00 || SigMsg(sig[64], 1) || ext), sig[0:64])''. * Otherwise, fail. In summary, the semantics of signature validation is identical to bip-taproot, except the following: -# The digest commits to tapscript-specific data ''key_version''.'''Why does the transaction digest commit to the ''key_version''?''' This is for future extensions that define unknown public key types, making sure signatures can't be moved from one key type to another. -# The digest commits to the executed script through the ''tapleaf_hash'' which includes the leaf version and script instead of ''scriptCode''. This implies that this commitment is unaffected by OP_CODESEPARATOR. -# The digest commits to the opcode position of the last executed OP_CODESEPARATOR.'''Why does the transaction digest commit to the position of the last executed OP_CODESEPARATOR?''' This allows continuing to use OP_CODESEPARATOR to sign the executed path of the script. Because the codeseparator_position is the last input to the digest, the SHA256 midstate can be efficiently cached for multiple OP_CODESEPARATORs in a single script. In contrast, the BIP143 handling of OP_CODESEPARATOR is to commit to the executed script only from the last executed OP_CODESEPARATOR onwards which requires unnecessary rehashing of the script. It should be noted that the one known OP_CODESEPARATOR use case of saving a second public key push in a script by sharing the first one between two code branches can be most likely expressed even cheaper by moving each branch into a separate taproot leaf. +# The signature message includes the tapscript-specific data ''key_version''.'''Why does the signature message commit to the ''key_version''?''' This is for future extensions that define unknown public key types, making sure signatures can't be moved from one key type to another. +# The signature message commits to the executed script through the ''tapleaf_hash'' which includes the leaf version and script instead of ''scriptCode''. This implies that this commitment is unaffected by OP_CODESEPARATOR. +# The signature message includes the opcode position of the last executed OP_CODESEPARATOR.'''Why does the signature message include the position of the last executed OP_CODESEPARATOR?''' This allows continuing to use OP_CODESEPARATOR to sign the executed path of the script. Because the codeseparator_position is the last input to the hash, the SHA256 midstate can be efficiently cached for multiple OP_CODESEPARATORs in a single script. In contrast, the BIP143 handling of OP_CODESEPARATOR is to commit to the executed script only from the last executed OP_CODESEPARATOR onwards which requires unnecessary rehashing of the script. It should be noted that the one known OP_CODESEPARATOR use case of saving a second public key push in a script by sharing the first one between two code branches can be most likely expressed even cheaper by moving each branch into a separate taproot leaf. ===Resource limits=== -- cgit v1.2.3 From e1914b817311526fffddb21ae84cce5b9a7d5eed Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sun, 19 Jan 2020 14:15:30 -0800 Subject: fixes --- bip-0340.mediawiki | 3 +++ bip-0340/speedup-batch.png | Bin 0 -> 11914 bytes bip-0341.mediawiki | 2 +- bip-0342.mediawiki | 2 +- bip-schnorr/speedup-batch.png | Bin 11914 -> 0 bytes 5 files changed, 5 insertions(+), 2 deletions(-) create mode 100644 bip-0340/speedup-batch.png delete mode 100644 bip-schnorr/speedup-batch.png diff --git a/bip-0340.mediawiki b/bip-0340.mediawiki index 6a431fe..6ae95c8 100644 --- a/bip-0340.mediawiki +++ b/bip-0340.mediawiki @@ -4,9 +4,12 @@ Author: Pieter Wuille Jonas Nick Tim Ruffing + Comments-Summary: No comments yet. + Comments-URI: Status: Draft Type: Informational License: BSD-2-Clause + Created: 2020-01-19 Post-History: 2018-07-06: https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-July/016203.html [bitcoin-dev] Schnorr signatures BIP diff --git a/bip-0340/speedup-batch.png b/bip-0340/speedup-batch.png new file mode 100644 index 0000000..fe672d4 Binary files /dev/null and b/bip-0340/speedup-batch.png differ diff --git a/bip-0341.mediawiki b/bip-0341.mediawiki index a0d2375..2b27ba7 100644 --- a/bip-0341.mediawiki +++ b/bip-0341.mediawiki @@ -9,7 +9,7 @@ Comments-URI: Status: Draft Type: Standards Track - Created: + Created: 2020-01-19 License: BSD-3-Clause Requires: 340 Post-History: 2019-05-06: https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2019-May/016914.html [bitcoin-dev] Taproot proposal diff --git a/bip-0342.mediawiki b/bip-0342.mediawiki index d0b2ece..e9c70e6 100644 --- a/bip-0342.mediawiki +++ b/bip-0342.mediawiki @@ -9,7 +9,7 @@ Comments-URI: Status: Draft Type: Standards Track - Created: + Created: 2020-01-19 License: BSD-3-Clause Requires: 340, 341 Post-History: 2019-05-06: https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2019-May/016914.html [bitcoin-dev] Taproot proposal diff --git a/bip-schnorr/speedup-batch.png b/bip-schnorr/speedup-batch.png deleted file mode 100644 index fe672d4..0000000 Binary files a/bip-schnorr/speedup-batch.png and /dev/null differ -- cgit v1.2.3 From fa305e5abda3c390acc4a186a415c0aa58b81cd4 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sun, 19 Jan 2020 14:24:30 -0800 Subject: Make buildtable.pl support Requires: field --- scripts/buildtable.pl | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/buildtable.pl b/scripts/buildtable.pl index 144ede6..75ace26 100755 --- a/scripts/buildtable.pl +++ b/scripts/buildtable.pl @@ -34,6 +34,7 @@ my %MiscField = ( 'Discussions-To' => undef, 'Post-History' => undef, 'Replaces' => undef, + 'Requires' => undef, 'Superseded-By' => undef, ); -- cgit v1.2.3 From c3b91dcc22fbaf976e64d3596c5680eb778e7be8 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sun, 19 Jan 2020 14:24:47 -0800 Subject: Fixes to headers --- bip-0340.mediawiki | 4 ++-- bip-0341.mediawiki | 4 ++-- bip-0342.mediawiki | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/bip-0340.mediawiki b/bip-0340.mediawiki index 6ae95c8..ad9e60e 100644 --- a/bip-0340.mediawiki +++ b/bip-0340.mediawiki @@ -5,9 +5,9 @@ Jonas Nick Tim Ruffing Comments-Summary: No comments yet. - Comments-URI: + Comments-URI: https://github.com/bitcoin/bips/wiki/Comments:BIP-0340 Status: Draft - Type: Informational + Type: Standards Track License: BSD-2-Clause Created: 2020-01-19 Post-History: 2018-07-06: https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-July/016203.html [bitcoin-dev] Schnorr signatures BIP diff --git a/bip-0341.mediawiki b/bip-0341.mediawiki index 2b27ba7..44b9818 100644 --- a/bip-0341.mediawiki +++ b/bip-0341.mediawiki @@ -1,12 +1,12 @@
   BIP: 341
   Layer: Consensus (soft fork)
-  Title: Taproot: SegWit version 1 output spending rules
+  Title: Taproot: SegWit version 1 spending rules
   Author: Pieter Wuille 
           Jonas Nick 
           Anthony Towns 
   Comments-Summary: No comments yet.
-  Comments-URI:
+  Comments-URI: https://github.com/bitcoin/bips/wiki/Comments:BIP-0341
   Status: Draft
   Type: Standards Track
   Created: 2020-01-19
diff --git a/bip-0342.mediawiki b/bip-0342.mediawiki
index e9c70e6..ac8f4aa 100644
--- a/bip-0342.mediawiki
+++ b/bip-0342.mediawiki
@@ -6,7 +6,7 @@
           Jonas Nick 
           Anthony Towns 
   Comments-Summary: No comments yet.
-  Comments-URI:
+  Comments-URI: https://github.com/bitcoin/bips/wiki/Comments:BIP-0342
   Status: Draft
   Type: Standards Track
   Created: 2020-01-19
-- 
cgit v1.2.3


From 9de7dfccfa996c36f9c7d446294dcb7e74cd31cf Mon Sep 17 00:00:00 2001
From: Pieter Wuille 
Date: Sun, 19 Jan 2020 14:24:57 -0800
Subject: Add to README

---
 README.mediawiki | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/README.mediawiki b/README.mediawiki
index 46cc389..4a086af 100644
--- a/README.mediawiki
+++ b/README.mediawiki
@@ -931,6 +931,27 @@ Those proposing changes should consider that ultimately consent may rest with th
 | Gleb Naumenko, Pieter Wuille
 | Standard
 | Draft
+|-
+| [[bip-0340.mediawiki|340]]
+|
+| Schnorr Signatures for secp256k1
+| Pieter Wuille, Jonas Nick, Tim Ruffing
+| Standard
+| Draft
+|-
+| [[bip-0341.mediawiki|341]]
+| Consensus (soft fork)
+| Taproot: SegWit version 1 spending rules
+| Pieter Wuille, Jonas Nick, Anthony Towns
+| Standard
+| Draft
+|-
+| [[bip-0342.mediawiki|342]]
+| Consensus (soft fork)
+| Validation of Taproot Scripts
+| Pieter Wuille, Jonas Nick, Anthony Towns
+| Standard
+| Draft
 |}
 
 
-- 
cgit v1.2.3


From 9cf4038f17cb566bdc79b5ec12dee5338b1122d1 Mon Sep 17 00:00:00 2001
From: Pieter Wuille 
Date: Sun, 19 Jan 2020 14:52:43 -0800
Subject: fix BIP links

---
 bip-0340.mediawiki | 10 +++++-----
 bip-0341.mediawiki | 38 +++++++++++++++++++-------------------
 bip-0342.mediawiki | 22 +++++++++++-----------
 3 files changed, 35 insertions(+), 35 deletions(-)

diff --git a/bip-0340.mediawiki b/bip-0340.mediawiki
index ad9e60e..9e0a73e 100644
--- a/bip-0340.mediawiki
+++ b/bip-0340.mediawiki
@@ -31,7 +31,7 @@ transactions. These are [https://www.secg.org/sec1-v2.pdf standardized], but hav
 compared to [http://publikationen.ub.uni-frankfurt.de/opus4/files/4280/schnorr.pdf Schnorr signatures] over the same curve:
 
 * '''Provable security''': Schnorr signatures are provably secure. In more detail, they are ''strongly unforgeable under chosen message attack (SUF-CMA)''Informally, this means that without knowledge of the secret key but given valid signatures of arbitrary messages, it is not possible to come up with further valid signatures. [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf in the random oracle model assuming the hardness of the elliptic curve discrete logarithm problem (ECDLP)] and [http://www.neven.org/papers/schnorr.pdf in the generic group model assuming variants of preimage and second preimage resistance of the used hash function]A detailed security proof in the random oracle model, which essentially restates [https://www.di.ens.fr/~pointche/Documents/Papers/2000_joc.pdf the original security proof by Pointcheval and Stern] more explicitly, can be found in [https://eprint.iacr.org/2016/191 a paper by Kiltz, Masny and Pan]. All these security proofs assume a variant of Schnorr signatures that use ''(e,s)'' instead of ''(R,s)'' (see Design above). Since we use a unique encoding of ''R'', there is an efficiently computable bijection that maps ''(R,s)'' to ''(e,s)'', which allows to convert a successful SUF-CMA attacker for the ''(e,s)'' variant to a successful SUF-CMA attacker for the ''(R,s)'' variant (and vice-versa). Furthermore, the proofs consider a variant of Schnorr signatures without key prefixing (see Design above), but it can be verified that the proofs are also correct for the variant with key prefixing. As a result, all the aforementioned security proofs apply to the variant of Schnorr signatures proposed in this document.. In contrast, the [https://nbn-resolving.de/urn:nbn:de:hbz:294-60803 best known results for the provable security of ECDSA] rely on stronger assumptions.
-* '''Non-malleability''': The SUF-CMA security of Schnorr signatures implies that they are non-malleable. On the other hand, ECDSA signatures are inherently malleableIf ''(r,s)'' is a valid ECDSA signature for a given message and key, then ''(r,n-s)'' is also valid for the same message and key. If ECDSA is restricted to only permit one of the two variants (as Bitcoin does through a policy rule on the network), it can be [https://nbn-resolving.de/urn:nbn:de:hbz:294-60803 proven] non-malleable under stronger than usual assumptions.; a third party without access to the secret key can alter an existing valid signature for a given public key and message into another signature that is valid for the same key and message. This issue is discussed in [bip-0062.mediawiki BIP62] and [bip-0146.mediawiki BIP146].
+* '''Non-malleability''': The SUF-CMA security of Schnorr signatures implies that they are non-malleable. On the other hand, ECDSA signatures are inherently malleableIf ''(r,s)'' is a valid ECDSA signature for a given message and key, then ''(r,n-s)'' is also valid for the same message and key. If ECDSA is restricted to only permit one of the two variants (as Bitcoin does through a policy rule on the network), it can be [https://nbn-resolving.de/urn:nbn:de:hbz:294-60803 proven] non-malleable under stronger than usual assumptions.; a third party without access to the secret key can alter an existing valid signature for a given public key and message into another signature that is valid for the same key and message. This issue is discussed in [[bip-0062.mediawiki|BIP62]] and [[bip-0146.mediawiki|BIP146]].
 * '''Linearity''': Schnorr signatures provide a simple and efficient method that enables multiple collaborating parties to produce a signature that is valid for the sum of their public keys. This is the building block for various higher-level constructions that improve efficiency and privacy, such as multisignatures and others (see Applications below).
 
 For all these advantages, there are virtually no disadvantages, apart
@@ -42,7 +42,7 @@ made:
 * '''Signature encoding''': Instead of using [https://en.wikipedia.org/wiki/X.690#DER_encoding DER]-encoding for signatures (which are variable size, and up to 72 bytes), we can use a simple fixed 64-byte format.
 * '''Public key encoding''': Instead of using ''compressed'' 33-byte encodings of elliptic curve points which are common in Bitcoin today, public keys in this proposal are encoded as 32 bytes.
 * '''Batch verification''': The specific formulation of ECDSA signatures that is standardized cannot be verified more efficiently in batch compared to individually, unless additional witness data is added. Changing the signature scheme offers an opportunity to address this.
-* '''Completely specified''': To be safe for usage in consensus systems, the verification algorithm must be completely specified at the byte level. This guarantees that nobody can construct a signature that is valid to some verifiers but not all. This is traditionally not a requirement for digital signature schemes, and the lack of exact specification for the DER parsing of ECDSA signatures has caused problems for Bitcoin [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2015-July/009697.html in the past], needing [https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki BIP66] to address it. In this document we aim to meet this property by design. For batch verification, which is inherently non-deterministic as the verifier can choose their batches, this property implies that the outcome of verification may only differ from individual verifications with negligible probability, even to an attacker who intentionally tries to make batch- and non-batch verification differ.
+* '''Completely specified''': To be safe for usage in consensus systems, the verification algorithm must be completely specified at the byte level. This guarantees that nobody can construct a signature that is valid to some verifiers but not all. This is traditionally not a requirement for digital signature schemes, and the lack of exact specification for the DER parsing of ECDSA signatures has caused problems for Bitcoin [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2015-July/009697.html in the past], needing [[bip-0066.mediawiki|BIP66]] to address it. In this document we aim to meet this property by design. For batch verification, which is inherently non-deterministic as the verifier can choose their batches, this property implies that the outcome of verification may only differ from individual verifications with negligible probability, even to an attacker who intentionally tries to make batch- and non-batch verification differ.
 
 By reusing the same curve and hash function as Bitcoin uses for ECDSA, we are able to retain existing mechanisms for choosing secret and public keys, and we avoid introducing new assumptions about the security of elliptic curves and hash functions.
 
@@ -62,11 +62,11 @@ encodings and operations.
 
 Since we would like to avoid the fragility that comes with short hashes, the ''e'' variant does not provide significant advantages. We choose the ''R''-option, which supports batch verification. 
 
-'''Key prefixing''' Using the verification rule above directly makes Schnorr signatures vulnerable to "related-key attacks" in which a third party can convert a signature ''(R, s)'' for public key ''P'' into a signature ''(R, s + a⋅hash(R || m))'' for public key ''P + a⋅G'' and the same message ''m'', for any given additive tweak ''a'' to the signing key. This would render signatures insecure when keys are generated using [bip-0032.mediawiki#public-parent-key--public-child-key BIP32's unhardened derivation] and other methods that rely on additive tweaks to existing keys such as Taproot.
+'''Key prefixing''' Using the verification rule above directly makes Schnorr signatures vulnerable to "related-key attacks" in which a third party can convert a signature ''(R, s)'' for public key ''P'' into a signature ''(R, s + a⋅hash(R || m))'' for public key ''P + a⋅G'' and the same message ''m'', for any given additive tweak ''a'' to the signing key. This would render signatures insecure when keys are generated using [[bip-0032.mediawiki#public-parent-key--public-child-key|BIP32's unhardened derivation]] and other methods that rely on additive tweaks to existing keys such as Taproot.
 
 To protect against these attacks, we choose ''key prefixed''A limitation of committing to the public key (rather than to a short hash of it, or not at all) is that it removes the ability for public key recovery or verifying signatures against a short public key hash. These constructions are generally incompatible with batch verification. Schnorr signatures; changing the equation to ''s⋅G = R + hash(R || P || m)⋅P''. [https://eprint.iacr.org/2015/1135.pdf It can be shown] that key prefixing protects against related-key attacks with additive tweaks. In general, key prefixing increases robustness in multi-user settings, e.g., it seems to be a requirement for proving the MuSig multisignature scheme secure (see Applications below).
 
-We note that key prefixing is not strictly necessary for transaction signatures as used in Bitcoin currently, because signed transactions indirectly commit to the public keys already, i.e., ''m'' contains a commitment to ''pk''. However, this indirect commitment should not be relied upon because it may change with proposals such as SIGHASH_NOINPUT ([bip-0118.mediawiki BIP118]), and would render the signature scheme unsuitable for other purposes than signing transactions, e.g., [https://bitcoin.org/en/developer-reference#signmessage signing ordinary messages].
+We note that key prefixing is not strictly necessary for transaction signatures as used in Bitcoin currently, because signed transactions indirectly commit to the public keys already, i.e., ''m'' contains a commitment to ''pk''. However, this indirect commitment should not be relied upon because it may change with proposals such as SIGHASH_NOINPUT ([[bip-0118.mediawiki|BIP118]]), and would render the signature scheme unsuitable for other purposes than signing transactions, e.g., [https://bitcoin.org/en/developer-reference#signmessage signing ordinary messages].
 
 '''Encoding R and public key point P''' There exist several possibilities for encoding elliptic curve points:
 # Encoding the full X and Y coordinates of ''P'' and ''R'', resulting in a 64-byte public key and a 96-byte signature.
@@ -141,7 +141,7 @@ The algorithm ''PubKey(sk)'' is defined as:
 
 Note that we use a very different public key format (32 bytes) than the ones used by existing systems (which typically use elliptic curve points as public keys, or 33-byte or 65-byte encodings of them). A side effect is that ''PubKey(sk) = PubKey(bytes(n - int(sk))'', so every public key has two corresponding secret keys.
 
-As an alternative to generating keys randomly, it is also possible and safe to repurpose existing key generation algorithms for ECDSA in a compatible way. The secret keys constructed by such an algorithm can be used as ''sk'' directly. The public keys constructed by such an algorithm (assuming they use the 33-byte compressed encoding) need to be converted by dropping the first byte. Specifically, [https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki BIP32] and schemes built on top of it remain usable.
+As an alternative to generating keys randomly, it is also possible and safe to repurpose existing key generation algorithms for ECDSA in a compatible way. The secret keys constructed by such an algorithm can be used as ''sk'' directly. The public keys constructed by such an algorithm (assuming they use the 33-byte compressed encoding) need to be converted by dropping the first byte. Specifically, [[bip-0032.mediawiki|BIP32]] and schemes built on top of it remain usable.
 
 ==== Default Signing ====
 
diff --git a/bip-0341.mediawiki b/bip-0341.mediawiki
index 44b9818..8f27c35 100644
--- a/bip-0341.mediawiki
+++ b/bip-0341.mediawiki
@@ -31,7 +31,7 @@ This proposal aims to improve privacy, efficiency, and flexibility of Bitcoin's
 
 ==Design==
 
-A number of related ideas for improving Bitcoin's scripting capabilities have been previously proposed: Schnorr signatures ([https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki BIP340), Merkle branches ("MAST", [bip-0114.mediawiki BIP114], [bip-0117.mediawiki BIP117]), new sighash modes ([bip-0118.mediawiki BIP118]), new opcodes like CHECKSIGFROMSTACK, [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-January/015614.html Taproot], [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-February/015700.html Graftroot], [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-July/016249.html G'root], and [https://bitcointalk.org/index.php?topic=1377298.0 cross-input aggregation].
+A number of related ideas for improving Bitcoin's scripting capabilities have been previously proposed: Schnorr signatures ([[bip-0340|BIP340]]), Merkle branches ("MAST", [[bip-0114|BIP114]], [[bip-0117|BIP117]]), new sighash modes ([[bip-0118|BIP118]]), new opcodes like CHECKSIGFROMSTACK, [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-January/015614.html Taproot], [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-February/015700.html Graftroot], [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-July/016249.html G'root], and [https://bitcointalk.org/index.php?topic=1377298.0 cross-input aggregation].
 
 Combining all these ideas in a single proposal would be an extensive change, be hard to review, and likely miss new discoveries that otherwise could have been made along the way. Not all are equally mature as well. For example, cross-input aggregation [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-March/015838.html interacts] in complex ways with upgrade mechanisms, and solutions to that are still [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-October/016461.html in flux]. On the other hand, separating them all into independent upgrades would reduce the efficiency and privacy gains to be had, and wallet and service providers may not be inclined to go through many incremental updates. Therefore, we're faced with a tradeoff between functionality and scope creep. In this design we strike a balance by focusing on the structural script improvements offered by Taproot and Merkle branches, as well as changes necessary to make them usable and efficient. For things like sighashes and opcodes we include fixes for known problems, but exclude new features that can be added independently with no downsides.
 
@@ -40,7 +40,7 @@ As a result we choose this combination of technologies:
 * '''Taproot''' on top of that lets us merge the traditionally separate pay-to-pubkey and pay-to-scripthash policies, making all outputs spendable by either a key or (optionally) a script, and indistinguishable from each other. As long as the key-based spending path is used for spending, it is not revealed whether a script path was permitted as well, resulting in space savings and an increase in scripting privacy at spending time.
 * Taproot's advantages become apparent under the assumption that most applications involve outputs that could be spent by all parties agreeing. That's where '''Schnorr''' signatures come in, as they permit [https://eprint.iacr.org/2018/068 key aggregation]: a public key can be constructed from multiple participant public keys, and which requires cooperation between all participants to sign for. Such multi-party public keys and signatures are indistinguishable from their single-party equivalents. This means that with taproot most applications can use the key-based spending path, which is both efficient and private. This can be generalized to arbitrary M-of-N policies, as Schnorr signatures support threshold signing, at the cost of more complex setup protocols.
 * As Schnorr signatures also permit '''batch validation''', allowing multiple signatures to be validated together more efficiently than validating each one independently, we make sure all parts of the design are compatible with this.
-* Where unused bits appear as a result of the above changes, they are reserved for mechanisms for '''future extensions'''. As a result, every script in the Merkle tree has an associated version such that new script versions can be introduced with a soft fork while remaining compatible with BIP 341. Additionally, future soft forks can make use of the currently unused annex in the witness (see [[#Rationale]]).
+* Where unused bits appear as a result of the above changes, they are reserved for mechanisms for '''future extensions'''. As a result, every script in the Merkle tree has an associated version such that new script versions can be introduced with a soft fork while remaining compatible with BIP 341. Additionally, future soft forks can make use of the currently unused annex in the witness (see [[bip-0341.mediawiki#Rationale|BIP341]]).
 * While the core semantics of the '''signature hashing algorithm''' are not changed, a number of improvements are included in this proposal. The new signature hashing algorithm fixes the verification capabilities of offline signing devices by including amount and scriptPubKey in the signature message, avoids unnecessary hashing, uses '''tagged hashes''' and defines a default sighash byte.
 * The '''public key is directly included in the output''' in contrast to typical earlier constructions which store a hash of the public key or script in the output. This has the same cost for senders and is more space efficient overall if the key-based spending path is taken. '''Why is the public key directly included in the output?''' While typical earlier constructions store a hash of a script or a public key in the output, this is rather wasteful when a public key is always involved. To guarantee batch verifiability, the public key must be known to every verifier, and thus only revealing its hash as an output would imply adding an additional 32 bytes to the witness. Furthermore, to maintain [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2016-January/012198.html 128-bit collision security] for outputs, a 256-bit hash would be required anyway, which is comparable in size (and thus in cost for senders) to revealing the public key directly. While the usage of public key hashes is often said to protect against ECDLP breaks or quantum computers, this protection is very weak at best: transactions are not protected while being confirmed, and a very [https://twitter.com/pwuille/status/1108097835365339136 large portion] of the currency's supply is not under such protection regardless. Actual resistance to such systems can be introduced by relying on different cryptographic assumptions, but this proposal focuses on improvements that do not change the security model.
 
@@ -50,14 +50,14 @@ Informally, the resulting design is as follows: a new witness version is added (
 
 This section specifies the Taproot consensus rules. Validity is defined by exclusion: a block or transaction is valid if no condition exists that marks it failed.
 
-The notation below follows that of [bip-0340.mediawiki#design BIP340]. This includes the ''hashtag(x)'' notation to refer to ''SHA256(SHA256(tag) || SHA256(tag) || x)''. To the best of the authors' knowledge, no existing use of SHA256 in Bitcoin feeds it a message that starts with two single SHA256 outputs, making collisions between ''hashtag'' with other hashes extremely unlikely.
+The notation below follows that of [[bip-0340.mediawiki#design|BIP340]]. This includes the ''hashtag(x)'' notation to refer to ''SHA256(SHA256(tag) || SHA256(tag) || x)''. To the best of the authors' knowledge, no existing use of SHA256 in Bitcoin feeds it a message that starts with two single SHA256 outputs, making collisions between ''hashtag'' with other hashes extremely unlikely.
 
 === Script validation rules ===
 
-A Taproot output is a native SegWit output (see [bip-0141.mediawiki BIP141]) with version number 1, and a 32-byte witness program.
+A Taproot output is a native SegWit output (see [[bip-0141.mediawiki|BIP141]]) with version number 1, and a 32-byte witness program.
 The following rules only apply when such an output is being spent. Any other outputs, including version 1 outputs with lengths other than 32 bytes, or P2SH-wrapped version 1 outputs'''Why is P2SH-wrapping not supported?''' Using P2SH-wrapped outputs only provides 80-bit collision security due to the use of a 160-bit hash. This is considered low, and becomes a security risk whenever the output includes data from more than a single party (public keys, hashes, ...)., remain unencumbered.
 
-* Let ''q'' be the 32-byte array containing the witness program (the second push in the scriptPubKey) which represents a public key according to [bip-0340.mediawiki#design BIP340].
+* Let ''q'' be the 32-byte array containing the witness program (the second push in the scriptPubKey) which represents a public key according to [[bip-0340.mediawiki#design|BIP340]].
 * Fail if the witness stack has 0 elements.
 * If there are at least two witness elements, and the first byte of the last element is 0x50'''Why is the first byte of the annex 0x50?''' The 0x50 is chosen as it could not be confused with a valid P2WPKH or P2WSH spending. As the control block's initial byte's lowest bit is used to indicate the public key's Y squareness, each leaf version needs an even byte value and the immediately following odd byte value that are both not yet used in P2WPKH or P2WSH spending. To indicate the annex, only an "unpaired" available byte is necessary like 0x50. This choice maximizes the available options for future script versions., this last element is called ''annex'' ''a'''''What is the purpose of the annex?''' The annex is a reserved space for future extensions, such as indicating the validation costs of computationally expensive new opcodes in a way that is recognizable without knowing the scriptPubKey of the output being spent. Until the meaning of this field is defined by another softfork, users SHOULD NOT include annex in transactions, or it may lead to PERMANENT FUND LOSS. and is removed from the witness stack. The annex (or the lack of thereof) is always covered by the signature and contributes to transaction weight, but is otherwise ignored during taproot validation.
 * If there is exactly one element left in the witness stack, key path spending is used:
@@ -65,19 +65,19 @@ The following rules only apply when such an output is being spent. Any other out
 * If there are at least two witness elements left, script path spending is used:
 ** Call the second-to-last stack element ''s'', the script.
 ** The last stack element is called the control block ''c'', and must have length ''33 + 32m'', for a value of ''m'' that is an integer between 0 and 128'''Why is the Merkle path length limited to 128?''' The optimally space-efficient Merkle tree can be constructed based on the probabilities of the scripts in the leaves, using the Huffman algorithm. This algorithm will construct branches with lengths approximately equal to ''log2(1/probability)'', but to have branches longer than 128 you would need to have scripts with an execution chance below 1 in ''2128''. As that is our security bound, scripts that truly have such a low chance can probably be removed entirely., inclusive. Fail if it does not have such a length.
-** Let ''p = c[1:33]'' and let ''P = point(p)'' where ''point'' and ''[:]'' are defined as in [bip-0340.mediawiki#design BIP340]. Fail if this point is not on the curve.
+** Let ''p = c[1:33]'' and let ''P = point(p)'' where ''point'' and ''[:]'' are defined as in [bip-0340.mediawiki#design|BIP340]. Fail if this point is not on the curve.
 ** Let ''v = c[0] & 0xfe'' and call it the ''leaf version'''''What constraints are there on the leaf version?''' First, the leaf version cannot be odd as ''c[0] & 0xfe'' will always be even, and cannot be ''0x50'' as that would result in ambiguity with the annex. In addition, in order to support some forms of static analysis that rely on being able to identify script spends without access to the output being spent, it is recommended to avoid using any leaf versions that would conflict with a valid first byte of either a valid P2WPKH pubkey or a valid P2WSH script (that is, both ''v'' and ''v | 1'' should be an undefined, invalid or disabled opcode or an opcode that is not valid as the first opcode). The values that comply to this rule are the 32 even values between ''0xc0'' and ''0xfe'' and also ''0x66'', ''0x7e'', ''0x80'', ''0x84'', ''0x96'', ''0x98'', ''0xba'', ''0xbc'', ''0xbe''. Note also that this constraint implies that leaf versions should be shared amongst different witness versions, as knowing the witness version requires access to the output being spent..
 ** Let ''k0 = hashTapLeaf(v || compact_size(size of s) || s)''; also call it the ''tapleaf hash''.
 ** For ''j'' in ''[0,1,...,m-1]'':
 *** Let ''ej = c[33+32j:65+32j]''.
 *** Let ''kj+1 depend on whether ''kj < ej'' (lexicographically)'''Why are child elements sorted before hashing in the Merkle tree?''' By doing so, it is not necessary to reveal the left/right directions along with the hashes in revealed Merkle branches. This is possible because we do not actually care about the position of specific scripts in the tree; only that they are actually committed to.:
-**** If ''kj < ej'': ''kj+1 = hashTapBranch(kj || ej)'''''Why not use a more efficient hash construction for inner Merkle nodes?''' The chosen construction does require two invocations of the SHA256 compression functions, one of which can be avoided in theory (see [bip-0098.mediawiki BIP98]). However, it seems preferable to stick to constructions that can be implemented using standard cryptographic primitives, both for implementation simplicity and analyzability. If necessary, a significant part of the second compression function can be optimized out by [https://github.com/bitcoin/bitcoin/pull/13191 specialization] for 64-byte inputs..
+**** If ''kj < ej'': ''kj+1 = hashTapBranch(kj || ej)'''''Why not use a more efficient hash construction for inner Merkle nodes?''' The chosen construction does require two invocations of the SHA256 compression functions, one of which can be avoided in theory (see [[bip-0098.mediawiki|BIP98]]). However, it seems preferable to stick to constructions that can be implemented using standard cryptographic primitives, both for implementation simplicity and analyzability. If necessary, a significant part of the second compression function can be optimized out by [https://github.com/bitcoin/bitcoin/pull/13191 specialization] for 64-byte inputs..
 **** If ''kj ≥ ej'': ''kj+1 = hashTapBranch(ej || kj)''.
 ** Let ''t = hashTapTweak(p || km)''.
 ** If ''t ≥ 0xFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141'' (order of secp256k1), fail.
-** Let ''Q = point(q) if (c[0] & 1) = 1 and -point(q) otherwise'''''Why is it necessary to reveal a bit to indicate if the point represented by the output public key is negated in a script path spend?''' The ''point'' function (defined in [bip-0340.mediawiki#design BIP340]) always constructs a point with a square Y coordinate, but because ''Q'' is constructed by adding the taproot tweak to the internal public key ''P'', it cannot easily be guaranteed that ''Q'' in fact has such a Y coordinate. Therefore, before verifying the taproot tweak the original point is restored by negating if necessary. We can not ignore the Y coordinate because it would prevent batch verification. Trying out multiple internal keys until there's such a ''Q'' is possible but undesirable and unnecessary since this information about the Y coordinate only consumes an unused bit.. Fail if this point is not on the curve.
+** Let ''Q = point(q) if (c[0] & 1) = 1 and -point(q) otherwise'''''Why is it necessary to reveal a bit to indicate if the point represented by the output public key is negated in a script path spend?''' The ''point'' function (defined in [[bip-0340.mediawiki#design|BIP340]]) always constructs a point with a square Y coordinate, but because ''Q'' is constructed by adding the taproot tweak to the internal public key ''P'', it cannot easily be guaranteed that ''Q'' in fact has such a Y coordinate. Therefore, before verifying the taproot tweak the original point is restored by negating if necessary. We can not ignore the Y coordinate because it would prevent batch verification. Trying out multiple internal keys until there's such a ''Q'' is possible but undesirable and unnecessary since this information about the Y coordinate only consumes an unused bit.. Fail if this point is not on the curve.
 ** If ''Q ≠ P + int(t)G'', fail.
-** Execute the script, according to the applicable script rules'''What are the applicable script rules in script path spends?''' [bip-0342.mediawiki#design BIP342] specifies validity rules that apply for leaf version 0xc0, but future proposals can introduce rules for other leaf versions., using the witness stack elements excluding the script ''s'', the control block ''c'', and the annex ''a'' if present, as initial stack.
+** Execute the script, according to the applicable script rules'''What are the applicable script rules in script path spends?''' [[bip-0342.mediawiki|BIP342]] specifies validity rules that apply for leaf version 0xc0, but future proposals can introduce rules for other leaf versions., using the witness stack elements excluding the script ''s'', the control block ''c'', and the annex ''a'' if present, as initial stack.
 
 ''q'' is referred to as ''taproot output key'' and ''p'' as ''taproot internal key''.
 
@@ -93,7 +93,7 @@ The parameter ''hash_type'' is an 8-bit unsigned value. The SIGHASH
 * Using any undefined ''hash_type'' (not ''0x00'', ''0x01'', ''0x02'', ''0x03'', ''0x81'', ''0x82'', or ''0x83'''''Why reject unknown ''hash_type'' values?''' By doing so, it is easier to reason about the worst case amount of signature hashing an implementation with adequate caching must perform.).
 * Using SIGHASH_SINGLE without a "corresponding output" (an output with the same index as the input being verified).
 
-The parameter ''ext_flag'' is an integer in range 0-127, and is used for indicating (in the message) that extensions are added at the end of the message'''What extensions use the ''ext_flag'' mechanism?''' [bip-0342.mediawiki#design BIP342] reuses the same common signature message algorithm, but adds BIP342-specific data at the end, which is indicated using ''ext_flag = 1''..
+The parameter ''ext_flag'' is an integer in range 0-127, and is used for indicating (in the message) that extensions are added at the end of the message'''What extensions use the ''ext_flag'' mechanism?''' [[bip-0342.mediawiki|BIP342]] reuses the same common signature message algorithm, but adds BIP342-specific data at the end, which is indicated using ''ext_flag = 1''..
 
 If the parameters take acceptable values, the message is the concatenation of the following data, in order(with byte size of each item listed in parentheses). Numerical values in 2, 4, or 8-byte are encoded in little-endian.
 
@@ -125,7 +125,7 @@ If the parameters take acceptable values, the message is the concatenation of th
 
 The total length of ''SigMsg()'' is at most ''209'' bytes'''What is the output length of ''SigMsg()''?''' The total length of ''SigMsg()'' can be computed using the following formula: ''177 - is_anyonecanpay * 52 - is_none * 32 + has_annex * 32''.. Note that this does not include the size of sub-hashes such as ''sha_prevouts'', which may be cached across signatures of the same transaction.
 
-In summary, the semantics of the [bip-0143.mediawiki BIP143] sighash types remain unchanged, except the following:
+In summary, the semantics of the [[bip-0143.mediawiki|BIP143]] sighash types remain unchanged, except the following:
 # The way and order of serialization is changed.'''Why is the serialization in the signature message changed?''' Hashes that go into the signature message and the message itself are now computed with a single SHA256 invocation instead of double SHA256. There is no expected security improvement by doubling SHA256 because this only protects against length-extension attacks against SHA256 which are not a concern for signature messages because there is no secret data. Therefore doubling SHA256 is a waste of resources. The message computation now follows a logical order with transaction level data first, then input data and output data. This allows to efficiently cache the transaction part of the message across different inputs using the SHA256 midstate. Additionally, sub-hashes can be skipped when calculating the message (for example `sha_prevouts` if SIGHASH_ANYONECANPAY is set) instead of setting them to zero and then hashing them as in BIP143. Despite that, collisions are made impossible by committing to the length of the data (implicit in ''hash_type'' and ''spend_type'') before the variable length data.
 # The signature message commits to the ''scriptPubKey'''''Why does the signature message commit to the ''scriptPubKey''?''' This prevents lying to offline signing devices about output being spent, even when the actually executed script (''scriptCode'' in BIP143) is correct. This means it's possible to compactly prove to a hardware wallet what (unused) execution paths existed..
 # If the SIGHASH_ANYONECANPAY flag is not set, the message commits to the amounts of ''all'' transaction inputs.'''Why does the signature message commit to the amounts of all transaction inputs?''' This eliminates the possibility to lie to offline signing devices about the fee of a transaction.
@@ -135,7 +135,7 @@ In summary, the semantics of the [bip-0143.mediawiki BIP143] sighash types remai
 ==== Taproot key path spending signature validation ====
 
 To validate a signature ''sig'' with public key ''q'':
-* If the ''sig'' is 64 bytes long, return ''Verify(q, hashTapSigHash(0x00 || SigMsg(0x00, 0)), sig)'''''Why is the input to ''hashTapSigHash'' prefixed with 0x00?''' This prefix is called the sighash epoch, and allows reusing the ''hashTapSigHash'' tagged hash in future signature algorithms that make invasive changes to how hashing is performed (as opposed to the ''ext_flag'' mechanism that is used for incremental extensions). An alternative is having them use a different tag, but supporting a growing number of tags may become undesirable., where ''Verify'' is defined in [bip-0340.mediawiki#design BIP340].
+* If the ''sig'' is 64 bytes long, return ''Verify(q, hashTapSigHash(0x00 || SigMsg(0x00, 0)), sig)'''''Why is the input to ''hashTapSigHash'' prefixed with 0x00?''' This prefix is called the sighash epoch, and allows reusing the ''hashTapSigHash'' tagged hash in future signature algorithms that make invasive changes to how hashing is performed (as opposed to the ''ext_flag'' mechanism that is used for incremental extensions). An alternative is having them use a different tag, but supporting a growing number of tags may become undesirable., where ''Verify'' is defined in [[bip-0340.mediawiki#design|BIP340]].
 * If the ''sig'' is 65 bytes long, return ''sig[64] ≠ 0x00'''Why can the hash_type not be 0x00 in 65-byte signatures?''' Permitting that would enable malleating (by third parties, including miners) 64-byte signatures into 65-byte ones, resulting in a different `wtxid` and a different fee rate than the creator intended and Verify(q, hashTapSighash(0x00 || SigMsg(sig[64], 0)), sig[0:64])''.
 * Otherwise, fail'''Why permit two signature lengths?''' By making the most common type of hash_type implicit, a byte can often be saved..
 
@@ -167,7 +167,7 @@ Alice will not be able to notice the script path, but Mallory can unilaterally s
 
 '''Computing the output script''' Once the spending conditions are split into an internal key internal_pubkey and a binary tree whose leaves are (leaf_version, script) tuples, the output script can be computed using the Python3 algorithms below. These algorithms take advantage of helper functions from the [bip-0340/referency.py BIP340 reference code] for integer conversion, point multiplication, and tagged hashes.
 
-First, we define taproot_tweak_pubkey for 32-byte [bip-0340.mediawiki#design BIP340] public key arrays.
+First, we define taproot_tweak_pubkey for 32-byte [[bip-0340.mediawiki|BIP340]] public key arrays.
 In addition to the tweaked public key byte array, the function returns a boolean indicating whether the public key represents the tweaked point or its negation.
 This will be required for spending the output with a script path.
 In order to allow spending with the key path, we define taproot_tweak_seckey to compute the secret key for a tweaked public key.
@@ -191,7 +191,7 @@ def taproot_tweak_seckey(seckey0, h):
     return (seckey + t) % SECP256K1_ORDER
 
 
-The following function, taproot_output_script, returns a byte array with the scriptPubKey (see BIP141).
+The following function, taproot_output_script, returns a byte array with the scriptPubKey (see [[bip-0141.mediawiki|BIP141]]).
 ser_script refers to a function that prefixes its input with a CCompactSize-encoded length.
 
 
@@ -210,7 +210,7 @@ def taproot_tree_helper(script_tree):
 def taproot_output_script(internal_pubkey, script_tree):
     """Given a internal public key and a tree of scripts, compute the output script.
     script_tree is either:
-     - a (leaf_version, script) tuple (leaf_version is 0xc0 for [bip-0342.mediawiki#design BIP342] scripts)
+     - a (leaf_version, script) tuple (leaf_version is 0xc0 for [[bip-0342.mediawiki|BIP342]] scripts)
      - a list of two elements, each with the same structure as script_tree itself
      - None
     """
@@ -222,13 +222,13 @@ def taproot_output_script(internal_pubkey, script_tree):
     return bytes([0x51, 0x20]) + output_pubkey
 
 
-[[File:bip-0342/tree.png|frame|This diagram shows the hashing structure to obtain the tweak from an internal key ''P'' and a Merkle tree consisting of 5 script leaves. ''A'', ''B'', ''C'' and ''E'' are ''TapLeaf'' hashes similar to ''D'' and ''AB'' is a ''TapBranch'' hash. Note that when ''CDE'' is computed ''E'' is hashed first because ''E'' is less than ''CD''.]]
+[[File:bip-0341/tree.png|frame|This diagram shows the hashing structure to obtain the tweak from an internal key ''P'' and a Merkle tree consisting of 5 script leaves. ''A'', ''B'', ''C'' and ''E'' are ''TapLeaf'' hashes similar to ''D'' and ''AB'' is a ''TapBranch'' hash. Note that when ''CDE'' is computed ''E'' is hashed first because ''E'' is less than ''CD''.]]
 
 To spend this output using script ''D'', the control block would contain the following data in this order:
 
          
 
-The TapTweak would then be computed as described in [[#script-validation-rules]] like so:
+The TapTweak would then be computed as described [[bip-0341.mediawiki#script-validation-rules|above]] like so:
 
 
 D = tagged_hash("TapLeaf", bytes([leaf_version]) + ser_script(script))
@@ -238,7 +238,7 @@ ABCDE = tagged_hash("TapBranch", AB + CDE)
 TapTweak = tagged_hash("TapTweak", p + ABCDE)
 
 
-'''Spending using the key path''' A Taproot output can be spent with the secret key corresponding to the internal_pubkey. To do so, a witness stack consists of a single element: a bip-schnorr signature on the signature hash as defined above, with the secret key tweaked by the same h as in the above snippet. See the code below:
+'''Spending using the key path''' A Taproot output can be spent with the secret key corresponding to the internal_pubkey. To do so, a witness stack consists of a single element: a [[bip-0340.mediawiki|BIP340]] signature on the signature hash as defined above, with the secret key tweaked by the same h as in the above snippet. See the code below:
 
 
 def taproot_sign_key(script_tree, internal_seckey, hash_type):
@@ -302,7 +302,7 @@ Non-upgraded nodes, however, will consider all SegWit version 1 witness programs
 They are strongly encouraged to upgrade in order to fully validate the new programs.
 
 Non-upgraded wallets can receive and send bitcoin from non-upgraded and upgraded wallets using SegWit version 0 programs, traditional pay-to-pubkey-hash, etc.
-Depending on the implementation non-upgraded wallets may be able to send to Segwit version 1 programs if they support sending to [https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki BIP173] Bech32 addresses.
+Depending on the implementation non-upgraded wallets may be able to send to Segwit version 1 programs if they support sending to [[bip-0173.mediawiki|BIP173]] Bech32 addresses.
 
 == Acknowledgements ==
 
diff --git a/bip-0342.mediawiki b/bip-0342.mediawiki
index ac8f4aa..3da9904 100644
--- a/bip-0342.mediawiki
+++ b/bip-0342.mediawiki
@@ -19,7 +19,7 @@
 
 ===Abstract===
 
-This document specifies the semantics of the initial scripting system under [bip-0341.mediawiki BIP341].
+This document specifies the semantics of the initial scripting system under [[bip-0341.mediawiki|BIP341]].
 
 ===Copyright===
 
@@ -27,14 +27,14 @@ This document is licensed under the 3-clause BSD license.
 
 ===Motivation===
 
-[bip-0341.mediawiki BIP341] proposes improvements to just the script structure, but some of its goals are incompatible with the semantics of certain opcodes within the scripting language itself.
-While it is possible to deal with these in separate optional improvements, their impact is not guaranteed unless they are addressed simultaneously with [bip-0341.mediawiki BIP341] itself.
+[[bip-0341.mediawiki|BIP341]] proposes improvements to just the script structure, but some of its goals are incompatible with the semantics of certain opcodes within the scripting language itself.
+While it is possible to deal with these in separate optional improvements, their impact is not guaranteed unless they are addressed simultaneously with [[bip-0341.mediawiki|BIP341]] itself.
 
 Specifically, the goal is making '''Schnorr signatures''', '''batch validation''', and '''signature hash''' improvements available to spends that use the script system as well.
 
 ==Design==
 
-In order to achieve these goals, signature opcodes OP_CHECKSIG and OP_CHECKSIGVERIFY are modified to verify Schnorr signatures as specified in [bip-0340.mediawiki BIP340] and to use a signature message algorithm based on the common message calculation in [bip-0341.mediawiki BIP341].
+In order to achieve these goals, signature opcodes OP_CHECKSIG and OP_CHECKSIGVERIFY are modified to verify Schnorr signatures as specified in [[bip-0340.mediawiki|BIP340]] and to use a signature message algorithm based on the common message calculation in [[bip-0341.mediawiki|BIP341]].
 The tapscript signature message also simplifies OP_CODESEPARATOR handling and makes it more efficient.
 
 The inefficient OP_CHECKMULTISIG and OP_CHECKMULTISIGVERIFY opcodes are disabled.
@@ -48,9 +48,9 @@ Additionally, the new tapscript OP_SUCCESS opcodes allow introducin
 ==Specification==
 
 The rules below only apply when validating a transaction input for which all of the conditions below are true:
-* The transaction input is a '''segregated witness spend''' (i.e., the scriptPubKey contains a witness program as defined in [bip-0141.mediawiki BIP141]).
-* It is a '''taproot spend''' as defined in [bip-0341.mediawiki BIP341] (i.e., the witness version is 1, the witness program is 32 bytes, and it is not P2SH wrapped).
-* It is a '''script path spend''' as defined in [bip-0341.mediawiki BIP341] (i.e., after removing the optional annex from the witness stack, two or more stack elements remain).
+* The transaction input is a '''segregated witness spend''' (i.e., the scriptPubKey contains a witness program as defined in [[bip-0141.mediawiki|BIP141]]).
+* It is a '''taproot spend''' as defined in [[bip-0341.mediawiki#design|BIP341]] (i.e., the witness version is 1, the witness program is 32 bytes, and it is not P2SH wrapped).
+* It is a '''script path spend''' as defined in [[bip-0341.mediawiki#design|BIP341]] (i.e., after removing the optional annex from the witness stack, two or more stack elements remain).
 * The leaf version is ''0xc0'' (i.e. the first byte of the last witness element after removing the optional annex is ''0xc0'' or ''0xc1''), marking it as a '''tapscript spend'''.
 
 Validation of such inputs must be equivalent to performing the following steps in the specified order.
@@ -70,11 +70,11 @@ Validation of such inputs must be equivalent to performing the following steps i
 
 ===Script execution===
 
-The execution rules for tapscript are based on those for P2WSH according to BIP141, including the OP_CHECKLOCKTIMEVERIFY and OP_CHECKSEQUENCEVERIFY opcodes defined in [bip-0065.mediawiki BIP65] and [bip-0112.mediawiki BIP112], but with the following modifications:
+The execution rules for tapscript are based on those for P2WSH according to BIP141, including the OP_CHECKLOCKTIMEVERIFY and OP_CHECKSEQUENCEVERIFY opcodes defined in [[bip-0065.mediawiki|BIP65]] and [[bip-0112.mediawiki|BIP112]], but with the following modifications:
 * '''Disabled script opcodes''' The following script opcodes are disabled in tapscript: OP_CHECKMULTISIG and OP_CHECKMULTISIGVERIFY'''Why are OP_CHECKMULTISIG and OP_CHECKMULTISIGVERIFY disabled, and not turned into OP_SUCCESSx?''' This is a precaution to make sure people who accidentally keep using OP_CHECKMULTISIG in Tapscript notice a problem immediately. It also avoids the complication of script disassemblers needing to become context-dependent.. The disabled opcodes behave in the same way as OP_RETURN, by failing and terminating the script immediately when executed, and being ignored when found in unexecuted branch of the script.
 * '''Consensus-enforced MINIMALIF''' The MINIMALIF rules, which are only a standardness rule in P2WSH, are consensus enforced in tapscript. This means that the input argument to the OP_IF and OP_NOTIF opcodes must be either exactly 0 (the empty vector) or exactly 1 (the one-byte vector with value 1)'''Why make MINIMALIF consensus?''' This makes it considerably easier to write non-malleable scripts that take branch information from the stack..
 * '''OP_SUCCESSx opcodes''' As listed above, some opcodes are renamed to OP_SUCCESSx, and make the script unconditionally valid.
-* '''Signature opcodes'''. The OP_CHECKSIG and OP_CHECKSIGVERIFY are modified to operate on Schnorr public keys and signatures (see [bip-0340.mediawiki BIP340]) instead of ECDSA, and a new opcode OP_CHECKSIGADD is added.
+* '''Signature opcodes'''. The OP_CHECKSIG and OP_CHECKSIGVERIFY are modified to operate on Schnorr public keys and signatures (see [[bip-0340.mediawiki|BIP340]]) instead of ECDSA, and a new opcode OP_CHECKSIGADD is added.
 ** The opcode 186 (0xba) is named as OP_CHECKSIGADD. '''OP_CHECKSIGADD''' This opcode is added to compensate for the loss of OP_CHECKMULTISIG-like opcodes, which are incompatible with batch verification. OP_CHECKSIGADD is functionally equivalent to OP_ROT OP_SWAP OP_CHECKSIG OP_ADD, but only takes 1 byte. All CScriptNum-related behaviours of OP_ADD are also applicable to OP_CHECKSIGADD.'''Alternatives to CHECKMULTISIG''' There are multiple ways of implementing a threshold ''k''-of-''n'' policy using Taproot and Tapscript:
 * '''Using a single OP_CHECKSIGADD-based script''' A CHECKMULTISIG script m  ...  n CHECKMULTISIG with witness 0  ...  can be rewritten as script  CHECKSIG ...  CHECKSIGADD m NUMEQUAL with witness  ... . Every witness element w_i is either a signature corresponding to pubkey_i or an empty vector. A similar CHECKMULTISIGVERIFY script can be translated to BIP342 by replacing NUMEQUAL with NUMEQUALVERIFY. This approach has very similar characteristics to the existing OP_CHECKMULTISIG-based scripts.
 * '''Using a ''k''-of-''k'' script for every combination''' A ''k''-of-''n'' policy can be implemented by splitting the script into several leaves of the Merkle tree, each implementing a ''k''-of-''k'' policy using  CHECKSIGVERIFY ...  CHECKSIGVERIFY  CHECKSIG. This may be preferable for privacy reasons over the previous approach, as it only exposes the participating public keys, but it is only more cost effective for small values of ''k'' (1-of-''n'' for any ''n'', 2-of-''n'' for ''n ≥ 6'', 3-of-''n'' for ''n ≥ 9'', ...). Furthermore, the signatures here commit to the branch used, which means signers need to be aware of which other signers will be participating, or produce signatures for each of the tree leaves.
@@ -108,10 +108,10 @@ The following rules apply to OP_CHECKSIG, OP_CHECKSIGVERIFYOP_CODESEPARATOR before the currently executed signature opcode, with the value in little endian (or ''0xffffffff'' if none executed). The first opcode in a script has a position of 0. A multi-byte push opcode is counted as one opcode, regardless of the size of data being pushed.
-* If the ''sig'' is 64 bytes long, return ''Verify(p, hashTapSigHash(0x00 || SigMsg(0x00, 1) || ext), sig)'', where ''Verify'' is defined in [bip-0340.mediawiki BIP340].
+* If the ''sig'' is 64 bytes long, return ''Verify(p, hashTapSigHash(0x00 || SigMsg(0x00, 1) || ext), sig)'', where ''Verify'' is defined in [[bip-0340.mediawiki#design|BIP340]].
 * If the ''sig'' is 65 bytes long, return ''sig[64] ≠ 0x00 and Verify(p, hashTapSighash(0x00 || SigMsg(sig[64], 1) || ext), sig[0:64])''.
 * Otherwise, fail.
 
-- 
cgit v1.2.3