Path: blob/main/SignalServiceKit/Account/IdentityKeyChecker.swift
1 views
//
// Copyright 2023 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
//
import LibSignalClient
protocol IdentityKeyChecker {
func serverHasSameKeyAsLocal(for identity: OWSIdentity, localIdentifier: ServiceId) async throws -> Bool
}
class IdentityKeyCheckerImpl: IdentityKeyChecker {
private let db: any DB
private let identityManager: OWSIdentityManager
private let profileFetcher: Shims.ProfileFetcher
init(
db: any DB,
identityManager: OWSIdentityManager,
profileFetcher: Shims.ProfileFetcher,
) {
self.db = db
self.identityManager = identityManager
self.profileFetcher = profileFetcher
}
func serverHasSameKeyAsLocal(for identity: OWSIdentity, localIdentifier: ServiceId) async throws -> Bool {
owsPrecondition((identity == .aci && localIdentifier is Aci) || (identity == .pni && localIdentifier is Pni))
let remoteIdentityKey = try await self.profileFetcher.fetchIdentityPublicKey(serviceId: localIdentifier)
let localIdentityKey = self.db.read(block: { tx -> IdentityKey? in
return self.identityManager.identityKeyPair(for: identity, tx: tx)?.keyPair.identityKey
})
return remoteIdentityKey == localIdentityKey
}
}
// MARK: - Dependencies
extension IdentityKeyCheckerImpl {
enum Shims {
typealias ProfileFetcher = _IdentityKeyCheckerImpl_ProfileFetcher_Shim
}
enum Wrappers {
typealias ProfileFetcher = _IdentityKeyCheckerImpl_ProfileFetcher_Wrapper
}
}
// MARK: ProfileFetcher
protocol _IdentityKeyCheckerImpl_ProfileFetcher_Shim {
func fetchIdentityPublicKey(serviceId: ServiceId) async throws -> IdentityKey
}
class _IdentityKeyCheckerImpl_ProfileFetcher_Wrapper: _IdentityKeyCheckerImpl_ProfileFetcher_Shim {
private let networkManager: NetworkManager
init(networkManager: NetworkManager) {
self.networkManager = networkManager
}
func fetchIdentityPublicKey(serviceId: ServiceId) async throws -> IdentityKey {
let request = OWSRequestFactory.getUnversionedProfileRequest(
serviceId: serviceId,
auth: .identified(.implicit()),
)
let response = try await networkManager.asyncRequest(request)
struct Response: Decodable {
var identityKey: Data
}
let decodedResponse = try JSONDecoder().decode(Response.self, from: response.responseBodyData ?? Data())
return try IdentityKey(bytes: decodedResponse.identityKey)
}
}