lib/webauthn/public_key.rb
# frozen_string_literal: true require "cose/algorithm" require "cose/error" require "cose/key" require "cose/rsapkcs1_algorithm" require "webauthn/attestation_statement/fido_u2f/public_key" module WebAuthn class PublicKey class UnsupportedAlgorithm < Error; end def self.deserialize(public_key) cose_key = if WebAuthn::AttestationStatement::FidoU2f::PublicKey.uncompressed_point?(public_key) # Gem version v1.11.0 and lower, used to behave so that Credential#public_key # returned an EC P-256 uncompressed point. # # Because of https://github.com/cedarcode/webauthn-ruby/issues/137 this was changed # and Credential#public_key started returning the unchanged COSE_Key formatted # credentialPublicKey (as in https://www.w3.org/TR/webauthn/#credentialpublickey). # # Given that the credential public key is expected to be stored long-term by the gem # user and later be passed as the public_key argument in the # AuthenticatorAssertionResponse.verify call, we then need to support the two formats. COSE::Key::EC2.new( alg: COSE::Algorithm.by_name("ES256").id, crv: 1, x: public_key[1..32], y: public_key[33..-1] ) else COSE::Key.deserialize(public_key) end new(cose_key: cose_key) end attr_reader :cose_key def initialize(cose_key:) @cose_key = cose_key end def pkey @cose_key.to_pkey end def alg @cose_key.alg end def verify(signature, verification_data) cose_algorithm.verify(pkey, signature, verification_data) rescue COSE::Error false end private def cose_algorithm @cose_algorithm ||= COSE::Algorithm.find(alg) || raise( UnsupportedAlgorithm, "The public key algorithm #{alg} is not among the available COSE algorithms" ) end end end