1

I've followed this tutorial on generating a Public Private key pair value and generating a valid Bitcoin address.
But one part makes me wonder if the implementation is done correctly which is the following:

ECPublicKey epub = (ECPublicKey) publicKey;
ECPoint pt = epub.getW();
byte[] pubBytes = new byte[33]; //32 + 1
pubBytes[0] = 2; //0x02
System.arraycopy(pt.getAffineX().toByteArray(), 0, pubBytes, 1, 32);

To me it seems like hardcoding the 0x02 could lead to errors when the last byte of the Y coordinate is odd or am I wrong?

If this implementation does prove to be wrong, how could I implement it correctly?

2
  • 1
    In addition to that bug, Java BigInteger.toByteArray() slightly more than half the time won't be 32 bytes as needed here. That looks like a good website to stay very far away from. Dec 15, 2021 at 9:07
  • @dave_thompson_085 I have checked that and for me, toByteArray() has consistently returned 32 bytes. Dec 17, 2021 at 7:07

1 Answer 1

3

You're correct that the first byte should be 0x03 if the y-coordinate of the public key is odd. So indeed, the tutorial is not correct. If the y-coordinate is odd, just set this instead:

pubBytes[0] = 3;

It is worth noting, though, that you can simply negate the private key to achieve an even y-coordinate. This is obvious because if [s]G = Y then [-s]G = -Y. So it isn't really an issue if you did make this mistake and then wanted to fix it later. This was used in BIP-340 to make all public keys 32-bytes instead of 33, by omitting the 0x02/0x03 and always assuming the even y-coordinate.

1
  • thank you for this confirmation I have adapted my code like this pubBytes[0] = pt.getAffineY().mod(new BigInteger("2")).equals(BigInteger.ZERO) ? (byte) 2 : (byte) 3; Dec 17, 2021 at 7:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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