smaak 0.2.1 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Gem Version](https://badge.fury.io/rb/smaak.png)](https://badge.fury.io/rb/smaak)
|
4
|
+
[![Build Status](https://travis-ci.org/evangraan/smaak.svg?branch=master)](https://travis-ci.org/evangraan/smaak)
|
5
|
+
[![Coverage Status](https://coveralls.io/repos/github/evangraan/smaak/badge.svg?branch=master)](https://coveralls.io/github/evangraan/smaak?branch=master)
|
6
|
+
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/e7a22dd7299242fcae3f3dda681103f6)](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)
|