Skip to content

Commit 85d5fda

Browse files
Add BIP32 seed to mnemonic service
1 parent 6e5df09 commit 85d5fda

File tree

1 file changed

+106
-5
lines changed

1 file changed

+106
-5
lines changed

Src/FinderOuter/Services/MnemonicSevice.cs

Lines changed: 106 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
using System.Linq;
1414
using System.Numerics;
1515
using System.Reflection;
16+
using System.Text;
1617
using System.Threading.Tasks;
1718

1819
namespace FinderOuter.Services
@@ -50,6 +51,7 @@ public MnemonicSevice(Report rep) : base(rep)
5051

5152
private int missCount;
5253
private string[] words;
54+
private string passPhrase;
5355

5456

5557
readonly List<IEnumerable<int>> Final = new List<IEnumerable<int>>();
@@ -59,6 +61,60 @@ private void SetResult(IEnumerable<int> item)
5961
}
6062

6163

64+
private unsafe void SetBip32(byte[] mnemonic)
65+
{
66+
HmacSha512 hmac = new HmacSha512(mnemonic);
67+
68+
byte[] salt = Encoding.UTF8.GetBytes($"mnemonic{passPhrase?.Normalize(NormalizationForm.FormKD)}");
69+
byte[] saltForHmac = new byte[salt.Length + 4];
70+
Buffer.BlockCopy(salt, 0, saltForHmac, 0, salt.Length);
71+
72+
byte[] seed = new byte[64];
73+
74+
fixed (byte* saltPt = &saltForHmac[salt.Length])
75+
{
76+
// F()
77+
byte[] resultOfF = new byte[hmac.OutputSize];
78+
79+
// Concatinate i after salt
80+
//saltPt[0] = (byte)(1 >> 24);
81+
//saltPt[1] = (byte)(1 >> 16);
82+
//saltPt[2] = (byte)(1 >> 8);
83+
saltPt[3] = 1;
84+
85+
// compute u1
86+
byte[] u1 = hmac.ComputeHash(saltForHmac);
87+
88+
Buffer.BlockCopy(u1, 0, resultOfF, 0, u1.Length);
89+
90+
// compute u2 to u(c-1) where c is iteration and each u is the hmac of previous u
91+
for (int j = 1; j < 2048; j++)
92+
{
93+
u1 = hmac.ComputeHash(u1);
94+
95+
// result of F() is XOR sum of all u arrays
96+
int len = u1.Length;
97+
fixed (byte* first = resultOfF, second = u1)
98+
{
99+
byte* fp = first;
100+
byte* sp = second;
101+
102+
*(ulong*)fp ^= *(ulong*)sp;
103+
*(ulong*)(fp + 8) ^= *(ulong*)(sp + 8);
104+
*(ulong*)(fp + 16) ^= *(ulong*)(sp + 16);
105+
*(ulong*)(fp + 24) ^= *(ulong*)(sp + 24);
106+
*(ulong*)(fp + 32) ^= *(ulong*)(sp + 32);
107+
*(ulong*)(fp + 40) ^= *(ulong*)(sp + 40);
108+
*(ulong*)(fp + 48) ^= *(ulong*)(sp + 48);
109+
*(ulong*)(fp + 56) ^= *(ulong*)(sp + 56);
110+
}
111+
}
112+
113+
Buffer.BlockCopy(resultOfF, 0, seed, 0, resultOfF.Length);
114+
}
115+
}
116+
117+
62118
private unsafe bool Loop24()
63119
{
64120
var cartesian = CartesianProduct.Create(Enumerable.Repeat(Enumerable.Range(0, 2048), missCount));
@@ -136,7 +192,16 @@ private unsafe bool Loop24()
136192

137193
if ((byte)wrd[23] == hPt[0] >> 24)
138194
{
139-
SetResult(item);
195+
StringBuilder sb = new StringBuilder(24);
196+
for (int i = 0; i < 23; i++)
197+
{
198+
sb.Append($"{allWords[wrd[i]]} ");
199+
}
200+
201+
// no space at the end.
202+
sb.Append($"{allWords[wrd[23]]}");
203+
204+
SetBip32(Encoding.UTF8.GetBytes(sb.ToString()));
140205
}
141206
}
142207
}
@@ -175,7 +240,16 @@ private unsafe bool Loop21()
175240

176241
if ((wrd[20] & 0b111_1111) == hPt[0] >> 25)
177242
{
178-
SetResult(item);
243+
StringBuilder sb = new StringBuilder(21);
244+
for (int i = 0; i < 20; i++)
245+
{
246+
sb.Append($"{allWords[wrd[i]]} ");
247+
}
248+
249+
// no space at the end.
250+
sb.Append($"{allWords[wrd[20]]}");
251+
252+
SetBip32(Encoding.UTF8.GetBytes(sb.ToString()));
179253
}
180254
}
181255
}
@@ -213,7 +287,16 @@ private unsafe bool Loop18()
213287

214288
if ((wrd[17] & 0b11_1111) == hPt[0] >> 26)
215289
{
216-
SetResult(item);
290+
StringBuilder sb = new StringBuilder(18);
291+
for (int i = 0; i < 17; i++)
292+
{
293+
sb.Append($"{allWords[wrd[i]]} ");
294+
}
295+
296+
// no space at the end.
297+
sb.Append($"{allWords[wrd[17]]}");
298+
299+
SetBip32(Encoding.UTF8.GetBytes(sb.ToString()));
217300
}
218301
}
219302
}
@@ -250,7 +333,16 @@ private unsafe bool Loop15()
250333

251334
if ((wrd[14] & 0b1_1111) == hPt[0] >> 27)
252335
{
253-
SetResult(item);
336+
StringBuilder sb = new StringBuilder(15);
337+
for (int i = 0; i < 14; i++)
338+
{
339+
sb.Append($"{allWords[wrd[i]]} ");
340+
}
341+
342+
// no space at the end.
343+
sb.Append($"{allWords[wrd[14]]}");
344+
345+
SetBip32(Encoding.UTF8.GetBytes(sb.ToString()));
254346
}
255347
}
256348
}
@@ -286,7 +378,16 @@ private unsafe bool Loop12()
286378

287379
if ((wrd[11] & 0b1111) == hPt[0] >> 28)
288380
{
289-
SetResult(item);
381+
StringBuilder sb = new StringBuilder(12);
382+
for (int i = 0; i < 11; i++)
383+
{
384+
sb.Append($"{allWords[wrd[i]]} ");
385+
}
386+
387+
// no space at the end.
388+
sb.Append($"{allWords[wrd[11]]}");
389+
390+
SetBip32(Encoding.UTF8.GetBytes(sb.ToString()));
290391
}
291392
}
292393
}

0 commit comments

Comments
 (0)