class HealthCards::JWS

Create JWS from a payload

Attributes

header[RW]
key[R]
payload[R]
public_key[R]
signature[W]

Public Class Methods

from_jws(jws, public_key: nil, key: nil) click to toggle source

Creates a Card from a JWS @param jws [String, HealthCards::JWS] the JWS string @param public_key [HealthCards::PublicKey] the public key associated with the JWS @param key [HealthCards::PrivateKey] the private key associated with the JWS @return [HealthCards::HealthCard]

# File lib/health_cards/jws.rb, line 14
def from_jws(jws, public_key: nil, key: nil)
  unless jws.is_a?(HealthCards::JWS) || jws.is_a?(String)
    raise ArgumentError,
          'Expected either a HealthCards::JWS or String'
  end

  header, payload, signature = jws.to_s.split('.').map { |entry| decode(entry) }
  header = JSON.parse(header)
  JWS.new(header: header, payload: payload, signature: signature,
          public_key: public_key, key: key)
end
new(header: nil, payload: nil, signature: nil, key: nil, public_key: nil) click to toggle source

Create a new JWS

# File lib/health_cards/jws.rb, line 33
def initialize(header: nil, payload: nil, signature: nil, key: nil, public_key: nil)
  # Not using accessors because they reset the signature which requires both a key and a payload
  @header = header
  @payload = payload
  @signature = signature if signature
  @key = key
  @public_key = public_key || key&.public_key
end

Public Instance Methods

key=(key) click to toggle source

Set the private key used for signing issued health cards

@param key [HealthCards::PrivateKey, nil] the private key used for signing issued health cards

# File lib/health_cards/jws.rb, line 51
def key=(key)
  PrivateKey.enforce_valid_key_type!(key, allow_nil: true)

  @key = key

  # If it's a new private key then the public key and signature should be updated
  return if @key.nil?

  reset_signature
  self.public_key = @key.public_key
end
kid() click to toggle source

The kid value from the JWS header, used to identify the key to use to verify @return [String]

# File lib/health_cards/jws.rb, line 44
def kid
  header['kid']
end
payload=(new_payload) click to toggle source

Set the JWS payload. Setting a new payload will result in the a new signature @param new_payload [Object]

# File lib/health_cards/jws.rb, line 74
def payload=(new_payload)
  @payload = new_payload
  reset_signature
end
public_key=(public_key) click to toggle source

Set the public key used for signing issued health cards

@param public_key [HealthCards::PublicKey, nil] the private key used for signing issued health cards

# File lib/health_cards/jws.rb, line 66
def public_key=(public_key)
  PublicKey.enforce_valid_key_type!(public_key, allow_nil: true)

  @public_key = public_key
end
signature() click to toggle source

The signature component of the card

@return [String] the unencoded signature

# File lib/health_cards/jws.rb, line 82
def signature
  return @signature if @signature

  raise MissingPrivateKeyError unless key

  @signature ||= key.sign(jws_signing_input)
end
to_s() click to toggle source

Export the card to a JWS String @return [String] the JWS

# File lib/health_cards/jws.rb, line 92
def to_s
  [JSON.generate(header), payload, signature].map { |entry| JWS.encode(entry) }.join('.')
end
verify() click to toggle source

Verify the digital signature on the jws

@return [Boolean]

# File lib/health_cards/jws.rb, line 99
def verify
  raise MissingPublicKeyError unless public_key

  public_key.verify(jws_signing_input, signature)
end

Private Instance Methods

encoded_payload() click to toggle source
# File lib/health_cards/jws.rb, line 111
def encoded_payload
  JWS.encode(payload)
end
jws_signing_input() click to toggle source
# File lib/health_cards/jws.rb, line 107
def jws_signing_input
  "#{JWS.encode(@header.to_json)}.#{encoded_payload}"
end
reset_signature() click to toggle source

Resets the signature

This method is primarily used when an attribute that affects the signature is changed (e.g. the private key changes, the payload changes)

# File lib/health_cards/jws.rb, line 119
def reset_signature
  @signature = nil
  signature if key && payload
end