Generating a Bitcoin address in C#

I recently needed to write a C# app to convert a Bitcoin public key to a human usable addresses to send coins to, using the example on https://en.bitcoin.it/wiki/Technical_background_of_Bitcoin_addresses

I hate using external libraries, so my main aim with this was to not require any 3rd party libraries, although you’ll need .Net framework 4.5 for the BigInteger classes.

Please note the full process of generating a valid bitcoin address is defined as:
Private Key > Public Key > Address
This tutorial concentrates on the last step. If you want to generate a Private/Public pair you can use a bitcoin wallet or look into using http://www.bouncycastle.org/csharp/ to create a valid pair within C#.

9 Steps verbose

Here we have all 9 steps as per the technical background document written in C#. Each step is written to the console to show the progress of making the address.

static void Main()
{
    string HexHash = "0450863AD64A87AE8A2FE83C1AF1A8403CB53F53E486D8511DAD8A04887E5B23522CD470243453A299FA9E77237716103ABC11A1DF38855ED6F2EE187E9C582BA6";
    byte [] PubKey = HexToByte(HexHash);
    Console.WriteLine("Public Key:" + ByteToHex(PubKey)); //Step 1
    byte[] PubKeySha = Sha256(PubKey);
    Console.WriteLine("Sha Public Key:" + ByteToHex(PubKeySha)); //Step 2
    byte[] PubKeyShaRIPE = RipeMD160(PubKeySha);
    Console.WriteLine("Ripe Sha Public Key:" + ByteToHex(PubKeyShaRIPE)); // Step 3
    byte[] PreHashWNetwork = AppendBitcoinNetwork(PubKeyShaRIPE, 0); // Step4
    byte[] PublicHash = Sha256(PreHashWNetwork);
    Console.WriteLine("Public Hash:" + ByteToHex(PublicHash)); // Step5
    byte[] PublicHashHash = Sha256(PublicHash);
    Console.WriteLine("Public HashHash:" + ByteToHex(PublicHashHash));  //Step 6
    Console.WriteLine("Checksum:" + ByteToHex(PublicHashHash).Substring(0,4));  //Step 7
    byte[] Address = ConcatAddress(PreHashWNetwork, PublicHashHash);
    Console.WriteLine("Address:" + ByteToHex(Address)); //Step 8
    Console.WriteLine("Human Address:" + Base58Encode(Address));    //Step 9
}

 

Shorthand Function

The entire function can be written in short for live (non debug) use:

public static string CreateAddress(string PublicKey)
{
    byte[] PreHashQ = AppendBitcoinNetwork(RipeMD160(Sha256(HexToByte(PublicKey))), 0);
    return Base58Encode(ConcatAddress(PreHashQ, Sha256(Sha256(PreHashQ))));
}

Additional Functions

I’ve used some helper functions along the way, they are very verbose (Some unnecessary) but it make it a lot easier to read and understand.

HexToByte

Hex to Byte converts the Hexidecimal string to a byte array, it’s simple as taking the 2 characters and converting it into base 256.

public static byte[] HexToByte(string HexString)
{
    if (HexString.Length % 2 != 0)
        throw new Exception("Invalid HEX");
    byte[] retArray = new byte[HexString.Length / 2];
    for (int i = 0; i < retArray.Length; ++i)
    {
        retArray[i] = byte.Parse(HexString.Substring(i*2, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture);
    }

    return retArray;
}

ByteToHex

Byte to hex converts a byte into a hexadecimal string

byte[] data = { 1, 2, 4, 8, 16, 32 };
string hex = BitConverter.ToString(data);

SHA256

Sha256 uses Microsoft’s security cryptography include, and by default takes a byte array (this function is bad in the sense It creates duplicate instances of the sha manager, which we probably shouldn’t do as we could reuse the same instance for the 3 times)

public static byte[] Sha256(byte [] array)
{
    SHA256Managed hashstring = new SHA256Managed();
    return hashstring.ComputeHash(array);
}

RipeMD160

Again this function uses Microsoft’s security cryptography include and is pretty much identical to the Sha256 function.

public static byte[] RipeMD160(byte[] array)
{
    RIPEMD160Managed hashstring = new RIPEMD160Managed();
    return hashstring.ComputeHash(array);
}

Append Bitcoin Network

AppendBitcoinNetwork simply pre-appends a byte onto the beginning of an array of bytes

public static byte[] AppendBitcoinNetwork(byte[] RipeHash, byte Network)
{
    byte[] extended = new byte[RipeHash.Length + 1];
    extended[0] = (byte)Network;
    Array.Copy(RipeHash, 0, extended, 1, RipeHash.Length);
    return extended;
}

Concat Address

Concat address appends the last 4 bytes of the hash onto the end of the RipeMD160 value

public static byte[] ConcatAddress(byte[] RipeHash, byte[] Checksum)
{
    byte[] ret = new byte[RipeHash.Length + 4];
    Array.Copy(RipeHash, ret, RipeHash.Length);
    Array.Copy(Checksum, 0, ret, RipeHash.Length, 4);
    return ret;
}

Base58

I’ve hacked together my own c# Base58 encoder based off the C++ code by Satoshi, notice it uses BigInterger, this is a new Microsoft class in C# that allows math operation on arbitrary big numbers, so we’re no longer limited to a 32 or 64 bit integer, see more here: http://msdn.microsoft.com/en-us/library/system.numerics.biginteger(v=vs.110).aspx

public static string Base58Encode(byte [] array)
{
    const string ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
    string retString = string.Empty;
    BigInteger encodeSize = ALPHABET.Length;
    BigInteger arrayToInt = 0;
    for (int i = 0; i < array.Length; ++i)
    {
        arrayToInt = arrayToInt * 256 + array[i];
    }
    while (arrayToInt > 0)
    {
        int rem = (int)(arrayToInt % encodeSize);
        arrayToInt /= encodeSize;
        retString = ALPHABET[rem] + retString;
    }
    for (int i = 0; i < array.Length && array[i] == 0; ++i)
       retString = ALPHABET[0] + retString;

    return retString;
}

Note: You’ll have to manually add references to the Microsoft.Numerics library to your project to get the BigInteger class.
sysNumerics

Conclusion

Hope this helps anyone looking to write Bitcoin/Litecoin C# applications. Any questions/improvements please leave a comment.
If you found this useful, consider donating here (it really helps!):

Bitcoin: 1Q9mKX164PMLeY7QdGA78oMF4kivQGmmmt
Litecoin: LV7deCYk3DRdq1QNWHaZYv8BzYPs3EqBra

14 Replies to “Generating a Bitcoin address in C#”

    1. The private key is a random number represented as a hex string (I think its 32 characters long), you can use bouncy castle sha library to calculate the corresponding public key given a private key, or it can generate both for you:
      http://www.bouncycastle.org/csharp/

      I recently used this method to generate some vanity addresses.

  1. Hi Jack,
    Can you please tell me whether the first string HexHash = “0450863…. is the so called master public key, the key from which you can derive numerous bitcoin addresses.

    Thank you!

    Theo

    1. BIP32 and other multi sig key generation were implemented after this tutorial, I’m not upto date on the role public keys have in order to generate alternative addresses unfortunately.

  2. Hi, by using SHA256Managed hashstring = new SHA256Managed(); I am getting “Bad Digest/CheckSum” error for the bitcoins addresses starting from “3”; what’s the possible work-around?

Leave a Reply to Theo Cancel reply