jose 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|