1980: een toetsenbord stuurt scan codes. Druk → matrix → controller → scan code → terminal. Eén laag vertaling.
Vandaag: een toetsenbord stuurt UTF-8 streams. Druk → matrix → HID → driver → IME → Unicode → UTF-8 → terminal. Zevend lagen vertaling.
Elke laag is een gat. En elk gat is een plek waar je analoog signaal kunt injecteren.
Dit is de kaart van die gaten.
128→1.1M
codepoints (ASCII→Unicode)
⚡ Signaalstroom: Analoog → Digitaal
vinger
→
schakelaar
→
matrix
→
CONTROLLER
→
scan code
→
HID
→
driver
→
Unicode
→
UTF-8
De lagen
1
Fysiek — Mechanische Schakelaar
Een vinger duwt een steel naar beneden. Contact sluit. Analoog signaal: spanning verandert van 0V naar 5V. Dit is het enige echte signaal. Alles na dit punt is vertaling.
5V → GND (analoog)
2
Matrix — Row × Column Scanning
Toetsen zitten in een raster. Controller scant rijen en kolommen. Welke combinatie = welke toets. Nog steeds analoog — een circuit dat opent of sluit.
row[4] × col[2] = 'A'
3
Controller — De Eerste Vertaler
Keyboard controller chip (bijv. Philips 8042, of modern USB-HID controller) vertaalt matrix-posities naar scan codes. Dit is het eerste moment waarop informatie toegevoegd wordt — de controller kent een tabel.
matrix[4,2] → scan code 0x1E (Set 1)
⚠
GAT #1: Controller Firmware
De controller firmware bepaalt welke scan codes gegenereerd worden. QMK, VIA, TMK — custom firmware kan alles injecteren. Een toets kan een macro, een script, of een heel document worden. Dit is het eerste echte gat in de keten.
injectie: custom firmware → alles wordt mogelijk
4
Transport — PS/2 → USB-HID → Bluetooth
Scan codes reizen over een kabel. PS/2 (analoge spanningen op twee draden). USB (digitaal, HID protocol). Bluetooth (draadloos, Bluetooth HID profile). Elke transportlaag voegt protocol overhead toe.
HID report: [0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00]
⚠
GAT #2: Transport Protocol
USB-HID is een "zero driver" protocol — het OS vertrouwt HID reports automatisch. Een kwaadaardig HID device ( Rubber Ducky, Bad USB) injecteert commands alsof het een toetsenbord is. Bluetooth HID kan geïntercepteerd en geïnjecteerd worden.
injectie: Bad USB → HID spoofing → Bluetooth MITM
5
OS Driver — Scan Code → Virtual Key
Besturingssysteem vertaalt scan codes naar virtual key codes. Linux: evdev. Windows: keyboard layout driver. macOS: IOKit HID. Toetsenbordindeling (US, NL, BE) bepaalt welke fysieke toets welk karakter wordt.
scan 0x1E + NL-layout → VK_A → 'a'
⚠
GAT #3: Input Method Editor (IME)
IME is de laag die fysieke toetsen vertaalt naar karakters in elke taal. Compose keys, dead keys, multi-stroke input. Een Nederlands toetsenbord met US-layout: AltGr+[ = €. Het gat: IME kan elke combinatie van toetsen in elk Unicode karakter transformeren. Het is de brug tussen 104 fysieke toetsen en 1.114.112 Unicode codepoints.
injectie: AltGr-combos → 1.1M codepoints uit 104 toetsen
6
Encoding — Unicode → UTF-8
Unicode codepoint wordt geëncodeerd als byte-stream. ASCII (128 chars, 1 byte). Latin-1 (256 chars, 1 byte). UTF-8 (variabele 1-4 bytes). UTF-16 (2-4 bytes). Het karakter 'a' = U+0061 = 0x61 (UTF-8). '€' = U+20AC = 0xE2 0x82 0xAC (UTF-8).
U+0061 → 0x61 | U+20AC → 0xE2 0x82 0xAC
⚠
GAT #4: Encoding Confusion
Wanneer systemen verschillende encodings mixen: UTF-8 bytes geïnterpreteerd als Latin-1, UTF-16 als UTF-8. "Mojibake" — onleesbaar geworden tekst. Maar ook: UTF-8 encoding kan verborgen data dragen in zogenaamde "overlong encodings". Een injectiepunt dat decennia van exploits heeft opgeleverd.
injectie: encoding mismatch → data injection → XSS → RCE
7
Terminal / App — Rendering
Byte-stream wordt geparst, karakters gerenderd. Terminal, browser, editor. Font bepaalt of het zichtbaar is. Het eindpunt van de keten: bytes → pixels op scherm.
0x61 → 'a' → █ (pixel)
⚡ De Volledige Keten met Gaten
vinger
→
schakelaar
→
matrix
→
controller ⚠
→
scan code
→
transport ⚠
→
HID
→
driver
→
IME ⚠
→
Unicode
→
UTF-8 ⚠
→
terminal
4 gaten × 7 lagen = elke vertaling is een kans voor injectie
⏱ Jurisprudentie: Encoding Evolutie (1963–2025)
1963
ASCII (American Standard Code for Information Interchange)
128 tekens. 7-bit. Alleen Engels + control codes. Het fundament van alle digitale communicatie. Het eerste gat: niet-Engelse talen bestaan niet in ASCII.
1967
ISO/IEC 646 — International Reference Version
Probeerde ASCII international te maken met "international reference characters" op vaste posities. Iedereen kon hun eigen karakters injecteren op deze posities. Chaos.
1985
ISO 8859-1 (Latin-1)
256 tekens. 8-bit. Westerse talen ondersteund. Eerste echte uitbreiding van ASCII. Maar: Arabisch, Chinees, Cyrillisch = nog steeds niet.
1987
IBM AT Keyboard (PS/2)
Extended scan codes (Set 1, 2, 3). PS/2 connector. Analoog signaal op clock + data draden. Scan code set = de eerste "taal" van het toetsenbord.
1991
Unicode 1.0
Eén encoding voor alle talen. 16-bit (65.536 codepoints). Het idee: één universele codepoint per karakter. De droom van één toetsenbord voor alle talen.
1992
UTF-8
Backwards-compatible met ASCII. Variabele lengte (1-4 bytes). Wordt de standaard van het internet. Het gat: UTF-8 kan "overlong encodings" maken die exploits mogelijk maken.
1996
USB-HID Protocol
Universal Serial Bus Human Interface Device. "Zero driver" — OS vertrouwt HID automatisch. Het gat: Bad USB exploitteert dit vertrouwen.
1996
Unicode 2.0
44.000+ codepoints. Alle wereldwijde schriften. De limiet van 16-bit wordt bereikt → UTF-16 surrogate pairs.
1998
Bluetooth 1.0 — HID Profile
Draadloos toetsenbord. Maar: geen encryptie in vroege versies. Easily intercepted. Dit is een gat in de transportlaag.
1999
Unicode 3.0
Auxiliary planes (BMP overschreden). Emoji worden toegevoegd later. Het toetsenbord kan nu theoretisch elke taal typen — maar alleen via IME.
2003
Unicode 4.0 — 96.382 codepoints
Braille, historische schriften, wiskundige symbolen. Het toetsenbord is nu een universeel signaal-injectie-apparaat.
2010
Unicode 6.0 — Emoji
Emoji worden officieel. 😊 = U+1F60A = 0xF0 0x9F 0x98 0x8A (UTF-8). Een toetsaanslag wordt nu 4 bytes die een gezicht op je scherm zetten.
2015
QMK / VIA — Open Source Keyboard Firmware
Eigen firmware op je toetsenbord. Macros, layers, key remapping. Het toetsenbord wordt een computer op zichzelf. GAT #1 wordt volledig exploitabel.
2016
Unicode Emoji — ZWJ Sequences
Zero-Width Joiner combineert emoji: 👨👩👧👦 = 9 codepoints = 31 bytes UTF-8. Een "karakter" is nu een stream van karakters. Het toetsenbord stuurt streams, niet meer letters.
2020
Analog Keyboard Protocol (USB)
USB HID update: toetsen kunnen nu analoge waarden sturen (drukkracht, snelheid). Het gat: een toets is niet meer "aan/uit" maar een continüm. Dit is het meest directe punt van analoge signaal-injectie naar digitaal systeem.
2022
Unicode 15.0 — 149.186 codepoints
Adlam, Hosawi, Kawi, Nyiakeng Puachue Hmong. Nieuwe talen krijgen een plek. Maar het fysieke toetsenbord heeft nog steeds 104 toetsen. De IME is de enige brug.
2025
Unicode 16.0 — 150.000+ codepoints
1.114.112 mogelijke codepoints. ~150.000 toegekend. 104 toetsen. Zevend vertaling-lagen. Vier gaten. Het gat is de architectuur.
📋 Encoding Index: Van Toets naar Byte
Hoe hetzelfde karakter in verschillende encodings vertaald wordt
| karakter | Unicode | ASCII | Latin-1 | UTF-8 | scan code |
| A | U+0041 | 65 | 0x41 | 0x41 | 0x1E |
| a | U+0061 | 97 | 0x61 | 0x61 | 0x1E + Shift=0 |
| é | U+00E9 | — | 0xE9 | 0xC3 0xA9 | dead + e |
| € | U+20AC | — | — | 0xE2 0x82 0xAC | AltGr+[ |
| Ω | U+03A9 | — | — | 0xCE 0xA9 | AltGr+Q |
| ☮ | U+262E | — | — | 0xE2 0x98 0xAE | compose |
| ☉ | U+2609 | — | — | 0xE2 0x98 0x89 | compose |
| ☾ | U+263E | — | — | 0xE2 0x98 0xBE | compose |
| ⚡ | U+26A1 | — | — | 0xE2 0x9A 0xA1 | compose |
| ☢ | U+2622 | — | — | 0xE2 0x98 0xA2 | compose |
| ⌬ | U+232C | — | — | 0xE2 0x8C 0xAC | compose |
| ☯ | U+262F | — | — | 0xE2 0x98 0xAF | compose |
| ⬡ | U+2B21 | — | — | 0xE2 0xAC 0xA1 | compose |
| ⬢ | U+2B22 | — | — | 0xE2 0xAC 0xA2 | compose |
⌨ Fysiek Toetsenbord: Scan Code Matrix
De "taal" van het toetsenbord — scan codes (Set 1). Klik op een toets voor details.
Klik op een toets om scan code te zien.
💉 Injectie Punten
Elk gat is een punt waar analoog signaal het digitale pad kan oversteken
1. Hardware Keylogger
Fysiek apparaat tussen toetsenbord en computer. Vangt alle scan codes op. Geen software nodig. Onzichtbaar.
fysiek — laag 2-3
2. QMK Custom Firmware
Eigen firmware op het toetsenbord. Een toets kan een heel script uitvoeren. Key remapping, macros, encryption, logging.
firmware — gat #1
3. Bad USB (Rubber Ducky)
USB stick die zich presenteert als toetsenbord. Injecteert HID reports alsof het iemand die typt. Zero driver = automatisch vertrouwd.
HID spoofing — gat #2
4. Bluetooth HID MITM
Man-in-the-middle op Bluetooth verbinding. Interceptar en injecteer HID reports. Vroege Bluetooth had geen encryptie.
transport — gat #2
5. IME Injection
IME kan elke toetscombinatie transformeren. Een "a" wordt "é" wordt "€" wordt "😊". De IME is de meest krachtige vertaler.
IME — gat #3
6. Encoding Confusion
UTF-8 bytes geïnterpreteerd als Latin-1. Overlong encodings. XSS via encoding mismatch. Decennia van web exploits.
encoding — gat #4
7. Analog Keyboard (2020+)
Nieuw USB HID protocol. Toetsen sturen analoge waarden. Drukkracht wordt data. Echte analoge injectie, niet meer alleen discrete toetsaanslagen.
nieuw — hybrid
8. Software Hook (xev, evdev)
Software-level keylogger. Vangt events op OS niveau. Linux evdev, Windows Raw Input. Kan elke toetsaanslag vangen, loggen, of modificeren.
software — laag 5
🔬 Live Test: Jouw Toetsenbord
Druk op een toets hieronder om de signaalstroom te traceren:
Wacht op invoer...
◈ Het Analog-Gap: 104 Toetsen → 150.000 Tekens
Het fysieke toetsenbord heeft ~104 toetsen. Unicode heeft 150.000+ codepoints en 1.1 miljoen mogelijke.
De verhouding is 104 : 150.000+. Het toetsenbord kan niet één-toets-per-teken werken.
Dat is waarom er lagen zijn: scan code → layout → IME → compose → Unicode.
Elke laag is een vertaling. Elke vertaling is een gat.
In 1980 was het gat klein: scan code → ASCII (128 tekens). 104 toetsen dekten 128 tekens. Nauwelijks een gat.
Vandaag is het gat enorm: scan code → Unicode (150.000+ tekens). Het gat is de architectuur.
Het toetsenbord van 1980 communiceerde met een terminal.
Het toetsenbord van 2025 communiceert met een universum.
En het gat ertussen is waar alles gebeurt.
◈ IPv6 Controller: Slot → Subnet Routing
Huidig probleem: Scan code → HID → driver → IME → Unicode → UTF-8. Zevend lagen vertaling. Elke laag is een gat.
Oplossing: Map de 64 slots (0–63) als lokale IPv6-DNS. Elke slot = een /64 subnet. Elke toetscombinatie = eigen adres binnen dat subnet.
Nieuwe toetsen, extra keyboards, onbekende combinaties → routeer naar 0.0.0.0. Buiten de terminal. Geen vertaling, geen gat, geen mysterie.
Resultaat: overzichtelijk. Elke combo heeft een eigen adres. Elk subnet is een slot. 64 subnets, geen 7 lagen.
⚡ Slot → Subnet Mapping
[64 bit: DEVICE]
:
[32 bit: LAYOUT]
:
[16 bit: EVENT]
:
[16 bit: SEQ]
Bits 0–63: DEVICE
MAC + vendor ID + hardware hash. Uniek per toetsenbord. Geen meer HID spoofing.
Bits 64–95: LAYOUT
Toetsenbordindeling + taal + IME-state. US-QWERTY, NL-AZERTY, 日本語 IME — allemaal in 32 bit.
Bits 96–111: EVENT
Fysieke toets + modif. 16 bit = 65,536 combinaties. Genoeg voor analoog keyboard (drukkracht, snelheid).
Bits 112–127: SEQ
Sequentie-nummer. 16 bit = 65,535 events per tick. Wrap-around = nieuwe sessie. Geen verlies.
📋 64 Slots → IPv6 Subnets
🔄 Routing: Huidig vs. IPv6 Controller
❌ Huidige Keten (7 lagen)
vinger →
schakelaar →
matrix →
controller →
scan code →
HID report →
OS driver →
IME →
Unicode →
UTF-8
4 gaten. 7 vertalingen. ∞ injectie-punten.
✅ IPv6 Controller (1 laag)
vinger →
schakelaar →
matrix →
slot [0-63] →
IPv6-subnet →
router →
output
onbekend → 0.0.0.0 → buiten terminal
🔬 Live IPv6 Slot Router
Druk op een toets om slot → IPv6-subnet routing te zien...
/sec/toetsenbord — analoog → digitaal → IPv6
104 toetsen × 128 bit × 3.4×10³⁸ adressen