Class: JOSE::JWE::ALG_PBES2

Inherits:
Struct
  • Object
show all
Defined in:
lib/jose/jwe/alg_pbes2.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#bitsObject

Returns the value of attribute bits

Returns:

  • (Object)

    the current value of bits



1
2
3
# File 'lib/jose/jwe/alg_pbes2.rb', line 1

def bits
  @bits
end

#hmacObject

Returns the value of attribute hmac

Returns:

  • (Object)

    the current value of hmac



1
2
3
# File 'lib/jose/jwe/alg_pbes2.rb', line 1

def hmac
  @hmac
end

#iterObject

Returns the value of attribute iter

Returns:

  • (Object)

    the current value of iter



1
2
3
# File 'lib/jose/jwe/alg_pbes2.rb', line 1

def iter
  @iter
end

#saltObject

Returns the value of attribute salt

Returns:

  • (Object)

    the current value of salt



1
2
3
# File 'lib/jose/jwe/alg_pbes2.rb', line 1

def salt
  @salt
end

Class Method Details

.from_map(fields) ⇒ Object

JOSE::JWE callbacks



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/jose/jwe/alg_pbes2.rb', line 5

def self.from_map(fields)
  bits = nil
  hmac = nil
  case fields['alg']
  when 'PBES2-HS256+A128KW'
    bits = 128
    hmac = OpenSSL::Digest::SHA256
  when 'PBES2-HS384+A192KW'
    bits = 192
    hmac = OpenSSL::Digest::SHA384
  when 'PBES2-HS512+A256KW'
    bits = 256
    hmac = OpenSSL::Digest::SHA512
  else
    raise ArgumentError, "invalid 'alg' for JWE: #{fields['alg'].inspect}"
  end
  iter = nil
  if not fields.has_key?('p2c')
    iter = bits * 32
  elsif fields['p2c'].is_a?(Integer) and fields['p2c'] >= 0
    iter = fields['p2c']
  else
    raise ArgumentError, "invalid 'p2c' for JWE: #{fields['p2c'].inspect}"
  end
  salt = nil
  if not fields.has_key?('p2s')
    salt = nil
  elsif fields['p2s'].is_a?(String)
    salt = wrap_salt(fields['alg'], JOSE.urlsafe_decode64(fields['p2s']))
  else
    raise ArgumentError, "invalid 'p2s' for JWE: #{fields['p2s'].inspect}"
  end
  return new(hmac, bits, salt, iter), fields.except('alg', 'p2c', 'p2s')
end

.unwrap_salt(algorithm, salt) ⇒ Object



104
105
106
107
108
109
110
111
# File 'lib/jose/jwe/alg_pbes2.rb', line 104

def self.unwrap_salt(algorithm, salt)
  salt_s = StringIO.new(salt)
  if salt_s.read(algorithm.length) != algorithm or salt_s.getbyte != 0
    raise ArgumentError, "unrecognized salt value"
  else
    return salt_s.read
  end
end

.wrap_salt(algorithm, salt_input) ⇒ Object



117
118
119
# File 'lib/jose/jwe/alg_pbes2.rb', line 117

def self.wrap_salt(algorithm, salt_input)
  return [algorithm, 0x00, salt_input].pack('a*Ca*')
end

Instance Method Details

#algorithmObject

API functions



92
93
94
95
96
97
98
99
100
101
102
# File 'lib/jose/jwe/alg_pbes2.rb', line 92

def algorithm
  if hmac == OpenSSL::Digest::SHA256
    'PBES2-HS256+A128KW'
  elsif hmac == OpenSSL::Digest::SHA384
    'PBES2-HS384+A192KW'
  elsif hmac == OpenSSL::Digest::SHA512
    'PBES2-HS512+A256KW'
  else
    raise ArgumentError, "unhandled JOSE::JWE::ALG_PBES2 hmac: #{hmac.inspect}"
  end
end

#generate_key(fields, enc) ⇒ Object

JOSE::JWE::ALG callbacks



53
54
55
56
57
58
59
60
61
62
# File 'lib/jose/jwe/alg_pbes2.rb', line 53

def generate_key(fields, enc)
  alg = algorithm
  extra_fields = {
    'p2c' => iter
  }
  if not salt.nil?
    extra_fields['p2s'] = JOSE.urlsafe_encode64(unwrap_salt(salt))
  end
  return JOSE::JWE::ALG.generate_key([:oct, 16], alg, enc.algorithm).merge(extra_fields)
end

#key_decrypt(key, enc, encrypted_key) ⇒ Object



64
65
66
67
68
69
70
71
# File 'lib/jose/jwe/alg_pbes2.rb', line 64

def key_decrypt(key, enc, encrypted_key)
  if key.is_a?(JOSE::JWK)
    key = key.kty.derive_key
  end
  derived_key = OpenSSL::PKCS5.pbkdf2_hmac(key, salt, iter, bits.div(8) + (bits % 8), hmac.new)
  decrypted_key = JOSE::JWA::AES_KW.unwrap(encrypted_key, derived_key)
  return decrypted_key
end

#key_encrypt(key, enc, decrypted_key) ⇒ Object



73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/jose/jwe/alg_pbes2.rb', line 73

def key_encrypt(key, enc, decrypted_key)
  if key.is_a?(JOSE::JWK)
    key = key.kty.derive_key
  end
  new_alg = self
  if new_alg.salt.nil?
    new_alg = JOSE::JWE::ALG_PBES2.new(hmac, bits, wrap_salt(SecureRandom.random_bytes(bits.div(8))), iter)
  end
  derived_key = OpenSSL::PKCS5.pbkdf2_hmac(key, new_alg.salt, new_alg.iter, new_alg.bits.div(8) + (new_alg.bits % 8), new_alg.hmac.new)
  encrypted_key = JOSE::JWA::AES_KW.wrap(decrypted_key, derived_key)
  return encrypted_key, new_alg
end

#next_cek(key, enc) ⇒ Object



86
87
88
# File 'lib/jose/jwe/alg_pbes2.rb', line 86

def next_cek(key, enc)
  return enc.next_cek, self
end

#to_map(fields) ⇒ Object



40
41
42
43
44
45
46
47
48
49
# File 'lib/jose/jwe/alg_pbes2.rb', line 40

def to_map(fields)
  alg = algorithm
  p2c = iter
  if salt.nil?
    return fields.put('alg', alg).put('p2c', p2c)
  else
    p2s = JOSE.urlsafe_encode64(unwrap_salt(salt))
    return fields.put('alg', alg).put('p2c', p2c).put('p2s', p2s)
  end
end

#unwrap_salt(salt) ⇒ Object



113
114
115
# File 'lib/jose/jwe/alg_pbes2.rb', line 113

def unwrap_salt(salt)
  return JOSE::JWE::ALG_PBES2.unwrap_salt(algorithm, salt)
end

#wrap_salt(salt_input) ⇒ Object



121
122
123
# File 'lib/jose/jwe/alg_pbes2.rb', line 121

def wrap_salt(salt_input)
  return JOSE::JWE::ALG_PBES2.wrap_salt(algorithm, salt_input)
end