Class: Linzer::JWS::Key

Inherits:
Key
  • Object
show all
Defined in:
lib/linzer/jws.rb

Overview

JWS-compatible signing key implementation.

Wraps a JWT::JWK key object to provide the Linzer Key interface. This enables using JWK-format keys with HTTP Message Signatures.

Instance Method Summary collapse

Instance Method Details

#jwk_thumbprintString

Computes the RFC 7638 JWK SHA-256 Thumbprint for this key's public material.

This is computed directly from the exported JWK rather than delegating to the underlying jwt-eddsa gem's own thumbprint/kid generation: jwt-eddsa (<= 0.9.0) has a bug where its OKP JWK class computes that value over the wrong members (an RSA-shaped n, x instead of the RFC 8037-correct kty, x), which silently produces a keyid that a spec-compliant verifier will reject.

Returns:

  • (String)

    base64url-encoded (no padding) SHA-256 thumbprint

Raises:

  • (Error)

    if this key's JWK "kty" is not supported

See Also:



121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/linzer/jws.rb', line 121

def jwk_thumbprint
  # XXX: drop this method custom implementation and just
  # return material.key_digest
  # once https://github.com/jwt/ruby-jwt-eddsa/pull/26 is resolved
  #
  exported = material.export

  members =
    case exported[:kty]
    when "OKP"
      {crv: exported[:crv], kty: exported[:kty], x: exported[:x]}
    else
      raise Error, "Unsupported JWK kty for thumbprint: #{exported[:kty]}"
    end

  digest = Digest::SHA256.digest(JWT::JSON.generate(members))
  Base64.urlsafe_encode64(digest, padding: false)
end

#sign(data) ⇒ String

Signs data using the JWS key.

Parameters:

  • data (String)

    The data to sign

Returns:

  • (String)

    The signature bytes

Raises:



88
89
90
91
92
# File 'lib/linzer/jws.rb', line 88

def sign(data)
  validate_signing_key
  algo = resolve_algorithm
  algo.sign(data: data, signing_key: signing_key)
end

#verify(signature, data) ⇒ Boolean

Verifies a signature using the JWS key.

Parameters:

  • signature (String)

    The signature bytes to verify

  • data (String)

    The data that was signed

Returns:

  • (Boolean)

    true if valid, false otherwise

Raises:

  • (VerifyError)

    If this key cannot be used for verification



100
101
102
103
104
# File 'lib/linzer/jws.rb', line 100

def verify(signature, data)
  validate_verify_key
  algo = resolve_algorithm
  algo.verify(data: data, signature: signature, verification_key: verify_key)
end