Skip to content

Commit a2c128a

Browse files
bartlomiejuclaude
andauthored
fix(ext/node): add chacha20-poly1305 cipher support (#33084)
## Summary Implements the ChaCha20-Poly1305 AEAD cipher (RFC 8439) for `node:crypto` `createCipheriv`/`createDecipheriv`. The implementation uses the `chacha20` and `poly1305` crates: 1. Derive Poly1305 key from first 32 bytes of ChaCha20 keystream (counter=0) 2. Encrypt/decrypt with ChaCha20 starting at counter=1 3. Compute auth tag per RFC 8439: `Poly1305(AAD || pad || CT || pad || len(AAD) || len(CT))` Supports streaming `update()`/`final()` with `setAAD()` and `getAuthTag()`. Closes #28411 --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent f79eedc commit a2c128a

7 files changed

Lines changed: 251 additions & 2 deletions

File tree

Cargo.lock

Lines changed: 24 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,7 @@ aes = "=0.8.3"
384384
aes-gcm = "0.10"
385385
aes-kw = "0.2.1"
386386
blake2 = "0.10.6"
387+
chacha20 = "0.9"
387388
const-oid = "0.9.5"
388389
ctr = { version = "0.9.2", features = ["alloc"] }
389390
curve25519-dalek = "4.1.3"
@@ -407,6 +408,7 @@ p384 = { version = "0.13.0", features = ["ecdh", "jwk"] }
407408
p521 = { version = "0.13.3", features = ["ecdh", "ecdsa", "jwk", "pkcs8"] }
408409
pbkdf2 = "0.12.1"
409410
pkcs8 = "0.10.2"
411+
poly1305 = "0.8"
410412
ripemd = "0.1.3"
411413
rsa = { version = "0.9.9", default-features = false, features = ["std", "pem", "hazmat"] } # hazmat needed for PrehashSigner in ext/node
412414
scrypt = "0.11.0"

ext/node/polyfills/internal/crypto/cipher.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ export function Cipheriv(
221221
this._needsBlockCache =
222222
!(cipher == "aes-128-gcm" || cipher == "aes-256-gcm" ||
223223
cipher == "aes-128-ctr" || cipher == "aes-192-ctr" ||
224-
cipher == "aes-256-ctr");
224+
cipher == "aes-256-ctr" || cipher == "chacha20-poly1305");
225225
this._authTag = undefined;
226226
this._autoPadding = true;
227227
this._finalized = false;
@@ -467,7 +467,7 @@ export function Decipheriv(
467467
this._needsBlockCache =
468468
!(cipher == "aes-128-gcm" || cipher == "aes-256-gcm" ||
469469
cipher == "aes-128-ctr" || cipher == "aes-192-ctr" ||
470-
cipher == "aes-256-ctr");
470+
cipher == "aes-256-ctr" || cipher == "chacha20-poly1305");
471471
this._authTag = undefined;
472472
this._finalized = false;
473473
this._decoder = undefined;

ext/node/polyfills/internal/crypto/util.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,14 @@ const cipherInfoTable: CipherInfoResult[] = [
188188
keyLength: 32,
189189
mode: "ctr",
190190
},
191+
{
192+
name: "chacha20-poly1305",
193+
nid: 1018,
194+
blockSize: 1,
195+
ivLength: 12,
196+
keyLength: 32,
197+
mode: "",
198+
},
191199
];
192200

193201
const cipherInfoByName = new Map<string, CipherInfoResult>();
@@ -218,6 +226,7 @@ const supportedCiphers = [
218226
"des-ede3-cbc",
219227
"aes128",
220228
"aes256",
229+
"chacha20-poly1305",
221230
];
222231

223232
export function getCiphers(): string[] {

ext/node_crypto/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ aws-lc-rs.workspace = true
1919
base64.workspace = true
2020
blake2.workspace = true
2121
cbc.workspace = true
22+
chacha20.workspace = true
2223
const-oid.workspace = true
2324
ctr.workspace = true
2425
data-encoding.workspace = true
@@ -49,6 +50,7 @@ p384.workspace = true
4950
p521.workspace = true
5051
pbkdf2.workspace = true
5152
pkcs8 = { workspace = true, features = ["std", "pkcs5", "encryption"] }
53+
poly1305.workspace = true
5254
rand.workspace = true
5355
ripemd = { workspace = true, features = ["oid"] }
5456
rsa.workspace = true

0 commit comments

Comments
 (0)