Skip to content

Commit 45dcd5c

Browse 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

File tree

8 files changed

+164
-2251
lines changed

8 files changed

+164
-2251
lines changed

doc/api/crypto.md

Lines changed: 9 additions & 2 deletions
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.

lib/internal/crypto/hkdf.js

Lines 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

lib/internal/crypto/webcrypto.js

Lines 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

src/crypto/crypto_hkdf.cc

Lines 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)

test/parallel/test-crypto-hkdf.js

Lines 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)

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

Lines 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 = {

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

Lines 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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy