{"record":{"id":"7c915ad2dbf30ec9","repo":"grafana/k6","slug":"failed-to-decode-exponent-w","errorCode":null,"errorMessage":"failed to decode exponent: %w","messagePattern":"failed to decode exponent: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/js/modules/k6/webcrypto/jwk.go","lineNumber":341,"sourceCode":"\nfunc importRSAJWK(jsonKeyData []byte) (any, CryptoKeyType, int, error) {\n\tvar jwk rsaJWK\n\tif err := json.Unmarshal(jsonKeyData, &jwk); err != nil {\n\t\treturn nil, UnknownCryptoKeyType, 0, fmt.Errorf(\"failed to parse input as RSA JWK key: %w\", err)\n\t}\n\n\tif err := jwk.validate(); err != nil {\n\t\treturn nil, UnknownCryptoKeyType, 0, fmt.Errorf(\"invalid RSA JWK key: %w\", err)\n\t}\n\n\t// decode the various key components\n\tnBytes, err := base64URLDecode(jwk.N)\n\tif err != nil {\n\t\treturn nil, UnknownCryptoKeyType, 0, fmt.Errorf(\"failed to decode modulus: %w\", err)\n\t}\n\teBytes, err := base64URLDecode(jwk.E)\n\tif err != nil {\n\t\treturn nil, UnknownCryptoKeyType, 0, fmt.Errorf(\"failed to decode exponent: %w\", err)\n\t}\n\n\t// convert exponent to an integer\n\teInt := new(big.Int).SetBytes(eBytes).Int64()\n\tpubKey := rsa.PublicKey{\n\t\tN: new(big.Int).SetBytes(nBytes),\n\t\tE: int(eInt),\n\t}\n\n\t// if the private exponent is missing, return the public key\n\tif jwk.D == \"\" {\n\t\treturn pubKey, PublicCryptoKeyType, pubKey.N.BitLen(), nil\n\t}\n\n\tdBytes, err := base64URLDecode(jwk.D)\n\tif err != nil {\n\t\treturn nil, UnknownCryptoKeyType, 0, fmt.Errorf(\"failed to decode private exponent: %w\", err)\n\t}","sourceCodeStart":323,"sourceCodeEnd":359,"githubUrl":"https://github.com/grafana/k6/blob/93accf6570dcd306ca5e99cc44c393ee3797761b/internal/js/modules/k6/webcrypto/jwk.go#L323-L359","documentation":"The RSA public exponent e is decoded with base64.RawURLEncoding during JWK import. This error means e is not a valid unpadded base64url string — most commonly because it was supplied as a plain integer rendered as digits (digits are legal base64url characters, so it may decode but the key will be wrong) with padding, or contains '+'/'/' characters or whitespace that make decoding fail outright.","triggerScenarios":"e given as padded base64url; e containing '+' or '/'; e with whitespace. Note e = 65537 must appear as 'AQAB', while '10001' (hex text) would decode as garbage bytes rather than error — check the wrapped cause for the exact failure.","commonSituations":"Exponent taken as hex text '10001' with padding appended; JWK builders that mix encodings between n and e; copy-paste from documentation showing different encodings.","solutions":["Encode e as unpadded base64url of the big-endian integer ('AQAB' for 65537)","Never paste hex text ('10001') or a decimal number as e","Strip padding and whitespace from the value","Verify by decoding: base64url-decoded e should be 3 bytes 01 00 01 for the standard exponent"],"exampleFix":"// before\nconst jwk = { kty: 'RSA', n: b64uN, e: '==AQAB==' };\n// after\nconst jwk = { kty: 'RSA', n: b64uN, e: 'AQAB' };","handlingStrategy":"validation","validationCode":"const B64URL = /^[A-Za-z0-9_-]+$/;\nconst e = String(jwk.e).replace(/=+$/, '');\nif (!B64URL.test(e)) throw new Error('exponent e is not unpadded base64url');\nif (e === '10001') throw new Error('e looks like hex text; use \"AQAB\"');\njwk = { ...jwk, e };","typeGuard":"function isB64uExponent(s) {\n  return typeof s === 'string' && /^[A-Za-z0-9_-]+$/.test(s) && !/^\\d+$/.test(s) && s.length >= 1;\n}","tryCatchPattern":"try {\n  key = await crypto.subtle.importKey('jwk', jwk, rsaAlg, true, usages);\n} catch (e) {\n  if (err.message.includes('failed to decode exponent')) {\n    jwk = { ...jwk, e: 'AQAB' }; // standard exponent\n    key = await crypto.subtle.importKey('jwk', jwk, rsaAlg, true, usages);\n  } else throw err;\n}","preventionTips":["Encode e as base64url of the big-endian integer ('AQAB' for 65537)","Reject pure-digit e values in fixture validation — they are hex or decimal text","Keep the same encoder for n and e"],"tags":["webcrypto","jwk","import","rsa","base64url","k6"],"backgroundTag":null,"analyzedSha":"93accf6570dcd306ca5e99cc44c393ee3797761b","analyzedAt":"2026-08-15T21:23:27.118Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}