Class: Acme::Client::JWK::ECDSA

Inherits:
Base
  • Object
show all
Defined in:
lib/acme/client/jwk/ecdsa.rb

Constant Summary collapse

KNOWN_CURVES =

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

{
  'prime256v1' => {
    jwa_crv: 'P-256',
    jwa_alg: 'ES256',
    digest: OpenSSL::Digest::SHA256
  }.freeze,
  'secp384r1' => {
    jwa_crv: 'P-384',
    jwa_alg: 'ES384',
    digest: OpenSSL::Digest::SHA384
  }.freeze,
  'secp521r1' => {
    jwa_crv: 'P-521',
    jwa_alg: 'ES512',
    digest: OpenSSL::Digest::SHA512
  }.freeze
}.freeze

Constants inherited from Base

Base::THUMBPRINT_DIGEST

Instance Method Summary collapse

Methods inherited from Base

#jws, #jws_header, #thumbprint, #to_json

Constructor Details

#initialize(private_key) ⇒ ECDSA

Instantiate a new ECDSA JWK.

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

Returns nothing.



27
28
29
30
31
32
33
34
35
36
37
# 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

Instance Method Details

#jwa_algObject

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

Returns a String.



42
43
44
# File 'lib/acme/client/jwk/ecdsa.rb', line 42

def jwa_alg
  @curve_params[:jwa_alg]
end

#sign(message) ⇒ Object

Sign a message with the private key.

message - A String message to sign.

Returns a String signature.



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# 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_hObject

Get this JWK as a Hash for JSON serialization.

Returns a Hash.



49
50
51
52
53
54
55
56
# 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].to_s(2)),
    y: Acme::Client::Util.urlsafe_base64(coordinates[:y].to_s(2))
  }
end