I read what mcdouglasx said and took it as a challenge for myself. Take a good look at what I did: The ipad_key and opad_key arrays with 128 bytes each to perform HMAC operations. When the mnemonic_length exceeds 128 bytes (24 words), the remainder of the key is not being processed correctly. Therefore, it would be necessary to implement a key normalization process that complies with HMAC. If the key is larger than the block size (128 bytes for SHA-512), it must first be hashed to reduce its size. Then, it should be padded with zeros to reach 128 bytes if needed.
The changes I made to the file int_to_address.cl look like this:
__kernel void int_to_address(ulong mnemonic_start_hi, ulong mnemonic_start_lo, __global uchar * target_mnemonic, __global uchar * found_mnemonic) {
ulong idx = get_global_id(0);
ulong mnemonic_lo = mnemonic_start_lo + idx;
ulong mnemonic_hi = mnemonic_start_hi;
// ... [existing code to construct 'bytes' and 'mnemonic']
// Constructing the mnemonic
uchar mnemonic[180] = {0};
uchar mnemonic_length = 11;
for(int i = 0; i < 12; i++) {
int word_index = indices[i];
int word_length = word_lengths[word_index];
mnemonic_length += word_lengths[word_index];
}
int mnemonic_index = 0;
for (int i = 0; i < 12; i++) {
int word_index = indices[i];
int word_length = word_lengths[word_index];
for(int j = 0; j < word_length; j++) {
mnemonic[mnemonic_index] = words[word_index][j];
mnemonic_index++;
}
mnemonic[mnemonic_index] = 32; // Space
mnemonic_index++;
}
mnemonic[mnemonic_index - 1] = 0; // Null termination
// Key Normalization
uchar normalized_key[128] = {0};
if (mnemonic_length > 128) {
// If the mnemonic is larger than 128 bytes, hash it with SHA-512
sha512(&mnemonic, mnemonic_length, &normalized_key);
// Remaining bytes are already zero-padded (done at initialization)
} else {
// If the mnemonic is less than or equal to 128 bytes, copy it directly
for(int i = 0; i < mnemonic_length; i++) {
normalized_key[i] = mnemonic[i];
}
// Remaining bytes are already zero-padded
}
// Initialization of ipad_key and opad_key
uchar ipad_key[128];
uchar opad_key[128];
for(int x = 0; x < 128; x++) {
ipad_key[x] = 0x36;
opad_key[x] = 0x5c;
}
// Apply XOR with the normalized key
for(int x = 0; x < 128; x++) {
ipad_key[x] ^= normalized_key[x];
opad_key[x] ^= normalized_key[x];
}
// Continue seed derivation process
uchar seed[64] = {0};
uchar sha512_result[64] = {0};
uchar key_previous_concat[256] = {0};
uchar salt[12] = {109, 110, 101, 109, 111, 110, 105, 99, 0, 0, 0, 1};
for(int x = 0; x < 128; x++) {
key_previous_concat[x] = ipad_key[x];
}
for(int x = 0; x < 12; x++) {
key_previous_concat[x + 128] = salt[x];
}
sha512(&key_previous_concat, 140, &sha512_result);
copy_pad_previous(&opad_key, &sha512_result, &key_previous_concat);
sha512(&key_previous_concat, 192, &sha512_result);
xor_seed_with_round(&seed, &sha512_result);
for(int x = 1; x < 2048; x++) {
copy_pad_previous(&ipad_key, &sha512_result, &key_previous_concat);
sha512(&key_previous_concat, 192, &sha512_result);
copy_pad_previous(&opad_key, &sha512_result, &key_previous_concat);
sha512(&key_previous_concat, 192, &sha512_result);
xor_seed_with_round(&seed, &sha512_result);
}
// ... [existing code for key generation and address verification]
if(found_target == 1) {
found_mnemonic[0] = 0x01;
for(int i = 0; i < mnemonic_index; i++) {
target_mnemonic[i] = mnemonic[i];
}
}
}
And in the file just_seed.cl, it turned out like this:
__kernel void just_seed(ulong mnemonic_start_hi, ulong mnemonic_start_lo, __global uchar * target_mnemonic, __global uchar * found_mnemonic) {
ulong idx = get_global_id(0);
ulong seed_start = idx * 64;
ulong mnemonic_lo = mnemonic_start_lo + idx;
ulong mnemonic_hi = mnemonic_start_hi;
// ... [existing code to build 'bytes' and 'mnemonic']
// Mnemonic construction
uchar mnemonic[180];
int mnemonic_index = 0;
for (int i = 0; i < 12; i++) {
int word_index = indices[i];
int word_length = word_lengths[word_index];
for(int j = 0; j < word_length; j++) {
mnemonic[mnemonic_index] = words[word_index][j];
mnemonic_index++;
}
mnemonic[mnemonic_index] = 32; // Space
mnemonic_index++;
}
mnemonic[mnemonic_index - 1] = 0; // Null termination
uchar mnemonic_length = 11 + word_lengths[indices[0]] + word_lengths[indices[1]] + word_lengths[indices[2]] + word_lengths[indices[3]] + word_lengths[indices[4]] + word_lengths[indices[5]] + word_lengths[indices[6]] + word_lengths[indices[7]] + word_lengths[indices[8]] + word_lengths[indices[9]] + word_lengths[indices[10]] + word_lengths[indices[11]];
// Key normalization
uchar normalized_key[128] = {0};
if (mnemonic_length > 128) {
// If the mnemonic is larger than 128 bytes, hash with SHA-512
sha512(&mnemonic, mnemonic_length, &normalized_key);
// Fill remaining bytes with zeros (already done during initialization)
} else {
// If the mnemonic is 128 bytes or less, copy directly
for(int i = 0; i < mnemonic_length; i++) {
normalized_key[i] = mnemonic[i];
}
// Remaining bytes are already filled with zeros
}
// Initialization of ipad_key and opad_key
uchar ipad_key[128];
uchar opad_key[128];
for(int x = 0; x < 128; x++) {
ipad_key[x] = 0x36;
opad_key[x] = 0x5c;
}
// Apply XOR with normalized key
for(int x = 0; x < 128; x++) {
ipad_key[x] ^= normalized_key[x];
opad_key[x] ^= normalized_key[x];
}
// Continue the seed derivation process
uchar seed[64] = { 0 };
uchar sha512_result[64] = { 0 };
uchar key_previous_concat[256] = { 0 };
uchar salt[12] = { 109, 110, 101, 109, 111, 110, 105, 99, 0, 0, 0, 1 };
for(int x = 0; x < 128; x++) {
key_previous_concat[x] = ipad_key[x];
}
for(int x = 0; x < 12; x++) {
key_previous_concat[x + 128] = salt[x];
}
sha512(&key_previous_concat, 140, &sha512_result);
copy_pad_previous(&opad_key, &sha512_result, &key_previous_concat);
sha512(&key_previous_concat, 192, &sha512_result);
xor_seed_with_round(&seed, &sha512_result);
for(int x = 1; x < 2048; x++) {
copy_pad_previous(&ipad_key, &sha512_result, &key_previous_concat);
sha512(&key_previous_concat, 192, &sha512_result);
copy_pad_previous(&opad_key, &sha512_result, &key_previous_concat);
sha512(&key_previous_concat, 192, &sha512_result);
xor_seed_with_round(&seed, &sha512_result);
}
}
This was my work, test it to see if everything is running fine and let me know
I've made a lot of changes to some of the kernel files and the host file, but the problem I’m facing is the incorrect derivation of addresses from the 24 words mnemonics. As you can see, after running the program, you will get two text files: one for the mnemonics and the other for the addresses. The mnemonics are correct, but the addresses are not. I want to correctly derive the BIP49 addresses from the mnemonics and save them into a text file.
https://github.com/johnnstewart/mt-gpu/tree/main