Module: JWE

Defined in:
lib/jwe.rb,
lib/jwe/alg.rb,
lib/jwe/enc.rb,
lib/jwe/zip.rb,
lib/jwe/base64.rb,
lib/jwe/alg/dir.rb,
lib/jwe/version.rb,
lib/jwe/zip/def.rb,
lib/jwe/alg/rsa15.rb,
lib/jwe/enc/a128gcm.rb,
lib/jwe/enc/a192gcm.rb,
lib/jwe/enc/a256gcm.rb,
lib/jwe/enc/aes_gcm.rb,
lib/jwe/alg/rsa_oaep.rb,
lib/jwe/enc/aes_cbc_hs.rb,
lib/jwe/enc/a128cbc_hs256.rb,
lib/jwe/enc/a192cbc_hs384.rb,
lib/jwe/enc/a256cbc_hs512.rb,
lib/jwe/serialization/compact.rb

Defined Under Namespace

Modules: Alg, Base64, Enc, Serialization, Zip Classes: BadCEK, DecodeError, InvalidData, NotImplementedError

Constant Summary collapse

VALID_ALG =
['RSA1_5', 'RSA-OAEP', 'RSA-OAEP-256', 'A128KW', 'A192KW', 'A256KW', 'dir', 'ECDH-ES', 'ECDH-ES+A128KW', 'ECDH-ES+A192KW', 'ECDH-ES+A256KW', 'A128GCMKW', 'A192GCMKW', 'A256GCMKW', 'PBES2-HS256+A128KW', 'PBES2-HS384+A192KW', 'PBES2-HS512+A256KW'].freeze
VALID_ENC =
['A128CBC-HS256', 'A192CBC-HS384', 'A256CBC-HS512', 'A128GCM', 'A192GCM', 'A256GCM'].freeze
VALID_ZIP =
['DEF'].freeze
VERSION =
'0.1.1'.freeze

Class Method Summary collapse

Class Method Details

.decrypt(payload, key) ⇒ Object

Raises:

  • (ArgumentError)


42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/jwe.rb', line 42

def self.decrypt(payload, key)
  header, enc_key, iv, ciphertext, tag = Serialization::Compact.decode(payload)
  header = JSON.parse(header)
  base64header = payload.split('.').first

  raise ArgumentError.new("\"#{header['alg']}\" is not a valid alg method") unless VALID_ALG.include?(header['alg'])
  raise ArgumentError.new("\"#{header['enc']}\" is not a valid enc method") unless VALID_ENC.include?(header['enc'])
  raise ArgumentError.new("\"#{header['zip']}\" is not a valid zip method") unless header['zip'].nil? || VALID_ZIP.include?(header['zip'])
  raise ArgumentError.new('The key must not be nil or blank') if key.nil? || (key.is_a?(String) && key.strip == '')

  cek = Alg.for(header['alg']).new(key).decrypt(enc_key)
  cipher = Enc.for(header['enc']).new(cek, iv)
  cipher.tag = tag

  plaintext = cipher.decrypt(ciphertext, base64header)

  if header['zip']
    Zip.for(header['zip']).new.decompress(plaintext)
  else
    plaintext
  end
end

.encrypt(payload, key, alg: 'RSA-OAEP', enc: 'A128GCM', zip: nil) ⇒ Object

Raises:

  • (ArgumentError)


22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/jwe.rb', line 22

def self.encrypt(payload, key, alg: 'RSA-OAEP', enc: 'A128GCM', zip: nil)
  raise ArgumentError.new("\"#{alg}\" is not a valid alg method") unless VALID_ALG.include?(alg)
  raise ArgumentError.new("\"#{enc}\" is not a valid enc method") unless VALID_ENC.include?(enc)
  raise ArgumentError.new("\"#{zip}\" is not a valid zip method") unless zip.nil? || zip == '' || VALID_ZIP.include?(zip)
  raise ArgumentError.new('The key must not be nil or blank') if key.nil? || (key.is_a?(String) && key.strip == '')

  header = { alg: alg, enc: enc }
  header[:zip] = zip if zip && zip != ''

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

  payload = Zip.for(zip).new.compress(payload) if zip && zip != ''

  ciphertext = cipher.encrypt(payload, Base64.jwe_encode(header.to_json))
  encrypted_cek = Alg.for(alg).new(key).encrypt(cipher.cek)

  Serialization::Compact.encode(header.to_json, encrypted_cek, cipher.iv, ciphertext, cipher.tag)
end