Esempio n. 1
0
        public void DeriveEntropyTest(string xprv, BIP0032Path path, byte[] expected)
        {
            using BIP0085 bip85 = new(xprv);
            byte[] actual = bip85.DeriveEntropy(path);

            Assert.Equal(expected, actual);
        }
Esempio n. 2
0
        public void Constructor_FromUIntsTest()
        {
            uint[]      uints = { 0x80000000, 1, 0x80000000 + 2, 2 };
            BIP0032Path path  = new BIP0032Path(uints);

            Assert.Equal(uints, path.Indexes);
        }
Esempio n. 3
0
        public void ToStringTest(uint[] toUse, string expected)
        {
            var    path   = new BIP0032Path(toUse);
            string actual = path.ToString();

            Assert.Equal(expected, actual);
        }
Esempio n. 4
0
        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);
        }
Esempio n. 5
0
        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);
        }
Esempio n. 6
0
        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);
        }
Esempio n. 7
0
        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)));
        }
Esempio n. 8
0
 private bool TrySetPath(string path)
 {
     try
     {
         this.path = new BIP0032Path(path);
         return(true);
     }
     catch (Exception ex)
     {
         report.Fail($"Invalid path ({ex.Message}).");
         return(false);
     }
 }
Esempio n. 9
0
        /// <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);
        }
Esempio n. 10
0
        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.");
        }
Esempio n. 11
0
        /// <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);
        }
Esempio n. 12
0
        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 } });
                }
            }
        }
Esempio n. 13
0
        /// <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);
        }
Esempio n. 14
0
        public void Constructor_FromStringTest(string toUse, uint[] expected)
        {
            var path = new BIP0032Path(toUse);

            Assert.Equal(expected, path.Indexes);
        }
Esempio n. 15
0
        public void Constructor_FromUInts_NullTest()
        {
            BIP0032Path path = new BIP0032Path();

            Assert.Empty(path.Indexes);
        }