Author

Topic: Getting incorrect public key (in Java's bitcoin's public/private key generator) (Read 218 times)

legendary
Activity: 3472
Merit: 10611
FWIW you are also making a couple of mistakes in your code too. for starters you are getting the X and Y coordinate of your public key in hexadecimal format then append 0x04 to its beginning but then convert the result to byte array using UTF8! that is why you are getting 1vrHc... as the uncompressed address instead of 1ARcqBL7EkpqEAu8EcTRHvu2fTUaqCoZR2
i am not familiar with Java but i can tell you that the problem is here, you should figure out how to change the bold part from UTF8 to base16 decode in Java
Quote
String sx = to64(pt.getAffineX().toString(16)).toUpperCase();
String sy = to64(pt.getAffineY().toString(16)).toUpperCase(); // <--toString(16) is converting them to hexadecimal aka base16
String bcPub = "04" + sx + sy;

MessageDigest sha = MessageDigest.getInstance("SHA-256");
byte[] s1 = sha.digest(bcPub.getBytes("UTF-8"));

additionally there is an extremely tiny chance that your to64 function can throw an exception because X and Y don't have to be as big as 32 bytes. technically it can be a smaller number so your hex may have less than 62 characters. also i am not sure about this part but toString(16) is not returning values in Two's complement otherwise you may see 00 in front of some of your numbers.

ps. it is best that you work with bytes instead of hex. it works a lot faster and there is less chance of introducing bugs.
legendary
Activity: 1862
Merit: 1505
I'm pretty sure those are bitcoin addresses, not public key since public key and address uses different format[1]

There are 2 types of public key which are compressed and uncompressed and i think that's the problem/reason you got different bitcoin address from what you expect. But i didn't read the code, so i might be wrong.

Reference :
1. https://en.bitcoin.it/wiki/List_of_address_prefixes

That helped, thanks!
legendary
Activity: 2870
Merit: 7490
Crypto Swap Exchange
I'm pretty sure those are bitcoin addresses, not public key since public key and address uses different format[1]

There are 2 types of public key which are compressed and uncompressed and i think that's the problem/reason you got different bitcoin address from what you expect. But i didn't read the code, so i might be wrong.

Reference :
1. https://en.bitcoin.it/wiki/List_of_address_prefixes
legendary
Activity: 1862
Merit: 1505
EDIT: Got my confusion sorted out, thanks to ETFbitcoin



I'm getting a correct private key, but an incorrect public key, with the following java program:

Quote
import com.google.bitcoin.core.Base58;
import java.io.UnsupportedEncodingException;
import java.security.........

////////////////////////////////////////////////////////////////////////////////////
   
public static String to64(String s) {
    switch(s.length()) {
    case 62: return "00" + s;
    case 63: return "0" + s;
    case 64: return s;
    default:
        throw new IllegalArgumentException("Invalid key: " + s);
        }
}

////////////////////////////////////////////////////////////////////////////////////

public static void main(String[] args) throws NoSuchAlgorithmException, InvalidAlgorithmParameterException, UnsupportedEncodingException, NoSuchProviderException {

Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());

KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC");
ECGenParameterSpec secp = new ECGenParameterSpec("secp256k1");
keyGen.initialize(secp);
KeyPair kp = keyGen.generateKeyPair();
PublicKey pub = kp.getPublic();
PrivateKey pvt = kp.getPrivate();
       
ECPrivateKey epvt = (ECPrivateKey)pvt;
String sepvt = to64(epvt.getS().toString(16)).toUpperCase();
       
ECPublicKey epub = (ECPublicKey)pub;

ECPoint pt = epub.getW();
String sx = to64(pt.getAffineX().toString(16)).toUpperCase();
String sy = to64(pt.getAffineY().toString(16)).toUpperCase();
String bcPub = "04" + sx + sy;

MessageDigest sha = MessageDigest.getInstance("SHA-256");
byte[] s1 = sha.digest(bcPub.getBytes("UTF-8"));

MessageDigest rmd = MessageDigest.getInstance("RipeMD160", "BC");

byte[] r1 = rmd.digest(s1);
byte[] r2 = new byte[r1.length + 1];

r2[0] = 0;

System.arraycopy(r1, 0, r2, 1, r1.length);

byte[] s2 = sha.digest(r2);
byte[] s3 = sha.digest(s2);
byte[] a1 = new byte[25];

System.arraycopy(r2, 0, a1, 0, r2.length);
System.arraycopy(s3, 0, a1, 20, 5);

System.out.println("Public Key: " + Base58.encode(a1));
System.out.println("Private Key: " + sepvt);}}

For example, instead of:



I should get:

Public key: 1BuXQcCU7eQA6z5N5qqNUubjQLk3vrATVk
Private key: 93B16A46CF1D71E79CA28BFFA8499B6F7412BEB1514CC6FE271AED19F3FAF946

Any idea what I'm doing wrong here?
Jump to: