touchpass 0.0.8.1 → 0.0.8.16
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +27 -12
- data/Rakefile +20 -1
- data/app/assets/images/touchpass/buttons/cancelling.png +0 -0
- data/app/assets/images/touchpass/buttons/unverified.png +0 -0
- data/app/assets/images/touchpass/buttons/verified.png +0 -0
- data/app/assets/images/touchpass/buttons/verify.png +0 -0
- data/app/assets/images/touchpass/buttons/verifying.png +0 -0
- data/app/assets/images/touchpass/cross.png +0 -0
- data/app/assets/images/touchpass/loading.gif +0 -0
- data/app/assets/images/touchpass/tick.png +0 -0
- data/app/assets/images/touchpass/touchpass-logo.jpg +0 -0
- data/app/assets/javascripts/touchpass/index.js +1 -0
- data/app/assets/javascripts/touchpass/jquery.touchpass-0.0.1.js +199 -0
- data/app/assets/stylesheets/touchpass/index.css +1 -0
- data/app/assets/stylesheets/touchpass/widget.css +17 -0
- data/app/controllers/touchpass/verifications_controller.rb +10 -6
- data/bin/tpcli.rb +29 -21
- data/bin/tpcrypt.rb +38 -0
- data/config/routes.rb +2 -2
- data/lib/touchpass/client.rb +33 -81
- data/lib/touchpass/crypt.rb +29 -6
- data/lib/touchpass/prp.rb +9 -6
- data/lib/touchpass/{device.rb → rp/device.rb} +5 -2
- data/lib/touchpass/rp/response.rb +34 -0
- data/lib/touchpass/rp/verification.rb +53 -0
- data/lib/touchpass/verification.rb +119 -86
- data/lib/touchpass/version.rb +1 -1
- data/lib/touchpass.rb +27 -5
- data/spec/curl.touchpass_client_spec-workingcontent.txt +268 -0
- data/spec/spec_helper.rb +9 -0
- data/spec/touchpass_client_spec.rb +42 -48
- data/spec/touchpass_crypt_spec.rb +27 -0
- data/spec/touchpass_rp_verification_spec.rb +52 -0
- data/spec/touchpass_spec.rb +12 -0
- data/spec/touchpass_verification_spec.rb +26 -0
- metadata +66 -14
data/lib/touchpass/client.rb
CHANGED
@@ -11,6 +11,7 @@ require 'base64'
|
|
11
11
|
require 'pp'
|
12
12
|
require 'cgi'
|
13
13
|
require 'json'
|
14
|
+
require 'securerandom'
|
14
15
|
|
15
16
|
module Touchpass
|
16
17
|
|
@@ -103,12 +104,13 @@ module Touchpass
|
|
103
104
|
# Collect attributes of new device
|
104
105
|
device_attributes = params.merge({
|
105
106
|
:udid => params[:udid],
|
107
|
+
:app_id => params[:app_id],
|
106
108
|
:name => params[:name],
|
107
109
|
:pub_key => crypt.public_key,
|
108
110
|
:messaging_type => params[:messaging_type],
|
109
|
-
:messaging_value => params[:messaging_value]
|
111
|
+
:messaging_value => params[:messaging_value]
|
110
112
|
})
|
111
|
-
http_options = standard_http_options(device_attributes, %W{udid name pub_key messaging_type messaging_value})
|
113
|
+
http_options = standard_http_options(device_attributes, %W{udid app_id name pub_key messaging_type messaging_value})
|
112
114
|
|
113
115
|
# Provision the new device with the Touchpass server
|
114
116
|
new_device = submit_request("post", "#{@hostname}/#{params[:username]}/devices.#{@output}", http_options)
|
@@ -179,77 +181,21 @@ module Touchpass
|
|
179
181
|
end
|
180
182
|
|
181
183
|
# Create a new verification
|
182
|
-
# needs: :to_party, :api_key
|
184
|
+
# needs: :to_party, :api_key
|
185
|
+
# uses:
|
186
|
+
# :address (for LV), :resolution (for LV)
|
187
|
+
# :message, :message_post_verification
|
183
188
|
def create_verification(params)
|
184
|
-
http_options = standard_http_options(params, %W{to_party})
|
185
|
-
message = params[:message]
|
186
|
-
address = params[:address]
|
189
|
+
http_options = standard_http_options(params, %W{to_party to_device_id to_app_id})
|
187
190
|
|
188
191
|
# Get the list of verifying party devices so we can encrypt data for them using each device's public key
|
189
192
|
response = submit_request("get", "#{@hostname}/#{params[:to_party]}/devices.json",
|
190
193
|
standard_http_options(params))
|
191
194
|
vp_devices = response["devices"]
|
192
195
|
|
193
|
-
#
|
194
|
-
|
195
|
-
|
196
|
-
http_options[:body][:claimed_token] = hashed_token
|
197
|
-
|
198
|
-
if !vp_devices.nil? and (vp_devices.is_a? Array and !vp_devices.empty?)
|
199
|
-
|
200
|
-
# Encrypt message using each verifying party's (to_party) device public keys
|
201
|
-
if !message.nil?
|
202
|
-
vp_devices.each_with_index do |device, index|
|
203
|
-
device_id = device["id"]
|
204
|
-
pub_key_str = device["pub_key"]
|
205
|
-
public_key = Crypt.read_key(pub_key_str)
|
206
|
-
crypted_message = Base64.encode64(public_key.public_encrypt(message))
|
207
|
-
http_options[:body]["crypted_messages[#{index}][device_id]"] = device_id
|
208
|
-
http_options[:body]["crypted_messages[#{index}][value]"] = crypted_message
|
209
|
-
end
|
210
|
-
end
|
211
|
-
|
212
|
-
# Encrypt token using each verifying party's (to_party) device public keys
|
213
|
-
crypted_tokens = []
|
214
|
-
vp_devices.each_with_index do |device, index|
|
215
|
-
device_id = device["id"]
|
216
|
-
pub_key_str = device["pub_key"]
|
217
|
-
public_key = Crypt.read_key(pub_key_str)
|
218
|
-
crypted_token = Base64.encode64(public_key.public_encrypt(token)) # per-transaction token generated by Crypt.salt above
|
219
|
-
http_options[:body]["crypted_tokens[#{index}][device_id]"] = device_id
|
220
|
-
http_options[:body]["crypted_tokens[#{index}][value]"] = crypted_token
|
221
|
-
end
|
222
|
-
end
|
223
|
-
|
224
|
-
# Encrypt prp-hash using verifying_party (to_party) devices
|
225
|
-
if !address.nil? # For location verification
|
226
|
-
http_options[:body][:location_verification] = true
|
227
|
-
|
228
|
-
# Convert address to PRP
|
229
|
-
resolution = options[:resolution] || "LOCAL" # Resolution used to calculate PRP
|
230
|
-
http_options[:body][:resolution] = resolution
|
231
|
-
prp = Proximity::PRP.new(:address => params[:address], :resolution => resolution)
|
232
|
-
# puts prp.print_bbox # for debugging
|
233
|
-
|
234
|
-
# Generate random salt
|
235
|
-
salt = Crypt.salt
|
236
|
-
# puts "Using salt: #{salt}" # for debugging
|
237
|
-
|
238
|
-
# Encrypt PRP using salt
|
239
|
-
claimed_prp = prp.encrypt(salt)
|
240
|
-
http_options[:body][:claimed_prp] = claimed_prp
|
241
|
-
|
242
|
-
# Encrypt salt using verifiying_party (to_party) devices
|
243
|
-
crypted_salts = []
|
244
|
-
vp_devices.each_with_index do |device, index|
|
245
|
-
device_id = device["id"]
|
246
|
-
pub_key_str = device["pub_key"]
|
247
|
-
public_key = Crypt.read_key(pub_key_str)
|
248
|
-
crypted_salt = Base64.encode64(public_key.public_encrypt(salt))
|
249
|
-
http_options[:body]["crypted_salts[#{index}][device_id]"] = device_id
|
250
|
-
http_options[:body]["crypted_salts[#{index}][value]"] = crypted_salt
|
251
|
-
end
|
252
|
-
end
|
196
|
+
# create a verification object
|
197
|
+
verification = Touchpass::Verification.new(vp_devices, params)
|
198
|
+
http_options[:body].merge!(verification.http_params)
|
253
199
|
|
254
200
|
submit_request("post", "#{@hostname}/verifications.#{@output}", http_options)
|
255
201
|
end
|
@@ -295,25 +241,19 @@ module Touchpass
|
|
295
241
|
def update_verification(params)
|
296
242
|
# Call show verification to get the crypted salts and resolution for the verification
|
297
243
|
# Note: crypted salts and resolution are also returned in the list verifications response
|
298
|
-
http_options = standard_http_options(params)
|
299
|
-
|
300
|
-
verification = submit_request("get", "#{@hostname}/verifications/#{params[:id]}.json", http_options)
|
301
|
-
crypted_tokens = verification["crypted_tokens"]
|
302
|
-
crypted_salts = verification["crypted_salts"]
|
303
|
-
resolution = verification["resolution"]
|
244
|
+
http_options = standard_http_options(params, %W{id})
|
304
245
|
|
305
|
-
|
306
|
-
hashed_token = Crypt.encrypt(token)
|
246
|
+
verification = get_verification(params)
|
307
247
|
|
308
|
-
|
309
|
-
http_options[:body][:verified_token] =
|
248
|
+
token = decrypt_salt(verification["crypted_tokens"], params[:device_id], self.api_key)
|
249
|
+
http_options[:body][:verified_token] = Crypt.hash(token) unless token.nil?
|
310
250
|
|
311
251
|
# Generate verified PRP for location verification
|
312
252
|
if !params[:address].nil?
|
313
|
-
prp = Proximity::PRP.new(:address => params[:address], :resolution => resolution)
|
253
|
+
prp = Proximity::PRP.new(:address => params[:address], :resolution => verification["resolution"])
|
314
254
|
# puts prp.print_bbox # for debugging
|
315
255
|
|
316
|
-
salt = decrypt_salt(crypted_salts, params[:device_id], self.api_key)
|
256
|
+
salt = decrypt_salt(verification["crypted_salts"], params[:device_id], self.api_key)
|
317
257
|
# puts "Using salt: #{salt}"
|
318
258
|
verified_prp = prp.encrypt(salt)
|
319
259
|
|
@@ -327,15 +267,27 @@ module Touchpass
|
|
327
267
|
# Cancel an existing verification
|
328
268
|
# needs: :api_key, :id
|
329
269
|
def cancel_verification(params)
|
270
|
+
http_options = standard_http_options(params)
|
271
|
+
verification = get_verification(params)
|
272
|
+
|
273
|
+
token = decrypt_salt(verification["crypted_tokens"], params[:device_id], self.api_key)
|
274
|
+
http_options[:body][:verified_token] = Crypt.hash(token) unless token.nil?
|
275
|
+
|
330
276
|
submit_request("put", "#{@hostname}/verifications/#{params[:id]}/cancel.#{@output}",
|
331
|
-
|
277
|
+
http_options)
|
332
278
|
end
|
333
279
|
|
334
280
|
# Reject a verification
|
335
|
-
# needs: :
|
281
|
+
# needs: :api_key, :id
|
336
282
|
def reject_verification(params)
|
283
|
+
http_options = standard_http_options(params)
|
284
|
+
verification = get_verification(params)
|
285
|
+
|
286
|
+
token = decrypt_salt(verification["crypted_tokens"], params[:device_id], self.api_key)
|
287
|
+
http_options[:body][:verified_token] = Crypt.hash(token) unless token.nil?
|
288
|
+
|
337
289
|
submit_request("put", "#{@hostname}/verifications/#{params[:id]}/reject.#{@output}",
|
338
|
-
|
290
|
+
http_options)
|
339
291
|
end
|
340
292
|
|
341
293
|
private
|
data/lib/touchpass/crypt.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
|
-
|
2
1
|
module Touchpass
|
3
2
|
class Crypt
|
4
3
|
# Encryption method
|
5
4
|
# Options: :md5, :sha1, :sha256, :sha512
|
6
|
-
|
5
|
+
HASH_CRYPTO_PROVIDER = :sha256
|
6
|
+
ENCRYPTION_ALGORITHM = 'AES-128-CBC'
|
7
7
|
|
8
8
|
def self.salt(length=10)
|
9
9
|
seeds = ('a'..'z').to_a
|
@@ -18,9 +18,32 @@ module Touchpass
|
|
18
18
|
salt_string
|
19
19
|
end
|
20
20
|
|
21
|
-
def self.
|
21
|
+
def self.generate_encryption_key
|
22
|
+
crypt = OpenSSL::Cipher.new(ENCRYPTION_ALGORITHM)
|
23
|
+
crypt.encrypt
|
24
|
+
crypt.random_key
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.cipher(mode, data, key)
|
28
|
+
return nil unless data
|
29
|
+
crypt = OpenSSL::Cipher.new(ENCRYPTION_ALGORITHM).send(mode)
|
30
|
+
crypt.key = key
|
31
|
+
crypt.padding = 1
|
32
|
+
crypt.update(data) << crypt.final
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.encrypt(data, key)
|
36
|
+
cipher(:encrypt, data, key)
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.decrypt(data, key)
|
40
|
+
cipher(:decrypt, data, key)
|
41
|
+
end
|
42
|
+
|
43
|
+
# hex digest
|
44
|
+
def self.hash(string)
|
22
45
|
crypto_provider = nil
|
23
|
-
case
|
46
|
+
case HASH_CRYPTO_PROVIDER
|
24
47
|
when :md5
|
25
48
|
require 'digest/md5' unless defined?(Digest::MD5)
|
26
49
|
crypto_provider = Digest::MD5
|
@@ -37,11 +60,11 @@ module Touchpass
|
|
37
60
|
return crypto_provider.hexdigest(string)
|
38
61
|
end
|
39
62
|
|
40
|
-
def self.
|
63
|
+
def self.read_rsa_key(pem)
|
41
64
|
begin
|
42
65
|
return OpenSSL::PKey::RSA.new(pem)
|
43
66
|
rescue
|
44
|
-
|
67
|
+
warn "Unable to read key."
|
45
68
|
end
|
46
69
|
return nil
|
47
70
|
end
|
data/lib/touchpass/prp.rb
CHANGED
@@ -144,11 +144,14 @@ module Touchpass
|
|
144
144
|
|
145
145
|
# Returns the hashed representation of the bounding coordinates
|
146
146
|
def encrypt(salt=nil)
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
147
|
+
if @bounding_coordinates
|
148
|
+
crypted_1 = encrypt_point(@bounding_coordinates[:top_left], salt)
|
149
|
+
crypted_2 = encrypt_point(@bounding_coordinates[:top_right], salt)
|
150
|
+
crypted_3 = encrypt_point(@bounding_coordinates[:bottom_right], salt)
|
151
|
+
crypted_4 = encrypt_point(@bounding_coordinates[:bottom_left], salt)
|
152
|
+
@crypted_coordinates = crypted_1 + crypted_2 + crypted_3 + crypted_4
|
153
|
+
end
|
154
|
+
|
152
155
|
return @crypted_coordinates
|
153
156
|
end
|
154
157
|
|
@@ -170,7 +173,7 @@ module Touchpass
|
|
170
173
|
# that are coming from 3,240,000 values (ie 1,800*1,800) as opposed to 2 hashes derived from a set of 1,800
|
171
174
|
# possible values.
|
172
175
|
str_to_encrypt = (lat.to_s) + "," + (lng.to_s) + salt.to_s
|
173
|
-
return Touchpass::Crypt.
|
176
|
+
return Touchpass::Crypt.hash(str_to_encrypt)
|
174
177
|
end
|
175
178
|
|
176
179
|
def self.truncate_size(resolution)
|
@@ -11,8 +11,11 @@ module Touchpass
|
|
11
11
|
def get_all(user)
|
12
12
|
http_options = { :body => {}, :headers => { Touchpass::Client::API_KEY_HEADER => Touchpass.api_key } }
|
13
13
|
response = self.class.get("/#{user}/devices.json", http_options)
|
14
|
-
|
14
|
+
|
15
|
+
tp_response = Touchpass::Rp::Response.new(response)
|
16
|
+
tp_response.response = tp_response['devices'] || []
|
17
|
+
tp_response
|
15
18
|
end
|
16
19
|
end
|
17
20
|
end
|
18
|
-
end
|
21
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Touchpass
|
2
|
+
module Rp
|
3
|
+
class Response
|
4
|
+
|
5
|
+
attr_accessor :http_status_code, :response
|
6
|
+
|
7
|
+
def initialize(http_party_response = nil)
|
8
|
+
if http_party_response
|
9
|
+
@http_status_code = http_party_response.code
|
10
|
+
@response = http_party_response.parsed_response
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_h
|
15
|
+
if @response.kind_of?(Hash)
|
16
|
+
@response.merge(:http_status_code => @http_status_code)
|
17
|
+
elsif @http_status_code != 200
|
18
|
+
{ :error => @response, :http_status_code => @http_status_code }
|
19
|
+
else
|
20
|
+
{ :text => @response, :http_status_code => @http_status_code }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def [](key)
|
25
|
+
@response.kind_of?(Hash) ? @response[key] : nil
|
26
|
+
end
|
27
|
+
|
28
|
+
def to_json(options = {})
|
29
|
+
to_h.to_json(options)
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Touchpass
|
2
|
+
module Rp
|
3
|
+
class Verification
|
4
|
+
include HTTParty
|
5
|
+
#debug_output
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
self.class.base_uri Touchpass.base_uri
|
9
|
+
end
|
10
|
+
|
11
|
+
def create(to_party, options={})
|
12
|
+
http_options = { :body => { :to_party => to_party }, :headers => api_key_header }
|
13
|
+
|
14
|
+
# Defines which application will be used to handle the verification
|
15
|
+
# (the default is to use the standalone app, or the first app registered)
|
16
|
+
http_options[:body][:to_app_id] = Touchpass.app_id if Touchpass.app_id
|
17
|
+
# puts "Touchpass.app_id: #{Touchpass.app_id}"
|
18
|
+
|
19
|
+
# Get the verifying party devices so we can encrypt message/prp using the devices public key
|
20
|
+
device = Touchpass::Rp::Device.new
|
21
|
+
vp_devices = device.get_all(to_party).response
|
22
|
+
# TODO: vp_devices can be empty here, in which case verification creation will fail.
|
23
|
+
|
24
|
+
# Create verification object
|
25
|
+
verification = Touchpass::Verification.new(vp_devices, options)
|
26
|
+
http_options[:body].merge!(verification.http_params)
|
27
|
+
|
28
|
+
response = self.class.post("/verifications.json", http_options)
|
29
|
+
|
30
|
+
return Touchpass::Rp::Response.new(response)
|
31
|
+
end
|
32
|
+
|
33
|
+
def cancel(id)
|
34
|
+
http_options = { :body => {}, :headers => api_key_header }
|
35
|
+
response = self.class.put("/verifications/#{id}/cancel.json", http_options)
|
36
|
+
return Touchpass::Rp::Response.new(response)
|
37
|
+
end
|
38
|
+
|
39
|
+
def show(id)
|
40
|
+
http_options = { :body => {}, :headers => api_key_header }
|
41
|
+
response = self.class.get("/verifications/#{id}.json", http_options)
|
42
|
+
return Touchpass::Rp::Response.new(response)
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def api_key_header
|
48
|
+
{ Touchpass::Client::API_KEY_HEADER => Touchpass.api_key }
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -1,112 +1,145 @@
|
|
1
1
|
module Touchpass
|
2
|
-
|
3
|
-
class Verification
|
4
|
-
include HTTParty
|
5
|
-
#debug_output
|
2
|
+
class Verification
|
6
3
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
def create(to_party, options={})
|
12
|
-
http_options = { :body => {:to_party => to_party}, :headers => api_key_header }
|
13
|
-
|
14
|
-
# Get the verifying party devices so we can encrypt message/prp using the devices public key
|
15
|
-
device = Touchpass::Rp::Device.new
|
16
|
-
vp_devices = device.get_all(to_party)
|
17
|
-
|
18
|
-
# Generate token
|
19
|
-
token = Touchpass::Crypt.salt
|
20
|
-
hashed_token = Touchpass::Crypt.encrypt(token)
|
21
|
-
http_options[:body][:claimed_token] = hashed_token
|
22
|
-
|
23
|
-
# Encrypt token using verifying_party (to_party) devices
|
24
|
-
create_crypted_tokens(token, vp_devices, http_options)
|
25
|
-
|
26
|
-
# Generate Claimed PRP (for Location Verification)
|
27
|
-
create_prp(options[:address], vp_devices, http_options)
|
28
|
-
|
29
|
-
# Generate Claimed PRP (for Location Verification)
|
30
|
-
create_crypted_messages(options[:message], vp_devices, http_options)
|
4
|
+
attr_reader :crypted_salts, :crypted_tokens, :crypted_messages
|
5
|
+
attr_reader :claimed_token
|
6
|
+
attr_reader :location_verification, :claimed_prp, :resolution
|
31
7
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
8
|
+
def initialize(vp_devices, options = {})
|
9
|
+
|
10
|
+
# Generate token
|
11
|
+
token = Crypt.salt
|
12
|
+
hashed_token = Crypt.hash(token)
|
13
|
+
@claimed_token = hashed_token
|
14
|
+
@vp_devices = vp_devices
|
15
|
+
@crypted_messages = []
|
16
|
+
|
17
|
+
# Encrypt message using each verifying party's (to_party) device public keys
|
18
|
+
add_message(options[:message]) if !options[:message].nil?
|
19
|
+
|
20
|
+
# Encrypt post-verification message, if present
|
21
|
+
if !options[:message_post_verification].nil?
|
22
|
+
add_message(options[:message_post_verification],
|
23
|
+
:requires_verification => true,
|
24
|
+
:scratch_to_reveal => options[:scratch_to_reveal])
|
40
25
|
end
|
41
26
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
27
|
+
# Encrypt post-verification location message, if present
|
28
|
+
if !options[:message_post_verification_location].nil?
|
29
|
+
add_message(options[:message_post_verification_location],
|
30
|
+
:requires_verification => true,
|
31
|
+
:requires_location_verification => true,
|
32
|
+
:scratch_to_reveal => options[:scratch_to_reveal])
|
46
33
|
end
|
47
34
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
pub_key = device["pub_key"]
|
54
|
-
public_key = Touchpass::Crypt.read_key(pub_key)
|
55
|
-
crypted_token = Base64.encode64(public_key.public_encrypt(token))
|
56
|
-
http_options[:body]["crypted_tokens[#{index}][device_id]"] = device_id
|
57
|
-
http_options[:body]["crypted_tokens[#{index}][value]"] = crypted_token
|
58
|
-
end
|
35
|
+
# allow adding messages from array of hashes (containing message and options)
|
36
|
+
messages = options[:messages]
|
37
|
+
messages = messages.values if messages.kind_of?(Hash)
|
38
|
+
if messages.kind_of?(Array)
|
39
|
+
messages.each { |i| add_message(i[:message], i) }
|
59
40
|
end
|
60
41
|
|
61
|
-
|
62
|
-
|
42
|
+
# Encrypt token using each verifying party's (to_party) device public keys
|
43
|
+
# (only use RSA encryption for the token)
|
44
|
+
@crypted_tokens = crypted_values("crypted_tokens", token, :rsa_only => true)
|
63
45
|
|
64
|
-
|
46
|
+
# Encrypt prp-hash using verifying_party (to_party) devices
|
47
|
+
if !options[:address].nil? # For location verification
|
48
|
+
@location_verification = true
|
65
49
|
|
66
|
-
# Convert address to PRP
|
67
|
-
|
68
|
-
prp =
|
50
|
+
# Convert address to PRP
|
51
|
+
@resolution = options[:resolution] || "LOCAL" # Resolution used to calculate PRP
|
52
|
+
prp = Proximity::PRP.new(:address => options[:address], :resolution => @resolution)
|
53
|
+
# puts prp.print_bbox # for debugging
|
69
54
|
|
70
55
|
# Generate random salt
|
71
|
-
salt =
|
56
|
+
salt = Crypt.salt
|
57
|
+
# puts "Using salt: #{salt}" # for debugging
|
72
58
|
|
73
59
|
# Encrypt PRP using salt
|
74
60
|
claimed_prp = prp.encrypt(salt)
|
75
|
-
|
61
|
+
@claimed_prp = claimed_prp
|
76
62
|
|
77
63
|
# Encrypt salt using verifiying_party (to_party) devices
|
78
|
-
|
79
|
-
devices.each_with_index do |device, index|
|
80
|
-
device_id = device["id"]
|
81
|
-
pub_key = device["pub_key"]
|
82
|
-
public_key = Touchpass::Crypt.read_key(pub_key)
|
83
|
-
crypted_salt = Base64.encode64(public_key.public_encrypt(salt))
|
84
|
-
http_options[:body]["crypted_salts[#{index}][device_id]"] = device_id
|
85
|
-
http_options[:body]["crypted_salts[#{index}][value]"] = crypted_salt
|
86
|
-
end
|
87
|
-
end
|
64
|
+
@crypted_salts = crypted_values("crypted_salts", salt, :rsa_only => true)
|
88
65
|
end
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
def add_message(message, options = {})
|
70
|
+
@crypted_messages ||= []
|
71
|
+
@crypted_messages += crypted_values("crypted_messages", message, options)
|
72
|
+
end
|
89
73
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
74
|
+
# create http parameters
|
75
|
+
def http_params
|
76
|
+
params = {}
|
77
|
+
|
78
|
+
params[:claimed_token] = @claimed_token
|
79
|
+
params[:crypted_messages] = param_hash(@crypted_messages)
|
80
|
+
params[:crypted_tokens] = param_hash(@crypted_tokens)
|
81
|
+
params[:crypted_salts] = param_hash(@crypted_salts)
|
82
|
+
params[:location_verification] = @location_verification
|
83
|
+
params[:resolution] = @resolution
|
84
|
+
params[:claimed_prp] = @claimed_prp
|
85
|
+
|
86
|
+
params
|
87
|
+
end
|
88
|
+
|
89
|
+
private
|
90
|
+
|
91
|
+
def param_hash(values)
|
92
|
+
ret = {}
|
93
|
+
if values.kind_of?(Array)
|
94
|
+
values.each_with_index do |value, i|
|
95
|
+
ret["#{i}"] = value
|
102
96
|
end
|
103
97
|
end
|
98
|
+
ret
|
99
|
+
end
|
100
|
+
|
101
|
+
# generate crypted value attributes for all devices
|
102
|
+
# used for messages and tokens
|
103
|
+
# returns array of hashes, hashes contain :device_id, :value, :key
|
104
|
+
def crypted_values(name, plaintext, options = {})
|
105
|
+
ret = []
|
106
|
+
|
107
|
+
return ret unless @vp_devices && @vp_devices.kind_of?(Array)
|
104
108
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
+
@vp_devices.each do |device|
|
110
|
+
device_id = device["id"]
|
111
|
+
|
112
|
+
# get the RSA public key
|
113
|
+
pub_key_str = device["pub_key"]
|
114
|
+
next unless pub_key_str && pub_key_str.length > 0
|
115
|
+
public_key = Crypt.read_rsa_key(pub_key_str)
|
116
|
+
|
117
|
+
next unless public_key # skip invalid keys
|
118
|
+
|
119
|
+
if options[:rsa_only]
|
120
|
+
# encrypt plaintext using rsa
|
121
|
+
encrypted_data = public_key.public_encrypt(plaintext)
|
122
|
+
else
|
123
|
+
# encrypt using AES
|
124
|
+
# generate a random key, encrypt plaintext and key
|
125
|
+
key = Touchpass::Crypt.generate_encryption_key
|
126
|
+
encrypted_data = Touchpass::Crypt.encrypt(plaintext, key)
|
127
|
+
encrypted_key = public_key.public_encrypt(key)
|
128
|
+
end
|
109
129
|
|
130
|
+
# Note: some parts of the server code expect keys here to be strings (not symbols)
|
131
|
+
ret.push( {
|
132
|
+
"device_id" => device_id,
|
133
|
+
"value" => Base64.strict_encode64(encrypted_data),
|
134
|
+
"key" => encrypted_key ? Base64.strict_encode64(encrypted_key) : nil,
|
135
|
+
"requires_verification" => options[:requires_verification] ? true : false,
|
136
|
+
"requires_location_verification" => options[:requires_location_verification] ? true : false,
|
137
|
+
"scratch_to_reveal" => options[:scratch_to_reveal] ? true : false,
|
138
|
+
"do_not_keep" => options[:do_not_keep] ? true : false
|
139
|
+
})
|
140
|
+
end
|
141
|
+
ret
|
110
142
|
end
|
143
|
+
|
111
144
|
end
|
112
|
-
end
|
145
|
+
end
|
data/lib/touchpass/version.rb
CHANGED
data/lib/touchpass.rb
CHANGED
@@ -1,16 +1,27 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
|
+
|
2
3
|
require "touchpass/version"
|
3
4
|
require 'touchpass/prp'
|
4
5
|
require 'touchpass/client'
|
5
6
|
require 'touchpass/crypt'
|
6
7
|
require 'touchpass/key_file_creator'
|
7
8
|
require 'touchpass/verification'
|
8
|
-
require 'touchpass/
|
9
|
+
require 'touchpass/rp/response'
|
10
|
+
require 'touchpass/rp/verification'
|
11
|
+
require 'touchpass/rp/device'
|
9
12
|
|
10
13
|
module Touchpass
|
11
|
-
|
14
|
+
if defined?(Rails) && Rails::VERSION::MAJOR == 3
|
15
|
+
require 'engine'
|
16
|
+
class Engine < Rails::Engine
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
DEFAULT_HOST = "localhost"
|
21
|
+
DEFAULT_PORT = "3000"
|
22
|
+
DEFAULT_USE_HTTPS = true
|
12
23
|
|
13
|
-
config = [:username, :api_key, :use_https, :host, :port, :resolution, :location_verification, :verified_message, :unverified_message]
|
24
|
+
config = [:username, :api_key, :use_https, :host, :port, :resolution, :location_verification, :verified_message, :unverified_message, :app_id]
|
14
25
|
|
15
26
|
# define getter and setter methods for each config
|
16
27
|
# normally we can use mattr_accessor :key for shortcut, but this only available in Rails environment
|
@@ -20,6 +31,13 @@ module Touchpass
|
|
20
31
|
module_eval( "def self.#{symbol.to_s}=(val) @@#{symbol.to_s} = val; end" )
|
21
32
|
end
|
22
33
|
|
34
|
+
begin
|
35
|
+
self.host = DEFAULT_HOST
|
36
|
+
self.port = DEFAULT_PORT
|
37
|
+
self.use_https = DEFAULT_USE_HTTPS
|
38
|
+
self.api_key = "" # prevents weird bug with HTTParty 'undefined method 'strip' for nil:NilClass'
|
39
|
+
end
|
40
|
+
|
23
41
|
# Default way to setup Touchpass. Run rails generate touchpass_install to create
|
24
42
|
# a fresh initializer with all configuration values.
|
25
43
|
def self.setup
|
@@ -28,16 +46,20 @@ module Touchpass
|
|
28
46
|
|
29
47
|
def self.base_uri
|
30
48
|
tp_base_uri = Touchpass.host
|
31
|
-
|
32
|
-
|
49
|
+
port = Touchpass.port.to_s
|
50
|
+
unless port.empty? # .present? is a rails add-on
|
51
|
+
tp_base_uri += ":#{port}"
|
33
52
|
end
|
34
53
|
protocol = Touchpass.use_https ? "https://" : "http://"
|
35
54
|
tp_base_uri = protocol + tp_base_uri
|
36
55
|
end
|
37
56
|
|
38
57
|
module Role
|
58
|
+
ADMIN = "admin"
|
39
59
|
RELYING_PARTY = "relying_party"
|
40
60
|
VERIFYING_PARTY = "verifying_party"
|
61
|
+
|
62
|
+
ROLES = [ADMIN, VERIFYING_PARTY, RELYING_PARTY]
|
41
63
|
end
|
42
64
|
|
43
65
|
module MessagingType
|