Module: JWE

Defined in:
lib/rodauth/oauth/jwe_extensions.rb

Class Method Summary collapse

Class Method Details

.__rodauth_oauth_decrypt_from_jwks(payload, jwks, alg: "RSA-OAEP", enc: "A128GCM") ⇒ Object

this is a monkey-patch! it’s necessary, as the original jwe does not support jwks. if this works long term, it may be merged upstreamm.



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# File 'lib/rodauth/oauth/jwe_extensions.rb', line 9

def self.__rodauth_oauth_decrypt_from_jwks(payload, jwks, alg: "RSA-OAEP", enc: "A128GCM")
  header, enc_key, iv, ciphertext, tag = Serialization::Compact.decode(payload)
  header = JSON.parse(header)

  key = find_key_by_kid(jwks, header["kid"], alg, enc)

  check_params(header, key)

  cek = Alg.decrypt_cek(header["alg"], key, enc_key)
  cipher = Enc.for(header["enc"], cek, iv, tag)

  plaintext = cipher.decrypt(ciphertext, payload.split(".").first)

  apply_zip(header, plaintext, :decompress)
end

.__rodauth_oauth_encrypt_from_jwks(payload, jwks, alg: "RSA-OAEP", enc: "A128GCM", **more_headers) ⇒ Object



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/rodauth/oauth/jwe_extensions.rb', line 25

def self.__rodauth_oauth_encrypt_from_jwks(payload, jwks, alg: "RSA-OAEP", enc: "A128GCM", **more_headers)
  header = generate_header(alg, enc, more_headers)

  key = find_key_by_alg_enc(jwks, alg, enc)

  check_params(header, key)
  payload = apply_zip(header, payload, :compress)

  cipher = Enc.for(enc)
  cipher.cek = key if alg == "dir"

  json_hdr = header.to_json
  ciphertext = cipher.encrypt(payload, Base64.jwe_encode(json_hdr))

  generate_serialization(json_hdr, Alg.encrypt_cek(alg, key, cipher.cek), ciphertext, cipher)
end

.find_key_by_alg_enc(jwks, alg, enc) ⇒ Object

Raises:

  • (DecodeError)


54
55
56
57
58
59
60
61
62
63
# File 'lib/rodauth/oauth/jwe_extensions.rb', line 54

def self.find_key_by_alg_enc(jwks, alg, enc)
  jwk = jwks.find do |key, _|
    (key[:alg] || key["alg"]) == alg &&
      (key[:enc] || key["enc"]) == enc
  end

  raise DecodeError, "No key found" unless jwk

  ::JWT::JWK.import(jwk).keypair
end

.find_key_by_kid(jwks, kid, alg, enc) ⇒ Object

Raises:

  • (DecodeError)


42
43
44
45
46
47
48
49
50
51
52
# File 'lib/rodauth/oauth/jwe_extensions.rb', line 42

def self.find_key_by_kid(jwks, kid, alg, enc)
  raise DecodeError, "No key id (kid) found from token headers" unless kid

  jwk = jwks.find { |key, _| (key[:kid] || key["kid"]) == kid }

  raise DecodeError, "Could not find public key for kid #{kid}" unless jwk
  raise DecodeError, "Expected a different encryption algorithm" unless alg == (jwk[:alg] || jwk["alg"])
  raise DecodeError, "Expected a different encryption method" unless enc == (jwk[:enc] || jwk["enc"])

  ::JWT::JWK.import(jwk).keypair
end