{"record":{"id":"4429bca25748ad03","repo":"basecamp/fizzy","slug":"invalid-ec2-key-error-message","errorCode":null,"errorMessage":"Invalid EC2 key: #{error.message}","messagePattern":"Invalid EC2 key: #(.+?)","errorType":"exception","errorClass":"ActionPack::WebAuthn::InvalidKeyError","httpStatus":null,"severity":"error","filePath":"lib/action_pack/web_authn/cose_key.rb","lineNumber":135,"sourceCode":"      x = parameters[EC2_X_LABEL]\n      y = parameters[EC2_Y_LABEL]\n      raise ActionPack::WebAuthn::InvalidKeyError, \"Missing EC2 key coordinates\" if x.nil? || y.nil?\n      raise ActionPack::WebAuthn::InvalidKeyError, \"Invalid EC2 coordinate length\" unless x.bytesize == P256_COORDINATE_LENGTH && y.bytesize == P256_COORDINATE_LENGTH\n\n      # Uncompressed point format: 0x04 || x || y\n      public_key_bytes = [ UNCOMPRESSED_POINT_MARKER, *x.bytes, *y.bytes ].pack(\"C*\")\n\n      asn1 = OpenSSL::ASN1::Sequence([\n        OpenSSL::ASN1::Sequence([\n          OpenSSL::ASN1::ObjectId(\"id-ecPublicKey\"),\n          OpenSSL::ASN1::ObjectId(\"prime256v1\")\n        ]),\n        OpenSSL::ASN1::BitString(public_key_bytes)\n      ])\n\n      OpenSSL::PKey::EC.new(asn1.to_der)\n    rescue OpenSSL::PKey::PKeyError => error\n      raise ActionPack::WebAuthn::InvalidKeyError, \"Invalid EC2 key: #{error.message}\"\n    end\n\n    def build_okp_eddsa_key\n      curve = parameters[OKP_CURVE_LABEL]\n      raise ActionPack::WebAuthn::UnsupportedKeyTypeError, \"Unsupported OKP curve: #{curve}\" unless curve == ED25519\n\n      x = parameters[OKP_X_LABEL]\n      raise ActionPack::WebAuthn::InvalidKeyError, \"Missing OKP key coordinate\" if x.nil?\n\n      asn1 = OpenSSL::ASN1::Sequence([\n        OpenSSL::ASN1::Sequence([\n          OpenSSL::ASN1::ObjectId(\"ED25519\")\n        ]),\n        OpenSSL::ASN1::BitString(x)\n      ])\n\n      OpenSSL::PKey.read(asn1.to_der)\n    rescue OpenSSL::PKey::PKeyError => error","sourceCodeStart":117,"sourceCodeEnd":153,"githubUrl":"https://github.com/basecamp/fizzy/blob/7aabe7458060d8a1759a53b7ede39e74e6c0b20d/lib/action_pack/web_authn/cose_key.rb#L117-L153","documentation":"When the coordinate lengths pass, the library packs 0x04||x||y into ASN.1 and hands it to OpenSSL::PKey::EC.new. If OpenSSL rejects it — most commonly because the point is not on the P-256 curve — the OpenSSL::PKey::PKeyError is re-raised as InvalidKeyError 'Invalid EC2 key: <openssl message>'. Structurally valid bytes but mathematically invalid key material.","triggerScenarios":"Coordinates that are each exactly 32 bytes but do not satisfy the curve equation y^2 = x^3 - 3x + b mod p — corrupt values, bit-flipped transport, forged attestation attempts, or random test bytes used as coordinates.","commonSituations":"Fuzz tests feeding random 32-byte strings; fixtures where x/y were swapped or truncated-then-padded incorrectly; tampered registration payloads; authenticator firmware bugs (rare).","solutions":["Treat it as a failed registration: rescue InvalidKeyError, log the OpenSSL message, and return 400 — never fall back to partial verification.","If it reproduces with one specific authenticator, capture a fresh registration from it and compare coordinates; a consistent failure indicates a firmware/encoder bug.","Verify the transport path for byte corruption (compare the client-side hash of the key bytes with the server-side one).","In tests, generate valid points with OpenSSL::PKey::EC.new('prime256v1').generate_key instead of random bytes."],"exampleFix":"# before\nkey = cose_key.to_openssl_key # raises InvalidKeyError: point not on curve\n\n# after — fail registration cleanly on any invalid key material\nbegin\n  key = cose_key.to_openssl_key\nrescue ActionPack::WebAuthn::InvalidKeyError => e\n  Rails.logger.warn { \"Rejected invalid credential key: #{e.message}\" }\n  return render json: { error: 'credential key invalid' }, status: :bad_request\nend","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"begin\n  key = cose_key.to_openssl_key\nrescue ActionPack::WebAuthn::InvalidKeyError => e\n  Rails.logger.warn { \"Rejected invalid EC2 key: #{e.message}\" }\n  render json: { error: 'credential key invalid' }, status: :bad_request\nend","preventionTips":["Never fall back to partial verification when key construction fails — fail the registration.","In tests, generate real P-256 keys with OpenSSL instead of random 32-byte strings.","Log the underlying OpenSSL message; 'point not on curve' almost always means corrupted transport or forged input."],"tags":["webauthn","cose","openssl","elliptic-curve","invalid-key"],"backgroundTag":"malformed-public-key","analyzedSha":"7aabe7458060d8a1759a53b7ede39e74e6c0b20d","analyzedAt":"2026-08-21T18:33:25.349Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}