Title: MuSig Key Aggregation
  Author:
  Status: Draft
  License: BSD-2-Clause
  Created: 2020-01-19
== Introduction == === Abstract === This document describes MuSig Key Aggregation in libsecp256k1-zkp. === Copyright === This document is licensed under the 2-clause BSD license. === Motivation === == Description == === Design === * The output of the ''KeyAgg'' algorithm depends on the order of the input public keys. * It is possible to sort the public keys with the ''KeySort'' algorithm before key aggregation to ensure the same output, independent of the (initial) order. * The KeyAgg coefficient is computed by hashing the key instead of key index. Otherwise, if the pubkey list gets sorted, the signer needs to translate between key indices pre- and post-sorting. * The second unique key in the pubkey list given to ''KeyAgg'' (as well as any keys identical to this key) gets the constant KeyAgg coefficient 1 which saves an exponentiation (see the MuSig2* appendix in the [https://eprint.iacr.org/2020/1261 MuSig2 paper]). * The public key inputs are serialized using x-only (32 byte) instead of compressed (33 byte) serialization. The reason for this is that as x-only keys are becoming more common, the full key may not be available. === Specification === The following conventions are used, with constants as defined for [https://www.secg.org/sec2-v2.pdf secp256k1]. We note that adapting this specification to other elliptic curves is not straightforward and can result in an insecure schemeAmong other pitfalls, using the specification with a curve whose order is not close to the size of the range of the nonce derivation function is insecure.. * 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 and ''i, j ≥ 0'', 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 ''has_even_y(P)'', where ''P'' is a point for which ''not is_infinite(P)'', returns ''y(P) mod 2 = 0''. ** The function ''cbytes(P)'', where ''P'' is a point, returns ''a || bytes(P)'' where ''a'' is ''2'' if ''has_even_y(P)'' and ''3'' otherwise. ** 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..2256-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_even_y(P)'', or fails if ''x'' is greater than ''p-1'' or no such point exists. The function ''lift_x(x)'' is equivalent to the following pseudocode: *** Fail if ''x > p-1''. *** Let ''c = x3 + 7 mod p''. *** Let ''y' = c(p+1)/4 mod p''. *** Fail if ''c ≠ y'2 mod p''. *** Let ''y = y' '' if ''y' mod 2 = 0'', otherwise let ''y = p - y' ''. *** Return the unique point ''P'' such that ''x(P) = x'' and ''y(P) = y''. ** 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)''. ==== Key Sorting ==== Input: * The number ''u'' of signatures with ''0 < u < 2^32'' * The public keys ''pk1..u'': ''u'' 32-byte arrays The algorithm ''KeySort(pk1..u)'' is defined as: * Return ''pk1..u'' sorted in lexicographical order. ==== Key Aggregation ==== Input: * The number ''u'' of public keys with ''0 < u < 2^32'' * The public keys ''pk1..u'': ''u'' 32-byte arrays The algorithm ''KeyAgg(pk1..u)'' is defined as: * For ''i = 1 .. u'': ** Let ''ai = KeyAggCoeff(pk1..u, pki)''. ** Let ''Pi = lift_x(int(pki))''; fail if it fails. * Let ''Q = a1⋅P1 + a2⋅P1 + ... + au⋅Pu'' * Fail if ''is_infinite(Q)''. * Return ''bytes(Q)''. The algorithm ''HashKeys(pk1..u)'' is defined as: * Return ''hashKeyAgg list(pk1 || pk2 || ... || pku)'' The algorithm ''IsSecond(pk1..u, pk')'' is defined as: * For ''j = 1 .. u'': ** If ''pkj ≠ pk1'': *** Return ''true'' if ''pkj = pk' '', otherwise return ''false''. * Return ''false'' The algorithm ''KeyAggCoeff(pk1..u, pk')'' is defined as: * Let ''L = HashKeys(pk1..u)''. * If ''IsSecond(pk1..u, pk')'': ** Return 1 * Return ''int(hashKeyAgg coefficient(L || pk')) mod n'' == Applications == == Test Vectors and Reference Code == There are some vectors in libsecp256k1's [https://github.com/ElementsProject/secp256k1-zkp/blob/master/src/modules/musig/tests_impl.h MuSig test file]. Search for the ''musig_test_vectors_keyagg'' function. == Footnotes == == Acknowledgements ==