Skip to content

Commit

Permalink
cipher: add cipher update/final methods encoding validation
Browse files Browse the repository at this point in the history
Adds encoding validation to update and final cipher methods.

#45189
  • Loading branch information
vitpavlenko committed Dec 28, 2022
1 parent 34af1f6 commit d1c165e
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 3 deletions.
2 changes: 2 additions & 0 deletions README.md
Expand Up @@ -446,6 +446,8 @@ For information about the governance of the Node.js project, see
**Rich Trott** <<rtrott@gmail.com>> (he/him)
* [vdeturckheim](https://github.com/vdeturckheim) -
**Vladimir de Turckheim** <<vlad2t@hotmail.com>> (he/him)
* [vitpavlenko](https://github.com/vitpavlenko) -
**Vitaliy Pavlenko** <<vitaliypavlenko01@gmail.com>> (he/him)
* [VoltrexKeyva](https://github.com/VoltrexKeyva) -
**Mohammed Keyvanzadeh** <<mohammadkeyvanzade94@gmail.com>> (he/him)
* [watilde](https://github.com/watilde) -
Expand Down
6 changes: 6 additions & 0 deletions doc/api/errors.md
Expand Up @@ -1112,6 +1112,12 @@ release binaries but can happen with custom builds, including distro builds.

A signing `key` was not provided to the [`sign.sign()`][] method.

<a id="ERR_CRYPTO_UNKNOWN_ENCODING"></a>

### `ERR_CRYPTO_UNKNOWN_ENCODING`

Invalid encoding was provided to the update/finalise cipher methods.

<a id="ERR_CRYPTO_TIMING_SAFE_EQUAL_LENGTH"></a>

### `ERR_CRYPTO_TIMING_SAFE_EQUAL_LENGTH`
Expand Down
30 changes: 27 additions & 3 deletions lib/internal/crypto/cipher.js
Expand Up @@ -27,6 +27,7 @@ const {
ERR_CRYPTO_INVALID_STATE,
ERR_INVALID_ARG_TYPE,
ERR_INVALID_ARG_VALUE,
ERR_CRYPTO_UNKNOWN_ENCODING,
}
} = require('internal/errors');

Expand Down Expand Up @@ -90,10 +91,31 @@ const privateEncrypt = rsaFunctionFor(_privateEncrypt, RSA_PKCS1_PADDING,
const privateDecrypt = rsaFunctionFor(_privateDecrypt, RSA_PKCS1_OAEP_PADDING,
'private');

const validateNormalizedEncoding = (encoding, originalEncodingName) => {
if (!encoding) {
throw new ERR_CRYPTO_UNKNOWN_ENCODING(originalEncodingName);
}

return encoding;
};

const normalizeAndValidateEncoding = (encoding) => {
return validateNormalizedEncoding(normalizeEncoding(encoding), encoding);
};

const validateInputEncoding = (encoding) => {
if (encoding === 'buffer') {
return;
}

return normalizeAndValidateEncoding(encoding);
};

function getDecoder(decoder, encoding) {
encoding = normalizeEncoding(encoding);
decoder = decoder || new StringDecoder(encoding);
assert(decoder.encoding === encoding, 'Cannot change encoding');
const normilizedEncoding = normalizeAndValidateEncoding(encoding);

decoder = decoder || new StringDecoder(normilizedEncoding);
assert(decoder.encoding === normilizedEncoding, 'Cannot change encoding');
return decoder;
}

Expand Down Expand Up @@ -177,6 +199,8 @@ Cipher.prototype.update = function update(data, inputEncoding, outputEncoding) {
'data', ['string', 'Buffer', 'TypedArray', 'DataView'], data);
}

validateInputEncoding(inputEncoding);

const ret = this[kHandle].update(data, inputEncoding);

if (outputEncoding && outputEncoding !== 'buffer') {
Expand Down
1 change: 1 addition & 0 deletions lib/internal/errors.js
Expand Up @@ -1015,6 +1015,7 @@ E('ERR_CRYPTO_SCRYPT_INVALID_PARAMETER', 'Invalid scrypt parameter', Error);
E('ERR_CRYPTO_SCRYPT_NOT_SUPPORTED', 'Scrypt algorithm not supported', Error);
// Switch to TypeError. The current implementation does not seem right.
E('ERR_CRYPTO_SIGN_KEY_REQUIRED', 'No key provided to sign', Error);
E('ERR_CRYPTO_UNKNOWN_ENCODING', 'Unknown encoding %s', TypeError);
E('ERR_DEBUGGER_ERROR', '%s', Error);
E('ERR_DEBUGGER_STARTUP_ERROR', '%s', Error);
E('ERR_DIR_CLOSED', 'Directory handle was closed', Error);
Expand Down
2 changes: 2 additions & 0 deletions lib/internal/validators.js
Expand Up @@ -371,6 +371,8 @@ function validateEncoding(data, encoding) {
throw new ERR_INVALID_ARG_VALUE('encoding', encoding,
`is invalid for data of length ${length}`);
}

return normalizedEncoding;
}

/**
Expand Down
41 changes: 41 additions & 0 deletions test/parallel/test-crypto-encoding-validation-error.js
@@ -0,0 +1,41 @@
'use strict';
const common = require('../common');
if (!common.hasCrypto)
common.skip('missing crypto');

// This test checks if error is thrown in case of wrong encoding provided into cipher.

const assert = require('assert');
const { createCipheriv, randomBytes } = require('crypto');

const createCipher = () => {
return createCipheriv('aes-256-cbc', randomBytes(32), randomBytes(16));
};

{
const cipher = createCipher();

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

{
const cipher = createCipher();
cipher.update('test', 'utf-8', 'utf-8');

assert.throws(
() => cipher.final('bad2'),
{ message: /^Unknown encoding bad2$/ }
);
}

{
const cipher = createCipher();

assert.throws(
() => cipher.update('test', 'utf-8', 'bad3'),
{ message: /^Unknown encoding bad3$/ }
);
}

0 comments on commit d1c165e

Please sign in to comment.