Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions lib/internal/crypto/cipher.js
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,10 @@ function _flush(callback) {
function update(data, inputEncoding, outputEncoding) {
if (typeof data === 'string') {
validateEncoding(data, inputEncoding);
if (inputEncoding != null &&
normalizeEncoding(inputEncoding) === undefined) {
throw new ERR_UNKNOWN_ENCODING(inputEncoding);
}
} else if (!isArrayBufferView(data)) {
throw new ERR_INVALID_ARG_TYPE(
'data', ['string', 'Buffer', 'TypedArray', 'DataView'], data);
Expand Down
49 changes: 49 additions & 0 deletions test/parallel/test-crypto-encoding-validation-error.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,52 @@ const createCipher = () => {
{ message: /^Unknown encoding: bad3$/, code: 'ERR_UNKNOWN_ENCODING' }
);
}

// Regression tests for https://github.com/nodejs/node/issues/45189:
// Unknown input encodings used to be silently accepted by Cipher/Decipher
// `update`, producing incorrect (and silently non-deterministic) output.
// They must now reject with ERR_UNKNOWN_ENCODING.

{
const cipher = createCipher();

assert.throws(
() => cipher.update('test', 'bad', 'hex'),
{ message: /^Unknown encoding: bad$/, code: 'ERR_UNKNOWN_ENCODING' }
);
}

{
const { createDecipheriv } = require('crypto');
const decipher = createDecipheriv(
'aes-256-cbc', randomBytes(32), randomBytes(16));

assert.throws(
() => decipher.update('test', 'bad', 'hex'),
{ message: /^Unknown encoding: bad$/, code: 'ERR_UNKNOWN_ENCODING' }
);
}

// A buffer-like data argument should not trigger encoding validation,
// because the input encoding is ignored when data is not a string.
{
const cipher = createCipher();
// Should not throw.
cipher.update(Buffer.from('test'), 'bad-but-ignored', 'hex');
}

// Valid input encodings must continue to work.
{
const cipher = createCipher();
let result = cipher.update('test', 'utf-8', 'hex');
result += cipher.final('hex');
assert.strictEqual(typeof result, 'string');
}

// Omitting the input encoding (undefined / null) is allowed; the
// underlying binding falls back to its default behavior.
{
const cipher = createCipher();
// Should not throw.
cipher.update(Buffer.from('test'));
}
Loading