Python Crypto Basics for Building a Blockchain

Basics of building a blockchain using python, part 1

“Even if you are on the right track, you’ll get run over if you just sit there.” ― Will Rogers

1. Introduction

A Blockchain is all the craze right now. With the Bitcoin price on a runaway track, everyone wants in on the bitcoin bandwagon. While buying and selling bitcoin and other cryptocurrencies is good (or bad, depending on your finances!), let us learn the basics of the technology behind these cryptocurrencies. In the process we will also attempt to come up with the building blocks of the technology starting from scratch.

Fundamental to the technology of the bitcoin is the blockchain. It is a database of transactions in the following format: it is a chain of blocks (hence the name blockchain), with each block containing one or more transactions between parties. Each block contains a cryptographic hash of the previous block and thus forms a chain. The blockchain is distributed across the network and each participant in the network has a copy of the blockchain.

Each party in a transaction is represented by the public key of a public-private key pair. The information in each block is hashed and stored in the next block in the chain. Data sent across the network is digitally signed by the party using the private key.

We will now discuss these technologies with regard to learning about the blockchain: Public and Private Keys, Cryptographic Hashing and Digital Signatures. We present code samples on how to accomplish these tasks in python.

2. Preliminaries

We will use Pycrypto for the cryptographic computations. You should create and use a virtual environment for the purpose.

Run these commands on a console. After this you should be in a virtual environment called bc (for blockchain).

pip install virtualenv
virtualenv bc
source bc/bin/activate

Now you can install Pycrypto.

pip install pycrypto

We are now ready.

3. RSA Public and Private Keys

We will use RSA for generating the keys. Each key has a public and a private part. The private part is securely stored and the public part is public. This is so others can verify the integrity of the information you send them, and also be sure that you indeed sent them.

Generate an RSA private key of 2048 bits like this:

from Crypto.PublicKey import RSA
key = RSA.generate(2048)

3.1. Saving the Keys

Save the private key in PEM format as follows. The saved key can be reloaded and re-used.

with open('mykey.pem','w') as f:
    f.write(key.exportKey('PEM'))

If you like, you can generate and save the public key to a file too. It is not really necessary though, since the public key can be generated from the private key.

with open('mykey.pub','w') as f:
    f.write(key.publickey().exportKey('PEM'))

3.2. Restoring the Keys

Restore the private key in a PEM format from a file as follows:

with open('mykey.pem') as f:
    key = RSA.importKey(f.read())

The public key can be generated from the private key as follows:

pubkey = key.publicKey()

4. Computing Hash Digests

A cryptographic hash is a one-way signature of a data buffer with the property that even a single bit of change in the data results in a different hash. This makes the hash a compact representation of the data, but the data itself cannot be derived from the hash. It is essentially a one-way mapping of data (of any size) to a fixed-sized string.

The most common hash function in use today is the Secure Hash Function. Formerly the SHA-1 algorithm was in widespread use, but collisions have been discovered in the algorithm. A collision means two different data arrays result in the same hash value. So the recommended hashing function today is the SHA-2 algorithm with a bit size of 256 or greater. This is known as SHA256.

Compute a SHA256 hash of a data buffer in python using:

from Crypto.Hash import SHA256, SHA, SHA512
mesg = 'hello world'
h = SHA256.new()
h.update(mesg)
print h.hexdigest()
# prints
b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9

5. Digital Signature

A digital signature is a method of cryptographically assuring a receiver (Bob) that the message is from a specified party (Alice). Alice prepares a data buffer, computes a secure checksum, encrypts the checksum using her private key, and sends the data buffer and the encrypted checksum to Bob. Bob unencrypts the checksum using Alice’s public key, computes the checksum of the data buffer with the same algorithm as used by Alice and compares the two checksums. If they match, the data buffer was prepared by Alice and has not been modified in-transit.

5.1. Computing a Digital Signature

Here is how you can compute the digital signature of a file.

  1. Read the input file
    fname = ...
    with open(fname) as f:
      message = f.read()
    
  2. Read the RSA private key
    with open('mykey.pem') as f:
      key = RSA.importKey(f.read())
    
  3. Compute the SHA256 checksum of the message.
    h = SHA256.new()
    h.update(message)
    
  4. Compute the signature and write it to a file.
    sgn = PKCS1_PSS.new(key)
    with open('mesg.sgn', 'w') as f:
      f.write(sgn.sign(h))
    

Now you have the digital signature in binary form in the file mesg.sgn. Send it along with the input file to the receiver.

5.2. Verifying the Digital Signature

Once the receiver (Bob) has received the file and the signature in mesg.sgn, he can verify that it came from Alice as follows.

  1. Read the input file
    with open(fname) as f:
      message = f.read()
    
  2. Compute the message digest
    h = SHA256.new()
    h.update(message)
    
  3. Read the signature data.
    with open('mesg.sgn') as f:
      signature = f.read()
    
  4. Read the public key from the file.
    with open('mykey.pub') as f:
      key = RSA.importKey(f.read())
    
  5. And verify that the signature is correct.
    vfy = PKCS1_PSS.new(key)
    if vfy.verify(h, signature):
      print 'signture matches.'
    else:
      print 'signature problem.'
    

And now the file is confirmed to have come from the sender (Alice).

Conclusion

In this article, we learnt about some of the technology underlying blockchains. These include, at the core

  1. Public and private keys
  2. SHA checksum of messages
  3. Digital signature and verification of messages using public keys.