1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
|
module JSON
class JWK < ActiveSupport::HashWithIndifferentAccess
class UnknownAlgorithm < JWT::Exception; end
def initialize(params = {}, ex_params = {})
case params
when OpenSSL::PKey::RSA, OpenSSL::PKey::EC
super params.to_jwk(ex_params)
when OpenSSL::PKey::PKey
raise UnknownAlgorithm.new('Unknown Key Type')
when String
super(
k: params,
kty: :oct
)
merge! ex_params
else
super params
merge! ex_params
end
self[:kid] ||= thumbprint rescue nil #ignore
end
def content_type
'application/jwk+json'
end
def thumbprint(digest = OpenSSL::Digest::SHA256.new)
digest = case digest
when OpenSSL::Digest
digest
when String, Symbol
OpenSSL::Digest.new digest.to_s
else
raise UnknownAlgorithm.new('Unknown Digest Algorithm')
end
UrlSafeBase64.encode64 digest.digest(normalize.to_json)
end
def to_key
case
when rsa?
to_rsa_key
when ec?
to_ec_key
when oct?
self[:k]
else
raise UnknownAlgorithm.new('Unknown Key Type')
end
end
private
def rsa?
self[:kty].try(:to_sym) == :RSA
end
def ec?
self[:kty].try(:to_sym) == :EC
end
def oct?
self[:kty].try(:to_sym) == :oct
end
def normalize
case
when rsa?
{
e: self[:e],
kty: self[:kty],
n: self[:n]
}
when ec?
{
crv: self[:crv],
kty: self[:kty],
x: self[:x],
y: self[:y]
}
when oct?
{
k: self[:k],
kty: self[:kty]
}
else
raise UnknownAlgorithm.new('Unknown Key Type')
end
end
def to_rsa_key
e, n, d, p, q = [:e, :n, :d, :p, :q].collect do |key|
if self[key]
OpenSSL::BN.new UrlSafeBase64.decode64(self[key]), 2
end
end
key = OpenSSL::PKey::RSA.new
key.e = e
key.n = n
key.d = d if d
key.p = p if p
key.q = q if q
key
end
def to_ec_key
curve_name = case self[:crv].try(:to_sym)
when :'P-256'
'prime256v1'
when :'P-384'
'secp384r1'
when :'P-521'
'secp521r1'
else
raise UnknownAlgorithm.new('Unknown EC Curve')
end
x, y, d = [:x, :y, :d].collect do |key|
if self[key]
OpenSSL::BN.new UrlSafeBase64.decode64(self[key]), 2
end
end
key = OpenSSL::PKey::EC.new curve_name
key.private_key = d if d
key.public_key = OpenSSL::PKey::EC::Point.new(
OpenSSL::PKey::EC::Group.new(curve_name),
OpenSSL::BN.new(['04' + x.to_s(16) + y.to_s(16)].pack('H*'), 2)
)
key
end
end
end
|