Module: LetsCert::JWKIOPluginMixin

Included in:
AccountKey
Defined in:
lib/letscert/io_plugins/jwk_io_plugin_mixin.rb

Overview

Mixin for IOPlugin subclasses that handle JWK

Author:

  • Sylvain Daubert

Instance Method Summary collapse

Instance Method Details

#dump_jwk(key) ⇒ String

Dump crypto data (key) to a JSON-encoded string

Parameters:

  • key (OpenSSL::PKey)

Returns:

  • (String)

Raises:

  • (Error)

    unsupported key type



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/letscert/io_plugins/jwk_io_plugin_mixin.rb', line 77

def dump_jwk(key)
  h = {}
  return h.to_json if key.nil?

  case key
  when OpenSSL::PKey::RSA
    h['kty'] = 'RSA'
    h['e'] = urlsafe_encode64(key.e.to_s(2)) if key.e
    h['n'] = urlsafe_encode64(key.n.to_s(2)) if key.n
    if key.private?
      h['d'] = urlsafe_encode64(key.d.to_s(2))
      h['p'] = urlsafe_encode64(key.p.to_s(2))
      h['q'] = urlsafe_encode64(key.q.to_s(2))
    end
  else
    raise Error, 'only RSA keys are supported'
  end
  h.to_json
end

#load_jwk(data) ⇒ OpenSSL::PKey::PKey?

Load crypto data from JSON-encoded file

Parameters:

  • data (String)

    JSON-encoded data

Returns:

  • (OpenSSL::PKey::PKey, nil)

Raises:

  • (Error)

    unsupported key type



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/letscert/io_plugins/jwk_io_plugin_mixin.rb', line 54

def load_jwk(data)
  return nil if data.empty?

  h = JSON.parse(data)
  case h['kty']
  when 'RSA'
    pkey = OpenSSL::PKey::RSA.new
    %w(e n d p q).collect do |key|
      next if h[key].nil?
      value = OpenSSL::BN.new(urlsafe_decode64(h[key]), 2)
      pkey.send "#{key}=".to_sym, value
    end
  else
    raise Error, "unknown account key type '#{k['kty']}'"
  end

  pkey
end

#urlsafe_decode64(data) ⇒ String

Decode base64 string data

Parameters:

  • data (String)

Returns:

  • (String)


40
41
42
43
44
45
46
47
48
# File 'lib/letscert/io_plugins/jwk_io_plugin_mixin.rb', line 40

def urlsafe_decode64(data)
  # Ruby < 2.3.0 urlsafe_decode64 use struct_decode64. So the string
  # is rejected if padding is removed (which JWK do)
  # So, we have to reinject padding
  if !data.end_with?('=') && (data.length % 4).nonzero?
    data = data.ljust((data.length + 3) & ~3, '=')
  end
  Base64.urlsafe_decode64(data)
end

#urlsafe_encode64(data) ⇒ String

Encode string data to base64

Parameters:

  • data (String)

Returns:

  • (String)


33
34
35
# File 'lib/letscert/io_plugins/jwk_io_plugin_mixin.rb', line 33

def urlsafe_encode64(data)
  Base64.urlsafe_encode64(data).sub(/[\s=]*\z/, '')
end