Skip to content

Commit

Permalink
Develop .seigr protocol: SeedDotSeigr and seigr_identity integration …
Browse files Browse the repository at this point in the history
…for secure lineage tracking

- Introduce protocol-aligned serialization format for .seigr files
- Integrate seigr_identity for senary-encoded unique IDs
- Expand SeedDotSeigr to support initial file creation and lineage tracking
- Update seigr_constants with 53,194 KB segment size target
- Develop replication, integrity, and rollback modules; functionality in progress
  • Loading branch information
sergism77 committed Nov 6, 2024
1 parent 3e61308 commit 569eacf
Show file tree
Hide file tree
Showing 26 changed files with 813 additions and 718 deletions.
135 changes: 16 additions & 119 deletions app.py
Original file line number Diff line number Diff line change
@@ -1,125 +1,22 @@
import sys
# app.py
from flask import Flask
from routes import identity_routes, ping_routes, cluster_routes, monitor_routes
from config import Config
import os
from flask import Flask, render_template, request, redirect, url_for, flash, send_file
import uuid
import logging

# Set up centralized logging to a file
LOG_FILE_PATH = os.path.join("logs", "dot_seigr.log")
os.makedirs("logs", exist_ok=True) # Ensure the logs directory exists

logging.basicConfig(
filename=LOG_FILE_PATH,
level=logging.DEBUG, # Set to DEBUG to capture all levels of log messages
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
filemode="a" # Append to log file
)

# Optionally set up logging to console for critical issues
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.ERROR) # Only show critical errors in console
formatter = logging.Formatter("%(name)s - %(levelname)s - %(message)s")
console_handler.setFormatter(formatter)
logging.getLogger().addHandler(console_handler)

# Set up logger
logger = logging.getLogger(__name__)

# Ensure the src directory is in the path
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'src'))

from dot_seigr.seigr_encoder import SeigrEncoder
from dot_seigr.seigr_decoder import SeigrDecoder

app = Flask(
__name__,
template_folder="src/templates",
static_folder="src/static"
)
app.secret_key = "supersecretkey"

# Configurations for uploads and file storage
app.config["UPLOAD_FOLDER"] = "uploads"
app.config["ENCODED_FOLDER"] = "encoded_files"
app.config["DECODED_FOLDER"] = "decoded_files"
os.makedirs(app.config["UPLOAD_FOLDER"], exist_ok=True)
os.makedirs(app.config["ENCODED_FOLDER"], exist_ok=True)
os.makedirs(app.config["DECODED_FOLDER"], exist_ok=True)

# Home route
@app.route("/")
def home():
return render_template("home.html")

# Encoding route
@app.route("/encode", methods=["GET", "POST"])
def encode():
if request.method == "POST":
uploaded_file = request.files.get("file")
if uploaded_file:
logger.info("File upload detected. Starting encoding process.")
file_id = str(uuid.uuid4())
file_path = os.path.join(app.config["UPLOAD_FOLDER"], f"{str(file_id)}_{uploaded_file.filename}")
uploaded_file.save(file_path)

try:
# Read and encode the file
with open(file_path, "rb") as f:
data = f.read()
encoder = SeigrEncoder(
data=data,
creator_id=file_id,
base_dir=app.config["ENCODED_FOLDER"],
original_filename=uploaded_file.filename
)
encoder.encode()
flash("File successfully encoded.", "success")
logger.info("Encoding process completed successfully.")
except Exception as e:
flash(f"Encoding failed: {e}", "error")
logger.error(f"Encoding process failed: {e}")
return redirect(url_for("home"))
else:
flash("No file detected for encoding.", "error")
logger.error("No file detected for encoding.")
return redirect(url_for("encode"))

# If request is GET, render the encode template
return render_template("encode.html")

# Decoding route
@app.route("/decode", methods=["GET", "POST"])
def decode():
if request.method == "POST":
seed_files = request.files.getlist("seed_files")
if seed_files:
seed_file_paths = []
for file in seed_files:
file_path = os.path.join(app.config["ENCODED_FOLDER"], file.filename)
file.save(file_path)
seed_file_paths.append(file.filename) # Pass filenames, not paths

try:
# Initialize decoder and perform decoding
decoder = SeigrDecoder(
cluster_files=seed_file_paths,
base_dir=app.config["ENCODED_FOLDER"]
)
decoded_file_path = decoder.decode()
import sys

if decoded_file_path:
flash("File successfully decoded.", "success")
return send_file(decoded_file_path, as_attachment=True)
else:
flash("Decoding failed: no data was decoded.", "error")
return redirect(url_for("decode"))
# Ensure `src` is added to the system path
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), 'src')))

except Exception as e:
flash(f"Decoding failed: {e}", "error")
logger.error(f"Decoding process failed: {e}")
return redirect(url_for("decode"))
# Initialize Flask app
app = Flask(__name__)
app.config.from_object(Config)

return render_template("decode.html")
# Register blueprints from each modular route
app.register_blueprint(identity_routes.bp)
app.register_blueprint(ping_routes.bp)
app.register_blueprint(cluster_routes.bp)
app.register_blueprint(monitor_routes.bp)

if __name__ == "__main__":
if __name__ == '__main__':
app.run(debug=True)
15 changes: 15 additions & 0 deletions config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# config.py
import os

class Config:
SECRET_KEY = os.environ.get("SECRET_KEY", "your_secret_key")
SEIGR_DIRECTORY = os.path.expanduser("~/.seigr")
SEIGR_ID_PATH = os.path.join(SEIGR_DIRECTORY, "seigr_id.json")
LOG_DIRECTORY = os.path.join(SEIGR_DIRECTORY, "logs")
PING_LOG_PATH = os.path.join(SEIGR_DIRECTORY, "ping_logs.json")
CLUSTER_DIRECTORY = os.path.join(SEIGR_DIRECTORY, "seed_clusters")
UPLOAD_FOLDER = os.path.join(SEIGR_DIRECTORY, "uploads")
os.makedirs(SEIGR_DIRECTORY, exist_ok=True)
os.makedirs(LOG_DIRECTORY, exist_ok=True)
os.makedirs(CLUSTER_DIRECTORY, exist_ok=True)
os.makedirs(UPLOAD_FOLDER, exist_ok=True)
9 changes: 7 additions & 2 deletions project_tree.txt
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,14 @@
│   │   ├── decoder.py
│   │   ├── encoder.py
│   │   ├── interpreter.py
│   │   ├── lineage.proto
│   │   ├── lineage_pb2.py
│   │   ├── manager.py
│   │   ├── metadata.py
│   │   └── seed_dot_seigr.proto
│   │   ├── seed_dot_seigr.proto
│   │   └── seed_dot_seigr_pb2.py
│   ├── identity
│   │   └── seigr_identity.py
│   ├── static
│   │   ├── css
│   │   │   └── style.css
Expand All @@ -61,4 +66,4 @@
│   └── home.html
└── uploads

15 directories, 47 files
16 directories, 51 files
Empty file added routes/__init__.py
Empty file.
29 changes: 29 additions & 0 deletions routes/cluster_routes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# routes/cluster_routes.py
from flask import Blueprint, jsonify, request
from src.dot_seigr.dot_seigr import DotSeigr
from src.dot_seigr.seed_dot_seigr import SeedDotSeigr
from config import Config
import os

bp = Blueprint('cluster_routes', __name__)

@bp.route('/create_seed_cluster', methods=['POST'])
def create_seed_cluster():
"""Creates a root cluster using SeedDotSeigr and saves metadata."""
initial_hash = "root_hash" # Placeholder root hash
seed = SeedDotSeigr(initial_hash)
seed_path = seed.save_to_disk(Config.CLUSTER_DIRECTORY)
return jsonify({"status": "seed_cluster_created", "path": seed_path})

@bp.route('/encode_data', methods=['POST'])
def encode_data():
"""Encodes data and stores it as .seigr files in clusters."""
data = request.data # Assumes binary data sent via POST
creator_id = "user_creator_id" # Placeholder creator ID
base_dir = Config.CLUSTER_DIRECTORY
dot_seigr = DotSeigr(data, creator_id, base_dir, original_filename="uploaded_data")

# Process segmentation and encoding
seed = SeedDotSeigr("root_hash")
updated_seed = dot_seigr.create_segmented_seigr_files(base_dir, seed)
return jsonify({"status": "data_encoded", "seed_path": updated_seed})
61 changes: 61 additions & 0 deletions routes/identity_routes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# routes/identity_routes.py
from flask import Blueprint, jsonify, request
from src.identity.seigr_identity import SeigrIdentity
from config import Config
import os
import json
import logging

bp = Blueprint('identity_routes', __name__)
logger = logging.getLogger(__name__)

@bp.route('/create_seigr_id', methods=['POST'])
def create_seigr_id():
"""Generates a new Seigr ID and saves it securely in the user's local .seigr directory."""
try:
data = request.get_json()
password = data.get("password")

if not password:
return jsonify({"error": "Password is required to create Seigr ID"}), 400

seigr_identity = SeigrIdentity()
seigr_id = seigr_identity.generate_seigr_id()
seigr_identity.set_encryption_key(password=password)

# Define the path to save the Seigr ID
if not os.path.exists(Config.SEIGR_ID_DIRECTORY):
os.makedirs(Config.SEIGR_ID_DIRECTORY)
seigr_id_path = os.path.join(Config.SEIGR_ID_DIRECTORY, "seigr_id.json")

seigr_identity.save_to_external(seigr_id_path)

logger.info("Seigr ID created and saved successfully.")
return jsonify({"status": "success", "seigr_id": seigr_id})
except Exception as e:
logger.error(f"Failed to create Seigr ID: {e}")
return jsonify({"error": "Failed to create Seigr ID"}), 500

@bp.route('/get_seigr_id', methods=['POST'])
def get_seigr_id():
"""Retrieves and decrypts the Seigr ID from the local storage if available."""
try:
data = request.get_json()
password = data.get("password")

if not password:
return jsonify({"error": "Password is required to retrieve Seigr ID"}), 400

seigr_identity = SeigrIdentity()
seigr_id_path = os.path.join(Config.SEIGR_ID_DIRECTORY, "seigr_id.json")

if os.path.exists(seigr_id_path):
if seigr_identity.load_from_external(seigr_id_path, password=password):
return jsonify({"status": "success", "seigr_id": seigr_identity.senary_id})
else:
return jsonify({"error": "Failed to decrypt Seigr ID. Check your password."}), 403
else:
return jsonify({"error": "Seigr ID not found"}), 404
except Exception as e:
logger.error(f"Failed to retrieve Seigr ID: {e}")
return jsonify({"error": "Failed to retrieve Seigr ID"}), 500
18 changes: 18 additions & 0 deletions routes/monitor_routes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# routes/monitor_routes.py
from flask import Blueprint, jsonify
import os
import json
from config import Config

bp = Blueprint('monitor_routes', __name__)

@bp.route('/get_activity_log', methods=['GET'])
def get_activity_log():
"""Returns the ping activity log for the Seigr ID."""
if not os.path.exists(Config.PING_LOG_PATH):
return jsonify({"error": "No activity log found"}), 404

with open(Config.PING_LOG_PATH, 'r') as f:
logs = [json.loads(line) for line in f.readlines()]

return jsonify({"activity_log": logs})
19 changes: 19 additions & 0 deletions routes/ping_routes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# routes/ping_routes.py
from flask import Blueprint, jsonify
from datetime import datetime
import json
from config import Config

bp = Blueprint('ping_routes', __name__)

@bp.route('/ping', methods=['POST'])
def ping():
"""Records a network ping for the Seigr ID, logging the timestamp."""
timestamp = datetime.now().isoformat()
ping_entry = {"timestamp": timestamp}

# Append the new ping to the log file
with open(Config.PING_LOG_PATH, 'a') as f:
f.write(json.dumps(ping_entry) + "\n")

return jsonify({"status": "pinged", "timestamp": timestamp})
52 changes: 52 additions & 0 deletions src/crypto/encoding_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# src/crypto/encoding_utils.py
import logging

logger = logging.getLogger(__name__)

def encode_to_senary(binary_data: bytes) -> str:
"""Encodes binary data to a senary-encoded string."""
senary_str = ""
previous_value = 1 # Presumably used as an integer seed for transformations

for i, byte in enumerate(binary_data):
transformed_byte = _substitution_permutation(byte + previous_value, i)
previous_value = transformed_byte
base6_encoded = _base6_encode(transformed_byte)
logger.debug(f"base6_encoded (should be str): {base6_encoded}, type: {type(base6_encoded)}")
senary_str += base6_encoded # _base6_encode should return a string

logger.debug("Encoded data to senary format.")
return senary_str

def decode_from_senary(senary_str: str) -> bytes:
"""Decodes a senary (base-6) encoded string back to binary data."""
binary_data = bytearray()
previous_value = 1
for i in range(0, len(senary_str), 2):
byte = _base6_decode(senary_str[i:i + 2])
reversed_byte = _reverse_substitution_permutation(byte, previous_value, i // 2)
binary_data.append(reversed_byte)
previous_value = byte
logger.debug("Decoded senary data to binary format.")
return bytes(binary_data)

# Helper functions
def _substitution_permutation(value: int, position: int) -> int:
substituted = (value ^ (position * 17 + 23)) & 0xFF
rotated = ((substituted << 3) & 0xFF) | (substituted >> 5)
return rotated

def _reverse_substitution_permutation(value: int, prev_val: int, position: int) -> int:
rotated = ((value >> 3) & 0x1F) | ((value & 0x1F) << 5)
substituted = (rotated ^ (position * 17 + 23)) & 0xFF
return (substituted - prev_val) & 0xFF

def _base6_encode(byte: int) -> str:
senary = [str((byte // 6**i) % 6) for i in range((byte.bit_length() + 1) // 3 + 1)]
return ''.join(reversed(senary)).zfill(2)

def _base6_decode(senary_str: str) -> int:
byte = 0
for char in senary_str:
byte = byte * 6 + int(char)
return byte
Loading

0 comments on commit 569eacf

Please sign in to comment.