com.github.DNAProject.crypto.bip32.HdKey Maven / Gradle / Ivy
The newest version!
/*
* Copyright (C) 2018 The DNA Authors
* This file is part of The DNA library.
*
* The DNA is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* The DNA is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with The DNA. If not, see .
*
*/
package com.github.DNAProject.crypto.bip32;
import com.github.DNAProject.common.ErrorCode;
import com.github.DNAProject.sdk.exception.SDKException;
import java.math.BigInteger;
import java.util.Arrays;
import static com.github.DNAProject.crypto.Digest.hash160;
import static com.github.DNAProject.crypto.bip32.Secp256r1SC.pointSerP_gMultiply;
import static io.github.novacrypto.hashing.Sha256.sha256Twice;
public class HdKey {
private final boolean neutered;
private final Network network;
private final byte[] chainCode;
private final byte[] key;
private final Serializer serializer;
private final int parentFingerprint;
private final int childNumber;
private final int depth;
private HdKey(final Builder builder) {
neutered = builder.neutered;
network = builder.network;
key = builder.key;
parentFingerprint = builder.parentFingerprint;
childNumber = builder.childNumber;
chainCode = builder.chainCode;
depth = builder.depth;
serializer = new Serializer.Builder()
.network(builder.network)
.neutered(builder.neutered)
.depth(builder.depth)
.childNumber(builder.childNumber)
.fingerprint(builder.parentFingerprint)
.build();
}
static BigInteger parse256(final byte[] bytes) {
return new BigInteger(1, bytes);
}
static void ser256(final byte[] target, final BigInteger integer) {
if (integer.bitLength() > target.length * 8)
throw new RuntimeException("ser256 failed, cannot fit integer in buffer");
final byte[] modArr = integer.toByteArray();
Arrays.fill(target, (byte) 0);
copyTail(modArr, target);
Arrays.fill(modArr, (byte) 0);
}
private static void copyTail(final byte[] src, final byte[] dest) {
if (src.length < dest.length) {
System.arraycopy(src, 0, dest, dest.length - src.length, src.length);
} else {
System.arraycopy(src, src.length - dest.length, dest, 0, dest.length);
}
}
byte[] serialize() {
return serializer.serialize(key, chainCode);
}
byte[] getPoint() {
return pointSerP_gMultiply(parse256(key));
}
byte[] getKey() {
return key;
}
boolean getNeutered() {
return neutered;
}
int getParentFingerprint() {
return parentFingerprint;
}
int calculateFingerPrint() {
final byte[] point = getPublicBuffer();
final byte[] o = hash160(point);
return ((o[0] & 0xFF) << 24) |
((o[1] & 0xFF) << 16) |
((o[2] & 0xFF) << 8) |
(o[3] & 0xFF);
}
static void confirmHdKeyChecksum(final byte[] extendedKeyData) throws SDKException {
final byte[] checkSum = checksum(extendedKeyData);
for (int i = 0; i < 4; i++) {
if (extendedKeyData[78 + i] != checkSum[i])
throw new SDKException(ErrorCode.OtherError("Checksum error"));
}
}
static byte[] checksum(final byte[] privateKey) {
return sha256Twice(privateKey, 0, 78);
}
private byte[] getPublicBuffer() {
return neutered ? key : getPoint();
}
public int depth() {
return depth;
}
Network getNetwork() {
return network;
}
byte[] getChainCode() {
return chainCode;
}
int getChildNumber() {
return childNumber;
}
Builder toBuilder() {
return new Builder()
.neutered(neutered)
.chainCode(chainCode)
.key(key)
.depth(depth)
.childNumber(childNumber)
.parentFingerprint(parentFingerprint);
}
static class Builder {
private Network network;
private boolean neutered;
private byte[] chainCode;
private byte[] key;
private int depth;
private int childNumber;
private int parentFingerprint;
Builder network(final Network network) {
this.network = network;
return this;
}
Builder neutered(final boolean neutered) {
this.neutered = neutered;
return this;
}
Builder key(final byte[] key) {
this.key = key;
return this;
}
Builder chainCode(final byte[] chainCode) {
this.chainCode = chainCode;
return this;
}
Builder depth(final int depth) {
this.depth = depth;
return this;
}
Builder childNumber(final int childNumber) {
this.childNumber = childNumber;
return this;
}
Builder parentFingerprint(final int parentFingerprint) {
this.parentFingerprint = parentFingerprint;
return this;
}
HdKey build() {
return new HdKey(this);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy