meshtastic 0.0.39 → 0.0.41
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/Gemfile +1 -0
- data/lib/meshtastic/mqtt.rb +43 -20
- data/lib/meshtastic/version.rb +1 -1
- metadata +16 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 94567b95fcf287b1a47b7af7ea3efb4b6f15a5a0daf81137127b6f5dede9a8fd
|
|
4
|
+
data.tar.gz: aa07f4271ac1cb1953492ab508f2f8f4f2c7c0c51fb306195b096b950b917c25
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 77093a3977ef63ad7c15d255c679771e5fe02448741147acbc608f19c057d9b9f8f47fe214e0f0a2799cca331726450f978bbda99248fb5d3f592e4d37b09a43
|
|
7
|
+
data.tar.gz: 4c617b139c876db4b3fff9f4357fba3785972e47e88e85a9a9a1656db8c5ced40e42699b737aa7b84f3cc86ced3f66480a3def02e6e1a2272bdd23ac70d82858
|
data/Gemfile
CHANGED
data/lib/meshtastic/mqtt.rb
CHANGED
|
@@ -6,6 +6,7 @@ require 'json'
|
|
|
6
6
|
require 'mqtt'
|
|
7
7
|
require 'openssl'
|
|
8
8
|
require 'securerandom'
|
|
9
|
+
require 'tty-prompt'
|
|
9
10
|
|
|
10
11
|
# Avoiding Namespace Collisions
|
|
11
12
|
MQTTClient = MQTT::Client
|
|
@@ -42,13 +43,33 @@ module Meshtastic
|
|
|
42
43
|
raise e
|
|
43
44
|
end
|
|
44
45
|
|
|
46
|
+
# Supported Method Parameters::
|
|
47
|
+
# Meshtastic::MQQT.get_cipher_keys(
|
|
48
|
+
# psks: 'required - hash of channel / pre-shared key value pairs'
|
|
49
|
+
# )
|
|
50
|
+
|
|
51
|
+
private_class_method def self.get_cipher_keys(opts = {})
|
|
52
|
+
psks = opts[:psks]
|
|
53
|
+
|
|
54
|
+
psks.each_key do |key|
|
|
55
|
+
psk = psks[key]
|
|
56
|
+
padded_psk = psk.ljust(psk.length + ((4 - (psk.length % 4)) % 4), '=')
|
|
57
|
+
replaced_psk = padded_psk.gsub('-', '+').gsub('_', '/')
|
|
58
|
+
psks[key] = replaced_psk
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
psks
|
|
62
|
+
rescue StandardError => e
|
|
63
|
+
raise e
|
|
64
|
+
end
|
|
65
|
+
|
|
45
66
|
# Supported Method Parameters::
|
|
46
67
|
# Meshtastic::MQQT.subscribe(
|
|
47
68
|
# mqtt_obj: 'required - mqtt_obj returned from #connect method'
|
|
48
69
|
# root_topic: 'optional - root topic (default: msh)',
|
|
49
70
|
# region: 'optional - region e.g. 'US/VA', etc (default: US)',
|
|
50
71
|
# channel: 'optional - channel name e.g. "2/stat/#" (default: "2/e/LongFast/#")',
|
|
51
|
-
#
|
|
72
|
+
# psks: 'optional - hash of :channel => psk key value pairs (default: { LongFast: "AQ==" })',
|
|
52
73
|
# qos: 'optional - quality of service (default: 0)',
|
|
53
74
|
# filter: 'optional - comma-delimited string(s) to filter on in message (default: nil)',
|
|
54
75
|
# gps_metadata: 'optional - include GPS metadata in output (default: false)'
|
|
@@ -59,34 +80,30 @@ module Meshtastic
|
|
|
59
80
|
root_topic = opts[:root_topic] ||= 'msh'
|
|
60
81
|
region = opts[:region] ||= 'US'
|
|
61
82
|
channel = opts[:channel] ||= '2/e/LongFast/#'
|
|
62
|
-
|
|
83
|
+
# TODO: Support Array of PSKs and attempt each until decrypted
|
|
84
|
+
|
|
85
|
+
public_psk = '1PG7OiApB1nwvP+rz05pAQ=='
|
|
86
|
+
psks = opts[:psks] ||= { LongFast: public_psk }
|
|
87
|
+
raise 'ERROR: psks parameter must be a hash of :channel => psk key value pairs' unless psks.is_a?(Hash)
|
|
88
|
+
|
|
89
|
+
psks[:LongFast] = public_psk if psks[:LongFast] == 'AQ=='
|
|
90
|
+
psks = get_cipher_keys(psks: psks)
|
|
91
|
+
|
|
63
92
|
qos = opts[:qos] ||= 0
|
|
64
93
|
json = opts[:json] ||= false
|
|
65
94
|
filter = opts[:filter]
|
|
66
95
|
gps_metadata = opts[:gps_metadata] ||= false
|
|
67
96
|
|
|
68
|
-
#
|
|
97
|
+
# NOTE: Use MQTT Explorer for topic discovery
|
|
69
98
|
full_topic = "#{root_topic}/#{region}/#{channel}"
|
|
70
99
|
puts "Subscribing to: #{full_topic}"
|
|
71
100
|
mqtt_obj.subscribe(full_topic, qos)
|
|
72
101
|
|
|
73
|
-
# Decrypt the message
|
|
74
|
-
# Our AES key is 128 or 256 bits, shared as part of the 'Channel' specification.
|
|
75
|
-
|
|
76
|
-
# Actual pre-shared key for LongFast channel
|
|
77
|
-
psk = '1PG7OiApB1nwvP+rz05pAQ==' if channel.include?('LongFast')
|
|
78
|
-
padded_psk = psk.ljust(psk.length + ((4 - (psk.length % 4)) % 4), '=')
|
|
79
|
-
replaced_psk = padded_psk.gsub('-', '+').gsub('_', '/')
|
|
80
|
-
psk = replaced_psk
|
|
81
|
-
dec_psk = Base64.strict_decode64(psk)
|
|
82
|
-
|
|
83
|
-
# cipher = OpenSSL::Cipher.new('AES-256-CTR')
|
|
84
|
-
cipher = OpenSSL::Cipher.new('AES-128-CTR')
|
|
85
102
|
filter_arr = filter.to_s.split(',').map(&:strip)
|
|
86
103
|
mqtt_obj.get_packet do |packet_bytes|
|
|
87
104
|
# raw_packet = packet_bytes.to_s.b
|
|
88
105
|
raw_topic = packet_bytes.topic ||= ''
|
|
89
|
-
raw_payload = packet_bytes.payload
|
|
106
|
+
raw_payload = packet_bytes.payload ||= ''
|
|
90
107
|
|
|
91
108
|
begin
|
|
92
109
|
disp = false
|
|
@@ -109,15 +126,21 @@ module Meshtastic
|
|
|
109
126
|
encrypted_message = message[:encrypted]
|
|
110
127
|
# If encrypted_message is not nil, then decrypt the message
|
|
111
128
|
if encrypted_message.to_s.length.positive?
|
|
129
|
+
|
|
112
130
|
packet_id = message[:id]
|
|
113
131
|
packet_from = message[:from]
|
|
132
|
+
|
|
114
133
|
nonce_packet_id = [packet_id].pack('V').ljust(8, "\x00")
|
|
115
134
|
nonce_from_node = [packet_from].pack('V').ljust(8, "\x00")
|
|
116
135
|
nonce = "#{nonce_packet_id}#{nonce_from_node}".b
|
|
117
136
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
137
|
+
psk = psks[:LongFast]
|
|
138
|
+
target_chanel = decoded_payload_hash[:channel_id].to_s.to_sym
|
|
139
|
+
psk = psks[target_chanel] if psks.keys.include?(target_chanel)
|
|
140
|
+
dec_psk = Base64.strict_decode64(psk)
|
|
141
|
+
|
|
142
|
+
cipher = OpenSSL::Cipher.new('AES-128-CTR')
|
|
143
|
+
cipher = OpenSSL::Cipher.new('AES-256-CTR') if dec_psk.length == 32
|
|
121
144
|
cipher.decrypt
|
|
122
145
|
cipher.key = dec_psk
|
|
123
146
|
cipher.iv = nonce
|
|
@@ -319,7 +342,7 @@ module Meshtastic
|
|
|
319
342
|
root_topic: 'optional - root topic (default: msh)',
|
|
320
343
|
region: 'optional - region e.g. 'US/VA', etc (default: US)',
|
|
321
344
|
channel: 'optional - channel name e.g. '2/stat/#' (default: '2/e/LongFast/#')',
|
|
322
|
-
|
|
345
|
+
psks: 'optional - hash of :channel => psk key value pairs (default: { LongFast: 'AQ==' })',
|
|
323
346
|
qos: 'optional - quality of service (default: 0)',
|
|
324
347
|
json: 'optional - JSON output (default: false)',
|
|
325
348
|
filter: 'optional - comma-delimited string(s) to filter on in message (default: nil)',
|
data/lib/meshtastic/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: meshtastic
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.41
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- 0day Inc.
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2024-05-
|
|
11
|
+
date: 2024-05-02 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -178,6 +178,20 @@ dependencies:
|
|
|
178
178
|
- - '='
|
|
179
179
|
- !ruby/object:Gem::Version
|
|
180
180
|
version: 1.11.3.9
|
|
181
|
+
- !ruby/object:Gem::Dependency
|
|
182
|
+
name: tty-prompt
|
|
183
|
+
requirement: !ruby/object:Gem::Requirement
|
|
184
|
+
requirements:
|
|
185
|
+
- - '='
|
|
186
|
+
- !ruby/object:Gem::Version
|
|
187
|
+
version: 0.23.1
|
|
188
|
+
type: :runtime
|
|
189
|
+
prerelease: false
|
|
190
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
191
|
+
requirements:
|
|
192
|
+
- - '='
|
|
193
|
+
- !ruby/object:Gem::Version
|
|
194
|
+
version: 0.23.1
|
|
181
195
|
- !ruby/object:Gem::Dependency
|
|
182
196
|
name: yard
|
|
183
197
|
requirement: !ruby/object:Gem::Requirement
|