class Google::Auth::IDTokens::KeyInfo

A public key used for verifying ID tokens.

This includes the public key data, ID, and the algorithm used for signature verification. RSA and Elliptical Curve (EC) keys are supported.

Constants

CURVE_NAME_MAP

@private

Attributes

algorithm[R]

The signature algorithm. (normally ‘RS256` or `ES256`) @return [String]

id[R]

The key ID. @return [String]

key[R]

The key itself. @return [OpenSSL::PKey::RSA,OpenSSL::PKey::EC]

Public Class Methods

from_jwk(jwk) click to toggle source

Create a KeyInfo from a single JWK, which may be given as either a hash or an unparsed JSON string.

@param jwk [Hash,String] The JWK specification. @return [KeyInfo] @raise [KeySourceError] If the key could not be extracted from the

JWK.
# File lib/googleauth/id_tokens/key_sources.rb, line 78
def from_jwk jwk
  jwk = symbolize_keys ensure_json_parsed jwk
  key = case jwk[:kty]
        when "RSA"
          extract_rsa_key jwk
        when "EC"
          extract_ec_key jwk
        when nil
          raise KeySourceError, "Key type not found"
        else
          raise KeySourceError, "Cannot use key type #{jwk[:kty]}"
        end
  new id: jwk[:kid], key: key, algorithm: jwk[:alg]
end
from_jwk_set(jwk_set) click to toggle source

Create an array of KeyInfo from a JWK Set, which may be given as either a hash or an unparsed JSON string.

@param jwk [Hash,String] The JWK Set specification. @return [Array<KeyInfo>] @raise [KeySourceError] If a key could not be extracted from the

JWK Set.
# File lib/googleauth/id_tokens/key_sources.rb, line 102
def from_jwk_set jwk_set
  jwk_set = symbolize_keys ensure_json_parsed jwk_set
  jwks = jwk_set[:keys]
  raise KeySourceError, "No keys found in jwk set" unless jwks
  jwks.map { |jwk| from_jwk jwk }
end
new(id: nil, key: nil, algorithm: nil) click to toggle source

Create a public key info structure.

@param id [String] The key ID. @param key [OpenSSL::PKey::RSA,OpenSSL::PKey::EC] The key itself. @param algorithm [String] The algorithm (normally ‘RS256` or `ES256`)

# File lib/googleauth/id_tokens/key_sources.rb, line 44
def initialize id: nil, key: nil, algorithm: nil
  @id = id
  @key = key
  @algorithm = algorithm
end

Private Class Methods

ensure_json_parsed(input) click to toggle source
# File lib/googleauth/id_tokens/key_sources.rb, line 111
def ensure_json_parsed input
  return input unless input.is_a? String
  JSON.parse input
rescue JSON::ParserError
  raise KeySourceError, "Unable to parse JSON"
end
extract_ec_key(jwk) click to toggle source
# File lib/googleauth/id_tokens/key_sources.rb, line 146
def extract_ec_key jwk
  begin
    x_data = Base64.urlsafe_decode64 jwk[:x]
    y_data = Base64.urlsafe_decode64 jwk[:y]
  rescue ArgumentError
    raise KeySourceError, "Badly formatted key data"
  end
  curve_name = CURVE_NAME_MAP[jwk[:crv]]
  raise KeySourceError, "Unsupported EC curve #{jwk[:crv]}" unless curve_name
  group = OpenSSL::PKey::EC::Group.new curve_name
  x_hex = x_data.unpack1 "H*"
  y_hex = y_data.unpack1 "H*"
  bn = OpenSSL::BN.new ["04#{x_hex}#{y_hex}"].pack("H*"), 2
  point =  OpenSSL::PKey::EC::Point.new group, bn
  sequence = OpenSSL::ASN1::Sequence([
                                       OpenSSL::ASN1::Sequence([OpenSSL::ASN1::ObjectId("id-ecPublicKey"),
                                                                OpenSSL::ASN1::ObjectId(curve_name)]),
                                       OpenSSL::ASN1::BitString(point.to_octet_string(:uncompressed))
                                     ])
  OpenSSL::PKey::EC.new sequence.to_der
end
extract_rsa_key(jwk) click to toggle source
# File lib/googleauth/id_tokens/key_sources.rb, line 124
def extract_rsa_key jwk
  begin
    n_data = Base64.urlsafe_decode64 jwk[:n]
    e_data = Base64.urlsafe_decode64 jwk[:e]
  rescue ArgumentError
    raise KeySourceError, "Badly formatted key data"
  end
  n_bn = OpenSSL::BN.new n_data, 2
  e_bn = OpenSSL::BN.new e_data, 2
  sequence = [OpenSSL::ASN1::Integer.new(n_bn), OpenSSL::ASN1::Integer.new(e_bn)]
  rsa_key =  OpenSSL::PKey::RSA.new OpenSSL::ASN1::Sequence(sequence).to_der
  rsa_key.public_key
end
symbolize_keys(hash) click to toggle source
# File lib/googleauth/id_tokens/key_sources.rb, line 118
def symbolize_keys hash
  result = {}
  hash.each { |key, val| result[key.to_sym] = val }
  result
end