Skip to content

MSc Exercise for Introduction to Computer Security. A simulation of a blockchain messaging platform based on the Bitcoin protocol. Exchange privately and securely messages and images. Become a miner and collect rewards or just a plebeian client and send messages without supporting the platform.

License

Notifications You must be signed in to change notification settings

WckdAwe/Uncuffed

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

17 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Contributors Forks Stargazers Issues MIT License


🔗 Uncuffed - Blockchain secure messaging

MSc Exercise for Introduction to Computer Security
A simulation of a blockchain messaging platform based on the Bitcoin protocol.
Exchange privately and securely messages and images. Become a miner and collect rewards or just a plebeian client and send messages without supporting the platform.
University of Thessaly

Table of Contents

About The Project

This project is inspired from Bitcoin: A Peer-to-Peer Electronic Cash System. A simplified version of the aformentioned paper, but with a message payload, was developed as part of an MSc Exercise for Introduction to Computer Security. We implemented the following:

  • Inspired from Bitcoin:
    • Proof of Work Algorithm, with fixed difficulty
    • Lite and Heavy Nodes
    • Transactions and Signatures
    • Peer Network, but simplified and fixed (for DEMO Purposes)
    • Incentive, Exchanging CPU time for Blabbers (Uncuffed currency)
    • Saving Disk Space, with lite nodes storing only a lite-hash, while miners store the full tree. (No implementation of the Merkle Tree)
    • Payment Verification and Value Splitting, using UTXOs
    • Privacy, by using the public key for communication purposes
  • Chat features:
    • Message and Image sharing, by attaching the message in the transactions payload
    • Encrypting communication over the blockchain asymmetric encryption
    • Web-based platform for easier demonstration
    • Expandable if necessary in the future to add more message types
    • Transfer of Wealth. The bigger the messages, the more Blabbers you'll need to transmit it.

Built with plenty of Python and pure 💖

Getting Started

Being the instructor, or just a random stranger, interested in this project is not easy. This is why we have created a quick Getting Started guide to help you try out this project.

Installation

  1. Download or Clone the repo

    git clone https://github.com/WckdAwe/Uncuffed.git
  2. Extract it on your desired location

  3. Create a Virtual Environment and install all Dependencies

    py -m venv venv
    pip install -r requirements.txt
  4. Start the project and enter a port

    py Uncuffed.py

    For demonstration purposes choose on of the ports inside data/node_list.json, ex. 5000, 5001 or 5002. The chosen port must be inside this node_list in order for the peers to communicate.

  5. Open a browser and navigate to home with the appropriate port, ex. http://127.0.0.1:5000/

You must repeat the process depending on the number of nodes you want to have in your system.

How does it work

We are going to deep dive on how the Uncuffed project works by explaining how generic blockchain projects work, and then seeing what we do slightly different.

What is a Blockchain

A blockchain is a list of a continuously ever-growing list of blocks, which are linked together using a cryptographic hash.

Each block contains a set of publicly viewable transactions which are stored permanently on the blockchain. Additionally, each block may also include some meta-data required for the calculations such as previous hashes, timestamps, difficulty, height etc.

All blockchain projects implement in one way or another the following characteristics:

  • Secure by Design: They are resistant to the modification of data, and become immutable when sufficient time passes as the blockchain stabilizes
  • Decentralized: Designed to work in Peer-to-Peer models, with no central point of failure
  • Permissionless: Originally, they are designed open for the world. No secrets. No access-control needed.

Uncuffed users

While using this project you will encounter two types of users/nodes, Clients and Miners.

Lite Nodes or Clients, can be used to send or receive messages in exchange for currency, Blabbers. When receiving Transactions and Blocks by other nodes they simply store information that they may deem necessary, and echo the Transaction or Block before they discard it. This way clients help to propagate incoming messages to other nodes.

Full Nodes or Miners, are more important to the network. These nodes store the whole blockchain, validate incoming transactions or blocks and spend a considerable amount of their CPU power and storage to sustain the network. As result, these nodes are also the ones awarded currency when they successfully validate and attach blocks to the blockchain. Miners can be considered the labor-force of the network.

Block Structure

The image contains a simplified and easier to understand block structure. The following characteristics remain the same between different blockchain projects.

  1. Every block is unique. Each block is identifiable by its unique hash or index.
  2. Every block follows a strict chronological order. To be validated each new block must have a timestamp higher than the previous one.
  3. Every block is linked with the previous one. Each block has a field containing the previous_block_hash. To be validated not only the index and timestamp must be higher than the previous block, but more importantly the previous_block_hash must be valid!
  4. Every block must contain at least one transaction.
  5. Every block must be validated by peers.

Proof-of-Work Algorithm

Proof of Work is the core mechanism that allows Uncuffed (and many other blockchain projects), to come to a consensus decentralized and agree on account balances, transactions, messages etc. It is a solution to a puzzle set by the blockchain to the miners. Solving this puzzle means a Miner can be allowed to append his block to the blockchain and be awarded for his contribution.

As soon as a new valid block is received in a Miner's blockchain he starts generating a new Proof of Work. The Miner uses the data from the previous block, usually the previous proof-of-work to solve the puzzle.

What is the puzzle you may ask? To generate a random set of characters, the proof of work, where the first X (where X is difficulty) characters must match a specific pattern. In the example above we can see a difficulty 4 puzzle, meaning the first 4 characters must match a specific pattern, in this case 1111.

This concept works fantastically because in order to generate those random characters, using the data from the previous block (in this case the previous proof), it may take many thousands or millions of calculations depending on the difficulty.

def verify_proof(prev_proof, proof, difficulty=2) -> bool:
    guess = f'{prev_proof}{proof}'.encode()
    guess_hash = SHA256.new(guess).hexdigest()
    return guess_hash[:difficulty] == "1" * difficulty

def proof_of_work(prev_proof: int, difficulty=2) -> int:
    proof = 0
    while verify_proof(prev_proof, proof, difficulty) is False:
        proof += 1

    return proof

To verify though that this proof is actually correct, we only need two variables; The previous proof and the proof a miner claims to have found.

Meaning, a Miner may take a huge amount of processing time in order to find a valid proof-of-work that solves the puzzle, but as soon as he does any miner or client can verify that proof with a single and fast calculation.

In our case the puzzle is solved with fixed difficulty of 2, which is quite easy to be fair. But easy is what we are looking for in order to update the user's chat faster.

Transactions

Usually, transactions signal the transfer of wealth from a user to another. This remains the case for Uncuffed, but with the additional payload of PLAINTEXT or ENCRYPTED messages.

Similarly to a block, each transaction is uniquely identifiable by its hash. This hash is generated using the transactions contents, such as the sender, receiver, value and timestamp.



UTXOs (Unspent Transaction Outputs)

The term UTXO refers to the amount of digital currency someone has left after executing a transaction.

Each single transaction entity contains two lists; Transaction Inputs and Transactions Outputs

The first one, Transaction Inputs, is easier to understand. It can be considered as a Pointer to a specific Transaction Output.

The Transacton Output stores the transfer of wealth, meaning it is a "coupon" saying that the X User has received Y amount of money. Each transaction output can be considered either SPENT or UNSPENT, aka UTXO (Unspent Transaction Output) or STXO (Spent Transaction Output).

The simplest way to demonstrate this is with an example.

UTXO Example

In a classical banking system, Vasilis may have 3.005.000 Euros, which were acquired by many years of hard work. That money is stored as a single variable, money, in a database of a centralized bank. If Vasilis wanted to transfer 3.000.000 Euros to Elon Musk he could just write a check of 3.000.000 Euros and immediately his bank account would update that money variable with his new balance.

In our decentralized banking system, this concept wouldn't be sustainable. As such lets consider we know the exact transactions where Vasilis got his 3.005.000 balance. Specifically Vasilis received as single transactions:

  • 2.000.000 from an Index Fund
  • 995.000 from his job
  • 10.000 from a friend

Now for Vasilis to send that amount of money to Elon Musk he would have to collect all these 'coupons' that say he has X amount of money (a.k.a Unspent Transaction Outputs) in a single list (Input List).

Now Vasilis wants to send 3.000.000 to Elon Musk, but he has 3.005.000 Euros. As such he creates a new list (Output List), where he sends 3.000.000 to Elon Musk and returns 5.000 to himself. The transaction is complete.

Although this might seem a complicated system, in actuality, this system allows every Miner to keep track of the UTXOs and quickly verify if a single transaction is valid or invalid without having to ask a central authority!

Validation

We spoke of validation many times, but what exactly do we validate and how?

Validations occur on each element of the Blockchain, from the Blockchain itself all the way to each single Transaction Input and Output.

We demonstrate the whole validation process starting from the whole Blockchain. If someone wanted to validate a single element presented here, all he would need to do is follow the graph and validate the ones right to it.

To be valid,

  • A Blockchain, must validate all each blocks
  • A Block:
    • Must have the correct ascending block order in the blockchain
    • Must have a valid hash
    • Must have at least one transaction_
    • Must follow a strictly chronological order with its timestamps
    • Must have a valid proof
    • Must have a valid miner reward, which is the sum of the transaction fees + mining reward. This transaction is called a Coinbase Transaction
  • Each Block's Transactions must be valid.
  • Each Transaction:
    • Must have a valid signature, signed by the sender to verify ownership
    • Must have valid transaction Inputs and Outputs, meaning you can't send more than you have
    • Must have a valid transaction fee going to a miner (0 or above)
  • Each Transaction Input must exist in a block and in order to be valid it must also exist in the UTXO list
  • Each Transaction Output must have a sender and a positive wealth exchange value

Message Payload

By reading everything above you must have by now at least some basic knowledge over how generic blockchains works and more importantly, how this blockchain works.

The last thing that we have to clarify about this project is how are these messages sent all over the network. Each message is inserted as a message payload inside a Transaction Output.

def __init__(self, recipient_address: str, value: int, message: Optional[AMessage]):
    self.recipient_address: str = recipient_address
    self.value: int = value
    self.message: Optional[AMessage] = message

The bigger the message, the more Blabbers you are going to need in order to transmit the message. This is done by the following simple calculation, which in essence Maximum between 1 and (message size in bits) / 64:

@staticmethod
def calculate_minimum_blabbers(message: AMessage) -> int:
    return max(1, int(get_deep_size(message) >> 6)

The message payload is the combination of an enumerator EMessageType and the actual string message message.

In this submitted version we support the following messages: Plain Text Message, Encrypted Message, Image Message and Encrypted Image Message. Each one of these has its own dedicated class.

The Plain Text Message simple attaches the user's message in the message variable.

The Encrypted Message encrypts using the RSA Algorithm (with ECB style) prior to attaching the user's message in the message variable. While this is not optimal for an actual blockchain, it is more than enough for this presentation.

The Image Message takes the uploaded image and converts it to a base64 string prior to sending the message, while the Encrypted Image does exactly the same thing but also uses the RSA Algorithm to encrypt it prior to sending it.

Upon receiving a message, a Client checks if the message is for him. If the message is plaintext it just stores it directly. In the case where the message is Encrypted, the client users his private key to decrypt the message and then stores it to his chat.

Peer Network (API)

The following URLs are used by the system in order to function. Most likely you are not going to mess with these. All the data transmitted are JSON serialized and encoded prior to any transmission.

/api/broadcasts/new_block
/api/broadcasts/new_transaction
/api/blockchain/
/api/blockchain/length
/api/blockchain/blocks
/api/transactions/pending
/api/transactions/UTXO
/api/nodes/list
/api/nodes/info
/api/nodes/register

Web Interface Routes

You are most likely going to encounter all of these urls while you are demoing this project.

/                   - GET: HOME
/selector           - GET/POST: Selection between Client or Miner
/chat               - POST: Send messages through the blockchain
/chat/{other_addr}/ - GET/POST: See and Send messages through he blockchain

All HTML templates used for the Web Interface are store inside Uncuffed/templates.

Storage Data Routes

All local data are stored inside the data folder. Looking inside that folder you are going to find the following.

/chats              - FOLDER: Contains all communications made between you and others
/chats/{id}.json    - FILE: Stores all communications between you and that address
/uploads            - FOLDER (UNUSED)
/blockchain.json    - FILE: Stores the whole blockchain
/node.json          - FILE: Stores node specific information, such as your UTXOs and STXOs
/node_list.json     - FILE: Stores all other nodes you are broadcasting messages to
/wallet.der         - FILE: Private key of your wallet

License

Distributed under the MIT License. See LICENSE.md for more information.

Authors

Disclaimer

All the information on this repository is provided in good faith, however we make no representation or warranty of any kind, express or implied, regarding the accuracy, adequacy, validity, reliability, availability or completeness of any information.

Acknowledgements

About

MSc Exercise for Introduction to Computer Security. A simulation of a blockchain messaging platform based on the Bitcoin protocol. Exchange privately and securely messages and images. Become a miner and collect rewards or just a plebeian client and send messages without supporting the platform.

Topics

Resources

License

Stars

Watchers

Forks