grafana/k6 · error
key derivation not implemented for algorithm %s
Error message
key derivation not implemented for algorithm %s
What it means
Returned when crypto.subtle.deriveKey is called with a base algorithm k6 does not implement. newKeyDeriver (internal/js/modules/k6/webcrypto/key.go:230) supports only PBKDF2, so any other normalized algorithm name — ECDH, HKDF, or a misspelling — hits the default branch and the deriveKey promise rejects with 'key derivation not implemented for algorithm <name>'. Note that deriveBits has its own deriver and does support ECDH, so deriveKey is the narrower API.
Source
Thrown at internal/js/modules/k6/webcrypto/key.go:230
type KeyDeriver interface {
DeriveKey(
privateKey *CryptoKey,
ki KeyImporter,
kgl KeyGetLengther,
keyUsages []CryptoKeyUsage,
extractable bool,
) (*CryptoKey, error)
}
func newKeyDeriver(rt *sobek.Runtime, normalized Algorithm, params sobek.Value) (KeyDeriver, error) {
var kd KeyDeriver
var err error
switch normalized.Name {
case PBKDF2:
kd, err = newPBKDF2DeriveParams(rt, normalized, params)
default:
return nil, errors.New("key derivation not implemented for algorithm " + normalized.Name)
}
if err != nil {
return nil, err
}
return kd, nil
}
// KeyGetLengther is the interface implemented by the parameters used to
// get the key length of cryptographic keys
type KeyGetLengther interface {
GetKeyLength() int
}
func newKeyGetLengther(rt *sobek.Runtime, normalized Algorithm, params sobek.Value) (KeyGetLengther, error) {
var kgi KeyGetLengther
var err errorView on GitHub (pinned to 01ffac6f24)
Solutions
- For password-based derivation, switch to PBKDF2: crypto.subtle.deriveKey({ name: 'PBKDF2', salt, iterations: 100000, hash: 'SHA-256' }, passwordKey, derived, extractable, usages)
- For ECDH or HKDF material, replace deriveKey with deriveBits followed by importKey: const bits = await crypto.subtle.deriveBits(alg, baseKey, 256); const key = await crypto.subtle.importKey('raw', bits, { name: 'AES-GCM', length: 256 }, false, ['encrypt'])
- Check the algorithm name spelling — it must normalize to exactly 'PBKDF2'
- Track the grafana/xk6-webcrypto repository for ECDH/HKDF deriveKey support and upgrade k6 when it lands
Example fix
// before (ECDH deriveKey — unsupported)
const aesKey = await crypto.subtle.deriveKey(
{ name: 'ECDH', public: peerPublic }, myPrivate,
{ name: 'AES-GCM', length: 256 }, false, ['encrypt']);
// after (deriveBits + importKey)
const bits = await crypto.subtle.deriveBits(
{ name: 'ECDH', public: peerPublic }, myPrivate, 256);
const aesKey = await crypto.subtle.importKey(
'raw', bits, { name: 'AES-GCM', length: 256 }, false, ['encrypt']); Defensive patterns
Strategy: fallback
Validate before calling
const DERIVE_KEY_BASE_ALGORITHMS = new Set(['PBKDF2']);
async function deriveKeyCompat(algorithm, baseKey, derivedKeyType, extractable, usages) {
if (DERIVE_KEY_BASE_ALGORITHMS.has(algorithm.name)) {
return crypto.subtle.deriveKey(algorithm, baseKey, derivedKeyType, extractable, usages);
}
// k6 deriveKey only supports PBKDF2 — fall back to deriveBits + importKey
const bits = await crypto.subtle.deriveBits(algorithm, baseKey, derivedKeyType.length);
return crypto.subtle.importKey('raw', bits, derivedKeyType, extractable, usages);
} Try / catch
try {
key = await crypto.subtle.deriveKey(alg, baseKey, derived, extractable, usages);
} catch (err) {
if (/key derivation not implemented/.test(String(err))) {
const bits = await crypto.subtle.deriveBits(alg, baseKey, derived.length);
key = await crypto.subtle.importKey('raw', bits, derived, extractable, usages);
} else {
throw err;
}
} Prevention
- Pin expectations to k6's coverage: deriveKey supports only PBKDF2 today
- Write new derivation code as deriveBits + importKey — it works for PBKDF2, ECDH and ports cleanly
- Watch the grafana/xk6-webcrypto roadmap before relying on ECDH/HKDF deriveKey
When it happens
Trigger: crypto.subtle.deriveKey({ name: 'ECDH', public: peerPublic }, myPrivate, { name: 'AES-GCM', length: 256 }, false, ['encrypt']) or crypto.subtle.deriveKey({ name: 'HKDF', hash: 'SHA-256', salt, info }, ikm, ...) — both reject with this message. A typo like 'PBKDF' also lands here because normalization must yield exactly 'PBKDF2'.
Common situations: Porting browser or Node.js WebCrypto code that supports ECDH/HKDF deriveKey and assuming k6 covers the same surface; password-based scripts where the algorithm string was changed; scripts written against xk6-webcrypto versions older than the integrated module.
Related errors
- coordinate Y is required
- k6/experimental/webcrypto has been graduated and it's now gl
- modulus (n) is required
- exponent (e) is required
- public exponent is even
AI-assisted analysis of grafana/k6@01ffac6f24 (2026-08-18).
Data as JSON: /api/errors/e2a50ad4ed8c0a54.
Report an issue: GitHub.