From f4216927a6daf796e36a53b6d2c8bc2782016d21 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Tue, 24 May 2022 18:41:52 +0000 Subject: [PATCH] Add NonceGen test vectors --- bip-musig2.mediawiki | 1 + bip-musig2/reference.py | 43 +++++++++++++++++++++++++++++++++-------- 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/bip-musig2.mediawiki b/bip-musig2.mediawiki index 11a19f044c..1a240b49d4 100644 --- a/bip-musig2.mediawiki +++ b/bip-musig2.mediawiki @@ -558,6 +558,7 @@ A change in the MAJOR version indicates that the specification is i The MINOR version is incremented whenever the inputs or the output of an algorithm changes in a backward-compatible way or new backward-compatible functionality is added. The PATCH version is incremented for other changes that are noteworthy (bug fixes, test vectors, important clarifications, etc.). +* '''0.3.1''' (2022-05-24): Add ''NonceGen'' test vectors * '''0.3.0''' (2022-05-24): Hash ''i - 1'' instead of ''i'' in ''NonceGen'' * '''0.2.0''' (2022-05-19): Change order of arguments in ''NonceGen'' hash function * '''0.1.0''' (2022-05-19): Publication of draft BIP on the bitcoin-dev mailing list diff --git a/bip-musig2/reference.py b/bip-musig2/reference.py index f6c4e07260..3510368dd2 100644 --- a/bip-musig2/reference.py +++ b/bip-musig2/reference.py @@ -204,14 +204,7 @@ def nonce_hash(rand: bytes, aggpk: bytes, i: int, msg: bytes, extra_in: bytes) - buf += i.to_bytes(1, 'big') return int_from_bytes(tagged_hash('MuSig/nonce', buf)) -def nonce_gen(sk: bytes, aggpk: bytes, msg: bytes, extra_in: bytes) -> Tuple[bytes, bytes]: - if len(sk) not in (0, 32): - raise ValueError('The optional byte array sk must have length 0 or 32.') - if len(aggpk) not in (0, 32): - raise ValueError('The optional byte array aggpk must have length 0 or 32.') - if len(msg) not in (0, 32): - raise ValueError('The optional byte array msg must have length 0 or 32.') - rand_ = secrets.token_bytes(32) +def nonce_gen_internal(rand_: bytes, sk: bytes, aggpk: bytes, msg: bytes, extra_in: bytes) -> Tuple[bytes, bytes]: if len(sk) > 0: rand = bytes_xor(sk, tagged_hash('MuSig/aux', rand_)) else: @@ -229,6 +222,16 @@ def nonce_gen(sk: bytes, aggpk: bytes, msg: bytes, extra_in: bytes) -> Tuple[byt secnonce = bytes_from_int(k_1) + bytes_from_int(k_2) return secnonce, pubnonce +def nonce_gen(sk: bytes, aggpk: bytes, msg: bytes, extra_in: bytes) -> Tuple[bytes, bytes]: + if len(sk) not in (0, 32): + raise ValueError('The optional byte array sk must have length 0 or 32.') + if len(aggpk) not in (0, 32): + raise ValueError('The optional byte array aggpk must have length 0 or 32.') + if len(msg) not in (0, 32): + raise ValueError('The optional byte array msg must have length 0 or 32.') + rand_ = secrets.token_bytes(32) + return nonce_gen_internal(rand_, sk, aggpk, msg, extra_in) + def nonce_agg(pubnonces: List[bytes]) -> bytes: u = len(pubnonces) aggnonce = b'' @@ -352,6 +355,29 @@ def test_key_agg_vectors(): assert key_agg([X[0], X[0], X[0]], [], []) == expected[2] assert key_agg([X[0], X[0], X[1], X[1]], [], []) == expected[3] + +def test_nonce_gen_vectors(): + def fill(i): + return i.to_bytes(1, byteorder='big') * 32 + rand_ = fill(0) + msg = fill(1) + sk = fill(2) + aggpk = fill(3) + extra_in = fill(4) + + expected = fromhex_all([ + '149378B996F012F70C1016C29AE0A9B1D86AAD557CCD29178A24479756205DFD' + + '6285697E57E8578FCFDE6FE7FA4B6CA8E3A5AECAB4FB92F84B7F9DF8DDEF4DB8', + '6613EA4A36A50F34990EAF73612EAA28636ED01325793456C04D8D89DB49372B' + + '54E9DB34D09CBD394DB3FE3CCFFBCA6ED016F3AC877938613095893F54FA70DF', + '7B3B5A002356471AF0E961DE2549C121BD0D48ABCEEDC6E034BDDF86AD3E0A18' + + '7ECEE674CEF7364B0BC4BEEFB8B66CAD89F98DE2F8C5A5EAD5D1D1E4BD7D04CD' + ]) + + assert nonce_gen_internal(rand_, sk, aggpk, msg, extra_in)[0] == expected[0] + assert nonce_gen_internal(rand_, sk, aggpk, b'', extra_in)[0] == expected[1] + assert nonce_gen_internal(rand_, b'', b'', b'', b'')[0] == expected[2] + def test_sign_vectors(): X = fromhex_all([ 'F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9', @@ -495,6 +521,7 @@ def test_sign_and_verify_random(iters): if __name__ == '__main__': test_key_agg_vectors() + test_nonce_gen_vectors() test_sign_vectors() test_tweak_vectors() test_sign_and_verify_random(4)