aliquot 0.15.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 54635adaeefcc42d7fb42a854825fb7f88472ab34be2992813d899581f278969
4
- data.tar.gz: 3f66d3b5d5cc20d3a58e0c0e64958906beee8e80f07af26a4868ad27efa68e2d
3
+ metadata.gz: 0cdd20926e96b21c0fb8c494b13fe34995c59646285d71416c33045e907b830a
4
+ data.tar.gz: 32d7e64f5ef20f37404bcc5293672dbaa43f6d299bd0701e49b859ad2e9c1a25
5
5
  SHA512:
6
- metadata.gz: 23548bcc9c7e7a5ad77353bae8eab0283bd7593b3a9cf536298961d501a0b1b3181b722bf3e75ae0805d9c9dfa336d71a037ed5553eb57d0082b69a7e62aa60b
7
- data.tar.gz: a14a66a56577b6de570fa4164f30d2ca96c3a23b5b6b915d136dfd7d825242c0ae6a403cc138ff97e26f76dcad1450ba67d8a733f7b45611141ba46241fafdb8
6
+ metadata.gz: 1b555a97041aaaf6e4cd3e3aaf82c17a94112627f36cc3e0835a4708c28eef8e8f6a4f20e51b978876cc77a1ced87b6a4b6066a7effd52e2a027c5d152a78995
7
+ data.tar.gz: ee081263c8ad3869eaa53127ec7ed300f9bba4c67619c548ed83099932cf0978cf3e0ec48dbca47e054a01f79f747c261a0e96eb84d26e9665846dbfed5a2025
@@ -26,7 +26,7 @@ module Aliquot
26
26
  validation = Aliquot::Validator::Token.new(JSON.parse(token_string))
27
27
  validation.validate
28
28
  rescue JSON::JSONError => e
29
- raise InputError, "invalid token JSON, #{e.message}"
29
+ raise InputError, "token JSON is invalid, #{e.message}"
30
30
  end
31
31
 
32
32
  @token = validation.output
@@ -49,7 +49,7 @@ module Aliquot
49
49
 
50
50
  if protocol_version == 'ECv2'
51
51
  @intermediate_key = validate_intermediate_key
52
- raise InvalidSignatureError, 'intermediate certificate has expired' if intermediate_key_expired?
52
+ raise InvalidSignatureError, 'intermediate certificate is expired' if intermediate_key_expired?
53
53
  end
54
54
 
55
55
  check_signature
@@ -59,22 +59,22 @@ module Aliquot
59
59
  begin
60
60
  aes_key, mac_key = derive_keys(@signed_message[:ephemeralPublicKey], @shared_secret, 'Google')
61
61
  rescue => e
62
- raise KeyDerivationError, "unable to derive keys, #{e.message}"
62
+ raise KeyDerivationError, "cannot derive keys, #{e.message}"
63
63
  end
64
64
 
65
- raise InvalidMacError, 'MAC did not match' unless valid_mac?(mac_key)
65
+ raise InvalidMacError, 'MAC does not match' unless valid_mac?(mac_key)
66
66
 
67
67
  begin
68
68
  @message = JSON.parse(decrypt(aes_key, @signed_message[:encryptedMessage]))
69
69
  rescue JSON::JSONError => e
70
- raise InputError, "invalid encryptedMessage JSON, #{e.message}"
70
+ raise InputError, "encryptedMessage JSON is invalid, #{e.message}"
71
71
  rescue => e
72
72
  raise DecryptionError, "decryption failed, #{e.message}"
73
73
  end
74
74
 
75
75
  @message = validate_message
76
76
 
77
- raise TokenExpiredError, 'token has expired' if expired?
77
+ raise TokenExpiredError, 'token is expired' if expired?
78
78
 
79
79
  @message
80
80
  end
@@ -133,7 +133,7 @@ module Aliquot
133
133
  key.verify(new_digest, message_signature, signed_string_message)
134
134
  end.any?
135
135
 
136
- raise InvalidSignatureError, 'signature of signedMessage did not match' unless success
136
+ raise InvalidSignatureError, 'signature of signedMessage does not match' unless success
137
137
  when 'ECv2'
138
138
  signed_key_signature = ['Google', 'ECv2', @token[:intermediateSigningKey][:signedKey]].map do |str|
139
139
  [str.length].pack('V') + str
@@ -141,7 +141,7 @@ module Aliquot
141
141
 
142
142
  # Check that the intermediate key signed the message
143
143
  pkey = OpenSSL::PKey::EC.new(Base64.strict_decode64(@intermediate_key[:keyValue]))
144
- raise InvalidSignatureError, 'signature of signedMessage did not match' unless pkey.verify(new_digest, message_signature, signed_string_message)
144
+ raise InvalidSignatureError, 'signature of signedMessage does not match' unless pkey.verify(new_digest, message_signature, signed_string_message)
145
145
 
146
146
  intermediate_signatures = @token[:intermediateSigningKey][:signatures]
147
147
 
@@ -152,7 +152,7 @@ module Aliquot
152
152
  signed_key_signature
153
153
  )
154
154
 
155
- raise InvalidSignatureError, 'no valid signature of intermediate key found' unless success
155
+ raise InvalidSignatureError, 'no valid signature of intermediate key' unless success
156
156
  end
157
157
  rescue OpenSSL::PKey::PKeyError => e
158
158
  # Catches problems with verifying signature. Can be caused by signature
@@ -22,6 +22,7 @@ module Aliquot
22
22
  month?: 'must be a month (1..12)',
23
23
  year?: 'must be a year (2000..3000)',
24
24
  base64_asn1?: 'must be base64 encoded asn1 value',
25
+ json_object?: 'must be a JSON object',
25
26
 
26
27
  authMethodCryptogram3DS: 'authMethod CRYPTOGRAM_3DS requires eciIndicator',
27
28
  authMethodCard: 'eciIndicator/cryptogram must be omitted when PAN_ONLY',
@@ -64,6 +65,8 @@ module Aliquot
64
65
  predicate(:year?) { |x| x.between?(2000, 3000) }
65
66
 
66
67
  predicate(:base64_asn1?) { |x| OpenSSL::ASN1.decode(Base64.strict_decode64(x)) rescue false }
68
+
69
+ predicate(:json_object?) { |x| hash?(x) }
67
70
  end
68
71
 
69
72
  # Base for DRY-Validation schemas used in Aliquot.
@@ -78,7 +81,6 @@ module Aliquot
78
81
  IntermediateSigningKeySchema = Dry::Validation.Schema(BaseSchema) do
79
82
  required(:signedKey).filled(:str?, :json_string?)
80
83
 
81
- # TODO: Check if elements of array are valid signatures
82
84
  required(:signatures).filled(:array?) { each { base64? & base64_asn1? } }
83
85
  end
84
86
 
@@ -91,21 +93,19 @@ module Aliquot
91
93
  TokenSchema = Dry::Validation.Schema(BaseSchema) do
92
94
  required(:signature).filled(:str?, :base64?, :base64_asn1?)
93
95
 
94
- # Currently supposed to be ECv1, but may evolve.
95
- required(:protocolVersion).filled(:str?)
96
- required(:signedMessage).filled(:str?, :json_string?)
96
+ required(:protocolVersion).filled(:str?).when(eql?: 'ECv2') do
97
+ required(:intermediateSigningKey)
98
+ end
97
99
 
98
- optional(:intermediateSigningKey).schema(IntermediateSigningKeySchema)
100
+ required(:signedMessage).filled(:str?, :json_string?)
99
101
 
100
- rule('ECv2 implies intermediateSigningKey': %i[protocolVersion intermediateSigningKey]) do |version, intermediatekey|
101
- version.eql?('ECv2') > intermediatekey.filled?
102
- end
102
+ optional(:intermediateSigningKey).value(:json_object?) { schema(IntermediateSigningKeySchema) }
103
103
  end
104
104
 
105
105
  # DRY-Validation schema for signedMessage component Google Pay token
106
106
  SignedMessageSchema = Dry::Validation.Schema(BaseSchema) do
107
107
  required(:encryptedMessage).filled(:str?, :base64?)
108
- required(:ephemeralPublicKey).filled(:str?, :base64?).value(size?: 44)
108
+ required(:ephemeralPublicKey).filled(:str?, :base64?)
109
109
  required(:tag).filled(:str?, :base64?)
110
110
  end
111
111
 
@@ -119,15 +119,15 @@ module Aliquot
119
119
  optional(:cryptogram).filled(:str?)
120
120
  optional(:eciIndicator).filled(:str?, :eci?)
121
121
 
122
- rule('when authMethod is CRYPTOGRAM_3DS, cryptogram': %i[authMethod cryptogram]) do |method, cryptogram|
123
- method.eql?('CRYPTOGRAM_3DS') > cryptogram.filled?
122
+ rule(cryptogram: %i[authMethod cryptogram]) do |method, cryptogram|
123
+ method.eql?('CRYPTOGRAM_3DS') > required(:cryptogram)
124
124
  end
125
125
 
126
- rule('when authMethod is PAN_ONLY, eciIndicator': %i[authMethod eciIndicator]) do |method, eci|
126
+ rule(eciIndicator: %i[authMethod eciIndicator]) do |method, eci|
127
127
  method.eql?('PAN_ONLY').then(eci.none?)
128
128
  end
129
129
 
130
- rule('when authMethod is PAN_ONLY, cryptogram': %i[authMethod cryptogram]) do |method, cryptogram|
130
+ rule(cryptogram: %i[authMethod cryptogram]) do |method, cryptogram|
131
131
  method.eql?('PAN_ONLY').then(cryptogram.none?)
132
132
  end
133
133
  end
@@ -137,7 +137,7 @@ module Aliquot
137
137
  required(:messageExpiration).filled(:str?, :integer_string?)
138
138
  required(:messageId).filled(:str?)
139
139
  required(:paymentMethod).filled(:str?, eql?: 'CARD')
140
- required(:paymentMethodDetails).schema(PaymentMethodDetailsSchema)
140
+ required(:paymentMethodDetails).value(:json_object?) { schema PaymentMethodDetailsSchema }
141
141
  end
142
142
 
143
143
  module InstanceMethods
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aliquot
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.15.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Clearhaus
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-01-17 00:00:00.000000000 Z
11
+ date: 2019-02-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dry-validation
@@ -58,14 +58,14 @@ dependencies:
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: 0.12.0
61
+ version: 1.0.0
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: 0.12.0
68
+ version: 1.0.0
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rspec
71
71
  requirement: !ruby/object:Gem::Requirement