ruby_home 0.1.2 → 0.1.3
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 +13 -14
- data/README.md +1 -1
- data/bin/rubyhome +1 -1
- data/lib/ruby_home/accessory_info.rb +33 -72
- data/lib/ruby_home/device_id.rb +0 -2
- data/lib/ruby_home/dns/service.rb +1 -6
- data/lib/ruby_home/dns/text_record.rb +0 -2
- data/lib/ruby_home/factories/accessory_factory.rb +0 -5
- data/lib/ruby_home/factories/characteristic_factory.rb +0 -3
- data/lib/ruby_home/factories/templates/characteristic_template.rb +0 -1
- data/lib/ruby_home/factories/templates/service_template.rb +0 -2
- data/lib/ruby_home/hap/accessory.rb +2 -2
- data/lib/ruby_home/hap/characteristic.rb +2 -2
- data/lib/ruby_home/hap/crypto/chacha20poly1305.rb +0 -4
- data/lib/ruby_home/hap/crypto/hkdf.rb +0 -2
- data/lib/ruby_home/hap/http_decryption.rb +5 -6
- data/lib/ruby_home/hap/http_encryption.rb +21 -11
- data/lib/ruby_home/hap/service.rb +0 -3
- data/lib/ruby_home/hap/tlv.rb +28 -21
- data/lib/ruby_home/hex_helper.rb +15 -0
- data/lib/ruby_home/http/application.rb +24 -19
- data/lib/ruby_home/http/controllers/accessories_controller.rb +1 -2
- data/lib/ruby_home/http/controllers/application_controller.rb +60 -13
- data/lib/ruby_home/http/controllers/characteristics_controller.rb +2 -3
- data/lib/ruby_home/http/controllers/pair_setups_controller.rb +41 -78
- data/lib/ruby_home/http/controllers/pair_verifies_controller.rb +22 -24
- data/lib/ruby_home/http/controllers/pairings_controller.rb +8 -8
- data/lib/ruby_home/http/hap_request.rb +2 -6
- data/lib/ruby_home/http/hap_response.rb +2 -8
- data/lib/ruby_home/http/hap_server.rb +7 -12
- data/lib/ruby_home/http/serializers/object_serializer.rb +0 -2
- data/lib/ruby_home/http/services/start_srp_service.rb +46 -0
- data/lib/ruby_home/http/services/verify_srp_service.rb +55 -0
- data/lib/ruby_home/rack/handler/hap_server.rb +2 -7
- data/lib/ruby_home/version.rb +1 -1
- data/lib/ruby_home/yaml_record.rb +440 -0
- data/lib/ruby_home.rb +45 -6
- data/rubyhome.gemspec +4 -4
- metadata +44 -49
- data/lib/ruby_home/broadcast.rb +0 -31
- data/lib/ruby_home/hap/hex_pad.rb +0 -13
- data/lib/ruby_home/http/cache.rb +0 -30
@@ -1,10 +1,9 @@
|
|
1
1
|
require_relative 'application_controller'
|
2
|
-
require_relative '../serializers/characteristic_value_serializer'
|
3
2
|
|
4
3
|
module RubyHome
|
5
4
|
module HTTP
|
6
5
|
class CharacteristicsController < ApplicationController
|
7
|
-
get '/
|
6
|
+
get '/' do
|
8
7
|
content_type 'application/hap+json'
|
9
8
|
|
10
9
|
if cache[:controller_to_accessory_key] && cache[:accessory_to_controller_key]
|
@@ -21,7 +20,7 @@ module RubyHome
|
|
21
20
|
end
|
22
21
|
end
|
23
22
|
|
24
|
-
put '/
|
23
|
+
put '/' do
|
25
24
|
content_type 'application/hap+json'
|
26
25
|
|
27
26
|
if cache[:controller_to_accessory_key] && cache[:accessory_to_controller_key]
|
@@ -1,81 +1,75 @@
|
|
1
|
-
require 'hkdf'
|
2
|
-
require 'openssl'
|
3
|
-
require 'rbnacl/libsodium'
|
4
|
-
require 'ruby_home-srp'
|
5
|
-
require_relative '../../hap/hex_pad'
|
6
|
-
require_relative '../../hap/tlv'
|
7
1
|
require_relative 'application_controller'
|
8
2
|
|
9
3
|
module RubyHome
|
10
4
|
module HTTP
|
11
5
|
class PairSetupsController < ApplicationController
|
12
|
-
post '/
|
6
|
+
post '/' do
|
13
7
|
content_type 'application/pairing+tlv8'
|
14
8
|
|
15
|
-
case unpack_request[
|
9
|
+
case unpack_request[:state]
|
16
10
|
when 1
|
17
|
-
|
11
|
+
start
|
18
12
|
when 3
|
19
|
-
|
13
|
+
verify
|
20
14
|
when 5
|
21
|
-
|
15
|
+
exchange
|
22
16
|
end
|
23
17
|
end
|
24
18
|
|
25
19
|
private
|
26
20
|
|
27
|
-
def
|
28
|
-
|
29
|
-
password = '031-45-154'
|
21
|
+
def pairing_failed
|
22
|
+
clear_cache
|
30
23
|
|
31
|
-
|
24
|
+
tlv state: 4, error: 2
|
25
|
+
end
|
32
26
|
|
33
|
-
|
34
|
-
|
27
|
+
def start
|
28
|
+
start_srp = StartSRPService.new(
|
29
|
+
username: accessory_info.username,
|
30
|
+
password: accessory_info.password
|
31
|
+
)
|
35
32
|
|
36
|
-
|
37
|
-
store_proof(challenge_and_proof[:proof])
|
33
|
+
cache[:srp_session] = start_srp.proof
|
38
34
|
|
39
|
-
|
40
|
-
'kTLVType_Salt' => [challenge_and_proof[:challenge][:salt]].pack('H*'),
|
41
|
-
'kTLVType_PublicKey' => [challenge_and_proof[:challenge][:B]].pack('H*'),
|
42
|
-
'kTLVType_State' => 2
|
43
|
-
})
|
35
|
+
tlv salt: start_srp.salt_bytes, public_key: start_srp.public_key_bytes, state: 2
|
44
36
|
end
|
45
37
|
|
46
|
-
def
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
38
|
+
def verify
|
39
|
+
verify_srp = VerifySRPService.new(
|
40
|
+
device_proof: unpack_request[:proof],
|
41
|
+
srp_session: cache[:srp_session],
|
42
|
+
public_key: unpack_request[:public_key],
|
43
|
+
)
|
51
44
|
|
52
|
-
|
53
|
-
|
45
|
+
if verify_srp.valid?
|
46
|
+
cache[:session_key] = verify_srp.session_key
|
47
|
+
cache.delete(:srp_session)
|
54
48
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
49
|
+
tlv state: 4, proof: verify_srp.server_proof
|
50
|
+
else
|
51
|
+
pairing_failed
|
52
|
+
end
|
59
53
|
end
|
60
54
|
|
61
|
-
def
|
62
|
-
encrypted_data = unpack_request[
|
55
|
+
def exchange
|
56
|
+
encrypted_data = unpack_request[:encrypted_data]
|
63
57
|
|
64
58
|
hkdf = HAP::Crypto::HKDF.new(info: 'Pair-Setup-Encrypt-Info', salt: 'Pair-Setup-Encrypt-Salt')
|
65
|
-
key = hkdf.encrypt(session_key)
|
59
|
+
key = hkdf.encrypt(cache[:session_key])
|
66
60
|
|
67
61
|
chacha20poly1305ietf = HAP::Crypto::ChaCha20Poly1305.new(key)
|
68
62
|
|
69
|
-
nonce =
|
63
|
+
nonce = HexHelper.pad('PS-Msg05')
|
70
64
|
decrypted_data = chacha20poly1305ietf.decrypt(nonce, encrypted_data)
|
71
65
|
unpacked_decrypted_data = HAP::TLV.read(decrypted_data)
|
72
66
|
|
73
|
-
iosdevicepairingid = unpacked_decrypted_data[
|
74
|
-
iosdevicesignature = unpacked_decrypted_data[
|
75
|
-
iosdeviceltpk = unpacked_decrypted_data[
|
67
|
+
iosdevicepairingid = unpacked_decrypted_data[:identifier]
|
68
|
+
iosdevicesignature = unpacked_decrypted_data[:signature]
|
69
|
+
iosdeviceltpk = unpacked_decrypted_data[:public_key]
|
76
70
|
|
77
71
|
hkdf = HAP::Crypto::HKDF.new(info: 'Pair-Setup-Controller-Sign-Info', salt: 'Pair-Setup-Controller-Sign-Salt')
|
78
|
-
iosdevicex = hkdf.encrypt(session_key)
|
72
|
+
iosdevicex = hkdf.encrypt(cache[:session_key])
|
79
73
|
|
80
74
|
iosdeviceinfo = [
|
81
75
|
iosdevicex.unpack1('H*'),
|
@@ -86,7 +80,7 @@ module RubyHome
|
|
86
80
|
|
87
81
|
if verify_key.verify(iosdevicesignature, [iosdeviceinfo].pack('H*'))
|
88
82
|
hkdf = HAP::Crypto::HKDF.new(info: 'Pair-Setup-Accessory-Sign-Info', salt: 'Pair-Setup-Accessory-Sign-Salt')
|
89
|
-
accessory_x = hkdf.encrypt(session_key)
|
83
|
+
accessory_x = hkdf.encrypt(cache[:session_key])
|
90
84
|
|
91
85
|
signing_key = accessory_info.signing_key
|
92
86
|
accessoryltpk = signing_key.verify_key.to_bytes
|
@@ -98,48 +92,17 @@ module RubyHome
|
|
98
92
|
|
99
93
|
accessorysignature = signing_key.sign([accessoryinfo].pack('H*'))
|
100
94
|
|
101
|
-
subtlv =
|
102
|
-
'kTLVType_Identifier' => accessory_info.device_id,
|
103
|
-
'kTLVType_PublicKey' => accessoryltpk,
|
104
|
-
'kTLVType_Signature' => accessorysignature
|
105
|
-
})
|
95
|
+
subtlv = tlv(identifier: accessory_info.device_id, public_key: accessoryltpk, signature: accessorysignature)
|
106
96
|
|
107
|
-
nonce =
|
97
|
+
nonce = HexHelper.pad('PS-Msg06')
|
108
98
|
encrypted_data = chacha20poly1305ietf.encrypt(nonce, subtlv)
|
109
99
|
|
110
100
|
pairing_params = { admin: true, identifier: iosdevicepairingid, public_key: iosdeviceltpk.unpack1('H*') }
|
111
101
|
accessory_info.add_paired_client pairing_params
|
112
102
|
|
113
|
-
|
114
|
-
'kTLVType_State' => 6,
|
115
|
-
'kTLVType_EncryptedData' => encrypted_data
|
116
|
-
})
|
103
|
+
tlv state: 6, encrypted_data: encrypted_data
|
117
104
|
end
|
118
105
|
end
|
119
|
-
|
120
|
-
def srp_verifier
|
121
|
-
@_verifier ||= RubyHome::SRP::Verifier.new
|
122
|
-
end
|
123
|
-
|
124
|
-
def store_proof(proof)
|
125
|
-
cache[:proof] = proof
|
126
|
-
end
|
127
|
-
|
128
|
-
def retrieve_proof
|
129
|
-
cache[:proof]
|
130
|
-
end
|
131
|
-
|
132
|
-
def forget_proof!
|
133
|
-
cache[:proof] = nil
|
134
|
-
end
|
135
|
-
|
136
|
-
def store_session_key(key)
|
137
|
-
cache[:session_key] = key
|
138
|
-
end
|
139
|
-
|
140
|
-
def session_key
|
141
|
-
cache[:session_key]
|
142
|
-
end
|
143
106
|
end
|
144
107
|
end
|
145
108
|
end
|
@@ -1,16 +1,14 @@
|
|
1
|
-
require 'x25519'
|
2
|
-
require_relative '../../hap/crypto/hkdf'
|
3
|
-
require_relative '../../hap/hex_pad'
|
4
|
-
require_relative '../../hap/tlv'
|
5
1
|
require_relative 'application_controller'
|
6
2
|
|
7
3
|
module RubyHome
|
8
4
|
module HTTP
|
9
5
|
class PairVerifiesController < ApplicationController
|
10
|
-
post '/
|
6
|
+
post '/' do
|
11
7
|
content_type 'application/pairing+tlv8'
|
12
8
|
|
13
|
-
|
9
|
+
verify_accessory_paired
|
10
|
+
|
11
|
+
case unpack_request[:state]
|
14
12
|
when 1
|
15
13
|
verify_start_response
|
16
14
|
when 3
|
@@ -21,10 +19,10 @@ module RubyHome
|
|
21
19
|
private
|
22
20
|
|
23
21
|
def verify_start_response
|
24
|
-
secret_key =
|
22
|
+
secret_key = RbNaCl::PrivateKey.generate
|
25
23
|
public_key = secret_key.public_key.to_bytes
|
26
|
-
client_public_key =
|
27
|
-
shared_secret =
|
24
|
+
client_public_key = RbNaCl::PublicKey.new(unpack_request[:public_key])
|
25
|
+
shared_secret = RbNaCl::GroupElement.new(client_public_key).mult(secret_key).to_bytes
|
28
26
|
cache[:shared_secret] = shared_secret
|
29
27
|
|
30
28
|
accessoryinfo = [
|
@@ -36,46 +34,46 @@ module RubyHome
|
|
36
34
|
signing_key = accessory_info.signing_key
|
37
35
|
accessorysignature = signing_key.sign([accessoryinfo].pack('H*'))
|
38
36
|
|
39
|
-
subtlv =
|
40
|
-
'kTLVType_Identifier' => accessory_info.device_id,
|
41
|
-
'kTLVType_Signature' => accessorysignature
|
42
|
-
})
|
37
|
+
subtlv = tlv(identifier: accessory_info.device_id, signature: accessorysignature)
|
43
38
|
|
44
39
|
hkdf = HAP::Crypto::HKDF.new(info: 'Pair-Verify-Encrypt-Info', salt: 'Pair-Verify-Encrypt-Salt')
|
45
40
|
session_key = hkdf.encrypt(shared_secret)
|
46
41
|
cache[:session_key] = session_key
|
47
42
|
|
48
43
|
chacha20poly1305ietf = HAP::Crypto::ChaCha20Poly1305.new(session_key)
|
49
|
-
nonce =
|
44
|
+
nonce = HexHelper.pad('PV-Msg02')
|
50
45
|
encrypted_data = chacha20poly1305ietf.encrypt(nonce, subtlv)
|
51
46
|
|
52
|
-
|
53
|
-
'kTLVType_State' => 2,
|
54
|
-
'kTLVType_PublicKey' => public_key,
|
55
|
-
'kTLVType_EncryptedData' => encrypted_data
|
56
|
-
})
|
47
|
+
tlv state: 2, public_key: public_key, encrypted_data: encrypted_data
|
57
48
|
end
|
58
49
|
|
59
50
|
def verify_finish_response
|
60
|
-
encrypted_data = unpack_request[
|
51
|
+
encrypted_data = unpack_request[:encrypted_data]
|
61
52
|
|
62
53
|
chacha20poly1305ietf = HAP::Crypto::ChaCha20Poly1305.new(cache[:session_key])
|
63
|
-
nonce =
|
54
|
+
nonce = HexHelper.pad('PV-Msg03')
|
64
55
|
decrypted_data = chacha20poly1305ietf.decrypt(nonce, encrypted_data)
|
65
56
|
unpacked_decrypted_data = HAP::TLV.read(decrypted_data)
|
66
57
|
|
67
|
-
if accessory_info.paired_clients.any? {|h| h[:identifier] == unpacked_decrypted_data[
|
58
|
+
if accessory_info.paired_clients.any? {|h| h[:identifier] == unpacked_decrypted_data[:identifier]}
|
68
59
|
hkdf = HAP::Crypto::HKDF.new(info: 'Control-Write-Encryption-Key', salt: 'Control-Salt')
|
69
60
|
cache[:controller_to_accessory_key] = hkdf.encrypt(cache[:shared_secret])
|
70
61
|
|
71
62
|
hkdf = HAP::Crypto::HKDF.new(info: 'Control-Read-Encryption-Key', salt: 'Control-Salt')
|
72
63
|
cache[:accessory_to_controller_key] = hkdf.encrypt(cache[:shared_secret])
|
73
64
|
|
74
|
-
|
65
|
+
cache.delete(:session_key)
|
66
|
+
cache.delete(:shared_secret)
|
67
|
+
|
68
|
+
tlv state: 4
|
75
69
|
else
|
76
|
-
|
70
|
+
tlv state: 4, error: 2
|
77
71
|
end
|
78
72
|
end
|
73
|
+
|
74
|
+
def verify_accessory_paired
|
75
|
+
halt 403 unless accessory_info.paired?
|
76
|
+
end
|
79
77
|
end
|
80
78
|
end
|
81
79
|
end
|
@@ -3,10 +3,10 @@ require_relative 'application_controller'
|
|
3
3
|
module RubyHome
|
4
4
|
module HTTP
|
5
5
|
class PairingsController < ApplicationController
|
6
|
-
post '/
|
6
|
+
post '/' do
|
7
7
|
content_type 'application/pairing+tlv8'
|
8
8
|
|
9
|
-
case unpack_request[
|
9
|
+
case unpack_request[:method]
|
10
10
|
when 3
|
11
11
|
add_pairing
|
12
12
|
when 4
|
@@ -18,20 +18,20 @@ module RubyHome
|
|
18
18
|
|
19
19
|
def add_pairing
|
20
20
|
pairing_params = {
|
21
|
-
admin: !!unpack_request[
|
22
|
-
identifier: unpack_request[
|
23
|
-
public_key: unpack_request[
|
21
|
+
admin: !!unpack_request[:permissions],
|
22
|
+
identifier: unpack_request[:identifier],
|
23
|
+
public_key: unpack_request[:public_key].unpack1('H*')
|
24
24
|
}
|
25
25
|
accessory_info.add_paired_client pairing_params
|
26
26
|
|
27
|
-
|
27
|
+
tlv state: 2
|
28
28
|
end
|
29
29
|
|
30
30
|
def remove_pairing
|
31
|
-
accessory_info.remove_paired_client(unpack_request[
|
31
|
+
accessory_info.remove_paired_client(unpack_request[:identifier])
|
32
32
|
|
33
33
|
response['connection'] = 'close'
|
34
|
-
|
34
|
+
tlv state: 2
|
35
35
|
end
|
36
36
|
end
|
37
37
|
end
|
@@ -1,11 +1,7 @@
|
|
1
|
-
require 'webrick/httprequest'
|
2
|
-
require_relative '../hap/http_decryption'
|
3
|
-
|
4
1
|
module RubyHome
|
5
2
|
module HTTP
|
6
3
|
class HAPRequest < WEBrick::HTTPRequest
|
7
|
-
def initialize(*args
|
8
|
-
@_request_id = request_id
|
4
|
+
def initialize(*args)
|
9
5
|
cache[:controller_to_accessory_count] ||= 0
|
10
6
|
|
11
7
|
super(*args)
|
@@ -49,7 +45,7 @@ module RubyHome
|
|
49
45
|
end
|
50
46
|
|
51
47
|
def cache
|
52
|
-
|
48
|
+
RequestStore.store
|
53
49
|
end
|
54
50
|
end
|
55
51
|
end
|
@@ -1,11 +1,7 @@
|
|
1
|
-
require 'webrick/httpresponse'
|
2
|
-
require_relative '../hap/http_encryption'
|
3
|
-
|
4
1
|
module RubyHome
|
5
2
|
module HTTP
|
6
3
|
class HAPResponse < WEBrick::HTTPResponse
|
7
|
-
def initialize(*args
|
8
|
-
@_request_id = request_id
|
4
|
+
def initialize(*args)
|
9
5
|
cache[:accessory_to_controller_count] ||= 0
|
10
6
|
|
11
7
|
super(*args)
|
@@ -48,10 +44,8 @@ module RubyHome
|
|
48
44
|
end
|
49
45
|
|
50
46
|
def cache
|
51
|
-
|
47
|
+
RequestStore.store
|
52
48
|
end
|
53
49
|
end
|
54
50
|
end
|
55
51
|
end
|
56
|
-
|
57
|
-
|
@@ -1,26 +1,21 @@
|
|
1
|
-
require 'webrick/httpserver'
|
2
|
-
require 'webrick/httpstatus'
|
3
|
-
require_relative 'hap_request'
|
4
|
-
require_relative 'hap_response'
|
5
|
-
|
6
1
|
module RubyHome
|
7
2
|
module HTTP
|
8
3
|
class HAPServer < WEBrick::HTTPServer
|
9
|
-
def run(
|
4
|
+
def run(socket)
|
10
5
|
while true
|
11
|
-
res = RubyHome::HTTP::HAPResponse.new(@config
|
12
|
-
req = RubyHome::HTTP::HAPRequest.new(@config
|
6
|
+
res = RubyHome::HTTP::HAPResponse.new(@config)
|
7
|
+
req = RubyHome::HTTP::HAPRequest.new(@config)
|
13
8
|
server = self
|
14
9
|
begin
|
15
10
|
timeout = @config[:RequestTimeout]
|
16
11
|
while timeout > 0
|
17
|
-
break if
|
12
|
+
break if socket.to_io.wait_readable(0.5)
|
18
13
|
break if @status != :Running
|
19
14
|
timeout -= 0.5
|
20
15
|
end
|
21
16
|
raise WEBrick::HTTPStatus::EOFError if timeout <= 0 || @status != :Running
|
22
|
-
raise WEBrick::HTTPStatus::EOFError if
|
23
|
-
req.parse(
|
17
|
+
raise WEBrick::HTTPStatus::EOFError if socket.eof?
|
18
|
+
req.parse(socket)
|
24
19
|
res.received_encrypted_request = req.received_encrypted_request?
|
25
20
|
res.request_method = req.request_method
|
26
21
|
res.request_uri = req.request_uri
|
@@ -50,7 +45,7 @@ module RubyHome
|
|
50
45
|
if req.keep_alive? && res.keep_alive?
|
51
46
|
req.fixup()
|
52
47
|
end
|
53
|
-
res.send_response(
|
48
|
+
res.send_response(socket)
|
54
49
|
server.access_log(@config, req, res)
|
55
50
|
end
|
56
51
|
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
class StartSRPService
|
2
|
+
def initialize(username: , password:)
|
3
|
+
@username = username
|
4
|
+
@password = password
|
5
|
+
end
|
6
|
+
|
7
|
+
def salt_bytes
|
8
|
+
[salt].pack('H*')
|
9
|
+
end
|
10
|
+
|
11
|
+
def public_key_bytes
|
12
|
+
[public_key].pack('H*')
|
13
|
+
end
|
14
|
+
|
15
|
+
def proof
|
16
|
+
challenge_and_proof[:proof]
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def salt
|
22
|
+
user_auth[:salt]
|
23
|
+
end
|
24
|
+
|
25
|
+
def public_key
|
26
|
+
challenge[:B]
|
27
|
+
end
|
28
|
+
|
29
|
+
def challenge
|
30
|
+
challenge_and_proof[:challenge]
|
31
|
+
end
|
32
|
+
|
33
|
+
def challenge_and_proof
|
34
|
+
srp_verifier.get_challenge_and_proof(username, user_auth[:verifier], user_auth[:salt])
|
35
|
+
end
|
36
|
+
|
37
|
+
def user_auth
|
38
|
+
@_user_auth ||= srp_verifier.generate_userauth(username, password)
|
39
|
+
end
|
40
|
+
|
41
|
+
def srp_verifier
|
42
|
+
@_verifier ||= RubyHome::SRP::Verifier.new
|
43
|
+
end
|
44
|
+
|
45
|
+
attr_reader :username, :password
|
46
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
class VerifySRPService
|
2
|
+
def initialize(public_key: , device_proof: , srp_session: )
|
3
|
+
@device_proof = device_proof
|
4
|
+
@srp_session = srp_session
|
5
|
+
@public_key = public_key
|
6
|
+
end
|
7
|
+
|
8
|
+
def valid?
|
9
|
+
return false unless public_key
|
10
|
+
return false unless device_proof
|
11
|
+
return false unless srp_session
|
12
|
+
return false unless valid_session?
|
13
|
+
|
14
|
+
true
|
15
|
+
end
|
16
|
+
|
17
|
+
def session_key
|
18
|
+
srp_verifier.K
|
19
|
+
end
|
20
|
+
|
21
|
+
def server_proof
|
22
|
+
verify_session_bytes
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def valid_session?
|
28
|
+
!!verify_session
|
29
|
+
end
|
30
|
+
|
31
|
+
def verify_session_bytes
|
32
|
+
[verify_session].pack('H*')
|
33
|
+
end
|
34
|
+
|
35
|
+
def verify_session
|
36
|
+
@_verify_session ||= srp_verifier.verify_session(
|
37
|
+
srp_session.merge({A: public_key_bytes}),
|
38
|
+
device_proof_bytes
|
39
|
+
)
|
40
|
+
end
|
41
|
+
|
42
|
+
def public_key_bytes
|
43
|
+
public_key.unpack1('H*')
|
44
|
+
end
|
45
|
+
|
46
|
+
def device_proof_bytes
|
47
|
+
device_proof.unpack1('H*')
|
48
|
+
end
|
49
|
+
|
50
|
+
def srp_verifier
|
51
|
+
@_verifier ||= RubyHome::SRP::Verifier.new
|
52
|
+
end
|
53
|
+
|
54
|
+
attr_reader :public_key, :device_proof, :srp_session
|
55
|
+
end
|
@@ -1,6 +1,3 @@
|
|
1
|
-
require 'webrick'
|
2
|
-
require_relative '../../http/hap_server'
|
3
|
-
|
4
1
|
module RubyHome
|
5
2
|
module Rack
|
6
3
|
module Handler
|
@@ -11,10 +8,8 @@ module RubyHome
|
|
11
8
|
|
12
9
|
options[:BindAddress] = options.delete(:Host) || default_host
|
13
10
|
options[:Port] ||= 8080
|
14
|
-
|
15
|
-
|
16
|
-
options[:AccessLog] = []
|
17
|
-
end
|
11
|
+
options[:Logger] = WEBrick::Log.new("/dev/null")
|
12
|
+
options[:AccessLog] = []
|
18
13
|
@server = HTTP::HAPServer.new(options)
|
19
14
|
@server.mount '/', Handler::HAPServer, app
|
20
15
|
yield @server if block_given?
|
data/lib/ruby_home/version.rb
CHANGED