public ExtKey GetParentExtKey(ExtPubKey parent) { if(parent == null) throw new ArgumentNullException("parent"); if(Depth == 0) throw new InvalidOperationException("This ExtKey is the root key of the HD tree"); if(IsHardened) throw new InvalidOperationException("This private key is hardened, so you can't get its parent"); var expectedFingerPrint = parent.CalculateChildFingerprint(); if(parent.Depth != this.Depth - 1 || !expectedFingerPrint.SequenceEqual(vchFingerprint)) throw new ArgumentException("The parent ExtPubKey is not the immediate parent of this ExtKey", "parent"); byte[] l = null; byte[] ll = new byte[32]; byte[] lr = new byte[32]; var pubKey = parent.PubKey.ToBytes(); l = Hashes.BIP32Hash(parent.vchChainCode, nChild, pubKey[0], pubKey.SafeSubarray(1)); Array.Copy(l, ll, 32); Array.Copy(l, 32, lr, 0, 32); var ccChild = lr; BigInteger parse256LL = new BigInteger(1, ll); BigInteger N = ECKey.CURVE.N; if(!ccChild.SequenceEqual(vchChainCode)) throw new InvalidOperationException("The derived chain code of the parent is not equal to this child chain code"); var keyBytes = PrivateKey.ToBytes(); var key = new BigInteger(1, keyBytes); BigInteger kPar = key.Add(parse256LL.Negate()).Mod(N); var keyParentBytes = kPar.ToByteArrayUnsigned(); if(keyParentBytes.Length < 32) keyParentBytes = new byte[32 - keyParentBytes.Length].Concat(keyParentBytes).ToArray(); var parentExtKey = new ExtKey { vchChainCode = parent.vchChainCode, nDepth = parent.Depth, vchFingerprint = parent.Fingerprint, nChild = parent.nChild, key = new Key(keyParentBytes) }; return parentExtKey; }
public BigInteger Subtract( BigInteger n) { if (n.sign == 0) return this; if (this.sign == 0) return n.Negate(); if (this.sign != n.sign) return Add(n.Negate()); int compare = CompareNoLeadingZeroes(0, magnitude, 0, n.magnitude); if (compare == 0) return Zero; BigInteger bigun, lilun; if (compare < 0) { bigun = n; lilun = this; } else { bigun = this; lilun = n; } return new BigInteger(this.sign * compare, doSubBigLil(bigun.magnitude, lilun.magnitude), true); }
public BigInteger Add( BigInteger value) { if (this.sign == 0) return value; if (this.sign != value.sign) { if (value.sign == 0) return this; if (value.sign < 0) return Subtract(value.Negate()); return value.Subtract(Negate()); } return AddToMagnitude(value.magnitude); }
public BigInteger ModPow(BigInteger e, BigInteger m) { if (m.sign < 1) throw new ArithmeticException("Modulus must be positive"); if (m.Equals(One)) return Zero; if (e.sign == 0) return One; if (sign == 0) return Zero; bool negExp = e.sign < 0; if (negExp) e = e.Negate(); BigInteger result = this.Mod(m); if (!e.Equals(One)) { if ((m.magnitude[m.magnitude.Length - 1] & 1) == 0) { result = ModPowBarrett(result, e, m); } else { result = ModPowMonty(result, e, m, true); } } if (negExp) result = result.ModInverse(m); return result; }