Skip to content

crypto.Decipher.update errors when inputEncoding is provided and data is a Buffer #31751

Closed
@benji2212

Description

@benji2212
  • Version: 13.8.0
  • Platform: any as far as I can tell - discovered on Windows 10 Enterprise 64bit
  • Subsystem: crypto

What steps will reproduce the bug?

Creating a piece of content to encrypt with an odd length, encrypting it using cipher then calling decipher.update with a buffer containing the encrypted value and 'hex' as the inputEncoding will reproduce the error.

const crypto = require('crypto');

const key = '76814765872355644465872785667516';
const iv = '594835440127';
const content = 'the content to be encrypted seems to need to be an odd length to reproduce the issue correctly.';

const cipher = crypto.createCipheriv('aes-256-gcm', key, iv);
let encrypted = cipher.update(content, 'utf8', 'hex');
encrypted += cipher.final('hex');
const authTag = cipher.getAuthTag().toString('hex');

const encryptedBuffer = Buffer.from(encrypted, 'hex');
const authTagBuffer = Buffer.from(authTag, 'hex');
const decipher = crypto.createDecipheriv('aes-256-gcm', key, iv);
decipher.setAuthTag(authTagBuffer);
let decrypted = decipher.update(encryptedBuffer, 'hex', 'utf8');
decrypted += decipher.final('utf8');

console.log(decrypted);

How often does it reproduce? Is there a required condition?

Should be consistently reproducible with the above code

What is the expected behavior?

The docs for Decipher.update state that inputEncoding should be ignored when the data argument is a Buffer:
Updates the decipher with data. If the inputEncoding argument is given, the data argument is a string using the specified encoding. If the inputEncoding argument is not given, data must be a Buffer. If data is a Buffer then inputEncoding is ignored.

The input encoding is instead being validated and failing validation. If the inputEncoding is provided as null in the example above, decryption happens correctly.

The above code snippet should log out 'the content to be encrypted seems to need to be an odd length to reproduce the issue correctly.'

What do you see instead?

internal/validators.js:153
throw new ERR_INVALID_ARG_VALUE('encoding', encoding,
^

TypeError [ERR_INVALID_ARG_VALUE]: The argument 'encoding' is invalid for data of length 95. Received 'hex'
at validateEncoding (internal/validators.js:153:11)
at Decipheriv.update (internal/crypto/cipher.js:159:3)
at Object. (C:\Users\n0139509\IdeaProjects\azure-node-auth\example.js:19:26)
at Module._compile (internal/modules/cjs/loader.js:1151:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1171:10)
at Module.load (internal/modules/cjs/loader.js:1000:32)
at Function.Module._load (internal/modules/cjs/loader.js:899:14)
at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:71:12)
at internal/main/run_main_module.js:17:47 {
code: 'ERR_INVALID_ARG_VALUE'
}

Additional information

This works properly in all versions of node I've tried prior to 13 (tried 10 and 12). It seems to be caused by the addition of the validateEncoding call to the Cipher.prototype.update function in internal/crypto/cipher.js without any check for whether the data provided is a Buffer or not, but I'm not sure if the docs were meant to change, or if the possibility of a Buffer being provided was overlooked when that call was added.

Metadata

Metadata

Assignees

No one assigned

    Labels

    cryptoIssues and PRs related to the crypto subsystem.docIssues and PRs related to the documentations.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions