Bitcoin Forum

Bitcoin => Bitcoin Technical Support => Topic started by: BlackHatCoiner on November 29, 2020, 11:40:04 AM



Title: C# - From hexadecimal to mnemonic?
Post by: BlackHatCoiner on November 29, 2020, 11:40:04 AM
I've read how an mnemonic works. Basically the program takes parts of the hex that represent a number between 0 and 2047 and it prints words from a txt file that correspond to the analogous numbers of their file line. I've also seen that there are many libraries in which you can create mnemonics with just a command.

On C#'s NBitcoin (https://github.com/NicolasDorier/NBitcoin) for example you can with
Code:
Mnemonic mnemo = new Mnemonic(Wordlist.English, WordCount.Twelve);

What I want to do is converting a hex (128-bit or 256-bit) into mnemonic. I have found ways to do that, but only from other programming languages' libraries. I want to do it on C# and because I'm a little afraid of implementing this (https://learnmeabitcoin.com/technical/mnemonic) into code for the first time, I would like to know if there is already a simple way to do that.


Title: Re: C# - From hexadecimal to mnemonic?
Post by: Coding Enthusiast on November 29, 2020, 01:53:59 PM
The conversion is pretty simple and straight forward. As you already know you treat the entropy (your hex) as an octet string and have to select 11 bits at a time. It appears that NBitcoin uses .net's BitArray class which I find very inefficient way of working with bits so I simply put the bits with the padding in a uint[] and then select the bits from there. You can see it here (https://github.com/Autarkysoft/Denovo/blob/504a52217405135de41a14293ef0c6223861f9ed/Src/Autarkysoft.Bitcoin/ImprovementProposals/BIP0039.cs#L218-L295) with sufficient comments.

What you want can be achieved from the following single line method:
Code:
using Autarkysoft.Bitcoin.Encoders;
using Autarkysoft.Bitcoin.ImprovementProposals;

public BIP0039 GetBip39FromHex(string hex) => new BIP0039(Base16.Decode(hex));


Title: Re: C# - From hexadecimal to mnemonic?
Post by: BlackHatCoiner on November 29, 2020, 01:59:13 PM
I guess that Autarkysoft.Bitcoin is one of your projects. Unfortunately, it seems that I can't install it. (Visual studio 2017 on windows 10)

Quote
Attempting to gather dependency information for package 'Autarkysoft.Bitcoin.0.6.1' with respect to project 'Mnemonic keys', targeting '.NETFramework,Version=v4.6.1'
Gathering dependency information took 20.43 ms
Attempting to resolve dependencies for package 'Autarkysoft.Bitcoin.0.6.1' with DependencyBehavior 'Lowest'
Resolving dependency information took 0 ms
Resolving actions to install package 'Autarkysoft.Bitcoin.0.6.1'
Resolved actions to install package 'Autarkysoft.Bitcoin.0.6.1'
Retrieving package 'Autarkysoft.Bitcoin 0.6.1' from 'nuget.org'.
Install failed. Rolling back...
Package 'Autarkysoft.Bitcoin.0.6.1' does not exist in project 'Mnemonic keys'
Package 'Autarkysoft.Bitcoin.0.6.1' does not exist in folder 'C:\Users\bymet\source\repos\Mnemonic keys\packages'
Executing nuget actions took 707.17 ms
Could not install package 'Autarkysoft.Bitcoin 0.6.1'. You are trying to install this package into a project that targets '.NETFramework,Version=v4.6.1', but the package does not contain any assembly references or content files that are compatible with that framework. For more information, contact the package author.
Time Elapsed: 00:00:00.8753458
========== Finished ==========


Title: Re: C# - From hexadecimal to mnemonic?
Post by: Coding Enthusiast on November 29, 2020, 02:25:54 PM
I guess that Autarkysoft.Bitcoin is one of your projects.
Yes it is, you can find it in my signature too. Keep in mind that the library is in beta and you can find my versioning convention here (https://github.com/Autarkysoft/Conventions/blob/master/Versioning.md#0100--version--1000)

Quote
Unfortunately, it seems that I can't install it. (Visual studio 2017 on windows 10)
This is a known bug with old visual studio, it will be fixed if you upgrade to VS2019. Until then check out this SE reply (https://stackoverflow.com/a/57884216/10401748) which should help.


Title: Re: C# - From hexadecimal to mnemonic?
Post by: BlackHatCoiner on November 29, 2020, 03:14:56 PM
I just installed VS2019 and got a similar error:
Quote
Could not install package 'Autarkysoft.Bitcoin 0.6.1'. You are trying to install this package into a project that targets '.NETFramework,Version=v4.7.2', but the package does not contain any assembly references or content files that are compatible with that framework. For more information, contact the package author.            


Title: Re: C# - From hexadecimal to mnemonic?
Post by: Coding Enthusiast on November 29, 2020, 03:39:40 PM
That error is because .net standard 2.1 (the library's target framework) is not compatible with the very old .net framework 4.7.2, you should upgrade to .net core 3.0+ (3.1 is LTS). See this table on MSDN (https://docs.microsoft.com/en-us/dotnet/standard/net-standard).


Title: Re: C# - From hexadecimal to mnemonic?
Post by: BlackHatCoiner on November 29, 2020, 04:07:54 PM
That error is because .net standard 2.1 (the library's target framework) is not compatible with the very old .net framework 4.7.2, you should upgrade to .net core 3.0+ (3.1 is LTS). See this table on MSDN (https://docs.microsoft.com/en-us/dotnet/standard/net-standard).
I upgraded to 3, then I tried to install your library, same error. I upgraded to 5, then I tried to install your library, same error again. I cleared the nuget cache as this guy says here (https://stackoverflow.com/questions/34991703/nuget-package-installation-failure/37178144), still nothing. I wonder what's the fault.

Should I download .net framework 4.8 (https://dotnet.microsoft.com/download/dotnet-framework/net48)?


Title: Re: C# - From hexadecimal to mnemonic?
Post by: Coding Enthusiast on November 29, 2020, 04:40:22 PM
I upgraded to 3, then I tried to install your library, same error.
If you get the "same error" saying "...into a project that targets '.NETFramework,Version=v4.7.2',..." it means you have not changed your target framework. Go to your project properties (select the project from solution explorer then from menu Project > {project name} properties) then in Application tab you should see a Target framework combobox where you can select the available frameworks. You can also manually modify your .csproj file if you are familiar with it, I'm already using the package in another project of mine targeting netcoreapp3.1 like this:
https://github.com/Coding-Enthusiast/FinderOuter/blob/b35b843987541dac24f8577342d287fd49f9dad7/Src/FinderOuter/FinderOuter.csproj#L58

Should I download .net framework 4.8 (https://dotnet.microsoft.com/download/dotnet-framework/net48)?
No version of .net framework would work, they are kind of obsolete. There are certain improvements that were added to .net core and are present only in .net standard 2.1 which I'm taking advantage of in the library, so you have to target .net core 3.0+.


Title: Re: C# - From hexadecimal to mnemonic?
Post by: BlackHatCoiner on November 29, 2020, 05:53:29 PM
If you get the "same error" saying "...into a project that targets '.NETFramework,Version=v4.7.2',..." it means you have not changed your target framework. Go to your project properties (select the project from solution explorer then from menu Project > {project name} properties) then in Application tab you should see a Target framework combobox where you can select the available frameworks.
And choose what framework? I was on 4.7.2, it has 2.0, 3.0 etc. I changed it to 3.0, then tried to install, same error.


Title: Re: C# - From hexadecimal to mnemonic?
Post by: Coding Enthusiast on November 29, 2020, 06:53:45 PM
And choose what framework? I was on 4.7.2, it has 2.0, 3.0 etc. I changed it to 3.0, then tried to install, same error.
Are you sure you set it to .net core 3.0 and not .net framework 3.0?
Try creating a new project like this:
https://i.imgur.com/U4hkEHX.jpg


Title: Re: C# - From hexadecimal to mnemonic?
Post by: BlackHatCoiner on November 29, 2020, 07:02:18 PM
There is no core 3.0:

https://i.imgur.com/QFmPDE1.png

Edit: It's a windows forms app, not a console app.


Title: Re: C# - From hexadecimal to mnemonic?
Post by: Coding Enthusiast on November 29, 2020, 07:40:54 PM
Edit: It's a windows forms app, not a console app.
You should be able to migrate the app to .net 5: https://docs.microsoft.com/en-us/dotnet/desktop/winforms/migration/?view=netdesktop-5.0

If this is a new project and if you are new to c# and .net I strongly suggest getting more familiar with XAML instead of winforms. The later is windows only and is old and limited while the former is a lot better and there are UI projects such as Avalonia that run on any OS.
If you want to try things out then using a console app is the easiest way to go, otherwise if you want UI install Avalonia (https://avaloniaui.net/docs/quickstart/create-new-project) and start from there. There is also WPF which is windows only but is ported to .net core and .net too.


Title: Re: C# - From hexadecimal to mnemonic?
Post by: BlackHatCoiner on November 29, 2020, 08:03:50 PM
If this is a new project and if you are new to c#
I am a beginner on C# and excited about that. I can imagine that any expert on C# can create brilliant programs on Visual Studio. Unfortunately, as far as I've seen in the internet, everything looks complicated. I try to learn, but only amateurly on my free time. I've looked on your projects and you've done some great work, especially FinderOuter. Do you have any e-books to suggest me that you believe are perfect for a beginner?

To clear up, once I say amateurly I mean that I don't have an important knowledge. If I ever have a query like how to insert a button that opens Windows Explorer onclick to choose a file, I'll have to google it. Because I simply don't know how to do it.

I strongly suggest getting more familiar with XAML instead of winforms.
Too bad that winforms are not a good choice. I had tided over with them. Buttons and other stuff look the same like on every single program on winforms. On WPF it looks more professional, something like photoshop.

If you want to try things out then using a console app is the easiest way to go
To prevent any misunderstandings, console app means that it is only available on cmd? It means that it has no UI?



Title: Re: C# - From hexadecimal to mnemonic?
Post by: A-Bolt on November 29, 2020, 08:06:47 PM
What I want to do is converting a hex (128-bit or 256-bit) into mnemonic.

NBitcoin again:
Code:
Byte[] entropy = { 0xfe, 0x5e, 0xa5, 0x18, 0xfb, 0x51, 0x53, 0xd7, 
                    0x34, 0x75, 0x54, 0x52, 0x5c, 0xba, 0xc7, 0x15 }; // 128-bit entropy
            
Mnemonic mnemo = new Mnemonic(Wordlist.English, entropy);
Console.WriteLine(mnemo.ToString());


Title: Re: C# - From hexadecimal to mnemonic?
Post by: Coding Enthusiast on November 29, 2020, 09:24:20 PM
Do you have any e-books to suggest me that you believe are perfect for a beginner?
I prefer videos myself, there is a free course by Microsoft here: https://channel9.msdn.com/Series/CSharp-Fundamentals-for-Absolute-Beginners
There are paid ones on Udemy which I hear are good.
For XAML: https://docs.microsoft.com/en-us/dotnet/desktop/wpf/fundamentals/xaml?view=netdesktop-5.0
For MVVM (an architectural pattern that goes well with XAML and C# following the IoC principle): https://www.tutorialspoint.com/mvvm/index.htm
For everything else just Google or feel free to ask me, I'll answer to the best of my abilities.

Quote
To clear up, once I say amateurly I mean that I don't have an important knowledge. If I ever have a query like how to insert a button that opens Windows Explorer onclick to choose a file, I'll have to google it. Because I simply don't know how to do it.
If you want to become familiar with XAML (the language used in UI) you could start a WPF project and then use the designer to simply draw any item such as a button (like you'd do in MS paint) then look at the XAML code that it generates. It may seem overwhelming at first but eventually you'll just type all of that in a much cleaner and more flexible way.

Quote
To prevent any misunderstandings, console app means that it is only available on cmd? It means that it has no UI?
Yes, it is a text-only interface similar to command line in windows. Technically this is a UI (user interface), but is not a GUI (graphical user interface).


Title: Re: C# - From hexadecimal to mnemonic?
Post by: BlackHatCoiner on December 01, 2020, 07:35:09 AM
I would like to ask one last thing related to the thread's title. As @A-Bolt posted, NBitcoin has a simple way on converting entropy to mnemonic. Is there any simple way to go backwards? From mnemonic to hexadecimal? I think that this, along with finding a way to encrypt messages with ECC on c#, are the only things that have remained to finish my work.


Title: Re: C# - From hexadecimal to mnemonic?
Post by: Coding Enthusiast on December 01, 2020, 08:32:16 AM
Is there any simple way to go backwards? From mnemonic to hexadecimal?
Take index of each word (an integer), convert it to binary, drop the highest bits and only keep the first 11, repeat this for each word and concatenate the bits to each other. Assume 1, 2 and 3 are the bits (0 or 1) of first, second and third word respectively:
Code:
11111111 11122222 22222233 33333333 3...
https://github.com/Autarkysoft/Denovo/blob/c5e741f76aa9318fc853b75f7a5270effebcc4ba/Src/Autarkysoft.Bitcoin/ImprovementProposals/BIP0039.cs#L121-L167

Quote
I think that this, along with finding a way to encrypt messages with ECC on c#, are the only things that have remained to finish my work.
I could implement ECIES if you are stuck.


Title: Re: C# - From hexadecimal to mnemonic?
Post by: BlackHatCoiner on December 01, 2020, 08:56:41 AM
Take index of each word (an integer), convert it to binary, drop the highest bits and only keep the first 11, repeat this for each word and concatenate the bits to each other. Assume 1, 2 and 3 are the bits (0 or 1) of first, second and third word respectively:
Code:
11111111 11122222 22222233 33333333 3...
https://github.com/Autarkysoft/Denovo/blob/c5e741f76aa9318fc853b75f7a5270effebcc4ba/Src/Autarkysoft.Bitcoin/ImprovementProposals/BIP0039.cs#L121-L167
I didn't fully understand this. Do you have a function that does that in your library? Because it seems that the link you gave me doesn't do that. (Tbh, I don't understand what exactly public BIP0039 does)

I could implement ECIES if you are stuck.
I'm really stuck on that! I don't know how to do it and yes I would like you to give me some code or a link to your library. I had started this thread (https://bitcointalk.org/index.php?topic=5295107.msg55720508#msg55720508) asking how to implement it, but didn't understand. Fortunately, I achieved the signing/verifying part, which I was searching too.


Title: Re: C# - From hexadecimal to mnemonic?
Post by: Coding Enthusiast on December 01, 2020, 09:28:58 AM
I didn't fully understand this. Do you have a function that does that in your library? Because it seems that the link you gave me doesn't do that. (Tbh, I don't understand what exactly public BIP0039 does)
This constructor instantiates BIP-39 (and 32) from a given mnemonic string, it first validates the string which requires converting the words to the entropy, computing its checksum and comparing it with the given checksum. The part of the code I posted is what you want (from mnemonic to entropy which can be converted to hex).
There is no public method for this since this not needed in any real world scenario, however you can copy the code and add a final line at the end using the ToBase16() (https://github.com/Autarkysoft/Denovo/blob/c5e741f76aa9318fc853b75f7a5270effebcc4ba/Src/Autarkysoft.Bitcoin/ExtentionsAndHelpers.cs#L254) extension on the entropy like string hex = entropy.ToBase16();

Quote
I'm really stuck on that! I don't know how to do it and yes I would like you to give me some code or a link to your library. I had started this thread (https://bitcointalk.org/index.php?topic=5295107.msg55720508#msg55720508) asking how to implement it, but didn't understand. Fortunately, I achieved the signing/verifying part, which I was searching too.
There is no code for it yet, I'll have to read how it works and then implement it.


Title: Re: C# - From hexadecimal to mnemonic?
Post by: BlackHatCoiner on December 01, 2020, 11:56:47 AM
This constructor instantiates BIP-39 (and 32) from a given mnemonic string, it first validates the string which requires converting the words to the entropy, computing its checksum and comparing it with the given checksum. The part of the code I posted is what you want (from mnemonic to entropy which can be converted to hex).
Yes but as far as I can see, within that part of the code there are variables already set outside of it. (for example ENT or wordIndexes). What am I supposed to put there? Copy the entire code?

There is no code for it yet, I'll have to read how it works and then implement it.
The whole encryption/decryption thing is based on pretty complicated maths, so if it's difficult to understand it imagine how difficult it would be for me to implement it on C#. A big thank you for giving a guiding hand to a C# beginner and cryptography enthusiast here. Your merits talk.


Title: Re: C# - From hexadecimal to mnemonic?
Post by: Coding Enthusiast on December 01, 2020, 01:45:50 PM
It's done: https://github.com/Autarkysoft/Denovo/commit/ddd3a6318a57aef2364f05a5a3e3bde18ada243c
You have to compile the library yourself or wait for the next release (this can take a while since I'm working on P2PNetwork namespace and it is very time consuming).

You encrypt messages using the PublicKey instance:
Code:
bool success = PublicKey.TryRead(Base16.Decode("replace_with_pubkey_hex"), out PublicKey pubkey);
// Make sure success is true
string encrypted = pubkey.Encrypt("replace_with_message");
and decrypt using the PrivateKey instance:
Code:
using PrivateKey key = new PrivateKey("replace_with_private_key_wif");
string decrypted = key.Decrypt(encrypted );
See the accompanying tests for more details.


Title: Re: C# - From hexadecimal to mnemonic?
Post by: BlackHatCoiner on December 01, 2020, 04:10:04 PM
Thank you very much. I guess I just import these csharp files on visual studio and then I perform the functions you gave me on my project's files. As for your library's namespace, I still get the same issue with the framework. I don't see any "core" on Target framework:

https://i.imgur.com/aEza4OE.png


Title: Re: C# - From hexadecimal to mnemonic?
Post by: Coding Enthusiast on December 01, 2020, 05:23:54 PM
That is because in the application window only the easy-to-convert target frameworks are listed, and since converting a project that is already targeting ".net framewoek" to ".net core" is not easy it can not be automated so the list excludes all .net core options.
You have to do it manually with some additional steps, I've already posted the migration link here, but the easier and better solution is to first decide what type of application* you want to make then create a new project of that type while selecting .net core as your target from the start. Then copy the code from this project over there, it doesn't seem to be that big.

* NO GUI -> console app with .net core as its target can run on any OS
* GUI -> Winforms or WPF both limited to Windows but can target .net core but still run on Windows only
* GUI -> other multi platform open source GUI such as Avalonia that I told you about, can target .net core and run on any OS


Title: Re: C# - From hexadecimal to mnemonic?
Post by: BlackHatCoiner on December 01, 2020, 05:35:43 PM
But even if I try to create a new project I still don't see any .net cores on my available frameworks:

https://i.imgur.com/7LoY2U8.png

I firstly want to end this project, with WinForms, and then I'll check the Avalonia thing you mentioned.


Title: Re: C# - From hexadecimal to mnemonic?
Post by: BlackHatCoiner on December 03, 2020, 10:32:18 AM
Fortunately, after a lot of searching, I successfully installed the Autarkysoft package on my project after following the instructions you sent me here (https://docs.microsoft.com/en-us/dotnet/desktop/winforms/migration/?view=netdesktop-5.0). As I said, I want to convert mnemonic to hexadecimal and I have some queries about your BIP0039.cs (https://github.com/Autarkysoft/Denovo/blob/c5e741f76aa9318fc853b75f7a5270effebcc4ba/Src/Autarkysoft.Bitcoin/ImprovementProposals/BIP0039.cs#L121-L167). Do I simply import it on my project? What's next? What will I have to write on my main csharp file to run that backwards (mnemonic->hex) function?


Title: Re: C# - From hexadecimal to mnemonic?
Post by: Coding Enthusiast on December 03, 2020, 04:18:03 PM
What's next? What will I have to write on my main csharp file to run that backwards (mnemonic->hex) function?
I don't really get what you're trying to make but based on your other topic (public key to mnemonic) I assume you don't want the checksum validation and you want to enter a mnemonic and get the 264 bit entropy out. With that assumption the code would be this:
Code:
using Autarkysoft.Bitcoin;
using Autarkysoft.Bitcoin.Encoders;
using Autarkysoft.Bitcoin.ImprovementProposals;
using System;
using System.Linq;
using System.Text;
Code:
public string MnToHex(string mnemonic, BIP0039.WordLists wl = BIP0039.WordLists.English)
{
    if (string.IsNullOrWhiteSpace(mnemonic))
        throw new ArgumentNullException(nameof(mnemonic), "Seed can not be null or empty!");
    string[] 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(nameof(mnemonic), "Seed has invalid words.");
    }
    if (!new int[] { 12, 15, 18, 21, 24 }.Contains(words.Length))
    {
        throw new FormatException("Invalid seed length. It should be ∈{12, 15, 18, 21, 24}");
    }

    uint[] wordIndexes = new uint[words.Length];
    for (int i = 0; i < words.Length; i++)
    {
        wordIndexes[i] = (uint)Array.IndexOf(allWords, words[i]);
    }

    int ENTCS = words.Length * 11;
    int CS = ENTCS % 32;
    int ENT = ENTCS - CS;

    byte[] entropy = new byte[(ENT / 8) + 1];

    int itemIndex = 0;
    int bitIndex = 0;
    for (int i = 0; i < entropy.Length - 1; i++)
    {
        if (bitIndex + 8 <= 11)
        {
            entropy[i] = (byte)(wordIndexes[itemIndex] >> (3 - bitIndex));
        }
        else
        {
            entropy[i] = (byte)(((wordIndexes[itemIndex] << (bitIndex - 3)) & 0xff) |
                                    (wordIndexes[itemIndex + 1] >> (14 - bitIndex)));
        }

        bitIndex += 8;
        if (bitIndex >= 11)
        {
            bitIndex -= 11;
            itemIndex++;
        }
    }

    uint mask = (1U << CS) - 1;
    entropy[^1] = (byte)(wordIndexes[itemIndex] & mask);

    return entropy.ToBase16();
}
HexToMn works only with 33 byte entropy (66 char hex):
Code:
public string HexToMn(string hex, BIP0039.WordLists wl = BIP0039.WordLists.English)
{
    byte[] entropy = Base16.Decode(hex);
    if (entropy.Length != 33)
        throw new ArgumentOutOfRangeException();

    byte[] ba = entropy.ConcatFast(new byte[3]);

    uint[] bits = new uint[9];
    for (int i = 0, j = 0; i < ba.Length - 1; i += 4, j++)
    {
        bits[j] = (uint)(ba[i + 3] | (ba[i + 2] << 8) | (ba[i + 1] << 16) | (ba[i] << 24));
    }

    int itemIndex = 0;
    int bitIndex = 0;
    uint[] wordIndexes = new uint[24];
    for (int i = 0; i < 24; i++)
    {
        if (bitIndex + 11 <= 32)
        {
            wordIndexes[i] = (bits[itemIndex] << bitIndex) >> 21;
        }
        else
        {
            wordIndexes[i] = ((bits[itemIndex] << bitIndex) >> 21) |
                                (bits[itemIndex + 1] >> (53 - bitIndex));
        }

        bitIndex += 11;
        if (bitIndex >= 32)
        {
            bitIndex -= 32;
            itemIndex++;
        }
    }

    StringBuilder sb = new StringBuilder(wordIndexes.Length * 8);
    string[] allWords = BIP0039.GetAllWords(wl);
    for (int i = 0; i < wordIndexes.Length; i++)
    {
        sb.Append($"{allWords[wordIndexes[i]]} ");
    }

    sb.Length--;
    return sb.ToString();
}


Title: Re: C# - From hexadecimal to mnemonic?
Post by: BlackHatCoiner on December 04, 2020, 06:44:18 AM
Once I try to convert Hex to mnemonic with HexToMn I get "Word list was not found.". I normally use 33 byte-string (66 chars).

https://i.imgur.com/eSs81z7.png

https://i.imgur.com/eJnQjb5.png

I guess it has to do with:
Code:
string path = $"Autarkysoft.Bitcoin.ImprovementProposals.BIP0039WordLists.{wl}.txt";

Does it read it? Where is the wordlist located?