mirror of
https://github.com/permissionlesstech/bitchat.git
synced 2026-07-25 14:05:18 +00:00
Fix encryption key exchange and add persistent identity for favorites
- Implement three-tier key system: ephemeral encryption, ephemeral signing, persistent identity - Fix signature verification by properly separating KeyAgreement and Signing keys - Add persistent identity key for favorites that survives app restarts - Fix Data subscript crashes by converting to byte arrays - Add proper error handling for key exchange - Private messages remain fully encrypted with ephemeral keys
This commit is contained in:
@@ -185,7 +185,6 @@ extension BitchatMessage {
|
||||
// - Recipient nickname length + data
|
||||
// - Sender peer ID length + data
|
||||
// - Mentions array
|
||||
// - Voice note duration (8 bytes, double) + data length (4 bytes) + data
|
||||
|
||||
var flags: UInt8 = 0
|
||||
if isRelay { flags |= 0x01 }
|
||||
@@ -194,7 +193,6 @@ extension BitchatMessage {
|
||||
if recipientNickname != nil { flags |= 0x08 }
|
||||
if senderPeerID != nil { flags |= 0x10 }
|
||||
if mentions != nil && !mentions!.isEmpty { flags |= 0x20 }
|
||||
if voiceNoteData != nil { flags |= 0x40 }
|
||||
|
||||
data.append(flags)
|
||||
|
||||
@@ -261,24 +259,6 @@ extension BitchatMessage {
|
||||
}
|
||||
}
|
||||
|
||||
// Voice note data
|
||||
if let voiceData = voiceNoteData, let duration = voiceNoteDuration {
|
||||
// Duration as 8 bytes (double)
|
||||
let durationBits = duration.bitPattern
|
||||
for i in (0..<8).reversed() {
|
||||
data.append(UInt8((durationBits >> (i * 8)) & 0xFF))
|
||||
}
|
||||
|
||||
// Voice data length as 4 bytes (UInt32)
|
||||
let voiceLength = UInt32(min(voiceData.count, Int(UInt32.max)))
|
||||
for i in (0..<4).reversed() {
|
||||
data.append(UInt8((voiceLength >> (i * 8)) & 0xFF))
|
||||
}
|
||||
|
||||
// Voice data
|
||||
data.append(voiceData.prefix(Int(voiceLength)))
|
||||
}
|
||||
|
||||
return data
|
||||
}
|
||||
|
||||
@@ -304,7 +284,6 @@ extension BitchatMessage {
|
||||
let hasRecipientNickname = (flags & 0x08) != 0
|
||||
let hasSenderPeerID = (flags & 0x10) != 0
|
||||
let hasMentions = (flags & 0x20) != 0
|
||||
let hasVoiceNote = (flags & 0x40) != 0
|
||||
|
||||
// Timestamp
|
||||
guard offset + 8 <= dataCopy.count else {
|
||||
@@ -402,31 +381,6 @@ extension BitchatMessage {
|
||||
}
|
||||
}
|
||||
|
||||
// Voice note data
|
||||
var voiceNoteData: Data?
|
||||
var voiceNoteDuration: TimeInterval?
|
||||
if hasVoiceNote && offset + 12 <= dataCopy.count {
|
||||
// Duration (8 bytes)
|
||||
let durationData = dataCopy[offset..<offset+8]
|
||||
let durationBits = durationData.reduce(0) { result, byte in
|
||||
(result << 8) | UInt64(byte)
|
||||
}
|
||||
voiceNoteDuration = TimeInterval(bitPattern: durationBits)
|
||||
offset += 8
|
||||
|
||||
// Voice data length (4 bytes)
|
||||
let lengthData = dataCopy[offset..<offset+4]
|
||||
let voiceLength = lengthData.reduce(0) { result, byte in
|
||||
(result << 8) | UInt32(byte)
|
||||
}
|
||||
offset += 4
|
||||
|
||||
// Voice data
|
||||
if offset + Int(voiceLength) <= dataCopy.count {
|
||||
voiceNoteData = dataCopy[offset..<offset+Int(voiceLength)]
|
||||
}
|
||||
}
|
||||
|
||||
let message = BitchatMessage(
|
||||
sender: sender,
|
||||
content: content,
|
||||
@@ -436,9 +390,7 @@ extension BitchatMessage {
|
||||
isPrivate: isPrivate,
|
||||
recipientNickname: recipientNickname,
|
||||
senderPeerID: senderPeerID,
|
||||
mentions: mentions,
|
||||
voiceNoteData: voiceNoteData,
|
||||
voiceNoteDuration: voiceNoteDuration
|
||||
mentions: mentions
|
||||
)
|
||||
return message
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ enum MessageType: UInt8 {
|
||||
case keyExchange = 0x06
|
||||
case leave = 0x07
|
||||
case privateMessage = 0x08
|
||||
case voiceNote = 0x09
|
||||
case fragmentStart = 0x0A // First fragment of a large message
|
||||
case fragmentContinue = 0x0B // Continuation fragment
|
||||
case fragmentEnd = 0x0C // Last fragment
|
||||
@@ -73,10 +72,8 @@ struct BitchatMessage: Codable, Equatable {
|
||||
let recipientNickname: String?
|
||||
let senderPeerID: String?
|
||||
let mentions: [String]? // Array of mentioned nicknames
|
||||
let voiceNoteData: Data? // Audio data for voice notes
|
||||
let voiceNoteDuration: TimeInterval? // Duration in seconds
|
||||
|
||||
init(sender: String, content: String, timestamp: Date, isRelay: Bool, originalSender: String? = nil, isPrivate: Bool = false, recipientNickname: String? = nil, senderPeerID: String? = nil, mentions: [String]? = nil, voiceNoteData: Data? = nil, voiceNoteDuration: TimeInterval? = nil) {
|
||||
init(sender: String, content: String, timestamp: Date, isRelay: Bool, originalSender: String? = nil, isPrivate: Bool = false, recipientNickname: String? = nil, senderPeerID: String? = nil, mentions: [String]? = nil) {
|
||||
self.id = UUID().uuidString
|
||||
self.sender = sender
|
||||
self.content = content
|
||||
@@ -87,8 +84,6 @@ struct BitchatMessage: Codable, Equatable {
|
||||
self.recipientNickname = recipientNickname
|
||||
self.senderPeerID = senderPeerID
|
||||
self.mentions = mentions
|
||||
self.voiceNoteData = voiceNoteData
|
||||
self.voiceNoteDuration = voiceNoteDuration
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user