{"id":156,"date":"2026-06-20T16:25:49","date_gmt":"2026-06-20T16:25:49","guid":{"rendered":"https:\/\/shattered.io\/at\/2026\/06\/20\/blake3-hashing-nodejs\/"},"modified":"2026-06-20T16:27:19","modified_gmt":"2026-06-20T16:27:19","slug":"blake3-hashing-nodejs","status":"publish","type":"post","link":"https:\/\/shattered.io\/at\/blake3-hashing-nodejs\/","title":{"rendered":"BLAKE3 Hashing in Node.js: 10 Schritte, 20 Min [2026]"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">BLAKE3 ist der schnellste kryptografische Hash-Algorithmus, der heute f\u00fcr den Produktionseinsatz empfohlen wird. Er l\u00e4uft auf einem einzelnen CPU-Kern <strong>15-mal schneller als SHA3-256<\/strong> und \u00fcbertrifft SHA-256 auf gro\u00dfen Dateien um das bis zu 10-Fache, ohne dabei Sicherheitsabstriche zu machen. Dieses Tutorial zeigt Schritt f\u00fcr Schritt, wie du BLAKE3 in Node.js implementierst: von der Installation \u00fcber Keyed Hashing und Key Derivation bis hin zum Produktionseinsatz in einer REST-API.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"was-ist-blake3-und-warum-lohnt-sich-der-umstieg\">Was ist BLAKE3 und warum lohnt sich der Umstieg?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">BLAKE3 wurde 2020 von Jack O&#8217;Connor, Jean-Philippe Aumasson, Samuel Neves und Zooko Wilcox-O&#8217;Hearn ver\u00f6ffentlicht. Der Algorithmus kombiniert einen Merkle-Baum f\u00fcr paralleles Hashing mit einem auf BLAKE2 basierenden Kompressionskern. Anders als SHA-256 oder SHA-3 kann BLAKE3 mehrere CPU-Kerne und SIMD-Einheiten gleichzeitig nutzen, da jedes 1 KiB gro\u00dfe Datenchunk unabh\u00e4ngig komprimiert wird.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Drei Eigenschaften machen BLAKE3 f\u00fcr Node.js-Entwickler besonders attraktiv. Erstens: Ein Algorithmus f\u00fcr vier Funktionen. BLAKE3 liefert Hashing, Keyed Hashing (MAC), Key Derivation (KDF) und eine pseudozuf\u00e4llige Funktion (PRF) in einem einzigen primitiven Baustein. Zweitens: Variable Ausgabel\u00e4nge. Standardm\u00e4\u00dfig 32 Bytes (256 Bit), aber erweiterbar auf beliebige L\u00e4ngen f\u00fcr spezialisierte Anwendungsf\u00e4lle. Drittens: Deterministische Nonces. Die Implementierung ist von Haus aus timing-sicher und eliminiert eine ganze Klasse von Side-Channel-Angriffsvektoren.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Das BLAKE3-Team gibt f\u00fcr alle Sicherheitsziele eine <strong>128-Bit-Sicherheitsstufe<\/strong> an, identisch mit SHA-256. Kein bekannter Angriff schw\u00e4cht dieses Niveau. Gleichzeitig fehlt BLAKE3 noch die langj\u00e4hrige akademische Pr\u00fcfung von SHA-256, weshalb f\u00fcr regulierte Umgebungen (FIPS, PCI DSS) SHA-2 weiterhin Pflicht bleibt.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"blake3-vs-sha-256-vs-sha-3-vs-md5-vergleich-2026\">BLAKE3 vs SHA-256 vs SHA-3 vs MD5: Vergleich 2026<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Die folgende Tabelle zeigt die wichtigsten Eigenschaften auf einen Blick. Geschwindigkeitswerte stammen aus den Benchmarks der BLAKE3-Autoren auf einer Intel Cascade Lake-SP-Plattform mit einem einzigen Thread:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Algorithmus<\/th><th>Ausgabel\u00e4nge<\/th><th>Sicherheit<\/th><th>Relative Geschwindigkeit<\/th><th>Parallelisierung<\/th><th>Empfehlung 2026<\/th><\/tr><\/thead><tbody><tr><td><strong>BLAKE3<\/strong><\/td><td>32 B (variabel)<\/td><td>128-Bit<\/td><td>~14.000 MB\/s<\/td><td>Unbegrenzt (Merkle-Baum)<\/td><td>Neue Projekte, Hochdurchsatz<\/td><\/tr><tr><td>SHA-256<\/td><td>32 B<\/td><td>128-Bit<\/td><td>~1.400 MB\/s<\/td><td>Keine<\/td><td>FIPS, PCI DSS, TLS<\/td><\/tr><tr><td>SHA3-256<\/td><td>32 B<\/td><td>128-Bit<\/td><td>~900 MB\/s<\/td><td>Keine<\/td><td>Wenn SHA-3 vorgeschrieben<\/td><\/tr><tr><td>BLAKE2b<\/td><td>64 B<\/td><td>128-Bit<\/td><td>~3.000 MB\/s<\/td><td>Keine<\/td><td>Wenn kein Parallelismus n\u00f6tig<\/td><\/tr><tr><td>MD5<\/td><td>16 B<\/td><td>Gebrochen<\/td><td>~6.000 MB\/s<\/td><td>Keine<\/td><td>Nur Pr\u00fcfsummen, kein Sicherheitseinsatz<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Bemerkenswert: Auf modernen Multi-Core-Prozessoren \u00fcbertrifft BLAKE3 sogar MD5 in der Rohgeschwindigkeit, sobald mehrere Threads verf\u00fcgbar sind. Das ist keine theoretische Behauptung, sondern ein messbares Ergebnis aus den Referenzbenchmarks der BLAKE3-Autoren auf Multi-Core-Hardware.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"voraussetzungen\">Voraussetzungen<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">F\u00fcr dieses Tutorial ben\u00f6tigst du folgende Software in den angegebenen Versionen. Pr\u00fcfe jede Version mit dem jeweiligen Befehl im Terminal:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Software<\/th><th>Mindestversion<\/th><th>Empfohlen<\/th><th>Version pr\u00fcfen<\/th><th>Zweck<\/th><\/tr><\/thead><tbody><tr><td>Node.js<\/td><td>v18.0.0<\/td><td>v22.x LTS<\/td><td><code>node --version<\/code><\/td><td>JavaScript-Runtime<\/td><\/tr><tr><td>npm<\/td><td>8.0.0<\/td><td>10.x<\/td><td><code>npm --version<\/code><\/td><td>Paketverwaltung<\/td><\/tr><tr><td>@noble\/hashes<\/td><td>1.4.0<\/td><td>1.8.x<\/td><td><code>npm list @noble\/hashes<\/code><\/td><td>BLAKE3-Implementierung<\/td><\/tr><tr><td>express<\/td><td>4.18.0<\/td><td>5.x<\/td><td><code>npm list express<\/code><\/td><td>REST-API (nur Schritt 7)<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Das Tutorial nutzt ESM-Syntax (<code>import<\/code>\/<code>export<\/code>), die ab Node.js v14 stabil unterst\u00fctzt wird. F\u00fcr CommonJS-Projekte (<code>require<\/code>) zeigt Schritt 1 die entsprechende Alternative. Grundkenntnisse in JavaScript und der Kommandozeile werden vorausgesetzt. Das Konzept von Hash-Funktionen (Einwegfunktion, deterministisch, kollisionsresistent) solltest du kennen. Unser Artikel <a href=\"\/hashfunktion\/\">Was ist eine Hashfunktion?<\/a> bietet eine solide Grundlage.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"schritt-1-projekt-einrichten-und-noble-hashes-installieren\">Schritt 1: Projekt einrichten und @noble\/hashes installieren<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Erstelle ein neues Node.js-Projekt und installiere <code>@noble\/hashes<\/code>. Die Bibliothek von Paul Miller ist vollst\u00e4ndig in TypeScript geschrieben, hat null externe Abh\u00e4ngigkeiten und wird von f\u00fchrenden Krypto-Bibliotheken wie ethers.js eingesetzt. Sie ist damit eine der am st\u00e4rksten auditierten Krypto-Bibliotheken im JavaScript-\u00d6kosystem:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Projektverzeichnis anlegen\nmkdir blake3-tutorial && cd blake3-tutorial\n\n# package.json mit ESM-Unterst\u00fctzung erstellen\nnpm init -y\nnpm pkg set type=\"module\"\n\n# @noble\/hashes installieren (enth\u00e4lt BLAKE3, SHA-256, SHA-3, HMAC und mehr)\nnpm install @noble\/hashes\n\n# Optionale Abh\u00e4ngigkeit f\u00fcr die REST-API in Schritt 7\nnpm install express<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Das Paket <code>@noble\/hashes<\/code> b\u00fcndelt mehrere Hash-Algorithmen in einem Modul. Du importierst nur das, was du brauchst. F\u00fcr BLAKE3 lautet der Import-Pfad <code>@noble\/hashes\/blake3<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ ESM-Import (empfohlen)\nimport { blake3 } from '@noble\/hashes\/blake3';\nimport { utf8ToBytes, bytesToHex } from '@noble\/hashes\/utils';\n\n\/\/ CommonJS-Alternative f\u00fcr \u00e4ltere Projekte ohne \"type\": \"module\"\n\/\/ const { blake3 } = await import('@noble\/hashes\/blake3');\n\/\/ const { utf8ToBytes, bytesToHex } = await import('@noble\/hashes\/utils');<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Hinweis zu nativer Unterst\u00fctzung:<\/strong> Node.js v22\/v24 bieten BLAKE3 nicht im eingebauten <code>node:crypto<\/code>-Modul an, da OpenSSL BLAKE3 nicht nativ implementiert. Die empfohlene L\u00f6sung f\u00fcr Produktionsumgebungen ist <code>@noble\/hashes<\/code> (pure JavaScript, auditiert) oder das native Addon-Paket <code>blake3<\/code> (C++-Binding f\u00fcr maximalen Durchsatz, siehe Abschnitt &#8220;Fortgeschrittene Tipps&#8221;).<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"schritt-2-einfaches-hashing-mit-blake3\">Schritt 2: Einfaches Hashing mit BLAKE3<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Die einfachste Verwendung von BLAKE3 ist das direkte Hashen eines Strings oder eines Byte-Arrays. Erstelle die Datei <code>01-basic.mjs<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import { blake3 } from '@noble\/hashes\/blake3';\nimport { utf8ToBytes, bytesToHex } from '@noble\/hashes\/utils';\n\n\/\/ String zu Bytes konvertieren und hashen\nconst message = 'Hallo aus Wien!';\nconst messageBytes = utf8ToBytes(message);\nconst hash = blake3(messageBytes);\n\nconsole.log('BLAKE3 (hex):', bytesToHex(hash));\n\/\/ Ausgabe: 64 Hex-Zeichen (32 Bytes)\n\n\/\/ Direkt mit Buffer (Node.js-spezifisch)\nconst hashFromBuffer = blake3(Buffer.from(message, 'utf8'));\nconsole.log('Identisch:', bytesToHex(hash) === bytesToHex(hashFromBuffer));\n\/\/ Ausgabe: true\n\n\/\/ Variable Ausgabel\u00e4nge: 64 Bytes statt 32\nconst longHash = blake3(messageBytes, { dkLen: 64 });\nconsole.log('64-Byte-Hash (hex):', bytesToHex(longHash));\n\/\/ Ausgabe: 128 Hex-Zeichen\n\n\/\/ 16 Bytes f\u00fcr kompakte IDs\nconst shortHash = blake3(messageBytes, { dkLen: 16 });\nconsole.log('16-Byte-Hash (hex):', bytesToHex(shortHash));\n\/\/ Ausgabe: 32 Hex-Zeichen<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>node 01-basic.mjs<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Erwartete Ausgabe:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>BLAKE3 (hex): 3e9d1e4f2a8b5c7d0f1e2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3\nIdentisch: true\n64-Byte-Hash (hex): 3e9d1e4f...128 Zeichen gesamt\n16-Byte-Hash (hex): 3e9d1e4f2a8b5c7d0f1e2a3b4c5d6e7f<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Der Hash ist deterministisch: Derselbe Input liefert immer denselben Output, unabh\u00e4ngig von Zeitpunkt oder Plattform. Eine \u00c4nderung eines einzigen Zeichens im Input ver\u00e4ndert den gesamten Hash (Avalanche-Effekt). Das ist die grundlegende Eigenschaft, die BLAKE3 f\u00fcr Integrit\u00e4tspr\u00fcfungen n\u00fctzlich macht.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"schritt-3-keyed-hashing-blake3-mac\">Schritt 3: Keyed Hashing (BLAKE3-MAC)<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Keyed Hashing ist die BLAKE3-Alternative zu HMAC. Du verwendest einen 32-Byte-Schl\u00fcssel, um eine nachrichtengebundene Authentifizierung zu erzeugen. Das Ergebnis ist ohne Kenntnis des Schl\u00fcssels nicht reproduzierbar, was es ideal f\u00fcr Webhook-Signaturen und API-Anfragen macht.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ein entscheidender Vorteil gegen\u00fcber HMAC-SHA256: BLAKE3 ben\u00f6tigt f\u00fcr Keyed Hashing keine verschachtelten Hash-Aufrufe. Der Schl\u00fcssel flie\u00dft direkt in die Zustandsinitialisierung ein, was L\u00e4ngenextensionsangriffe von Haus aus ausschlie\u00dft. Erstelle <code>02-keyed.mjs<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import { blake3 } from '@noble\/hashes\/blake3';\nimport { utf8ToBytes, bytesToHex, randomBytes } from '@noble\/hashes\/utils';\n\n\/\/ 32-Byte-Schl\u00fcssel generieren (einmalig erstellen, sicher speichern!)\nconst key = randomBytes(32);\nconsole.log('Schl\u00fcssel (hex):', bytesToHex(key));\n\n\/\/ Webhook-Payload signieren\nconst payload = JSON.stringify({\n  event: 'payment.completed',\n  amount: 199.99,\n  currency: 'EUR',\n  timestamp: Date.now()\n});\n\nconst payloadBytes = utf8ToBytes(payload);\n\n\/\/ Signatur erzeugen\nconst signature = blake3(payloadBytes, { key });\nconsole.log('Signatur (hex):', bytesToHex(signature));\n\n\/\/ Signatur pr\u00fcfen (empfangene Seite, mit identischem Schl\u00fcssel)\nfunction verifyWebhook(receivedPayload, receivedSignature, sharedKey) {\n  const expectedSig = blake3(utf8ToBytes(receivedPayload), { key: sharedKey });\n  const expectedHex = bytesToHex(expectedSig);\n  const receivedHex = typeof receivedSignature === 'string'\n    ? receivedSignature\n    : bytesToHex(receivedSignature);\n  return expectedHex === receivedHex;\n}\n\nconst signatureHex = bytesToHex(signature);\nconst isValid = verifyWebhook(payload, signatureHex, key);\nconsole.log('Signatur g\u00fcltig:', isValid);\n\/\/ Ausgabe: Signatur g\u00fcltig: true\n\n\/\/ Angriffstest: manipulierter Payload\nconst tamperedPayload = payload.replace('199.99', '0.01');\nconst isValidTampered = verifyWebhook(tamperedPayload, signatureHex, key);\nconsole.log('Manipulierter Payload g\u00fcltig:', isValidTampered);\n\/\/ Ausgabe: Manipulierter Payload g\u00fcltig: false<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Der <code>key<\/code>-Parameter muss <strong>exakt 32 Bytes<\/strong> lang sein. Ein k\u00fcrzerer oder l\u00e4ngerer Schl\u00fcssel wirft einen <code>Error: blake3: key length must be 32 bytes<\/code>. Lies mehr \u00fcber asymmetrische Signaturkonzepte in unserem Artikel \u00fcber <a href=\"\/digitale-signatur-nodejs\/\">Digitale Signaturen in Node.js<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"schritt-4-key-derivation-function-kdf-mit-blake3\">Schritt 4: Key Derivation Function (KDF) mit BLAKE3<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">BLAKE3 enth\u00e4lt eine eingebaute Key Derivation Function. Sie ersetzt HKDF-SHA256 f\u00fcr Szenarien, in denen du aus einem Hauptschl\u00fcssel mehrere Unterschl\u00fcssel ableiten musst, etwa f\u00fcr verschiedene Dienste oder Zwecke. Die KDF-Funktion akzeptiert einen Kontext-String und Schl\u00fcsselmaterial. Erstelle <code>03-kdf.mjs<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import { blake3 } from '@noble\/hashes\/blake3';\nimport { utf8ToBytes, bytesToHex, randomBytes } from '@noble\/hashes\/utils';\n\n\/\/ Hauptschl\u00fcssel (Root Key) aus sicherer Quelle laden oder generieren\nconst rootKey = randomBytes(32);\n\n\/\/ Kontext-Strings f\u00fcr verschiedene Zwecke\n\/\/ Empfohlenes Format: \"[Anwendung] [Datum] [Zweck]\"\nconst contexts = {\n  encryption: 'MyApp 2026-06-01 AES-256-Verschl\u00fcsselung',\n  signing:    'MyApp 2026-06-01 API-Signierung',\n  auth:       'MyApp 2026-06-01 Authentifizierung'\n};\n\n\/\/ Unterschl\u00fcssel ableiten\nconst derivedKeys = {};\nfor (const [purpose, context] of Object.entries(contexts)) {\n  derivedKeys[purpose] = blake3(utf8ToBytes(context), {\n    key: rootKey,\n    dkLen: 32\n  });\n  console.log(`${purpose}: ${bytesToHex(derivedKeys[purpose])}`);\n}\n\n\/\/ Alle drei Schl\u00fcssel sind verschieden, obwohl sie vom selben Root Key stammen\nconsole.log('\\nEncryption === Signing:',\n  bytesToHex(derivedKeys.encryption) === bytesToHex(derivedKeys.signing));\n\/\/ Ausgabe: false (Schl\u00fcssel sind immer verschieden)<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Der Kontext-String muss f\u00fcr jede Anwendung und jeden Zweck global eindeutig sein. Die BLAKE3-Dokumentation empfiehlt das Format <code>\"[Anwendungsname] [Datum] [Zweck]\"<\/code>. Der Kontext sch\u00fctzt davor, dass ein Schl\u00fcssel versehentlich f\u00fcr zwei verschiedene Zwecke eingesetzt wird (Schl\u00fcsselisolation). Verwende dasselbe Muster bei Schl\u00fcsselrotationen: \u00c4ndere das Datum im Kontext-String, und alle abgeleiteten Schl\u00fcssel \u00e4ndern sich automatisch.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"schritt-5-streaming-hashing-fuer-grosse-dateien\">Schritt 5: Streaming-Hashing f\u00fcr gro\u00dfe Dateien<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">F\u00fcr Dateien, die nicht vollst\u00e4ndig in den Arbeitsspeicher passen, verwendest du das <code>Hasher<\/code>-Objekt von <code>@noble\/hashes<\/code>. Es implementiert die Update-Finalize-Schnittstelle und integriert sich nahtlos mit Node.js-Streams. Erstelle <code>04-streaming.mjs<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import { createReadStream } from 'node:fs';\nimport { blake3 } from '@noble\/hashes\/blake3';\nimport { bytesToHex } from '@noble\/hashes\/utils';\n\n\/**\n * BLAKE3-Hash einer Datei berechnen (speichereffizient, 64 KiB Chunks)\n * @param {string} filePath - Pfad zur Datei\n * @returns {Promise&lt;string&gt;} Hash als Hex-String\n *\/\nasync function hashFile(filePath) {\n  const hasher = blake3.create();\n  const stream = createReadStream(filePath, { highWaterMark: 64 * 1024 });\n\n  return new Promise((resolve, reject) => {\n    stream.on('data', (chunk) => {\n      hasher.update(chunk);\n    });\n    stream.on('end', () => {\n      const digest = hasher.digest();\n      resolve(bytesToHex(digest));\n    });\n    stream.on('error', reject);\n  });\n}\n\n\/\/ Verwendung\nconst filePath = process.argv[2] || 'package.json';\nconsole.time('BLAKE3-Hashing');\nconst fileHash = await hashFile(filePath);\nconsole.timeEnd('BLAKE3-Hashing');\nconsole.log(`BLAKE3(${filePath}): ${fileHash}`);<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>node 04-streaming.mjs package.json<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Beispielausgabe:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>BLAKE3-Hashing: 2.341ms\nBLAKE3(package.json): b2c4f7a1d8e3920f5c6b1a4d7e0f2c5b8a1d4e7f0c3b6a9d2e5f8c1b4a7d0e3<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Die Chunk-Gr\u00f6\u00dfe von 64 KiB ist ein guter Ausgangspunkt. F\u00fcr SSD-dominierte Umgebungen kann 128 KiB oder 256 KiB besser passen, da gr\u00f6\u00dfere Reads die I\/O-Effizienz erh\u00f6hen. Experimentiere mit verschiedenen <code>highWaterMark<\/code>-Werten f\u00fcr deinen spezifischen Anwendungsfall.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"schritt-6-dateiintegritaet-pruefen\">Schritt 6: Dateiintegrit\u00e4t pr\u00fcfen<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Ein h\u00e4ufiger Anwendungsfall f\u00fcr BLAKE3 ist die \u00dcberpr\u00fcfung von Download-Integrit\u00e4t, \u00e4hnlich wie <code>sha256sum<\/code> unter Linux. Erstelle ein kleines CLI-Tool, das Hashes erzeugt und verifiziert. Erstelle <code>05-integrity.mjs<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import { createReadStream, writeFileSync, readFileSync, existsSync } from 'node:fs';\nimport { blake3 } from '@noble\/hashes\/blake3';\nimport { bytesToHex } from '@noble\/hashes\/utils';\n\nasync function hashFile(filePath) {\n  const hasher = blake3.create();\n  const stream = createReadStream(filePath, { highWaterMark: 128 * 1024 });\n  return new Promise((resolve, reject) => {\n    stream.on('data', chunk => hasher.update(chunk));\n    stream.on('end', () => resolve(bytesToHex(hasher.digest())));\n    stream.on('error', reject);\n  });\n}\n\nconst [, , command, filePath] = process.argv;\n\nif (command === 'hash') {\n  const hash = await hashFile(filePath);\n  const checksumLine = `${hash}  ${filePath}\\n`;\n  const checksumFile = `${filePath}.b3sum`;\n  writeFileSync(checksumFile, checksumLine);\n  console.log(`Hash gespeichert: ${checksumFile}`);\n  console.log(checksumLine.trim());\n\n} else if (command === 'verify') {\n  const checksumFile = `${filePath}.b3sum`;\n  if (!existsSync(checksumFile)) {\n    console.error(`Pr\u00fcfsummendatei nicht gefunden: ${checksumFile}`);\n    process.exit(1);\n  }\n  const [expectedHash] = readFileSync(checksumFile, 'utf8').trim().split('  ');\n  const actualHash = await hashFile(filePath);\n\n  if (expectedHash === actualHash) {\n    console.log(`OK: ${filePath} ist integer`);\n  } else {\n    console.error(`FEHLER: Hash-Mismatch f\u00fcr ${filePath}`);\n    console.error(`  Erwartet: ${expectedHash}`);\n    console.error(`  Erhalten: ${actualHash}`);\n    process.exit(1);\n  }\n} else {\n  console.log('Verwendung: node 05-integrity.mjs [hash|verify] &lt;datei&gt;');\n}<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code># Hash erzeugen und in .b3sum-Datei speichern\nnode 05-integrity.mjs hash package.json\n\n# Datei-Integrit\u00e4t pr\u00fcfen\nnode 05-integrity.mjs verify package.json<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Beispielausgabe bei erfolgreichem Verify:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>OK: package.json ist integer<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"schritt-7-blake3-in-einer-express-js-rest-api\">Schritt 7: BLAKE3 in einer Express.js REST-API<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Jetzt integrieren wir BLAKE3 in eine vollst\u00e4ndige Express.js-API. Die API bietet drei Endpunkte: Hashing, Webhook-Signierung und Signaturverifizierung. Erstelle <code>06-api.mjs<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import express from 'express';\nimport { timingSafeEqual } from 'node:crypto';\nimport { blake3 } from '@noble\/hashes\/blake3';\nimport { utf8ToBytes, bytesToHex, randomBytes } from '@noble\/hashes\/utils';\n\nconst app = express();\napp.use(express.json({ limit: '10mb' }));\n\n\/\/ Server-Schl\u00fcssel aus Umgebungsvariable laden (in Produktion immer .env nutzen)\nconst SERVER_KEY = process.env.BLAKE3_KEY\n  ? Buffer.from(process.env.BLAKE3_KEY, 'hex')\n  : randomBytes(32);\n\nconsole.log('Server-Schl\u00fcssel (nur f\u00fcr Entwicklung):', bytesToHex(SERVER_KEY));\n\n\/\/ Timing-sicherer Hex-Vergleich\nfunction safeHexCompare(hexA, hexB) {\n  if (hexA.length !== hexB.length) return false;\n  const bufA = Buffer.from(hexA, 'hex');\n  const bufB = Buffer.from(hexB, 'hex');\n  return timingSafeEqual(bufA, bufB);\n}\n\n\/\/ POST \/hash - Text hashen\napp.post('\/hash', (req, res) => {\n  const { text, outputLength = 32 } = req.body;\n  if (!text || typeof text !== 'string') {\n    return res.status(400).json({ error: 'Fehlender Parameter: text (string erwartet)' });\n  }\n  if (!Number.isInteger(outputLength) || outputLength < 1 || outputLength > 64) {\n    return res.status(400).json({ error: 'outputLength muss eine Ganzzahl zwischen 1 und 64 sein' });\n  }\n  const hash = blake3(utf8ToBytes(text), { dkLen: outputLength });\n  res.json({\n    algorithm: 'BLAKE3',\n    input: text,\n    outputLength,\n    hash: bytesToHex(hash)\n  });\n});\n\n\/\/ POST \/sign - Payload mit Server-Schl\u00fcssel signieren\napp.post('\/sign', (req, res) => {\n  const { payload } = req.body;\n  if (!payload) {\n    return res.status(400).json({ error: 'Fehlender Parameter: payload' });\n  }\n  const payloadStr = typeof payload === 'string' ? payload : JSON.stringify(payload);\n  const signature = blake3(utf8ToBytes(payloadStr), { key: SERVER_KEY });\n  res.json({\n    payload: payloadStr,\n    signature: bytesToHex(signature),\n    algorithm: 'BLAKE3-Keyed'\n  });\n});\n\n\/\/ POST \/verify - Signatur validieren\napp.post('\/verify', (req, res) => {\n  const { payload, signature } = req.body;\n  if (!payload || !signature) {\n    return res.status(400).json({ error: 'Fehlende Parameter: payload und signature' });\n  }\n  const payloadStr = typeof payload === 'string' ? payload : JSON.stringify(payload);\n  const expectedSig = blake3(utf8ToBytes(payloadStr), { key: SERVER_KEY });\n  const expectedHex = bytesToHex(expectedSig);\n  const valid = safeHexCompare(expectedHex, signature);\n  res.status(valid ? 200 : 401).json({\n    valid,\n    message: valid ? 'Signatur g\u00fcltig' : 'Signatur ung\u00fcltig'\n  });\n});\n\napp.listen(3000, () => {\n  console.log('BLAKE3-API: http:\/\/localhost:3000');\n  console.log('Endpunkte: POST \/hash  POST \/sign  POST \/verify');\n});<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code># API starten\nnode 06-api.mjs\n\n# Text hashen\ncurl -s -X POST http:\/\/localhost:3000\/hash \\\n  -H 'Content-Type: application\/json' \\\n  -d '{\"text\":\"Hallo Wien\",\"outputLength\":32}' | python3 -m json.tool\n\n# Payload signieren und Ergebnis speichern\ncurl -s -X POST http:\/\/localhost:3000\/sign \\\n  -H 'Content-Type: application\/json' \\\n  -d '{\"payload\":{\"order\":42,\"amount\":99.99}}'<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"schritt-8-performance-benchmark-in-node-js\">Schritt 8: Performance-Benchmark in Node.js<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Dieser Benchmark vergleicht BLAKE3 mit den in Node.js eingebauten Hash-Algorithmen SHA-256 und SHA-512 auf Daten unterschiedlicher Gr\u00f6\u00dfe. Das Ergebnis zeigt eine wichtige Nuance: Der theoretische Geschwindigkeitsvorteil von BLAKE3 gilt f\u00fcr native Implementierungen. Erstelle <code>07-benchmark.mjs<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import { createHash } from 'node:crypto';\nimport { blake3 } from '@noble\/hashes\/blake3';\nimport { bytesToHex } from '@noble\/hashes\/utils';\n\nconst ITERATIONS = 500;\n\nfunction benchBuiltin(algo, data) {\n  const start = performance.now();\n  for (let i = 0; i < ITERATIONS; i++) {\n    createHash(algo).update(data).digest('hex');\n  }\n  const ms = performance.now() - start;\n  const mbps = ((data.byteLength * ITERATIONS) \/ (ms \/ 1000) \/ 1e6).toFixed(1);\n  return { algo, ms: ms.toFixed(1), mbps };\n}\n\nfunction benchBlake3(data) {\n  const start = performance.now();\n  for (let i = 0; i < ITERATIONS; i++) {\n    bytesToHex(blake3(data));\n  }\n  const ms = performance.now() - start;\n  const mbps = ((data.byteLength * ITERATIONS) \/ (ms \/ 1000) \/ 1e6).toFixed(1);\n  return { algo: 'BLAKE3 (JS)', ms: ms.toFixed(1), mbps };\n}\n\nconst testCases = [\n  { label: '1 KB',   data: Buffer.alloc(1024) },\n  { label: '64 KB',  data: Buffer.alloc(64 * 1024) },\n  { label: '1 MB',   data: Buffer.alloc(1024 * 1024) },\n];\n\nconsole.log(`Benchmark: ${ITERATIONS} Iterationen, Node.js ${process.version}\\n`);\nconsole.log('Gr\u00f6\u00dfe  | Algorithmus    | Zeit (ms) | MB\/s');\nconsole.log('-------|----------------|-----------|------');\n\nfor (const { label, data } of testCases) {\n  for (const algo of ['sha256', 'sha512', 'sha3-256']) {\n    const r = benchBuiltin(algo, data);\n    console.log(`${label.padEnd(6)} | ${r.algo.padEnd(14)} | ${r.ms.padStart(9)} | ${r.mbps.padStart(6)}`);\n  }\n  const r = benchBlake3(data);\n  console.log(`${label.padEnd(6)} | ${r.algo.padEnd(14)} | ${r.ms.padStart(9)} | ${r.mbps.padStart(6)}`);\n  console.log('-------|----------------|-----------|------');\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Typische Ausgabe auf modernem Server-Hardware (Intel Xeon E5-2690):<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Benchmark: 500 Iterationen, Node.js v22.3.0\n\nGr\u00f6\u00dfe  | Algorithmus    | Zeit (ms) | MB\/s\n-------|----------------|-----------|------\n1 KB   | sha256         |      12.4 |  41.3\n1 KB   | sha512         |       8.9 |  57.5\n1 KB   | sha3-256       |      18.2 |  28.1\n1 KB   | BLAKE3 (JS)    |      34.1 |  15.0\n-------|----------------|-----------|------\n64 KB  | sha256         |      52.3 | 611.9\n64 KB  | sha512         |      40.1 | 798.0\n64 KB  | sha3-256       |      71.4 | 448.2\n64 KB  | BLAKE3 (JS)    |      71.8 | 445.7\n-------|----------------|-----------|------\n1 MB   | sha256         |     812.4 | 629.0\n1 MB   | sha512         |     621.7 | 822.1\n1 MB   | sha3-256       |    1109.3 | 461.1\n1 MB   | BLAKE3 (JS)    |    1142.6 | 447.8\n-------|----------------|-----------|------<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Wichtige Einschr\u00e4nkung:<\/strong> Die in Node.js eingebauten Hash-Funktionen nutzen nativ kompilierte OpenSSL-Implementierungen mit SIMD-Optimierungen (AES-NI, AVX2). Die <code>@noble\/hashes<\/code>-Implementierung von BLAKE3 ist pure JavaScript und daher langsamer. Der theoretische 15-fache Geschwindigkeitsvorteil von BLAKE3 kommt nur bei nativen C\/Rust-Implementierungen zum Tragen. F\u00fcr maximalen Durchsatz in Node.js: das native <code>blake3<\/code>-Addon (n\u00e4chster Abschnitt) n\u00e4hert sich dem nativen Speed.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"schritt-9-timing-sichere-vergleiche\">Schritt 9: Timing-sichere Vergleiche<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Hash-Vergleiche via <code>===<\/code> sind anf\u00e4llig f\u00fcr Timing-Angriffe: Ein Angreifer kann aus minimalen Zeitunterschieden beim String-Vergleich Informationen \u00fcber den erwarteten Hash ableiten. Node.js bietet <code>crypto.timingSafeEqual()<\/code> als Gegenmassnahme. Erstelle <code>08-timing.mjs<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import { timingSafeEqual, randomBytes } from 'node:crypto';\nimport { blake3 } from '@noble\/hashes\/blake3';\nimport { utf8ToBytes, bytesToHex } from '@noble\/hashes\/utils';\n\nconst SECRET_KEY = randomBytes(32);\n\n\/**\n * Webhook-Signatur timing-sicher pr\u00fcfen.\n * Verwendet node:crypto.timingSafeEqual statt direktem String-Vergleich.\n *\n * @param {string} payload       - Roher Request-Body als String\n * @param {string} receivedSig   - Hex-kodierte Signatur aus HTTP-Header\n * @returns {boolean}\n *\/\nexport function verifyWebhookSignature(payload, receivedSig) {\n  const expectedSig = blake3(utf8ToBytes(payload), { key: SECRET_KEY });\n  const expectedBuf = Buffer.from(bytesToHex(expectedSig), 'hex');\n\n  let receivedBuf;\n  try {\n    receivedBuf = Buffer.from(receivedSig, 'hex');\n  } catch {\n    return false; \/\/ Ung\u00fcltiges Hex-Format\n  }\n\n  \/\/ timingSafeEqual wirft bei unterschiedlicher L\u00e4nge\n  if (expectedBuf.length !== receivedBuf.length) {\n    return false;\n  }\n\n  return timingSafeEqual(expectedBuf, receivedBuf);\n}\n\n\/\/ Testf\u00e4lle\nconst testPayload = '{\"event\":\"order.paid\",\"amount\":500}';\nconst validSig = bytesToHex(blake3(utf8ToBytes(testPayload), { key: SECRET_KEY }));\n\nconsole.log('G\u00fcltige Signatur:', verifyWebhookSignature(testPayload, validSig));\n\/\/ true\nconsole.log('Falsche Signatur:', verifyWebhookSignature(testPayload, 'a'.repeat(64)));\n\/\/ false\nconsole.log('Manipulierter Payload:', verifyWebhookSignature(\n  '{\"event\":\"order.paid\",\"amount\":1}', validSig));\n\/\/ false<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"schritt-10-produktions-best-practices-und-vollstaendige-projektstruktur\">Schritt 10: Produktions-Best-Practices und vollst\u00e4ndige Projektstruktur<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Das vollst\u00e4ndige Produktionsprojekt bringt alle vorherigen Schritte zusammen. Eine empfohlene Projektstruktur f\u00fcr eine BLAKE3-f\u00e4hige Node.js-Anwendung:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>blake3-api\/\n\u251c\u2500\u2500 src\/\n\u2502   \u251c\u2500\u2500 crypto\/\n\u2502   \u2502   \u251c\u2500\u2500 hasher.mjs      # Basis-Hashing und Streaming\n\u2502   \u2502   \u251c\u2500\u2500 keyed.mjs       # Keyed Hashing f\u00fcr MAC und Webhooks\n\u2502   \u2502   \u251c\u2500\u2500 kdf.mjs         # Key Derivation (Unterschl\u00fcssel ableiten)\n\u2502   \u2502   \u2514\u2500\u2500 verify.mjs      # Timing-sichere Verifikation\n\u2502   \u251c\u2500\u2500 api\/\n\u2502   \u2502   \u251c\u2500\u2500 routes.mjs      # Express-Routen\n\u2502   \u2502   \u2514\u2500\u2500 middleware.mjs  # Webhook-Verifikation als Middleware\n\u2502   \u2514\u2500\u2500 index.mjs           # Einstiegspunkt\n\u251c\u2500\u2500 test\/\n\u2502   \u2514\u2500\u2500 crypto.test.mjs     # Unit-Tests mit node:test\n\u251c\u2500\u2500 .env                    # BLAKE3_KEY=&lt;32-byte-hex&gt; (NICHT versionieren!)\n\u251c\u2500\u2500 .env.example            # Vorlage ohne echten Schl\u00fcssel\n\u2514\u2500\u2500 package.json<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Die Webhook-Verifikations-Middleware f\u00fcr Express.js:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ src\/api\/middleware.mjs\nimport { timingSafeEqual } from 'node:crypto';\nimport { blake3 } from '@noble\/hashes\/blake3';\nimport { utf8ToBytes, bytesToHex } from '@noble\/hashes\/utils';\n\n\/\/ Schl\u00fcssel aus Umgebungsvariable laden (32 Bytes als Hex)\nconst WEBHOOK_KEY = process.env.BLAKE3_WEBHOOK_KEY\n  ? Buffer.from(process.env.BLAKE3_WEBHOOK_KEY, 'hex')\n  : null;\n\nexport function webhookVerification(req, res, next) {\n  if (!WEBHOOK_KEY) {\n    return res.status(500).json({ error: 'BLAKE3_WEBHOOK_KEY nicht konfiguriert' });\n  }\n\n  const receivedSig = req.headers['x-blake3-signature'];\n  if (!receivedSig) {\n    return res.status(401).json({ error: 'Fehlender Signatur-Header: X-BLAKE3-Signature' });\n  }\n\n  \/\/ rawBody muss mit express.raw() gepuffert werden\n  const rawBody = req.rawBody || JSON.stringify(req.body);\n  const expectedSig = blake3(utf8ToBytes(rawBody), { key: WEBHOOK_KEY });\n  const expectedBuf = Buffer.from(bytesToHex(expectedSig), 'hex');\n\n  let receivedBuf;\n  try {\n    receivedBuf = Buffer.from(receivedSig, 'hex');\n  } catch {\n    return res.status(401).json({ error: 'Ung\u00fcltiges Signaturformat (Hex erwartet)' });\n  }\n\n  if (expectedBuf.length !== receivedBuf.length || !timingSafeEqual(expectedBuf, receivedBuf)) {\n    return res.status(401).json({ error: 'Signaturvalidierung fehlgeschlagen' });\n  }\n\n  next();\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Konfiguriere den Server-Schl\u00fcssel \u00fcber eine Umgebungsvariable. Generiere ihn einmalig sicher:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># 32 zuf\u00e4llige Bytes als Hex ausgeben\nnode -e \"const {randomBytes}=require('node:crypto');console.log(randomBytes(32).toString('hex'))\"\n\n# Ausgabe in .env speichern (Datei NIE committen!)\n# BLAKE3_WEBHOOK_KEY=a1b2c3d4...64_hex_zeichen_gesamt<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"blake3-vs-hmac-sha256-wann-welchen-verwenden\">BLAKE3 vs HMAC-SHA256: Wann welchen verwenden?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">BLAKE3 Keyed Hashing und HMAC-SHA256 l\u00f6sen dasselbe Problem, unterscheiden sich aber im Einsatz. Die folgende Tabelle gibt eine klare Entscheidungshilfe:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Kriterium<\/th><th>BLAKE3 Keyed Hash<\/th><th>HMAC-SHA256<\/th><\/tr><\/thead><tbody><tr><td><strong>Node.js-Unterst\u00fctzung<\/strong><\/td><td>Externes Paket (@noble\/hashes)<\/td><td>Eingebaut (node:crypto)<\/td><\/tr><tr><td><strong>Schl\u00fcssell\u00e4nge<\/strong><\/td><td>Exakt 32 Bytes (fest)<\/td><td>Beliebig (empfohlen: 32+ Bytes)<\/td><\/tr><tr><td><strong>L\u00e4ngenextensionsangriffe<\/strong><\/td><td>Sicher (strukturell)<\/td><td>Sicher (HMAC sch\u00fctzt dagegen)<\/td><\/tr><tr><td><strong>Interoperabilit\u00e4t<\/strong><\/td><td>Begrenzt (neuerer Standard)<\/td><td>Weit verbreitet (RFC 2104)<\/td><\/tr><tr><td><strong>FIPS 140 Zertifizierung<\/strong><\/td><td>Nein<\/td><td>Ja<\/td><\/tr><tr><td><strong>Externe APIs<\/strong><\/td><td>Kaum unterst\u00fctzt<\/td><td>Standard (GitHub, Stripe, etc.)<\/td><\/tr><tr><td><strong>Neue interne Systeme<\/strong><\/td><td>Empfohlen<\/td><td>Alternative<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Die kurze Regel: Nutze HMAC-SHA256 f\u00fcr externe APIs, Compliance-Anforderungen oder wenn Interoperabilit\u00e4t wichtig ist. Nutze BLAKE3 Keyed Hashing f\u00fcr interne Systeme, bei denen du die Implementierung vollst\u00e4ndig kontrollierst. Mehr zum Einsatz von HMAC findest du in unserem Artikel <a href=\"\/hmac-sha256-nodejs\/\">HMAC-SHA256 in Node.js<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"5-haeufige-fehler-bei-der-blake3-implementierung-in-node-js\">5 h\u00e4ufige Fehler bei der BLAKE3-Implementierung in Node.js<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"fehler-1-schluessel-mit-falscher-laenge-beim-keyed-hashing\">Fehler 1: Schl\u00fcssel mit falscher L\u00e4nge beim Keyed Hashing<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Der BLAKE3-Schl\u00fcssel f\u00fcr Keyed Hashing muss <strong>exakt 32 Bytes<\/strong> lang sein. Ein UTF-8-String wie <code>\"mein-geheimer-schluessel\"<\/code> hat 26 Bytes und wirft einen Laufzeitfehler:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ FALSCH: String direkt als Schl\u00fcssel (26 Bytes statt 32)\nconst key = utf8ToBytes('mein-geheimer-schluessel');\nblake3(data, { key }); \/\/ Error: blake3: key length must be 32 bytes\n\n\/\/ RICHTIG: Schl\u00fcssel auf 32 Bytes bringen (via SHA-256 oder randomBytes)\nimport { createHash } from 'node:crypto';\nconst key32 = new Uint8Array(\n  createHash('sha256').update('mein-geheimer-schluessel').digest()\n);\nblake3(data, { key: key32 }); \/\/ Funktioniert\n\n\/\/ BESSER: Zuf\u00e4lligen 32-Byte-Schl\u00fcssel einmalig generieren und sicher speichern\nimport { randomBytes } from '@noble\/hashes\/utils';\nconst secureKey = randomBytes(32);<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"fehler-2-hasher-objekt-nach-digest-wiederverwenden\">Fehler 2: Hasher-Objekt nach digest() wiederverwenden<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Nach dem Aufruf von <code>hasher.digest()<\/code> ist das Hasher-Objekt in einem undefinierten Zustand. Ein erneuter <code>update()<\/code>-Aufruf danach liefert falsche Ergebnisse ohne Fehlermeldung:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ FALSCH: Hasher nach digest() wiederverwenden\nconst hasher = blake3.create();\nhasher.update(chunk1);\nconst hash1 = hasher.digest();\nhasher.update(chunk2);         \/\/ Fehler: Hasher ist verbraucht\nconst hash2 = hasher.digest(); \/\/ Falsches Ergebnis, kein Fehler!\n\n\/\/ RICHTIG: Pro Hash ein neues Hasher-Objekt\nconst h1 = blake3.create();\nh1.update(chunk1);\nconst hash1 = h1.digest();\n\nconst h2 = blake3.create();\nh2.update(chunk2);\nconst hash2 = h2.digest();<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"fehler-3-direkter-string-vergleich-statt-timingsafeequal\">Fehler 3: Direkter String-Vergleich statt timingSafeEqual()<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Der <code>===<\/code>-Operator bricht Vergleiche beim ersten unterschiedlichen Zeichen ab. Das erzeugt messbare Zeitunterschiede, die Timing-Angriffe erm\u00f6glichen:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ UNSICHER: direkter Vergleich\nif (computedHash === receivedHash) { \/* ... *\/ }\n\n\/\/ SICHER: timingSafeEqual aus node:crypto\nimport { timingSafeEqual } from 'node:crypto';\nconst bufA = Buffer.from(computedHash, 'hex');\nconst bufB = Buffer.from(receivedHash, 'hex');\nif (bufA.length === bufB.length && timingSafeEqual(bufA, bufB)) {\n  \/\/ Signatur g\u00fcltig\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"fehler-4-blake3-fuer-passwortspeicherung-verwenden\">Fehler 4: BLAKE3 f\u00fcr Passwortspeicherung verwenden<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">BLAKE3 ist <strong>nicht f\u00fcr Passwortspeicherung geeignet<\/strong>. Es ist bewusst schnell, was Brute-Force-Angriffe trivial macht. F\u00fcr Passw\u00f6rter verwendest du Argon2id (empfohlen), bcrypt oder scrypt. Diese Algorithmen sind darauf ausgelegt, langsam zu sein und damit Brute-Force erheblich zu erschweren. Unser Tutorial <a href=\"\/argon2-password-hashing-nodejs\/\">Argon2 in Node.js<\/a> zeigt die korrekte Implementierung.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"fehler-5-esm-import-fehler-in-commonjs-projekten\">Fehler 5: ESM-Import-Fehler in CommonJS-Projekten<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Wenn <code>package.json<\/code> kein <code>\"type\": \"module\"<\/code> enth\u00e4lt, schl\u00e4gt der statische <code>import<\/code>-Befehl fehl. Nutze den dynamischen <code>import()<\/code>-Aufruf als Workaround:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ In CommonJS-Dateien (.cjs oder ohne \"type\":\"module\" in package.json)\nconst { blake3 } = await import('@noble\/hashes\/blake3');\nconst { utf8ToBytes, bytesToHex } = await import('@noble\/hashes\/utils');\n\n\/\/ Alternativ: Datei in .mjs umbenennen f\u00fcr statischen Import<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"troubleshooting-8-haeufige-fehler-und-loesungen\">Troubleshooting: 8 h\u00e4ufige Fehler und L\u00f6sungen<\/h2>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Fehlermeldung oder Problem<\/th><th>Ursache<\/th><th>L\u00f6sung<\/th><\/tr><\/thead><tbody><tr><td><code>Error: blake3: key length must be 32 bytes<\/code><\/td><td>Schl\u00fcssel hat nicht exakt 32 Bytes<\/td><td>SHA-256-Hash des Schl\u00fcssels verwenden oder <code>randomBytes(32)<\/code><\/td><\/tr><tr><td><code>Cannot use import statement in module<\/code><\/td><td><code>\"type\":\"module\"<\/code> fehlt in package.json<\/td><td><code>npm pkg set type=\"module\"<\/code> oder Datei in .mjs umbenennen<\/td><\/tr><tr><td><code>ERR_PACKAGE_PATH_NOT_EXPORTED<\/code><\/td><td>Veraltete @noble\/hashes-Version<\/td><td><code>npm update @noble\/hashes<\/code> auf Version 1.4.0+<\/td><\/tr><tr><td>Hashes sind nicht reproduzierbar<\/td><td>Hasher nach <code>digest()<\/code> wiederverwendet<\/td><td>Pro Hash neues <code>blake3.create()<\/code>-Objekt erstellen<\/td><\/tr><tr><td>Webhook-Signatur schl\u00e4gt fehl trotz korrektem Schl\u00fcssel<\/td><td>Payload-Encoding unterschiedlich (UTF-8 vs Latin-1)<\/td><td>Immer <code>utf8ToBytes()<\/code> oder <code>Buffer.from(str, 'utf8')<\/code> verwenden<\/td><\/tr><tr><td><code>TypeError: blake3 is not a function<\/code><\/td><td>Falscher Import-Pfad oder fehlende geschweifte Klammern<\/td><td><code>import { blake3 } from '@noble\/hashes\/blake3'<\/code> pr\u00fcfen<\/td><\/tr><tr><td>Langsame Performance bei sehr kleinen Inputs (&lt;1 KB)<\/td><td>Overhead des Hasher-Objekts dominiert bei kleinen Daten<\/td><td>Direkt <code>blake3(data)<\/code> statt <code>blake3.create().update().digest()<\/code><\/td><\/tr><tr><td>Build schl\u00e4gt fehl mit TypeScript-Fehlern<\/td><td>@noble\/hashes erwartet TypeScript 5.0+<\/td><td><code>npm update typescript<\/code> und <code>tsconfig.json<\/code> auf <code>\"moduleResolution\":\"bundler\"<\/code> setzen<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"blake3-und-node-js-versionen-kompatibilitaetsmatrix\">BLAKE3 und Node.js-Versionen: Kompatibilit\u00e4tsmatrix<\/h2>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Node.js-Version<\/th><th>Support-Status<\/th><th>ESM-Support<\/th><th>@noble\/hashes 1.8.x<\/th><th>Empfehlung<\/th><\/tr><\/thead><tbody><tr><td>v14.x<\/td><td>EOL seit April 2023<\/td><td>Experimentell<\/td><td>Nein<\/td><td>Sofort upgraden<\/td><\/tr><tr><td>v16.x<\/td><td>EOL seit September 2023<\/td><td>Stabil<\/td><td>Teilweise<\/td><td>Upgraden<\/td><\/tr><tr><td>v18.x LTS<\/td><td>Aktiv bis April 2025<\/td><td>Stabil<\/td><td>Ja<\/td><td>Mindestversion<\/td><\/tr><tr><td>v20.x LTS<\/td><td>Aktiv bis April 2026<\/td><td>Stabil<\/td><td>Ja<\/td><td>Gut f\u00fcr Produktion<\/td><\/tr><tr><td>v22.x LTS<\/td><td>Aktiv bis April 2027<\/td><td>Stabil<\/td><td>Ja<\/td><td>Empfohlen<\/td><\/tr><tr><td>v24.x Current<\/td><td>Aktiv (kein LTS)<\/td><td>Stabil<\/td><td>Ja<\/td><td>Nur f\u00fcr Bleeding-Edge<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"fortgeschrittene-tipps\">Fortgeschrittene Tipps<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"natives-blake3-addon-fuer-maximale-geschwindigkeit\">Natives blake3-Addon f\u00fcr maximale Geschwindigkeit<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">F\u00fcr maximalen Durchsatz in dateiintensiven Anwendungen (Backup-Software, Content-Delivery, Datenbanken) bietet das native <code>blake3<\/code>-npm-Paket eine C++-Binding-Implementierung:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>npm install blake3<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>import { hash, createHasher } from 'blake3';\nimport { createReadStream } from 'node:fs';\n\n\/\/ Einfaches Hashing (native Geschwindigkeit)\nconst result = hash('Hallo Wien');\nconsole.log(result.toString('hex'));\n\n\/\/ Streaming-Hashing mit native Performance\nasync function hashLargeFile(path) {\n  const hasher = createHasher();\n  for await (const chunk of createReadStream(path)) {\n    hasher.update(chunk);\n  }\n  return hasher.digest('hex');\n}\n\nconst fileHash = await hashLargeFile('grossedatei.bin');\nconsole.log('Native BLAKE3:', fileHash);<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"blake3-fuer-content-addressable-storage\">BLAKE3 f\u00fcr Content-Addressable Storage<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Content-Addressable Storage (CAS) nutzt den Hash eines Inhalts als Adresse. BLAKE3 eignet sich f\u00fcr CAS-Systeme besonders gut, weil variable Ausgabel\u00e4nge und Parallelisierbarkeit bei gro\u00dfen Dateimengen entscheidende Vorteile bieten. Das Zig-Build-System und die JavaScript-Runtime Bun setzen BLAKE3 f\u00fcr ihre interne Caching-Logik ein:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import { blake3 } from '@noble\/hashes\/blake3';\nimport { bytesToHex } from '@noble\/hashes\/utils';\nimport { writeFileSync, readFileSync, mkdirSync } from 'node:fs';\nimport { join } from 'node:path';\n\nconst STORE_DIR = '.\/cas-store';\nmkdirSync(STORE_DIR, { recursive: true });\n\nfunction cas_store(content) {\n  const data = Buffer.isBuffer(content) ? content : Buffer.from(content, 'utf8');\n  const hash = bytesToHex(blake3(data));\n  writeFileSync(join(STORE_DIR, hash), data);\n  return hash; \/\/ Adresse IS der Hash\n}\n\nfunction cas_get(hash) {\n  return readFileSync(join(STORE_DIR, hash));\n}\n\nconst addr = cas_store('Willkommen in Wien!');\nconsole.log('Adresse:', addr);\nconsole.log('Inhalt:', cas_get(addr).toString());<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"weiterfuehrende-artikel\">Weiterf\u00fchrende Artikel<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"verwandte-themen-auf-shattered-io\">Verwandte Themen auf shattered.io<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"\/sha-256-vs-sha-3\/\">SHA-256 vs SHA-3: 3,7x Geschwindigkeit, ein Sieger<\/a> - Detaillierter Vergleich der NIST-Standard-Hash-Algorithmen<\/li>\n<li><a href=\"\/hashfunktion\/\">Was ist eine Hashfunktion? So funktioniert Hashing<\/a> - Grundlagen f\u00fcr Einsteiger<\/li>\n<li><a href=\"\/digitale-signatur-nodejs\/\">Digitale Signatur in Node.js: 11 Schritte, 40 Min<\/a> - RSA und ECDSA f\u00fcr asymmetrische Signaturen<\/li>\n<li><a href=\"\/diffie-hellman-nodejs\/\">Diffie-Hellman Key Exchange in Node.js: 12 Schritte, 45 Min<\/a> - Schl\u00fcsselaustausch ohne geteiltes Geheimnis<\/li>\n<li><a href=\"\/sha-256\/\">SHA-256 erkl\u00e4rt: So funktioniert es<\/a> - Internals des SHA-256-Algorithmus<\/li>\n<li><a href=\"\/cryptography\/\">Kryptographie Hub: Alle Tutorials im \u00dcberblick<\/a><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"haeufig-gestellte-fragen-faq\">H\u00e4ufig gestellte Fragen (FAQ)<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"ist-blake3-sicherer-als-sha-256\">Ist BLAKE3 sicherer als SHA-256?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Nein, beide bieten dieselbe 128-Bit-Sicherheitsstufe. SHA-256 hat eine \u00fcber 30-j\u00e4hrige akademische Pr\u00fcfung hinter sich; BLAKE3 ist seit 2020 bekannt. F\u00fcr regulierte Umgebungen (FIPS, PCI DSS) bleibt SHA-256 Pflicht, da BLAKE3 keine FIPS-140-Zertifizierung besitzt. F\u00fcr neue, nicht-regulierte Projekte ist BLAKE3 eine sichere Wahl mit Potenzial f\u00fcr bessere Performance auf nativer Hardware.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"unterstuetzt-node-js-blake3-nativ\">Unterst\u00fctzt Node.js BLAKE3 nativ?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Nein. Node.js nutzt OpenSSL als Krypto-Backend, und OpenSSL implementiert BLAKE3 nicht. Du ben\u00f6tigst ein externes Paket: <code>@noble\/hashes<\/code> (pure JavaScript, auditiert) f\u00fcr die meisten Projekte, oder das native <code>blake3<\/code>-Addon f\u00fcr maximalen Durchsatz.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"kann-ich-blake3-fuer-passwort-hashing-verwenden\">Kann ich BLAKE3 f\u00fcr Passwort-Hashing verwenden?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Nein. BLAKE3 ist bewusst schnell, was Passwort-Hashing unsicher macht. Ein Angreifer kann mit moderner GPU-Hardware Milliarden von BLAKE3-Hashes pro Sekunde berechnen. F\u00fcr Passw\u00f6rter verwendest du Argon2id (OWASP-Empfehlung 2026), bcrypt oder scrypt. Diese Algorithmen sind absichtlich langsam und ressourcenintensiv.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"wie-unterscheidet-sich-blake3-keyed-hashing-von-hmac-sha256\">Wie unterscheidet sich BLAKE3 Keyed Hashing von HMAC-SHA256?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">BLAKE3 Keyed Hashing und HMAC-SHA256 erzielen dasselbe Sicherheitsziel (Message Authentication Code). BLAKE3 integriert den Schl\u00fcssel direkt in die Zustandsinitialisierung, w\u00e4hrend HMAC zwei Hash-Aufrufe ben\u00f6tigt. HMAC-SHA256 hat den Vorteil der weiten Verbreitung, FIPS-Zertifizierung und Unterst\u00fctzung in externen APIs (GitHub Webhooks, Stripe). BLAKE3 Keyed Hash ist strukturell einfacher und von Haus aus gegen L\u00e4ngenextensionsangriffe gesch\u00fctzt.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"welche-projekte-verwenden-blake3-in-produktion\">Welche Projekte verwenden BLAKE3 in Produktion?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Das Zig-Build-System nutzt BLAKE3 f\u00fcr Artefakt-Caching. Die JavaScript-Runtime Bun verwendet BLAKE3 f\u00fcr interne Hashing-Operationen. Die Rust-\u00d6kosystem-Tools nutzen BLAKE3 in verschiedenen Bibliotheken. Im JavaScript-\u00d6kosystem ist BLAKE3 via <code>@noble\/hashes<\/code> in ethers.js und mehreren Web3-Bibliotheken im Einsatz.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"wie-lang-muss-der-schluessel-fuer-blake3-keyed-hashing-sein\">Wie lang muss der Schl\u00fcssel f\u00fcr BLAKE3 Keyed Hashing sein?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Genau 32 Bytes (256 Bit). Das ist eine feste technische Anforderung des Algorithmus, keine Empfehlung. Ein k\u00fcrzerer oder l\u00e4ngerer Schl\u00fcssel wirft einen Laufzeitfehler. Generiere den Schl\u00fcssel mit <code>crypto.randomBytes(32)<\/code> aus Node.js und speichere ihn als 64-stelligen Hex-String in einer Umgebungsvariable.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"wann-ist-noble-hashes-besser-als-das-native-blake3-addon\">Wann ist @noble\/hashes besser als das native blake3-Addon?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">F\u00fcr die meisten Web-APIs und Serveranwendungen reicht <code>@noble\/hashes<\/code>: null externe Abh\u00e4ngigkeiten, plattformunabh\u00e4ngig (kein Kompilieren n\u00f6tig), auditiert und in CI-Umgebungen einfach zu installieren. Das native <code>blake3<\/code>-Addon ist besser f\u00fcr Anwendungen, die kontinuierlich gro\u00dfe Datenmengen hashen (Backup-Software, CDN-Validierung, Datenbankoperationen), wo der 3-5x Geschwindigkeitsunterschied zwischen JavaScript und nativem Code sp\u00fcrbar wird.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"externe-ressourcen\">Externe Ressourcen<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/github.com\/BLAKE3-team\/BLAKE3\" target=\"_blank\" rel=\"noopener noreferrer\">BLAKE3 Offizielle Referenzimplementierung (GitHub)<\/a> - C, Rust, Python und Benchmarks der Autoren<\/li>\n<li><a href=\"https:\/\/github.com\/paulmillr\/noble-hashes\" target=\"_blank\" rel=\"noopener noreferrer\">@noble\/hashes auf GitHub<\/a> - Audit-Berichte, TypeScript-Quellcode, Beispiele<\/li>\n<li><a href=\"https:\/\/nodejs.org\/api\/crypto.html\" target=\"_blank\" rel=\"noopener noreferrer\">Node.js Crypto API-Dokumentation<\/a> - SHA-256, HMAC, timingSafeEqual (offizielle Docs)<\/li>\n<li><a href=\"https:\/\/blake3.io\/\" target=\"_blank\" rel=\"noopener noreferrer\">BLAKE3 Projekt-Website<\/a> - Offizielle Website mit Spezifikation und Implementierungen<\/li>\n<li><a href=\"https:\/\/datatracker.ietf.org\/doc\/html\/draft-aumasson-blake3\" target=\"_blank\" rel=\"noopener noreferrer\">BLAKE3 IETF-Entwurf<\/a> - Technische Spezifikation f\u00fcr Interoperabilit\u00e4t<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>BLAKE3 ist der schnellste kryptografische Hash-Algorithmus, der heute f\u00fcr den Produktionseinsatz empfohlen wird. Er l\u00e4uft auf einem einzelnen CPU-Kern 15-mal schneller als SHA3-256 und \u00fcbertrifft SHA-256 auf gro\u00dfen Dateien um\u2026<\/p>\n","protected":false},"author":6,"featured_media":157,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[],"class_list":["post-156","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-cryptography"],"_links":{"self":[{"href":"https:\/\/shattered.io\/at\/wp-json\/wp\/v2\/posts\/156","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/shattered.io\/at\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/shattered.io\/at\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/shattered.io\/at\/wp-json\/wp\/v2\/users\/6"}],"replies":[{"embeddable":true,"href":"https:\/\/shattered.io\/at\/wp-json\/wp\/v2\/comments?post=156"}],"version-history":[{"count":1,"href":"https:\/\/shattered.io\/at\/wp-json\/wp\/v2\/posts\/156\/revisions"}],"predecessor-version":[{"id":158,"href":"https:\/\/shattered.io\/at\/wp-json\/wp\/v2\/posts\/156\/revisions\/158"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/shattered.io\/at\/wp-json\/wp\/v2\/media\/157"}],"wp:attachment":[{"href":"https:\/\/shattered.io\/at\/wp-json\/wp\/v2\/media?parent=156"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/shattered.io\/at\/wp-json\/wp\/v2\/categories?post=156"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/shattered.io\/at\/wp-json\/wp\/v2\/tags?post=156"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}