diff --git a/lib/internal/crypto/webcrypto.js b/lib/internal/crypto/webcrypto.js
index 63dd03bd00e..a7916e6ac34 100644
--- a/lib/internal/crypto/webcrypto.js
+++ b/lib/internal/crypto/webcrypto.js
@@ -153,6 +153,41 @@ async function deriveBits(algorithm, baseKey, length) {
   throw lazyDOMException('Unrecognized name.');
 }
 
+function getKeyLength({ name, length, hash }) {
+  switch (name) {
+    case 'AES-CTR':
+    case 'AES-CBC':
+    case 'AES-GCM':
+    case 'AES-KW':
+      if (length !== 128 && length !== 192 && length !== 256)
+        throw lazyDOMException('Invalid key length', 'OperationError');
+
+      return length;
+    case 'HMAC':
+      if (length === undefined) {
+        switch (hash?.name) {
+          case 'SHA-1':
+            return 160;
+          case 'SHA-256':
+            return 256;
+          case 'SHA-384':
+            return 384;
+          case 'SHA-512':
+            return 512;
+        }
+      }
+
+      if (typeof length === 'number' && length !== 0) {
+        return length;
+      }
+
+      throw lazyDOMException('Invalid key length', 'OperationError');
+    case 'HKDF':
+    case 'PBKDF2':
+      return null;
+  }
+}
+
 async function deriveKey(
   algorithm,
   baseKey,
@@ -176,7 +211,7 @@ async function deriveKey(
   validateBoolean(extractable, 'extractable');
   validateArray(keyUsages, 'keyUsages');
 
-  const { length } = derivedKeyAlgorithm;
+  const length = getKeyLength(derivedKeyAlgorithm);
   let bits;
   switch (algorithm.name) {
     case 'ECDH':
diff --git a/test/parallel/test-webcrypto-derivekey.js b/test/parallel/test-webcrypto-derivekey.js
index ee48a61f4ac..0c11d38af30 100644
--- a/test/parallel/test-webcrypto-derivekey.js
+++ b/test/parallel/test-webcrypto-derivekey.js
@@ -7,7 +7,7 @@ if (!common.hasCrypto)
   common.skip('missing crypto');
 
 const assert = require('assert');
-const { subtle } = require('crypto').webcrypto;
+const { webcrypto: { subtle }, KeyObject } = require('crypto');
 
 const { internalBinding } = require('internal/test/binding');
 
@@ -152,3 +152,35 @@ if (typeof internalBinding('crypto').ScryptJob === 'function') {
 
   tests.then(common.mustCall());
 }
+
+// Test default key lengths
+{
+  const vectors = [
+    ['PBKDF2', 'deriveKey', 528],
+    ['HKDF', 'deriveKey', 528],
+    [{ name: 'HMAC', hash: 'SHA-1' }, 'sign', 160],
+    [{ name: 'HMAC', hash: 'SHA-256' }, 'sign', 256],
+    [{ name: 'HMAC', hash: 'SHA-384' }, 'sign', 384],
+    [{ name: 'HMAC', hash: 'SHA-512' }, 'sign', 512],
+  ];
+
+  (async () => {
+    const keyPair = await subtle.generateKey({ name: 'ECDH', namedCurve: 'P-521' }, false, ['deriveKey']);
+    for (const [derivedKeyAlgorithm, usage, expected] of vectors) {
+      const derived = await subtle.deriveKey(
+        { name: 'ECDH', public: keyPair.publicKey },
+        keyPair.privateKey,
+        derivedKeyAlgorithm,
+        false,
+        [usage]);
+
+      if (derived.algorithm.name === 'HMAC') {
+        assert.strictEqual(derived.algorithm.length, expected);
+      } else {
+        // KDFs cannot be exportable and do not indicate their length
+        const secretKey = KeyObject.from(derived);
+        assert.strictEqual(secretKey.symmetricKeySize, expected / 8);
+      }
+    }
+  })().then(common.mustCall());
+}