meshtastic 0.0.40 → 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 +42 -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)'
|
@@ -60,34 +81,29 @@ module Meshtastic
|
|
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
|
63
|
-
|
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
|
+
|
64
92
|
qos = opts[:qos] ||= 0
|
65
93
|
json = opts[:json] ||= false
|
66
94
|
filter = opts[:filter]
|
67
95
|
gps_metadata = opts[:gps_metadata] ||= false
|
68
96
|
|
69
|
-
#
|
97
|
+
# NOTE: Use MQTT Explorer for topic discovery
|
70
98
|
full_topic = "#{root_topic}/#{region}/#{channel}"
|
71
99
|
puts "Subscribing to: #{full_topic}"
|
72
100
|
mqtt_obj.subscribe(full_topic, qos)
|
73
101
|
|
74
|
-
# Decrypt the message
|
75
|
-
# Our AES key is 128 or 256 bits, shared as part of the 'Channel' specification.
|
76
|
-
|
77
|
-
# Actual pre-shared key for LongFast channel
|
78
|
-
psk = '1PG7OiApB1nwvP+rz05pAQ==' if psk == 'AQ=='
|
79
|
-
padded_psk = psk.ljust(psk.length + ((4 - (psk.length % 4)) % 4), '=')
|
80
|
-
replaced_psk = padded_psk.gsub('-', '+').gsub('_', '/')
|
81
|
-
psk = replaced_psk
|
82
|
-
dec_psk = Base64.strict_decode64(psk)
|
83
|
-
|
84
|
-
# cipher = OpenSSL::Cipher.new('AES-256-CTR')
|
85
|
-
cipher = OpenSSL::Cipher.new('AES-128-CTR')
|
86
102
|
filter_arr = filter.to_s.split(',').map(&:strip)
|
87
103
|
mqtt_obj.get_packet do |packet_bytes|
|
88
104
|
# raw_packet = packet_bytes.to_s.b
|
89
105
|
raw_topic = packet_bytes.topic ||= ''
|
90
|
-
raw_payload = packet_bytes.payload
|
106
|
+
raw_payload = packet_bytes.payload ||= ''
|
91
107
|
|
92
108
|
begin
|
93
109
|
disp = false
|
@@ -110,15 +126,21 @@ module Meshtastic
|
|
110
126
|
encrypted_message = message[:encrypted]
|
111
127
|
# If encrypted_message is not nil, then decrypt the message
|
112
128
|
if encrypted_message.to_s.length.positive?
|
129
|
+
|
113
130
|
packet_id = message[:id]
|
114
131
|
packet_from = message[:from]
|
132
|
+
|
115
133
|
nonce_packet_id = [packet_id].pack('V').ljust(8, "\x00")
|
116
134
|
nonce_from_node = [packet_from].pack('V').ljust(8, "\x00")
|
117
135
|
nonce = "#{nonce_packet_id}#{nonce_from_node}".b
|
118
136
|
|
119
|
-
|
120
|
-
|
121
|
-
|
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
|
122
144
|
cipher.decrypt
|
123
145
|
cipher.key = dec_psk
|
124
146
|
cipher.iv = nonce
|
@@ -320,7 +342,7 @@ module Meshtastic
|
|
320
342
|
root_topic: 'optional - root topic (default: msh)',
|
321
343
|
region: 'optional - region e.g. 'US/VA', etc (default: US)',
|
322
344
|
channel: 'optional - channel name e.g. '2/stat/#' (default: '2/e/LongFast/#')',
|
323
|
-
|
345
|
+
psks: 'optional - hash of :channel => psk key value pairs (default: { LongFast: 'AQ==' })',
|
324
346
|
qos: 'optional - quality of service (default: 0)',
|
325
347
|
json: 'optional - JSON output (default: false)',
|
326
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
|