Class: JOSE::JWK

Inherits:
Struct
  • Object
show all
Defined in:
lib/jose/jwk.rb

Overview

JWK stands for JSON Web Key which is defined in RFC 7517.

Defined Under Namespace

Modules: KTY, OpenSSHKey, PEM Classes: KTY_EC, KTY_OKP_Ed25519, KTY_OKP_Ed25519ph, KTY_OKP_Ed448, KTY_OKP_Ed448ph, KTY_OKP_X25519, KTY_OKP_X448, KTY_RSA, KTY_oct, Set

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#fieldsObject

Returns the value of attribute fields

Returns:

  • (Object)

    the current value of fields


3
4
5
# File 'lib/jose/jwk.rb', line 3

def fields
  @fields
end

#keysObject

Returns the value of attribute keys

Returns:

  • (Object)

    the current value of keys


3
4
5
# File 'lib/jose/jwk.rb', line 3

def keys
  @keys
end

#ktyObject

Returns the value of attribute kty

Returns:

  • (Object)

    the current value of kty


3
4
5
# File 'lib/jose/jwk.rb', line 3

def kty
  @kty
end

Class Method Details

.block_decrypt(jwk, encrypted) ⇒ [String, JOSE::JWE]

Decrypts the encrypted binary or map using the jwk.

Parameters:

Returns:

See Also:

  • JOWE::JWE.block_decrypt

599
600
601
# File 'lib/jose/jwk.rb', line 599

def self.block_decrypt(jwk, encrypted)
  return from(jwk).block_decrypt(encrypted)
end

.block_encrypt(jwk, plain_text, jwe = nil) ⇒ JOSE::EncryptedMap

Encrypts the plain_text using the jwk and algorithms specified by the jwe.

Parameters:

Returns:

See Also:


619
620
621
# File 'lib/jose/jwk.rb', line 619

def self.block_encrypt(jwk, plain_text, jwe = nil)
  return from(jwk).block_encrypt(plain_text, jwe)
end

.block_encryptor(jwk) ⇒ JOSE::Map+

Returns a block encryptor map for the key type.

Parameters:

Returns:


638
639
640
641
642
643
644
# File 'lib/jose/jwk.rb', line 638

def self.block_encryptor(jwk)
  if jwk.is_a?(Array)
    return from(jwk).map { |obj| obj.block_encryptor }
  else
    return from(jwk).block_encryptor
  end
end

.box_decrypt(jwk, encrypted, public_jwk = nil) ⇒ [String, JOSE::JWE]

Key Agreement decryption of the encrypted binary or map using my_private_jwk.

Parameters:

Returns:

See Also:


661
662
663
# File 'lib/jose/jwk.rb', line 661

def self.box_decrypt(jwk, encrypted, public_jwk = nil)
  return from(jwk).box_decrypt(encrypted, public_jwk)
end

.box_encrypt(plain_text, box_keys, jwe = nil) ⇒ JOSE::EncryptedMap, [JOSE::EncryptedMap, JOSE::JWK]

Key Agreement encryption of plain_text by generating an ephemeral private key based on other_public_jwk curve.

If no private key has been specified in box_keys, it generates an ephemeral private key based on other public key curve.

Parameters:

Returns:

See Also:


690
691
692
693
# File 'lib/jose/jwk.rb', line 690

def self.box_encrypt(plain_text, box_keys, jwe = nil)
  other_public_key, my_private_key = box_keys
  return from(other_public_key).box_encrypt(plain_text, my_private_jwk, jwe)
end

.from(object, modules = nil, key = nil) ⇒ JOSE::JWK+

Converts a binary or map into a JOSE.JWK.

JOSE::JWK.from({"k" => "", "kty" => "oct"})
# => #<struct JOSE::JWK keys=nil, kty=#<struct JOSE::JWK::KTY_oct oct="">, fields=JOSE::Map[]>
JOSE::JWK.from("{\"k\":\"\",\"kty\":\"oct\"}")
# => #<struct JOSE::JWK keys=nil, kty=#<struct JOSE::JWK::KTY_oct oct="">, fields=JOSE::Map[]>

The "kty" field may be overridden with a custom module that implements the JOSE::JWK::KTY behaviours.

For example:

JOSE::JWK.from({ "kty" => "custom" }, { kty: MyCustomKey })
# => #<struct JOSE::JWK keys=nil, kty=#<MyCustomKey:0x007f8c5419ff68>, fields=JOSE::Map[]>

If a key has been specified, it will decrypt an encrypted binary or map into a JOSE::JWK using the specified key.

JOSE::JWK.from("eyJhbGciOiJQQkVTMi1IUzI1NitBMTI4S1ciLCJjdHkiOiJqd2sranNvbiIsImVuYyI6IkExMjhHQ00iLCJwMmMiOjQwOTYsInAycyI6Im5OQ1ZNQUktNTU5UVFtbWRFcnBsZFEifQ.Ucye69ii4dxd1ykNFlJyBVeA6xeNu4aV.2pZ4nBoxBjmdrneS.boqwdFZVNAFHk1M5P6kPYgBUgGwW32QuKzHuFA.wL9Hy6dcE_DPkUW9s5iwKA", "password")
# => [#<struct JOSE::JWK keys=nil, kty=#<struct JOSE::JWK::KTY_oct oct="secret">, fields=JOSE::Map[]>,
#  #<struct JOSE::JWE
#   alg=
#    #<struct JOSE::JWE::ALG_PBES2
#     hmac=OpenSSL::Digest::SHA256,
#     bits=128,
#     salt="PBES2-HS256+A128KW\x00\x9C\xD0\x950\x02>\xE7\x9FPBi\x9D\x12\xBAeu",
#     iter=4096>,
#   enc=#<struct JOSE::JWE::ENC_AES_GCM cipher_name="aes-128-gcm", bits=128, cek_len=16, iv_len=12>,
#   zip=nil,
#   fields=JOSE::Map["cty" => "jwk+json"]>]

Parameters:

Returns:


43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/jose/jwk.rb', line 43

def self.from(object, modules = nil, key = nil)
  case object
  when JOSE::Map, Hash
    return from_map(object, modules, key)
  when String
    return from_binary(object, modules, key)
  when JOSE::JWK
    return object
  when Array
    return object.map { |obj| from(obj, modules, key) }
  else
    raise ArgumentError, "'object' must be a Hash, String, JOSE::JWK, or Array"
  end
end

.from_binary(object, modules = nil, key = nil) ⇒ JOSE::JWK+

Converts a binary into a JOSE::JWK.

Parameters:

  • object (String, Array<String>)
  • modules (Hash) (defaults to: nil)
  • key (String) (defaults to: nil)

Returns:


64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/jose/jwk.rb', line 64

def self.from_binary(object, modules = nil, key = nil)
  if (modules.is_a?(String) or modules.is_a?(JOSE::JWK)) and key.nil?
    key = modules
    modules = {}
  end
  modules ||= {}
  case object
  when String
    if key
      plain_text, jwe = JOSE::JWE.block_decrypt(key, object)
      return from_binary(plain_text, modules), jwe
    else
      return from_map(JOSE.decode(object), modules)
    end
  when Array
    return object.map { |obj| from_binary(obj, modules, key) }
  else
    raise ArgumentError, "'object' must be a String or Array"
  end
end

.from_file(file, modules = nil, key = nil) ⇒ JOSE::JWK

Reads file and calls from_binary to convert into a JOSE::JWK.

Parameters:

  • file (String)
  • modules (Hash) (defaults to: nil)
  • key (String) (defaults to: nil)

Returns:


91
92
93
# File 'lib/jose/jwk.rb', line 91

def self.from_file(file, modules = nil, key = nil)
  return from_binary(File.binread(file), modules, key)
end

.from_key(object, modules = {}) ⇒ JOSE::JWK

Converts Ruby records for EC and RSA keys into a JOSE::JWK.

Parameters:

  • object (OpenSSL::PKey)
  • modules (Hash) (defaults to: {})

Returns:


100
101
102
103
# File 'lib/jose/jwk.rb', line 100

def self.from_key(object, modules = {})
  kty = modules[:kty] || JOSE::JWK::KTY
  return JOSE::JWK.new(nil, *kty.from_key(object))
end

.from_map(object, modules = nil, key = nil) ⇒ JOSE::JWK+

Converts a map into a JOSE::JWK.

Parameters:

  • object (JOSE::Map, Hash, Array<JOSE::Map, Hash>)
  • modules (Hash) (defaults to: nil)
  • key (String) (defaults to: nil)

Returns:


111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/jose/jwk.rb', line 111

def self.from_map(object, modules = nil, key = nil)
  if (modules.is_a?(String) or modules.is_a?(JOSE::JWK)) and key.nil?
    key = modules
    modules = {}
  end
  modules ||= {}
  case object
  when JOSE::Map, Hash
    if key
      plain_text, jwe = JOSE::JWE.block_decrypt(key, object)
      return from_binary(plain_text, modules), jwe
    else
      return from_fields(JOSE::JWK.new(nil, nil, JOSE::Map.new(object)), modules)
    end
  when Array
    return object.map { |obj| from_map(obj, modules, key) }
  else
    raise ArgumentError, "'object' must be a JOSE::Map, Hash, or Array"
  end
end

.from_oct(object, modules = {}) ⇒ JOSE::JWK

Converts an arbitrary binary into a JOSE::JWK with "kty" of "oct".

Parameters:

  • object (String)
  • modules (Hash) (defaults to: {})

Returns:


137
138
139
140
# File 'lib/jose/jwk.rb', line 137

def self.from_oct(object, modules = {})
  kty = modules[:kty] || JOSE::JWK::KTY_oct
  return JOSE::JWK.new(nil, *kty.from_oct(object))
end

.from_oct_file(file, modules = {}) ⇒ JOSE::JWK

Reads file and calls JOSE::JWK.from_oct to convert into a JOSE::JWK.

Parameters:

  • file (String)
  • modules (Hash) (defaults to: {})

Returns:


147
148
149
# File 'lib/jose/jwk.rb', line 147

def self.from_oct_file(file, modules = {})
  return from_oct(File.binread(file), modules)
end

.from_okp(object, modules = {}) ⇒ JOSE::JWK

Converts an octet key pair into a JOSE::JWK with "kty" of "OKP".

Parameters:

  • object (Array)
  • modules (Hash) (defaults to: {})

Returns:

Raises:

  • (ArgumentError)

156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
# File 'lib/jose/jwk.rb', line 156

def self.from_okp(object, modules = {})
  raise ArgumentError, "object must be an Array of length 2" if not object.is_a?(Array) or object.length != 2
  kty = modules[:kty] || case object[0]
  when :Ed25519
    JOSE::JWK::KTY_OKP_Ed25519
  when :Ed25519ph
    JOSE::JWK::KTY_OKP_Ed25519ph
  when :Ed448
    JOSE::JWK::KTY_OKP_Ed448
  when :Ed448ph
    JOSE::JWK::KTY_OKP_Ed448ph
  when :X25519
    JOSE::JWK::KTY_OKP_X25519
  when :X448
    JOSE::JWK::KTY_OKP_X448
  else
    raise ArgumentError, "unrecognized :okp object"
  end
  return JOSE::JWK.new(nil, *kty.from_okp(object))
end

.from_openssh_key(object, modules = {}) ⇒ JOSE::JWK

Converts an openssh key into a JOSE::JWK with "kty" of "OKP".

Parameters:

  • object (String, Array)
  • modules (Hash) (defaults to: {})

Returns:

Raises:

  • (ArgumentError)

182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
# File 'lib/jose/jwk.rb', line 182

def self.from_openssh_key(object, modules = {})
  raise ArgumentError, "object must be a String or Array" if not object.is_a?(String) and not object.is_a?(Array)
  keys = object
  if object.is_a?(String)
    keys = JOSE::JWK::OpenSSHKey.from_binary(object)
  end
  ((pk_type, pk), key), = keys[0]
  sk_type, sk_pk, = key
  if pk_type and pk and key and sk_type and sk_pk and pk_type == sk_type and pk == sk_pk
    kty = modules[:kty] || case pk_type
    when 'ssh-ed25519'
      JOSE::JWK::KTY_OKP_Ed25519
    when 'ssh-ed25519ph'
      JOSE::JWK::KTY_OKP_Ed25519ph
    when 'ssh-ed448'
      JOSE::JWK::KTY_OKP_Ed448
    when 'ssh-ed448ph'
      JOSE::JWK::KTY_OKP_Ed448ph
    when 'ssh-x25519'
      JOSE::JWK::KTY_OKP_X25519
    when 'ssh-x448'
      JOSE::JWK::KTY_OKP_X448
    else
      raise ArgumentError, "unrecognized openssh key type: #{pk_type.inspect}"
    end
    return JOSE::JWK.new(nil, *kty.from_openssh_key(key))
  else
    raise ArgumentError, "unrecognized openssh key format"
  end
end

.from_openssh_key_file(file, modules = {}) ⇒ JOSE::JWK

Reads file and calls JOSE::JWK.from_openssh_key to convert into a JOSE::JWK.

Parameters:

  • file (String)
  • modules (Hash) (defaults to: {})

Returns:


218
219
220
# File 'lib/jose/jwk.rb', line 218

def self.from_openssh_key_file(file, modules = {})
  return from_openssh_key(File.binread(file), modules)
end

.from_pem(object, modules = nil, password = nil) ⇒ JOSE::JWK

Converts a PEM (Privacy Enhanced Email) binary into a JOSE::JWK.

If password is present, decrypts an encrypted PEM (Privacy Enhanced Email) binary into a JOSE::JWK using password.

Parameters:

  • object (String)
  • modules (Hash) (defaults to: nil)
  • password (String) (defaults to: nil)

Returns:


230
231
232
233
234
235
236
237
238
# File 'lib/jose/jwk.rb', line 230

def self.from_pem(object, modules = nil, password = nil)
  if modules.is_a?(String) and password.nil?
    password = modules
    modules  = {}
  end
  modules ||= {}
  kty = modules[:kty] || JOSE::JWK::PEM
  return JOSE::JWK.new(nil, *kty.from_binary(object, password))
end

.from_pem_file(file, modules = nil, password = nil) ⇒ JOSE::JWK

Reads file and calls JOSE::JWK.from_pem to convert into a JOSE::JWK.

Parameters:

  • file (String)
  • modules (Hash) (defaults to: nil)
  • password (String) (defaults to: nil)

Returns:


246
247
248
# File 'lib/jose/jwk.rb', line 246

def self.from_pem_file(file, modules = nil, password = nil)
  return from_pem(File.binread(file), modules, password)
end

.generate_key(params) ⇒ JOSE::JWK

Generates a new JOSE::JWK based on another JOSE::JWK or from initialization params provided.

Passing another JOSE::JWK results in different behavior depending on the "kty":

  • "EC" - uses the same named curve to generate a new key
  • "oct" - uses the byte size to generate a new key
  • "OKP" - uses the named curve to generate a new key
  • "RSA" - uses the same modulus and exponent sizes to generate a new key

The following initialization params may also be used:

  • [:ec, "P-256" | "P-384" | "P-521"] - generates an "EC" key using the "P-256", "P-384", or "P-521" curves
  • [:oct, bytes] - generates an "oct" key made of a random bytes number of bytes
  • [:okp, :Ed25519 | :Ed25519ph | :Ed448 | :Ed448ph | :X25519 | :X448] - generates an "OKP" key using the specified curve
  • [:rsa, modulus_size] | [:rsa, modulus_size, exponent_size] - generates an "RSA" key using the modulus_size and exponent_size

Parameters:

  • params (Array)

Returns:


764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
# File 'lib/jose/jwk.rb', line 764

def self.generate_key(params)
  if params.is_a?(Array) and (params.length == 2 or params.length == 3)
    case params[0]
    when :ec
      return JOSE::JWK.new(nil, *JOSE::JWK::KTY_EC.generate_key(params))
    when :oct
      return JOSE::JWK.new(nil, *JOSE::JWK::KTY_oct.generate_key(params))
    when :okp
      case params[1]
      when :Ed25519
        return JOSE::JWK.new(nil, *JOSE::JWK::KTY_OKP_Ed25519.generate_key(params))
      when :Ed25519ph
        return JOSE::JWK.new(nil, *JOSE::JWK::KTY_OKP_Ed25519ph.generate_key(params))
      when :Ed448
        return JOSE::JWK.new(nil, *JOSE::JWK::KTY_OKP_Ed448.generate_key(params))
      when :Ed448ph
        return JOSE::JWK.new(nil, *JOSE::JWK::KTY_OKP_Ed448ph.generate_key(params))
      when :X25519
        return JOSE::JWK.new(nil, *JOSE::JWK::KTY_OKP_X25519.generate_key(params))
      when :X448
        return JOSE::JWK.new(nil, *JOSE::JWK::KTY_OKP_X448.generate_key(params))
      else
        raise ArgumentError, "invalid :okp key generation params"
      end
    when :rsa
      return JOSE::JWK.new(nil, *JOSE::JWK::KTY_RSA.generate_key(params))
    else
      raise ArgumentError, "invalid key generation params"
    end
  elsif params.is_a?(JOSE::JWK)
    return params.generate_key
  elsif params.respond_to?(:generate_key)
    return JOSE::JWK.new(nil, *params.generate_key(JOSE::Map[]))
  else
    raise ArgumentError, "invalid key generation params"
  end
end

.merge(left, right) ⇒ JOSE::JWK

Merges map on right into map on left.

Parameters:

Returns:


813
814
815
# File 'lib/jose/jwk.rb', line 813

def self.merge(left, right)
  return from(left).merge(right)
end

.shared_secret(your_jwk, my_jwk) ⇒ String

Computes the shared secret between two keys.

Currently only works for "EC" keys and "OKP" keys with "crv" set to "X25519" or "X448".

Parameters:

Returns:

  • (String)

841
842
843
# File 'lib/jose/jwk.rb', line 841

def self.shared_secret(your_jwk, my_jwk)
  return from(your_jwk).shared_secret(from(my_jwk))
end

.sign(jwk, plain_text, jws = nil, header = nil) ⇒ JOSE::SignedMap

Signs the plain_text using the jwk and the default signer algorithm jws for the key type.

Parameters:

Returns:

See Also:


866
867
868
# File 'lib/jose/jwk.rb', line 866

def self.sign(jwk, plain_text, jws = nil, header = nil)
  return from(jwk).sign(plain_text, jws, header)
end

.signer(jwk) ⇒ JOSE::Map

Returns a signer map for the key type.

Parameters:

Returns:


886
887
888
# File 'lib/jose/jwk.rb', line 886

def self.signer(jwk)
  return from(jwk).signer
end

.thumbprint(digest_type, jwk = nil) ⇒ String

Returns the unique thumbprint for a JOSE::JWK using the digest_type.

# let's define two different keys that will have the same thumbprint
jwk1 = JOSE::JWK.from_oct("secret")
jwk2 = JOSE::JWK.from({ "use" => "sig", "k" => "c2VjcmV0", "kty" => "oct" })

JOSE::JWK.thumbprint(jwk1)
# => "DWBh0SEIAPYh1x5uvot4z3AhaikHkxNJa3Ada2fT-Cg"
JOSE::JWK.thumbprint(jwk2)
# => "DWBh0SEIAPYh1x5uvot4z3AhaikHkxNJa3Ada2fT-Cg"
JOSE::JWK.thumbprint('MD5', jwk1)
# => "Kldz8k5PQm7y1E3aNBlMiA"
JOSE::JWK.thumbprint('MD5', jwk2)
# => "Kldz8k5PQm7y1E3aNBlMiA"

Parameters:

  • digest_type (String)
  • jwk (JOSE::JWK) (defaults to: nil)

Returns:

  • (String)

See Also:


917
918
919
920
921
922
923
# File 'lib/jose/jwk.rb', line 917

def self.thumbprint(digest_type, jwk = nil)
  if jwk.nil?
    jwk = digest_type
    digest_type = nil
  end
  return from(jwk).thumbprint(digest_type)
end

.to_binary(jwk, key = nil, jwe = nil) ⇒ String, ...

Converts a JOSE::JWK into a binary.

Parameters:

Returns:


258
259
260
261
262
263
264
# File 'lib/jose/jwk.rb', line 258

def self.to_binary(jwk, key = nil, jwe = nil)
  if jwk.is_a?(Array)
    return jwk.map { |obj| from(obj).to_binary(key, jwe) }
  else
    return from(jwk).to_binary(key, jwe)
  end
end

.to_file(jwk, file, key = nil, jwe = nil) ⇒ Fixnum

Calls JOSE::JWK.to_binary on a JOSE::JWK and then writes the binary to file.

Parameters:

Returns:

  • (Fixnum)

    bytes written


289
290
291
# File 'lib/jose/jwk.rb', line 289

def self.to_file(jwk, file, key = nil, jwe = nil)
  return from(jwk).to_file(file, key, jwe)
end

.to_key(jwk) ⇒ OpenSSL::PKey, Object

Converts a JOSE::JWK into the raw key format.

Parameters:

Returns:

  • (OpenSSL::PKey, Object)

307
308
309
# File 'lib/jose/jwk.rb', line 307

def self.to_key(jwk)
  return from(jwk).to_key
end

.to_map(jwk, key = nil, jwe = nil) ⇒ JOSE::Map+

Converts a JOSE::JWK into a map.

Parameters:

Returns:


324
325
326
327
328
329
330
# File 'lib/jose/jwk.rb', line 324

def self.to_map(jwk, key = nil, jwe = nil)
  if jwk.is_a?(Array)
    return from(jwk).map { |obj| obj.to_map(key, jwe) }
  else
    return from(jwk).to_map(key, jwe)
  end
end

.to_oct(jwk) ⇒ String+

Converts a JOSE::JWK into a raw binary octet.

Parameters:

Returns:

  • (String, Array<String>)

352
353
354
355
356
357
358
# File 'lib/jose/jwk.rb', line 352

def self.to_oct(jwk)
  if jwk.is_a?(Array)
    return from(jwk).map { |obj| obj.to_oct }
  else
    return from(jwk).to_oct
  end
end

.to_oct_file(jwk, file) ⇒ Fixnum

Calls JOSE::JWK.to_oct on a JOSE::JWK and then writes the binary to file.

Parameters:

Returns:

  • (Fixnum)

    bytes written


372
373
374
# File 'lib/jose/jwk.rb', line 372

def self.to_oct_file(jwk, file)
  return from(jwk).to_file(file)
end

.to_okp(jwk) ⇒ Object+

Converts a JOSE::JWK into an octet key pair.

Parameters:

Returns:

  • (Object, Array<Object>)

388
389
390
391
392
393
394
# File 'lib/jose/jwk.rb', line 388

def self.to_okp(jwk)
  if jwk.is_a?(Array)
    return from(jwk).map { |obj| obj.to_okp }
  else
    return from(jwk).to_okp
  end
end

.to_openssh_key(jwk) ⇒ Object+

Converts a JOSE::JWK into an OpenSSH key binary.

Parameters:

Returns:

  • (Object, Array<Object>)

407
408
409
410
411
412
413
# File 'lib/jose/jwk.rb', line 407

def self.to_openssh_key(jwk)
  if jwk.is_a?(Array)
    return from(jwk).map { |obj| obj.to_openssh_key }
  else
    return from(jwk).to_openssh_key
  end
end

.to_openssh_key_file(jwk, file) ⇒ Fixnum

Calls JOSE::JWK.to_openssh_key on a JOSE::JWK and then writes the binary to file.

Parameters:

Returns:

  • (Fixnum)

    bytes written


427
428
429
# File 'lib/jose/jwk.rb', line 427

def self.to_openssh_key_file(jwk, file)
  return from(jwk).to_file(file)
end

.to_pem(jwk, password = nil) ⇒ String+

Converts a JOSE::JWK into a PEM (Privacy Enhanced Email) binary.

Parameters:

Returns:

  • (String, Array<String>)

444
445
446
447
448
449
450
# File 'lib/jose/jwk.rb', line 444

def self.to_pem(jwk, password = nil)
  if jwk.is_a?(Array)
    return from(jwk).map { |obj| obj.to_pem(password) }
  else
    return from(jwk).to_pem(password)
  end
end

.to_pem_file(jwk, file, password = nil) ⇒ Fixnum

Calls JOSE::JWK.to_pem on a JOSE::JWK and then writes the binary to file.

Parameters:

  • jwk (JOSE::Map, Hash, String, JOSE::JWK)
  • file (String)
  • password (String) (defaults to: nil)

Returns:

  • (Fixnum)

    bytes written


466
467
468
# File 'lib/jose/jwk.rb', line 466

def self.to_pem_file(jwk, file, password = nil)
  return from(jwk).to_file(file, password)
end

.to_public(jwk) ⇒ JOSE::JWK+

Converts a private JOSE::JWK into a public JOSE::JWK.

jwk_rsa = JOSE::JWK.generate_key([:rsa, 256]).to_map
# => JOSE::Map[
#  "dq" => "Iv_BghpjRyv8hk4AgsX_3w",
#  "e" => "AQAB",
#  "d" => "imiCh2gK77pDAa_NuQbHN1hZdLY0eTl8tp4WLfe1uQ0",
#  "p" => "-eKE_wk7O5JWw_1fw-rciw",
#  "qi" => "MqCwIoTTCkYmGQHsOM7IuA",
#  "n" => "vj2WbxlGF1yU9SoQJMqKw6c2asTks_cVuXEAO3x_yOU",
#  "kty" => "RSA",
#  "q" => "wuVog_0-60w7_56y8wZuTw",
#  "dp" => "lU_9GEdz1UzD-6hSqMaVsQ"]
JOSE::JWK.to_public(jwk_rsa).to_map
# => JOSE::Map[
#  "e" => "AQAB",
#  "n" => "vj2WbxlGF1yU9SoQJMqKw6c2asTks_cVuXEAO3x_yOU",
#  "kty" => "RSA"]

Parameters:

Returns:


501
502
503
504
505
506
507
# File 'lib/jose/jwk.rb', line 501

def self.to_public(jwk)
  if jwk.is_a?(Array)
    return from(jwk).map { |obj| obj.to_public }
  else
    return from(jwk).to_public
  end
end

.to_public_file(jwk, file) ⇒ Fixnum

Calls JOSE::JWK.to_binary on a JOSE::JWK and then writes the binary to file.

Parameters:

Returns:

  • (Fixnum)

    bytes written


522
523
524
# File 'lib/jose/jwk.rb', line 522

def self.to_public_file(jwk, file)
  return from(jwk).to_public_file(file)
end

.to_public_key(jwk) ⇒ OpenSSL::PKey, ...

Parameters:

Returns:

  • (OpenSSL::PKey, Object, Array<OpenSSL::PKey, Object>)

538
539
540
541
542
543
544
# File 'lib/jose/jwk.rb', line 538

def self.to_public_key(jwk)
  if jwk.is_a?(Array)
    return from(jwk).map { |obj| obj.to_public_key }
  else
    return from(jwk).to_public_key
  end
end

.to_public_map(jwk) ⇒ JOSE::Map+

Parameters:

Returns:


557
558
559
560
561
562
563
# File 'lib/jose/jwk.rb', line 557

def self.to_public_map(jwk)
  if jwk.is_a?(Array)
    return from(jwk).map { |obj| obj.to_public_map }
  else
    return from(jwk).to_public_map
  end
end

.to_thumbprint_map(jwk) ⇒ JOSE::Map+

Converts a JOSE::JWK into a map that can be used by JOSE::JWK.thumbprint.

Parameters:

Returns:


576
577
578
579
580
581
582
# File 'lib/jose/jwk.rb', line 576

def self.to_thumbprint_map(jwk)
  if jwk.is_a?(Array)
    return from(jwk).map { |obj| obj.to_thumbprint_map }
  else
    return from(jwk).to_thumbprint_map
  end
end

.verifier(jwk) ⇒ Array<String>

Returns a verifier algorithm list for the key type.

Parameters:

Returns:

  • (Array<String>)

941
942
943
944
945
946
947
# File 'lib/jose/jwk.rb', line 941

def self.verifier(jwk)
  if jwk.is_a?(Array)
    return from(jwk).map { |obj| obj.verifier }
  else
    return from(jwk).verifier
  end
end

.verify(signed, jwk) ⇒ [Boolean, String, JOSE::JWS]

Verifies the signed using the jwk.

Parameters:

Returns:

See Also:


962
963
964
# File 'lib/jose/jwk.rb', line 962

def self.verify(signed, jwk)
  return from(jwk).verify(signed)
end

.verify_strict(signed, allow, jwk) ⇒ [Boolean, String, JOSE::JWS]

Verifies the signed using the jwk and whitelists the "alg" using allow.

Parameters:

Returns:

See Also:


982
983
984
# File 'lib/jose/jwk.rb', line 982

def self.verify_strict(signed, allow, jwk)
  return from(jwk).verify_strict(signed, allow)
end

Instance Method Details

#block_decrypt(encrypted) ⇒ [String, JOSE::JWE]

Decrypts the encrypted binary or map using the jwk.

Parameters:

Returns:

See Also:

  • JOWE::JWE.block_decrypt

608
609
610
# File 'lib/jose/jwk.rb', line 608

def block_decrypt(encrypted)
  return JOSE::JWE.block_decrypt(self, encrypted)
end

#block_encrypt(plain_text, jwe = nil) ⇒ JOSE::EncryptedMap

Encrypts the plain_text using the jwk and algorithms specified by the jwe.

Parameters:

  • plain_text (String)
  • jwe (JOSE::JWE) (defaults to: nil)

Returns:

See Also:


629
630
631
632
# File 'lib/jose/jwk.rb', line 629

def block_encrypt(plain_text, jwe = nil)
  jwe ||= block_encryptor
  return JOSE::JWE.block_encrypt(self, plain_text, jwe)
end

#block_encryptorJOSE::Map

Returns a block encryptor map for the key type.

Returns:


649
650
651
# File 'lib/jose/jwk.rb', line 649

def block_encryptor
  return kty.block_encryptor(fields)
end

#box_decrypt(encrypted, public_jwk = nil) ⇒ [String, JOSE::JWE]

Key Agreement decryption of the encrypted binary or map using my_private_jwk.

Parameters:

Returns:

See Also:


672
673
674
675
676
677
678
# File 'lib/jose/jwk.rb', line 672

def box_decrypt(encrypted, public_jwk = nil)
  if public_jwk
    return JOSE::JWE.block_decrypt([public_jwk, self], encrypted)
  else
    return JOSE::JWE.block_decrypt(self, encrypted)
  end
end

#box_encrypt(plain_text, my_private_jwk = nil, jwe = nil) ⇒ JOSE::EncryptedMap, [JOSE::EncryptedMap, JOSE::JWK]

Key Agreement encryption of plain_text by generating an ephemeral private key based on other_public_jwk curve.

If no private key has been specified in my_private_key, it generates an ephemeral private key based on other public key curve.

Parameters:

  • plain_text (String)
  • my_private_jwk (JOSE::JWK) (defaults to: nil)
  • jwe (JOSE::JWE) (defaults to: nil)

Returns:

See Also:


705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
# File 'lib/jose/jwk.rb', line 705

def box_encrypt(plain_text, my_private_jwk = nil, jwe = nil)
  generated_jwk = nil
  other_public_jwk = self
  if my_private_jwk.nil?
    generated_jwk = my_private_jwk = other_public_jwk.generate_key
  end
  if not my_private_jwk.is_a?(JOSE::JWK)
    my_private_jwk = JOSE::JWK.from(my_private_jwk)
  end
  if jwe.nil?
    jwe = other_public_jwk.block_encryptor
  end
  if jwe.is_a?(Hash)
    jwe = JOSE::Map.new(jwe)
  end
  if jwe.is_a?(JOSE::Map)
    if jwe['apu'].nil?
      jwe = jwe.put('apu', my_private_jwk.fields['kid'] || my_private_jwk.thumbprint)
    end
    if jwe['apv'].nil?
      jwe = jwe.put('apv', other_public_jwk.fields['kid'] || other_public_jwk.thumbprint)
    end
    if jwe['epk'].nil?
      jwe = jwe.put('epk', my_private_jwk.to_public_map)
    end
  end
  if generated_jwk
    return JOSE::JWE.block_encrypt([other_public_jwk, my_private_jwk], plain_text, jwe), generated_jwk
  else
    return JOSE::JWE.block_encrypt([other_public_jwk, my_private_jwk], plain_text, jwe)
  end
end

#derive_key(*args) ⇒ String

Derives a key (typically just returns a binary representation of the key).

Parameters:

  • args (*Object)

Returns:

  • (String)

742
743
744
# File 'lib/jose/jwk.rb', line 742

def derive_key(*args)
  return kty.derive_key(*args)
end

#generate_keyJOSE::JWK

Generates a new key based on the current one.

Returns:


805
806
807
# File 'lib/jose/jwk.rb', line 805

def generate_key
  return JOSE::JWK.new(nil, *kty.generate_key(fields))
end

#merge(object) ⇒ JOSE::JWK

Merges object into current map.

Parameters:

Returns:


820
821
822
823
824
825
826
827
828
829
830
831
832
# File 'lib/jose/jwk.rb', line 820

def merge(object)
  object = case object
  when JOSE::Map, Hash
    object
  when String
    JOSE.decode(object)
  when JOSE::JWK
    object.to_map
  else
    raise ArgumentError, "'object' must be a Hash, String, or JOSE::JWK"
  end
  return JOSE::JWK.from_map(self.to_map.merge(object))
end

#shared_secret(other_jwk) ⇒ String

Computes the shared secret between two keys.

Currently only works for "EC" keys and "OKP" keys with "crv" set to "X25519" or "X448".

Parameters:

Returns:

  • (String)

Raises:

  • (ArgumentError)

851
852
853
854
855
856
# File 'lib/jose/jwk.rb', line 851

def shared_secret(other_jwk)
  other_jwk = from(other_jwk) if not other_jwk.is_a?(JOSE::JWK)
  raise ArgumentError, "key types must match" if other_jwk.kty.class != kty.class
  raise ArgumentError, "key type does not support shared secret computations" if not kty.respond_to?(:derive_key)
  return kty.derive_key(other_jwk)
end

#sign(plain_text, jws = nil, header = nil) ⇒ JOSE::SignedMap

Signs the plain_text using the jwk and the default signer algorithm jws for the key type.

Parameters:

  • plain_text (String)
  • jws (JOSE::JWS) (defaults to: nil)
  • header (JOSE::Map) (defaults to: nil)

Returns:

See Also:


877
878
879
880
# File 'lib/jose/jwk.rb', line 877

def sign(plain_text, jws = nil, header = nil)
  jws ||= signer
  return JOSE::JWS.sign(self, plain_text, jws, header)
end

#signerJOSE::Map

Returns a signer map for the key type.

Returns:


893
894
895
# File 'lib/jose/jwk.rb', line 893

def signer
  return kty.signer(fields)
end

#thumbprint(digest_type = nil) ⇒ String

Returns the unique thumbprint for a JOSE::JWK using the digest_type.

Parameters:

  • digest_type (String) (defaults to: nil)

Returns:

  • (String)

See Also:


931
932
933
934
935
# File 'lib/jose/jwk.rb', line 931

def thumbprint(digest_type = nil)
  digest_type ||= 'SHA256'
  thumbprint_binary = JOSE.encode(to_thumbprint_map)
  return JOSE.urlsafe_encode64(OpenSSL::Digest.new(digest_type).digest(thumbprint_binary))
end

#to_binary(key = nil, jwe = nil) ⇒ String, JOSE::EncryptedBinary

Converts a JOSE::JWK into a binary.

Parameters:

  • key (String) (defaults to: nil)
  • jwe (JOSE::JWE) (defaults to: nil)

Returns:


271
272
273
274
275
276
277
278
279
280
# File 'lib/jose/jwk.rb', line 271

def to_binary(key = nil, jwe = nil)
  if not key.nil?
    jwe ||= kty.key_encryptor(fields, key)
  end
  if key and jwe
    return to_map(key, jwe).compact
  else
    return JOSE.encode(to_map)
  end
end

#to_file(file, key = nil, jwe = nil) ⇒ Fixnum

Calls JOSE::JWK.to_binary on a JOSE::JWK and then writes the binary to file.

Parameters:

  • file (String)
  • key (String) (defaults to: nil)
  • jwe (JOSE::JWE) (defaults to: nil)

Returns:

  • (Fixnum)

    bytes written


299
300
301
# File 'lib/jose/jwk.rb', line 299

def to_file(file, key = nil, jwe = nil)
  return File.binwrite(file, to_binary(key, jwe))
end

#to_keyOpenSSL::PKey, Object

Converts a JOSE::JWK into the raw key format.

Returns:

  • (OpenSSL::PKey, Object)

314
315
316
# File 'lib/jose/jwk.rb', line 314

def to_key
  return kty.to_key
end

#to_map(key = nil, jwe = nil) ⇒ JOSE::Map

Converts a JOSE::JWK into a map.

Parameters:

  • key (String) (defaults to: nil)
  • jwe (JOSE::JWE) (defaults to: nil)

Returns:


337
338
339
340
341
342
343
344
345
346
# File 'lib/jose/jwk.rb', line 337

def to_map(key = nil, jwe = nil)
  if not key.nil?
    jwe ||= kty.key_encryptor(fields, key)
  end
  if key and jwe
    return JOSE::JWE.block_encrypt(key, to_binary, jwe)
  else
    return kty.to_map(fields)
  end
end

#to_octString

Converts a JOSE::JWK into a raw binary octet.

Returns:

  • (String)

363
364
365
# File 'lib/jose/jwk.rb', line 363

def to_oct
  return kty.to_oct
end

#to_oct_file(file) ⇒ Fixnum

Calls JOSE::JWK#to_oct on a JOSE::JWK and then writes the binary to file.

Parameters:

  • file (String)

Returns:

  • (Fixnum)

    bytes written


380
381
382
# File 'lib/jose/jwk.rb', line 380

def to_oct_file(file)
  return File.binwrite(file, to_oct)
end

#to_okpString

Converts a JOSE::JWK into an octet key pair.

Returns:

  • (String)

399
400
401
# File 'lib/jose/jwk.rb', line 399

def to_okp
  return kty.to_okp
end

#to_openssh_keyObject

Converts a JOSE::JWK into an OpenSSH key binary.

Returns:

  • (Object)

418
419
420
# File 'lib/jose/jwk.rb', line 418

def to_openssh_key
  return kty.to_openssh_key(fields)
end

#to_openssh_key_file(file) ⇒ Fixnum

Calls JOSE::JWK#to_openssh_key on a JOSE::JWK and then writes the binary to file.

Parameters:

  • file (String)

Returns:

  • (Fixnum)

    bytes written


435
436
437
# File 'lib/jose/jwk.rb', line 435

def to_openssh_key_file(file)
  return File.binwrite(file, to_openssh_key)
end

#to_pem(password = nil) ⇒ String

Converts a JOSE::JWK into a PEM (Privacy Enhanced Email) binary.

Parameters:

  • password (String) (defaults to: nil)

Returns:

  • (String)

456
457
458
# File 'lib/jose/jwk.rb', line 456

def to_pem(password = nil)
  return kty.to_pem(password)
end

#to_pem_file(file, password = nil) ⇒ Fixnum

Calls JOSE::JWK#to_pem on a JOSE::JWK and then writes the binary to file.

Parameters:

  • file (String)
  • password (String) (defaults to: nil)

Returns:

  • (Fixnum)

    bytes written


475
476
477
# File 'lib/jose/jwk.rb', line 475

def to_pem_file(file, password = nil)
  return File.binwrite(file, to_pem(password))
end

#to_publicJOSE::JWK

Converts a private JOSE::JWK into a public JOSE::JWK.

Returns:

See Also:


513
514
515
# File 'lib/jose/jwk.rb', line 513

def to_public
  return JOSE::JWK.from_map(to_public_map)
end

#to_public_file(file) ⇒ Fixnum

Calls JOSE::JWK.to_public on a JOSE::JWK and then writes the binary to file.

Parameters:

  • file (String)

Returns:

  • (Fixnum)

    bytes written


530
531
532
# File 'lib/jose/jwk.rb', line 530

def to_public_file(file)
  return File.binwrite(file, to_public.to_binary)
end

#to_public_keyOpenSSL::PKey, Object

Returns:

  • (OpenSSL::PKey, Object)

549
550
551
# File 'lib/jose/jwk.rb', line 549

def to_public_key
  return to_public.to_key
end

#to_public_mapJOSE::Map

Returns:


568
569
570
# File 'lib/jose/jwk.rb', line 568

def to_public_map
  return kty.to_public_map(fields)
end

#to_thumbprint_mapJOSE::Map

Converts a JOSE::JWK into a map that can be used by JOSE::JWK.thumbprint.

Returns:


587
588
589
# File 'lib/jose/jwk.rb', line 587

def to_thumbprint_map
  return kty.to_thumbprint_map(fields)
end

#verifierArray<String>

Returns a verifier algorithm list for the key type.

Returns:

  • (Array<String>)

952
953
954
# File 'lib/jose/jwk.rb', line 952

def verifier
  return kty.verifier(fields)
end

#verify(signed) ⇒ [Boolean, String, JOSE::JWS]

Verifies the signed using the jwk.

Parameters:

Returns:

See Also:


971
972
973
# File 'lib/jose/jwk.rb', line 971

def verify(signed)
  return JOSE::JWS.verify(self, signed)
end

#verify_strict(signed, allow) ⇒ [Boolean, String, JOSE::JWS]

Verifies the signed using the jwk and whitelists the "alg" using allow.

Parameters:

Returns:

See Also:


992
993
994
# File 'lib/jose/jwk.rb', line 992

def verify_strict(signed, allow)
  return JOSE::JWS.verify_strict(self, allow, signed)
end