Signatur
Beschreibung
AesCtrParams ist ein Wörterbuch (Dictionary) der Web Crypto API, also kein Konstruktor und keine Klasse. Man übergibt ein einfaches Objektliteral als algorithm-Argument an crypto.subtle.encrypt(), decrypt(), wrapKey() oder unwrapKey(), wenn ein AES-Schlüssel im Counter-Modus (CTR) verwendet werden soll.
Im CTR-Modus wird ein 16 Byte großer Zählerblock verschlüsselt. Das Ergebnis wird per XOR mit dem Klartext verknüpft. Der Zählerblock besteht aus zwei Teilen: einer Nonce (einmalig pro Nachricht) in den oberen Bits und dem eigentlichen Zähler in den unteren length Bits. Der Zähler wird für jeden Block um eins erhöht. So wird AES zu einer Stromchiffre: Es ist kein Padding nötig, und Geheimtext und Klartext sind gleich lang.
AES-CTR eignet sich, wenn Sie beliebig lange Daten ohne Padding verschlüsseln wollen oder zu anderen Systemen kompatibel sein müssen, die CTR verwenden. Der Modus bietet aber keine Integritätsprüfung: Ein Angreifer kann einzelne Bits im Geheimtext unbemerkt umkippen. Für neue Anwendungen ist daher meist AES-GCM die bessere Wahl. Wenn Sie trotzdem CTR verwenden, sichern Sie die Daten zusätzlich mit einem MAC ab, zum Beispiel HMAC.
Wichtig: Zum Entschlüsseln müssen exakt dieselben Werte für counter und length verwendet werden wie beim Verschlüsseln. Der Zählerblock ist nicht geheim und wird üblicherweise zusammen mit dem Geheimtext gespeichert oder übertragen.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $name Pflicht | string | Muss "AES-CTR" sein. Groß-/Kleinschreibung wird nicht beachtet. |
|
| $counter Pflicht | ArrayBuffer | TypedArray | DataView | Der anfängliche Zählerblock, genau 16 Byte lang (eine AES-Blockgröße). Die oberen Bits bilden die Nonce, die unteren length Bits den Zähler, der hochgezählt wird. Mit demselben Schlüssel darf der Zählerblock niemals wiederverwendet werden. |
|
| $length Pflicht | number | Anzahl der Bits im Zählerblock (1–128), die als eigentlicher Zähler dienen. Die restlichen 128 - length Bits bleiben als Nonce unverändert. Üblich ist 64. Läuft der Zähler über, wirft der Browser einen OperationError. |
Rückgabewert
AesCtrParams ist ein reines Parameter-Objekt ohne eigenen Rückgabewert. Die Methoden, die es verwenden, geben ein Promise<ArrayBuffer> (encrypt/decrypt/wrapKey) bzw. ein Promise<CryptoKey> (unwrapKey) zurück.Beispiele
Text mit AES-CTR verschlüsseln und wieder entschlüsseln
const key = await crypto.subtle.generateKey(
{ name: 'AES-CTR', length: 256 },
true,
['encrypt', 'decrypt']
);
// 16-Byte-Zählerblock: zufällige Nonce, die unteren 64 Bit dienen als Zähler
const counter = crypto.getRandomValues(new Uint8Array(16));
const params = { name: 'AES-CTR', counter, length: 64 };
const plaintext = new TextEncoder().encode('Geheime Nachricht');
const ciphertext = await crypto.subtle.encrypt(params, key, plaintext);
console.log('Länge Geheimtext:', ciphertext.byteLength);
// Entschlüsseln mit exakt denselben Parametern
const decrypted = await crypto.subtle.decrypt(params, key, ciphertext);
console.log(new TextDecoder().decode(decrypted));
Zählerblock zusammen mit dem Geheimtext speichern
const encryptPacked = async (key, text) => {
const counter = crypto.getRandomValues(new Uint8Array(16));
const data = new TextEncoder().encode(text);
const ct = new Uint8Array(
await crypto.subtle.encrypt({ name: 'AES-CTR', counter, length: 64 }, key, data)
);
// Format: [16 Byte Zählerblock | Geheimtext]
const packed = new Uint8Array(16 + ct.length);
packed.set(counter, 0);
packed.set(ct, 16);
return packed;
};
const decryptPacked = async (key, packed) => {
const counter = packed.slice(0, 16);
const ct = packed.slice(16);
const pt = await crypto.subtle.decrypt({ name: 'AES-CTR', counter, length: 64 }, key, ct);
return new TextDecoder().decode(pt);
};
const key = await crypto.subtle.generateKey({ name: 'AES-CTR', length: 128 }, false, ['encrypt', 'decrypt']);
const blob = await encryptPacked(key, 'Hallo Welt');
console.log(blob.length);
console.log(await decryptPacked(key, blob));
Einen Schlüssel mit AES-CTR ein- und auspacken (wrapKey/unwrapKey)
const wrappingKey = await crypto.subtle.generateKey(
{ name: 'AES-CTR', length: 256 }, false, ['wrapKey', 'unwrapKey']
);
const hmacKey = await crypto.subtle.generateKey(
{ name: 'HMAC', hash: 'SHA-256' }, true, ['sign', 'verify']
);
const counter = crypto.getRandomValues(new Uint8Array(16));
const params = { name: 'AES-CTR', counter, length: 64 };
const wrapped = await crypto.subtle.wrapKey('raw', hmacKey, wrappingKey, params);
const restored = await crypto.subtle.unwrapKey(
'raw', wrapped, wrappingKey, params,
{ name: 'HMAC', hash: 'SHA-256' }, true, ['sign', 'verify']
);
console.log(restored.algorithm.name, restored.type);
// Wichtig · Fallstricke
- Zählerblock niemals wiederverwenden: Wird dieselbe Kombination aus Schlüssel und
counterfür zwei Nachrichten verwendet, kann ein Angreifer per XOR der beiden Geheimtexte Rückschlüsse auf die Klartexte ziehen. Erzeugen Sie für jede Nachricht eine neue Nonce, zum Beispiel mitcrypto.getRandomValues(). - Keine Authentifizierung: AES-CTR erkennt keine Manipulation. Ein falscher Schlüssel oder ein veränderter Geheimtext führt nicht zu einem Fehler, sondern nur zu unbrauchbaren Daten. Verwenden Sie AES-GCM oder sichern Sie die Daten zusätzlich mit HMAC ab (Encrypt-then-MAC).
countermuss exakt 16 Byte lang sein undlengthzwischen 1 und 128 liegen. Sonst wird das Promise mit einemOperationErrorabgelehnt. Ein kleineslengthbegrenzt die maximale Datenmenge pro Nachricht auf 2length Blöcke à 16 Byte.- Die Parameter
counterundlengthgehören zuAesCtrParams. Nicht verwechseln mitlengthinAesKeyGenParams: Dort steht es für die Schlüssellänge (128/192/256). - Kompatibilität:
crypto.subtleist nur in einem sicheren Kontext (HTTPS oder localhost) verfügbar. Alle modernen Browser unterstützen AES-CTR, ebenso Node.js ab Version 15 überglobalThis.crypto.subtlebzw.require('node:crypto').webcrypto.