jose 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.editorconfig +20 -0
- data/.gitignore +9 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +4 -0
- data/CODE_OF_CONDUCT.md +13 -0
- data/Gemfile +20 -0
- data/LICENSE.txt +373 -0
- data/README.md +41 -0
- data/Rakefile +10 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/jose.gemspec +36 -0
- data/lib/jose.rb +61 -0
- data/lib/jose/jwa.rb +21 -0
- data/lib/jose/jwa/aes_kw.rb +105 -0
- data/lib/jose/jwa/concat_kdf.rb +50 -0
- data/lib/jose/jwa/pkcs1.rb +269 -0
- data/lib/jose/jwa/pkcs7.rb +23 -0
- data/lib/jose/jwe.rb +290 -0
- data/lib/jose/jwe/alg.rb +12 -0
- data/lib/jose/jwe/alg_aes_gcm_kw.rb +98 -0
- data/lib/jose/jwe/alg_aes_kw.rb +57 -0
- data/lib/jose/jwe/alg_dir.rb +40 -0
- data/lib/jose/jwe/alg_ecdh_es.rb +123 -0
- data/lib/jose/jwe/alg_pbes2.rb +90 -0
- data/lib/jose/jwe/alg_rsa.rb +63 -0
- data/lib/jose/jwe/enc.rb +8 -0
- data/lib/jose/jwe/enc_aes_cbc_hmac.rb +80 -0
- data/lib/jose/jwe/enc_aes_gcm.rb +68 -0
- data/lib/jose/jwe/zip.rb +7 -0
- data/lib/jose/jwe/zip_def.rb +28 -0
- data/lib/jose/jwk.rb +347 -0
- data/lib/jose/jwk/kty.rb +34 -0
- data/lib/jose/jwk/kty_ec.rb +179 -0
- data/lib/jose/jwk/kty_oct.rb +104 -0
- data/lib/jose/jwk/kty_rsa.rb +185 -0
- data/lib/jose/jwk/pem.rb +19 -0
- data/lib/jose/jwk/set.rb +2 -0
- data/lib/jose/jws.rb +242 -0
- data/lib/jose/jws/alg.rb +10 -0
- data/lib/jose/jws/alg_ecdsa.rb +41 -0
- data/lib/jose/jws/alg_hmac.rb +41 -0
- data/lib/jose/jws/alg_rsa_pkcs1_v1_5.rb +41 -0
- data/lib/jose/jws/alg_rsa_pss.rb +41 -0
- data/lib/jose/jwt.rb +145 -0
- data/lib/jose/version.rb +3 -0
- metadata +162 -0
@@ -0,0 +1,23 @@
|
|
1
|
+
module JOSE::JWA::PKCS7
|
2
|
+
|
3
|
+
extend self
|
4
|
+
|
5
|
+
def pad(binary)
|
6
|
+
size = 16 - (binary.bytesize % 16)
|
7
|
+
return [binary, *([size] * size)].pack('a*C*')
|
8
|
+
end
|
9
|
+
|
10
|
+
def unpad(binary)
|
11
|
+
p = binary.getbyte(-1)
|
12
|
+
size = binary.bytesize - p
|
13
|
+
binary_s = StringIO.new(binary)
|
14
|
+
result = binary_s.read(size)
|
15
|
+
p.times do
|
16
|
+
if binary_s.getbyte != p
|
17
|
+
raise ArgumentError, "unrecognized padding"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
return result
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
data/lib/jose/jwe.rb
ADDED
@@ -0,0 +1,290 @@
|
|
1
|
+
module JOSE
|
2
|
+
|
3
|
+
class EncryptedBinary < ::String
|
4
|
+
def expand
|
5
|
+
return JOSE::JWE.expand(self)
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
class EncryptedMap < JOSE::Map
|
10
|
+
def compact
|
11
|
+
return JOSE::JWE.compact(self)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class JWE < Struct.new(:alg, :enc, :zip, :fields)
|
16
|
+
|
17
|
+
# Decode API
|
18
|
+
|
19
|
+
def self.from(object, modules = {})
|
20
|
+
case object
|
21
|
+
when JOSE::Map, Hash
|
22
|
+
return from_map(object, modules)
|
23
|
+
when String
|
24
|
+
return from_binary(object, modules)
|
25
|
+
when JOSE::JWE
|
26
|
+
return object
|
27
|
+
else
|
28
|
+
raise ArgumentError, "'object' must be a Hash, String, or JOSE::JWE"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.from_binary(object, modules = {})
|
33
|
+
case object
|
34
|
+
when String
|
35
|
+
return from_map(JOSE.decode(object), modules)
|
36
|
+
else
|
37
|
+
raise ArgumentError, "'object' must be a String"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.from_file(file, modules = {})
|
42
|
+
return from_binary(File.binread(file), modules)
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.from_map(object, modules = {})
|
46
|
+
case object
|
47
|
+
when JOSE::Map, Hash
|
48
|
+
return from_fields(JOSE::JWE.new(nil, nil, nil, JOSE::Map.new(object)), modules)
|
49
|
+
else
|
50
|
+
raise ArgumentError, "'object' must be a Hash"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Encode API
|
55
|
+
|
56
|
+
def self.to_binary(jwe)
|
57
|
+
return from(jwe).to_binary
|
58
|
+
end
|
59
|
+
|
60
|
+
def to_binary
|
61
|
+
return JOSE.encode(to_map)
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.to_file(jwe, file)
|
65
|
+
return from(jwe).to_file(file)
|
66
|
+
end
|
67
|
+
|
68
|
+
def to_file(file)
|
69
|
+
return File.binwrite(file, to_binary)
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.to_map(jwe)
|
73
|
+
return from(jwe).to_map
|
74
|
+
end
|
75
|
+
|
76
|
+
def to_map
|
77
|
+
if zip.nil?
|
78
|
+
return alg.to_map(enc.to_map(fields))
|
79
|
+
else
|
80
|
+
return alg.to_map(enc.to_map(zip.to_map(fields)))
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# API
|
85
|
+
|
86
|
+
def self.block_decrypt(key, encrypted)
|
87
|
+
if encrypted.is_a?(String)
|
88
|
+
encrypted = JOSE::JWE.expand(encrypted)
|
89
|
+
end
|
90
|
+
if encrypted.is_a?(Hash)
|
91
|
+
encrypted = JOSE::EncryptedMap.new(encrypted)
|
92
|
+
end
|
93
|
+
if encrypted.is_a?(JOSE::Map) and encrypted['ciphertext'].is_a?(String) and encrypted['encrypted_key'].is_a?(String) and encrypted['iv'].is_a?(String) and encrypted['protected'].is_a?(String) and encrypted['tag'].is_a?(String)
|
94
|
+
jwe = from_binary(JOSE.urlsafe_decode64(encrypted['protected']))
|
95
|
+
encrypted_key = JOSE.urlsafe_decode64(encrypted['encrypted_key'])
|
96
|
+
iv = JOSE.urlsafe_decode64(encrypted['iv'])
|
97
|
+
cipher_text = JOSE.urlsafe_decode64(encrypted['ciphertext'])
|
98
|
+
cipher_tag = JOSE.urlsafe_decode64(encrypted['tag'])
|
99
|
+
if encrypted['aad'].is_a?(String)
|
100
|
+
concat_aad = [encrypted['protected'], '.', encrypted['aad']].join
|
101
|
+
return jwe.block_decrypt(key, concat_aad, cipher_text, cipher_tag, encrypted_key, iv), jwe
|
102
|
+
else
|
103
|
+
return jwe.block_decrypt(key, encrypted['protected'], cipher_text, cipher_tag, encrypted_key, iv), jwe
|
104
|
+
end
|
105
|
+
else
|
106
|
+
raise ArgumentError, "'encrypted' is not a valid encrypted String, Hash, or JOSE::Map"
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def block_decrypt(key, aad, cipher_text, cipher_tag, encrypted_key, iv)
|
111
|
+
cek = key_decrypt(key, encrypted_key)
|
112
|
+
return uncompress(enc.block_decrypt([aad, cipher_text, cipher_tag], cek, iv))
|
113
|
+
end
|
114
|
+
|
115
|
+
def self.block_encrypt(key, block, jwe, cek = nil, iv = nil)
|
116
|
+
return from(jwe).block_encrypt(key, block, cek, iv)
|
117
|
+
end
|
118
|
+
|
119
|
+
def block_encrypt(key, block, cek = nil, iv = nil)
|
120
|
+
cek ||= next_cek(key)
|
121
|
+
iv ||= next_iv
|
122
|
+
aad, plain_text = block
|
123
|
+
if plain_text.nil?
|
124
|
+
plain_text = aad
|
125
|
+
aad = nil
|
126
|
+
end
|
127
|
+
encrypted_key, jwe = key_encrypt(key, cek)
|
128
|
+
protected_binary = JOSE.urlsafe_encode64(jwe.to_binary)
|
129
|
+
if aad.nil?
|
130
|
+
cipher_text, cipher_tag = enc.block_encrypt([protected_binary, jwe.compress(plain_text)], cek, iv)
|
131
|
+
return JOSE::EncryptedMap[
|
132
|
+
'ciphertext' => JOSE.urlsafe_encode64(cipher_text),
|
133
|
+
'encrypted_key' => JOSE.urlsafe_encode64(encrypted_key),
|
134
|
+
'iv' => JOSE.urlsafe_encode64(iv),
|
135
|
+
'protected' => protected_binary,
|
136
|
+
'tag' => JOSE.urlsafe_encode64(cipher_tag)
|
137
|
+
]
|
138
|
+
else
|
139
|
+
aad_b64 = JOSE.urlsafe_encode64(aad)
|
140
|
+
concat_aad = [protected_binary, '.', aad_b64].join
|
141
|
+
cipher_text, cipher_tag = enc.block_encrypt([aad_b64, jwe.compress(plain_text)], cek, iv)
|
142
|
+
return JOSE::EncryptedMap[
|
143
|
+
'aad' => aad_b64,
|
144
|
+
'ciphertext' => JOSE.urlsafe_encode64(cipher_text),
|
145
|
+
'encrypted_key' => JOSE.urlsafe_encode64(encrypted_key),
|
146
|
+
'iv' => JOSE.urlsafe_encode64(iv),
|
147
|
+
'protected' => protected_binary,
|
148
|
+
'tag' => JOSE.urlsafe_encode64(cipher_tag)
|
149
|
+
]
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def self.compact(map)
|
154
|
+
if map.is_a?(Hash) or map.is_a?(JOSE::Map)
|
155
|
+
if map.has_key?('aad')
|
156
|
+
raise ArgumentError, "'map' with 'aad' cannot be compacted"
|
157
|
+
end
|
158
|
+
return JOSE::EncryptedBinary.new([
|
159
|
+
map['protected'] || '',
|
160
|
+
'.',
|
161
|
+
map['encrypted_key'] || '',
|
162
|
+
'.',
|
163
|
+
map['iv'] || '',
|
164
|
+
'.',
|
165
|
+
map['ciphertext'] || '',
|
166
|
+
'.',
|
167
|
+
map['tag'] || ''
|
168
|
+
].join)
|
169
|
+
else
|
170
|
+
raise ArgumentError, "'map' must be a Hash or a JOSE::Map"
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
def compress(plain_text)
|
175
|
+
if zip.nil?
|
176
|
+
return plain_text
|
177
|
+
else
|
178
|
+
return zip.compress(plain_text)
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
def self.expand(binary)
|
183
|
+
if binary.is_a?(String)
|
184
|
+
parts = binary.split('.')
|
185
|
+
if parts.length == 5
|
186
|
+
protected_binary, encrypted_key, initialization_vector, cipher_text, authentication_tag = parts
|
187
|
+
return JOSE::EncryptedMap[
|
188
|
+
'ciphertext' => cipher_text,
|
189
|
+
'encrypted_key' => encrypted_key,
|
190
|
+
'iv' => initialization_vector,
|
191
|
+
'protected' => protected_binary,
|
192
|
+
'tag' => authentication_tag
|
193
|
+
]
|
194
|
+
else
|
195
|
+
raise ArgumentError, "'binary' is not a valid encrypted String"
|
196
|
+
end
|
197
|
+
else
|
198
|
+
raise ArgumentError, "'binary' must be a String"
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
def key_decrypt(key, encrypted_key)
|
203
|
+
return alg.key_decrypt(key, enc, encrypted_key)
|
204
|
+
end
|
205
|
+
|
206
|
+
def key_encrypt(key, decrypted_key)
|
207
|
+
encrypted_key, new_alg = alg.key_encrypt(key, enc, decrypted_key)
|
208
|
+
new_jwe = JOSE::JWE.from_map(to_map)
|
209
|
+
new_jwe.alg = new_alg
|
210
|
+
return encrypted_key, new_jwe
|
211
|
+
end
|
212
|
+
|
213
|
+
def next_cek(key)
|
214
|
+
return alg.next_cek(key, enc)
|
215
|
+
end
|
216
|
+
|
217
|
+
def next_iv
|
218
|
+
return enc.next_iv
|
219
|
+
end
|
220
|
+
|
221
|
+
def self.peek_protected(encrypted)
|
222
|
+
if encrypted.is_a?(String)
|
223
|
+
encrypted = expand(encrypted)
|
224
|
+
end
|
225
|
+
return JOSE::Map.new(JOSE.decode(JOSE.urlsafe_decode64(encrypted['protected'])))
|
226
|
+
end
|
227
|
+
|
228
|
+
def uncompress(cipher_text)
|
229
|
+
if zip.nil?
|
230
|
+
return cipher_text
|
231
|
+
else
|
232
|
+
return zip.uncompress(cipher_text)
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
private
|
237
|
+
|
238
|
+
def self.from_fields(jwe, modules)
|
239
|
+
if jwe.fields.has_key?('alg')
|
240
|
+
alg = modules[:alg] || case jwe.fields['alg']
|
241
|
+
when 'A128KW', 'A192KW', 'A256KW'
|
242
|
+
JOSE::JWE::ALG_AES_KW
|
243
|
+
when 'A128GCMKW', 'A192GCMKW', 'A256GCMKW'
|
244
|
+
JOSE::JWE::ALG_AES_GCM_KW
|
245
|
+
when 'dir'
|
246
|
+
JOSE::JWE::ALG_dir
|
247
|
+
when 'ECDH-ES', 'ECDH-ES+A128KW', 'ECDH-ES+A192KW', 'ECDH-ES+A256KW'
|
248
|
+
JOSE::JWE::ALG_ECDH_ES
|
249
|
+
when 'PBES2-HS256+A128KW', 'PBES2-HS384+A192KW', 'PBES2-HS512+A256KW'
|
250
|
+
JOSE::JWE::ALG_PBES2
|
251
|
+
when 'RSA1_5', 'RSA-OAEP', 'RSA-OAEP-256'
|
252
|
+
JOSE::JWE::ALG_RSA
|
253
|
+
else
|
254
|
+
raise ArgumentError, "unknown 'alg': #{jwe.fields['alg'].inspect}"
|
255
|
+
end
|
256
|
+
jwe.alg, jwe.fields = alg.from_map(jwe.fields)
|
257
|
+
return from_fields(jwe, modules)
|
258
|
+
elsif jwe.fields.has_key?('enc')
|
259
|
+
enc = modules[:enc] || case jwe.fields['enc']
|
260
|
+
when 'A128CBC-HS256', 'A192CBC-HS384', 'A256CBC-HS512'
|
261
|
+
JOSE::JWE::ENC_AES_CBC_HMAC
|
262
|
+
when 'A128GCM', 'A192GCM', 'A256GCM'
|
263
|
+
JOSE::JWE::ENC_AES_GCM
|
264
|
+
else
|
265
|
+
raise ArgumentError, "unknown 'enc': #{jwe.fields['enc'].inspect}"
|
266
|
+
end
|
267
|
+
jwe.enc, jwe.fields = enc.from_map(jwe.fields)
|
268
|
+
return from_fields(jwe, modules)
|
269
|
+
elsif jwe.fields.has_key?('zip')
|
270
|
+
zip = modules[:zip] || case jwe.fields['zip']
|
271
|
+
when 'DEF'
|
272
|
+
JOSE::JWE::ZIP_DEF
|
273
|
+
else
|
274
|
+
raise ArgumentError, "unknown 'zip': #{jwe.fields['zip'].inspect}"
|
275
|
+
end
|
276
|
+
jwe.zip, jwe.fields = zip.from_map(jwe.fields)
|
277
|
+
return from_fields(jwe, modules)
|
278
|
+
elsif jwe.alg.nil? and jwe.enc.nil?
|
279
|
+
raise ArgumentError, "missing required keys: 'alg' and 'enc'"
|
280
|
+
else
|
281
|
+
return jwe
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
require 'jose/jwe/alg'
|
289
|
+
require 'jose/jwe/enc'
|
290
|
+
require 'jose/jwe/zip'
|
data/lib/jose/jwe/alg.rb
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
class JOSE::JWE::ALG_AES_GCM_KW < Struct.new(:cipher_name, :bits, :iv, :tag)
|
2
|
+
|
3
|
+
# JOSE::JWE callbacks
|
4
|
+
|
5
|
+
def self.from_map(fields)
|
6
|
+
bits = nil
|
7
|
+
cipher_name = nil
|
8
|
+
case fields['alg']
|
9
|
+
when 'A128GCMKW'
|
10
|
+
bits = 128
|
11
|
+
cipher_name = 'aes-128-gcm'
|
12
|
+
when 'A192GCMKW'
|
13
|
+
bits = 192
|
14
|
+
cipher_name = 'aes-192-gcm'
|
15
|
+
when 'A256GCMKW'
|
16
|
+
bits = 256
|
17
|
+
cipher_name = 'aes-256-gcm'
|
18
|
+
else
|
19
|
+
raise ArgumentError, "invalid 'alg' for JWE: #{fields['alg'].inspect}"
|
20
|
+
end
|
21
|
+
iv = nil
|
22
|
+
if fields.has_key?('iv')
|
23
|
+
iv = JOSE.urlsafe_decode64(fields['iv'])
|
24
|
+
end
|
25
|
+
tag = nil
|
26
|
+
if fields.has_key?('tag')
|
27
|
+
tag = JOSE.urlsafe_decode64(fields['tag'])
|
28
|
+
end
|
29
|
+
return new(cipher_name, bits, iv, tag), fields.except('alg', 'iv', 'tag')
|
30
|
+
end
|
31
|
+
|
32
|
+
def to_map(fields)
|
33
|
+
alg = case bits
|
34
|
+
when 128
|
35
|
+
'A128GCMKW'
|
36
|
+
when 192
|
37
|
+
'A192GCMKW'
|
38
|
+
when 256
|
39
|
+
'A256GCMKW'
|
40
|
+
else
|
41
|
+
raise ArgumentError, "unhandled JOSE::JWE::ALG_AES_KW bits: #{bits.inspect}"
|
42
|
+
end
|
43
|
+
fields = fields.put('alg', alg)
|
44
|
+
if iv
|
45
|
+
fields = fields.put('iv', JOSE.urlsafe_encode64(iv))
|
46
|
+
end
|
47
|
+
if tag
|
48
|
+
fields = fields.put('tag', JOSE.urlsafe_encode64(tag))
|
49
|
+
end
|
50
|
+
return fields
|
51
|
+
end
|
52
|
+
|
53
|
+
# JOSE::JWE::ALG callbacks
|
54
|
+
|
55
|
+
def key_decrypt(key, enc, encrypted_key)
|
56
|
+
if iv.nil? or tag.nil?
|
57
|
+
raise ArgumentError, "missing required fields for decryption: 'iv' and 'tag'"
|
58
|
+
end
|
59
|
+
if key.is_a?(JOSE::JWK)
|
60
|
+
key = key.kty.derive_key
|
61
|
+
end
|
62
|
+
derived_key = key
|
63
|
+
aad = ''
|
64
|
+
cipher_text = encrypted_key
|
65
|
+
cipher_tag = tag
|
66
|
+
cipher = OpenSSL::Cipher.new(cipher_name)
|
67
|
+
cipher.decrypt
|
68
|
+
cipher.key = derived_key
|
69
|
+
cipher.iv = iv
|
70
|
+
cipher.auth_data = aad
|
71
|
+
cipher.auth_tag = cipher_tag
|
72
|
+
plain_text = cipher.update(cipher_text) + cipher.final
|
73
|
+
return plain_text
|
74
|
+
end
|
75
|
+
|
76
|
+
def key_encrypt(key, enc, decrypted_key)
|
77
|
+
if key.is_a?(JOSE::JWK)
|
78
|
+
key = key.kty.derive_key
|
79
|
+
end
|
80
|
+
new_alg = JOSE::JWE::ALG_AES_GCM_KW.new(cipher_name, bits, iv || SecureRandom.random_bytes(12))
|
81
|
+
derived_key = key
|
82
|
+
aad = ''
|
83
|
+
plain_text = decrypted_key
|
84
|
+
cipher = OpenSSL::Cipher.new(new_alg.cipher_name)
|
85
|
+
cipher.encrypt
|
86
|
+
cipher.key = derived_key
|
87
|
+
cipher.iv = new_alg.iv
|
88
|
+
cipher.auth_data = aad
|
89
|
+
cipher_text = cipher.update(plain_text) + cipher.final
|
90
|
+
new_alg.tag = cipher.auth_tag
|
91
|
+
return cipher_text, new_alg
|
92
|
+
end
|
93
|
+
|
94
|
+
def next_cek(key, enc)
|
95
|
+
return enc.next_cek
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
class JOSE::JWE::ALG_AES_KW < Struct.new(:bits)
|
2
|
+
|
3
|
+
# JOSE::JWE callbacks
|
4
|
+
|
5
|
+
def self.from_map(fields)
|
6
|
+
bits = case fields['alg']
|
7
|
+
when 'A128KW'
|
8
|
+
128
|
9
|
+
when 'A192KW'
|
10
|
+
192
|
11
|
+
when 'A256KW'
|
12
|
+
256
|
13
|
+
else
|
14
|
+
raise ArgumentError, "invalid 'alg' for JWE: #{fields['alg'].inspect}"
|
15
|
+
end
|
16
|
+
return new(bits), fields.except('alg')
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_map(fields)
|
20
|
+
alg = case bits
|
21
|
+
when 128
|
22
|
+
'A128KW'
|
23
|
+
when 192
|
24
|
+
'A192KW'
|
25
|
+
when 256
|
26
|
+
'A256KW'
|
27
|
+
else
|
28
|
+
raise ArgumentError, "unhandled JOSE::JWE::ALG_AES_KW bits: #{bits.inspect}"
|
29
|
+
end
|
30
|
+
return fields.put('alg', alg)
|
31
|
+
end
|
32
|
+
|
33
|
+
# JOSE::JWE::ALG callbacks
|
34
|
+
|
35
|
+
def key_decrypt(key, enc, encrypted_key)
|
36
|
+
if key.is_a?(JOSE::JWK)
|
37
|
+
key = key.kty.derive_key
|
38
|
+
end
|
39
|
+
derived_key = key
|
40
|
+
decrypted_key = JOSE::JWA::AES_KW.unwrap(encrypted_key, derived_key)
|
41
|
+
return decrypted_key
|
42
|
+
end
|
43
|
+
|
44
|
+
def key_encrypt(key, enc, decrypted_key)
|
45
|
+
if key.is_a?(JOSE::JWK)
|
46
|
+
key = key.kty.derive_key
|
47
|
+
end
|
48
|
+
derived_key = key
|
49
|
+
encrypted_key = JOSE::JWA::AES_KW.wrap(decrypted_key, derived_key)
|
50
|
+
return encrypted_key, self
|
51
|
+
end
|
52
|
+
|
53
|
+
def next_cek(key, enc)
|
54
|
+
return enc.next_cek
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|