Table of content
- Introduction on Bitcoin
- The entrepreneur perspective
- The economist perspective
- The whistleblower perspective
- The dark perspective
- Show me the code
- Getting started
- Bitcoin address
- Protecting privacy
- Identity verification
- Under the hood
- Shared ownership
- 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 shit.
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.
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.
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.
static void Main(string[] args)
{
BitcoinAddress address = (BitcoinAddress)Network.CreateFromBase58Data("15sYbVpRh6dyWycZMwPdxJWD4xbfxReeHe");
Console.WriteLine(address.ID);
}
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.
static void Main(string[] args)
{
Key privateKey = new Key(); BitcoinAddress address = privateKey.PubKey.GetAddress(Network.Main); Console.WriteLine(address); }
Seemingly, if you want to store the private key,
Key privateKey = new Key(); BitcoinSecret secret = privateKey.GetBitcoinSecret(Network.Main);
Console.Write(secret);
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.
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.
ExtKey privateKey = new ExtKey();
ExtPubKey pubKey = privateKey.Neuter();
uint orderID = 1001;
BitcoinAddress address = pubKey.Derive(orderID).PubKey.GetAddress(Network.Main);
Console.WriteLine(address);
Key key = privateKey.Derive(orderID).Key;
BitcoinSecret secret = key.GetBitcoinSecret(Network.Main);
Console.WriteLine(secret);
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
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 ?
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 ?
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.
Until now, if you want to pay me, the ScriptPubKey will looks like that. (In readable form)
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
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
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.
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.
[NEW : Part 2 Here]