lib/webauthn/encoder.rb
# frozen_string_literal: true require "base64" module WebAuthn def self.standard_encoder @standard_encoder ||= Encoder.new end class Encoder # https://www.w3.org/TR/webauthn-2/#base64url-encoding STANDARD_ENCODING = :base64url attr_reader :encoding def initialize(encoding = STANDARD_ENCODING) @encoding = encoding end def encode(data) case encoding when :base64 [data].pack("m0") # Base64.strict_encode64(data) when :base64url data = [data].pack("m0") # Base64.urlsafe_encode64(data, padding: false) data.chomp!("==") or data.chomp!("=") data.tr!("+/", "-_") data when nil, false data else raise "Unsupported or unknown encoding: #{encoding}" end end def decode(data) case encoding when :base64 data.unpack1("m0") # Base64.strict_decode64(data) when :base64url if !data.end_with?("=") && data.length % 4 != 0 # Base64.urlsafe_decode64(data) data = data.ljust((data.length + 3) & ~3, "=") data.tr!("-_", "+/") else data = data.tr("-_", "+/") end data.unpack1("m0") when nil, false data else raise "Unsupported or unknown encoding: #{encoding}" end end end end