Source Code
The entire project, readable in your browser. No hidden JavaScript, no sneaky beacons. If we claimed we don't track you, this is where you check.
|
Pages/
Feeds/
Backend/
Includes/
Stylesheet/
JavaScript/
data/counter.txt and data/guestbook.txt hold visitor-supplied content
(a number and signed messages), so they are not shown here.
|
1 <?php 2 /** 3 * fingerprint.php -- Local browser fingerprinting demo. 4 * Builds canvas/audio/WebGL/font/screen/timezone/language/hardware fingerprints 5 * and combines them into one SHA-256 ID, all in the browser. Nothing uploaded. 6 */ 7 require_once __DIR__ . '/includes/config.php'; 8 require_once __DIR__ . '/includes/functions.php'; 9 10 $PAGE_TITLE = 'Fingerprint'; 11 $PAGE_ID = 'fingerprint.php'; 12 13 include __DIR__ . '/includes/header.php'; 14 ?> 15 16 <h1><?php echo section_icon('eye', '#FF3030', 22); ?> Browser Fingerprint</h1> 17 18 <div class="badbx"> 19 <b>The scary part.</b> Cookies can be cleared. Fingerprints cannot — they are 20 re-derived from your hardware and software every time. The ID below identifies 21 <i>this browser on this machine</i> with <b>no cookies at all</b>. We compute it 22 here and immediately throw it away. Trackers do not. 23 </div> 24 25 <div id="fpOut"> 26 <div class="panel"><div class="panel-body center dim"> 27 Hashing your canvas, audio, WebGL, fonts, and hardware <span class="cursor"></span> 28 </div></div> 29 </div> 30 31 <div id="fpExport" class="asciibox center" style="display:none"> 32 <b>Export this fingerprint report (local only):</b><br> 33 <button class="export-btn" data-fmt="json">[ JSON ]</button> 34 <button class="export-btn" data-fmt="html">[ HTML ]</button> 35 <button class="export-btn" data-fmt="md">[ Markdown ]</button> 36 <button class="export-btn" data-fmt="txt">[ TXT ]</button> 37 </div> 38 39 <hr> 40 41 <details> 42 <summary>How does fingerprinting actually work?</summary> 43 <div class="details-body"> 44 <p><b>Canvas:</b> the page draws hidden text and shapes, then reads back the 45 pixels. Your exact GPU, driver, and font rendering produce a subtly unique 46 image — the same every time.</p> 47 <p><b>Audio:</b> an offline audio graph processes a tone. Floating-point 48 differences between devices leave a stable numeric signature. No sound plays.</p> 49 <p><b>WebGL:</b> the 3D API reports your GPU vendor/renderer and dozens of 50 capability limits — often enough to identify your graphics card outright.</p> 51 <p><b>Fonts:</b> by measuring the width of text, a page can tell which fonts 52 you have installed — a surprisingly personal fingerprint of your software.</p> 53 <p>Combine these with your screen, timezone, language, and hardware, hash the 54 lot, and you get a durable identifier. That is exactly what happens below.</p> 55 </div> 56 </details> 57 58 <script> 59 window.EYES = window.EYES || {}; 60 window.EYES.BASE = <?php echo json_encode(BASE_URL); ?>; 61 </script> 62 <script src="<?php echo eattr(url('assets/js/detect.js')); ?>"></script> 63 <script src="<?php echo eattr(url('assets/js/fingerprint.js')); ?>"></script> 64 <script src="<?php echo eattr(url('assets/js/scan.js')); ?>"></script> 65 <script src="<?php echo eattr(url('assets/js/export.js')); ?>"></script> 66 <script> 67 (function () { 68 function esc(s){return String(s==null?'':s).replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');} 69 function badge(l){var c=l==='HIGH'?'risk-high':l==='MEDIUM'?'risk-medium':l==='LOW'?'risk-low':'risk-info';return '<span class="risk '+c+'">'+esc(l)+'</span>';} 70 function bar(p){p=Math.max(0,Math.min(100,p|0));var t=20,f=Math.round(p/100*t),s='[';for(var i=0;i<t;i++)s+=(i<f?'#':'<span class="empty">-</span>');return '<span class="asciibar">'+s+'] '+p+'%</span>';} 71 72 function go() { 73 window.EYES.wireExportButtons(); 74 // We still need the browser object (fonts feed the fingerprint), so build 75 // the full report; then render a fingerprint-focused view. 76 window.EYES.buildReport().then(function (report) { 77 var fp = report.fingerprint || {}; 78 var el = document.getElementById('fpOut'); 79 if (!fp.id) { el.innerHTML = '<div class="badbx">Fingerprinting unavailable in this browser.</div>'; return; } 80 81 var sigRows = Object.keys(fp.signals).map(function (k) { 82 var sig = fp.signals[k]; 83 return '<tr><td class="k">' + esc(k) + '</td>' + 84 '<td class="v"><span class="mono" style="font-size:13px;word-break:break-all">' + esc(sig.hash) + '</span></td></tr>'; 85 }).join(''); 86 87 el.innerHTML = 88 '<div class="panel"><div class="panel-title">Your Fingerprint ID</div><div class="panel-body">' + 89 '<div class="badbx" style="text-align:center">' + 90 '<div class="dim">SHA-256 identifier for this browser</div>' + 91 '<div class="mono" style="font-size:18px;word-break:break-all;color:#FF6666">' + esc(fp.id) + '</div>' + 92 '</div>' + 93 '<table class="data kv">' + 94 '<tr><td class="k">Estimated Entropy</td><td class="v">' + esc(fp.entropyBits) + ' bits</td></tr>' + 95 '<tr><td class="k">Uniqueness</td><td class="v">' + bar(fp.uniqueness) + '</td></tr>' + 96 '<tr><td class="k">You are ~1 in</td><td class="v"><b class="yellow">' + esc(fp.oneIn.toLocaleString()) + '</b></td></tr>' + 97 '<tr><td class="k">Tracking Risk</td><td class="v">' + badge(fp.trackingRisk) + '</td></tr>' + 98 '</table>' + 99 '</div></div>' + 100 '<div class="panel"><div class="panel-title">Per-Signal Hashes</div><div class="panel-body">' + 101 '<table class="data kv">' + sigRows + '</table>' + 102 '<p class="dim">Each signal is hashed independently, then all are combined into the master ID above. ' + 103 'Change any one (new GPU, new fonts, resized window) and the ID shifts — but day to day, it is remarkably stable.</p>' + 104 '</div></div>'; 105 106 document.getElementById('fpExport').style.display = 'block'; 107 }).catch(function (e) { 108 document.getElementById('fpOut').innerHTML = '<div class="badbx">Fingerprinting failed: ' + esc(e && e.message ? e.message : e) + '</div>'; 109 }); 110 } 111 if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', go); 112 else go(); 113 })(); 114 </script> 115 116 <?php include __DIR__ . '/includes/footer.php'; ?> 117 You are reading the real file being executed on the server. What you see is what runs. |