Skip to content

Commit 54f327b

Browse files
tniessenBridgeAR
authored andcommittedSep 25, 2019
crypto: add oaepLabel option
The label acts as the "L" input to the RSA-OAEP algorithm. PR-URL: #29489 Reviewed-By: David Carlier <[email protected]> Reviewed-By: Ben Noordhuis <[email protected]> Reviewed-By: Minwoo Jung <[email protected]> Reviewed-By: James M Snell <[email protected]>
1 parent ca8e87a commit 54f327b

File tree

6 files changed

+89
-48
lines changed

6 files changed

+89
-48
lines changed
 

‎doc/api/crypto.md

+10
Original file line numberDiff line numberDiff line change
@@ -2383,6 +2383,9 @@ An array of supported digest functions can be retrieved using
23832383
<!-- YAML
23842384
added: v0.11.14
23852385
changes:
2386+
- version: REPLACEME
2387+
pr-url: https://github.com/nodejs/node/pull/29489
2388+
description: The `oaepLabel` option was added.
23862389
- version: v12.9.0
23872390
pr-url: https://github.com/nodejs/node/pull/28335
23882391
description: The `oaepHash` option was added.
@@ -2394,6 +2397,8 @@ changes:
23942397
* `privateKey` {Object | string | Buffer | KeyObject}
23952398
- `oaepHash` {string} The hash function to use for OAEP padding.
23962399
**Default:** `'sha1'`
2400+
- `oaepLabel` {Buffer | TypedArray | DataView} The label to use for OAEP
2401+
padding. If not specified, no label is used.
23972402
- `padding` {crypto.constants} An optional padding value defined in
23982403
`crypto.constants`, which may be: `crypto.constants.RSA_NO_PADDING`,
23992404
`crypto.constants.RSA_PKCS1_PADDING`, or
@@ -2467,6 +2472,9 @@ be passed instead of a public key.
24672472
<!-- YAML
24682473
added: v0.11.14
24692474
changes:
2475+
- version: REPLACEME
2476+
pr-url: https://github.com/nodejs/node/pull/29489
2477+
description: The `oaepLabel` option was added.
24702478
- version: v12.9.0
24712479
pr-url: https://github.com/nodejs/node/pull/28335
24722480
description: The `oaepHash` option was added.
@@ -2477,6 +2485,8 @@ changes:
24772485

24782486
* `key` {Object | string | Buffer | KeyObject}
24792487
- `key` {string | Buffer | KeyObject} A PEM encoded public or private key.
2488+
- `oaepLabel` {Buffer | TypedArray | DataView} The label to use for OAEP
2489+
padding. If not specified, no label is used.
24802490
- `oaepHash` {string} The hash function to use for OAEP padding.
24812491
**Default:** `'sha1'`
24822492
- `passphrase` {string | Buffer} An optional passphrase for the private key.

‎lib/internal/crypto/cipher.js

+8-2
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,16 @@ function rsaFunctionFor(method, defaultPadding, keyType) {
5050
preparePrivateKey(options) :
5151
preparePublicOrPrivateKey(options);
5252
const padding = options.padding || defaultPadding;
53-
const { oaepHash } = options;
53+
const { oaepHash, oaepLabel } = options;
5454
if (oaepHash !== undefined && typeof oaepHash !== 'string')
5555
throw new ERR_INVALID_ARG_TYPE('options.oaepHash', 'string', oaepHash);
56-
return method(data, format, type, passphrase, buffer, padding, oaepHash);
56+
if (oaepLabel !== undefined && !isArrayBufferView(oaepLabel)) {
57+
throw new ERR_INVALID_ARG_TYPE('options.oaepLabel',
58+
['Buffer', 'TypedArray', 'DataView'],
59+
oaepLabel);
60+
}
61+
return method(data, format, type, passphrase, buffer, padding, oaepHash,
62+
oaepLabel);
5763
};
5864
}
5965

‎src/node_crypto.cc

+20
Original file line numberDiff line numberDiff line change
@@ -5201,6 +5201,8 @@ bool PublicKeyCipher::Cipher(Environment* env,
52015201
const ManagedEVPPKey& pkey,
52025202
int padding,
52035203
const EVP_MD* digest,
5204+
const void* oaep_label,
5205+
size_t oaep_label_len,
52045206
const unsigned char* data,
52055207
int len,
52065208
AllocatedBuffer* out) {
@@ -5217,6 +5219,16 @@ bool PublicKeyCipher::Cipher(Environment* env,
52175219
return false;
52185220
}
52195221

5222+
if (oaep_label_len != 0) {
5223+
// OpenSSL takes ownership of the label, so we need to create a copy.
5224+
void* label = OPENSSL_memdup(oaep_label, oaep_label_len);
5225+
CHECK_NOT_NULL(label);
5226+
if (!EVP_PKEY_CTX_set0_rsa_oaep_label(ctx.get(), label, oaep_label_len)) {
5227+
OPENSSL_free(label);
5228+
return false;
5229+
}
5230+
}
5231+
52205232
size_t out_len = 0;
52215233
if (EVP_PKEY_cipher(ctx.get(), nullptr, &out_len, data, len) <= 0)
52225234
return false;
@@ -5262,6 +5274,12 @@ void PublicKeyCipher::Cipher(const FunctionCallbackInfo<Value>& args) {
52625274
return THROW_ERR_OSSL_EVP_INVALID_DIGEST(env);
52635275
}
52645276

5277+
ArrayBufferViewContents<unsigned char> oaep_label;
5278+
if (!args[offset + 3]->IsUndefined()) {
5279+
CHECK(args[offset + 3]->IsArrayBufferView());
5280+
oaep_label.Read(args[offset + 3].As<ArrayBufferView>());
5281+
}
5282+
52655283
AllocatedBuffer out;
52665284

52675285
ClearErrorOnReturn clear_error_on_return;
@@ -5271,6 +5289,8 @@ void PublicKeyCipher::Cipher(const FunctionCallbackInfo<Value>& args) {
52715289
pkey,
52725290
padding,
52735291
digest,
5292+
oaep_label.data(),
5293+
oaep_label.length(),
52745294
buf.data(),
52755295
buf.length(),
52765296
&out);

‎src/node_crypto.h

+2
Original file line numberDiff line numberDiff line change
@@ -714,6 +714,8 @@ class PublicKeyCipher {
714714
const ManagedEVPPKey& pkey,
715715
int padding,
716716
const EVP_MD* digest,
717+
const void* oaep_label,
718+
size_t oaep_label_size,
717719
const unsigned char* data,
718720
int len,
719721
AllocatedBuffer* out);

‎test/fixtures/rsa-oaep-test-vectors.js

+30
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎test/parallel/test-crypto-rsa-dsa.js

+19-46
Original file line numberDiff line numberDiff line change
@@ -202,59 +202,21 @@ common.expectsError(() => {
202202
// The following RSA-OAEP test cases were created using the WebCrypto API to
203203
// ensure compatibility when using non-SHA1 hash functions.
204204
{
205-
function testDecrypt(oaepHash, ciphertext) {
205+
const { decryptionTests } =
206+
JSON.parse(fixtures.readSync('rsa-oaep-test-vectors.js', 'utf8'));
207+
208+
for (const { ct, oaepHash, oaepLabel } of decryptionTests) {
206209
const decrypted = crypto.privateDecrypt({
207210
key: rsaPkcs8KeyPem,
208-
oaepHash
209-
}, Buffer.from(ciphertext, 'hex'));
211+
oaepHash,
212+
oaepLabel: oaepLabel ? Buffer.from(oaepLabel, 'hex') : undefined
213+
}, Buffer.from(ct, 'hex'));
210214

211215
assert.strictEqual(decrypted.toString('utf8'), 'Hello Node.js');
212216
}
213-
214-
testDecrypt(undefined, '16ece59cf985a8cf1a3434e4b9707c922c20638fdf9abf7e5dc' +
215-
'7943f4136899348c54116d15b2c17563b9c7143f9d5b85b4561' +
216-
'5ad0598ea6d21c900f3957b65400612306a9bebae441f005646' +
217-
'f7a7c97129a103ab54e777168ef966514adb17786b968ea0ff4' +
218-
'30a524904c4a11c683764b7c8dbb60df0952768381cdba4d665' +
219-
'e5006034393a10d56d33e75b2714db824a18da46441ef7f94a3' +
220-
'4a7058c0bbad0394083a038558bcc6dd370f8e518e1bd8d73b2' +
221-
'96fc51d77da44799e4ee774926ded7910e8768f92db76f63107' +
222-
'338d33354b735d3ad094240dbd7ffdfda27ef0255306dcf4a64' +
223-
'62849492abd1a97fdd37743ff87c4d2ec89866c5cdbb696bd2b' +
224-
'30');
225-
testDecrypt('sha1', '16ece59cf985a8cf1a3434e4b9707c922c20638fdf9abf7e5dc794' +
226-
'3f4136899348c54116d15b2c17563b9c7143f9d5b85b45615ad059' +
227-
'8ea6d21c900f3957b65400612306a9bebae441f005646f7a7c9712' +
228-
'9a103ab54e777168ef966514adb17786b968ea0ff430a524904c4a' +
229-
'11c683764b7c8dbb60df0952768381cdba4d665e5006034393a10d' +
230-
'56d33e75b2714db824a18da46441ef7f94a34a7058c0bbad039408' +
231-
'3a038558bcc6dd370f8e518e1bd8d73b296fc51d77da44799e4ee7' +
232-
'74926ded7910e8768f92db76f63107338d33354b735d3ad094240d' +
233-
'bd7ffdfda27ef0255306dcf4a6462849492abd1a97fdd37743ff87' +
234-
'c4d2ec89866c5cdbb696bd2b30');
235-
testDecrypt('sha256', '16ccf09afe5eb0130182b9fc1ca4af61a38e772047cac42146bf' +
236-
'a0fa5879aa9639203e4d01442d212ff95bddfbe4661222215a2e' +
237-
'91908c37ab926edea7cfc53f83357bc27f86af0f5f2818ae141f' +
238-
'4e9e934d4e66189aff30f062c9c3f6eb9bc495a59082cb978f99' +
239-
'b56ce5fa530a8469e46129258e5c42897cb194b6805e936e5cbb' +
240-
'eaa535bad6b1d3cdfc92119b7dd325a2e6d2979e316bdacc9f80' +
241-
'e29c7bbdf6846d738e380deadcb48df8c1e8aabf7a9dd2f8c71d' +
242-
'6681dbec7dcadc01887c51288674268796bc77fdf8f1c94c9ca5' +
243-
'0b1cc7cddbaf4e56cb151d23e2c699d2844c0104ee2e7e9dcdb9' +
244-
'07cfab43339120a40c59ca54f32b8d21b48a29656c77');
245-
testDecrypt('sha512', '831b72e8dd91841729ecbddf2647d6f19dc0094734f8803d8c65' +
246-
'1b5655a12ae6156b74d9b594bcc0eacd002728380b94f46e8657' +
247-
'f130f354e03b6e7815ee257eda78dba296d67d24410c31c48e58' +
248-
'75cc79e4bde594b412be5f357f57a7ac1f1d18b718e408df162d' +
249-
'1795508e6a0616192b647ad942ea068a44fb2b323d35a3a61b92' +
250-
'6feb105d6c0b2a8fc8050222d1cf4a9e44da1f95bbc677fd6437' +
251-
'49c6c89ac551d072f04cd9320c97a8d94755c8a804954c082bed' +
252-
'7fa59199a00aca154c14a7b584b63c538daf9b9c7c90abfca193' +
253-
'87d2131f9d9b9ecfc8672249c33144d1be3bfc41558a13f99466' +
254-
'3661a3af24fd0a97619d508db36f5fc131af86fc68cf');
255217
}
256218

257-
// Test invalid oaepHash options.
219+
// Test invalid oaepHash and oaepLabel options.
258220
for (const fn of [crypto.publicEncrypt, crypto.privateDecrypt]) {
259221
assert.throws(() => {
260222
fn({
@@ -275,6 +237,17 @@ for (const fn of [crypto.publicEncrypt, crypto.privateDecrypt]) {
275237
code: 'ERR_INVALID_ARG_TYPE'
276238
});
277239
}
240+
241+
for (const oaepLabel of [0, false, null, Symbol(), () => {}, {}, 'foo']) {
242+
common.expectsError(() => {
243+
fn({
244+
key: rsaPubPem,
245+
oaepLabel
246+
}, Buffer.alloc(10));
247+
}, {
248+
code: 'ERR_INVALID_ARG_TYPE'
249+
});
250+
}
278251
}
279252

280253
// Test RSA key signing/verification

0 commit comments

Comments
 (0)
Please sign in to comment.