From 5d25580a6c1c89034954fb4d36f72c05933c39e8 Mon Sep 17 00:00:00 2001 From: goncalo-frade-iohk Date: Sat, 16 Dec 2023 14:46:47 +0000 Subject: [PATCH] feat(pluto): pluto will save link secret as a storable key. BREAKING CHANGE: This makes changes on pluto interface. --- .../Sources/ApolloImpl+KeyRestoration.swift | 13 ++++ .../Apollo/Sources/ApolloImpl+Public.swift | 4 +- .../Apollo/Sources/Model/LinkSecret.swift | 47 ++++++++++++ .../CreateLinkSecretOperation.swift | 8 -- AtalaPrismSDK/Domain/Sources/BBs/Apollo.swift | 5 +- AtalaPrismSDK/Domain/Sources/BBs/Pluto.swift | 4 +- .../Models/KeyManagement/KeyRestoration.swift | 16 ++++ .../Domain/Providers/LinkSecretProvider.swift | 3 +- .../Domain/Stores/LinkSecretStore.swift | 3 +- ...DPrivateKeyDAO+DIDPrivateKeyProvider.swift | 47 +----------- ...DDIDPrivateKeyDAO+DIDPrivateKeyStore.swift | 6 +- .../DAO/CDDIDPrivateKeyDAO.swift | 2 - .../DAO/CDKeyDAO+LinkSecretProvider.swift | 11 +++ .../DAO/CDKeyDAO+LinkSecretStore.swift | 73 +++++++++++++++++++ .../PersistentStorage/DAO/CDKeyDAO.swift | 41 +++++++++++ .../CDLinkSecretDAO+LinkSecretProvider.swift | 10 --- .../DAO/CDLinkSecretDAO+LinkSecretStore.swift | 13 ---- .../Pluto/Sources/PlutoImpl+Public.swift | 8 +- AtalaPrismSDK/Pluto/Sources/PlutoImpl.swift | 14 ++-- .../PrismPluto.xcdatamodel/contents | 5 +- .../Pluto/Tests/CDDIDPairDAOTests.swift | 4 +- .../Pluto/Tests/CDDIDPrivateKeyDAOTests.swift | 16 ++-- .../Pluto/Tests/CDMessagesDAOTests.swift | 4 +- .../Tests/Helper/KeyRestoration+Test.swift | 8 ++ .../Sources/PrismAgent+Credentials.swift | 18 ++++- .../PrismAgent/Sources/PrismAgent.swift | 6 +- 26 files changed, 273 insertions(+), 116 deletions(-) create mode 100644 AtalaPrismSDK/Apollo/Sources/Model/LinkSecret.swift delete mode 100644 AtalaPrismSDK/Apollo/Sources/Operations/CreateLinkSecretOperation.swift create mode 100644 AtalaPrismSDK/Pluto/Sources/PersistentStorage/DAO/CDKeyDAO+LinkSecretProvider.swift create mode 100644 AtalaPrismSDK/Pluto/Sources/PersistentStorage/DAO/CDKeyDAO+LinkSecretStore.swift delete mode 100644 AtalaPrismSDK/Pluto/Sources/PersistentStorage/DAO/CDLinkSecretDAO+LinkSecretProvider.swift delete mode 100644 AtalaPrismSDK/Pluto/Sources/PersistentStorage/DAO/CDLinkSecretDAO+LinkSecretStore.swift diff --git a/AtalaPrismSDK/Apollo/Sources/ApolloImpl+KeyRestoration.swift b/AtalaPrismSDK/Apollo/Sources/ApolloImpl+KeyRestoration.swift index 55392553..8a151b34 100644 --- a/AtalaPrismSDK/Apollo/Sources/ApolloImpl+KeyRestoration.swift +++ b/AtalaPrismSDK/Apollo/Sources/ApolloImpl+KeyRestoration.swift @@ -10,6 +10,10 @@ extension ApolloImpl: KeyRestoration { identifier.hasSuffix("pub") } + public func isKeyData(identifier: String, data: Data) throws -> Bool { + identifier.hasSuffix("key") + } + public func restorePrivateKey(_ key: StorableKey) throws -> PrivateKey { switch key.restorationIdentifier { case "secp256k1+priv": @@ -38,4 +42,13 @@ extension ApolloImpl: KeyRestoration { throw ApolloError.restoratonFailedNoIdentifierOrInvalid } } + + public func restoreKey(_ key: StorableKey) async throws -> Key { + switch key.restorationIdentifier { + case "linkSecret+key": + return try LinkSecret(data: key.storableData) + default: + throw ApolloError.restoratonFailedNoIdentifierOrInvalid + } + } } diff --git a/AtalaPrismSDK/Apollo/Sources/ApolloImpl+Public.swift b/AtalaPrismSDK/Apollo/Sources/ApolloImpl+Public.swift index dea7c4be..c6754583 100644 --- a/AtalaPrismSDK/Apollo/Sources/ApolloImpl+Public.swift +++ b/AtalaPrismSDK/Apollo/Sources/ApolloImpl+Public.swift @@ -145,7 +145,7 @@ returns random mnemonics nerver returns invalid mnemonics } } - public func createNewLinkSecret() throws -> String { - try CreateLinkSecretOperation().create() + public func createNewLinkSecret() throws -> Key { + try LinkSecret() } } diff --git a/AtalaPrismSDK/Apollo/Sources/Model/LinkSecret.swift b/AtalaPrismSDK/Apollo/Sources/Model/LinkSecret.swift new file mode 100644 index 00000000..039dbbd9 --- /dev/null +++ b/AtalaPrismSDK/Apollo/Sources/Model/LinkSecret.swift @@ -0,0 +1,47 @@ +import AnoncredsSwift +import Domain +import Foundation + +struct LinkSecret: Key { + let keyType = "LinkSecret" + let keySpecifications = [String : String]() + let raw: Data + var size: Int { raw.count } + + let anoncred: AnoncredsSwift.LinkSecret + + init(string: String) throws { + self.anoncred = try AnoncredsSwift.LinkSecret.newFromValue(valueString: string) + guard let strData = string.data(using: .utf8) else { + throw CommonError.invalidCoding(message: "Could not encode LinkSecret in Data") + } + self.raw = strData + } + + init(data: Data) throws { + guard let str = String(data: data, encoding: .utf8) else { + throw CommonError.invalidCoding(message: "Could not encode LinkSecret in String") + } + self.anoncred = try AnoncredsSwift.LinkSecret.newFromValue(valueString: str) + self.raw = data + } + + init() throws { + let anoncred = Prover().createLinkSecret() + self.anoncred = anoncred + guard let strData = try anoncred.getValue().data(using: .utf8) else { + throw CommonError.invalidCoding(message: "Could not encode LinkSecret in Data") + } + self.raw = strData + } +} + +extension LinkSecret: KeychainStorableKey { + var restorationIdentifier: String { "linkSecret+key" } + var storableData: Data { raw } + var index: Int? { nil } + var type: Domain.KeychainStorableKeyProperties.KeyAlgorithm { .rawKey } + var keyClass: Domain.KeychainStorableKeyProperties.KeyType { .privateKey } + var accessiblity: Domain.KeychainStorableKeyProperties.Accessability? { .firstUnlock(deviceOnly: true) } + var synchronizable: Bool { false } +} diff --git a/AtalaPrismSDK/Apollo/Sources/Operations/CreateLinkSecretOperation.swift b/AtalaPrismSDK/Apollo/Sources/Operations/CreateLinkSecretOperation.swift deleted file mode 100644 index 44c0b8c3..00000000 --- a/AtalaPrismSDK/Apollo/Sources/Operations/CreateLinkSecretOperation.swift +++ /dev/null @@ -1,8 +0,0 @@ -import AnoncredsSwift -import Foundation - -struct CreateLinkSecretOperation { - func create() throws -> String { - try Prover().createLinkSecret().getValue() - } -} diff --git a/AtalaPrismSDK/Domain/Sources/BBs/Apollo.swift b/AtalaPrismSDK/Domain/Sources/BBs/Apollo.swift index e8c98805..863612fc 100644 --- a/AtalaPrismSDK/Domain/Sources/BBs/Apollo.swift +++ b/AtalaPrismSDK/Domain/Sources/BBs/Apollo.swift @@ -55,5 +55,8 @@ public protocol Apollo { /// - Returns: The decompressed public key func uncompressedPublicKey(compressedData: Data) -> PublicKey - func createNewLinkSecret() throws -> String + /// createNewLinkSecret creates a link secret. + /// + /// - Returns: A key that represents the link secret + func createNewLinkSecret() throws -> Key } diff --git a/AtalaPrismSDK/Domain/Sources/BBs/Pluto.swift b/AtalaPrismSDK/Domain/Sources/BBs/Pluto.swift index 3b0e9858..6417a4e5 100644 --- a/AtalaPrismSDK/Domain/Sources/BBs/Pluto.swift +++ b/AtalaPrismSDK/Domain/Sources/BBs/Pluto.swift @@ -81,7 +81,7 @@ public protocol Pluto { credential: StorableCredential ) -> AnyPublisher - func storeLinkSecret(secret: String) -> AnyPublisher + func storeLinkSecret(secret: StorableKey) -> AnyPublisher /// Returns all stored PRISM DIDs, along with their associated key pair indices and aliases (if any). /// - Returns: A publisher that emits an array of tuples representing the stored PRISM DIDs, along with their associated key pair indices and aliases (if any). @@ -217,5 +217,5 @@ public protocol Pluto { /// - Returns: A publisher that emits an array of stored verifiable credentials. func getAllCredentials() -> AnyPublisher<[StorableCredential], Error> - func getLinkSecret() -> AnyPublisher<[String], Error> + func getLinkSecret() -> AnyPublisher<[StorableKey], Error> } diff --git a/AtalaPrismSDK/Domain/Sources/Models/KeyManagement/KeyRestoration.swift b/AtalaPrismSDK/Domain/Sources/Models/KeyManagement/KeyRestoration.swift index 4de010bd..57553c8c 100644 --- a/AtalaPrismSDK/Domain/Sources/Models/KeyManagement/KeyRestoration.swift +++ b/AtalaPrismSDK/Domain/Sources/Models/KeyManagement/KeyRestoration.swift @@ -18,6 +18,14 @@ public protocol KeyRestoration { /// - Returns: A boolean value indicating whether the data represents a public key (true) or not (false). func isPublicKeyData(identifier: String, data: Data) throws -> Bool + /// Determines if the given data corresponds to a key. + /// - Parameters: + /// - identifier: An optional string used to identify the key. + /// - data: The raw data potentially representing the key. + /// - Throws: If the verification process fails, this method throws an error. + /// - Returns: A boolean value indicating whether the data represents a key (true) or not (false). + func isKeyData(identifier: String, data: Data) throws -> Bool + /// Restores a private key from the given data. /// - Parameters: /// - identifier: An optional string used to identify the key. @@ -33,4 +41,12 @@ public protocol KeyRestoration { /// - Throws: If the restoration process fails, this method throws an error. /// - Returns: The restored `PublicKey` instance. func restorePublicKey(_ key: StorableKey) async throws -> PublicKey + + /// Restores a key from the given data. + /// - Parameters: + /// - identifier: An optional string used to identify the key. + /// - data: The raw data representing the key. + /// - Throws: If the restoration process fails, this method throws an error. + /// - Returns: The restored `Key` instance. + func restoreKey(_ key: StorableKey) async throws -> Key } diff --git a/AtalaPrismSDK/Pluto/Sources/Domain/Providers/LinkSecretProvider.swift b/AtalaPrismSDK/Pluto/Sources/Domain/Providers/LinkSecretProvider.swift index 89d8fd88..3929f725 100644 --- a/AtalaPrismSDK/Pluto/Sources/Domain/Providers/LinkSecretProvider.swift +++ b/AtalaPrismSDK/Pluto/Sources/Domain/Providers/LinkSecretProvider.swift @@ -1,6 +1,7 @@ import Combine +import Domain import Foundation protocol LinkSecretProvider { - func getAll() -> AnyPublisher<[String], Error> + func getAll() -> AnyPublisher<[StorableKey], Error> } diff --git a/AtalaPrismSDK/Pluto/Sources/Domain/Stores/LinkSecretStore.swift b/AtalaPrismSDK/Pluto/Sources/Domain/Stores/LinkSecretStore.swift index 3c20020f..d773b004 100644 --- a/AtalaPrismSDK/Pluto/Sources/Domain/Stores/LinkSecretStore.swift +++ b/AtalaPrismSDK/Pluto/Sources/Domain/Stores/LinkSecretStore.swift @@ -1,6 +1,7 @@ import Combine +import Domain import Foundation protocol LinkSecretStore { - func addLinkSecret(_ linkSecret: String) -> AnyPublisher + func addLinkSecret(_ linkSecret: StorableKey) -> AnyPublisher } diff --git a/AtalaPrismSDK/Pluto/Sources/PersistentStorage/DAO/CDDIDPrivateKeyDAO+DIDPrivateKeyProvider.swift b/AtalaPrismSDK/Pluto/Sources/PersistentStorage/DAO/CDDIDPrivateKeyDAO+DIDPrivateKeyProvider.swift index b14c9028..75ea0d5b 100644 --- a/AtalaPrismSDK/Pluto/Sources/PersistentStorage/DAO/CDDIDPrivateKeyDAO+DIDPrivateKeyProvider.swift +++ b/AtalaPrismSDK/Pluto/Sources/PersistentStorage/DAO/CDDIDPrivateKeyDAO+DIDPrivateKeyProvider.swift @@ -10,7 +10,7 @@ extension CDDIDPrivateKeyDAO: DIDPrivateKeyProvider { try $0.map { ( DID(from: $0), - try $0.keys.map { try $0.parseToStorableKey(keychain: self.keychain) }, + try $0.keys.map { try $0.parseToStorableKey(keychain: self.keyDao.keychain) }, $0.alias ) } @@ -24,7 +24,7 @@ extension CDDIDPrivateKeyDAO: DIDPrivateKeyProvider { try $0.map { ( DID(from: $0), - try $0.keys.map { try $0.parseToStorableKey(keychain: self.keychain) }, + try $0.keys.map { try $0.parseToStorableKey(keychain: self.keyDao.keychain) }, $0.alias ) } @@ -41,7 +41,7 @@ extension CDDIDPrivateKeyDAO: DIDPrivateKeyProvider { try $0.map { ( DID(from: $0), - try $0.keys.map { try $0.parseToStorableKey(keychain: self.keychain) }, + try $0.keys.map { try $0.parseToStorableKey(keychain: self.keyDao.keychain) }, $0.alias ) } @@ -52,7 +52,7 @@ extension CDDIDPrivateKeyDAO: DIDPrivateKeyProvider { func getPrivateKeys(did: DID) -> AnyPublisher<[StorableKey]?, Error> { fetchByIDsPublisher(did.string, context: readContext) .tryMap { - try $0?.keys.map { try $0.parseToStorableKey(keychain: self.keychain) } + try $0?.keys.map { try $0.parseToStorableKey(keychain: self.keyDao.keychain) } } .eraseToAnyPublisher() } @@ -68,42 +68,3 @@ extension CDDIDPrivateKeyDAO: DIDPrivateKeyProvider { .eraseToAnyPublisher() } } - -extension CDKey { - func parseToStorableKey(keychain: KeychainProvider) throws -> StorableKey { - switch self { - case let keychainKey as CDKeychainKey: - guard - let algortihm = KeychainStorableKeyProperties.KeyAlgorithm(rawValue: keychainKey.algorithm), - let keyType = KeychainStorableKeyProperties.KeyType(rawValue: keychainKey.type) - else { - // TODO: Update this error - throw PlutoError.algorithmOrKeyTypeNotValid(algorithm: keychainKey.algorithm, keyType: keychainKey.type) - } - let keyData = try keychain.getKey( - service: keychainKey.service, - account: keychainKey.identifier, - tag: keychainKey.tag, - algorithm: algortihm, - type: keyType - ) - - return StorableKeyModel( - restorationIdentifier: keychainKey.restorationIdentifier, - storableData: keyData, - index: keychainKey.index?.intValue - ) - case let databaseKey as CDDatabaseKey: - return StorableKeyModel( - restorationIdentifier: databaseKey.restorationIdentifier, - storableData: databaseKey.storableData, - index: databaseKey.index?.intValue - ) - default: - throw UnknownError.somethingWentWrongError( - customMessage: "This should never happen it a key always have a type of CDKeychainKey or CDDatabaseKey", - underlyingErrors: nil - ) - } - } -} diff --git a/AtalaPrismSDK/Pluto/Sources/PersistentStorage/DAO/CDDIDPrivateKeyDAO+DIDPrivateKeyStore.swift b/AtalaPrismSDK/Pluto/Sources/PersistentStorage/DAO/CDDIDPrivateKeyDAO+DIDPrivateKeyStore.swift index 72790ab9..0c311b3f 100644 --- a/AtalaPrismSDK/Pluto/Sources/PersistentStorage/DAO/CDDIDPrivateKeyDAO+DIDPrivateKeyStore.swift +++ b/AtalaPrismSDK/Pluto/Sources/PersistentStorage/DAO/CDDIDPrivateKeyDAO+DIDPrivateKeyStore.swift @@ -14,16 +14,16 @@ extension CDDIDPrivateKeyDAO: DIDPrivateKeyStore { try storeKeychainKey( did: did, keychainKey: keychainKey, - service: self.keychainService, + service: self.keyDao.keychainService, account: identifier, - keychain: self.keychain + keychain: self.keyDao.keychain ) let cdkey = CDKeychainKey(entity: CDKeychainKey.entity(), insertInto: context) cdkey.parseFromStorableKey( keychainKey, did: cdobj, identifier: identifier, - service: self.keychainService + service: self.keyDao.keychainService ) return cdkey as CDKey default: diff --git a/AtalaPrismSDK/Pluto/Sources/PersistentStorage/DAO/CDDIDPrivateKeyDAO.swift b/AtalaPrismSDK/Pluto/Sources/PersistentStorage/DAO/CDDIDPrivateKeyDAO.swift index c909bebf..020f0b9d 100644 --- a/AtalaPrismSDK/Pluto/Sources/PersistentStorage/DAO/CDDIDPrivateKeyDAO.swift +++ b/AtalaPrismSDK/Pluto/Sources/PersistentStorage/DAO/CDDIDPrivateKeyDAO.swift @@ -4,8 +4,6 @@ import Domain struct CDDIDPrivateKeyDAO: CoreDataDAO { typealias CoreDataObject = CDDIDPrivateKey - let keychain: KeychainStore & KeychainProvider - let keychainService: String let keyDao: CDKeyDAO let readContext: NSManagedObjectContext let writeContext: NSManagedObjectContext diff --git a/AtalaPrismSDK/Pluto/Sources/PersistentStorage/DAO/CDKeyDAO+LinkSecretProvider.swift b/AtalaPrismSDK/Pluto/Sources/PersistentStorage/DAO/CDKeyDAO+LinkSecretProvider.swift new file mode 100644 index 00000000..1c6e78ce --- /dev/null +++ b/AtalaPrismSDK/Pluto/Sources/PersistentStorage/DAO/CDKeyDAO+LinkSecretProvider.swift @@ -0,0 +1,11 @@ +import Combine +import Foundation +import Domain + +extension CDKeyDAO: LinkSecretProvider { + func getAll() -> AnyPublisher<[StorableKey], Error> { + fetchController(context: readContext) + .tryMap { try $0.map { try $0.parseToStorableKey(keychain: self.keychain) } } + .eraseToAnyPublisher() + } +} diff --git a/AtalaPrismSDK/Pluto/Sources/PersistentStorage/DAO/CDKeyDAO+LinkSecretStore.swift b/AtalaPrismSDK/Pluto/Sources/PersistentStorage/DAO/CDKeyDAO+LinkSecretStore.swift new file mode 100644 index 00000000..32b9fb31 --- /dev/null +++ b/AtalaPrismSDK/Pluto/Sources/PersistentStorage/DAO/CDKeyDAO+LinkSecretStore.swift @@ -0,0 +1,73 @@ +import Combine +import CoreData +import Domain + +extension CDKeyDAO: LinkSecretStore { + func addLinkSecret(_ linkSecret: StorableKey) -> AnyPublisher { + updateOrCreate("linkSecret", context: writeContext) { cdobj, context in + switch linkSecret { + case let keychainKey as KeychainStorableKey: + try storeKeychainKey( + keychainKey: keychainKey, + service: self.keychainService, + account: "linkSecret", + keychain: self.keychain + ) + let cdkey = CDKeychainKey(entity: CDKeychainKey.entity(), insertInto: context) + cdkey.parseFromStorableKey( + keychainKey, + identifier: "linkSecret", + service: self.keychainService + ) + default: + let cdkey = CDDatabaseKey(entity: CDDatabaseKey.entity(), insertInto: context) + cdkey.parseFromStorableKey( + linkSecret, + identifier: "linkSecret" + ) + } + } + .map { _ in } + .eraseToAnyPublisher() + } +} + +private func storeKeychainKey( + keychainKey: KeychainStorableKey, + service: String, + account: String, + keychain: KeychainStore +) throws { + try keychain.addKey( + keychainKey, + service: service, + account: account + ) +} + +private extension CDDatabaseKey { + func parseFromStorableKey( + _ key: StorableKey, + identifier: String + ) { + self.identifier = identifier + self.storableData = key.storableData + self.index = key.index.map { NSNumber(integerLiteral: $0) } + self.restorationIdentifier = key.restorationIdentifier + } +} + +private extension CDKeychainKey { + func parseFromStorableKey( + _ key: KeychainStorableKey, + identifier: String, + service: String + ) { + self.identifier = identifier + self.restorationIdentifier = key.restorationIdentifier + self.index = key.index.map { NSNumber(integerLiteral: $0) } + self.type = key.keyClass.rawValue + self.algorithm = key.type.rawValue + self.service = service + } +} diff --git a/AtalaPrismSDK/Pluto/Sources/PersistentStorage/DAO/CDKeyDAO.swift b/AtalaPrismSDK/Pluto/Sources/PersistentStorage/DAO/CDKeyDAO.swift index a3675352..1268ca77 100644 --- a/AtalaPrismSDK/Pluto/Sources/PersistentStorage/DAO/CDKeyDAO.swift +++ b/AtalaPrismSDK/Pluto/Sources/PersistentStorage/DAO/CDKeyDAO.swift @@ -4,7 +4,48 @@ import Domain struct CDKeyDAO: CoreDataDAO { typealias CoreDataObject = CDKey + let keychain: KeychainStore & KeychainProvider + let keychainService: String let readContext: NSManagedObjectContext let writeContext: NSManagedObjectContext let identifierKey: String? = "identifier" } + +extension CDKey { + func parseToStorableKey(keychain: KeychainProvider) throws -> StorableKey { + switch self { + case let keychainKey as CDKeychainKey: + guard + let algortihm = KeychainStorableKeyProperties.KeyAlgorithm(rawValue: keychainKey.algorithm), + let keyType = KeychainStorableKeyProperties.KeyType(rawValue: keychainKey.type) + else { + // TODO: Update this error + throw PlutoError.algorithmOrKeyTypeNotValid(algorithm: keychainKey.algorithm, keyType: keychainKey.type) + } + let keyData = try keychain.getKey( + service: keychainKey.service, + account: keychainKey.identifier, + tag: keychainKey.tag, + algorithm: algortihm, + type: keyType + ) + + return StorableKeyModel( + restorationIdentifier: keychainKey.restorationIdentifier, + storableData: keyData, + index: keychainKey.index?.intValue + ) + case let databaseKey as CDDatabaseKey: + return StorableKeyModel( + restorationIdentifier: databaseKey.restorationIdentifier, + storableData: databaseKey.storableData, + index: databaseKey.index?.intValue + ) + default: + throw UnknownError.somethingWentWrongError( + customMessage: "This should never happen it a key always have a type of CDKeychainKey or CDDatabaseKey", + underlyingErrors: nil + ) + } + } +} diff --git a/AtalaPrismSDK/Pluto/Sources/PersistentStorage/DAO/CDLinkSecretDAO+LinkSecretProvider.swift b/AtalaPrismSDK/Pluto/Sources/PersistentStorage/DAO/CDLinkSecretDAO+LinkSecretProvider.swift deleted file mode 100644 index f97d02f3..00000000 --- a/AtalaPrismSDK/Pluto/Sources/PersistentStorage/DAO/CDLinkSecretDAO+LinkSecretProvider.swift +++ /dev/null @@ -1,10 +0,0 @@ -import Combine -import Foundation - -extension CDLinkSecretDAO: LinkSecretProvider { - func getAll() -> AnyPublisher<[String], Error> { - fetchController(context: readContext) - .map { $0.map(\.secret) } - .eraseToAnyPublisher() - } -} diff --git a/AtalaPrismSDK/Pluto/Sources/PersistentStorage/DAO/CDLinkSecretDAO+LinkSecretStore.swift b/AtalaPrismSDK/Pluto/Sources/PersistentStorage/DAO/CDLinkSecretDAO+LinkSecretStore.swift deleted file mode 100644 index 025d30b5..00000000 --- a/AtalaPrismSDK/Pluto/Sources/PersistentStorage/DAO/CDLinkSecretDAO+LinkSecretStore.swift +++ /dev/null @@ -1,13 +0,0 @@ -import Combine -import CoreData -import Domain - -extension CDLinkSecretDAO: LinkSecretStore { - func addLinkSecret(_ linkSecret: String) -> AnyPublisher { - updateOrCreate(linkSecret, context: writeContext) { cdobj, context in - cdobj.secret = linkSecret - } - .map { _ in } - .eraseToAnyPublisher() - } -} diff --git a/AtalaPrismSDK/Pluto/Sources/PlutoImpl+Public.swift b/AtalaPrismSDK/Pluto/Sources/PlutoImpl+Public.swift index e9c946b4..01cf3bc2 100644 --- a/AtalaPrismSDK/Pluto/Sources/PlutoImpl+Public.swift +++ b/AtalaPrismSDK/Pluto/Sources/PlutoImpl+Public.swift @@ -167,11 +167,11 @@ extension PlutoImpl: Pluto { credentialsDAO.getAll() } - public func storeLinkSecret(secret: String) -> AnyPublisher { - linkSecretDao.addLinkSecret(secret) + public func storeLinkSecret(secret: StorableKey) -> AnyPublisher { + keyDao.addLinkSecret(secret) } - public func getLinkSecret() -> AnyPublisher<[String], Error> { - linkSecretDao.getAll() + public func getLinkSecret() -> AnyPublisher<[StorableKey], Error> { + keyDao.getAll() } } diff --git a/AtalaPrismSDK/Pluto/Sources/PlutoImpl.swift b/AtalaPrismSDK/Pluto/Sources/PlutoImpl.swift index 24bcd3e3..5c2f466d 100644 --- a/AtalaPrismSDK/Pluto/Sources/PlutoImpl.swift +++ b/AtalaPrismSDK/Pluto/Sources/PlutoImpl.swift @@ -36,6 +36,7 @@ public struct PlutoImpl { } let setup: PlutoSetup + let keyDao: CDKeyDAO let registeredDIDDao: CDRegisteredDIDDAO let privateKeyDIDDao: CDDIDPrivateKeyDAO let pairDIDDao: CDDIDPairDAO @@ -53,13 +54,16 @@ public struct PlutoImpl { readContext: manager.mainContext, writeContext: manager.editContext ) - let privateKeyDao = CDDIDPrivateKeyDAO( + let keyDao = CDKeyDAO( keychain: setup.keychain, keychainService: setup.keychainService, - keyDao: CDKeyDAO( - readContext: manager.mainContext, - writeContext: manager.editContext - ), + readContext: manager.mainContext, + writeContext: manager.editContext + ) + self.keyDao = keyDao + + let privateKeyDao = CDDIDPrivateKeyDAO( + keyDao: keyDao, readContext: manager.mainContext, writeContext: manager.editContext ) diff --git a/AtalaPrismSDK/Pluto/Sources/Resources/PrismPluto.xcdatamodeld/PrismPluto.xcdatamodel/contents b/AtalaPrismSDK/Pluto/Sources/Resources/PrismPluto.xcdatamodeld/PrismPluto.xcdatamodel/contents index 12424d2c..779cf85c 100644 --- a/AtalaPrismSDK/Pluto/Sources/Resources/PrismPluto.xcdatamodeld/PrismPluto.xcdatamodel/contents +++ b/AtalaPrismSDK/Pluto/Sources/Resources/PrismPluto.xcdatamodeld/PrismPluto.xcdatamodel/contents @@ -1,5 +1,5 @@ - + @@ -49,9 +49,6 @@ - - - diff --git a/AtalaPrismSDK/Pluto/Tests/CDDIDPairDAOTests.swift b/AtalaPrismSDK/Pluto/Tests/CDDIDPairDAOTests.swift index db8ae139..ea0c5fc4 100644 --- a/AtalaPrismSDK/Pluto/Tests/CDDIDPairDAOTests.swift +++ b/AtalaPrismSDK/Pluto/Tests/CDDIDPairDAOTests.swift @@ -15,9 +15,9 @@ final class CDDIDPairDAOTests: XCTestCase { )) keychainMock = KeychainMock() privateKeyDao = CDDIDPrivateKeyDAO( - keychain: keychainMock, - keychainService: "test", keyDao: CDKeyDAO( + keychain: keychainMock, + keychainService: "test", readContext: coreDataManager.mainContext, writeContext: coreDataManager.editContext ), diff --git a/AtalaPrismSDK/Pluto/Tests/CDDIDPrivateKeyDAOTests.swift b/AtalaPrismSDK/Pluto/Tests/CDDIDPrivateKeyDAOTests.swift index 3e9bd731..7ed8be83 100644 --- a/AtalaPrismSDK/Pluto/Tests/CDDIDPrivateKeyDAOTests.swift +++ b/AtalaPrismSDK/Pluto/Tests/CDDIDPrivateKeyDAOTests.swift @@ -18,9 +18,9 @@ final class CDDIDPrivateKeyDAOTestsTests: XCTestCase { func testStoreSingleDID() throws { let dao = CDDIDPrivateKeyDAO( - keychain: keychainMock, - keychainService: "test", keyDao: CDKeyDAO( + keychain: keychainMock, + keychainService: "test", readContext: coreDataManager.mainContext, writeContext: coreDataManager.editContext ), @@ -48,9 +48,9 @@ final class CDDIDPrivateKeyDAOTestsTests: XCTestCase { func testStoreNoDuplicatedDID() throws { let dao = CDDIDPrivateKeyDAO( - keychain: keychainMock, - keychainService: "test", keyDao: CDKeyDAO( + keychain: keychainMock, + keychainService: "test", readContext: coreDataManager.mainContext, writeContext: coreDataManager.editContext ), @@ -86,9 +86,9 @@ final class CDDIDPrivateKeyDAOTestsTests: XCTestCase { func testGetAllDIDs() throws { let dao = CDDIDPrivateKeyDAO( - keychain: keychainMock, - keychainService: "test", keyDao: CDKeyDAO( + keychain: keychainMock, + keychainService: "test", readContext: coreDataManager.mainContext, writeContext: coreDataManager.editContext ), @@ -128,9 +128,9 @@ final class CDDIDPrivateKeyDAOTestsTests: XCTestCase { func testGetDIDInfoByDID() throws { let dao = CDDIDPrivateKeyDAO( - keychain: keychainMock, - keychainService: "test", keyDao: CDKeyDAO( + keychain: keychainMock, + keychainService: "test", readContext: coreDataManager.mainContext, writeContext: coreDataManager.editContext ), diff --git a/AtalaPrismSDK/Pluto/Tests/CDMessagesDAOTests.swift b/AtalaPrismSDK/Pluto/Tests/CDMessagesDAOTests.swift index 4776d293..7078905b 100644 --- a/AtalaPrismSDK/Pluto/Tests/CDMessagesDAOTests.swift +++ b/AtalaPrismSDK/Pluto/Tests/CDMessagesDAOTests.swift @@ -16,9 +16,9 @@ final class CDMessagesDAOTests: XCTestCase { storeType: .memory )) privateDAO = CDDIDPrivateKeyDAO( - keychain: keychainMock, - keychainService: "test", keyDao: CDKeyDAO( + keychain: keychainMock, + keychainService: "test", readContext: coreDataManager.mainContext, writeContext: coreDataManager.editContext ), diff --git a/AtalaPrismSDK/Pluto/Tests/Helper/KeyRestoration+Test.swift b/AtalaPrismSDK/Pluto/Tests/Helper/KeyRestoration+Test.swift index 891b8a1f..8ee86fd8 100644 --- a/AtalaPrismSDK/Pluto/Tests/Helper/KeyRestoration+Test.swift +++ b/AtalaPrismSDK/Pluto/Tests/Helper/KeyRestoration+Test.swift @@ -10,6 +10,10 @@ struct MockKeyRestoration: KeyRestoration { identifier == "MockPublic" } + func isKeyData(identifier: String, data: Data) throws -> Bool { + identifier == "MockKey" + } + func restorePrivateKey(_ key: Domain.StorableKey) throws -> PrivateKey { MockPrivateKey(raw: key.storableData) } @@ -17,4 +21,8 @@ struct MockKeyRestoration: KeyRestoration { func restorePublicKey(_ key: Domain.StorableKey) throws -> PublicKey { MockPublicKey(raw: key.storableData) } + + func restoreKey(_ key: StorableKey) async throws -> Key { + MockPublicKey(raw: key.storableData) + } } diff --git a/AtalaPrismSDK/PrismAgent/Sources/PrismAgent+Credentials.swift b/AtalaPrismSDK/PrismAgent/Sources/PrismAgent+Credentials.swift index 6cfcf7bd..a81bd9bf 100644 --- a/AtalaPrismSDK/PrismAgent/Sources/PrismAgent+Credentials.swift +++ b/AtalaPrismSDK/PrismAgent/Sources/PrismAgent+Credentials.swift @@ -33,12 +33,17 @@ public extension PrismAgent { guard let linkSecret = try await pluto.getLinkSecret().first().await().first else { throw PrismAgentError.cannotFindDIDKeyPairIndex } - + + let restored = try await self.apollo.restoreKey(linkSecret) + guard + let linkSecretString = String(data: restored.raw, encoding: .utf8) + else { throw PrismAgentError.cannotFindDIDKeyPairIndex } + let downloader = DownloadDataWithResolver(castor: castor) let credential = try await pollux.parseCredential( issuedCredential: message.makeMessage(), options: [ - .linkSecret(id: "", secret: linkSecret), + .linkSecret(id: "", secret: linkSecretString), .credentialDefinitionDownloader(downloader: downloader), .schemaDownloader(downloader: downloader) ] @@ -76,14 +81,19 @@ public extension PrismAgent { let exporting = privateKey.exporting, let linkSecret = try await pluto.getLinkSecret().first().await().first else { throw PrismAgentError.cannotFindDIDKeyPairIndex } - + + let restored = try await self.apollo.restoreKey(linkSecret) + guard + let linkSecretString = String(data: restored.raw, encoding: .utf8) + else { throw PrismAgentError.cannotFindDIDKeyPairIndex } + let downloader = DownloadDataWithResolver(castor: castor) let requestString = try await pollux.processCredentialRequest( offerMessage: offer.makeMessage(), options: [ .exportableKey(exporting), .subjectDID(did), - .linkSecret(id: did.string, secret: linkSecret), + .linkSecret(id: did.string, secret: linkSecretString), .credentialDefinitionDownloader(downloader: downloader), .schemaDownloader(downloader: downloader) ] diff --git a/AtalaPrismSDK/PrismAgent/Sources/PrismAgent.swift b/AtalaPrismSDK/PrismAgent/Sources/PrismAgent.swift index 3519bdfb..d2f801b6 100644 --- a/AtalaPrismSDK/PrismAgent/Sources/PrismAgent.swift +++ b/AtalaPrismSDK/PrismAgent/Sources/PrismAgent.swift @@ -197,7 +197,11 @@ public class PrismAgent { private func firstLinkSecretSetup() async throws { if try await pluto.getLinkSecret().first().await().first == nil { let secret = try apollo.createNewLinkSecret() - try await pluto.storeLinkSecret(secret: secret).first().await() + guard let storableSecret = secret.storable else { + throw UnknownError + .somethingWentWrongError(customMessage: "Secret does not conform with StorableKey") + } + try await pluto.storeLinkSecret(secret: storableSecret).first().await() } } }