You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
session-ios/SessionMessagingKit/Utilities/Authentication+SessionMessa...

129 lines
4.9 KiB
Swift

// Copyright © 2023 Rangeproof Pty Ltd. All rights reserved.
import Foundation
import GRDB
import SessionSnodeKit
import SessionUtilitiesKit
// MARK: - Authentication Types
public extension Authentication {
/// Used for when interacting as the current user
struct standard: AuthenticationMethod {
public let sessionId: SessionId
public let ed25519KeyPair: KeyPair
public var info: Info { .standard(sessionId: sessionId, ed25519KeyPair: ed25519KeyPair) }
public init(sessionId: SessionId, ed25519KeyPair: KeyPair) {
self.sessionId = sessionId
self.ed25519KeyPair = ed25519KeyPair
}
// MARK: - SignatureGenerator
public func generateSignature(with verificationBytes: [UInt8], using dependencies: Dependencies) throws -> Authentication.Signature {
return try dependencies[singleton: .crypto].tryGenerate(
.signature(message: verificationBytes, ed25519SecretKey: ed25519KeyPair.secretKey)
)
}
}
/// Used for when interacting as a group admin
struct groupAdmin: AuthenticationMethod {
public let groupSessionId: SessionId
public let ed25519SecretKey: [UInt8]
public var info: Info { .groupAdmin(groupSessionId: groupSessionId, ed25519SecretKey: ed25519SecretKey) }
public init(groupSessionId: SessionId, ed25519SecretKey: [UInt8]) {
self.groupSessionId = groupSessionId
self.ed25519SecretKey = ed25519SecretKey
}
// MARK: - SignatureGenerator
public func generateSignature(with verificationBytes: [UInt8], using dependencies: Dependencies) throws -> Authentication.Signature {
return try dependencies[singleton: .crypto].tryGenerate(
.signature(message: verificationBytes, ed25519SecretKey: ed25519SecretKey)
)
}
}
/// Used for when interacting as a group member
struct groupMember: AuthenticationMethod {
public let groupSessionId: SessionId
public let authData: Data
public var info: Info { .groupMember(groupSessionId: groupSessionId, authData: authData) }
public init(groupSessionId: SessionId, authData: Data) {
self.groupSessionId = groupSessionId
self.authData = authData
}
// MARK: - SignatureGenerator
public func generateSignature(with verificationBytes: [UInt8], using dependencies: Dependencies) throws -> Authentication.Signature {
return try dependencies.mutate(cache: .libSession) { cache in
try dependencies[singleton: .crypto].tryGenerate(
.signatureSubaccount(
config: cache.config(for: .groupKeys, sessionId: groupSessionId),
verificationBytes: verificationBytes,
memberAuthData: authData
)
)
}
}
}
}
// MARK: - Convenience
fileprivate struct GroupAuthData: Codable, FetchableRecord {
let groupIdentityPrivateKey: Data?
let authData: Data?
}
public extension Authentication {
static func with(
_ db: Database,
swarmPublicKey: String,
using dependencies: Dependencies
) throws -> AuthenticationMethod {
switch try? SessionId(from: swarmPublicKey) {
case .some(let sessionId) where sessionId.prefix == .standard:
guard let keyPair: KeyPair = Identity.fetchUserEd25519KeyPair(db) else {
throw SnodeAPIError.noKeyPair
}
return Authentication.standard(sessionId: sessionId, ed25519KeyPair: keyPair)
case .some(let sessionId) where sessionId.prefix == .group:
let authData: GroupAuthData? = try? ClosedGroup
.filter(id: swarmPublicKey)
.select(.authData, .groupIdentityPrivateKey)
.asRequest(of: GroupAuthData.self)
.fetchOne(db)
switch (authData?.groupIdentityPrivateKey, authData?.authData) {
case (.some(let privateKey), _):
return Authentication.groupAdmin(
groupSessionId: sessionId,
ed25519SecretKey: Array(privateKey)
)
case (_, .some(let authData)):
return Authentication.groupMember(
groupSessionId: sessionId,
authData: authData
)
default: throw SnodeAPIError.invalidAuthentication
}
default: throw SnodeAPIError.invalidAuthentication
}
}
}