Skip to content

Commit

Permalink
Use the KeyBase to register the different key types
Browse files Browse the repository at this point in the history
  • Loading branch information
anakinj committed Oct 15, 2020
1 parent 86b9ec0 commit e6c1487
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 55 deletions.
38 changes: 26 additions & 12 deletions lib/jwt/jwk.rb
@@ -1,36 +1,50 @@
# frozen_string_literal: true

require_relative 'jwk/key_abstract'
require_relative 'jwk/rsa'
require_relative 'jwk/hmac'
require_relative 'jwk/key_finder'

module JWT
module JWK
MAPPINGS = {
'RSA' => ::JWT::JWK::RSA,
OpenSSL::PKey::RSA => ::JWT::JWK::RSA,
'oct' => ::JWT::JWK::HMAC,
String => ::JWT::JWK::HMAC
}.freeze

class << self
def import(jwk_data)
jwk_kty = jwk_data[:kty] || jwk_data['kty']
raise JWT::JWKError, 'Key type (kty) not provided' unless jwk_kty

MAPPINGS.fetch(jwk_kty.to_s) do |kty|
mappings.fetch(jwk_kty.to_s) do |kty|
raise JWT::JWKError, "Key type #{kty} not supported"
end.import(jwk_data)
end

def create_from(keypair)
MAPPINGS.fetch(keypair.class) do |klass|
mappings.fetch(keypair.class) do |klass|
raise JWT::JWKError, "Cannot create JWK from a #{klass.name}"
end.new(keypair)
end

def classes
@mappings = nil # reset the cached mappings
@classes ||= []
end

alias new create_from

private

def mappings
@mappings ||= generate_mappings
end

def generate_mappings
classes.each_with_object({}) do |klass, hash|
next unless klass.const_defined?('KTYS')
Array(klass::KTYS).each do |kty|
hash[kty] = klass
end
end
end
end
end
end

require_relative 'jwk/key_base'
require_relative 'jwk/rsa'
require_relative 'jwk/hmac'
3 changes: 2 additions & 1 deletion lib/jwt/jwk/hmac.rb
Expand Up @@ -2,8 +2,9 @@

module JWT
module JWK
class HMAC < KeyAbstract
class HMAC < KeyBase
KTY = 'oct'.freeze
KTYS = [KTY, String].freeze

def initialize(keypair, kid = nil)
raise ArgumentError, 'keypair must be of type String' unless keypair.is_a?(String)
Expand Down
36 changes: 0 additions & 36 deletions lib/jwt/jwk/key_abstract.rb

This file was deleted.

18 changes: 18 additions & 0 deletions lib/jwt/jwk/key_base.rb
@@ -0,0 +1,18 @@
# frozen_string_literal: true

module JWT
module JWK
class KeyBase
attr_reader :keypair, :kid

def initialize(keypair, kid = nil)
@keypair = keypair
@kid = kid
end

def self.inherited(klass)
::JWT::JWK.classes << klass
end
end
end
end
12 changes: 6 additions & 6 deletions lib/jwt/jwk/rsa.rb
Expand Up @@ -2,15 +2,15 @@

module JWT
module JWK
class RSA < KeyAbstract
BINARY = 2
KTY = 'RSA'.freeze
class RSA < KeyBase
BINARY = 2
KTY = 'RSA'.freeze
KTYS = [KTY, OpenSSL::PKey::RSA].freeze
RSA_KEY_ELEMENTS = %i[n e d p q dp dq qi].freeze

def initialize(keypair, kid = nil)
raise ArgumentError, 'keypair must be of type OpenSSL::PKey::RSA' unless keypair.is_a?(OpenSSL::PKey::RSA)
super
self.kid ||= generate_kid
super(keypair, kid || generate_kid(keypair.public_key))
end

def private?
Expand All @@ -36,7 +36,7 @@ def export(options = {})

private

def generate_kid
def generate_kid(public_key)
sequence = OpenSSL::ASN1::Sequence([OpenSSL::ASN1::Integer.new(public_key.n),
OpenSSL::ASN1::Integer.new(public_key.e)])
OpenSSL::Digest::SHA256.hexdigest(sequence.to_der)
Expand Down

0 comments on commit e6c1487

Please sign in to comment.