Skip to content

Commit

Permalink
Merge pull request #5 from ggleszczynski/features/starting
Browse files Browse the repository at this point in the history
Initial commit
  • Loading branch information
ppolewicz authored Oct 29, 2024
2 parents 69f826b + 708f88b commit ff8cb47
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 28 deletions.
34 changes: 31 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@

## Overview

`bt-ddos-shield` is a Python package designed to address the critical issue of Distributed Denial-of-Service (DDoS) attacks in bittensor ecosystem. The project leverages encryption to protect communication between miners and validators, ensuring the IPs and ports of these nodes remain secure and hidden from malicious actors. This decentralized solution aims to eliminate the financial burden caused by traditional DDoS protection methods like WAF and Cloudflare, which are often costly and impractical for subnets handling large volumes of data.
`bt-ddos-shield` is a Python package designed to address the critical issue of Distributed Denial-of-Service (DDoS) attacks
in bittensor ecosystem. The project leverages encryption to protect communication between miners and validators, ensuring
the IPs and ports of these nodes remain secure and hidden from malicious actors. This decentralized solution aims to eliminate
the financial burden caused by traditional DDoS protection methods like WAF and Cloudflare, which are often costly and
impractical for subnets handling large volumes of data.

## Project Goals

Expand All @@ -23,8 +27,32 @@ The goal of this project is to implement a distributed and decentralized system
- Prevents IP address exposure by sharing encrypted connection data through a decentralized network of subtensors.

3. **Secure Message Exchange**:
- Validators can request the connection information of miners from the subtensor network. This information is validated and decrypted locally using the validator's private key.

- Validators can request the connection information of miners from the subtensor network. This information is validated and
decrypted locally using the validator's private key.

## Communication Flow

<!--
@startuml ./assets/diagrams/CommunicationFlow
participant Validator
participant Miner
participant GitHub
participant Storage
participant Bittensor
Validator -> Validator: Generate Validator key-pair
Validator -> GitHub: Publish public key along with HotKey
GitHub -> Miner: Fetch Validator info
Miner -> Miner: Encrypt Miner IP/Domain with Validator public key
Miner -> Storage: Add/update file with encrypted IPs/Domains for Validators
Miner -> Bittensor: Publish file location
Bittensor -> Validator: Fetch file location
Storage -> Validator: Fetch Miner file
Validator -> Validator: Decrypt Miner file entry encrypted for given Validator
Validator -> Miner: Send request using decrypted Miner IP/Domain
@enduml
-->

![](./assets/diagrams/CommunicationFlow.svg)

## Installation
```
Expand Down
29 changes: 29 additions & 0 deletions assets/diagrams/CommunicationFlow.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 8 additions & 8 deletions bt_ddos_shield/encryption.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,18 @@ class DecryptionError(Exception):


class EncryptionManager:
def __init__(self):
pass

@staticmethod
def encrypt_data(
self, public_key: str, data: dict, encoding: str = "utf-8"
public_key: str, data: dict, encoding: str = "utf-8"
) -> bytes:
"""
Encrypts the given data as a dictionary using the provided public key.
Args:
public_key (str): The public key in string format that will be used to encrypt the data.
data (dict): The data to be encrypted, represented as a dictionary.
encoding (str): Encoding format for the string representation of the data (default: 'utf-8).
encoding (str): Encoding format for the string representation of the data (default: 'utf-8').
Returns:
bytes: The encrypted data in bytes format.
Expand All @@ -41,16 +40,17 @@ def encrypt_data(
except Exception as e:
raise EncryptionError(f"Encryption failed: {e}")

@staticmethod
def decrypt_data(
self, private_key: str, encrypted_data: bytes, encoding: str = "utf-8"
private_key: str, encrypted_data: bytes, encoding: str = "utf-8"
) -> dict:
"""
Decrypts the given encrypted data using the provided private key.
Args:
private_key (str): The private key in string format used for decription.
private_key (str): The private key in string format used for decryption.
encrypted_data (bytes): The encrypted data to be decrypted.
encoding (str): Encoding format for the string representation of the data (default: 'utf-8).
encoding (str): Encoding format for the string representation of the data (default: 'utf-8').
Returns:
dict: The decrypted data, converted back to a dictionary.
Expand All @@ -67,4 +67,4 @@ def decrypt_data(
decrypted_dict = json.loads(decrypted_str)
return decrypted_dict
except Exception as e:
raise DecryptionError(f"Decrption failed: {e}")
raise DecryptionError(f"Decryption failed: {e}")
34 changes: 17 additions & 17 deletions tests/test_encryption.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
invalid_string_data = "invalid_data"

# Pre-encrypt valid data for decryption tests.
pre_encrypted_data = EncryptionManager().encrypt_data(
pre_encrypted_data = EncryptionManager.encrypt_data(
public_key=public_key, data=valid_test_data
)

Expand All @@ -40,7 +40,7 @@ def test_encrypt_data_valid(self):
Test encryption with valid public key and data.
Ensures the returned encrypted data is of bytes type.
"""
encrypted_data = EncryptionManager().encrypt_data(
encrypted_data = EncryptionManager.encrypt_data(
public_key=public_key, data=valid_test_data
)
assert isinstance(
Expand All @@ -49,11 +49,11 @@ def test_encrypt_data_valid(self):

def test_encrypt_data_invalid_public_key(self):
"""
Test encryption with an invalid public key (string that doens't represent a valid key).
Test encryption with an invalid public key (string that doesn't represent a valid key).
Expects EncryptionError to be raised.
"""
with pytest.raises(EncryptionError):
EncryptionManager().encrypt_data(
EncryptionManager.encrypt_data(
public_key=invalid_string_data, data=valid_test_data
)

Expand All @@ -63,17 +63,17 @@ def test_encrypt_data_invalid_data_type(self):
Expects TypeError to be raised.
"""
with pytest.raises(TypeError):
EncryptionManager().encrypt_data(
EncryptionManager.encrypt_data(
public_key=public_key, data=invalid_string_data
)

def test_encrypt_data_invalid_public_key_type(self):
"""
Test encryption with a public key of invalid type (e.g., integer).
Exepcts TypeError to be raised.
Expects TypeError to be raised.
"""
with pytest.raises(TypeError):
EncryptionManager().encrypt_data(
EncryptionManager.encrypt_data(
public_key=invalid_key_type, data=valid_test_data
)

Expand All @@ -82,7 +82,7 @@ def test_encrypt_data_empty_data(self):
Test encryption with an empty dictionary.
Expects encryption to succeed and return data of type bytes.
"""
encrypted_empty_data = EncryptionManager().encrypt_data(
encrypted_empty_data = EncryptionManager.encrypt_data(
public_key=public_key, data=empty_data_dict
)
assert isinstance(
Expand All @@ -94,7 +94,7 @@ def test_decrypt_data_valid(self):
Test decryption with valid private key and encrypted data.
Ensures that the decrypted data matches the original dictionary.
"""
decrypted_data = EncryptionManager().decrypt_data(
decrypted_data = EncryptionManager.decrypt_data(
private_key=private_key, encrypted_data=pre_encrypted_data
)
assert isinstance(decrypted_data, dict), "Decrypted data should be of type dict"
Expand All @@ -107,10 +107,10 @@ def test_decrypt_data_empty_data(self):
Test decryption with an empty dictionary.
Expects that the decrypted data matches the original dictionary.
"""
encrypted_empty_data = EncryptionManager().encrypt_data(
encrypted_empty_data = EncryptionManager.encrypt_data(
public_key=public_key, data=empty_data_dict
)
decrypted_data = EncryptionManager().decrypt_data(
decrypted_data = EncryptionManager.decrypt_data(
private_key=private_key, encrypted_data=encrypted_empty_data
)
assert isinstance(decrypted_data, dict), "Decrypted data should be of type dict"
Expand All @@ -120,11 +120,11 @@ def test_decrypt_data_empty_data(self):

def test_decrypt_data_invalid_private_key(self):
"""
Test decryption with an invalid private key (string that doesn't represnet a valid key).
Test decryption with an invalid private key (string that doesn't represent a valid key).
Expects DecryptionError to be raised.
"""
with pytest.raises(DecryptionError):
EncryptionManager().decrypt_data(
EncryptionManager.decrypt_data(
private_key=invalid_string_data, encrypted_data=pre_encrypted_data
)

Expand All @@ -134,7 +134,7 @@ def test_decrypt_data_invalid_encrypted_data(self):
Expects DecryptionError to be raised.
"""
with pytest.raises(DecryptionError):
EncryptionManager().decrypt_data(
EncryptionManager.decrypt_data(
private_key=private_key, encrypted_data=non_encrypted_bytes
)

Expand All @@ -144,7 +144,7 @@ def test_decrypt_data_invalid_private_key_type(self):
Expects TypeError to be raised.
"""
with pytest.raises(TypeError):
EncryptionManager().decrypt_data(
EncryptionManager.decrypt_data(
private_key=invalid_key_type, encrypted_data=pre_encrypted_data
)

Expand All @@ -154,7 +154,7 @@ def test_decrypt_data_invalid_encrypted_data_type(self):
Expects TypeError to be raised.
"""
with pytest.raises(TypeError):
EncryptionManager().decrypt_data(
EncryptionManager.decrypt_data(
private_key=private_key, encrypted_data=invalid_key_type
)

Expand All @@ -164,6 +164,6 @@ def test_decrypt_data_empty_encrypted_data(self):
Expects DecryptionError to be raised.
"""
with pytest.raises(DecryptionError):
EncryptionManager().decrypt_data(
EncryptionManager.decrypt_data(
private_key=private_key, encrypted_data=empty_byte
)

0 comments on commit ff8cb47

Please sign in to comment.