Beginning of message decryption

This commit is contained in:
Daniel Pupius
2025-04-18 18:40:30 -07:00
parent b9767a3a7f
commit cd648508c1
6 changed files with 137 additions and 61 deletions
+72
View File
@@ -0,0 +1,72 @@
package decoder
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"encoding/binary"
"fmt"
)
// XOR encrypts or decrypts text with the specified key. It requires the packetID and sending node ID for the AES IV
func XOR(text []byte, key []byte, packetID, fromNode uint32) ([]byte, error) {
if len(key) != 16 && len(key) != 24 && len(key) != 32 {
return nil, fmt.Errorf("key length must be 16, 24, or 32 bytes")
}
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
// The IV needs to be unique, but not secure. It's common to include it at
// the beginning of the text. In CTR mode, the IV size is equal to the block size.
//if len(text) < aes.BlockSize {
// return nil, fmt.Errorf("text too short")
//}
iv, err := CreateNonce(packetID, fromNode)
if err != nil {
return nil, err
}
//text = text[aes.BlockSize:]
// CTR mode is the same for both encryption and decryption, so we use
// the NewCTR function rather than NewCBCDecrypter.
stream := cipher.NewCTR(block, iv)
// XORKeyStream can work in-place if the two arguments are the same.
plaintext := make([]byte, len(text))
stream.XORKeyStream(plaintext, text)
return plaintext, nil
}
// CreateNonce creates a 128-bit nonce.
// It takes a uint32 packetId, converts it to a uint64, and a uint32 fromNode.
// The nonce is concatenated as [64-bit packetId][32-bit fromNode][32-bit block counter].
func CreateNonce(packetId uint32, fromNode uint32) ([]byte, error) {
// Expand packetId to 64 bits
packetId64 := uint64(packetId)
// Initialize block counter (32-bit, starts at zero)
blockCounter := uint32(0)
// Create a buffer for the nonce
buf := new(bytes.Buffer)
// Write packetId, fromNode, and block counter to the buffer
err := binary.Write(buf, binary.LittleEndian, packetId64)
if err != nil {
return nil, err
}
err = binary.Write(buf, binary.LittleEndian, fromNode)
if err != nil {
return nil, err
}
err = binary.Write(buf, binary.LittleEndian, blockCounter)
if err != nil {
return nil, err
}
return buf.Bytes(), nil
}
+12 -8
View File
@@ -15,15 +15,15 @@ import (
)
const (
mqttBroker = "mqtt.bayme.sh"
mqttUsername = "meshdev"
mqttPassword = "large4cats"
mqttBroker = "mqtt.bayme.sh"
mqttUsername = "meshdev"
mqttPassword = "large4cats"
mqttTopicPrefix = "msh/US/CA/Motherlode"
)
var messagePubHandler mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) {
fmt.Printf("Received message from topic: %s\n", msg.Topic())
// Parse the topic structure
topicInfo, err := decoder.ParseTopic(msg.Topic())
if err != nil {
@@ -35,7 +35,7 @@ var messagePubHandler mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Me
formattedOutput := decoder.FormatMessage(topicInfo, msg.Payload())
fmt.Println(formattedOutput)
}
fmt.Println(strings.Repeat("-", 80))
}
@@ -50,13 +50,17 @@ var connectLostHandler mqtt.ConnectionLostHandler = func(client mqtt.Client, err
func main() {
// Set up logging
log.SetOutput(os.Stdout)
// Initialize default channel key
err := decoder.AddChannelKey("LongFast", decoder.DefaultPrivateKey)
if err != nil {
log.Printf("Failed to initialize default channel key: %v", err)
}
if err := decoder.AddChannelKey("ERSN", "VIuMtC5uDDJtC/ojdH314HLkDIHanX4LdbK5yViV9jA="); err != nil {
log.Printf("Failed to initialize ERSN channel key: %v", err)
}
// Create MQTT client options
opts := mqtt.NewClientOptions()
opts.AddBroker(fmt.Sprintf("tcp://%s:1883", mqttBroker))
@@ -93,4 +97,4 @@ func main() {
token = client.Unsubscribe(topic)
token.Wait()
client.Disconnect(250)
}
}
+2 -2
View File
@@ -711,7 +711,7 @@ var File_meshtastic_deviceonly_proto protoreflect.FileDescriptor
const file_meshtastic_deviceonly_proto_rawDesc = "" +
"\n" +
"\x1bmeshtastic/deviceonly.proto\x12\n" +
"meshtastic\x1a\x18meshtastic/channel.proto\x1a\x15meshtastic/mesh.proto\x1a\x1ameshtastic/telemetry.proto\x1a\x17meshtastic/config.proto\x1a\x1ameshtastic/localonly.proto\x1a\fnanopb.proto\"\xc7\x01\n" +
"meshtastic\x1a\x18meshtastic/channel.proto\x1a\x15meshtastic/mesh.proto\x1a\x1ameshtastic/telemetry.proto\x1a\x17meshtastic/config.proto\x1a\x1ameshtastic/localonly.proto\x1a\x17meshtastic/nanopb.proto\"\xc7\x01\n" +
"\fPositionLite\x12\x1d\n" +
"\n" +
"latitude_i\x18\x01 \x01(\x0fR\tlatitudeI\x12\x1f\n" +
@@ -846,7 +846,7 @@ func file_meshtastic_deviceonly_proto_init() {
file_meshtastic_telemetry_proto_init()
file_meshtastic_config_proto_init()
file_meshtastic_localonly_proto_init()
file_nanopb_proto_init()
file_meshtastic_nanopb_proto_init()
file_meshtastic_deviceonly_proto_msgTypes[2].OneofWrappers = []any{}
type x struct{}
out := protoimpl.TypeBuilder{
@@ -9,7 +9,7 @@
// versions:
// protoc-gen-go v1.36.6
// protoc v5.29.3
// source: nanopb.proto
// source: meshtastic/nanopb.proto
package generated
@@ -71,11 +71,11 @@ func (x FieldType) String() string {
}
func (FieldType) Descriptor() protoreflect.EnumDescriptor {
return file_nanopb_proto_enumTypes[0].Descriptor()
return file_meshtastic_nanopb_proto_enumTypes[0].Descriptor()
}
func (FieldType) Type() protoreflect.EnumType {
return &file_nanopb_proto_enumTypes[0]
return &file_meshtastic_nanopb_proto_enumTypes[0]
}
func (x FieldType) Number() protoreflect.EnumNumber {
@@ -94,7 +94,7 @@ func (x *FieldType) UnmarshalJSON(b []byte) error {
// Deprecated: Use FieldType.Descriptor instead.
func (FieldType) EnumDescriptor() ([]byte, []int) {
return file_nanopb_proto_rawDescGZIP(), []int{0}
return file_meshtastic_nanopb_proto_rawDescGZIP(), []int{0}
}
type IntSize int32
@@ -136,11 +136,11 @@ func (x IntSize) String() string {
}
func (IntSize) Descriptor() protoreflect.EnumDescriptor {
return file_nanopb_proto_enumTypes[1].Descriptor()
return file_meshtastic_nanopb_proto_enumTypes[1].Descriptor()
}
func (IntSize) Type() protoreflect.EnumType {
return &file_nanopb_proto_enumTypes[1]
return &file_meshtastic_nanopb_proto_enumTypes[1]
}
func (x IntSize) Number() protoreflect.EnumNumber {
@@ -159,7 +159,7 @@ func (x *IntSize) UnmarshalJSON(b []byte) error {
// Deprecated: Use IntSize.Descriptor instead.
func (IntSize) EnumDescriptor() ([]byte, []int) {
return file_nanopb_proto_rawDescGZIP(), []int{1}
return file_meshtastic_nanopb_proto_rawDescGZIP(), []int{1}
}
type TypenameMangling int32
@@ -198,11 +198,11 @@ func (x TypenameMangling) String() string {
}
func (TypenameMangling) Descriptor() protoreflect.EnumDescriptor {
return file_nanopb_proto_enumTypes[2].Descriptor()
return file_meshtastic_nanopb_proto_enumTypes[2].Descriptor()
}
func (TypenameMangling) Type() protoreflect.EnumType {
return &file_nanopb_proto_enumTypes[2]
return &file_meshtastic_nanopb_proto_enumTypes[2]
}
func (x TypenameMangling) Number() protoreflect.EnumNumber {
@@ -221,7 +221,7 @@ func (x *TypenameMangling) UnmarshalJSON(b []byte) error {
// Deprecated: Use TypenameMangling.Descriptor instead.
func (TypenameMangling) EnumDescriptor() ([]byte, []int) {
return file_nanopb_proto_rawDescGZIP(), []int{2}
return file_meshtastic_nanopb_proto_rawDescGZIP(), []int{2}
}
type DescriptorSize int32
@@ -263,11 +263,11 @@ func (x DescriptorSize) String() string {
}
func (DescriptorSize) Descriptor() protoreflect.EnumDescriptor {
return file_nanopb_proto_enumTypes[3].Descriptor()
return file_meshtastic_nanopb_proto_enumTypes[3].Descriptor()
}
func (DescriptorSize) Type() protoreflect.EnumType {
return &file_nanopb_proto_enumTypes[3]
return &file_meshtastic_nanopb_proto_enumTypes[3]
}
func (x DescriptorSize) Number() protoreflect.EnumNumber {
@@ -286,7 +286,7 @@ func (x *DescriptorSize) UnmarshalJSON(b []byte) error {
// Deprecated: Use DescriptorSize.Descriptor instead.
func (DescriptorSize) EnumDescriptor() ([]byte, []int) {
return file_nanopb_proto_rawDescGZIP(), []int{3}
return file_meshtastic_nanopb_proto_rawDescGZIP(), []int{3}
}
// This is the inner options message, which basically defines options for
@@ -404,7 +404,7 @@ const (
func (x *NanoPBOptions) Reset() {
*x = NanoPBOptions{}
mi := &file_nanopb_proto_msgTypes[0]
mi := &file_meshtastic_nanopb_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -416,7 +416,7 @@ func (x *NanoPBOptions) String() string {
func (*NanoPBOptions) ProtoMessage() {}
func (x *NanoPBOptions) ProtoReflect() protoreflect.Message {
mi := &file_nanopb_proto_msgTypes[0]
mi := &file_meshtastic_nanopb_proto_msgTypes[0]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -429,7 +429,7 @@ func (x *NanoPBOptions) ProtoReflect() protoreflect.Message {
// Deprecated: Use NanoPBOptions.ProtoReflect.Descriptor instead.
func (*NanoPBOptions) Descriptor() ([]byte, []int) {
return file_nanopb_proto_rawDescGZIP(), []int{0}
return file_meshtastic_nanopb_proto_rawDescGZIP(), []int{0}
}
func (x *NanoPBOptions) GetMaxSize() int32 {
@@ -635,14 +635,14 @@ func (x *NanoPBOptions) GetFallbackType() FieldType {
return Default_NanoPBOptions_FallbackType
}
var file_nanopb_proto_extTypes = []protoimpl.ExtensionInfo{
var file_meshtastic_nanopb_proto_extTypes = []protoimpl.ExtensionInfo{
{
ExtendedType: (*descriptorpb.FileOptions)(nil),
ExtensionType: (*NanoPBOptions)(nil),
Field: 1010,
Name: "nanopb_fileopt",
Tag: "bytes,1010,opt,name=nanopb_fileopt",
Filename: "nanopb.proto",
Filename: "meshtastic/nanopb.proto",
},
{
ExtendedType: (*descriptorpb.MessageOptions)(nil),
@@ -650,7 +650,7 @@ var file_nanopb_proto_extTypes = []protoimpl.ExtensionInfo{
Field: 1010,
Name: "nanopb_msgopt",
Tag: "bytes,1010,opt,name=nanopb_msgopt",
Filename: "nanopb.proto",
Filename: "meshtastic/nanopb.proto",
},
{
ExtendedType: (*descriptorpb.EnumOptions)(nil),
@@ -658,7 +658,7 @@ var file_nanopb_proto_extTypes = []protoimpl.ExtensionInfo{
Field: 1010,
Name: "nanopb_enumopt",
Tag: "bytes,1010,opt,name=nanopb_enumopt",
Filename: "nanopb.proto",
Filename: "meshtastic/nanopb.proto",
},
{
ExtendedType: (*descriptorpb.FieldOptions)(nil),
@@ -666,39 +666,39 @@ var file_nanopb_proto_extTypes = []protoimpl.ExtensionInfo{
Field: 1010,
Name: "nanopb",
Tag: "bytes,1010,opt,name=nanopb",
Filename: "nanopb.proto",
Filename: "meshtastic/nanopb.proto",
},
}
// Extension fields to descriptorpb.FileOptions.
var (
// optional NanoPBOptions nanopb_fileopt = 1010;
E_NanopbFileopt = &file_nanopb_proto_extTypes[0]
E_NanopbFileopt = &file_meshtastic_nanopb_proto_extTypes[0]
)
// Extension fields to descriptorpb.MessageOptions.
var (
// optional NanoPBOptions nanopb_msgopt = 1010;
E_NanopbMsgopt = &file_nanopb_proto_extTypes[1]
E_NanopbMsgopt = &file_meshtastic_nanopb_proto_extTypes[1]
)
// Extension fields to descriptorpb.EnumOptions.
var (
// optional NanoPBOptions nanopb_enumopt = 1010;
E_NanopbEnumopt = &file_nanopb_proto_extTypes[2]
E_NanopbEnumopt = &file_meshtastic_nanopb_proto_extTypes[2]
)
// Extension fields to descriptorpb.FieldOptions.
var (
// optional NanoPBOptions nanopb = 1010;
E_Nanopb = &file_nanopb_proto_extTypes[3]
E_Nanopb = &file_meshtastic_nanopb_proto_extTypes[3]
)
var File_nanopb_proto protoreflect.FileDescriptor
var File_meshtastic_nanopb_proto protoreflect.FileDescriptor
const file_nanopb_proto_rawDesc = "" +
const file_meshtastic_nanopb_proto_rawDesc = "" +
"\n" +
"\fnanopb.proto\x1a google/protobuf/descriptor.proto\"\x86\n" +
"\x17meshtastic/nanopb.proto\x1a google/protobuf/descriptor.proto\"\x86\n" +
"\n" +
"\rNanoPBOptions\x12\x19\n" +
"\bmax_size\x18\x01 \x01(\x05R\amaxSize\x12\x1d\n" +
@@ -775,20 +775,20 @@ const file_nanopb_proto_rawDesc = "" +
"\x18fi.kapsi.koti.jpa.nanopbZ\"github.com/meshtastic/go/generated"
var (
file_nanopb_proto_rawDescOnce sync.Once
file_nanopb_proto_rawDescData []byte
file_meshtastic_nanopb_proto_rawDescOnce sync.Once
file_meshtastic_nanopb_proto_rawDescData []byte
)
func file_nanopb_proto_rawDescGZIP() []byte {
file_nanopb_proto_rawDescOnce.Do(func() {
file_nanopb_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_nanopb_proto_rawDesc), len(file_nanopb_proto_rawDesc)))
func file_meshtastic_nanopb_proto_rawDescGZIP() []byte {
file_meshtastic_nanopb_proto_rawDescOnce.Do(func() {
file_meshtastic_nanopb_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_meshtastic_nanopb_proto_rawDesc), len(file_meshtastic_nanopb_proto_rawDesc)))
})
return file_nanopb_proto_rawDescData
return file_meshtastic_nanopb_proto_rawDescData
}
var file_nanopb_proto_enumTypes = make([]protoimpl.EnumInfo, 4)
var file_nanopb_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_nanopb_proto_goTypes = []any{
var file_meshtastic_nanopb_proto_enumTypes = make([]protoimpl.EnumInfo, 4)
var file_meshtastic_nanopb_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_meshtastic_nanopb_proto_goTypes = []any{
(FieldType)(0), // 0: FieldType
(IntSize)(0), // 1: IntSize
(TypenameMangling)(0), // 2: TypenameMangling
@@ -800,7 +800,7 @@ var file_nanopb_proto_goTypes = []any{
(*descriptorpb.EnumOptions)(nil), // 8: google.protobuf.EnumOptions
(*descriptorpb.FieldOptions)(nil), // 9: google.protobuf.FieldOptions
}
var file_nanopb_proto_depIdxs = []int32{
var file_meshtastic_nanopb_proto_depIdxs = []int32{
1, // 0: NanoPBOptions.int_size:type_name -> IntSize
0, // 1: NanoPBOptions.type:type_name -> FieldType
2, // 2: NanoPBOptions.mangle_names:type_name -> TypenameMangling
@@ -822,28 +822,28 @@ var file_nanopb_proto_depIdxs = []int32{
0, // [0:6] is the sub-list for field type_name
}
func init() { file_nanopb_proto_init() }
func file_nanopb_proto_init() {
if File_nanopb_proto != nil {
func init() { file_meshtastic_nanopb_proto_init() }
func file_meshtastic_nanopb_proto_init() {
if File_meshtastic_nanopb_proto != nil {
return
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_nanopb_proto_rawDesc), len(file_nanopb_proto_rawDesc)),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_meshtastic_nanopb_proto_rawDesc), len(file_meshtastic_nanopb_proto_rawDesc)),
NumEnums: 4,
NumMessages: 1,
NumExtensions: 4,
NumServices: 0,
},
GoTypes: file_nanopb_proto_goTypes,
DependencyIndexes: file_nanopb_proto_depIdxs,
EnumInfos: file_nanopb_proto_enumTypes,
MessageInfos: file_nanopb_proto_msgTypes,
ExtensionInfos: file_nanopb_proto_extTypes,
GoTypes: file_meshtastic_nanopb_proto_goTypes,
DependencyIndexes: file_meshtastic_nanopb_proto_depIdxs,
EnumInfos: file_meshtastic_nanopb_proto_enumTypes,
MessageInfos: file_meshtastic_nanopb_proto_msgTypes,
ExtensionInfos: file_meshtastic_nanopb_proto_extTypes,
}.Build()
File_nanopb_proto = out.File
file_nanopb_proto_goTypes = nil
file_nanopb_proto_depIdxs = nil
File_meshtastic_nanopb_proto = out.File
file_meshtastic_nanopb_proto_goTypes = nil
file_meshtastic_nanopb_proto_depIdxs = nil
}
+1 -1
View File
@@ -7,7 +7,7 @@ import "meshtastic/mesh.proto";
import "meshtastic/telemetry.proto";
import "meshtastic/config.proto";
import "meshtastic/localonly.proto";
import "nanopb.proto";
import "meshtastic/nanopb.proto";
option csharp_namespace = "Meshtastic.Protobufs";
option go_package = "github.com/meshtastic/go/generated";