Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

NBitcoin : Cryptography Part 2

0.00/5 (No votes)
21 May 2014 1  
Two Factor keys and Stealth Addresses

Introduction

After my first article on NBitcoin, I decided to make a serie of article on NBitcoin, the bitcoin gateway for .NET Developers.

This article will skip the internal math so you can get the general idea and data flow. I will briefly point to link that can explain the math better than me at the end of this article.

My first article was discussing about some basics of how Bitcoin works to ensure you can spend the funds you claim to own.
This article will speak about some solutions to increase privacy and security.
For privacy, the root of the problem is that bitcoin transactions are publicly published. So if you use always the same address, someone can see how much you have and receive and the timestamps, and deduce information about you.
Snowden’s leaks, switched on the “privacy by default” light in the head of lots of people. Not a bad thing, since such behavior will protect against other treats as well.

We explored one solution in the previous article called HD Wallet. This works fine, but if a root public key leaks with the IDs you used to derive children keys, then you are exposed again.
We will explore Stealth Address, that protect against such problem.

We will also see how to encrypt your keys with a password, we call such keys Encrypted Key.
And, in the same way as HD Wallet from the previous article, we will see it is possible to give right to a third party to generate an Encrypted Key for you without giving him knowledge of your password, nor the underlying private key.
If this third party is your own payment server, it means that if it is hacked, there will be no access granted to your private keys, making hacking futile. (but you stay weak to physical and personal treat Clignement d'œil)

Encrypting keys : Two factor (BIP 38)

There is two ways to encrypt a key :

  • By knowing the key,
  • By knowing the PassphraseCode (useful if you delegate the process to untrusted third party)

Encrypt by knowing your key

Imagine that you own a key in Bitcoin to reclaim your funds.
Normally, whoever possess the key, possess the right to spend your fund, this is fundamentally one factor.
But you can encrypt it with a password, so someone need both : your key and know the password to spend your funds.

image

In code :

Key key = new Key(); //Create a new key
BitcoinSecret secret = key.GetBitcoinSecret(Network.Main);
Console.WriteLine(secret); //Will print the key in base58 check format
BitcoinEncryptedSecret encrypted = secret.Encrypt("This is my secret password");
Console.WriteLine(encrypted); //Will print the encrypted key in base58 check format
key = encrypted.GetKey("This is my secret password"); //Get the same key as before

The encryption process is defined by BIP 38. It is protected from brute force by the key derivation algorithm Scrypt, which will slow any attempt.

Encrypt by knowing the PassphraseCode

In some case, you want to allow a third party (a payment server for example) to generate bitcoin addresses and the associated encrypted keys for you… but without giving him neither the key or the password.
In such situation, you need to give a PassphraseCode to the third party, the third party will then generate keys for you. (For each business transaction for example)

image

In code:

BitcoinPassphraseCode result = new BitcoinPassphraseCode("This is my secret password", Network.Main, null); //Generate a passphrase, even if the password is used in the constructor, it is not embedded in the PassphraseCode
Console.WriteLine(result); //Print passphraseCode in base 58 check format
//Give the passphrase code to the third party.
var generationResult = result.GenerateEncryptedSecret(); //Generate a new encrypted key
Console.WriteLine(generationResult.GeneratedAddress); //Print the generated address
Console.WriteLine(generationResult.EncryptedKey); //Print the BitcoinEncryptedKey
            
//...Give the generated address back to the owner
Key key = generationResult.EncryptedKey.GetKey("This is my secret password");

BitcoinPassphraseCode is the only information given to the third party, and does not include any sensitive data. The third party can then use it to generate encrypt keys for you, but can’t decrypt them.

Protecting your privacy : Stealth Address

If you want this simplicity of a static, fixed, bitcoin address but with the privacy that an BitcoinPassphraseCode or HD key can give you, then stealth address is for you.

Here was the original idea behind Stealth Address:

As a receiver, you will publish a spending PubKey and keep secret the associated spending Key.

As a sender, you combine the spending PubKey, with an ephemere, random key, called Ephem Key, that will generate a Stealth PubKey and so a Bitcoin address to which to pay.

image

As a receiver, you will receive the Ephem PubKey, and will combine your Spend Key to retrieve the Stealth Key to spend the funds sent to the generated Bitcoin address.

image

However, there is one fundamental problem with such design.
There is no automatic way to send the Ephem PubKey from sender to receiver.

The solution is to include the Ephem PubKey in the same transaction that send the funds to Bitcoin Address.
In the transaction, two TxOut will be generated : The payment to the Bitcoin Address (Spendable output) and an unspendable TxOut with the ephem key embedded in it.
We call such unspendable TxOut the Stealth Metadata. I will call such pair of TxOut a Stealth Payment.

As a receiver, you will scan all transactions with such Stealth Payment on the bitcoin network, you will extract the Ephem PubKey, then you generate the Stealth Key and checked if it’s address match the one in the spendable output.

image

As a receiver, you want to automate such scan, however, you don’t want to give to the scanner your Spend Key, because the scanner, or a hacker, would be able to use it to steal your money.

The solution is to introduce a Scan Key that both the scanner and the sender will use to generate and scan the Stealth PubKey.
This way, the scanner will be able to report your balance by scanning the blockchain without the need of the Spend Key.
However, now the sender need two pieces of information to pay you : The Scan PubKey + the Spend PubKey these two are bundled inside a BitcoinStealthAddress that the receiver publicly share.

image

Now, the sender want to send you some money, here is how he generate the Stealth PubKey. (Note that now he needs the two keys, from the StealthAddress)

image

As a receiver or scanner, you don’t need the Spend Key anymore to check if a transaction is for you.

image

And if you want to spend the money, then use the Spend Key manually to get the Stealth Key.

image

This is the current design of DarkWallet transactions, and the one that is expressed in the following NBitcoin code.

Key scan = new Key();
Key spend = new Key();
BitcoinStealthAddress address = spend.PukKey.CreateStealthAddress(scan.PubKey,Network.Main);
//The receiver publish the address on a forum or whatever....
//Sender then create payment
Key ephem = new Key(); //Optional, CreatePayment create one if not specified
StealthPayment payment = address.CreatePayment(ephem);
//In you want to include the payment to a transaction
Transaction tx = new Transaction();
payment.AddToTransaction(tx);
//Receiver receive the payment via the block chain with (address.Bitfield.GetPayments(tx))
Key key = spend.Uncover(scan,payment.Metadata.EphemKey);
//Or, if you just want the public key (equals to key.PubKey)
PubKey pubkey = spend.PubKey.UncoverReceiver(scan, payment.Metadata.EphemKey);

You can replay these steps in parallel with sx (command line utility on linux) to verify the implementation.
There is a deterministic unit test for that.

Conclusion

This article tried to stay developer friendly. The underlying math documentation are published in the links below. The general flow was hard to understand for me, because I am not very familiar with the underlying math (Elliptic Curve), I hope this article will help other developers to grasp the idea without being lost in the math.

Next, I will make articles on the network aspect of bitcoin.

Underlying math, and scanner : https://wiki.unsystem.net/index.php/DarkWallet/Stealth#Theory
Command line utility : http://sx.dyne.org/index.html
Early bitcoin page about the idea : https://en.bitcoin.it/wiki/Sx/Stealth

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here