smaak 0.2.1 → 0.2.2
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 +4 -4
- data/.travis.yml +4 -0
- data/README.md +7 -2
- data/Rakefile +7 -1
- data/lib/smaak.rb +9 -9
- data/lib/smaak/adaptors/net_http_adaptor.rb +2 -2
- data/lib/smaak/adaptors/rack_adaptor.rb +18 -10
- data/lib/smaak/associate.rb +6 -6
- data/lib/smaak/auth_message.rb +35 -15
- data/lib/smaak/cavage_04.rb +23 -18
- data/lib/smaak/client.rb +25 -13
- data/lib/smaak/crypto.rb +2 -2
- data/lib/smaak/server.rb +83 -31
- data/lib/smaak/smaak_service.rb +1 -1
- data/lib/smaak/utils.rb +1 -1
- data/lib/smaak/version.rb +1 -1
- data/smaak.gemspec +3 -2
- data/spec/lib/smaak/adaptors/net_http_adaptor_spec.rb +3 -3
- data/spec/lib/smaak/auth_message_spec.rb +11 -11
- data/spec/lib/smaak/cavage_04_spec.rb +9 -9
- data/spec/lib/smaak/crypto_spec.rb +14 -14
- data/spec/lib/smaak/server_spec.rb +3 -4
- data/spec/lib/smaak/smaak_service_spec.rb +3 -3
- data/spec/lib/smaak_spec.rb +34 -34
- data/spec/spec_helper.rb +13 -8
- metadata +8 -23
- data/spec/mock/request.rb +0 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7e314a8921be1280f317cf55cd6a1a0120fd58cc
|
4
|
+
data.tar.gz: a69c88890f1a0df5a99343e9bc1cccd6f3d69388
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 79c97ce8e16c9bb1150428a424bc4480092a26ea195d1824327230b8f06cc0e737d5e64dac4f591ded660cf60b4ac265e6f961c6faeb4ad1b4a7f49a82cca8f8
|
7
|
+
data.tar.gz: 5dc1ea24854f06c8cc5e6a7ca9763cde370aff76b24abca955447f773dc23d9b96267cf99a3fb450fbe62af8d6deaa257680288add653fbecad355a8e096f914
|
data/.travis.yml
ADDED
data/README.md
CHANGED
@@ -1,5 +1,10 @@
|
|
1
1
|
# Smaak
|
2
2
|
|
3
|
+
[](https://badge.fury.io/rb/smaak)
|
4
|
+
[](https://travis-ci.org/evangraan/smaak)
|
5
|
+
[](https://coveralls.io/github/evangraan/smaak?branch=master)
|
6
|
+
[](https://www.codacy.com/app/ernst-van-graan/smaak?utm_source=github.com&utm_medium=referral&utm_content=evangraan/smaak&utm_campaign=Badge_Grade)
|
7
|
+
|
3
8
|
This gems caters for both client and server sides of a signed message interaction over HTTP implementing RFC2617 Digest Access Authentication as well as IETF draft-cavage-http-signatures-04, extended with 'x-smaak-recipient', 'x-smaak-identifier', 'x-smaak-route-info', 'x-smaak-psk', 'x-smaak-expires' and 'x-smaak-nonce' headers. The following compromises are protected against as specified: Man in the middle (header and payload signature, as well as body digest) / snooping (message body encryption), Replay (nonce + expiry), Forgery (signature), Masquerading (identifier and signature), Forwarding / Unintended recipient (recipient pub key check), Clear-text password compromise (MD5 pre-shared key, obfuscated), lack of password (pre-shared key), Message fabrication (associations are purpose-fully provisioned to known associates.)
|
4
9
|
|
5
10
|
## Smaak mechanism
|
@@ -22,7 +27,7 @@ In order for smaak to utilize adaptors and technology you choose, ensure to requ
|
|
22
27
|
|
23
28
|
### Example Server
|
24
29
|
|
25
|
-
A Smaak::Server operates on an instance of an HTTP request received. The Smaak module can be told about different request technology implementations by providing an adaptor to a request technology (Smaak
|
30
|
+
A Smaak::Server operates on an instance of an HTTP request received. The Smaak module can be told about different request technology implementations by providing an adaptor to a request technology (Smaak.add_request_adaptor). The gem ships with a Rack::Request adaptor. Call Smaak.create_adaptor with your request to get an instance of an adaptor.
|
26
31
|
|
27
32
|
A Smaak::Server needs to keep track of nonces received in the fresh-ness interval of requests. To make this easy, you can extend Smaak::SmaakService. Override the configure_services method to provide your server's public key, private key and associations. Smaak::SmaakService provides a cache of received nonces checked against the freshness interval.
|
28
33
|
|
@@ -51,7 +56,7 @@ trust stores as follows. USE WITH CAUTION:
|
|
51
56
|
|
52
57
|
### Example Client
|
53
58
|
|
54
|
-
A Smaak::Client operates on an instance of an HTTP request. The Smaak module can be told about different request technology implementations by providing an adaptor to a request technology (Smaak
|
59
|
+
A Smaak::Client operates on an instance of an HTTP request. The Smaak module can be told about different request technology implementations by providing an adaptor to a request technology (Smaak.add_request_adaptor). The gem ships with a Net::HTTP adaptor. Call Smaak.create_adaptor with your request to get an instance of an adaptor.
|
55
60
|
|
56
61
|
# The user requested some data which requires my service to talk to another, a Smaak::Server
|
57
62
|
class SecureController
|
data/Rakefile
CHANGED
data/lib/smaak.rb
CHANGED
@@ -34,7 +34,7 @@ module Smaak
|
|
34
34
|
@@adaptors.each do |r, a|
|
35
35
|
return a.new(request) if request.is_a? r
|
36
36
|
end
|
37
|
-
raise ArgumentError.new("Unknown request class #{request.class}. Add an adaptor using Smaak
|
37
|
+
raise ArgumentError.new("Unknown request class #{request.class}. Add an adaptor using Smaak.add_request_adaptor.")
|
38
38
|
end
|
39
39
|
|
40
40
|
def self.select_specification(adaptor, specification)
|
@@ -44,18 +44,18 @@ module Smaak
|
|
44
44
|
end
|
45
45
|
|
46
46
|
def self.sign_authorization_headers(key, auth_message, adaptor, specification = Smaak::Cavage04::SPECIFICATION)
|
47
|
-
specification = Smaak
|
47
|
+
specification = Smaak.select_specification(adaptor, specification)
|
48
48
|
|
49
49
|
signature_headers = specification.compile_signature_headers(auth_message)
|
50
|
-
signature_data = Smaak::Crypto
|
51
|
-
signature = Smaak::Crypto
|
50
|
+
signature_data = Smaak::Crypto.sign_data(signature_headers, key)
|
51
|
+
signature = Smaak::Crypto.encode64(signature_data)
|
52
52
|
specification.compile_auth_header(signature)
|
53
53
|
specification.adaptor
|
54
54
|
end
|
55
55
|
|
56
56
|
def self.verify_authorization_headers(adaptor, pubkey)
|
57
57
|
raise ArgumentError.new("Key is required") if pubkey.nil?
|
58
|
-
signature_headers, signature = Smaak
|
58
|
+
signature_headers, signature = Smaak.get_signature_data_from_request(adaptor)
|
59
59
|
if signature.nil?
|
60
60
|
puts "[smaak error]: could not extract signature"
|
61
61
|
return false
|
@@ -64,20 +64,20 @@ module Smaak
|
|
64
64
|
puts "[smaak error]: could not extract signature headers"
|
65
65
|
return false
|
66
66
|
end
|
67
|
-
verified = Smaak::Crypto
|
68
|
-
puts "[smaak error]: verification of headers and signature using pubkey failed"
|
67
|
+
verified = Smaak::Crypto.verify_signature(signature, Smaak::Crypto.encode64(signature_headers), pubkey)
|
68
|
+
puts "[smaak error]: verification of headers and signature using pubkey failed" unless verified
|
69
69
|
verified
|
70
70
|
end
|
71
71
|
|
72
72
|
private
|
73
73
|
|
74
74
|
def self.get_signature_data_from_request(adaptor, specification = Smaak::Cavage04::SPECIFICATION)
|
75
|
-
specification = Smaak
|
75
|
+
specification = Smaak.select_specification(adaptor, specification)
|
76
76
|
|
77
77
|
signature_headers = specification.extract_signature_headers
|
78
78
|
signature = specification.extract_signature
|
79
79
|
|
80
|
-
return signature_headers, Smaak::Crypto
|
80
|
+
return signature_headers, Smaak::Crypto.decode64(signature)
|
81
81
|
end
|
82
82
|
end
|
83
83
|
|
@@ -7,12 +7,12 @@ module Smaak
|
|
7
7
|
attr_reader :request
|
8
8
|
|
9
9
|
def initialize(request)
|
10
|
-
raise ArgumentError.new("Must provide a Net::HTTPRequest")
|
10
|
+
raise ArgumentError.new("Must provide a Net::HTTPRequest") unless request.is_a? Net::HTTPRequest
|
11
11
|
@request = request
|
12
12
|
end
|
13
13
|
|
14
14
|
def set_header(header, value)
|
15
|
-
raise ArgumentError.new("Header must be a non-blank string")
|
15
|
+
raise ArgumentError.new("Header must be a non-blank string") unless Smaak::Utils.non_blank_string?(header)
|
16
16
|
@request[header] = value
|
17
17
|
end
|
18
18
|
|
@@ -6,20 +6,13 @@ module Smaak
|
|
6
6
|
attr_reader :request
|
7
7
|
|
8
8
|
def initialize(request)
|
9
|
-
raise ArgumentError.new("Must provide a Rack::Request")
|
9
|
+
raise ArgumentError.new("Must provide a Rack::Request") unless request.is_a? Rack::Request
|
10
10
|
@request = request
|
11
11
|
end
|
12
12
|
|
13
13
|
def header(header)
|
14
|
-
raise ArgumentError.new("Header must be a non-blank string")
|
15
|
-
|
16
|
-
value = @request.env["CONTENT_LENGTH"]
|
17
|
-
value = 0 if value.nil?
|
18
|
-
return value
|
19
|
-
end
|
20
|
-
return @request.env["HTTP_HOST"].split(':')[0] if not @request.env["HTTP_HOST"].nil? and header == "host"
|
21
|
-
return value = @request.env["REQUEST_METHOD"] if header == "request-method"
|
22
|
-
return @request.env["HTTP_#{header.upcase.gsub("-", "_")}"]
|
14
|
+
raise ArgumentError.new("Header must be a non-blank string") unless Smaak::Utils.non_blank_string?(header)
|
15
|
+
match_header(header)
|
23
16
|
end
|
24
17
|
|
25
18
|
def method
|
@@ -33,5 +26,20 @@ module Smaak
|
|
33
26
|
def body
|
34
27
|
@request.body
|
35
28
|
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def match_header(header)
|
33
|
+
return content_length if header == "content-length"
|
34
|
+
return @request.env["HTTP_HOST"].split(':')[0] if (not @request.env["HTTP_HOST"].nil?) and (header == "host")
|
35
|
+
return @request.env["REQUEST_METHOD"] if header == "request-method"
|
36
|
+
return @request.env["HTTP_#{header.upcase.gsub("-", "_")}"]
|
37
|
+
end
|
38
|
+
|
39
|
+
def content_length
|
40
|
+
value = @request.env["CONTENT_LENGTH"]
|
41
|
+
value = 0 if value.nil?
|
42
|
+
return value
|
43
|
+
end
|
36
44
|
end
|
37
45
|
end
|
data/lib/smaak/associate.rb
CHANGED
@@ -19,13 +19,13 @@ module Smaak
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def set_token_life(token_life)
|
22
|
-
raise ArgumentError.new("Token life has to be a positive number of seconds")
|
22
|
+
raise ArgumentError.new("Token life has to be a positive number of seconds") unless validate_token_life(token_life)
|
23
23
|
@token_life = token_life
|
24
24
|
end
|
25
25
|
|
26
26
|
def add_association(identifier, key, psk, encrypt = false)
|
27
27
|
the_key = key.is_a?(String) ? OpenSSL::PKey::RSA.new(key) : key
|
28
|
-
raise ArgumentError.new("Key needs to be valid")
|
28
|
+
raise ArgumentError.new("Key needs to be valid") unless validate_key(the_key)
|
29
29
|
@association_store[identifier] = { 'public_key' => the_key, 'psk' => psk, 'encrypt' => encrypt }
|
30
30
|
|
31
31
|
rescue OpenSSL::PKey::RSAError
|
@@ -36,7 +36,7 @@ module Smaak
|
|
36
36
|
|
37
37
|
def adapt_rsa_key(key)
|
38
38
|
the_key = key.is_a?(String) ? OpenSSL::PKey::RSA.new(key) : key
|
39
|
-
raise ArgumentError.new("Key needs to be valid")
|
39
|
+
raise ArgumentError.new("Key needs to be valid") unless validate_key(the_key)
|
40
40
|
the_key
|
41
41
|
end
|
42
42
|
|
@@ -45,14 +45,14 @@ module Smaak
|
|
45
45
|
def validate_key(key)
|
46
46
|
return false if key.nil?
|
47
47
|
return false if key.is_a? String and key.empty?
|
48
|
-
return false
|
48
|
+
return false unless key.is_a? OpenSSL::PKey::RSA
|
49
49
|
true
|
50
50
|
end
|
51
51
|
|
52
52
|
def validate_token_life(token_life)
|
53
53
|
return false if token_life.nil?
|
54
|
-
return false
|
55
|
-
return false
|
54
|
+
return false unless token_life.is_a? Integer
|
55
|
+
return false unless token_life > 0
|
56
56
|
true
|
57
57
|
end
|
58
58
|
end
|
data/lib/smaak/auth_message.rb
CHANGED
@@ -11,37 +11,57 @@ module Smaak
|
|
11
11
|
attr_reader :encrypt
|
12
12
|
|
13
13
|
def self.create(recipient_public_key, psk, token_life, identifier, route_info = "", encrypt = false)
|
14
|
-
nonce = Smaak::Crypto
|
14
|
+
nonce = Smaak::Crypto.generate_nonce
|
15
15
|
expires = Time.now.to_i + token_life
|
16
|
-
#Must obfuscate PSK. AuthMessage must always have an obfuscated PSK
|
17
|
-
psk = Smaak::Crypto
|
18
|
-
AuthMessage
|
16
|
+
# Must obfuscate PSK. AuthMessage must always have an obfuscated PSK
|
17
|
+
psk = Smaak::Crypto.obfuscate_psk(psk)
|
18
|
+
AuthMessage.build(recipient_public_key, psk, expires, identifier, route_info, nonce, encrypt)
|
19
19
|
end
|
20
20
|
|
21
21
|
def self.build(recipient_public_key, psk, expires, identifier, route_info, nonce, encrypt = false)
|
22
|
-
#No need to obfuscate PSK. Off the wire we should always expect an obfuscated PSK
|
22
|
+
# No need to obfuscate PSK. Off the wire we should always expect an obfuscated PSK
|
23
23
|
AuthMessage.new(identifier, route_info, nonce, expires, psk, recipient_public_key, encrypt)
|
24
24
|
end
|
25
25
|
|
26
26
|
def initialize(identifier, route_info, nonce, expires, psk, recipient_public_key, encrypt)
|
27
|
+
set_and_validate_identifier(identifier)
|
28
|
+
set_and_validate_route_info(route_info)
|
29
|
+
set_and_validate_nonce(nonce)
|
30
|
+
set_and_validate_expires(expires)
|
31
|
+
set_recipient(recipient_public_key)
|
32
|
+
set_psk(psk)
|
33
|
+
set_encrypt(encrypt)
|
34
|
+
end
|
35
|
+
|
36
|
+
def set_and_validate_identifier(identifier)
|
27
37
|
raise ArgumentError.new("Message must have a valid identifier set") if identifier.nil? or identifier.empty?
|
28
|
-
raise ArgumentError.new("Message must have a valid route information set") if route_info.nil?
|
29
38
|
@identifier = identifier
|
30
39
|
@identifier.freeze
|
31
|
-
|
40
|
+
end
|
32
41
|
|
42
|
+
def set_and_validate_route_info(route_info)
|
43
|
+
raise ArgumentError.new("Message must have a valid route information set") if route_info.nil?
|
44
|
+
@route_info = route_info
|
33
45
|
@route_info.freeze
|
46
|
+
end
|
34
47
|
|
35
|
-
|
48
|
+
def set_and_validate_nonce(nonce)
|
49
|
+
raise ArgumentError.new("Message must have a valid nonce set") unless validate_nonce(nonce)
|
36
50
|
@nonce = nonce
|
37
51
|
@nonce.freeze
|
52
|
+
end
|
38
53
|
|
54
|
+
def set_and_validate_expires(expires)
|
55
|
+
raise ArgumentError.new("Message must have a valid expiry set") unless validate_expiry(expires)
|
56
|
+
@expires = expires
|
57
|
+
end
|
58
|
+
|
59
|
+
def set_recipient(recipient_public_key)
|
39
60
|
@recipient = recipient_public_key
|
40
|
-
|
61
|
+
end
|
41
62
|
|
42
|
-
|
43
|
-
@
|
44
|
-
set_encrypt(encrypt)
|
63
|
+
def set_psk(psk)
|
64
|
+
@psk = psk
|
45
65
|
end
|
46
66
|
|
47
67
|
def set_encrypt(encrypt)
|
@@ -56,7 +76,7 @@ module Smaak
|
|
56
76
|
def psk_match?(psk)
|
57
77
|
return false if psk.nil?
|
58
78
|
return false if @psk.nil?
|
59
|
-
@psk == Smaak::Crypto
|
79
|
+
@psk == Smaak::Crypto.obfuscate_psk(psk)
|
60
80
|
end
|
61
81
|
|
62
82
|
def intended_for_recipient?(pubkey)
|
@@ -66,7 +86,7 @@ module Smaak
|
|
66
86
|
end
|
67
87
|
|
68
88
|
def verify(psk)
|
69
|
-
return false
|
89
|
+
return false unless psk_match?(psk)
|
70
90
|
true
|
71
91
|
end
|
72
92
|
|
@@ -83,7 +103,7 @@ module Smaak
|
|
83
103
|
|
84
104
|
def validate_expiry(expires)
|
85
105
|
return false if expires.nil?
|
86
|
-
return false
|
106
|
+
return false unless (expires.to_i > 0)
|
87
107
|
true
|
88
108
|
|
89
109
|
rescue
|
data/lib/smaak/cavage_04.rb
CHANGED
@@ -9,7 +9,7 @@ module Smaak
|
|
9
9
|
def initialize(adaptor)
|
10
10
|
raise ArgumentError.new("Must provide a valid request adaptor") if adaptor.nil?
|
11
11
|
@adaptor = adaptor
|
12
|
-
@headers_to_be_signed = Smaak::Cavage04
|
12
|
+
@headers_to_be_signed = Smaak::Cavage04.headers_to_be_signed + Smaak.headers_to_be_signed
|
13
13
|
end
|
14
14
|
|
15
15
|
def self.headers_to_be_signed
|
@@ -21,9 +21,9 @@ module Smaak
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def compile_auth_header(signature)
|
24
|
-
raise ArgumentError.new("invalid signature")
|
24
|
+
raise ArgumentError.new("invalid signature") unless Smaak::Utils.non_blank_string?(signature)
|
25
25
|
ordered_headers = ""
|
26
|
-
@adaptor.each_header do |header,
|
26
|
+
@adaptor.each_header do |header, _value|
|
27
27
|
ordered_headers = "#{ordered_headers} #{header}" if @headers_to_be_signed.include?(header)
|
28
28
|
end
|
29
29
|
ordered_headers = ordered_headers[1..ordered_headers.size]
|
@@ -31,20 +31,7 @@ module Smaak
|
|
31
31
|
end
|
32
32
|
|
33
33
|
def compile_signature_headers(auth_message)
|
34
|
-
|
35
|
-
@adaptor.set_header("authorization", "")
|
36
|
-
@adaptor.set_header("host", "#{@adaptor.host}")
|
37
|
-
@adaptor.set_header("date", "#{gmt_now}")
|
38
|
-
@adaptor.set_header("digest", "SHA-256=#{Digest::SHA256.hexdigest(body)}")
|
39
|
-
@adaptor.set_header("x-smaak-recipient", "#{Smaak::Crypto::encode64(auth_message.recipient)}")
|
40
|
-
@adaptor.set_header("x-smaak-identifier", "#{auth_message.identifier}")
|
41
|
-
@adaptor.set_header("x-smaak-route-info", "#{auth_message.route_info}")
|
42
|
-
@adaptor.set_header("x-smaak-psk", "#{auth_message.psk}")
|
43
|
-
@adaptor.set_header("x-smaak-expires", "#{auth_message.expires}")
|
44
|
-
@adaptor.set_header("x-smaak-nonce", "#{auth_message.nonce}")
|
45
|
-
@adaptor.set_header("x-smaak-encrypt", "#{auth_message.encrypt}")
|
46
|
-
@adaptor.set_header("content-type", "text/plain")
|
47
|
-
@adaptor.set_header("content-length", "#{body.size}")
|
34
|
+
set_adaptor_headers(auth_message)
|
48
35
|
|
49
36
|
signature_headers = ""
|
50
37
|
@adaptor.each_header do |header, value|
|
@@ -68,6 +55,7 @@ module Smaak
|
|
68
55
|
@adaptor.header("authorization") =~ /signature=\"([^"]*)\"/
|
69
56
|
$1
|
70
57
|
end
|
58
|
+
|
71
59
|
private
|
72
60
|
|
73
61
|
def gmt_now
|
@@ -75,11 +63,28 @@ module Smaak
|
|
75
63
|
end
|
76
64
|
|
77
65
|
def append_header(header_list, header)
|
78
|
-
|
66
|
+
"#{header_list}\n#{header}"
|
79
67
|
end
|
80
68
|
|
81
69
|
def prepend_header(header, value, signature_headers)
|
82
70
|
"#{header}: #{value}#{signature_headers}"
|
83
71
|
end
|
72
|
+
|
73
|
+
def set_adaptor_headers(auth_message)
|
74
|
+
body = @adaptor.body.nil? ? "" : @adaptor.body
|
75
|
+
@adaptor.set_header("authorization", "")
|
76
|
+
@adaptor.set_header("host", "#{@adaptor.host}")
|
77
|
+
@adaptor.set_header("date", "#{gmt_now}")
|
78
|
+
@adaptor.set_header("digest", "SHA-256=#{Digest::SHA256.hexdigest(body)}")
|
79
|
+
@adaptor.set_header("x-smaak-recipient", "#{Smaak::Crypto.encode64(auth_message.recipient)}")
|
80
|
+
@adaptor.set_header("x-smaak-identifier", "#{auth_message.identifier}")
|
81
|
+
@adaptor.set_header("x-smaak-route-info", "#{auth_message.route_info}")
|
82
|
+
@adaptor.set_header("x-smaak-psk", "#{auth_message.psk}")
|
83
|
+
@adaptor.set_header("x-smaak-expires", "#{auth_message.expires}")
|
84
|
+
@adaptor.set_header("x-smaak-nonce", "#{auth_message.nonce}")
|
85
|
+
@adaptor.set_header("x-smaak-encrypt", "#{auth_message.encrypt}")
|
86
|
+
@adaptor.set_header("content-type", "text/plain")
|
87
|
+
@adaptor.set_header("content-length", "#{body.size}")
|
88
|
+
end
|
84
89
|
end
|
85
90
|
end
|
data/lib/smaak/client.rb
CHANGED
@@ -18,7 +18,7 @@ module Smaak
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def set_identifier(identifier)
|
21
|
-
raise ArgumentError.new("Invalid identifier")
|
21
|
+
raise ArgumentError.new("Invalid identifier") unless Smaak::Utils.non_blank_string?(identifier)
|
22
22
|
@identifier = identifier
|
23
23
|
end
|
24
24
|
|
@@ -28,12 +28,12 @@ module Smaak
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def sign_request(associate_identifier, adaptor)
|
31
|
-
raise ArgumentError.new("Associate invalid")
|
31
|
+
raise ArgumentError.new("Associate invalid") unless validate_associate(associate_identifier)
|
32
32
|
associate = @association_store[associate_identifier]
|
33
33
|
raise ArgumentError.new("Invalid adaptor") if adaptor.nil?
|
34
34
|
auth_message = Smaak::AuthMessage.create(associate['public_key'].export, associate['psk'], @token_life, @identifier, @route_info, associate['encrypt'])
|
35
|
-
adaptor.body = Smaak::Crypto
|
36
|
-
|
35
|
+
adaptor.body = Smaak::Crypto.encrypt(adaptor.body, associate['public_key']) if auth_message.encrypt
|
36
|
+
Smaak.sign_authorization_headers(@key, auth_message, adaptor, Smaak::Cavage04::SPECIFICATION)
|
37
37
|
end
|
38
38
|
|
39
39
|
def get(identifier, uri, body, ssl = false, ssl_verify = OpenSSL::SSL::VERIFY_PEER)
|
@@ -53,23 +53,35 @@ module Smaak
|
|
53
53
|
end
|
54
54
|
|
55
55
|
def connect(connector, identifier, uri, body, ssl, ssl_verify)
|
56
|
+
url, http = build_http(uri, ssl, ssl_verify)
|
57
|
+
req = build_request(connector, url, body, identifier)
|
58
|
+
request_and_respond(http, req, identifier)
|
59
|
+
|
60
|
+
rescue => ex
|
61
|
+
puts "[smaak error] request to associate failed"
|
62
|
+
throw ex
|
63
|
+
end
|
64
|
+
|
65
|
+
def build_http(uri, ssl, ssl_verify)
|
56
66
|
url = URI.parse(uri)
|
57
67
|
http = Net::HTTP.new(url.host, url.port)
|
58
68
|
http.use_ssl = ssl
|
59
69
|
http.verify_mode = ssl_verify
|
70
|
+
return url, http
|
71
|
+
end
|
72
|
+
|
73
|
+
def build_request(connector, url, body, identifier)
|
60
74
|
req = connector.new(url.to_s)
|
61
75
|
req.body = body
|
62
|
-
adaptor = Smaak
|
63
|
-
|
76
|
+
adaptor = Smaak.create_adaptor(req)
|
77
|
+
(sign_request(identifier, adaptor)).request
|
78
|
+
end
|
79
|
+
|
80
|
+
def request_and_respond(http, req, identifier)
|
64
81
|
response = http.request(req)
|
65
|
-
|
66
|
-
|
67
|
-
puts "[smaak error]: response from #{identifier} was #{response.code}" if not response.code[0] == '2'
|
82
|
+
response.body = Smaak::Crypto.decrypt(response.body, @key) if encrypt_associate?(identifier) and response.code[0] == '2'
|
83
|
+
puts "[smaak error]: response from #{identifier} was #{response.code}" unless response.code[0] == '2'
|
68
84
|
response
|
69
|
-
|
70
|
-
rescue => ex
|
71
|
-
puts "[smaak error] request to associate failed"
|
72
|
-
throw ex
|
73
85
|
end
|
74
86
|
|
75
87
|
def encrypt_associate?(identifier)
|