Lab 7 Details for MPCS 56600

Each lab will consist of a small problem and details of how to proceed. Each lab is intended to give every student hands-on experience with the core concepts and technologies covered during the course.  A student may concentrate, as a team member, on one technology over another for the final project, but labs are designed to give each and every student exposure to all the technologies that come into play.  You need to submit labs to the TAs for grading--see submission instructions below.  Generally, unless otherwise specified, you will have one week to complete each assigned lab.

See the syllabus for information on grading.  Turning in lab assignments on time is required, without exception, and all late deliveries will be penalized, regardless of cause.  Submit your assignments to the subversion repository according to the directions on the syllabus page.

Lab 7   Due: 5:00 PM, Friday, May 24, 2019

BACKGROUND:

Like all programming problems, learning a new technology is not an exercise in reading but rather an exercise in thinking and typing.  This lab is designed to give you  hands-on experience in some fundamental skills involved in bitcoin address generation.  This is a fundamental capability of bitcoin wallets.  You will generally find the References section below helpful in addition to the required and recommended reading.  

Problem 1:  Write a Base58 encoding function:  

WHAT YOU NEED TO DO:

Create a working directory for Lab 7. 

We covered Base58Check encoding in our lecture.  Your first task is to write, in your language of choice, an implementation for base58 encoding.  A general introduction to Base58 encoding can be found on the Bitcoin wiki here.  An online site that will allow you to type in any text to check whether your function is working correctly can be found here.  You can both encode and decode on this site; therefore, you can check that your implementation of the algorithm is functional there.  You may find the BitcoinWiki discussion here helpful.  The associated video will also likely prove helpful.

Note that for Problem 1, all you have to do is write a functioning Base58 encoder.  You do not need to provide a decoder.  You can check your results online at the site mentioned above.  Note that although there are numerous libraries that provide working functions and methods for doing Base58 encoding, written in a variety of languages, you are expected to produce your own version of the algorithm and you may not use one existing, either in source code or in a library (such as SSL, bitcoinlib, etc.).  Note that if you can find and copy an implementation of base58 encoding online, we likely can find it too.  So do your own work.

Further, a Base58 encoder and decoder for legal bitcoin addresses can be found here.

Problem 2:  Bitcoin Address Generation:  

WHAT YOU NEED TO DO:

Step 1:  You will need base58check available (we will reuse yours from Problem 1 above a little later) to run the script that serves as our initial example.  To install, simply execute:  "sudo pip install base58".  Confirm that you have it installed and available by executing:

$ echo "hi" | base58

As output, you should see:  "c55T".

Step 2:  Download this zip file into your working directory.  Unzip it and type make.  If you get an error about secp256k1 being missing, you need to install this small library from source as follows:

git clone https://github.com/libbitcoin/secp256k1
cd secp256k1
./autogen.sh
./configure
make
sudo make install
If you see any other issues, post to piazza.

Then, visit this web page that describes in detail how to create a bitcoin address (for mainnet) from a secret and public key created through elliptic curve cryptography along with various hashing algorithms.  Read through the page carefully to see how the bitcoin address "1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs" is created from an initial private ECDSA Compressed Public Key of "18e14a7b6a307f426a94f8114701e7c8e774e7f9a47e2c2035db29a206321725". 

After understanding the general idea, execute the following script in the directory you unzipped the zip file above in (after having successfully run make):

$ runitCPP3.sh
Starting with ECDSA key from STEP 0: 18e14a7b6a307f426a94f8114701e7c8e774e7f9a47e2c2035db29a206321725
STAGE 0 is: 18e14a7b6a307f426a94f8114701e7c8e774e7f9a47e2c2035db29a206321725
secret: 1qN5zM32g7pvJictqC1nz2v8kpMvdws3m5PMb7WEVrrAMQoZvsE
Public key: 0250863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352
STAGE 1 is: 0250863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352
Private key: 1qN5zM32g7pvJictqC1nz2v8kpMvdws3m5PMb7WEVrrAMQoZvsE
EC Point: 0450863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b23522cd470243453a299fa9e77237716103abc11a1df38855ed6f2ee187e9c582ba6
s: 0450863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b23522cd470243453a299fa9e77237716103abc11a1df38855ed6f2ee187e9c582ba6
x coord: 50863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352
y coord: 2cd470243453a299fa9e77237716103abc11a1df38855ed6f2ee187e9c582ba6
Public Key Compressed:
0250863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352
Working with Compressed Public Key: 0250863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352
STAGE 2 is: 0b7c28c9b7290c98d7438e70b3d3f7c848fbd7d1dc194ff83f4f7cc9b1378e98
STAGE 3 is: f54a5851e9372b87810a8e60cdd2e7cfd80b6e31
STAGE 4 is: 00f54a5851e9372b87810a8e60cdd2e7cfd80b6e31
STAGE 5 is: ad3c854da227c7e99c4abfad4ea41d71311160df2e415e713318c70d67c6b41c
STAGE 6 is: c7f18fe8fcbed6396741e58ad259b5cb16b7fd7f041904147ba1dcffabf747fd
STAGE 7 is: c7f18fe8
STAGE 8 is: 00f54a5851e9372b87810a8e60cdd2e7cfd80b6e31c7f18fe8
STAGE 9 is: 1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs

Notice the output above that is preceded with the prefix "STAGE X:" with X running from 0 through 9.  Compare the output of these various STAGE outputs [0-9] above with the steps described in the web page above.  Note especially in the code (both C++ and the shell script b58converter2.sh) that we are working with binary data.  This should be familiar to you now.  Note and understand what the multiple calls to xxd -r -p are doing.

Step 3:  Your job is to code, in your language of choice, the specific steps 0 through 9.  For Problem 2 (with the exception of STAGE 9 below), you may use any set of libraries available to perform the ECDSA cryptography as well as any library functions (openSSL, bitcoinlib, etc.) providing the requirements for STAGEs 0 through 8 (your mileage may vary if you chose libreSSL FYI...you are better off using the actual OpenSSL libraries).  You may find the OpenSSL libraries here.  For those working in python, you will want to make sure you have pip installed ecdsa and that you are importing (at least) os, binascii, ecdsa, annd hashlib.  There are of course other options as well. 

Everyone will be dealing with very big numbers here.  So make sure you have the appropriate tools in place for such support (e.g., Golang people might look into "math/big", etc.).  And of course there are the C++ bitcoin core libraries as well...e.g., libbitcoin.

Note in the final stage, STAGE 9, you are to use your own Base58Check encoding function that you created above in Problem 1.  Your code output should match the output of each of the "STAGE X" printouts from runitCPP3.sh above (you do not need to match the other output unless you wish...that said, we will be impressed if you can print out the EC point value).  That is to say, at a minimum, your output should display (precisely, at a minimum):

$ myprog
STAGE 0 is: 18e14a7b6a307f426a94f8114701e7c8e774e7f9a47e2c2035db29a206321725
STAGE 1 is: 0250863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352
STAGE 2 is: 0b7c28c9b7290c98d7438e70b3d3f7c848fbd7d1dc194ff83f4f7cc9b1378e98
STAGE 3 is: f54a5851e9372b87810a8e60cdd2e7cfd80b6e31
STAGE 4 is: 00f54a5851e9372b87810a8e60cdd2e7cfd80b6e31
STAGE 5 is: ad3c854da227c7e99c4abfad4ea41d71311160df2e415e713318c70d67c6b41c
STAGE 6 is: c7f18fe8fcbed6396741e58ad259b5cb16b7fd7f041904147ba1dcffabf747fd
STAGE 7 is: c7f18fe8
STAGE 8 is: 00f54a5851e9372b87810a8e60cdd2e7cfd80b6e31c7f18fe8
STAGE 9 is: 1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs

Once you have your desired output from STAGE 9, viz. "1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs", you should verify that this is indeed a valid bitcoin mainnet address by visiting this site and entering the address.

NOTE:  You are not expected to code your own implementation of elliptic curve private key generation.  You may leverage any of a number of libraries that provide such capability, including python's ecdsa etc.  Java people may wish to investigate options from Bouncy Castle.

References:

You may find the following references helpful (in addition to the links listed above):

https://learnmeabitcoin.com/glossary/base58
https://awebanalysis.com/en/bitcoin-address-validate/
https://en.bitcoin.it/wiki/Base58Check_encoding#Base58_symbol_chart
https://en.bitcoinwiki.org/wiki/Base58
https://incoherency.co.uk/base58/

Bouncy Castle for Java:
https://stackoverflow.com/questions/18244630/elliptic-curve-with-digital-signature-algorithm-ecdsa-implementation-on-bouncy

General  Links

Submitting:

Use the folder named "lab7" in your Subversion repository. See the syllabus for more info about submission using Subversion. Upload your Lab 7 code and any supporting materials to the repo.  Please include a README text file to explain what parts of the work you are submitting, where the different parts of the work are located and please provide a little info on how to compile and run your code.