ruby_home 0.1.14 → 0.1.15

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 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