Skip to content

Latest commit

Β 

History

History
690 lines (568 loc) Β· 17 KB

File metadata and controls

690 lines (568 loc) Β· 17 KB

Privacy-RIP (PRIP) API Reference

πŸš€ Overview

Privacy-RIP provides both client-side JavaScript APIs and server-side Python APIs for browser fingerprinting research. This document covers all available endpoints, configuration options, and integration methods.

πŸ“‘ Server API Endpoints

Core Endpoints

GET /

Description: Main research interface
Purpose: Serves the interactive PRIP testing environment

Response:

<!-- Interactive HTML interface with real-time monitoring -->

Example:

curl http://localhost:5000/

GET /reconnect_user

Description: User reconnection endpoint
Purpose: Handles storage consistency validation and user tracking

Parameters:

  • u (int): User ID code indicating storage availability
  • d (int): Device ID code indicating storage availability

Response:

{
    "message": "User reconnection processed",
    "timestamp": "2025-05-30T10:30:00Z",
    "uid_code": 7,
    "did_code": 7
}

Example:

curl "http://localhost:5000/reconnect_user?u=7&d=7"

UID/DID Code Values:

  • 0: No storage available
  • 1: Only cookies available
  • 2: Only localStorage available
  • 3: Cookies + localStorage available
  • 4: Only sessionStorage available
  • 5: Cookies + sessionStorage available
  • 6: localStorage + sessionStorage available
  • 7: All storage types available

POST /test

Description: Generate test data
Purpose: Creates sample fingerprinting data for testing

Response:

{
    "status": "success",
    "test_data_generated": true,
    "timestamp": "2025-05-30T10:30:00Z",
    "sample_fingerprint": {
        "visitor_id": "abc123def456",
        "user_agent": "Mozilla/5.0...",
        "screen_resolution": [1920, 1080]
    }
}

Example:

curl -X POST http://localhost:5000/test

POST /clear_data

Description: Clear collected data
Purpose: Removes all stored research data

Response:

{
    "status": "success",
    "message": "All data cleared",
    "timestamp": "2025-05-30T10:30:00Z"
}

Example:

curl -X POST http://localhost:5000/clear_data

Data Processing Endpoints

POST /api/data

Description: Process PRIP fingerprint data
Purpose: Accepts and processes browser fingerprinting data

Request Body:

{
    "cookies": {
        "data_a": "eyJ0eXAiOiJKV1QiLCJhbGc...",
        "data_b": "iOiJIUzI1NiIsInR5cCI6Ik...",
        "PRIP_USERID": "123456789012",
        "PRIP_USERDEVICE": "987654321098"
    }
}

Response:

{
    "status": "success",
    "processed": true,
    "user_id": "123456789012",
    "device_id": "987654321098",
    "fingerprint_confidence": 0.95
}

Example:

import requests

data = {
    "cookies": {
        "data_a": "base64_encoded_data...",
        "PRIP_USERID": "123456789012"
    }
}

response = requests.post("http://localhost:5000/api/data", json=data)
print(response.json())

πŸŽ›οΈ JavaScript Client API

PrivacyRipper Class

Constructor

const prip = new PrivacyRipper(options);

Options:

{
    endpoint: '/reconnect_user',        // Server endpoint URL
    debug: false,                       // Enable debug logging
    autoInit: true,                     // Automatically initialize
    userDeviceLength: 12,               // Device ID length
    userIdLength: 12,                   // User ID length
    reconnectMethod: 'GET',             // HTTP method for reconnection
    cookiePrefix: 'data_',              // Prefix for data cookies
    storagePrefix: 'PRIP_'              // Prefix for storage keys
}

Methods

generateDeviceId()

Description: Generate unique device identifier
Returns: String (device ID)

const deviceId = prip.generateDeviceId();
console.log(deviceId); // "123456789012"
generateUserId()

Description: Generate unique user identifier
Returns: String (user ID)

const userId = prip.generateUserId();
console.log(userId); // "987654321098"
collectFingerprint()

Description: Collect comprehensive browser fingerprint
Returns: Promise (fingerprint data)

const fingerprint = await prip.collectFingerprint();
console.log(fingerprint);
/*
{
    userAgent: "Mozilla/5.0...",
    screenResolution: [1920, 1080],
    colorDepth: 24,
    hardwareConcurrency: 8,
    // ... many more attributes
}
*/
checkStorageConsistency()

Description: Validate ID consistency across storage types
Returns: Object (consistency status)

const consistency = prip.checkStorageConsistency();
console.log(consistency);
/*
{
    isConsistent: true,
    userIdMatches: true,
    deviceIdMatches: true,
    storageTypes: ['cookie', 'localStorage', 'sessionStorage']
}
*/
reconnectUser()

Description: Send reconnection request to server
Returns: Promise

const response = await prip.reconnectUser();
console.log(response);
clearAllData()

Description: Remove all PRIP data from browser
Returns: void

prip.clearAllData();

Configuration API

HTML Data Attributes

<script src="P-RIP/PrivacyRipper.js"
        data-prip-userdevice-length="16"
        data-prip-userdevice-chars="ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
        data-prip-userid-length="20"
        data-prip-userid-chars="abcdefghijklmnopqrstuvwxyz0123456789"
        data-prip-reconnect-url="/api/user-reconnect"
        data-prip-reconnect-method="POST"
        data-prip-debug="true">
</script>

Global Configuration

window.PRIP_CONFIG = {
    PRIP_USERDEVICE: {
        length: 16,
        randomChars: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
    },
    PRIP_USERID: {
        length: 20,
        randomChars: 'abcdefghijklmnopqrstuvwxyz0123456789'
    },
    PRIP_RECONNECT: {
        url: '/api/user-reconnect',
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'X-API-Key': 'your-api-key'
        }
    },
    PRIP_DEBUG: true
};

Meta Tag Configuration

<meta name="prip-config" content='{"PRIP_RECONNECT":{"url":"/custom-endpoint","method":"POST"},"PRIP_DEBUG":true}'>

🐍 Python Data Extraction API

Extractor Module

process_request(request)

Description: Extract and process PRIP data from Flask request
Parameters: Flask request object
Returns: Dictionary with extracted data

from Extractor import process_request

@app.route('/api/analyze', methods=['POST'])
def analyze_data():
    try:
        user_data = process_request(request)
        return jsonify(user_data)
    except ValueError as e:
        return jsonify({"error": str(e)}), 400

user_info_extract(user_data, user_id, device_id)

Description: Extract structured information from raw fingerprint data
Parameters:

  • user_data (dict): Raw fingerprint data
  • user_id (str): User identifier
  • device_id (str): Device identifier

Returns: Structured dictionary with categorized data

from Extractor import user_info_extract

extracted = user_info_extract(raw_data, "user123", "device456")
print(extracted['system']['platform'])  # "Win32"
print(extracted['webgl']['vendor'])     # "NVIDIA Corporation"

Data Structure

{
    "timestamp": "2025-05-30T10:30:00Z",
    "visitor_id": "abc123def456",
    "user_id_from_cookie": "123456789012", 
    "device_id_from_cookie": "987654321098",
    "confidence": 0.95,
    "fingerprint": {
        "canvas": {
            "geometry_hash_sha256": "a1b2c3...",
            "text_hash_sha256": "d4e5f6..."
        },
        "webgl": {
            "version": "WebGL 2.0",
            "vendor": "NVIDIA Corporation",
            "renderer": "GeForce GTX 1060"
        },
        "system": {
            "platform": "Win32",
            "hardware_concurrency": 8,
            "device_memory": 16
        },
        "screen": {
            "resolution_x": 1920,
            "resolution_y": 1080,
            "color_depth": 24
        }
    }
}

πŸ”§ Integration Examples

Basic Flask Integration

from flask import Flask, request, jsonify
from Extractor import process_request

app = Flask(__name__)

@app.route('/track', methods=['POST'])
def track_user():
    """Basic tracking endpoint"""
    try:
        # Extract PRIP data
        user_data = process_request(request)
        
        # Store in database (your implementation)
        store_fingerprint_data(user_data)
        
        return jsonify({
            "status": "success",
            "user_id": user_data.get("user_id_from_cookie"),
            "visitor_id": user_data.get("visitor_id")
        })
        
    except ValueError as e:
        return jsonify({"error": "Invalid data"}), 400
    except Exception as e:
        return jsonify({"error": "Server error"}), 500

def store_fingerprint_data(data):
    """Store fingerprint data in database"""
    # Your database implementation here
    pass

Advanced Research Platform

from flask import Flask, request, jsonify, session
from Extractor import process_request
import sqlite3
import datetime

app = Flask(__name__)
app.secret_key = 'your-secret-key'

class ResearchDB:
    def __init__(self, db_path='research.db'):
        self.db_path = db_path
        self.init_database()
    
    def init_database(self):
        """Initialize research database"""
        conn = sqlite3.connect(self.db_path)
        cursor = conn.cursor()
        
        cursor.execute('''
            CREATE TABLE IF NOT EXISTS fingerprints (
                id INTEGER PRIMARY KEY,
                visitor_id TEXT,
                user_id TEXT,
                device_id TEXT,
                timestamp TEXT,
                fingerprint_data TEXT,
                consent_given BOOLEAN,
                study_id TEXT
            )
        ''')
        
        conn.commit()
        conn.close()
    
    def store_fingerprint(self, data, study_id, consent=False):
        """Store fingerprint with research metadata"""
        conn = sqlite3.connect(self.db_path)
        cursor = conn.cursor()
        
        cursor.execute('''
            INSERT INTO fingerprints 
            (visitor_id, user_id, device_id, timestamp, fingerprint_data, consent_given, study_id)
            VALUES (?, ?, ?, ?, ?, ?, ?)
        ''', (
            data.get('visitor_id'),
            data.get('user_id_from_cookie'),
            data.get('device_id_from_cookie'),
            datetime.datetime.now().isoformat(),
            json.dumps(data),
            consent,
            study_id
        ))
        
        conn.commit()
        conn.close()

research_db = ResearchDB()

@app.route('/research/collect', methods=['POST'])
def research_collect():
    """Research data collection with consent"""
    try:
        # Check consent
        if not session.get('consent_given'):
            return jsonify({"error": "Consent required"}), 403
        
        # Extract data
        user_data = process_request(request)
        
        # Store with research metadata
        study_id = session.get('study_id', 'default')
        research_db.store_fingerprint(user_data, study_id, consent=True)
        
        return jsonify({
            "status": "success",
            "message": "Data collected for research"
        })
        
    except Exception as e:
        return jsonify({"error": str(e)}), 500

@app.route('/research/consent', methods=['POST'])
def give_consent():
    """Handle research consent"""
    consent_data = request.json
    
    if consent_data.get('agrees_to_research'):
        session['consent_given'] = True
        session['study_id'] = consent_data.get('study_id', 'default')
        return jsonify({"status": "consent_granted"})
    else:
        return jsonify({"status": "consent_denied"})

Frontend Integration with Consent

<!DOCTYPE html>
<html>
<head>
    <title>Privacy Research Study</title>
</head>
<body>
    <div id="consent-banner">
        <h3>Research Participation</h3>
        <p>This study collects browser fingerprinting data for privacy research.</p>
        <button onclick="giveConsent()">I Agree to Participate</button>
        <button onclick="declineConsent()">No Thanks</button>
    </div>
    
    <div id="research-content" style="display: none;">
        <h1>Privacy Research Interface</h1>
        <p>Thank you for participating in our research!</p>
    </div>
    
    <script src="P-RIP/PrivacyRipper.js"></script>
    <script>
        let prip;
        
        async function giveConsent() {
            // Send consent to server
            const response = await fetch('/research/consent', {
                method: 'POST',
                headers: {'Content-Type': 'application/json'},
                body: JSON.stringify({
                    agrees_to_research: true,
                    study_id: 'privacy_study_2025'
                })
            });
            
            if (response.ok) {
                // Initialize PRIP after consent
                prip = new PrivacyRipper({
                    endpoint: '/research/collect',
                    debug: true
                });
                
                // Show research interface
                document.getElementById('consent-banner').style.display = 'none';
                document.getElementById('research-content').style.display = 'block';
                
                // Start data collection
                await collectResearchData();
            }
        }
        
        function declineConsent() {
            alert('Thank you for your consideration. No data will be collected.');
        }
        
        async function collectResearchData() {
            try {
                const fingerprint = await prip.collectFingerprint();
                console.log('Research data collected:', fingerprint);
            } catch (error) {
                console.error('Research data collection failed:', error);
            }
        }
    </script>
</body>
</html>

πŸ“Š Data Analysis API

Aggregation Functions

def analyze_fingerprint_diversity(fingerprints):
    """Analyze uniqueness of collected fingerprints"""
    unique_features = {}
    
    for fp in fingerprints:
        for feature, value in fp.items():
            if feature not in unique_features:
                unique_features[feature] = set()
            unique_features[feature].add(str(value))
    
    diversity_scores = {}
    for feature, values in unique_features.items():
        diversity_scores[feature] = len(values) / len(fingerprints)
    
    return diversity_scores

def detect_browser_families(user_agents):
    """Categorize browsers from user agent strings"""
    families = {
        'Chrome': 0,
        'Firefox': 0, 
        'Safari': 0,
        'Edge': 0,
        'Other': 0
    }
    
    for ua in user_agents:
        if 'Chrome' in ua and 'Edge' not in ua:
            families['Chrome'] += 1
        elif 'Firefox' in ua:
            families['Firefox'] += 1
        elif 'Safari' in ua and 'Chrome' not in ua:
            families['Safari'] += 1
        elif 'Edge' in ua:
            families['Edge'] += 1
        else:
            families['Other'] += 1
    
    return families

πŸ”’ Security Considerations

Rate Limiting

from flask_limiter import Limiter
from flask_limiter.util import get_remote_address

limiter = Limiter(
    app,
    key_func=get_remote_address,
    default_limits=["100 per hour"]
)

@app.route('/api/data', methods=['POST'])
@limiter.limit("10 per minute")
def limited_data_collection():
    """Rate-limited data collection endpoint"""
    return process_request(request)

Input Validation

from jsonschema import validate, ValidationError

FINGERPRINT_SCHEMA = {
    "type": "object",
    "properties": {
        "visitor_id": {"type": "string", "maxLength": 100},
        "user_agent": {"type": "string", "maxLength": 1000},
        "screen_resolution": {
            "type": "array",
            "items": {"type": "integer"},
            "minItems": 2,
            "maxItems": 2
        }
    },
    "required": ["visitor_id"]
}

def validate_fingerprint_data(data):
    """Validate incoming fingerprint data"""
    try:
        validate(data, FINGERPRINT_SCHEMA)
        return True
    except ValidationError as e:
        print(f"Validation error: {e}")
        return False

πŸ“ Error Handling

Common Error Codes

Code Description Solution
400 Invalid request data Check data format and required fields
403 Missing consent Implement proper consent mechanism
429 Rate limit exceeded Reduce request frequency
500 Server processing error Check logs and data format

Error Response Format

{
    "error": "Invalid data format",
    "code": 400,
    "details": "Missing required field: visitor_id",
    "timestamp": "2025-05-30T10:30:00Z"
}

For more detailed examples and advanced usage patterns, see the examples directory in the repository.