public void DeriveEntropyTest(string xprv, BIP0032Path path, byte[] expected) { using BIP0085 bip85 = new(xprv); byte[] actual = bip85.DeriveEntropy(path); Assert.Equal(expected, actual); }
public void Constructor_FromUIntsTest() { uint[] uints = { 0x80000000, 1, 0x80000000 + 2, 2 }; BIP0032Path path = new BIP0032Path(uints); Assert.Equal(uints, path.Indexes); }
public void ToStringTest(uint[] toUse, string expected) { var path = new BIP0032Path(toUse); string actual = path.ToString(); Assert.Equal(expected, actual); }
public void CreateBip49Test(BIP0032Path.CoinType ct, uint account, bool isChange, string expected) { var path = BIP0032Path.CreateBip49(ct, account, isChange); string actual = path.ToString(); Assert.Equal(expected, actual); }
public void AddTest() { var path = new BIP0032Path(1, 0x12345678, 3); Assert.Equal(new uint[] { 1, 0x12345678, 3 }, path.Indexes); path.Add(5); Assert.Equal(new uint[] { 1, 0x12345678, 3, 5 }, path.Indexes); path.Add(Hard); Assert.Equal(new uint[] { 1, 0x12345678, 3, 5, Hard }, path.Indexes); }
public void GetPrivatePublicKeysTest(byte[] ent, BIP0032Path path, string[] expectedPrvKeys, string[] expectedPubKeys) { using BIP0032 bip32 = new BIP0032(ent); string[] actualPrvKeys = bip32.GetPrivateKeys(path, 3, 0, 5) .Select(x => x.ToWif(true)) .ToArray(); string[] actualPubKeys = bip32.GetPublicKeys(path, 3, 10, 12) .Select(x => Helper.BytesToHex(x.ToByteArray(true))) .ToArray(); Assert.Equal(expectedPrvKeys, actualPrvKeys); Assert.Equal(expectedPubKeys, actualPubKeys); }
public void DeriveEntropy_ExceptionTest() { var bip85 = new BIP0085(Xprv); var badPath = new BIP0032Path(1); var badPath2 = new BIP0032Path("m/1'/0/0'"); Assert.Throws <ArgumentNullException>(() => bip85.DeriveEntropy(null)); Assert.Throws <ArgumentException>(() => bip85.DeriveEntropy(badPath)); Assert.Throws <ArgumentException>(() => bip85.DeriveEntropy(badPath2)); bip85.Dispose(); Assert.Throws <ObjectDisposedException>(() => bip85.DeriveEntropy(new BIP0032Path(uint.MaxValue))); }
private bool TrySetPath(string path) { try { this.path = new BIP0032Path(path); return(true); } catch (Exception ex) { report.Fail($"Invalid path ({ex.Message})."); return(false); } }
/// <summary> /// Initializes a new instance of <see cref="BetterMnemonic"/> using the given arguments. /// </summary> /// <exception cref="ArgumentNullException"/> /// <exception cref="ArgumentOutOfRangeException"/> /// <param name="entropy">Entropy to use</param> /// <param name="path">Child key derivation path</param> /// <param name="creationTime">Creation time as a <see cref="LockTime"/></param> /// <param name="wl">Word list to use</param> /// <param name="passPhrase">Optional passphrase to extend the key</param> public BetterMnemonic(byte[] entropy, BIP0032Path path, LockTime creationTime, BIP0039.WordLists wl = BIP0039.WordLists.English, string passPhrase = null) { if (entropy == null) { throw new ArgumentNullException(nameof(entropy), "Entropy can not be null."); } if (!BIP0039.allowedEntropyLengths.Contains(entropy.Length)) { throw new ArgumentOutOfRangeException(nameof(entropy), "Entropy must be 16 or 20 or 24 or 28 or 32 bytes."); } DerivationPath = path; Locktime = creationTime; allWords = BIP0039.GetAllWords(wl); this.entropy = entropy; SetBip32(passPhrase); }
public void Loop(BIP0032 bip32, uint count) { BIP0032Path[] allPaths = new BIP0032Path[] { new BIP0032Path("m/0"), new BIP0032Path("m/0'"), new BIP0032Path("m/0'/0/"), new BIP0032Path("m/0'/0'"), // BIP-44 xprv/xpub P2PKH new BIP0032Path("m/44'/0'/0'/0"), new BIP0032Path("m/44'/0'/0'"), // BIP-49 yprv/upub P2SH-P2WPKH new BIP0032Path("m/49'/0'/0'/0"), new BIP0032Path("m/49'/0'/0'"), // BIP-84 zprv/zpub P2WPKH new BIP0032Path("m/84'/0'/0'/0"), new BIP0032Path("m/84'/0'/0'/"), new BIP0032Path("m/84'/0'/2147483644'/0"), new BIP0032Path("m/84'/0'/2147483645'/0"), new BIP0032Path("m/84'/0'/2147483646'/0"), new BIP0032Path("m/84'/0'/2147483647'/0"), new BIP0032Path("m/49'/0'/2147483647'/0"), new BIP0032Path("m/44'/0'/2147483647'/0"), new BIP0032Path("m/141'/0'/0'/0"), }; foreach (BIP0032Path path in allPaths) { PrivateKey[] keys = bip32.GetPrivateKeys(path, count); for (int i = 0; i < keys.Length; i++) { if (comparer.Compare(keys[i].ToBytes())) { report.AddMessageSafe($"The correct key path is: {path}/{i}"); report.FoundAnyResult = true; return; } } } report.AddMessageSafe("Could not find any correct paths."); }
/// <summary> /// Initializes a new instance of <see cref="BetterMnemonic"/> using the given arguments. /// </summary> /// <exception cref="ArgumentNullException"/> /// <exception cref="ArgumentOutOfRangeException"/> /// <param name="rng">Random number generator to use</param> /// <param name="entropySize">Entropy size</param> /// <param name="path">Child key derivation path</param> /// <param name="creationTime">Creation time as a <see cref="LockTime"/></param> /// <param name="wl">Word list to use</param> /// <param name="passPhrase">Optional passphrase to extend the key</param> public BetterMnemonic(IRandomNumberGenerator rng, int entropySize, BIP0032Path path, LockTime creationTime, BIP0039.WordLists wl = BIP0039.WordLists.English, string passPhrase = null) { if (rng is null) { throw new ArgumentNullException(nameof(rng), "Random number generator can not be null."); } if (!BIP0039.allowedEntropyLengths.Contains(entropySize)) { throw new ArgumentOutOfRangeException(nameof(entropySize), "Entropy must be 16 or 20 or 24 or 28 or 32 bytes."); } DerivationPath = path; Locktime = creationTime; allWords = BIP0039.GetAllWords(wl); entropy = new byte[entropySize]; rng.GetBytes(entropy); SetBip32(passPhrase); }
public static IEnumerable <object[]> GetPrivateKeyCases() { JArray jarr = Helper.ReadResource <JArray>("BIP0032TestData"); foreach (var item in jarr) { byte[] ent = Helper.HexToBytes(item["Entropy"].ToString()); foreach (var chain in item["Chains"]) { BIP0032Path path = new BIP0032Path(chain["Path"].ToString()); string pr1 = chain["Prv0"].ToString(); string pr2 = chain["Prv5"].ToString(); string pr3 = chain["Prv10"].ToString(); string pu1 = chain["Pub10"].ToString(); string pu2 = chain["Pub22"].ToString(); string pu3 = chain["Pub34"].ToString(); yield return(new object[] { ent, path, new string[] { pr1, pr2, pr3 }, new string[] { pu1, pu2, pu3 } }); } } }
/// <summary> /// Initializes a new instance of <see cref="BetterMnemonic"/> using the given arguments. /// </summary> /// <exception cref="ArgumentException"/> /// <exception cref="ArgumentNullException"/> /// <exception cref="FormatException"/> /// <param name="mnemonic">Mnemonic to use</param> /// <param name="wl">Word list to use</param> /// <param name="passPhrase">Optional passphrase to extend the key</param> public BetterMnemonic(string mnemonic, BIP0039.WordLists wl = BIP0039.WordLists.English, string passPhrase = null) { if (string.IsNullOrWhiteSpace(mnemonic)) { throw new ArgumentNullException(nameof(mnemonic), "Seed can not be null or empty!"); } allWords = BIP0039.GetAllWords(wl); string[] words = mnemonic.Normalize(NormalizationForm.FormKD) .Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); if (!words.All(x => allWords.Contains(x))) { throw new ArgumentException("Seed has invalid words.", nameof(mnemonic)); } uint[] wordIndexes = new uint[words.Length]; for (int i = 0; i < words.Length; i++) { wordIndexes[i] = (uint)Array.IndexOf(allWords, words[i]); } int itemIndex = 0; int bitIndex = 0; byte verDepth = Read(wordIndexes, ref itemIndex, ref bitIndex, 8); int version = verDepth >> 4; int depth = verDepth & 0b00001111; uint[] pathIndexes = new uint[depth]; for (int i = 0; i < pathIndexes.Length; i++) { byte a1 = Read(wordIndexes, ref itemIndex, ref bitIndex, 8); byte a2 = Read(wordIndexes, ref itemIndex, ref bitIndex, 8); byte a3 = Read(wordIndexes, ref itemIndex, ref bitIndex, 8); byte a4 = Read(wordIndexes, ref itemIndex, ref bitIndex, 8); pathIndexes[i] = (uint)(a1 | a2 << 8 | a3 << 16 | a4 << 24); } DerivationPath = new BIP0032Path(pathIndexes); byte entLen = Read(wordIndexes, ref itemIndex, ref bitIndex, 8); entropy = new byte[entLen]; for (int i = 0; i < entropy.Length; i++) { entropy[i] = Read(wordIndexes, ref itemIndex, ref bitIndex, 8); } // Compute and compare checksum: var stream = new FastStream(100); Debug.Assert(version <= 0b00001111); Debug.Assert(depth <= 0b00001111); stream.Write((byte)(version << 4 | depth)); foreach (var item in DerivationPath.Indexes) { stream.Write(item); } stream.WriteWithCompactIntLength(entropy); using Sha256 sha = new Sha256(); byte[] hash = sha.ComputeHash(stream.ToByteArray()); int rem = wordIndexes.Length * 11 - (itemIndex * 11) - bitIndex; int hashIndex = 0; if (rem > 8) { byte cs1 = Read(wordIndexes, ref itemIndex, ref bitIndex, 8); if (hash[hashIndex++] != cs1) { throw new FormatException("Invalid checksum."); } rem -= 8; } byte cs2 = (byte)((wordIndexes[itemIndex] << (bitIndex - 3)) & 0xff); if ((hash[hashIndex] & (0xff << (8 - rem))) != cs2) { throw new FormatException("Invalid checksum."); } SetBip32(passPhrase); }
public void Constructor_FromStringTest(string toUse, uint[] expected) { var path = new BIP0032Path(toUse); Assert.Equal(expected, path.Indexes); }
public void Constructor_FromUInts_NullTest() { BIP0032Path path = new BIP0032Path(); Assert.Empty(path.Indexes); }