class Acme::Client::JWK::ECDSA

Constants

KNOWN_CURVES

JWA parameters for supported OpenSSL curves. tools.ietf.org/html/rfc7518#section-3.1

Public Class Methods

new(private_key) click to toggle source

Instantiate a new ECDSA JWK.

private_key - A OpenSSL::PKey::EC instance.

Returns nothing.

# File lib/acme/client/jwk/ecdsa.rb, line 27
def initialize(private_key)
  unless private_key.is_a?(OpenSSL::PKey::EC)
    raise ArgumentError, 'private_key must be a OpenSSL::PKey::EC'
  end

  unless @curve_params = KNOWN_CURVES[private_key.group.curve_name]
    raise ArgumentError, 'Unknown EC curve'
  end

  @private_key = private_key
end

Public Instance Methods

jwa_alg() click to toggle source

The name of the algorithm as needed for the ‘alg` member of a JWS object.

Returns a String.

# File lib/acme/client/jwk/ecdsa.rb, line 42
def jwa_alg
  @curve_params[:jwa_alg]
end
sign(message) click to toggle source

Sign a message with the private key.

message - A String message to sign.

Returns a String signature.

# File lib/acme/client/jwk/ecdsa.rb, line 63
def sign(message)
  # DER encoded ASN.1 signature
  der = @private_key.sign(@curve_params[:digest].new, message)

  # ASN.1 SEQUENCE
  seq = OpenSSL::ASN1.decode(der)

  # ASN.1 INTs
  ints = seq.value

  # BigNumbers
  bns = ints.map(&:value)

  byte_size = (@private_key.group.degree + 7) / 8

  # Binary R/S values
  r, s = bns.map { |bn| bn.to_s(2).rjust(byte_size, "\x00") }

  # JWS wants raw R/S concatenated.
  [r, s].join
end
to_h() click to toggle source

Get this JWK as a Hash for JSON serialization.

Returns a Hash.

# File lib/acme/client/jwk/ecdsa.rb, line 49
def to_h
  {
    crv: @curve_params[:jwa_crv],
    kty: 'EC',
    x: Acme::Client::Util.urlsafe_base64(coordinates[:x]),
    y: Acme::Client::Util.urlsafe_base64(coordinates[:y])
  }
end

Private Instance Methods

coordinates() click to toggle source
# File lib/acme/client/jwk/ecdsa.rb, line 87
def coordinates
  @coordinates ||= begin
    hex = public_key.to_bn.to_s(16)
    data_len = hex.length - 2
    hex_x = hex[2, data_len / 2]
    hex_y = hex[2 + data_len / 2, data_len / 2]

    {
      x: [hex_x].pack('H*'),
      y: [hex_y].pack('H*')
    }
  end
end
public_key() click to toggle source
# File lib/acme/client/jwk/ecdsa.rb, line 101
def public_key
  @private_key.public_key
end