deno
deno copied to clipboard
Bug: Panic with deno `std/node/crypto` `createDecipheriv`
$> RUST_BACKTRACE=full deno run cipher.ts
customData my-custom-data
cipherResult 3ffb093fd383730c2d4b75f066414ed1
decipherResult my-custom-data
============================================================
Deno has panicked. This is a bug in Deno. Please report this
at https://github.com/denoland/deno/issues/new.
If you can reliably reproduce this panic, include the
reproduction steps and re-run with the RUST_BACKTRACE=1 env
var set and include the backtrace in your report.
Platform: linux x86_64
Version: 1.45.2
Args: ["deno", "run", "cipher.ts"]
thread 'main' panicked at ext/node/ops/crypto/cipher.rs:399:9:
assertion failed: input.len() == 16
stack backtrace:
0: 0x5c85148795c5 - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::h1e1a1972118942ad
1: 0x5c85148ac1db - core::fmt::write::hc090a2ffd6b28c4a
2: 0x5c85148738df - std::io::Write::write_fmt::h8898bac6ff039a23
3: 0x5c851487939e - std::sys_common::backtrace::print::ha96650907276675e
4: 0x5c851487ad19 - std::panicking::default_hook::{{closure}}::h215c2a0a8346e0e0
5: 0x5c851487aa5d - std::panicking::default_hook::h207342be97478370
6: 0x5c8514decba3 - deno::setup_panic_hook::{{closure}}::h45bf1fb3ded7309c
7: 0x5c851487b356 - std::panicking::rust_panic_with_hook::hac8bdceee1e4fe2c
8: 0x5c851487b0cb - std::panicking::begin_panic_handler::{{closure}}::h00d785e82757ce3c
9: 0x5c8514879a89 - std::sys_common::backtrace::__rust_end_short_backtrace::h1628d957bcd06996
10: 0x5c851487ae37 - rust_begin_unwind
11: 0x5c85148a9093 - core::panicking::panic_fmt::hdc63834ffaaefae5
12: 0x5c85148a913c - core::panicking::panic::h75b3c9209f97d725
13: 0x5c8515b3aa6c - deno_node::ops::crypto::cipher::DecipherContext::final::h9e91e645b7e4535e
14: 0x5c8515bb0872 - deno_node::ops::crypto::op_node_decipheriv_final::op_node_decipheriv_final::v8_fn_ptr::h4ff7befea965f7fc
15: 0x5c851467b6df - Builtins_CallApiCallbackGeneric
File cipher.ts:
import { randomBytes, createHash, createCipheriv, createDecipheriv } from 'node:crypto'
import { Buffer } from 'node:buffer'
// generate random iv/key hashes
const ivHash = randomBytes(21).toString('hex')
const keyHash = randomBytes(21).toString('hex')
const resizedIV = Buffer.allocUnsafe(16)
const iv = createHash('sha256').update(ivHash).digest()
iv.copy(resizedIV)
const key = createHash('sha256').update(keyHash).digest()
// Data to cipher
const customData = 'my-custom-data'
console.log('customData', customData)
// Cipher
const cipher = createCipheriv('aes256', key, resizedIV)
const cipherResult = [
cipher.update(customData, 'binary', 'hex'),
cipher.final('hex'),
].join('')
console.log('cipherResult', cipherResult)
// Normal decipher
const decipher = createDecipheriv('aes256', key, resizedIV)
const decipherResult = [
decipher.update(cipherResult, 'hex', 'binary'),
decipher.final('binary'),
].join('')
console.log('decipherResult', decipherResult)
// Incorrect decipher
try {
const cipherBadResult = cipherResult.slice(0, cipherResult.length - 1)
const decipher2 = createDecipheriv('aes256', key, resizedIV)
const decipherBadResult = [
decipher2.update(cipherBadResult, 'hex', 'binary'),
decipher2.final('binary'),
].join('')
console.log('decipherBadResult', decipherBadResult)
} catch (err) {
console.warn('Unable to catch the error...', err)
}
When providing an incorrect data to the createDecipheriv, the .final('binary') is crashing deno, without being able to catch the error.
Deno is up to date (v1.45.2)
Smaller file to reproduce the panic:
// deno run xxxx.ts
import { createHash, createDecipheriv } from 'node:crypto'
import { Buffer } from 'node:buffer'
const resizedIV = Buffer.allocUnsafe(16)
const iv = createHash('sha256').update('798aa3c053a45f3f3c6693caed03d197e04c415754').digest()
iv.copy(resizedIV)
const key = createHash('sha256').update('c95f6f9d2fe5193922a17d3ba4c1b9fa6df60bd05b').digest()
const decipher = createDecipheriv('aes256', key, resizedIV)
console.log('update', decipher.update('419de07673c2285e988962af979cebd', 'hex', 'binary'))
console.log('final', decipher.final('binary'))
Fixed by #24957. This throws an error now:
$ deno -V
deno 1.45.5+8288434
$ node repro.mjs
update <Buffer d8 52 6d 63 bf c4 ac 7f e3 89 10 00 34 d4 f8 27>
node:internal/crypto/cipher:184
const ret = this[kHandle].final();
^
Error: error:1C80006B:Provider routines::wrong final block length
at Decipheriv.final (node:internal/crypto/cipher:184:29)
at file:///home/divy/gh/deno/repro.mjs:11:31
at ModuleJob.run (node:internal/modules/esm/module_job:262:25)
at async ModuleLoader.import (node:internal/modules/esm/loader:475:24)
at async asyncRunEntryPointWithESMLoader (node:internal/modules/run_main:109:5) {
library: 'Provider routines',
reason: 'wrong final block length',
code: 'ERR_OSSL_WRONG_FINAL_BLOCK_LENGTH'
}
Node.js v22.2.0
$ deno run -A repro.mjs
update <Buffer d8 52 6d 63 bf c4 ac 7f e3 89 10 00 34 d4 f8 27>
error: Uncaught (in promise) Error: Invalid final block size
console.log('final', decipher.final('binary'))
^
at Decipheriv.final (ext:deno_node/internal/crypto/cipher.ts:159:13)
at file:///home/divy/gh/deno/repro.mjs:11:31