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, PKeyProxy, 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


601
602
603
604
605
606
607
608
609
610
611
612
# File 'lib/jose/jwk.rb', line 601

def self.block_decrypt(jwk, encrypted)
  if jwk.is_a?(Array)
    public_jwk, secret_jwk = from(jwk)
    if secret_jwk.nil?
      secret_jwk = public_jwk
      public_jwk = nil
    end
    return box_decrypt(secret_jwk, encrypted, public_jwk)
  else
    return from(jwk).block_decrypt(encrypted)
  end
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:



630
631
632
633
634
635
636
# File 'lib/jose/jwk.rb', line 630

def self.block_encrypt(jwk, plain_text, jwe = nil)
  if jwk.is_a?(Array)
    return box_encrypt(plain_text, from(jwk), jwe)
  else
    return from(jwk).block_encrypt(plain_text, jwe)
  end
end

.block_encryptor(jwk) ⇒ JOSE::Map+

Returns a block encryptor map for the key type.

Parameters:

Returns:



653
654
655
656
657
658
659
# File 'lib/jose/jwk.rb', line 653

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:



676
677
678
# File 'lib/jose/jwk.rb', line 676

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:



705
706
707
708
# File 'lib/jose/jwk.rb', line 705

def self.box_encrypt(plain_text, box_keys, jwe = nil)
  jwk_public, jwk_secret = from(box_keys)
  return jwk_public.box_encrypt(plain_text, jwk_secret, jwe)
end

.derive_key(jwk, *args) ⇒ String

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

Parameters:

Returns:

  • (String)


758
759
760
# File 'lib/jose/jwk.rb', line 758

def self.derive_key(jwk, *args)
  return from(jwk).derive_key(*args)
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:



788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
# File 'lib/jose/jwk.rb', line 788

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:



837
838
839
# File 'lib/jose/jwk.rb', line 837

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)


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

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

.sign(plain_text, jws, jwk = 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:



890
891
892
893
894
895
896
# File 'lib/jose/jwk.rb', line 890

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

.signer(jwk) ⇒ JOSE::Map

Returns a signer map for the key type.

Parameters:

Returns:



914
915
916
# File 'lib/jose/jwk.rb', line 914

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:



945
946
947
948
949
950
951
# File 'lib/jose/jwk.rb', line 945

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>)


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

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



374
375
376
# File 'lib/jose/jwk.rb', line 374

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

.to_okp(jwk) ⇒ Object+

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

Parameters:

Returns:

  • (Object, Array<Object>)


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

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>)


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

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



429
430
431
# File 'lib/jose/jwk.rb', line 429

def self.to_openssh_key_file(jwk, file)
  return from(jwk).to_openssh_key_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>)


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

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



468
469
470
# File 'lib/jose/jwk.rb', line 468

def self.to_pem_file(jwk, file, password = nil)
  return from(jwk).to_pem_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, 1024]).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:



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

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



524
525
526
# File 'lib/jose/jwk.rb', line 524

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>)


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

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:



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

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:



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

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>)


969
970
971
972
973
974
975
# File 'lib/jose/jwk.rb', line 969

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:



990
991
992
# File 'lib/jose/jwk.rb', line 990

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:



1010
1011
1012
# File 'lib/jose/jwk.rb', line 1010

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


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

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:



644
645
646
647
# File 'lib/jose/jwk.rb', line 644

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:



664
665
666
# File 'lib/jose/jwk.rb', line 664

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:



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

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, jwk_secret = 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)
  • jwk_secret (JOSE::JWK) (defaults to: nil)
  • jwe (JOSE::JWE) (defaults to: nil)

Returns:

See Also:



720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
# File 'lib/jose/jwk.rb', line 720

def box_encrypt(plain_text, jwk_secret = nil, jwe = nil)
  epk_secret = nil
  jwk_public = self
  if jwk_secret.nil?
    epk_secret = jwk_secret = jwk_public.generate_key
  end
  if not jwk_secret.is_a?(JOSE::JWK)
    jwk_secret = JOSE::JWK.from(jwk_secret)
  end
  if jwe.nil?
    jwe = jwk_public.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', jwk_secret.fields['kid'] || jwk_secret.thumbprint)
    end
    if jwe['apv'].nil?
      jwe = jwe.put('apv', jwk_public.fields['kid'] || jwk_public.thumbprint)
    end
    if jwe['epk'].nil?
      jwe = jwe.put('epk', jwk_secret.to_public_map)
    end
  end
  if epk_secret
    return JOSE::JWE.block_encrypt([jwk_public, jwk_secret], plain_text, jwe), epk_secret
  else
    return JOSE::JWE.block_encrypt([jwk_public, jwk_secret], 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)


766
767
768
# File 'lib/jose/jwk.rb', line 766

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

#generate_keyJOSE::JWK

Generates a new key based on the current one.

Returns:



829
830
831
# File 'lib/jose/jwk.rb', line 829

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

#merge(object) ⇒ JOSE::JWK

Merges object into current map.

Parameters:

Returns:



844
845
846
847
848
849
850
851
852
853
854
855
856
# File 'lib/jose/jwk.rb', line 844

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)


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

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:



905
906
907
908
# File 'lib/jose/jwk.rb', line 905

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:



921
922
923
# File 'lib/jose/jwk.rb', line 921

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:



959
960
961
962
963
# File 'lib/jose/jwk.rb', line 959

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
347
348
# 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)
  elsif kty.nil? and keys
    return keys.to_map(fields)
  else
    return kty.to_map(fields)
  end
end

#to_octString

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

Returns:

  • (String)


365
366
367
# File 'lib/jose/jwk.rb', line 365

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



382
383
384
# File 'lib/jose/jwk.rb', line 382

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)


401
402
403
# File 'lib/jose/jwk.rb', line 401

def to_okp
  return kty.to_okp
end

#to_openssh_keyObject

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

Returns:

  • (Object)


420
421
422
# File 'lib/jose/jwk.rb', line 420

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



437
438
439
# File 'lib/jose/jwk.rb', line 437

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)


458
459
460
# File 'lib/jose/jwk.rb', line 458

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



477
478
479
# File 'lib/jose/jwk.rb', line 477

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:



515
516
517
# File 'lib/jose/jwk.rb', line 515

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



532
533
534
# File 'lib/jose/jwk.rb', line 532

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

#to_public_keyOpenSSL::PKey, Object

Returns:

  • (OpenSSL::PKey, Object)


551
552
553
# File 'lib/jose/jwk.rb', line 551

def to_public_key
  return to_public.to_key
end

#to_public_mapJOSE::Map

Returns:



570
571
572
# File 'lib/jose/jwk.rb', line 570

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:



589
590
591
# File 'lib/jose/jwk.rb', line 589

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>)


980
981
982
# File 'lib/jose/jwk.rb', line 980

def verifier
  return kty.verifier(fields)
end

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

Verifies the signed using the jwk.

Parameters:

Returns:

See Also:



999
1000
1001
# File 'lib/jose/jwk.rb', line 999

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:



1020
1021
1022
# File 'lib/jose/jwk.rb', line 1020

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