mv-experiment #1
|
@ -54,8 +54,12 @@ trailing_semicolon:
|
||||||
severity: error
|
severity: error
|
||||||
|
|
||||||
type_name:
|
type_name:
|
||||||
min_length: 3
|
min_length:
|
||||||
severity: warning
|
warninig: 3
|
||||||
|
error: 0
|
||||||
|
max_length:
|
||||||
|
warninig: 40
|
||||||
|
error: 80
|
||||||
|
|
||||||
identifier_name:
|
identifier_name:
|
||||||
min_length: 3
|
min_length: 3
|
||||||
|
@ -73,6 +77,7 @@ identifier_name:
|
||||||
- tz
|
- tz
|
||||||
- to
|
- to
|
||||||
- db
|
- db
|
||||||
|
- _db
|
||||||
|
|
||||||
# Disable rules from the default enabled set.
|
# Disable rules from the default enabled set.
|
||||||
disabled_rules:
|
disabled_rules:
|
||||||
|
|
174
ConversationsClassic/AppData/Client/Client+MartinOMEMO.swift
Normal file
174
ConversationsClassic/AppData/Client/Client+MartinOMEMO.swift
Normal file
|
@ -0,0 +1,174 @@
|
||||||
|
import Foundation
|
||||||
|
import GRDB
|
||||||
|
import Martin
|
||||||
|
import MartinOMEMO
|
||||||
|
|
||||||
|
final class ClientMartinOMEMO {
|
||||||
|
let credentials: Credentials
|
||||||
|
|
||||||
|
init(_ credentials: Credentials) {
|
||||||
|
self.credentials = credentials
|
||||||
|
}
|
||||||
|
|
||||||
|
var signal: (SignalStorage, SignalContext) {
|
||||||
|
let signalStorage = SignalStorage(sessionStore: self, preKeyStore: self, signedPreKeyStore: self, identityKeyStore: self, senderKeyStore: self)
|
||||||
|
// swiftlint:disable:next force_unwrapping
|
||||||
|
let signalContext = SignalContext(withStorage: signalStorage)!
|
||||||
|
signalStorage.setup(withContext: signalContext)
|
||||||
|
return (signalStorage, signalContext)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension ClientMartinOMEMO: SignalSessionStoreProtocol, SignalPreKeyStoreProtocol, SignalSignedPreKeyStoreProtocol, SignalIdentityKeyStoreProtocol, SignalSenderKeyStoreProtocol {
|
||||||
|
func sessionRecord(forAddress address: MartinOMEMO.SignalAddress) -> Data? {
|
||||||
|
// static let omemoSessionRecordLoad = Query("SELECT key FROM omemo_sessions WHERE account = :account AND name = :name AND device_id = :deviceId")
|
||||||
|
|
||||||
|
// do {
|
||||||
|
// let data = try Database.shared.dbQueue.read { db in
|
||||||
|
//
|
||||||
|
// try Row.fetchOne(db, sql: "SELECT key FROM omemo_sessions WHERE account = :account AND name = :name AND device_id = :deviceId", arguments: ["account": address.account, "name": address.name, "deviceId": address.deviceId])
|
||||||
|
// }
|
||||||
|
// return data?["key"]
|
||||||
|
// } catch {
|
||||||
|
// logIt(.error, "Error fetching chats: \(error.localizedDescription)")
|
||||||
|
// return nil
|
||||||
|
// }
|
||||||
|
print(address)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func allDevices(for _: String, activeAndTrusted: Bool) -> [Int32] {
|
||||||
|
print(activeAndTrusted, "allDevices")
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
func storeSessionRecord(_ data: Data, forAddress: MartinOMEMO.SignalAddress) -> Bool {
|
||||||
|
print(data, forAddress)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func containsSessionRecord(forAddress: MartinOMEMO.SignalAddress) -> Bool {
|
||||||
|
print(forAddress)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func deleteSessionRecord(forAddress: MartinOMEMO.SignalAddress) -> Bool {
|
||||||
|
print(forAddress)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func deleteAllSessions(for _: String) -> Bool {
|
||||||
|
print("deleteAllSessions")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func currentPreKeyId() -> UInt32 {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadPreKey(withId: UInt32) -> Data? {
|
||||||
|
print(withId)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func storePreKey(_ data: Data, withId: UInt32) -> Bool {
|
||||||
|
print(data, withId)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func containsPreKey(withId: UInt32) -> Bool {
|
||||||
|
print(withId)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func deletePreKey(withId: UInt32) -> Bool {
|
||||||
|
print(withId)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func flushDeletedPreKeys() -> Bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
func countSignedPreKeys() -> Int {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadSignedPreKey(withId: UInt32) -> Data? {
|
||||||
|
print(withId)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func storeSignedPreKey(_ data: Data, withId: UInt32) -> Bool {
|
||||||
|
print(data, withId)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func containsSignedPreKey(withId: UInt32) -> Bool {
|
||||||
|
print(withId)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func deleteSignedPreKey(withId: UInt32) -> Bool {
|
||||||
|
print(withId)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func keyPair() -> (any MartinOMEMO.SignalIdentityKeyPairProtocol)? {
|
||||||
|
nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func localRegistrationId() -> UInt32 {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
func save(identity: MartinOMEMO.SignalAddress, key: (any MartinOMEMO.SignalIdentityKeyProtocol)?) -> Bool {
|
||||||
|
print(identity, key)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func isTrusted(identity: MartinOMEMO.SignalAddress, key: (any MartinOMEMO.SignalIdentityKeyProtocol)?) -> Bool {
|
||||||
|
print(identity, key)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func save(identity: MartinOMEMO.SignalAddress, publicKeyData: Data?) -> Bool {
|
||||||
|
print(identity, publicKeyData)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func isTrusted(identity: MartinOMEMO.SignalAddress, publicKeyData: Data?) -> Bool {
|
||||||
|
print(identity, publicKeyData)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func setStatus(_ status: MartinOMEMO.IdentityStatus, forIdentity: MartinOMEMO.SignalAddress) -> Bool {
|
||||||
|
print(status, forIdentity)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func setStatus(active: Bool, forIdentity: MartinOMEMO.SignalAddress) -> Bool {
|
||||||
|
print(active, forIdentity)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func identities(forName: String) -> [MartinOMEMO.Identity] {
|
||||||
|
print(forName)
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
func identityFingerprint(forAddress address: MartinOMEMO.SignalAddress) -> String? {
|
||||||
|
print(address)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func storeSenderKey(_ key: Data, address: MartinOMEMO.SignalAddress?, groupId: String?) -> Bool {
|
||||||
|
print(key, address, groupId)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadSenderKey(forAddress: MartinOMEMO.SignalAddress?, groupId: String?) -> Data? {
|
||||||
|
print(forAddress, groupId)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,7 @@ import Combine
|
||||||
import Foundation
|
import Foundation
|
||||||
import GRDB
|
import GRDB
|
||||||
import Martin
|
import Martin
|
||||||
|
import MartinOMEMO
|
||||||
|
|
||||||
enum ClientState: Equatable {
|
enum ClientState: Equatable {
|
||||||
enum ClientConnectionState {
|
enum ClientConnectionState {
|
||||||
|
@ -190,13 +191,17 @@ private extension Client {
|
||||||
client.connectionConfiguration.userJid = .init(credentials.bareJid)
|
client.connectionConfiguration.userJid = .init(credentials.bareJid)
|
||||||
client.connectionConfiguration.credentials = .password(password: credentials.pass)
|
client.connectionConfiguration.credentials = .password(password: credentials.pass)
|
||||||
|
|
||||||
|
// OMEMO
|
||||||
|
let omemoManager = ClientMartinOMEMO(credentials)
|
||||||
|
let (signalStorage, signalContext) = omemoManager.signal
|
||||||
|
client.modulesManager.register(OMEMOModule(aesGCMEngine: AESGSMEngine.shared, signalContext: signalContext, signalStorage: signalStorage))
|
||||||
|
|
||||||
// group chats
|
// group chats
|
||||||
// client.modulesManager.register(MucModule(roomManager: manager))
|
// client.modulesManager.register(MucModule(roomManager: manager))
|
||||||
|
|
||||||
// channels
|
// channels
|
||||||
// client.modulesManager.register(MixModule(channelManager: manager))
|
// client.modulesManager.register(MixModule(channelManager: manager))
|
||||||
|
|
||||||
// add client to clients
|
|
||||||
return client
|
return client
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
18
ConversationsClassic/AppData/Services/AESGSMEngine.swift
Normal file
18
ConversationsClassic/AppData/Services/AESGSMEngine.swift
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
import CryptoKit
|
||||||
|
import Foundation
|
||||||
|
import MartinOMEMO
|
||||||
|
|
||||||
|
final class AESGSMEngine: AES_GCM_Engine {
|
||||||
|
static let shared = AESGSMEngine()
|
||||||
|
|
||||||
|
private init() {}
|
||||||
|
func encrypt(iv: Data, key: Data, message: Data, output: UnsafeMutablePointer<Data>?, tag: UnsafeMutablePointer<Data>?) -> Bool {
|
||||||
|
print(iv, key, message, output, tag)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func decrypt(iv: Data, key: Data, encoded: Data, auth tag: Data?, output: UnsafeMutablePointer<Data>?) -> Bool {
|
||||||
|
print(iv, key, encoded, tag, output)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
|
@ -59,6 +59,50 @@ extension Database {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
migrator.registerMigration("Add OMEMO tables") { db in
|
||||||
|
try db.create(table: "omemo_sessions", options: [.ifNotExists]) { table in
|
||||||
|
table.column("account", .text).notNull()
|
||||||
|
table.column("name", .text).notNull()
|
||||||
|
table.column("device_id", .integer).notNull()
|
||||||
|
table.column("key", .text).notNull()
|
||||||
|
table.primaryKey(["account", "name", "device_id"], onConflict: .replace)
|
||||||
|
}
|
||||||
|
|
||||||
|
try db.create(table: "omemo_identities", options: [.ifNotExists]) { table in
|
||||||
|
table.column("account", .text).notNull()
|
||||||
|
table.column("name", .text).notNull()
|
||||||
|
table.column("device_id", .integer).notNull()
|
||||||
|
table.column("fingerprint", .text).notNull()
|
||||||
|
table.column("key", .blob).notNull()
|
||||||
|
table.column("own", .integer).notNull()
|
||||||
|
table.column("status", .integer).notNull()
|
||||||
|
table.primaryKey(["account", "name", "fingerprint"], onConflict: .ignore)
|
||||||
|
}
|
||||||
|
|
||||||
|
try db.create(table: "omemo_pre_keys", options: [.ifNotExists]) { table in
|
||||||
|
table.column("account", .text).notNull()
|
||||||
|
table.column("id", .integer).notNull()
|
||||||
|
table.column("key", .blob).notNull()
|
||||||
|
table.primaryKey(["account", "id"], onConflict: .replace)
|
||||||
|
}
|
||||||
|
|
||||||
|
try db.create(table: "omemo_signed_pre_keys", options: [.ifNotExists]) { table in
|
||||||
|
table.column("account", .text).notNull()
|
||||||
|
table.column("id", .integer).notNull()
|
||||||
|
table.column("key", .blob).notNull()
|
||||||
|
table.primaryKey(["account", "id"], onConflict: .replace)
|
||||||
|
}
|
||||||
|
|
||||||
|
try db.alter(table: "chats") { table in
|
||||||
|
table.add(column: "encryption", .text)
|
||||||
|
}
|
||||||
|
|
||||||
|
try db.alter(table: "chat_history") { table in
|
||||||
|
table.add(column: "encryption", .integer)
|
||||||
|
table.add(column: "fingerprint", .text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// return migrator
|
// return migrator
|
||||||
return migrator
|
return migrator
|
||||||
}()
|
}()
|
||||||
|
|
|
@ -75,6 +75,7 @@ targets:
|
||||||
# keychain-access-groups: imt.narayana.ConversationsClassic.ios
|
# keychain-access-groups: imt.narayana.ConversationsClassic.ios
|
||||||
dependencies:
|
dependencies:
|
||||||
- sdk: Security.framework
|
- sdk: Security.framework
|
||||||
|
- sdk: CryptoKit.framework
|
||||||
# - framework: Lib/WebRTC.xcframework
|
# - framework: Lib/WebRTC.xcframework
|
||||||
# - target: Engine
|
# - target: Engine
|
||||||
- package: SwiftfulRouting
|
- package: SwiftfulRouting
|
||||||
|
|
Loading…
Reference in a new issue