deriveChild method

Bip32 deriveChild(
  1. int i
)

Implementation

Bip32 deriveChild(int i) {
  if (!(i is int)) {
    throw ('i must be a number');
  }

  List<int> ib = [];
  ib.add((i >> 24) & 0xff);
  ib.add((i >> 16) & 0xff);
  ib.add((i >> 8) & 0xff);
  ib.add(i & 0xff);
  ib = List<int>.from(ib);

  var usePrivate = (i & 0x80000000) != 0;

  var isPrivate = this.versionBytesNum == this.bip32PrivKey;

  if (usePrivate && ((this.privKey == null) || !isPrivate)) {
    throw ('Cannot do private key derivation without private key');
  }

  Bip32 ret;
  if (this.privKey != null) {
    Uint8List data;

    if (usePrivate) {
      data = Uint8List.fromList([
        ...[0],
        ...this.privKey!.bn!.toBuffer(size: 32),
        ...ib,
      ]);
    } else {
      // data =  List<int>.from([this.pubKey.toBuffer( size: 32 ), ib]);
      data = Uint8List.fromList([
        ...this.pubKey!.toBuffer(),
        ...ib,
      ]);
    }

    var hash =
        Hash.sha512Hmac(Uint8List.fromList(data), this.chainCode!).data;
    // var il = BigIntX.fromBuffer(hash.slice(0, 32), { size: 32 })
    var il = BigIntX.fromBuffer(hash.slice(0, 32));
    var ir = hash.slice(32, 64).asUint8List();

    // ki = IL + kpar (mod n).
    var k = il.add(this.privKey!.bn!).mod(PointWrapper.getN());

    ret = new Bip32();
    ret.chainCode = ir;

    ret.privKey = PrivKey.fromBn(k);
    ret.pubKey = new PubKey().fromPrivKey(ret.privKey!);
  } else {
    var data = Uint8List.fromList([...this.pubKey!.toBuffer(), ...ib]);
    var hash = Hash.sha512Hmac(data, this.chainCode!).data;
    var il = BigIntX.fromBuffer(hash.slice(0, 32));
    var ir = hash.slice(32, 64).asUint8List();

    // Ki = (IL + kpar)*G = IL*G + Kpar
    var ilG = PointWrapper.getG().mul(il);
    // ignore: non_constant_identifier_names
    var Kpar = this.pubKey!.point!;
    // ignore: non_constant_identifier_names
    var Ki = ilG.add(Kpar);
    var newpub = new PubKey();
    newpub.point = Ki;

    ret = new Bip32();
    ret.chainCode = ir;

    ret.pubKey = newpub;
  }

  ret.childIndex = i;
  var pubKeyhash =
      Hash.sha256Ripemd160(this.pubKey!.toBuffer().asUint8List()).data;
  ret.parentFingerPrint = pubKeyhash.slice(0, 4).asUint8List();
  ret.versionBytesNum = this.versionBytesNum;
  ret.depth = this.depth! + 1;
  ret.bip32PrivKey = this.bip32PrivKey;
  ret.bip32PubKey = this.bip32PubKey;

  return ret;
}