basecamp/fizzy · error · ActionPack::WebAuthn::InvalidKeyError
Missing RSA key parameters
Error message
Missing RSA key parameters
What it means
ActionPack::WebAuthn::CoseKey raised InvalidKeyError because a COSE RSA key (key type 3, algorithm -257 RS256) was missing label -1 (the modulus n) or label -2 (the public exponent e). RFC 9053 requires both integer parameters for an RSA public key, and the library refuses to guess or default before constructing the OpenSSL key. It means the decoded CBOR map was structurally incomplete.
Source
Thrown at lib/action_pack/web_authn/cose_key.rb:160
x = parameters[OKP_X_LABEL]
raise ActionPack::WebAuthn::InvalidKeyError, "Missing OKP key coordinate" if x.nil?
asn1 = OpenSSL::ASN1::Sequence([
OpenSSL::ASN1::Sequence([
OpenSSL::ASN1::ObjectId("ED25519")
]),
OpenSSL::ASN1::BitString(x)
])
OpenSSL::PKey.read(asn1.to_der)
rescue OpenSSL::PKey::PKeyError => error
raise ActionPack::WebAuthn::InvalidKeyError, "Invalid OKP key: #{error.message}"
end
def build_rsa_rs256_key
n_bytes = parameters[RSA_N_LABEL]
e_bytes = parameters[RSA_E_LABEL]
raise ActionPack::WebAuthn::InvalidKeyError, "Missing RSA key parameters" if n_bytes.nil? || e_bytes.nil?
raise ActionPack::WebAuthn::InvalidKeyError, "RSA key must be at least #{MINIMUM_RSA_KEY_BITS} bits" if n_bytes.bytesize * 8 < MINIMUM_RSA_KEY_BITS
n = OpenSSL::BN.new(n_bytes, 2)
e = OpenSSL::BN.new(e_bytes, 2)
asn1 = OpenSSL::ASN1::Sequence([
OpenSSL::ASN1::Sequence([
OpenSSL::ASN1::ObjectId("rsaEncryption"),
OpenSSL::ASN1::Null.new(nil)
]),
OpenSSL::ASN1::BitString(
OpenSSL::ASN1::Sequence([
OpenSSL::ASN1::Integer(n),
OpenSSL::ASN1::Integer(e)
]).to_der
)
])
View on GitHub (pinned to 7aabe74580)
Solutions
- Inspect the decoded parameters map and confirm which of -1 (n) or -2 (e) is missing
- Fix the slice offset of the credential public key in authenticatorData (16-byte AAGUID + 2-byte credentialIdLength + credentialId) and verify against a known-good WebAuthn payload such as one from webauthn.io
- Complete the fixture: { 1 => 3, 3 => -257, -1 => n_bytes, -2 => e_bytes }
- Rescue ActionPack::WebAuthn::InvalidKeyError at the ceremony boundary and fail registration cleanly
Example fix
# before (fixture): RSA map without n/e
params = { 1 => 3, 3 => -257 }
# after: carry both RSA parameters as raw byte strings
rsa = OpenSSL::PKey::RSA.new(2048)
params = { 1 => 3, 3 => -257, -1 => rsa.n.to_s(2), -2 => rsa.e.to_s(2) } Defensive patterns
Strategy: validation
Validate before calling
cose = ActionPack::WebAuthn::CoseKey.decode(public_key_bytes) n = cose.parameters[ActionPack::WebAuthn::CoseKey::RSA_N_LABEL] e = cose.parameters[ActionPack::WebAuthn::CoseKey::RSA_E_LABEL] return if n.nil? || e.nil? # incomplete COSE RSA map key = cose.to_openssl_key
Type guard
def valid_rsa_cose_key?(cose)
[cose.key_type, cose.algorithm] == [3, -257] &&
cose.parameters[-1].is_a?(String) && cose.parameters[-1].bytesize >= 256 &&
cose.parameters[-2].is_a?(String) && !cose.parameters[-2].empty?
end Try / catch
begin
openssl_key = cose_key.to_openssl_key
rescue ActionPack::WebAuthn::InvalidKeyError => e
render json: { error: e.message }, status: :unprocessable_entity
end Prevention
- When switching fixtures between EC2, OKP, and RSA key types, update all labels: -1/-2 mean different parameters per key type
- Re-verify authenticator-data offsets whenever credential ID lengths change
- Rescue InvalidKeyError at the ceremony boundary and log parameters.keys to see which labels arrived
- Use CoseKey.decode in tests the same way production code does so fixture shape gets exercised
When it happens
Trigger: Calling to_openssl_key on a COSE map with {1=>3, 3=>-257} that lacks -1 or -2: typically a fixture built with only one RSA parameter, or credential-public-key bytes sliced at the wrong offset in authenticatorData (misread credential ID length) so the remaining CBOR decodes to a partial map.
Common situations: Switching test fixtures from EC2/OKP keys to RSA without remembering that -1/-2 carry different parameters per key type; offset drift while hand-parsing attestedCredentialData after credential ID lengths change; emulators emitting incomplete RSA COSE maps.
Related errors
- Invalid EC2 key: #{error.message}
- Missing OKP key coordinate
- RSA key must be at least #{MINIMUM_RSA_KEY_BITS} bits
- Invalid RSA key: #{error.message}
- Unsupported COSE key type/algorithm: #{key_type}/#{algorithm
AI-assisted analysis of basecamp/fizzy@7aabe74580 (2026-08-21).
Data as JSON: /api/errors/2edaaaccef376222.
Report an issue: GitHub.