Click here to Skip to main content
15,867,704 members
Articles / Security / Blockchain

NBitcoin : The most complete Bitcoin port (Part 1 : Crypto)

Rate me:
Please Sign up or sign in to vote.
4.96/5 (55 votes)
21 May 2014LGPL313 min read 165.6K   73   45
Intro to Bitcoin for .NET Developers

Table of content

  1. Introduction on Bitcoin
    1. The entrepreneur perspective
    2. The economist perspective
    3. The whistleblower perspective
    4. The dark perspective
  2. Show me the code
    1. Getting started
    2. Bitcoin address
    3. Protecting privacy
    4. Identity verification
    5. Under the hood
    6. Shared ownership
  3. Conclusion

Introduction on Bitcoin

Codeproject fellows, I am glad to release the first article of a serie. [NEW : Part 2 Here]
I recently ported a good part of bitcoin source code from C++ to C#. I imported almost all unit tests. NBitcoin have approximately 70 tests you can use to play and discover.
This is a great learning experience that I will share with you. But Bitcoin all the technical aspects of bitcoin are too long to explain in only one article.
I will start this intro by looking Bitcoin from different perspectives, talking what led to its birth, and then showing you the code. For the first part I will cover only the offline aspect of bitcoin. In other words, I will omit all protocol details, and talk about the high level cryptographic part.

The Entrepreneur Perspective

Bitcoin grabbed my attention when I got fed up with Paypal happily blocking my fund as they pleased, along with the bureaucratic burden, fees, lack of transparence, and lack of privacy of our banking system to make any monetary transfer.

As a startup, integrating a payment provider to the website was a huge burden and cost center.
I tried a lot, before using paypal that is now happily taking 5% on each transaction, and reserve the right to block my money when it pleases them. They have lawyers, so they are always right.

Why is it so painful ? Why can’t I transfer my money easily without any intermediary ? Just me and the customer without the middle man. Bitcoin makes it possible.
This is my view as an entrepreneur.

The Economist Perspective

For the Keynes economist, Bitcoin is a money whose central banking (FED or European central bank) can’t control the supply, their poor lizard brains activate and remind them the scares of the Great Depression.
By then, transforming dollar into a fiat currency (not backed by gold, but controlled by central banking) was seen as the smartest decision to get out of crisis.
From this day, the FED (federal reserve), the bank of the banks, the bank of least resort changed. Before the great depression, the FED was a stock of gold for banks.
After, the FED became a large money printer.

Abolishing gold standard seemed a good idea, until Milton Friedman, properly explained what led to the Great Depression, leading Ben Bernanke to admit in 2002, then a Federal Reserve governor, that the FED was the culprit of the Great Depression. In other words, the problem was not with the dollar being backed by gold, but by the creation of the FED that led banks to take risks by believing they will be rescued. This Great Depression, caused by the FED, ironically caused the FED to be more powerfull, since it became free of the burden of gold. (Long story here)

For Milton Friedman, the creation of the fed, “the bank of the banks” is an error, which lead the big banks to take risks because they know they will be bailout in any case.
Our school does not teach this story though.

The economist perspective is important. Bitcoin was created by Satoshi Nakamoto precisely because he deeply believe Milton Friedman theory, the birth of bitcoin is around 03/Jan/2009, the first block, the genesis block, attests it with the following message embedded in it “03/Jan/2009 Chancellor on brink of second bailout for banks”.

The Developer Perspective

Bitcoin is a gift from the god, whatever is god for you. It is like if a whole monetary system open source for all to see and learn. If you want to send me some bitcoin, Satoshi Nakamoto bless you. Here is my address 15sYbVpRh6dyWycZMwPdxJWD4xbfxReeHe .
Yes that is all you need to know to send me money. There is nothing more to do for us, as developer, to get paid.

The problem is that I am sure lots of you are not really interested into looking a C++ code, and compiling on Linux with some bizarre voodoo like command line.
You like Visual studio ? You like C# ? You venerate Anders ? you are at the right place.

How I got my bitcoin address ? How do I know you sent me money ? How do I pay you ? this is be the red line of this article. (And thanks to NBitcoin, it is 4 lines long)

For more complex scenario like automatic monthly payment or automatic payment and delivery handling, all of this is possible but will be the subject to the (or 2) next article. (Spoiler : It is simply a matter of JSON calls)

The Whistleblower Perspective

You can like or despise what Wikileaks or Snowden did, but you can’t ignore them, as would say a long time Apple Ad.
But for a moment, imagine you are a whistleblower.
You live in Sweden and exposes some corrupted officials, and illegal activity of government officials. Now in defense, these officials, will block, without any trial, all of your payment mediums.
No paypal, no wire transfer, no credit card, no visa, no nothing, they will starve you to death for your crime. Without any trial.
But whatever they do, you can count on Bitcoin, Bitcoin can’t be subverted by any entity, not even by its creator.

The Dark Perspective

Now, let’s admit it, Bitcoin is not used only for brave cause.
But I would say that currently criminal can send money aboard by letter, or simply via some mafia led banks.
Plain bills can be used for money laundring as easily as bitcoin.
In the media, when an article says : “Money laundring in NYC” nobody will get a sh*t.
If an article says : “Money laundring in NYC with Bitcoin”, this will generate attention for sure.

Bitcoin is not dark, and is not led by mafia, it is the most open and democratic form of money that exist on this planet, and you can prove it, it is open source. But let’s face it : as our beloved dollar bill, criminal will use it too. (I will speak later about the democratic part of bitcoin, the community have an interesting way of “voting” features in bitcoin)
Bitcoin, however, is more traceable that the money that goes through a dark bank. (cf : HSBC)

A bitcoin bank already fell, it was called MtGox, and their customers lost money.
Mt Gox says it is because of a hack, I think it is because of a bank rush. Nobody can prove Mt Gox is right, or that I am. Anyway if you deal with bitcoin always remember the following quote, and spread it to everyone.

If you don’t own the private key. You don’t own bitcoins.

Mt Gox was a bank, they were keeping the private key for you, without giving it to you, and claiming to keep your money safe. But if you don’t have the private key, you have no way to prove they really keep your money, nor you have the right to spend it on bitcoin network directly.
Once again.

If you don’t own the private key. You don’t own bitcoins.

Talk is cheap, show me the code

Getting started

First of all, the code is on GitHub.
Secondly, the binaries are on Nuget.
So to get started, new console project, then add a reference on the nuget package NBitcoin.

image

For the dependencies, BouncyCastle is used for the crypto part, bitcoin use ECDSA asymmetric keys under the hood and I don’t want to implement that myself. In the C++ code, OpenSSL is used instead.

Mono.NAT and SQLite are used only if you intend to create your own Bitcoin Node (next article). Mono.NAT will use UPNP to open bitcoin ports on your gateway to run your node.
SQLite is the embedded database that your node server will use to store transactions, blocks and peers. It works in both x86 and x64. You can remove those if you don’t intend to talk with Bitcoin network.

Bitcoin addresses

As I said, if you want to send me some bitcoins, send it to 15sYbVpRh6dyWycZMwPdxJWD4xbfxReeHe .
But, as a developer what represent this address ? The formal spec is here, but let’s explore it with NBitcoin instead.
This string is a base58 string encoded byte array.
Let’s see that address under its hexadecimal representation.

C#
static void Main(string[] args)
{
    byte[] byteArray = Encoders.Base58.DecodeData("15sYbVpRh6dyWycZMwPdxJWD4xbfxReeHe");
    string hex = Encoders.Hex.EncodeData(byteArray);
    Console.WriteLine(hex);
}

Which gives us :
00356facdac5f5bcae995d13e667bb5864fd1e7d59fb69d021
00
: Prefix that identify the type of the bitcoin data structure, in this case it is a public key hash (see later)
356facdac5f5bcae995d13e667bb5864fd1e7d59 : actual public key hash (20 bytes)
fb69d021 : checksum of all the previous data (detect mistyping)

In bitcoin, an address belongs to a network, and there is two networks : Main and Test. You can get bitcoin on the test network for free for your tests.
However, each network have a different prefix to identify a public key hash.
On the Main Network 00 is the prefix for the public key hash. But for Test Network it is 6f.
This is done so you can’t send money to an address that belong to another network.

You can use the BitcoinAddress type to do the conversion for you in several way.

C#
static void Main(string[] args)
{
    BitcoinAddress address = (BitcoinAddress)Network.CreateFromBase58Data("15sYbVpRh6dyWycZMwPdxJWD4xbfxReeHe");
    //BitcoinAddress address = Network.Main.CreateBitcoinAddress("15sYbVpRh6dyWycZMwPdxJWD4xbfxReeHe");
    //BitcoinAddress address = new BitcoinAddress("15sYbVpRh6dyWycZMwPdxJWD4xbfxReeHe", Network.Main);
    Console.WriteLine(address.ID);
    //Print 356facdac5f5bcae995d13e667bb5864fd1e7d59
}

But where did I got this “public key hash” ?
When someone send you money in bitcoin, they broadcast a Transaction to the network.
All transactions contain one or more TxIn (Transaction input) and one or more TxOut. (Transaction output)
Any TxOut that contains your public key hash is spendable by you.

When, in your turn, you will pay someone, you send a new Transaction to the network, but this time you will include a TxIn with a reference to the TxOut you want to spend. (We call such reference an OutPoint)
However, you will sign the transaction with the private key associated to the public key hash present in the TxOut you want to spend. Thus proving to the network your ownership.

Here is the process of creating a new keypair.

C#
static void Main(string[] args)
{
    Key privateKey = new Key(); //Create private key
    BitcoinAddress address = privateKey.PubKey.GetAddress(Network.Main); //Get the public key, and derive the address on the Main network
    Console.WriteLine(address); //printed in my case 15sYbVpRh6dyWycZMwPdxJWD4xbfxReeHe
}

Seemingly, if you want to store the private key,
C#
Key privateKey = new Key(); //Create private key
BitcoinSecret secret = privateKey.GetBitcoinSecret(Network.Main);
Console.Write(secret); //Print base58 string

Here is a small diagram of all classes, you can see that a BitcoinAddress is nothing but a public key hash, and does not allow you to deduce the PubKey.

image

Protecting privacy

If every transaction is broadcasted to the network, it means that anyone should be able to track how much I receive, which raise some privacy concern. This is true, you can see that someone sent me 0.0026 BTC.

You can create as much private key you want. If you want to keep private key, you can break your receive among several addresses. (A set of private key is called a wallet)
If you are a business and need to automate your payments you have another alternative :
Create one different bitcoin address per business transaction.

However, there is two problems with that :

  • You need to maintain a mapping between your business transaction and the private key you used,
  • If such database is compromised or private key stolen, you loose money.

The solution is called Hierarchical Deterministic Wallet.
Thanks to that, you can give your payment server the right to generate public keys, without giving the private key. If the payment database is stolen or compromised, you loose nothing.

In NBitcoin, this feature is implemented with two classes : ExtKey and ExtPubKey.
ExtKey will generate a Key for a corresponding ID,
ExtPubKey will generate a PubKey for a corresponding ID.

image

C#
ExtKey privateKey = new ExtKey();
ExtPubKey pubKey = privateKey.Neuter();
//Now, give the pubkey to your payment server
//....
//The payment server receive an order, note the server does not need the private key to generate the address
uint orderID = 1001;
BitcoinAddress address = pubKey.Derive(orderID).PubKey.GetAddress(Network.Main);
Console.WriteLine(address);

//Now on the server that have access to the private key, you get the private key from the orderID
Key key = privateKey.Derive(orderID).Key;
BitcoinSecret secret = key.GetBitcoinSecret(Network.Main);
Console.WriteLine(secret); //Print a nice secret key string

In this example we only use an orderId to generate the Key/Pubkey, but in reality you can use more data, this is why we that a Hierarchical Wallet.

For example

C#
pubKey.Derive(departmentID).Derive(orderID).PubKey

This way, you can generate a dedicated private key to each department. (And also spend their funds if you have the master ExtKey)

Using bitcoin key pairs for identity verification

How can I prove you, dear reader, that I am indeed, the owner of the private key of 15sYbVpRh6dyWycZMwPdxJWD4xbfxReeHe ?
Here is the proof :
Message : “I am Nicolas Dorier, owner of this address 15sYbVpRh6dyWycZMwPdxJWD4xbfxReeHe”.
Signature : “IGkC4NKGXOXJ6CNT8T6Dx0egqaiSb8rAlBdsmanStOhbVfILmY+3p88Z/Fhb/jSkUhHFhsbcxFZydoPrh/2LNY0=”

How did I generate this signature ?

C#
BitcoinSecret secret = new BitcoinSecret("base58 private key", Network.Main);
string signature = secret.Key.SignMessage("I am Nicolas Dorier, owner of this address 15sYbVpRh6dyWycZMwPdxJWD4xbfxReeHe");
Console.WriteLine(signature);

On your side, how do you verify ?

C#
string message = "I am Nicolas Dorier, owner of this address 15sYbVpRh6dyWycZMwPdxJWD4xbfxReeHe";
string signature = "IGkC4NKGXOXJ6CNT8T6Dx0egqaiSb8rAlBdsmanStOhbVfILmY+3p88Z/Fhb/jSkUhHFhsbcxFZydoPrh/2LNY0=";
BitcoinAddress address = new BitcoinAddress("15sYbVpRh6dyWycZMwPdxJWD4xbfxReeHe", Network.Main);
bool verified = address.VerifyMessage(message, signature);
Console.WriteLine(verified);

Under the hood

To simplify my explanation, I made some shortcut to explain you what is a bitcoin address.
I said, a TxOut send money to a bitcoin address, and when you want to spend it, you add a TxIn in your transaction that reference the TxOut, and sign that with your private key.

But Bitcoin is more flexible than that.
TxOut does not necessarily contains your address. TxOut contains a Script that we call the ScriptPubKey. This script is like an algorithm that say what you need to do to spend this TxOut.
Seemingly, TxIn have a Script called a ScriptSig this does what ScriptPubKey wants to spend the TxOut. These scripts are a sort of stack language without any loop.

When the SigPubKey is concatenated to the ScriptSig, the algorithm is executed, its result get push in the stack.

image

Until now, if you want to pay me, the ScriptPubKey will looks like that. (In readable form)

C#
BitcoinAddress to = new BitcoinAddress("15sYbVpRh6dyWycZMwPdxJWD4xbfxReeHe", Network.Main);
PayToPubkeyHashScriptTemplate template = new PayToPubkeyHashScriptTemplate();
Script script = template.GenerateOutputScript(to);
Console.WriteLine(script);

OP_DUP OP_HASH160 356facdac5f5bcae995d13e667bb5864fd1e7d59(public key hash) OP_EQUALVERIFY OP_CHECKSIG

On the other hand, if I want to use these funds my script will be

C#
BitcoinSecret secret = new BitcoinSecret("base58 secret key", Network.Main);
byte[] transactionSignature = secret.Key.Sign(transactionHash);
PayToPubkeyHashScriptTemplate template = new PayToPubkeyHashScriptTemplate();
Script scriptSig = template.GenerateInputScript(new TransactionSignature(transactionSignature, SigHash.All), secret.Key.PubKey);
Console.WriteLine(scriptSig);


The resulting script will push two values on the stack : the signature of the transaction and the public key.
<signature of transaction> <public key>

If we concatenate both scripts we get

<signature of transaction> <public key> OP_DUP OP_HASH160 <public key hash> OP_EQUALVERIFY OP_CHECKSIG

It means
Push <signature of transaction>
Push <public key (1)>
Push <public key (2)> again
Hash <public key (2)>, pop <public key (2)>, push <public key hash (1)>
Push <public key hash (2)>
Verify <public key hash(1)> equals to <public key hash(2)>, pop <public key hash(1)>, pop <public key hash(2)>
Check signature <signature of transaction> with Push <public key (1)>, pop <signature of transaction>, pop <public key (1)>, push true if verified or false

Shared ownership

Why the scripting system is such big of a deal ?
Because it allows new way of ownership, there is a special script that is called “M of N wallet”, when someone sends funds to a M of N wallet, it means the spender will need to provide N signature of M possible addresses.

This way, you can enforce the fact that 2 persons among 3 should agree to spend to enforce a consensus.
You can use a 1 person among 2 persons, if you want to share money with someone.
The difference between that and sharing a private key is nonrepudiation. When you use a “1 of 2 wallet”, you have the proof of the identity of the spender.
Such script can be generated as such

C#
PayToMultiSigScriptTemplate template = new PayToMultiSigScriptTemplate();
Script scriptPubKey = template.GenerateOutputScript(1, new PubKey[] { nicoPubKey, bobPubKey });

01 <nico hash pub key> <bob hash pub key> 02 OP_CHECKMULTISIG

There are other standard scripts, that I will surely talk in next post. Here is a class diagram of them.

image

image

Conclusion

Finally, this article is longer than I thought…next time I will go more into the internal of bitcoin protocol as well as talk about other standard scripts. Please, let me know if you liked this article. Sourire
[NEW : Part 2 Here]

License

This article, along with any associated source code and files, is licensed under The GNU Lesser General Public License (LGPLv3)


Written By
Software Developer Freelance
France France
I am currently the CTO of Metaco, we are leveraging the Bitcoin Blockchain for delivering financial services.

I also developed a tool to make IaaS on Azure more easy to use IaaS Management Studio.

If you want to contact me, go this way Smile | :)

Comments and Discussions

 
GeneralMy vote of 5 Pin
Damian Suess14-Feb-20 7:21
Damian Suess14-Feb-20 7:21 
QuestionUse NBitcoin to Make Payment Pin
Member 1460543312-Dec-19 3:56
Member 1460543312-Dec-19 3:56 
QuestionAny Update on this paper? Pin
Ron Yam15-Jun-18 7:22
Ron Yam15-Jun-18 7:22 
Hi Nicolas, thanks for writing a great article for a late comer in the Bitcoin development like me.
The financial market definitely has changed with big swings and is trading 6.7 K USD today. On the technical side which I am interested in, the Block Chain development also have other new comers and progress, like Ethereum and others. But I really like you approach with using .Net. Do you have any updated ideas on Bitcoin itself, and impact of .Net Core on what you have done? Many of us like to hear from you. Thanks, Ron Yam
QuestionNot getting Key Pin
C For Code!!! 13-Dec-17 4:58
C For Code!!! 13-Dec-17 4:58 
QuestionCompare to Solidity Pin
Member 1000333010-Jun-17 14:43
Member 1000333010-Jun-17 14:43 
QuestionThe article is awesome Pin
To Thanh Liem22-May-17 1:17
To Thanh Liem22-May-17 1:17 
PraiseMany thanks and congrats!!! Pin
Tiago Colombo22-Oct-16 8:46
Tiago Colombo22-Oct-16 8:46 
QuestionHow about litecoin? Pin
piotrgal28-Dec-15 4:44
piotrgal28-Dec-15 4:44 
QuestionConfirming the Transaction Pin
David James10-Nov-15 1:34
David James10-Nov-15 1:34 
AnswerRe: Confirming the Transaction Pin
Mr Jen Withers23-Nov-15 9:05
Mr Jen Withers23-Nov-15 9:05 
AnswerRe: Confirming the Transaction Pin
Mr Jen Withers23-Nov-15 9:15
Mr Jen Withers23-Nov-15 9:15 
QuestionNew Tx notification Pin
Member 98218528-Feb-15 2:05
Member 98218528-Feb-15 2:05 
AnswerRe: New Tx notification Pin
Nicolas Dorier8-Feb-15 2:38
professionalNicolas Dorier8-Feb-15 2:38 
GeneralRe: New Tx notification Pin
Member 98218528-Feb-15 3:01
Member 98218528-Feb-15 3:01 
GeneralRe: New Tx notification Pin
Nicolas Dorier8-Feb-15 3:18
professionalNicolas Dorier8-Feb-15 3:18 
GeneralRe: New Tx notification Pin
Member 98218528-Feb-15 3:49
Member 98218528-Feb-15 3:49 
GeneralRe: New Tx notification Pin
Senek9-Apr-15 22:09
Senek9-Apr-15 22:09 
QuestionPayToPubkeyHashScriptTemplate Pin
Member 112815152-Dec-14 16:29
Member 112815152-Dec-14 16:29 
AnswerRe: PayToPubkeyHashScriptTemplate Pin
Nicolas Dorier4-Dec-14 1:08
professionalNicolas Dorier4-Dec-14 1:08 
QuestionMake payment Pin
Oriol Ventura20-Aug-14 22:52
Oriol Ventura20-Aug-14 22:52 
AnswerRe: Make payment Pin
Nicolas Dorier20-Aug-14 23:14
professionalNicolas Dorier20-Aug-14 23:14 
GeneralRe: Make payment Pin
Member 1164936828-Apr-15 6:11
Member 1164936828-Apr-15 6:11 
AnswerRe: Make payment Pin
Nicolas Dorier2-Feb-15 2:01
professionalNicolas Dorier2-Feb-15 2:01 
GeneralRe: Make payment Pin
pinca george27-Mar-15 21:08
pinca george27-Mar-15 21:08 
GeneralThank You Pin
Lucas Ontivero22-May-14 8:35
professionalLucas Ontivero22-May-14 8:35 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.