Class: MastercardCoreSdk::Util::Jose

Inherits:
Object
  • Object
show all
Extended by:
Core, Exceptions
Defined in:
lib/mastercard_core_sdk/util/jose.rb

Constant Summary collapse

SEGMENTS =
5

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.aadObject

Returns the value of attribute aad.



17
18
19
# File 'lib/mastercard_core_sdk/util/jose.rb', line 17

def aad
  @aad
end

.aes_enc_keyObject

Returns the value of attribute aes_enc_key.



17
18
19
# File 'lib/mastercard_core_sdk/util/jose.rb', line 17

def aes_enc_key
  @aes_enc_key
end

.alObject

Returns the value of attribute al.



17
18
19
# File 'lib/mastercard_core_sdk/util/jose.rb', line 17

def al
  @al
end

.algObject

Returns the value of attribute alg.



16
17
18
# File 'lib/mastercard_core_sdk/util/jose.rb', line 16

def alg
  @alg
end

.api_configObject

Returns the value of attribute api_config.



16
17
18
# File 'lib/mastercard_core_sdk/util/jose.rb', line 16

def api_config
  @api_config
end

.auth_tagObject

Returns the value of attribute auth_tag.



17
18
19
# File 'lib/mastercard_core_sdk/util/jose.rb', line 17

def auth_tag
  @auth_tag
end

.cekObject

Returns the value of attribute cek.



17
18
19
# File 'lib/mastercard_core_sdk/util/jose.rb', line 17

def cek
  @cek
end

.cipher_textObject

Returns the value of attribute cipher_text.



16
17
18
# File 'lib/mastercard_core_sdk/util/jose.rb', line 16

def cipher_text
  @cipher_text
end

.encObject

Returns the value of attribute enc.



16
17
18
# File 'lib/mastercard_core_sdk/util/jose.rb', line 16

def enc
  @enc
end

.encrypted_cekObject

Returns the value of attribute encrypted_cek.



17
18
19
# File 'lib/mastercard_core_sdk/util/jose.rb', line 17

def encrypted_cek
  @encrypted_cek
end

.hmac_inputObject

Returns the value of attribute hmac_input.



17
18
19
# File 'lib/mastercard_core_sdk/util/jose.rb', line 17

def hmac_input
  @hmac_input
end

.hmac_keyObject

Returns the value of attribute hmac_key.



17
18
19
# File 'lib/mastercard_core_sdk/util/jose.rb', line 17

def hmac_key
  @hmac_key
end

.ivObject

Returns the value of attribute iv.



17
18
19
# File 'lib/mastercard_core_sdk/util/jose.rb', line 17

def iv
  @iv
end

.jwe_protected_headerObject

Returns the value of attribute jwe_protected_header.



17
18
19
# File 'lib/mastercard_core_sdk/util/jose.rb', line 17

def jwe_protected_header
  @jwe_protected_header
end

.plain_textObject

Returns the value of attribute plain_text.



16
17
18
# File 'lib/mastercard_core_sdk/util/jose.rb', line 16

def plain_text
  @plain_text
end

.private_keyObject

Returns the value of attribute private_key.



16
17
18
# File 'lib/mastercard_core_sdk/util/jose.rb', line 16

def private_key
  @private_key
end

.public_keyObject

Returns the value of attribute public_key.



16
17
18
# File 'lib/mastercard_core_sdk/util/jose.rb', line 16

def public_key
  @public_key
end

Class Method Details

.decode_compact_serialized(input) ⇒ Object



63
64
65
66
67
68
69
70
71
72
# File 'lib/mastercard_core_sdk/util/jose.rb', line 63

def decode_compact_serialized(input)
  unless input.count('.') + 1 == SEGMENTS
    raise SDKValidationError.new("Invalid format, should include #{SEGMENTS} segments.")
  end
  header, self.encrypted_cek, self.iv, self.cipher_text, self.auth_tag = input.split('.').collect do |segment|
    url_safe_decode64 segment
  end
  self.aad = input.split('.').first
  self.jwe_protected_header = JSON.load(header)
end

.decrypt(input, private_key) ⇒ Object



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/mastercard_core_sdk/util/jose.rb', line 74

def decrypt(input, private_key)
  decode_compact_serialized input
  self.alg = jwe_protected_header["alg"]
  self.enc = jwe_protected_header["enc"]
  self.private_key = private_key
  cipher = OpenSSL::Cipher.new 'AES-128-CBC'
  cipher.decrypt
  self.cek = private_key.private_decrypt encrypted_cek, OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING
  self.hmac_key, self.aes_enc_key = derive_encryption_and_hmac_keys
  cipher.key = aes_enc_key
  cipher.iv = iv
  self.plain_text = cipher.update(cipher_text) + cipher.final
  self.al = derive_al
  self.hmac_input = [ aad, iv, cipher_text, al ].join
  verify_cbc_authentication_tag!
  return self.plain_text
end

.derive_alObject



92
93
94
# File 'lib/mastercard_core_sdk/util/jose.rb', line 92

def derive_al
  [(aad.bytesize * 8)].pack('Q>')
end

.derive_encryption_and_hmac_keysObject



96
97
98
99
100
# File 'lib/mastercard_core_sdk/util/jose.rb', line 96

def derive_encryption_and_hmac_keys
  cek.unpack(
    "a#{cek.length / 2}" * 2
  )
end

.secure_compare(a, b) ⇒ Object



111
112
113
114
115
116
117
118
119
# File 'lib/mastercard_core_sdk/util/jose.rb', line 111

def secure_compare(a, b)
  return false unless a.bytesize == b.bytesize
  
  l = a.unpack "C#{a.bytesize}"
  
  res = 0
  b.each_byte { |byte| res |= byte ^ l.shift }
  res == 0
end

.sha_sizeObject



31
32
33
34
35
36
37
38
39
40
# File 'lib/mastercard_core_sdk/util/jose.rb', line 31

def sha_size
  case enc.to_sym
  when :'A128CBC-HS256'
    256
  when :'A256CBC-HS512'
    512
  else
    raise 'Unknown Hash Size'
  end
end

.to_sObject



19
20
21
22
23
24
25
26
27
28
29
# File 'lib/mastercard_core_sdk/util/jose.rb', line 19

def to_s
  [
    jwe_protected_header,
    encrypted_cek,
    iv,
    cipher_text,
    auth_tag
  ].collect do |segment|
    url_safe_encode64 segment.to_s
  end.join('.')
end

.url_safe_decode64(binary) ⇒ String

Returns the Base64Url decoded version of ‘binary` without padding.



45
46
47
48
49
50
51
52
53
54
# File 'lib/mastercard_core_sdk/util/jose.rb', line 45

def url_safe_decode64(binary)
  binary = binary.tr('-_', '+/')
  case binary.bytesize % 4
  when 2
    binary += '=='
  when 3
    binary += '='
  end
  return Base64.decode64(binary)
end

.url_safe_encode64(binary) ⇒ String

Returns the Base64Url encoded version of ‘binary` without padding.



59
60
61
# File 'lib/mastercard_core_sdk/util/jose.rb', line 59

def url_safe_encode64(binary)
  return Base64.strict_encode64(binary).tr('+/', '-_').delete('=')
end

.verify_cbc_authentication_tag!Object



102
103
104
105
106
107
108
109
# File 'lib/mastercard_core_sdk/util/jose.rb', line 102

def verify_cbc_authentication_tag!
  expected_auth_tag = OpenSSL::HMAC.digest(
    OpenSSL::Digest.new("SHA#{sha_size}"), hmac_key, hmac_input
  )[0, sha_size / 2 / 8]
  unless secure_compare(auth_tag, expected_auth_tag)
    raise SDKValidationError.new(ERR_MSG_JOSE_DECRYPTION)
  end
end