Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 45dcd5c

Browse filesBrowse files
panvadanielleadams
authored andcommitted
crypto: allow zero-length IKM in HKDF and in webcrypto PBKDF2
PR-URL: #44201 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Tobias Nießen <tniessen@tnie.de>
1 parent 521ad0e commit 45dcd5c
Copy full SHA for 45dcd5c

File tree

Expand file treeCollapse file tree

8 files changed

+164
-2251
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

8 files changed

+164
-2251
lines changed
Open diff view settings
Collapse file

‎doc/api/crypto.md‎

Copy file name to clipboardExpand all lines: doc/api/crypto.md
+9-2Lines changed: 9 additions & 2 deletions
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -4203,6 +4203,9 @@ web-compatible code use [`crypto.webcrypto.getRandomValues()`][] instead.
42034203
<!-- YAML
42044204
added: v15.0.0
42054205
changes:
4206+
- version: REPLACEME
4207+
pr-url: https://github.com/nodejs/node/pull/44201
4208+
description: The input keying material can now be zero-length.
42064209
- version: v18.0.0
42074210
pr-url: https://github.com/nodejs/node/pull/41678
42084211
description: Passing an invalid callback to the `callback` argument
@@ -4212,7 +4215,7 @@ changes:
42124215

42134216
* `digest` {string} The digest algorithm to use.
42144217
* `ikm` {string|ArrayBuffer|Buffer|TypedArray|DataView|KeyObject} The input
4215-
keying material. It must be at least one byte in length.
4218+
keying material. Must be provided but can be zero-length.
42164219
* `salt` {string|ArrayBuffer|Buffer|TypedArray|DataView} The salt value. Must
42174220
be provided but can be zero-length.
42184221
* `info` {string|ArrayBuffer|Buffer|TypedArray|DataView} Additional info value.
@@ -4262,11 +4265,15 @@ hkdf('sha512', 'key', 'salt', 'info', 64, (err, derivedKey) => {
42624265

42634266
<!-- YAML
42644267
added: v15.0.0
4268+
changes:
4269+
- version: REPLACEME
4270+
pr-url: https://github.com/nodejs/node/pull/44201
4271+
description: The input keying material can now be zero-length.
42654272
-->
42664273

42674274
* `digest` {string} The digest algorithm to use.
42684275
* `ikm` {string|ArrayBuffer|Buffer|TypedArray|DataView|KeyObject} The input
4269-
keying material. It must be at least one byte in length.
4276+
keying material. Must be provided but can be zero-length.
42704277
* `salt` {string|ArrayBuffer|Buffer|TypedArray|DataView} The salt value. Must
42714278
be provided but can be zero-length.
42724279
* `info` {string|ArrayBuffer|Buffer|TypedArray|DataView} Additional info value.
Collapse file

‎lib/internal/crypto/hkdf.js‎

Copy file name to clipboardExpand all lines: lib/internal/crypto/hkdf.js
+1-3Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
const {
44
FunctionPrototypeCall,
55
Promise,
6-
Uint8Array,
76
} = primordials;
87

98
const {
@@ -80,9 +79,8 @@ function prepareKey(key) {
8079
if (isKeyObject(key))
8180
return key;
8281

83-
// TODO(@jasnell): createSecretKey should allow using an ArrayBuffer
8482
if (isAnyArrayBuffer(key))
85-
return createSecretKey(new Uint8Array(key));
83+
return createSecretKey(key);
8684

8785
key = toBuf(key);
8886

Collapse file

‎lib/internal/crypto/webcrypto.js‎

Copy file name to clipboardExpand all lines: lib/internal/crypto/webcrypto.js
-3Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -494,9 +494,6 @@ async function importGenericSecretKey(
494494

495495
const checkLength = keyData.byteLength * 8;
496496

497-
if (checkLength === 0 || length === 0)
498-
throw lazyDOMException('Zero-length key is not supported', 'DataError');
499-
500497
// The Web Crypto spec allows for key lengths that are not multiples of
501498
// 8. We don't. Our check here is stricter than that defined by the spec
502499
// in that we require that algorithm.length match keyData.length * 8 if
Collapse file

‎src/crypto/crypto_hkdf.cc‎

Copy file name to clipboardExpand all lines: src/crypto/crypto_hkdf.cc
+46-8Lines changed: 46 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -103,20 +103,58 @@ bool HKDFTraits::DeriveBits(
103103
EVPKeyCtxPointer ctx =
104104
EVPKeyCtxPointer(EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, nullptr));
105105
if (!ctx || !EVP_PKEY_derive_init(ctx.get()) ||
106-
!EVP_PKEY_CTX_hkdf_mode(ctx.get(),
107-
EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND) ||
108106
!EVP_PKEY_CTX_set_hkdf_md(ctx.get(), params.digest) ||
109-
!EVP_PKEY_CTX_set1_hkdf_salt(
110-
ctx.get(), params.salt.data<unsigned char>(), params.salt.size()) ||
111-
!EVP_PKEY_CTX_set1_hkdf_key(
112-
ctx.get(),
113-
reinterpret_cast<const unsigned char*>(params.key->GetSymmetricKey()),
114-
params.key->GetSymmetricKeySize()) ||
115107
!EVP_PKEY_CTX_add1_hkdf_info(
116108
ctx.get(), params.info.data<unsigned char>(), params.info.size())) {
117109
return false;
118110
}
119111

112+
// TODO(panva): Once support for OpenSSL 1.1.1 is dropped the whole
113+
// of HKDFTraits::DeriveBits can be refactored to use
114+
// EVP_KDF which does handle zero length key.
115+
if (params.key->GetSymmetricKeySize() != 0) {
116+
if (!EVP_PKEY_CTX_hkdf_mode(ctx.get(),
117+
EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND) ||
118+
!EVP_PKEY_CTX_set1_hkdf_salt(
119+
ctx.get(), params.salt.data<unsigned char>(), params.salt.size()) ||
120+
!EVP_PKEY_CTX_set1_hkdf_key(ctx.get(),
121+
reinterpret_cast<const unsigned char*>(
122+
params.key->GetSymmetricKey()),
123+
params.key->GetSymmetricKeySize())) {
124+
return false;
125+
}
126+
} else {
127+
// Workaround for EVP_PKEY_derive HKDF not handling zero length keys.
128+
unsigned char temp_key[EVP_MAX_MD_SIZE];
129+
unsigned int len = sizeof(temp_key);
130+
if (params.salt.size() != 0) {
131+
if (HMAC(params.digest,
132+
params.salt.data(),
133+
params.salt.size(),
134+
nullptr,
135+
0,
136+
temp_key,
137+
&len) == nullptr) {
138+
return false;
139+
}
140+
} else {
141+
char salt[EVP_MAX_MD_SIZE] = {0};
142+
if (HMAC(params.digest,
143+
salt,
144+
EVP_MD_size(params.digest),
145+
nullptr,
146+
0,
147+
temp_key,
148+
&len) == nullptr) {
149+
return false;
150+
}
151+
}
152+
if (!EVP_PKEY_CTX_hkdf_mode(ctx.get(), EVP_PKEY_HKDEF_MODE_EXPAND_ONLY) ||
153+
!EVP_PKEY_CTX_set1_hkdf_key(ctx.get(), temp_key, len)) {
154+
return false;
155+
}
156+
}
157+
120158
size_t length = params.length;
121159
ByteSource::Builder buf(length);
122160
if (EVP_PKEY_derive(ctx.get(), buf.data<unsigned char>(), &length) <= 0)
Collapse file

‎test/parallel/test-crypto-hkdf.js‎

Copy file name to clipboardExpand all lines: test/parallel/test-crypto-hkdf.js
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,8 @@ const {
120120

121121
const algorithms = [
122122
['sha256', 'secret', 'salt', 'info', 10],
123+
['sha256', '', '', '', 10],
124+
['sha256', '', 'salt', '', 10],
123125
['sha512', 'secret', 'salt', '', 15],
124126
];
125127
if (!common.hasOpenSSL3)
Collapse file

‎test/parallel/test-webcrypto-derivebits-hkdf.js‎

Copy file name to clipboardExpand all lines: test/parallel/test-webcrypto-derivebits-hkdf.js
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ const kDerivedKeys = {
3131
short: '5040737377307264',
3232
long: '55736572732073686f756c64207069636b206c6f6e6720706173737068726' +
3333
'173657320286e6f74207573652073686f72742070617373776f7264732921',
34-
// empty: ''
34+
empty: ''
3535
};
3636

3737
const kSalts = {
Collapse file

‎test/pummel/test-webcrypto-derivebits-pbkdf2.js‎

Copy file name to clipboardExpand all lines: test/pummel/test-webcrypto-derivebits-pbkdf2.js
+105-106Lines changed: 105 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,7 @@ const kPasswords = {
3737
long: '55736572732073686f756c64207069636b206c6f6' +
3838
'e6720706173737068726173657320286e6f742075' +
3939
'73652073686f72742070617373776f7264732921',
40-
// TODO(@jasnell): Zero-length password not currently supported
41-
// empty: ''
40+
empty: ''
4241
};
4342

4443
const kSalts = {
@@ -256,110 +255,110 @@ const kDerivations = {
256255
}
257256
}
258257
},
259-
// empty: {
260-
// short: {
261-
// 'SHA-384': {
262-
// '1': 'e9f0da1e97dfa455f858ce6b9af1ecc0299' +
263-
// 'f125ff1a847eb5d4955866f43e604',
264-
// '1000': '7ff7954aeddf41795fc8300666786d49' +
265-
// '74269aa91cc7e93811c953331d56d609',
266-
// '100000': '1c73132b6a55e9d9de2cdbfe1f55bf' +
267-
// '0ab59fd91f78f109c50096038b8557b147'
268-
// },
269-
// 'SHA-512': {
270-
// '1': 'e7e2b41f4887421bcb764eb4a56f63d2502' +
271-
// 'e33c764fbdf60626ad42ed9672342',
272-
// '1000': 'd561c4c84e9c60ba4752a2d383bf55ef' +
273-
// 'f643fc9e452252d6821e39449350cf72',
274-
// '100000': 'efd00752bc9ffafb5a399dd1d5834e' +
275-
// '8d2c2b676ecd4b2063fb1fe581d0f1380b'
276-
// },
277-
// 'SHA-1': {
278-
// '1': 'a667da47b8f857b7c65f70a6c8e7a06ce0d' +
279-
// '25211a2b6ebaf58dcaaf268b46b1d',
280-
// '1000': '72c92bbd3ddab4789e88e42ad1cda83c' +
281-
// 'c0729e6cb5106a577e50d5cf61782481',
282-
// '100000': '06e19e1b83e6480b1554df2b31a2c9' +
283-
// '2d1bfcf9bc1bdbc8751ff8685bdeef7dc9'
284-
// },
285-
// 'SHA-256': {
286-
// '1': '2ddb49243eb3b5912cb260cdd87fb04ef0d' +
287-
// '111bfa44d40a45e02a8a5c3c1518d',
288-
// '1000': '2835f3ed53565420c90951509b0c1173' +
289-
// 'b645174f1546ab3ac3e6c85cb471b53b',
290-
// '100000': '80aed905ca32ae0bb2a9d8f532f048' +
291-
// 'a0e672463eef9f83dfa7d88bca726553ea'
292-
// }
293-
// },
294-
// long: {
295-
// 'SHA-384': {
296-
// '1': '7b0bcca81dd637a3b3398666619716c5f2b1' +
297-
// 'f4a5c24e85c18a9955559e4d7692',
298-
// '1000': '8bb89cf71972fe5acc16fdc5f8cffd2c2' +
299-
// 'e7178c086b3bbe61cc1314619135958',
300-
// '100000': '26c6a8ae4bd1fbe715ae478efff3eca' +
301-
// 'e83afa617ed35bd4a3f63c3da76a42d22'
302-
// },
303-
// 'SHA-512': {
304-
// '1': 'bb73f8168a8f391d3d54ca892fb72b8e603' +
305-
// '5e37f891e5a70491b94dc05510bc4',
306-
// '1000': '5cacc16cdfbe052cfd73a9891b8c0e78' +
307-
// 'b19b2e07eae2423d48fed5e08aa8494b',
308-
// '100000': '87fdfc293392cbf33ecc9b5141a2fe' +
309-
// 'fa74d150499756863c484c0a78b6274d7f'
310-
// },
311-
// 'SHA-1': {
312-
// '1': '1f46b40cf2fb3dc41a3d9ced8897b861050' +
313-
// '36810e2bfac7040814bd65d428d67',
314-
// '1000': 'cc5748ecc41288a0e13368543aaa2ef6' +
315-
// '2c97ba7518fa88f6e11c35763fc930b4',
316-
// '100000': '33e2993bf4729dc993fff66e69cc55' +
317-
// '777135ebfabce533575bce4a96645a742c'
318-
// },
319-
// 'SHA-256': {
320-
// '1': '61c935c462c3321c89663545d13a4f6b52b' +
321-
// '5191cfb7479e58dcfe6444d43106c',
322-
// '1000': '1353f7458237ab332ee052e29f829a2a' +
323-
// 'b90e72630ea10493b4eecffb9ff89e1d',
324-
// '100000': '79baf80ec582920538801e9d929ce0' +
325-
// '7084277987488d733a026852c452f06fb4'
326-
// }
327-
// },
328-
// empty: {
329-
// 'SHA-384': {
330-
// '1': '4bb042a5c28cee6f66f991c717fd7702677' +
331-
// '87e2bb3031eae270d87d63ad99534',
332-
// '1000': '9cbfe72d194da34e17c821dd1569ef50' +
333-
// 'a86eb4d893591776adc6a5c21e0031cf',
334-
// '100000': 'ed6bd7282567abe48d542d067d09f4' +
335-
// '04bd044ae2cefe11dacc531c4764cd35cd'
336-
// },
337-
// 'SHA-512': {
338-
// '1': '6d2ecbbbfb2e6dcd7056faf9af6aa06eae5' +
339-
// '94391db983279a6bf27e0eb228614',
340-
// '1000': 'cb93096c3a02beeb1c5fac36765c9011' +
341-
// 'fe99f8d8ea62366048fc98cb98dfea8f',
342-
// '100000': '89e16254ebad5cba72e0aebe1614c7' +
343-
// 'f9b795a7505f2637206ce10a3449a2b8bb'
344-
// },
345-
// 'SHA-1': {
346-
// '1': '1e437a1c79d75be61e91141dae20affc489' +
347-
// '2cc99abcc3fe753887bccc8920176',
348-
// '1000': '6e40910ac02ec89cebb9d898b13a09d1' +
349-
// 'cd7adf6f8cc08cc473302c8973aa2e19',
350-
// '100000': 'a9e1bebb36bc26d7c997d5483cbc8d' +
351-
// 'e4a419d1e706571342632586ec330a7290'
352-
// },
353-
// 'SHA-256': {
354-
// '1': 'f7ce0b653d2d72a4108cf5abe912ffdd777' +
355-
// '616dbbb27a70e8204f3ae2d0f6fad',
356-
// '1000': '4fc58a21c100ce1835b8f9991d738b56' +
357-
// '965d14b24e1761fbdffc69ac5e0b667a',
358-
// '100000': '64a868d4b23af696d3734d0b814d04' +
359-
// 'cdd1ac280128e97653a05f32b49c13a29a'
360-
// }
361-
// }
362-
// }
258+
empty: {
259+
short: {
260+
'SHA-384': {
261+
'1': 'e9f0da1e97dfa455f858ce6b9af1ecc0299' +
262+
'f125ff1a847eb5d4955866f43e604',
263+
'1000': '7ff7954aeddf41795fc8300666786d49' +
264+
'74269aa91cc7e93811c953331d56d609',
265+
'100000': '1c73132b6a55e9d9de2cdbfe1f55bf' +
266+
'0ab59fd91f78f109c50096038b8557b147'
267+
},
268+
'SHA-512': {
269+
'1': 'e7e2b41f4887421bcb764eb4a56f63d2502' +
270+
'e33c764fbdf60626ad42ed9672342',
271+
'1000': 'd561c4c84e9c60ba4752a2d383bf55ef' +
272+
'f643fc9e452252d6821e39449350cf72',
273+
'100000': 'efd00752bc9ffafb5a399dd1d5834e' +
274+
'8d2c2b676ecd4b2063fb1fe581d0f1380b'
275+
},
276+
'SHA-1': {
277+
'1': 'a667da47b8f857b7c65f70a6c8e7a06ce0d' +
278+
'25211a2b6ebaf58dcaaf268b46b1d',
279+
'1000': '72c92bbd3ddab4789e88e42ad1cda83c' +
280+
'c0729e6cb5106a577e50d5cf61782481',
281+
'100000': '06e19e1b83e6480b1554df2b31a2c9' +
282+
'2d1bfcf9bc1bdbc8751ff8685bdeef7dc9'
283+
},
284+
'SHA-256': {
285+
'1': '2ddb49243eb3b5912cb260cdd87fb04ef0d' +
286+
'111bfa44d40a45e02a8a5c3c1518d',
287+
'1000': '2835f3ed53565420c90951509b0c1173' +
288+
'b645174f1546ab3ac3e6c85cb471b53b',
289+
'100000': '80aed905ca32ae0bb2a9d8f532f048' +
290+
'a0e672463eef9f83dfa7d88bca726553ea'
291+
}
292+
},
293+
long: {
294+
'SHA-384': {
295+
'1': '7b0bcca81dd637a3b3398666619716c5f2b1' +
296+
'f4a5c24e85c18a9955559e4d7692',
297+
'1000': '8bb89cf71972fe5acc16fdc5f8cffd2c2' +
298+
'e7178c086b3bbe61cc1314619135958',
299+
'100000': '26c6a8ae4bd1fbe715ae478efff3eca' +
300+
'e83afa617ed35bd4a3f63c3da76a42d22'
301+
},
302+
'SHA-512': {
303+
'1': 'bb73f8168a8f391d3d54ca892fb72b8e603' +
304+
'5e37f891e5a70491b94dc05510bc4',
305+
'1000': '5cacc16cdfbe052cfd73a9891b8c0e78' +
306+
'b19b2e07eae2423d48fed5e08aa8494b',
307+
'100000': '87fdfc293392cbf33ecc9b5141a2fe' +
308+
'fa74d150499756863c484c0a78b6274d7f'
309+
},
310+
'SHA-1': {
311+
'1': '1f46b40cf2fb3dc41a3d9ced8897b861050' +
312+
'36810e2bfac7040814bd65d428d67',
313+
'1000': 'cc5748ecc41288a0e13368543aaa2ef6' +
314+
'2c97ba7518fa88f6e11c35763fc930b4',
315+
'100000': '33e2993bf4729dc993fff66e69cc55' +
316+
'777135ebfabce533575bce4a96645a742c'
317+
},
318+
'SHA-256': {
319+
'1': '61c935c462c3321c89663545d13a4f6b52b' +
320+
'5191cfb7479e58dcfe6444d43106c',
321+
'1000': '1353f7458237ab332ee052e29f829a2a' +
322+
'b90e72630ea10493b4eecffb9ff89e1d',
323+
'100000': '79baf80ec582920538801e9d929ce0' +
324+
'7084277987488d733a026852c452f06fb4'
325+
}
326+
},
327+
empty: {
328+
'SHA-384': {
329+
'1': '4bb042a5c28cee6f66f991c717fd7702677' +
330+
'87e2bb3031eae270d87d63ad99534',
331+
'1000': '9cbfe72d194da34e17c821dd1569ef50' +
332+
'a86eb4d893591776adc6a5c21e0031cf',
333+
'100000': 'ed6bd7282567abe48d542d067d09f4' +
334+
'04bd044ae2cefe11dacc531c4764cd35cd'
335+
},
336+
'SHA-512': {
337+
'1': '6d2ecbbbfb2e6dcd7056faf9af6aa06eae5' +
338+
'94391db983279a6bf27e0eb228614',
339+
'1000': 'cb93096c3a02beeb1c5fac36765c9011' +
340+
'fe99f8d8ea62366048fc98cb98dfea8f',
341+
'100000': '89e16254ebad5cba72e0aebe1614c7' +
342+
'f9b795a7505f2637206ce10a3449a2b8bb'
343+
},
344+
'SHA-1': {
345+
'1': '1e437a1c79d75be61e91141dae20affc489' +
346+
'2cc99abcc3fe753887bccc8920176',
347+
'1000': '6e40910ac02ec89cebb9d898b13a09d1' +
348+
'cd7adf6f8cc08cc473302c8973aa2e19',
349+
'100000': 'a9e1bebb36bc26d7c997d5483cbc8d' +
350+
'e4a419d1e706571342632586ec330a7290'
351+
},
352+
'SHA-256': {
353+
'1': 'f7ce0b653d2d72a4108cf5abe912ffdd777' +
354+
'616dbbb27a70e8204f3ae2d0f6fad',
355+
'1000': '4fc58a21c100ce1835b8f9991d738b56' +
356+
'965d14b24e1761fbdffc69ac5e0b667a',
357+
'100000': '64a868d4b23af696d3734d0b814d04' +
358+
'cdd1ac280128e97653a05f32b49c13a29a'
359+
}
360+
}
361+
}
363362
};
364363

365364
async function setupBaseKeys() {

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.