Files
computerhistory/00_aMeta/toolz/progressiveKlickDecryption.html
T

348 lines
12 KiB
HTML

<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Computer Historyz - Progressive Klick-Decryption</title>
<style>
/* --- KERNFARBEN AUS DESIGN-DOKU: MASCHINEN-INSTANZEN --- */
:root {
--bg-deep: #05070a;
--bg-panel: #0b0e14;
--accent-cyan: #00f2ff;
--accent-green: #00ff73;
--accent-amber: #ffb700;
--accent-red: #ff3e3e;
--text-dim: #888899;
--font-mono: "JetBrains Mono", "Fira Code", "Courier Prime", monospace;
}
body {
background: var(--bg-deep);
color: var(--text-dim);
font-family: var(--font-mono);
margin: 20px;
line-height: 1.5;
}
.panel {
background: var(--bg-panel);
border: 1px solid var(--text-dim);
backdrop-filter: blur(4px);
padding: 15px;
margin-bottom: 25px;
box-shadow: 0 0 6px rgba(0, 242, 255, 0.1);
}
.panel-title {
color: var(--accent-green);
font-weight: bold;
text-transform: uppercase;
letter-spacing: 1px;
margin-top: 0;
margin-bottom: 15px;
border-bottom: 1px dashed var(--text-dim);
padding-bottom: 5px;
}
input, textarea, button {
background: #07090e;
border: 1px solid var(--text-dim);
color: var(--accent-green);
padding: 8px;
font-family: var(--font-mono);
width: 100%;
box-sizing: border-box;
margin-bottom: 10px;
}
input:focus, textarea:focus {
outline: none;
border-color: var(--accent-cyan);
box-shadow: 0 0 6px var(--accent-cyan);
}
button {
cursor: pointer;
font-weight: bold;
background: #0c161a;
border-color: var(--accent-cyan);
color: var(--accent-cyan);
transition: all 0.2s ease;
}
button:hover {
background: var(--accent-cyan);
color: var(--bg-deep);
box-shadow: 0 0 6px var(--accent-cyan);
}
/* --- CRYPTO BLÖCKE SYSTEM --- */
.lock-chain {
white-space: pre-wrap;
word-break: break-all;
background: #020407;
padding: 12px;
border-left: 3px solid var(--text-dim);
margin: 15px 0;
color: #555566;
transition: all 0.3s ease;
opacity: 0.6;
}
/* Zustand: Block wartet darauf, geklickt zu werden */
.lock-chain.is-active {
border-left: 3px solid var(--accent-amber);
color: var(--accent-cyan);
cursor: pointer;
opacity: 1;
box-shadow: 0 0 6px rgba(255, 183, 0, 0.2);
animation: pulse-active 2s infinite ease-in-out;
}
/* Zustand: Erfolgreich decodiert */
.lock-chain.is-decrypted {
border-left: 3px solid var(--accent-green);
color: var(--accent-green);
background: transparent;
white-space: normal;
opacity: 1;
animation: none;
cursor: default;
}
/* Zustand: Fehler bei der Entschlüsselung */
.lock-chain.error {
border-left: 3px solid var(--accent-red);
color: var(--accent-red);
opacity: 1;
animation: blink-error 1s infinite;
}
@keyframes pulse-active {
0% { background: #020407; }
50% { background: #0a121c; }
100% { background: #020407; }
}
@keyframes blink-error {
50% { opacity: 0.4; }
}
.control-panel {
max-width: 600px;
}
.status-badge {
display: inline-block;
padding: 2px 6px;
font-size: 0.85em;
background: #111;
border: 1px solid var(--text-dim);
margin-bottom: 10px;
}
</style>
</head>
<body>
<div class="panel control-panel">
<div class="panel-title">Decryption Control Deck</div>
<label for="master-pass">Master-Passwort (Key 0):</label>
<input type="password" id="master-pass" value="OortscheWolke2448">
<button onclick="initializeCryptoChain()">Krypto-Kette initialisieren</button>
<div id="deck-status" class="status-badge" style="color: var(--accent-amber);">Status: Warte auf Initialisierung...</div>
</div>
<div class="panel">
<div class="panel-title">Dokument-Struktur (Instanzen-Protokoll)</div>
<h3>Knotenpunkt-Datenstrom</h3>
<p><em>Dieser Textbereich liegt außerhalb der Kette und bleibt dauerhaft sichtbar.</em></p>
<div class="lock-chain" id="block-0" onclick="triggerBlockDecryption(0)">&#x02;
4a21184a44f9deeb8db93ee5c56dfba2d28fbfb3970b880197d19e9eb10a
a011de36bdfc1103f6f14066094ef5ad0554ba739cae9dfc01991a0c0f99
8ee2954aef83fbdf9842a2acb119cb
&#x03;</div>
<div class="lock-chain" id="block-1" onclick="triggerBlockDecryption(1)">&#x02;
108b688d01a3579ab5a6c117b38d388f8d689b9d3ff02102554dfa45bbca
c0a7cc02ccff5d8ee9d110f01ccba1dd010ea4fbc11e22778da5a6c1deba
99a9cf588b
&#x03;</div>
<div class="lock-chain" id="block-2" onclick="triggerBlockDecryption(2)">&#x02;
92da21085ba1f43a99e7d9b9d62da3ffde4bb8df115dd0ca31bdaef9d877
bbad84ff4da92da74e99a4c11100bb17dca5ffca188e7d22cb54fb77ac90
d22bb488de1a56daff8e9b
&#x03;</div>
</div>
<div class="panel">
<div class="panel-title">Ketten-Generator (Text-zu-Klick-Block)</div>
<textarea id="gen-input" rows="4">Das Ur-Ding der Erbauer war die Energie.
Die Hauptmaschinen sind monumentale Datenbanken.
Das Nina-Protokoll verhindert den Ressourcen-Kollaps.</textarea>
<button onclick="generateNewChain()">Neue Krypto-Kette generieren</button>
<div id="gen-output" style="white-space: pre; font-family: var(--font-mono); color: var(--accent-cyan); margin-top: 10px; font-size: 0.9em;"></div>
</div>
<script>
// --- STATE MACHINE FÜR DIE KLICK-KETTE ---
let currentActiveIndex = -1;
let nextKeyString = "";
// --- UTILITIES (Native Web Crypto) ---
function bufToHex(buf) {
return Array.from(new Uint8Array(buf)).map(b => b.toString(16).padStart(2, '0')).join('');
}
function hexToBuf(hex) {
const bytes = new Uint8Array(hex.length / 2);
for (let i = 0; i < hex.length; i += 2) {
bytes[i / 2] = parseInt(hex.substring(i, i + 2), 16);
}
return bytes.buffer;
}
async function deriveKey(passwordString) {
const encoder = new TextEncoder();
const data = encoder.encode(passwordString);
const hash = await crypto.subtle.digest('SHA-256', data);
return await crypto.subtle.importKey('raw', hash, { name: 'AES-GCM' }, false, ['encrypt', 'decrypt']);
}
// --- INTERAKTIVE LOGIK ---
// Schritt 1: Master-Passwort laden und Block 0 scharf schalten
function initializeCryptoChain() {
const masterPassword = document.getElementById('master-pass').value;
if (!masterPassword) {
updateStatus("FEHLER: Passwort fehlt", "var(--accent-red)");
return;
}
nextKeyString = masterPassword;
currentActiveIndex = 0;
// Alle UI-Klassen zurücksetzen
const blocks = document.querySelectorAll('.lock-chain');
blocks.forEach((block, idx) => {
block.classList.remove('is-active', 'is-decrypted', 'error');
// Wenn es der erste Block ist, aktiv schalten
if(idx === 0) {
block.classList.add('is-active');
}
});
updateStatus("Kette bereit. Klicke auf Block 1...", "var(--accent-cyan)");
}
// Schritt 2: Klick-Handler für die einzelnen Blöcke
async function triggerBlockDecryption(blockIndex) {
// Ignoriere Klicks, wenn der Block noch nicht an der Reihe ist
if (blockIndex !== currentActiveIndex) return;
const block = document.getElementById(`block-${blockIndex}`);
let rawContent = block.innerText.replace(/\r?\n|\r/g, "");
// Format-Sicherheitscheck (\x02 STX und \x03 ETX)
if (!rawContent.startsWith('\x02') || !rawContent.endsWith('\x03')) {
markError(block, "Formatierungsfehler (Steuerzeichen fehlen)");
return;
}
// Payload-Filterung
const payload = rawContent.substring(1, rawContent.length - 1).replace(/\s/g, "");
const ivHex = payload.substring(0, 24);
const cipherHex = payload.substring(24);
try {
const iv = hexToBuf(ivHex);
const cipherData = hexToBuf(cipherHex);
const key = await deriveKey(nextKeyString);
const decryptedBuf = await crypto.subtle.decrypt(
{ name: 'AES-GCM', iv: iv },
key,
cipherData
);
const plaintext = new TextDecoder().decode(decryptedBuf);
// DOM-Austausch unter Beibehaltung der Struktur
block.innerHTML = plaintext;
block.classList.remove('is-active', 'error');
block.classList.add('is-decrypted');
// HIER PASSIERT DIE FORTLAUFENDE SCHLÜSSEL-ÜBERGABE:
nextKeyString = plaintext;
// Nächsten Block in der Kette freischalten
currentActiveIndex++;
const nextBlock = document.getElementById(`block-${currentActiveIndex}`);
if (nextBlock) {
nextBlock.classList.add('is-active');
updateStatus(`Block ${blockIndex + 1} gelöst. Nächster Block freigegeben!`, "var(--accent-cyan)");
} else {
updateStatus("System vollständig decodiert. Kette beendet.", "var(--accent-green)");
}
} catch (err) {
markError(block, `Kettenschluss fehlgeschlagen. Falscher Key.`);
}
}
function markError(element, message) {
element.classList.remove('is-active');
element.classList.add('error');
element.innerText = `[CRITICAL CODE CORRUPTION: ${message}]`;
updateStatus("Kette dauerhaft unterbrochen.", "var(--accent-red)");
currentActiveIndex = -1; // Blockiert weitere Klicks
}
function updateStatus(text, color) {
const badge = document.getElementById('deck-status');
badge.innerText = `Status: ${text}`;
badge.style.color = color;
badge.style.borderColor = color;
}
// --- CHIP-GENERATOR FÜR DEINE TEXTE ---
async function generateNewChain() {
const masterPassword = document.getElementById('master-pass').value;
const lines = document.getElementById('gen-input').value.split('\n').filter(l => l.trim() !== "");
let currentKeyString = masterPassword;
let htmlOutput = "";
for (let i = 0; i < lines.length; i++) {
const plaintext = lines[i];
const iv = crypto.getRandomValues(new Uint8Array(12));
const key = await deriveKey(currentKeyString);
const encryptedBuf = await crypto.subtle.encrypt(
{ name: 'AES-GCM', iv: iv },
key,
new TextEncoder().encode(plaintext)
);
const fullPayloadHex = bufToHex(iv) + bufToHex(encryptedBuf);
let formattedHex = "";
for (let j = 0; j < fullPayloadHex.length; j += 60) {
formattedHex += "\n" + fullPayloadHex.substring(j, j + 60);
}
// Generiert direkt die korrekten Klick-IDs und Handler für deinen Quelltext
htmlOutput += `&lt;div class="lock-chain" id="block-${i}" onclick="triggerBlockDecryption(${i})"&gt;&#x02;${formattedHex}\n&#x03;&lt;/div&gt;\n\n`;
currentKeyString = plaintext;
}
document.getElementById('gen-output').innerHTML = htmlOutput;
}
</script>
</body>
</html>