Class: R2D2::PaymentToken
- Inherits:
-
Object
- Object
- R2D2::PaymentToken
- Defined in:
- lib/r2d2/payment_token.rb
Defined Under Namespace
Classes: TagVerificationError
Instance Attribute Summary collapse
-
#encrypted_message ⇒ Object
Returns the value of attribute encrypted_message.
-
#ephemeral_public_key ⇒ Object
Returns the value of attribute ephemeral_public_key.
-
#tag ⇒ Object
Returns the value of attribute tag.
Class Method Summary collapse
- .decrypt_message(encrypted_data, symmetric_key) ⇒ Object
- .derive_hkdf_keys(ephemeral_public_key, shared_secret) ⇒ Object
- .generate_shared_secret(private_key, ephemeral_public_key) ⇒ Object
- .verify_mac(digest, mac_key, encrypted_message, tag) ⇒ Object
Instance Method Summary collapse
- #decrypt(private_key_pem) ⇒ Object
-
#initialize(token_attrs) ⇒ PaymentToken
constructor
A new instance of PaymentToken.
-
#secure_compare(a, b) ⇒ Object
constant-time comparison algorithm to prevent timing attacks; borrowed from ActiveSupport::MessageVerifier.
Constructor Details
#initialize(token_attrs) ⇒ PaymentToken
Returns a new instance of PaymentToken.
12 13 14 15 16 |
# File 'lib/r2d2/payment_token.rb', line 12 def initialize(token_attrs) self.ephemeral_public_key = token_attrs["ephemeralPublicKey"] self.tag = token_attrs["tag"] self. = token_attrs["encryptedMessage"] end |
Instance Attribute Details
#encrypted_message ⇒ Object
Returns the value of attribute encrypted_message.
8 9 10 |
# File 'lib/r2d2/payment_token.rb', line 8 def end |
#ephemeral_public_key ⇒ Object
Returns the value of attribute ephemeral_public_key.
8 9 10 |
# File 'lib/r2d2/payment_token.rb', line 8 def ephemeral_public_key @ephemeral_public_key end |
#tag ⇒ Object
Returns the value of attribute tag.
8 9 10 |
# File 'lib/r2d2/payment_token.rb', line 8 def tag @tag end |
Class Method Details
.decrypt_message(encrypted_data, symmetric_key) ⇒ Object
56 57 58 59 60 61 62 |
# File 'lib/r2d2/payment_token.rb', line 56 def (encrypted_data, symmetric_key) decipher = OpenSSL::Cipher::AES128.new(:CTR) decipher.decrypt decipher.key = symmetric_key decipher.auth_data = "" decipher.update(Base64.decode64(encrypted_data)) + decipher.final end |
.derive_hkdf_keys(ephemeral_public_key, shared_secret) ⇒ Object
42 43 44 45 46 47 48 49 |
# File 'lib/r2d2/payment_token.rb', line 42 def derive_hkdf_keys(ephemeral_public_key, shared_secret) key_material = Base64.decode64(ephemeral_public_key) + shared_secret; hkdf = HKDF.new(key_material, :algorithm => 'SHA256', :info => 'Android') { :symmetric_encryption_key => hkdf.next_bytes(16), :mac_key => hkdf.next_bytes(16) } end |
.generate_shared_secret(private_key, ephemeral_public_key) ⇒ Object
35 36 37 38 39 40 |
# File 'lib/r2d2/payment_token.rb', line 35 def generate_shared_secret(private_key, ephemeral_public_key) ec = OpenSSL::PKey::EC.new('prime256v1') bn = OpenSSL::BN.new(Base64.decode64(ephemeral_public_key), 2) point = OpenSSL::PKey::EC::Point.new(ec.group, bn) private_key.dh_compute_key(point) end |
.verify_mac(digest, mac_key, encrypted_message, tag) ⇒ Object
51 52 53 54 |
# File 'lib/r2d2/payment_token.rb', line 51 def verify_mac(digest, mac_key, , tag) mac = OpenSSL::HMAC.digest(digest, mac_key, Base64.decode64()) raise TagVerificationError unless secure_compare(mac, Base64.decode64(tag)) end |
Instance Method Details
#decrypt(private_key_pem) ⇒ Object
18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
# File 'lib/r2d2/payment_token.rb', line 18 def decrypt(private_key_pem) digest = OpenSSL::Digest.new('sha256') private_key = OpenSSL::PKey::EC.new(private_key_pem) shared_secret = self.class.generate_shared_secret(private_key, ephemeral_public_key) # derive the symmetric_encryption_key and mac_key hkdf_keys = self.class.derive_hkdf_keys(ephemeral_public_key, shared_secret); # verify the tag is a valid value self.class.verify_mac(digest, hkdf_keys[:mac_key], , tag) self.class.(, hkdf_keys[:symmetric_encryption_key]) end |
#secure_compare(a, b) ⇒ Object
constant-time comparison algorithm to prevent timing attacks; borrowed from ActiveSupport::MessageVerifier
70 71 72 |
# File 'lib/r2d2/payment_token.rb', line 70 def secure_compare(a, b) FastSecureCompare.compare(a, b) end |