ruby_home 0.1.14 → 0.1.15

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 247444e8f829a6189260709b8e0ea216ebe541788e2c8db878a944a92ed926f2
4
- data.tar.gz: a015fb65638df959a1d0bd5b69d6510f5c1b04d24eef96742fb0c6188153db8f
3
+ metadata.gz: 90d257a9cc88bba2f6323a89829fc89000e6e84842dbf7abadefb35168eb2848
4
+ data.tar.gz: 94acb47192d8cb7b9a54f01f7621da8b5371c2218ebf9494d2324af2193a705d
5
5
  SHA512:
6
- metadata.gz: 93daf94385bd9f965392cd9ed748ff3e0f23132383bff1fe510f326b255aa6fe45b33f88a43b01b98c181de54d43bec2fbe48dde02d39e3004cf956c86616cb6
7
- data.tar.gz: 8100648de51d429ec93b6de81137cf0c9354435acbb11a47fb57a365f0a5a14f38224a6dfaf41cba61edae6dc67d762a227ae6da9af4d22fef8d18c742ebaebd
6
+ metadata.gz: e229661aca3237368c77159703e01b10ad8a39d4c3ce35176ce73251668bba6077646285c2360fa783d79d5c77b658ae84299af6143ecd613b8abf97edd2213b
7
+ data.tar.gz: 3e4aadce797eb3b8a8be1ae6f70af601866726c7d53f76e3a0c7246fda25affadc0c67220e98d1596b4befa1a6dc6299ff89f7863c232b45e1748529497d84c8
@@ -3,44 +3,37 @@ module RubyHome
3
3
  class EVResponse
4
4
  def initialize(session, body)
5
5
  @session = session
6
- @socket = session.socket
7
6
  @body = body
8
7
  end
9
8
 
10
9
  def send_response
11
- response = ''
12
-
13
- send_header(response)
14
- send_body(response)
15
-
16
- encrypter = session.encrypter
17
- encrypted_response = encrypter.encrypt(response).join
18
- session.accessory_to_controller_count = encrypter.count
19
-
20
- socket << encrypted_response
10
+ send_header(session)
11
+ send_body(session)
21
12
  end
22
13
 
23
14
  private
24
15
 
25
- attr_reader :body, :socket, :session
16
+ attr_reader :body, :session
26
17
 
27
18
  CRLF = -"\x0d\x0a"
28
19
  STATUS_LINE = -'EVENT/1.0 200 OK'
29
20
  CONTENT_TYPE_LINE = -'Content-Type: application/hap+json'
30
21
 
31
- def send_header(socket)
32
- socket << STATUS_LINE + CRLF
33
- socket << CONTENT_TYPE_LINE + CRLF
34
- socket << content_length_line + CRLF
35
- socket << CRLF
22
+ def content_length_line
23
+ "Content-Length: #{body.length}"
36
24
  end
37
25
 
38
- def send_body(socket)
39
- socket << body
26
+ def send_header(io)
27
+ data = STATUS_LINE + CRLF
28
+ data << CONTENT_TYPE_LINE + CRLF
29
+ data << content_length_line + CRLF
30
+ data << CRLF
31
+
32
+ io.write(data)
40
33
  end
41
34
 
42
- def content_length_line
43
- "Content-Length: #{body.length}"
35
+ def send_body(io)
36
+ io.write(body)
44
37
  end
45
38
  end
46
39
  end
@@ -1,26 +1,11 @@
1
1
  module RubyHome
2
2
  module HAP
3
3
  class HAPRequest < WEBrick::HTTPRequest
4
- def parse(session)
5
- @session = session
6
- socket = session.socket
7
-
8
- if session.decryption_time?
9
- request_line = socket.read_nonblock(@buffer_size)
10
-
11
- decrypter = session.decrypter
12
- decrypted_request = decrypter.decrypt(request_line).join
13
- session.controller_to_accessory_count = decrypter.count
14
-
15
- super(StringIO.new(decrypted_request))
16
- else
17
- super(socket)
18
- end
19
- end
4
+ attr_accessor :session
20
5
 
21
6
  def meta_vars
22
7
  super.merge(
23
- { "REQUEST_SESSION" => @session }
8
+ { "REQUEST_SESSION" => session }
24
9
  )
25
10
  end
26
11
  end
@@ -1,23 +1,6 @@
1
1
  module RubyHome
2
2
  module HAP
3
3
  class HAPResponse < WEBrick::HTTPResponse
4
- def send_response(session)
5
- socket = session.socket
6
-
7
- if session.encryption_time?
8
- response = StringIO.new
9
- super(response)
10
-
11
- encrypter = session.encrypter
12
-
13
- encrypted_response = encrypter.encrypt(response.string).join
14
- session.accessory_to_controller_count = encrypter.count
15
-
16
- _write_data(socket, encrypted_response)
17
- else
18
- super(socket)
19
- end
20
- end
21
4
  end
22
5
  end
23
6
  end
@@ -42,13 +42,13 @@ module RubyHome
42
42
  def read(socket)
43
43
  return close(socket) if socket.eof?
44
44
 
45
- session = SESSIONS[socket] ||= Session.new(socket)
46
-
47
45
  request = HAPRequest.new(webrick_config)
48
46
  response = HAPResponse.new(webrick_config)
49
47
 
50
- request.parse(session)
48
+ session = SESSIONS[socket] ||= Session.new(socket)
49
+ request.session = session
51
50
 
51
+ request.parse(session.parse)
52
52
  response.request_method = request.request_method
53
53
  response.request_uri = request.request_uri
54
54
  response.request_http_version = request.http_version
@@ -1,6 +1,6 @@
1
1
  module RubyHome
2
2
  module HAP
3
- class HTTPDecryption
3
+ class Decrypter
4
4
  AAD_LENGTH_BYTES = 2.freeze
5
5
  AUTHENTICATE_TAG_LENGTH_BYTES = 16.freeze
6
6
  NONCE_32_BIT_FIX_COMMENT_PART = [0].pack('L').freeze
@@ -16,7 +16,7 @@ module RubyHome
16
16
 
17
17
  while read_pointer < data.length
18
18
  little_endian_length_of_encrypted_data = data[read_pointer...read_pointer+AAD_LENGTH_BYTES]
19
- length_of_encrypted_data = little_endian_length_of_encrypted_data.unpack('v').first
19
+ length_of_encrypted_data = little_endian_length_of_encrypted_data.unpack1('v')
20
20
  read_pointer += AAD_LENGTH_BYTES
21
21
 
22
22
  message = data[read_pointer...read_pointer+length_of_encrypted_data]
@@ -32,7 +32,7 @@ module RubyHome
32
32
  increment_count!
33
33
  end
34
34
 
35
- decrypted_data
35
+ decrypted_data.join
36
36
  end
37
37
 
38
38
  attr_reader :count
@@ -0,0 +1,56 @@
1
+ module RubyHome
2
+ module HAP
3
+ class Session
4
+ class Encrypter
5
+ MAX_FRAME_LENGTH = 1024.freeze
6
+ NONCE_32_BIT_FIX_COMMENT_PART = [0].pack('L').freeze
7
+
8
+ def initialize(key, count: 0)
9
+ @key = key
10
+ @count = count
11
+ end
12
+
13
+ def encrypt(data)
14
+ encrypted_data = []
15
+ read_pointer = 0
16
+
17
+ while read_pointer < data.length
18
+ encrypted_frame = ""
19
+
20
+ frame = data[read_pointer...read_pointer+MAX_FRAME_LENGTH]
21
+ length_of_encrypted_data = frame.length
22
+ little_endian_length_of_encrypted_data = [length_of_encrypted_data].pack('v')
23
+
24
+ encrypted_frame += little_endian_length_of_encrypted_data
25
+ encrypted_frame += chacha20poly1305ietf.encrypt(nonce, frame, little_endian_length_of_encrypted_data)
26
+ encrypted_data << encrypted_frame
27
+
28
+ read_pointer += length_of_encrypted_data
29
+ increment_count!
30
+ end
31
+
32
+ encrypted_data.join
33
+ end
34
+
35
+ attr_reader :count
36
+
37
+ private
38
+
39
+ attr_reader :key
40
+
41
+ def increment_count!
42
+ @count += 1
43
+ end
44
+
45
+ def nonce
46
+ NONCE_32_BIT_FIX_COMMENT_PART + [count].pack('Q')
47
+ end
48
+
49
+ def chacha20poly1305ietf
50
+ @_chacha20poly1305ietf ||= HAP::Crypto::ChaCha20Poly1305.new(key)
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+
@@ -1,68 +1,85 @@
1
1
  module RubyHome
2
2
  module HAP
3
3
  class Session
4
- def initialize(socket)
5
- @socket = socket
6
- @accessory_to_controller_count = 0
7
- @controller_to_accessory_count = 0
8
- end
4
+ PARSE_BUFFER_SIZE = 65536
9
5
 
10
- attr_reader :socket
11
- attr_accessor :controller_to_accessory_key
12
- attr_accessor :accessory_to_controller_key
13
- attr_writer :accessory_to_controller_count
14
- attr_writer :controller_to_accessory_count
15
- attr_accessor :shared_secret
16
- attr_accessor :session_key
17
- attr_accessor :srp_session
18
-
19
- def encryption_time?
20
- accessory_to_controller_key? && received_encrypted_request?
6
+ def initialize(socket, decrypter_class: Decrypter, encrypter_class: Encrypter)
7
+ @socket = socket
8
+ @encrypter_class = encrypter_class
9
+ @decrypter_class = decrypter_class
21
10
  end
22
11
 
23
- def received_encrypted_request?
24
- controller_to_accessory_count > 0
25
- end
12
+ attr_accessor(
13
+ :controller_to_accessory_key,
14
+ :accessory_to_controller_key,
15
+ :shared_secret,
16
+ :session_key,
17
+ :srp_session
18
+ )
26
19
 
27
- def encrypter
28
- HTTPEncryption.new(accessory_to_controller_key, encrypter_params)
20
+ def sufficient_privileges?
21
+ controller_to_accessory_key? && accessory_to_controller_key?
29
22
  end
30
23
 
31
- def decryption_time?
32
- controller_to_accessory_key.present?
24
+ def active?
25
+ !socket.closed?
33
26
  end
34
27
 
35
- def decrypter
36
- HTTPDecryption.new(controller_to_accessory_key, decrypter_params)
28
+ def write(data)
29
+ if encryption_time?
30
+ socket.write(encrypter.encrypt(data))
31
+ else
32
+ socket.write(data)
33
+ end
37
34
  end
38
35
 
39
- def sufficient_privileges?
40
- controller_to_accessory_key? && accessory_to_controller_key?
36
+ def parse
37
+ if decryption_time?
38
+ received_encrypted_request!
39
+ StringIO.new(
40
+ decrypter.decrypt(
41
+ socket.read_nonblock(PARSE_BUFFER_SIZE)
42
+ )
43
+ )
44
+ else
45
+ socket
46
+ end
41
47
  end
42
48
 
43
- def active?
44
- !socket.closed?
49
+ def received_encrypted_request!
50
+ @received_encrypted_request ||= true
45
51
  end
46
52
 
47
53
  private
48
54
 
49
- attr_reader :accessory_to_controller_count,
50
- :controller_to_accessory_count
55
+ attr_reader :socket, :encrypter_class, :decrypter_class
51
56
 
52
- def accessory_to_controller_key?
53
- accessory_to_controller_key.present?
57
+ def received_encrypted_request?
58
+ @received_encrypted_request ||= false
54
59
  end
55
60
 
56
- def controller_to_accessory_key?
61
+ def encrypter
62
+ @_encrypter ||= encrypter_class.new(accessory_to_controller_key)
63
+ end
64
+
65
+ def encryption_time?
66
+ accessory_to_controller_key? && received_encrypted_request?
67
+ end
68
+
69
+ def decrypter
70
+ @_decrypter ||= decrypter_class.new(controller_to_accessory_key)
71
+ end
72
+
73
+ def decryption_time?
57
74
  controller_to_accessory_key.present?
58
75
  end
59
76
 
60
- def encrypter_params
61
- { count: accessory_to_controller_count }
77
+ def accessory_to_controller_key?
78
+ accessory_to_controller_key.present?
62
79
  end
63
80
 
64
- def decrypter_params
65
- { count: controller_to_accessory_count }
81
+ def controller_to_accessory_key?
82
+ controller_to_accessory_key.present?
66
83
  end
67
84
  end
68
85
  end
@@ -1,3 +1,3 @@
1
1
  module RubyHome
2
- VERSION = '0.1.14'
2
+ VERSION = '0.1.15'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby_home
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.14
4
+ version: 0.1.15
5
5
  platform: ruby
6
6
  authors:
7
7
  - Karl Entwistle
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-11-22 00:00:00.000000000 Z
11
+ date: 2018-11-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -291,11 +291,11 @@ files:
291
291
  - lib/ruby_home/hap/ev_response.rb
292
292
  - lib/ruby_home/hap/hap_request.rb
293
293
  - lib/ruby_home/hap/hap_response.rb
294
- - lib/ruby_home/hap/http_decryption.rb
295
- - lib/ruby_home/hap/http_encryption.rb
296
294
  - lib/ruby_home/hap/server.rb
297
295
  - lib/ruby_home/hap/service.rb
298
296
  - lib/ruby_home/hap/session.rb
297
+ - lib/ruby_home/hap/session/decrypter.rb
298
+ - lib/ruby_home/hap/session/encrypter.rb
299
299
  - lib/ruby_home/hap/tlv.rb
300
300
  - lib/ruby_home/hap/values/base_value.rb
301
301
  - lib/ruby_home/hap/values/bool_value.rb
@@ -1,53 +0,0 @@
1
- module RubyHome
2
- module HAP
3
- class HTTPEncryption
4
- MAX_FRAME_LENGTH = 1024.freeze
5
- NONCE_32_BIT_FIX_COMMENT_PART = [0].pack('L').freeze
6
-
7
- def initialize(key, count: 0)
8
- @key = key
9
- @count = count
10
- end
11
-
12
- def encrypt(data)
13
- encrypted_data = []
14
- read_pointer = 0
15
-
16
- while read_pointer < data.length
17
- encrypted_frame = ""
18
-
19
- frame = data[read_pointer...read_pointer+MAX_FRAME_LENGTH]
20
- length_of_encrypted_data = frame.length
21
- little_endian_length_of_encrypted_data = [length_of_encrypted_data].pack('v')
22
-
23
- encrypted_frame += little_endian_length_of_encrypted_data
24
- encrypted_frame += chacha20poly1305ietf.encrypt(nonce, frame, little_endian_length_of_encrypted_data)
25
- encrypted_data << encrypted_frame
26
-
27
- read_pointer += length_of_encrypted_data
28
- increment_count!
29
- end
30
-
31
- encrypted_data
32
- end
33
-
34
- attr_reader :count
35
-
36
- private
37
-
38
- attr_reader :key
39
-
40
- def increment_count!
41
- @count += 1
42
- end
43
-
44
- def nonce
45
- NONCE_32_BIT_FIX_COMMENT_PART + [count].pack('Q')
46
- end
47
-
48
- def chacha20poly1305ietf
49
- @_chacha20poly1305ietf ||= HAP::Crypto::ChaCha20Poly1305.new(key)
50
- end
51
- end
52
- end
53
- end