{"record":{"id":"ff338f3fab93f2cb","repo":"grafana/k6","slug":"failed-to-decode-modulus-w","errorCode":null,"errorMessage":"failed to decode modulus: %w","messagePattern":"failed to decode modulus: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/js/modules/k6/webcrypto/jwk.go","lineNumber":337,"sourceCode":"\n\t// TODO: consider validating the other fields in future\n\treturn nil\n}\n\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","sourceCodeStart":319,"sourceCodeEnd":355,"githubUrl":"https://github.com/grafana/k6/blob/93accf6570dcd306ca5e99cc44c393ee3797761b/internal/js/modules/k6/webcrypto/jwk.go#L319-L355","documentation":"During RSA JWK import the modulus n is decoded with base64.RawURLEncoding (base64url, no padding). This error indicates n is not valid unpadded base64url: '=' padding, '+'/'/' alphabet characters, whitespace, or impossible length. It surfaces from crypto.subtle.importKey('jwk', ...) for RSA algorithms.","triggerScenarios":"n encoded in standard or padded base64; whitespace or newlines inside the modulus; truncated modulus; hex-encoded modulus (0x... or plain hex) instead of base64url.","commonSituations":"Moduli copied from OpenSSL output (standard base64 with wrapping); JWKs from systems using padded base64url; values converted from hex representations by hand.","solutions":["Convert n to unpadded base64url (replace '+'->'-', '/'->'_', strip '=')","If the value is hex, re-encode the raw bytes as base64url without padding","Remove embedded newlines/whitespace","Confirm the decoded modulus byte length matches the announced key size (e.g. 256 bytes for RSA-2048)"],"exampleFix":"// before\nconst jwk = { kty: 'RSA', n: stdB64N, e: 'AQAB' };\n// after\nconst toB64u = (s) => s.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '').replace(/\\s+/g, '');\nconst jwk = { kty: 'RSA', n: toB64u(stdB64N), e: 'AQAB' };","handlingStrategy":"validation","validationCode":"const B64URL = /^[A-Za-z0-9_-]+$/;\nconst toB64u = (s) => String(s).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '').replace(/\\s+/g, '');\nconst n = toB64u(jwk.n);\nif (!B64URL.test(n)) throw new Error('modulus n is not unpadded base64url');\njwk = { ...jwk, n };","typeGuard":"function isB64uModulus(s) {\n  return typeof s === 'string' && /^[A-Za-z0-9_-]+$/.test(s) && s.length >= 40;\n}","tryCatchPattern":"try {\n  key = await crypto.subtle.importKey('jwk', jwk, rsaAlg, true, usages);\n} catch (e) {\n  if (e.message.includes('failed to decode modulus')) {\n    jwk = { ...jwk, n: toB64u(jwk.n) };\n    key = await crypto.subtle.importKey('jwk', jwk, rsaAlg, true, usages);\n  } else throw e;\n}","preventionTips":["Convert standard base64 to base64url at the system boundary","Expect ~342 chars for an RSA-2048 modulus, ~683 for RSA-4096","Never use hex-encoded moduli directly"],"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"}