Zero-config network request obfuscation middleware for Flask - protect your APIs from reverse engineering
Project description
rossetta-flask
Zero-config network request obfuscation middleware for Flask
Features
- 🔒 Automatic endpoint obfuscation - API endpoints are hashed and unreadable
- 🔐 Request/response encryption - AES-256-CBC encryption for all data
- ✅ Session-based key management - No hardcoded secrets in frontend
- 🛡️ Anti-replay protection - Timestamp validation prevents replay attacks
- 📝 Request signatures - HMAC-SHA256 ensures request integrity
- 🎯 Zero-config setup - Works out of the box with minimal code
Installation
pip install rossetta-flask
Quick Start
from flask import Flask
from rossetta_flask import RossettaFlask
app = Flask(__name__)
app.secret_key = 'your-secret-key-here' # Required for Flask sessions
# Initialize Rossetta middleware
rossetta = RossettaFlask(app)
# Define your routes normally
@app.route('/api/users')
def get_users():
return {"users": []}
if __name__ == '__main__':
app.run(debug=True)
That's it! All API endpoints are now automatically obfuscated and encrypted.
Usage
Basic Setup
from flask import Flask
from rossetta_flask import RossettaFlask
app = Flask(__name__)
app.secret_key = 'your-super-secret-key-change-this'
# Initialize with default settings
rossetta = RossettaFlask(app)
# Or with custom settings
rossetta = RossettaFlask(
app,
secret='your-rossetta-secret', # Optional
timestamp_window=300000 # 5 minutes (default)
)
Encrypting Responses
Method 1: Using the protected_route decorator
from flask import Flask
from rossetta_flask import RossettaFlask, protected_route
app = Flask(__name__)
app.secret_key = 'your-secret-key'
rossetta = RossettaFlask(app)
@app.route('/api/data')
@protected_route
def get_data():
# Simply return a dict - it will be automatically encrypted
return {"message": "Hello, World!"}
Method 2: Using the encrypt_response helper
from flask import request
from rossetta_flask import RossettaFlask, encrypt_response
app = Flask(__name__)
app.secret_key = 'your-secret-key'
rossetta = RossettaFlask(app)
@app.route('/api/data')
def get_data():
data = {"message": "Hello, World!"}
return encrypt_response(data)
Method 3: Manual encryption using request context
from flask import request, Response
@app.route('/api/data')
def get_data():
data = {"message": "Hello, World!"}
session_key = request.rossetta['session_key']
# Encrypt manually
timestamp = int(time.time() * 1000)
response_payload = {'data': data, 'timestamp': timestamp}
encrypted = request.rossetta['encrypt'](response_payload)
return Response(encrypted, mimetype='text/plain')
Accessing Decrypted Request Data
from flask import request
from rossetta_flask import RossettaFlask, encrypt_response
app = Flask(__name__)
app.secret_key = 'your-secret-key'
rossetta = RossettaFlask(app)
@app.post('/api/create')
def create_item():
# Decrypted data is automatically available in request.decrypted_data
data = request.decrypted_data
name = data.get('name')
result = {"id": 1, "name": name, "created": True}
return encrypt_response(result)
Session Initialization Endpoint
The session initialization endpoint is automatically created at /api/init-session:
# This endpoint is automatically available when you initialize RossettaFlask
# It returns the session keys needed by the client
# Client-side usage:
# POST /api/init-session
# Response: {"sessionKey": "...", "endpointSalt": "..."}
How It Works
- Session Initialization: Client requests session keys from
/api/init-session - Key Generation: Server generates unique encryption keys per session
- Endpoint Obfuscation: All endpoints are hashed using SHA-256 with salt
- Request Encryption: Client encrypts requests with session key
- Server Decryption: Middleware automatically decrypts and validates
- Response Encryption: Responses are encrypted before sending
Security Features
- No Hardcoded Secrets: Keys are generated per session
- Perfect Forward Secrecy: Each session has unique keys
- Replay Attack Prevention: Timestamp-based validation (5-minute window)
- Request Integrity: HMAC-SHA256 signatures prevent tampering
- Endpoint Obfuscation: API structure hidden from inspection
- AES-256-CBC: Industry-standard encryption algorithm
⚠️ Production Deployment
IMPORTANT: This package provides obfuscation and encryption at the application layer. For production use, you MUST also implement:
Required for Production:
-
HTTPS/TLS: Always use HTTPS in production
- Obfuscation is NOT a replacement for TLS
- Use valid SSL/TLS certificates (Let's Encrypt, etc.)
- Configure HSTS headers
- Redirect all HTTP traffic to HTTPS
-
Environment Variables: Never hardcode secrets
import os app.secret_key = os.environ.get('FLASK_SECRET_KEY') rossetta = RossettaFlask( app, secret=os.environ.get('ROSSETTA_SECRET_KEY') )
-
Rate Limiting: Add rate limiting middleware
from flask_limiter import Limiter from flask_limiter.util import get_remote_address limiter = Limiter( app=app, key_func=get_remote_address, default_limits=["200 per day", "50 per hour"] )
-
Authentication & Authorization: Add proper auth layer
- This package only handles obfuscation
- Implement JWT, OAuth, or session-based auth
- Use Flask-Login, Flask-JWT-Extended, or similar
-
CORS Configuration: Restrict allowed origins
from flask_cors import CORS CORS(app, origins=['https://yourdomain.com'])
-
Database Security: Use SQLAlchemy or other ORMs
- Parameterized queries prevent SQL injection
- Never use string formatting for queries
-
Input Validation: Validate all user inputs
from marshmallow import Schema, fields, validate class UserSchema(Schema): name = fields.Str(required=True, validate=validate.Length(min=1, max=100)) email = fields.Email(required=True)
-
Security Headers: Use Flask-Talisman
from flask_talisman import Talisman Talisman(app, content_security_policy=None)
-
Logging & Monitoring: Track security events
import logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__)
-
Key Rotation: Implement regular secret rotation
- Rotate ROSSETTA_SECRET_KEY periodically
- Rotate FLASK_SECRET_KEY periodically
- Use versioned secrets management
Recommended Security Stack:
[Client] → HTTPS/TLS → [Rate Limiter] → [Auth Middleware] → [Rossetta Middleware] → [Your API]
Production Checklist:
- HTTPS/TLS enabled with valid certificates
- All secrets in environment variables
- Rate limiting configured
- Authentication/authorization implemented
- CORS properly configured
- Security headers set (CSP, HSTS, etc.)
- Input validation on all endpoints
- SQL injection protection (use ORM)
- Logging and monitoring enabled
- Error handling doesn't leak information
- Debug mode disabled (
debug=False) - Session configuration secure (
SESSION_COOKIE_SECURE=True)
Environment Variables
# Flask session secret (required)
FLASK_SECRET_KEY=your-flask-secret-key-min-32-chars
# Rossetta encryption secret (optional, auto-generated if not provided)
ROSSETTA_SECRET_KEY=your-rossetta-secret-key-min-32-chars
API Reference
RossettaFlask
Main middleware class.
Constructor Parameters:
app(Flask, optional): Flask application instancesecret(str, optional): Secret key for encryption (auto-generated if not provided)timestamp_window(int, optional): Request validity window in milliseconds (default: 300000)
Methods:
init_app(app): Initialize the Flask application with middleware
Request Context
After middleware processing, the following are available:
request.rossetta dictionary:
session_key(str): Current session encryption keyendpoint_salt(str): Salt for endpoint obfuscationobfuscate_endpoint(name)(function): Function to obfuscate endpointsencrypt(data)(function): Function to encrypt datadecrypt(data)(function): Function to decrypt data
request.decrypted_data (dict): Decrypted request payload (for POST/PUT/DELETE)
Helper Functions
encrypt_response(data)
Encrypts response data and returns a Flask Response object.
Parameters:
data(dict): Data to encrypt
Returns: Flask Response object with encrypted data
@protected_route
Decorator for routes that automatically encrypt responses.
Usage:
@app.route('/api/data')
@protected_route
def get_data():
return {"message": "Hello"}
Complete Example
from flask import Flask, request
from rossetta_flask import RossettaFlask, encrypt_response, protected_route
import os
# Create Flask app
app = Flask(__name__)
app.secret_key = os.environ.get('FLASK_SECRET_KEY', 'dev-secret-change-in-production')
# Initialize Rossetta middleware
rossetta = RossettaFlask(
app,
secret=os.environ.get('ROSSETTA_SECRET_KEY'),
timestamp_window=300000 # 5 minutes
)
# Session initialization is automatically available at /api/init-session
# Example: List endpoint with decorator
@app.route('/api/todos', methods=['GET'])
@protected_route
def list_todos():
todos = [
{"id": 1, "text": "Learn Rossetta API", "completed": False},
{"id": 2, "text": "Build secure app", "completed": False}
]
return todos # Automatically encrypted
# Example: Create endpoint with manual encryption
@app.route('/api/todos', methods=['POST'])
def create_todo():
# Access decrypted data
data = request.decrypted_data
todo = {
"id": 3,
"text": data['text'],
"completed": False
}
# Encrypt and return response
return encrypt_response(todo)
# Example: Update endpoint
@app.route('/api/todos/<int:todo_id>', methods=['PUT'])
@protected_route
def update_todo(todo_id):
data = request.decrypted_data
return {
"id": todo_id,
"text": data.get('text'),
"completed": data.get('completed', False)
}
# Example: Delete endpoint
@app.route('/api/todos/<int:todo_id>', methods=['DELETE'])
@protected_route
def delete_todo(todo_id):
return {"deleted": True, "id": todo_id}
if __name__ == '__main__':
# Production: Use a production WSGI server like gunicorn
# gunicorn -w 4 -b 0.0.0.0:5000 app:app
app.run(debug=False, host='0.0.0.0', port=5000)
Client Integration
Use the @rossetta-api/client package for frontend integration:
import RossettaClient from '@rossetta-api/client';
const api = new RossettaClient('http://localhost:5000');
// Automatically encrypted requests
const todos = await api.get('/api/todos');
const newTodo = await api.post('/api/todos', { text: 'Buy milk' });
Troubleshooting
"Session key not found" error
- Make sure Flask sessions are enabled with
app.secret_key - Check that cookies are enabled in the client
"Invalid signature" error
- Verify timestamp synchronization between client and server
- Check that the session hasn't expired
"Request expired" error
- Adjust
timestamp_windowif needed - Ensure client and server clocks are synchronized
CORS issues
- Install and configure Flask-CORS
- Add proper CORS headers for cross-origin requests
Testing
# test_app.py
import pytest
from flask import Flask
from rossetta_flask import RossettaFlask
@pytest.fixture
def app():
app = Flask(__name__)
app.secret_key = 'test-secret-key'
rossetta = RossettaFlask(app)
@app.route('/api/test')
def test_route():
return {"message": "test"}
return app
@pytest.fixture
def client(app):
return app.test_client()
def test_session_init(client):
response = client.post('/api/init-session')
assert response.status_code == 200
data = response.get_json()
assert 'sessionKey' in data
assert 'endpointSalt' in data
Performance Considerations
- Encryption adds ~1-5ms latency per request
- Session keys are stored in Flask sessions (consider Redis for production)
- Use connection pooling for database queries
- Consider caching frequently accessed data
Compatibility
- Python: 3.8+
- Flask: 2.3.2+
- Tested with:
- Flask 2.3, 3.0
- Python 3.8, 3.9, 3.10, 3.11, 3.12
License
MIT
Support
- Issues: https://github.com/yiheinchai/rossetta-api/issues
- Documentation: https://github.com/yiheinchai/rossetta-api
- Source Code: https://github.com/yiheinchai/rossetta-api/tree/main/packages/rossetta-flask
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Related Packages
- @rossetta-api/express - Express.js middleware
- @rossetta-api/client - Universal client for browser and Node.js
- rossetta-fastapi - FastAPI middleware
Acknowledgments
Built with security in mind, inspired by the need for better API protection in modern web applications.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file rossetta_flask-0.1.0.tar.gz.
File metadata
- Download URL: rossetta_flask-0.1.0.tar.gz
- Upload date:
- Size: 10.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5ed1dc460ce99740477e6bcc99a7d8f652d9dfa0fd428a174bed10d5cde93d82
|
|
| MD5 |
73514e7ca70bc1fbd435e0d9fa8fe341
|
|
| BLAKE2b-256 |
cc9c46685a4d16dfc71d933ef0ae5f6dbb064f3cf4be3d520eba16ec593ffc5d
|
File details
Details for the file rossetta_flask-0.1.0-py3-none-any.whl.
File metadata
- Download URL: rossetta_flask-0.1.0-py3-none-any.whl
- Upload date:
- Size: 10.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b3d46c8375591fab29025da2713be5a881d5140b176518e4d2229ad3ec822cef
|
|
| MD5 |
0364553f820d91c792e50fce6925d23e
|
|
| BLAKE2b-256 |
77caf67fd5cf04c700b447cbe8cf5236324d931302e514f4d0253a0c722b27b1
|