touchpass 0.0.8.1 → 0.0.8.16
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.
- 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
|