I now understand why some of the bip340_test_vectors fail signature verification.

I would like to tweak these test vectors to check that signature verification fails for other test vectors. How do I do this?


Disclaimer: This is an educational exercise. This Python code is for testing and should not be used in production or with mainnet Bitcoin. A private key of 3 is absolutely insecure.

There are two Python files in the BIPs repo reference.py and test_vectors.py which you can view by cloning the BIPs repo.

git clone https://github.com/bitcoin/bips.git

These two files are in /bitcoin/bips/tree/master/bip-0340.

If you run python3 test-vectors.py from within the bip-0340 directory you will get the output and error messages that are in the CSV file test-vectors.csv.

If you open test-vectors.py with your text editor e.g. vim test-vectors.py

you can edit any of the test vectors' secret key (private key), message, auxiliary randomness.

For example vector0 has the secret key 3.

seckey = bytes_from_int(3)

You could change the secret from 3 to 4.

seckey = bytes_from_int(4)

Save and close your text editor and then run python3 test-vectors.py again.

This will generate an AssertionError.

Traceback (most recent call last):
  File "test-vectors.py", line 253, in <module>
  File "test-vectors.py", line 31, in vector0
    assert(not has_square_y(pubkey_point))

There is an assert that checks that for a particular public key (X,Y) (calculated from the secret (private) key) the Y coordinate isn't square. This is a check implemented due to a previous design decision to use squaredness as the tiebreaker for two Y coordinates. The tiebreaker is now evenness rather than squaredness. This test is included to catch when an implementer is mistakenly using squaredness rather than evenness. In this case the public key has a square Y coordinate.

Every private key (scalar) maps to a single corresponding public key (point). In BIP 340 we restrict ourselves to public keys with an even Y coordinate. This could lead to only half of the public keys being valid and hence only half of the private keys being valid too. Instead we say that every private key has a public key and if d.G has an odd Y coordinate we effectively sign with -d (the negated private key) instead.

Negated means taking the complement with the group order n

-m = n-m (mod n)

With that change you could say that every scalar is a valid private key but there are two private keys that map to the same public key. Only one private key maps to a public key with an even Y coordinate though. (Only one BIP 340 private key maps to a BIP 340 public key.)

Remember when you are finished experimenting you can use this to reset:

git reset --hard HEAD

This will discard the changes you have made and go back to the state of the code before you started experimenting.

Thanks to Pieter Wuille on IRC for some additions.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.