mirror of
https://github.com/Qortal/altcoinj.git
synced 2025-02-07 06:44:16 +00:00
Use compressed pubkeys by default. Resolves issue 111.
This commit is contained in:
parent
0bdfa7b635
commit
d268270d7b
@ -45,7 +45,6 @@ import static com.google.common.base.Preconditions.checkArgument;
|
||||
|
||||
// TODO: This class is quite a mess by now. Once users are migrated away from Java serialization for the wallets,
|
||||
// refactor this to have better internal layout and a more consistent API.
|
||||
// TODO: Properly/completely support compressed pubkeys and use them by default.
|
||||
|
||||
/**
|
||||
* Represents an elliptic curve keypair that we own and can use for signing transactions. Currently,
|
||||
@ -58,9 +57,6 @@ public class ECKey implements Serializable {
|
||||
private static final SecureRandom secureRandom;
|
||||
private static final long serialVersionUID = -728224901792295832L;
|
||||
|
||||
/** How many bytes a Bitcoin public key is: 65, that is, two 32 byte co-ordinates plus a one byte header. */
|
||||
public static final int PUBLIC_KEY_LENGTH = 65;
|
||||
|
||||
static {
|
||||
// All clients must agree on the curve to use by agreement. Bitcoin uses secp256k1.
|
||||
X9ECParameters params = SECNamedCurves.getByName("secp256k1");
|
||||
@ -80,7 +76,10 @@ public class ECKey implements Serializable {
|
||||
// Transient because it's calculated on demand.
|
||||
transient private byte[] pubKeyHash;
|
||||
|
||||
/** Generates an entirely new keypair. */
|
||||
/**
|
||||
* Generates an entirely new keypair. Point compression is used so the resulting public key will be 33 bytes
|
||||
* (32 for the co-ordinate and 1 byte to represent the y bit).
|
||||
*/
|
||||
public ECKey() {
|
||||
ECKeyPairGenerator generator = new ECKeyPairGenerator();
|
||||
ECKeyGenerationParameters keygenParams = new ECKeyGenerationParameters(ecParams, secureRandom);
|
||||
@ -89,8 +88,12 @@ public class ECKey implements Serializable {
|
||||
ECPrivateKeyParameters privParams = (ECPrivateKeyParameters) keypair.getPrivate();
|
||||
ECPublicKeyParameters pubParams = (ECPublicKeyParameters) keypair.getPublic();
|
||||
priv = privParams.getD();
|
||||
// The public key is an encoded point on the elliptic curve. It has no meaning independent of the curve.
|
||||
pub = pubParams.getQ().getEncoded();
|
||||
// Unfortunately Bouncy Castle does not let us explicitly change a point to be compressed, even though it
|
||||
// could easily do so. We must re-build it here so the ECPoints withCompression flag can be set to true.
|
||||
ECPoint uncompressed = pubParams.getQ();
|
||||
ECPoint compressed = new ECPoint.Fp(ecParams.getCurve(), uncompressed.getX(), uncompressed.getY(), true);
|
||||
pub = compressed.getEncoded();
|
||||
|
||||
creationTimeSeconds = Utils.now().getTime() / 1000;
|
||||
}
|
||||
|
||||
@ -103,7 +106,7 @@ public class ECKey implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Output this ECKey as an ASN.1 encoded private key, as understood by OpenSSL or used by the BitCoin reference
|
||||
* Output this ECKey as an ASN.1 encoded private key, as understood by OpenSSL or used by the Bitcoin reference
|
||||
* implementation in its wallet storage format.
|
||||
*/
|
||||
public byte[] toASN1() {
|
||||
@ -160,8 +163,8 @@ public class ECKey implements Serializable {
|
||||
|
||||
/**
|
||||
* Creates an ECKey given only the private key bytes. This is the same as using the BigInteger constructor, but
|
||||
* is more convenient if you are importing a key from elsewhere. The public key will be automatically derived
|
||||
* from the private key.
|
||||
* is more convenient if you are importing a key from elsewhere. If not provided the public key will be
|
||||
* automatically derived from the private key.
|
||||
*/
|
||||
public ECKey(byte[] privKeyBytes, byte[] pubKey) {
|
||||
this(privKeyBytes == null ? null : new BigInteger(1, privKeyBytes), pubKey);
|
||||
@ -191,10 +194,10 @@ public class ECKey implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this key is using the compressed form or not. Compressed pubkeys are only 35 bytes, not 64.
|
||||
* Returns whether this key is using the compressed form or not. Compressed pubkeys are only 33 bytes, not 64.
|
||||
*/
|
||||
public boolean isCompressed() {
|
||||
return pub.length == 35;
|
||||
return pub.length == 33;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
@ -480,9 +483,9 @@ public class ECKey implements Serializable {
|
||||
// Q = mi(r) * (sR - eG)
|
||||
//
|
||||
// Where mi(x) is the modular multiplicative inverse. We transform this into the following:
|
||||
// Q = (mi(r) * s * R) + (mi(r) * -e * G)
|
||||
// Where -e is the modular additive inverse of e, that is z such that z + e = 0 (mod n), and + is the EC
|
||||
// group operator.
|
||||
// Q = (mi(r) * s ** R) + (mi(r) * -e ** G)
|
||||
// Where -e is the modular additive inverse of e, that is z such that z + e = 0 (mod n). In the above equation
|
||||
// ** is point multiplication and + is point addition (the EC group operator).
|
||||
//
|
||||
// We can find the additive inverse by subtracting e from zero then taking the mod. For example the additive
|
||||
// inverse of 3 modulo 11 is 8 because 3 + 8 mod 11 = 0, and -3 mod 11 = 8.
|
||||
|
@ -165,8 +165,7 @@ public class ECKeyTest {
|
||||
key = new ECKey(null, key.getPubKey());
|
||||
boolean found = false;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
ECKey key2 = ECKey.recoverFromSignature(i, sig, hash, false);
|
||||
assertNotNull("Key recovery did not work", key2);
|
||||
ECKey key2 = ECKey.recoverFromSignature(i, sig, hash, true);
|
||||
if (key.equals(key2)) {
|
||||
found = true;
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user