Public-Key
從壓縮形式獲取未壓縮的公鑰
一個類似的問題在 Python 中有一個答案,它連結到 bitcointalk 論壇:
- 如何從 openssl 中的壓縮公鑰中獲取未壓縮的公鑰?
- <https://bitcointalk.org/index.php?topic=644919.msg7205689#msg7205689>
但我想知道如何為相同的轉換編寫 Java 程序?我注意到 Java 使用字節數據類型,我無法理解如何對值進行操作。
是的,您可以在 Java 中將 33 字節的壓縮公鑰轉換為 65 字節的未壓縮公鑰。
這是執行操作的程式碼。它是正確的、健壯的,並且只需要 Java SE 類(不需要其他庫)——但我為實現長度道歉。
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; }
我的比特幣密碼庫確實實現了模素欄位算法,但它還應該添加解壓縮公鑰的功能……