{"record":{"id":"5af6083ab1a5a832","repo":"OpenNHP/opennhp","slug":"invalid-n-w","errorCode":null,"errorMessage":"invalid n: %w","messagePattern":"invalid n: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"endpoints/server/kbs/attest/attest.go","lineNumber":108,"sourceCode":"\t\t\"kbs-session-id\",\n\t\tsessionID,\n\t\t3600,\n\t\t\"/\", \"\", true, true, // Secure: only send over HTTPS\n\t)\n\n\tc.JSON(http.StatusOK, gin.H{\n\t\t\"token\": token,\n\t})\n}\n\nfunc parseTeePubkey(pubkey TeePubkey) (*rsa.PublicKey, error) {\n\tif pubkey.Kty != \"RSA\" {\n\t\treturn nil, errors.New(\"unsupported key type, expect RSA\")\n\t}\n\n\tnBytes, err := base64.RawURLEncoding.DecodeString(pubkey.N)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"invalid n: %w\", err)\n\t}\n\n\teBytes, err := base64.RawURLEncoding.DecodeString(pubkey.E)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"invalid e: %w\", err)\n\t}\n\n\te := 0\n\tfor _, b := range eBytes {\n\t\te = e<<8 | int(b)\n\t}\n\n\treturn &rsa.PublicKey{\n\t\tN: new(big.Int).SetBytes(nBytes),\n\t\tE: e,\n\t}, nil\n}\n","sourceCodeStart":90,"sourceCodeEnd":126,"githubUrl":"https://github.com/OpenNHP/opennhp/blob/6e04ca5ff03222a699c24205cd4bf8fee9af7ffe/endpoints/server/kbs/attest/attest.go#L90-L126","documentation":"parseTeePubkey decodes the JWK-style RSA public key fields with base64.RawURLEncoding. This error is returned when the teePubKey.n field is not valid unpadded base64url, so the modulus cannot be decoded. The underlying decode error is wrapped in 'invalid n: %w'.","triggerScenarios":"Attest receives a TEK pubkey JSON whose n contains padded base64 ('=' chars), standard-base64 symbols ('+','/'), whitespace, or other invalid characters, and RawURLEncoding.DecodeString fails.","commonSituations":"Clients producing JWKs with padded base64url; a JSON value that got percent-encoded or newline-wrapped; hand-edited keys; mixing standard and URL-safe alphabets between signer and verifier.","solutions":["Fix the client to emit n as unpadded base64url (base64.RawURLEncoding on the producer side)","Strip any '=' padding before decoding: base64.RawURLEncoding.DecodeString(strings.TrimRight(pubkey.N, \"=\"))","Try a tolerant decoder that attempts RawURLEncoding then RawStdEncoding","Validate the n field on receipt and return a clear 400 to the client instead of an internal 500"],"exampleFix":"// before\nnBytes, err := base64.RawURLEncoding.DecodeString(pubkey.N)\nif err != nil {\n\treturn nil, fmt.Errorf(\"invalid n: %w\", err)\n}\n// after\nnBytes, err := base64.RawURLEncoding.DecodeString(strings.TrimRight(pubkey.N, \"=\"))\nif err != nil {\n\treturn nil, fmt.Errorf(\"invalid n encoding (expect unpadded base64url): %w\", err)\n}","handlingStrategy":"validation","validationCode":"var jwk struct{ Kty, N, E string }\nif err := json.Unmarshal(body, &jwk); err != nil || jwk.Kty != \"RSA\" {\n\treturn fmt.Errorf(\"expect RSA JWK\")\n}\nif _, err := base64.RawURLEncoding.DecodeString(jwk.N); err != nil {\n\treturn fmt.Errorf(\"n is not unpadded base64url\")\n}","typeGuard":"func isValidRawURLBase64(s string) bool {\n\t_, err := base64.RawURLEncoding.DecodeString(s)\n\treturn err == nil && s != \"\"\n}","tryCatchPattern":"pubkey, err := parseTeePubkey(body)\nif err != nil {\n\tif strings.HasPrefix(err.Error(), \"invalid n\") || strings.HasPrefix(err.Error(), \"invalid e\") {\n\t\thttp.Error(w, \"malformed TEK public key\", http.StatusBadRequest)\n\t\treturn\n\t}\n\treturn err\n}","preventionTips":["Encode JWK fields with base64.RawURLEncoding on the client","Never send padded or standard-base64 JWK values","Validate n/e decode before submitting attestation requests","Test against both \"AQAB\" and decimal exponent forms to pin down the contract"],"tags":["go","base64","jwk","attestation"],"backgroundTag":"invalid-argument-format","analyzedSha":"6e04ca5ff03222a699c24205cd4bf8fee9af7ffe","analyzedAt":"2026-09-07T15:44:59.941Z","contentChangedAt":"2026-09-07T15:44:59.941Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}