[Ethereum] How to get address from private key in java

accountsaddressesethereumjprivate-key

I use generate a private key in java code HashUtil.sha3("cow".getBytes())

Write to a new private key file:

c85ef7d79691fe79573b1a7064c19c1a9819ebdbd1faaab1a8ec92344438aaf4

Then, I use geth account import, I got an address ["0xcd2a3d9f938e13cd947ec05abc7fe734df8dd826"] in geth.

But when I try to get public address in Java, it shows a different address:

BigInteger pk = new BigInteger(senderPrivKey);
ECKey key = ECKey.fromPrivate(pk);
System.out.println("address\t: " + Hex.toHexString(key.getAddress()) );

The result is address : 8e54de809503da0a87309f8d5e98f77551ddd7f5

I expected the address to show cd2a3d9f938e13cd947ec05abc7fe734df8dd826, did I use wrong code?

I also learned the ECKeyTest.java in EthereumJ, there are unit tests that gets public key from private key first, and then get address from public key. But in my case, the result is still 8e54de809503da0a87309f8d5e98f77551ddd7f5.

Best Answer

Summary

The code in the question theoretically should not run, as the private key is in hex format and the call to new BigInteger(senderPrivKey) to parse the hex string without the 16 radix specified would result in a thrown exception.

When the code is adjusted to use new BigInteger(senderPrivKey, 16) specifying the base 16 radix, the public key is generated as expected.



The Details

Here is a working example. Save it as TestKey.java, compile and run it.

import java.math.BigInteger;

import org.ethereum.crypto.ECKey;
import org.spongycastle.util.encoders.Hex;

public class TestKey {

    public static void main(String[] args) {
        String senderPrivKey = "c85ef7d79691fe79573b1a7064c19c1a9819ebdbd1faaab1a8ec92344438aaf4";

        BigInteger pk = new BigInteger(senderPrivKey, 16);
        System.out.println("Private key: " + pk.toString(16));

        ECKey key = ECKey.fromPrivate(pk);
        System.out.println("Public key: " + Hex.toHexString(key.getAddress()));
    }
}

And the output when running it:

Private key: c85ef7d79691fe79573b1a7064c19c1a9819ebdbd1faaab1a8ec92344438aaf4
Public key: cd2a3d9f938e13cd947ec05abc7fe734df8dd826

I have used the following maven dependency:

    <dependency>
        <groupId>org.ethereum</groupId>
        <artifactId>ethereumj-core</artifactId>
        <version>1.1.0-RELEASE</version>
        <!--  <type>zip</type>  -->
    </dependency>

I don't know how your code ran, because when I change the following line in the source code above to match your code, the BigInteger(...) constructor is expecting to parse a base 10 number rather than a base 16 number :

        BigInteger pk = new BigInteger(senderPrivKey);

And I get the following exception:

Exception in thread "main" java.lang.NumberFormatException: For input string: "c"
    at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
    at java.lang.Integer.parseInt(Integer.java:580)
    at java.math.BigInteger.<init>(BigInteger.java:461)
    at java.math.BigInteger.<init>(BigInteger.java:597)
    at TestKey.main(TestKey.java:14)