3
0
mirror of https://github.com/Qortal/altcoinj.git synced 2025-02-14 11:15:51 +00:00

Add a method to deserialize a DeterministicKey from a byte-array rather than from the base-58 encoding thereof.

This commit is contained in:
Adam Mackler 2014-06-08 00:49:18 -04:00 committed by Mike Hearn
parent 2a8454a85c
commit 40bc6f4c46
2 changed files with 58 additions and 44 deletions

View File

@ -347,54 +347,58 @@ public class DeterministicKey extends ECKey {
public static DeterministicKey deserializeB58(@Nullable DeterministicKey parent, String base58) {
try {
ByteBuffer buffer = ByteBuffer.wrap(Base58.decodeChecked(base58));
int header = buffer.getInt();
if (header != HEADER_PRIV && header != HEADER_PUB)
throw new IllegalArgumentException("Unknown header bytes: " + base58.substring(0, 4));
boolean pub = header == HEADER_PUB;
byte depth = buffer.get();
byte[] parentFingerprint = new byte[4];
buffer.get(parentFingerprint);
final int i = buffer.getInt();
final ChildNumber childNumber = new ChildNumber(i);
ImmutableList<ChildNumber> path;
if (parent != null) {
if (Arrays.equals(parentFingerprint, HDUtils.longTo4ByteArray(0)))
throw new IllegalArgumentException("Parent was provided but this key doesn't have one");
if (!Arrays.equals(parent.getFingerprint(), parentFingerprint))
throw new IllegalArgumentException("Parent fingerprints don't match");
path = HDUtils.append(parent.getPath(), childNumber);
if (path.size() != depth)
throw new IllegalArgumentException("Depth does not match");
} else {
if (depth == 0) {
path = ImmutableList.of();
} else if (depth == 1) {
// We have been given a key that is not a root key, yet we also don't have any object representing
// the parent. This can happen when deserializing an account key for a watching wallet. In this case,
// we assume that the parent has a path of zero.
path = ImmutableList.of(childNumber);
} else {
throw new IllegalArgumentException("Depth is " + depth + " and no parent key was provided, so we " +
"cannot reconstruct the key path from the provided data.");
}
}
byte[] chainCode = new byte[32];
buffer.get(chainCode);
byte[] data = new byte[33];
buffer.get(data);
checkArgument(!buffer.hasRemaining(), "Found unexpected data in key");
if (pub) {
ECPoint point = ECKey.CURVE.getCurve().decodePoint(data);
return new DeterministicKey(path, chainCode, point, null, parent);
} else {
return new DeterministicKey(path, chainCode, new BigInteger(1, data), parent);
}
return deserialize(parent, Base58.decodeChecked(base58));
} catch (AddressFormatException e) {
throw new IllegalArgumentException(e);
}
}
public static DeterministicKey deserialize(@Nullable DeterministicKey parent, byte[] serializedKey) {
ByteBuffer buffer = ByteBuffer.wrap(serializedKey);
int header = buffer.getInt();
if (header != HEADER_PRIV && header != HEADER_PUB)
throw new IllegalArgumentException("Unknown header bytes: " + toBase58(serializedKey).substring(0, 4));
boolean pub = header == HEADER_PUB;
byte depth = buffer.get();
byte[] parentFingerprint = new byte[4];
buffer.get(parentFingerprint);
final int i = buffer.getInt();
final ChildNumber childNumber = new ChildNumber(i);
ImmutableList<ChildNumber> path;
if (parent != null) {
if (Arrays.equals(parentFingerprint, HDUtils.longTo4ByteArray(0)))
throw new IllegalArgumentException("Parent was provided but this key doesn't have one");
if (!Arrays.equals(parent.getFingerprint(), parentFingerprint))
throw new IllegalArgumentException("Parent fingerprints don't match");
path = HDUtils.append(parent.getPath(), childNumber);
if (path.size() != depth)
throw new IllegalArgumentException("Depth does not match");
} else {
if (depth == 0) {
path = ImmutableList.of();
} else if (depth == 1) {
// We have been given a key that is not a root key, yet we also don't have any object representing
// the parent. This can happen when deserializing an account key for a watching wallet. In this case,
// we assume that the parent has a path of zero.
path = ImmutableList.of(childNumber);
} else {
throw new IllegalArgumentException("Depth is " + depth + " and no parent key was provided, so we " +
"cannot reconstruct the key path from the provided data.");
}
}
byte[] chainCode = new byte[32];
buffer.get(chainCode);
byte[] data = new byte[33];
buffer.get(data);
checkArgument(!buffer.hasRemaining(), "Found unexpected data in key");
if (pub) {
ECPoint point = ECKey.CURVE.getCurve().decodePoint(data);
return new DeterministicKey(path, chainCode, point, null, parent);
} else {
return new DeterministicKey(path, chainCode, new BigInteger(1, data), parent);
}
}
/**
* Verifies equality of all fields but NOT the parent pointer (thus the same key derived in two separate heirarchy
* objects will equal each other.

View File

@ -165,22 +165,32 @@ public class ChildKeyDerivationTest {
}
@Test
public void serializeToText() {
public void serializeToTextAndBytes() {
DeterministicKey key1 = HDKeyDerivation.createMasterPrivateKey("satoshi lives!".getBytes());
DeterministicKey key2 = HDKeyDerivation.deriveChildKey(key1, ChildNumber.ZERO_HARDENED);
{
final String pub58 = key1.serializePubB58();
final String priv58 = key1.serializePrivB58();
final byte[] pub = key1.serializePublic();
final byte[] priv = key1.serializePrivate();
assertEquals("xpub661MyMwAqRbcF7mq7Aejj5xZNzFfgi3ABamE9FedDHVmViSzSxYTgAQGcATDo2J821q7Y9EAagjg5EP3L7uBZk11PxZU3hikL59dexfLkz3", pub58);
assertEquals("xprv9s21ZrQH143K2dhN197jMx1ppxRBHFKJpMqdLsF1ewxncv7quRED8N5nksxphju3W7naj1arF56L5PUEWfuSk8h73Sb2uh7bSwyXNrjzhAZ", priv58);
assertArrayEquals(new byte[]{4, -120, -78, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57, -68, 93, -104, -97, 31, -105, -18, 109, 112, 104, 45, -77, -77, 18, 85, -29, -120, 86, -113, 26, 48, -18, -79, -110, -6, -27, 87, 86, 24, 124, 99, 3, 96, -33, -14, 67, -19, -47, 16, 76, -49, -11, -30, -123, 7, 56, 101, 91, 74, 125, -127, 61, 42, -103, 90, -93, 66, -36, 2, -126, -107, 30, 24, -111}, pub);
assertArrayEquals(new byte[]{4, -120, -83, -28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57, -68, 93, -104, -97, 31, -105, -18, 109, 112, 104, 45, -77, -77, 18, 85, -29, -120, 86, -113, 26, 48, -18, -79, -110, -6, -27, 87, 86, 24, 124, 99, 0, -96, -75, 47, 90, -49, 92, -74, 92, -128, -125, 23, 38, -10, 97, -66, -19, 50, -112, 30, -111, -57, -124, 118, -86, 126, -35, -4, -51, 19, 109, 67, 116}, priv);
assertEquals(DeterministicKey.deserializeB58(null, priv58), key1);
assertEquals(DeterministicKey.deserializeB58(null, pub58).getPubKeyPoint(), key1.getPubKeyPoint());
assertEquals(DeterministicKey.deserialize(null, priv), key1);
assertEquals(DeterministicKey.deserialize(null, pub).getPubKeyPoint(), key1.getPubKeyPoint());
}
{
final String pub58 = key2.serializePubB58();
final String priv58 = key2.serializePrivB58();
final byte[] pub = key2.serializePublic();
final byte[] priv = key2.serializePrivate();
assertEquals(DeterministicKey.deserializeB58(key1, priv58), key2);
assertEquals(DeterministicKey.deserializeB58(key1, pub58).getPubKeyPoint(), key2.getPubKeyPoint());
assertEquals(DeterministicKey.deserialize(key1, priv), key2);
assertEquals(DeterministicKey.deserialize(key1, pub).getPubKeyPoint(), key2.getPubKeyPoint());
}
}