Yes, you can convert a 33-byte compressed public key into a 65-byte uncompressed public key in Java.
Here is the code to perform the operation. It is correct, robust, and only requires Java SE classes (no other libraries) - but I apologize for the implementation length.
import java.math.BigInteger;
import java.util.Arrays;
static final BigInteger MODULUS =
new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", 16);
static final BigInteger CURVE_A = new BigInteger("0");
static final BigInteger CURVE_B = new BigInteger("7");
// Given a 33-byte compressed public key, this returns a 65-byte uncompressed key.
byte[] decompressPubkey(byte[] compKey) {
// Check array length and type indicator byte
if (compKey.length != 33 || compKey[0] != 2 && compKey[0] != 3)
throw new IllegalArgumentException();
final byte[] xCoordBytes = Arrays.copyOfRange(compKey, 1, compKey.length);
final BigInteger xCoord = new BigInteger(1, xCoordBytes); // Range [0, 2^256)
BigInteger temp = xCoord.pow(2).add(CURVE_A);
temp = sqrtMod(temp.add(CURVE_B));
boolean tempIsOdd = temp.testBit(0);
boolean yShouldBeOdd = compKey[0] == 3;
if (tempIsOdd != yShouldBeOdd)
temp = temp.negate().mod(MODULUS);
final BigInteger yCoord = temp;
// Copy the x coordinate into the new
// uncompressed key, and change the type byte
byte[] result = Arrays.copyOf(compKey, 65);
result[0] = 4;
// Carefully copy the y coordinate into uncompressed key
final byte[] yCoordBytes = yCoord.toByteArray();
for (int i = 0; i < 32 && i < yCoordBytes.length; i++)
result[result.length - 1 - i] = yCoordBytes[yCoordBytes.length - 1 - i];
return result;
}
// Given x, this returns a value y such that y^2 % MODULUS == x.
BigInteger sqrtMod(BigInteger value) {
assert (MODULUS.intValue() & 3) == 3;
BigInteger pow = MODULUS.add(BigInteger.ONE).shiftRight(2);
BigInteger result = value.modPow(pow, MODULUS);
assert result.pow(2).mod(MODULUS).equals(value);
return result;
}
My Bitcoin cryptography library does implement the modulo-prime field arithmetic, but it should add the functionality to decompress public keys as well...
It looks like the algorithm you need is published on bitcointalk. Are you asking whether Java has the same capabilities to convert public keys as Python? – Jestin – 2016-05-09T16:49:21.560
Right! Actually I started doing the code I don't understand how to do the p//4 (floor division) part though since I'm working with biginteger. I also tried doing y=((x^3+7)^1/2)mod p where p = FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE FFFFFC2F but it didn't work either. – prof.Zoom – 2016-05-09T17:17:24.807
If your question is about how to do a specific thing in Java, it might be worthwhile to post the question to StackOverflow. I'm sure there's a few people here who have worked with BigIntegers in Java, but there's certainly more on SO. – Jestin – 2016-05-09T18:08:30.327