another media expolre digital content snippet idear
This commit is contained in:
@@ -0,0 +1,348 @@
|
||||
<!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)">
|
||||
4a21184a44f9deeb8db93ee5c56dfba2d28fbfb3970b880197d19e9eb10a
|
||||
a011de36bdfc1103f6f14066094ef5ad0554ba739cae9dfc01991a0c0f99
|
||||
8ee2954aef83fbdf9842a2acb119cb
|
||||
</div>
|
||||
|
||||
<div class="lock-chain" id="block-1" onclick="triggerBlockDecryption(1)">
|
||||
108b688d01a3579ab5a6c117b38d388f8d689b9d3ff02102554dfa45bbca
|
||||
c0a7cc02ccff5d8ee9d110f01ccba1dd010ea4fbc11e22778da5a6c1deba
|
||||
99a9cf588b
|
||||
</div>
|
||||
|
||||
<div class="lock-chain" id="block-2" onclick="triggerBlockDecryption(2)">
|
||||
92da21085ba1f43a99e7d9b9d62da3ffde4bb8df115dd0ca31bdaef9d877
|
||||
bbad84ff4da92da74e99a4c11100bb17dca5ffca188e7d22cb54fb77ac90
|
||||
d22bb488de1a56daff8e9b
|
||||
</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 += `<div class="lock-chain" id="block-${i}" onclick="triggerBlockDecryption(${i})">${formattedHex}\n</div>\n\n`;
|
||||
|
||||
currentKeyString = plaintext;
|
||||
}
|
||||
|
||||
document.getElementById('gen-output').innerHTML = htmlOutput;
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user