Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(pollux): zkp verification #113

Merged
merged 1 commit into from
Jan 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion AtalaPrismSDK/Domain/Sources/BBs/Pluto.swift
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ public protocol Pluto {
credential: StorableCredential
) -> AnyPublisher<Void, Error>

/// Stores a link secret in the data store.
/// - Parameter secret: The storable key link secret.
/// - Returns: A publisher that completes when the operation finishes.
func storeLinkSecret(secret: StorableKey) -> AnyPublisher<Void, Error>

/// Returns all stored PRISM DIDs, along with their associated key pair indices and aliases (if any).
Expand Down Expand Up @@ -217,5 +220,7 @@ public protocol Pluto {
/// - Returns: A publisher that emits an array of stored verifiable credentials.
func getAllCredentials() -> AnyPublisher<[StorableCredential], Error>

func getLinkSecret() -> AnyPublisher<[StorableKey], Error>
/// Returns the stored link secret.
/// - Returns: A publisher that emits an optonal `StorableKey` that represents the link secret.
func getLinkSecret() -> AnyPublisher<StorableKey?, Error>
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ import Domain
import Foundation

protocol LinkSecretProvider {
func getAll() -> AnyPublisher<[StorableKey], Error>
func getLinkSecret() -> AnyPublisher<StorableKey?, Error>
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ extension CDDIDPrivateKeyDAO: DIDPrivateKeyProvider {
try $0.map {
(
DID(from: $0),
try $0.keys.map { try $0.parseToStorableKey(keychain: self.keyDao.keychain) },
try $0.keys.map { try $0.parseToStorableKey(keychain: self.keyDao.keychainDao.keychain) },
$0.alias
)
}
Expand All @@ -24,7 +24,7 @@ extension CDDIDPrivateKeyDAO: DIDPrivateKeyProvider {
try $0.map {
(
DID(from: $0),
try $0.keys.map { try $0.parseToStorableKey(keychain: self.keyDao.keychain) },
try $0.keys.map { try $0.parseToStorableKey(keychain: self.keyDao.keychainDao.keychain) },
$0.alias
)
}
Expand All @@ -41,7 +41,7 @@ extension CDDIDPrivateKeyDAO: DIDPrivateKeyProvider {
try $0.map {
(
DID(from: $0),
try $0.keys.map { try $0.parseToStorableKey(keychain: self.keyDao.keychain) },
try $0.keys.map { try $0.parseToStorableKey(keychain: self.keyDao.keychainDao.keychain) },
$0.alias
)
}
Expand All @@ -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.keyDao.keychain) }
try $0?.keys.map { try $0.parseToStorableKey(keychain: self.keyDao.keychainDao.keychain) }
}
.eraseToAnyPublisher()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,16 @@ extension CDDIDPrivateKeyDAO: DIDPrivateKeyStore {
try storeKeychainKey(
did: did,
keychainKey: keychainKey,
service: self.keyDao.keychainService,
service: self.keyDao.keychainDao.keychainService,
account: identifier,
keychain: self.keyDao.keychain
keychain: self.keyDao.keychainDao.keychain
)
let cdkey = CDKeychainKey(entity: CDKeychainKey.entity(), insertInto: context)
cdkey.parseFromStorableKey(
keychainKey,
did: cdobj,
identifier: identifier,
service: self.keyDao.keychainService
service: self.keyDao.keychainDao.keychainService
)
return cdkey as CDKey
default:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import Combine
import CoreData
import Domain

struct CDDatabaseKeyDAO: CoreDataDAO {
typealias CoreDataObject = CDDatabaseKey
let readContext: NSManagedObjectContext
let writeContext: NSManagedObjectContext
let identifierKey: String? = "identifier"
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ 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) } }
func getLinkSecret() -> AnyPublisher<StorableKey?, Error> {
fetchByIDsPublisher("linkSecret", context: readContext)
.tryMap {
try $0?.parseToStorableKey(keychain: self.keychainDao.keychain)
}
.eraseToAnyPublisher()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,33 @@ import Domain

extension CDKeyDAO: LinkSecretStore {
func addLinkSecret(_ linkSecret: StorableKey) -> AnyPublisher<Void, Error> {
updateOrCreate("linkSecret", context: writeContext) { cdobj, context in
switch linkSecret {
case let keychainKey as KeychainStorableKey:
switch linkSecret {
case let keychainKey as KeychainStorableKey:
return keychainDao.updateOrCreate("linkSecret", context: writeContext) { cdobj, context in
try storeKeychainKey(
keychainKey: keychainKey,
service: self.keychainService,
service: self.keychainDao.keychainService,
account: "linkSecret",
keychain: self.keychain
keychain: self.keychainDao.keychain
)
let cdkey = CDKeychainKey(entity: CDKeychainKey.entity(), insertInto: context)
cdkey.parseFromStorableKey(
cdobj.parseFromStorableKey(
keychainKey,
identifier: "linkSecret",
service: self.keychainService
service: self.keychainDao.keychainService
)
default:
let cdkey = CDDatabaseKey(entity: CDDatabaseKey.entity(), insertInto: context)
cdkey.parseFromStorableKey(
}
.map { _ in }
.eraseToAnyPublisher()
default:
return databaseDAO.updateOrCreate("linkSecret", context: writeContext) { cdobj, context in
cdobj.parseFromStorableKey(
linkSecret,
identifier: "linkSecret"
)
}
.map { _ in }
.eraseToAnyPublisher()
}
.map { _ in }
.eraseToAnyPublisher()
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,31 @@ import Domain

struct CDKeyDAO: CoreDataDAO {
typealias CoreDataObject = CDKey
let keychain: KeychainStore & KeychainProvider
let keychainService: String
let keychainDao: CDKeychainKeyDAO
let databaseDAO: CDDatabaseKeyDAO
let readContext: NSManagedObjectContext
let writeContext: NSManagedObjectContext
let identifierKey: String? = "identifier"

init(
keychain: KeychainStore & KeychainProvider,
keychainService: String,
readContext: NSManagedObjectContext,
writeContext: NSManagedObjectContext
) {
self.keychainDao = CDKeychainKeyDAO(
keychain: keychain,
keychainService: keychainService,
readContext: readContext,
writeContext: writeContext
)
self.databaseDAO = CDDatabaseKeyDAO(
readContext: readContext,
writeContext: writeContext
)
self.readContext = readContext
self.writeContext = writeContext
}
}

extension CDKey {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import Combine
import CoreData
import Domain

struct CDKeychainKeyDAO: CoreDataDAO {
typealias CoreDataObject = CDKeychainKey
let keychain: KeychainStore & KeychainProvider
let keychainService: String
let readContext: NSManagedObjectContext
let writeContext: NSManagedObjectContext
let identifierKey: String? = "identifier"
}
4 changes: 2 additions & 2 deletions AtalaPrismSDK/Pluto/Sources/PlutoImpl+Public.swift
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ extension PlutoImpl: Pluto {
keyDao.addLinkSecret(secret)
}

public func getLinkSecret() -> AnyPublisher<[StorableKey], Error> {
keyDao.getAll()
public func getLinkSecret() -> AnyPublisher<StorableKey?, Error> {
keyDao.getLinkSecret()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,7 @@ struct AnonCredentialSchema: Codable {
let attrNames: [String]
let issuerId: String
}

struct SchemaAnonCredentialSchema: Codable {
let schema: AnonCredentialSchema
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ struct ParseAnoncredsCredentialFromMessage {

let processedCredentialJson = try processedCredential.getJson().tryData(using: .utf8)
let finalCredential = try JSONDecoder().decode(AnonCredential.self, from: processedCredentialJson)

return AnoncredsCredentialStack(
schema: try JSONDecoder.didComm().decode(AnonCredentialSchema.self, from: schemaData),
definition: try JSONDecoder.didComm().decode(AnonCredentialDefinition.self, from: credentialDefinitionData),
Expand Down
4 changes: 2 additions & 2 deletions AtalaPrismSDK/Pollux/Tests/Mocks/MockPluto.swift
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ class MockPluto: Pluto {
self.credentials.publisher.collect().tryMap { $0 }.eraseToAnyPublisher()
}

func getLinkSecret() -> AnyPublisher<[StorableKey], Error> {
return Just([]).tryMap { $0 }.eraseToAnyPublisher()
func getLinkSecret() -> AnyPublisher<StorableKey?, Error> {
return Just(nil).tryMap { $0 }.eraseToAnyPublisher()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ public extension PrismAgent {
func verifiableCredentials() -> AnyPublisher<[Credential], Error> {
let pollux = self.pollux
return pluto.getAllCredentials().tryMap {
try $0.map {
try pollux.restoreCredential(
$0.compactMap {
try? pollux.restoreCredential(
restorationIdentifier: $0.recoveryId,
credentialData: $0.credentialData
)
Expand All @@ -31,7 +31,7 @@ public extension PrismAgent {
/// - Throws: PrismAgentError, if there is a problem parsing the credential.
func processIssuedCredentialMessage(message: IssueCredential3_0) async throws -> Credential {
guard
let linkSecret = try await pluto.getLinkSecret().first().await().first
let linkSecret = try await pluto.getLinkSecret().first().await()
else { throw PrismAgentError.cannotFindDIDKeyPairIndex }

let restored = try await self.apollo.restoreKey(linkSecret)
Expand Down Expand Up @@ -79,7 +79,7 @@ public extension PrismAgent {

guard
let exporting = privateKey.exporting,
let linkSecret = try await pluto.getLinkSecret().first().await().first
let linkSecret = try await pluto.getLinkSecret().first().await()
else { throw PrismAgentError.cannotFindDIDKeyPairIndex }

let restored = try await self.apollo.restoreKey(linkSecret)
Expand Down
77 changes: 51 additions & 26 deletions AtalaPrismSDK/PrismAgent/Sources/PrismAgent+Proof.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,40 +20,65 @@ public extension PrismAgent {
) async throws -> Presentation {
guard let proofableCredential = credential.proof else { throw UnknownError.somethingWentWrongError() }

guard
let subjectDIDString = credential.subject
else {
throw PolluxError.invalidPrismDID
guard let requestType = request.attachments.first?.format else {
throw UnknownError.somethingWentWrongError(customMessage: nil, underlyingErrors: nil)
}

let subjectDID = try DID(string: subjectDIDString)
let presentationString: String
switch requestType {
case "anoncreds/[email protected]":
guard
let linkSecret = try await pluto.getLinkSecret().first().await()
else { throw PrismAgentError.cannotFindDIDKeyPairIndex }

let didInfo = try await pluto
.getDIDInfo(did: subjectDID)
.first()
.await()
let restored = try await self.apollo.restoreKey(linkSecret)
guard
let linkSecretString = String(data: restored.raw, encoding: .utf8)
else { throw PrismAgentError.cannotFindDIDKeyPairIndex }
presentationString = try proofableCredential.presentation(
request: request.makeMessage(),
options: [
.linkSecret(id: "", secret: linkSecretString)
]
)
case "prism/jwt":
guard
let subjectDIDString = credential.subject
else {
throw PolluxError.invalidPrismDID
}

guard
let storedPrivateKey = didInfo?.privateKeys.first
else { throw PrismAgentError.cannotFindDIDKeyPairIndex }
let subjectDID = try DID(string: subjectDIDString)

let privateKey = try await apollo.restorePrivateKey(storedPrivateKey)
let didInfo = try await pluto
.getDIDInfo(did: subjectDID)
.first()
.await()

guard
let storedPrivateKey = didInfo?.privateKeys.first
else { throw PrismAgentError.cannotFindDIDKeyPairIndex }

let privateKey = try await apollo.restorePrivateKey(storedPrivateKey)

guard
let exporting = privateKey.exporting
else { throw PrismAgentError.cannotFindDIDKeyPairIndex }

presentationString = try proofableCredential.presentation(
request: request.makeMessage(),
options: [
.exportableKey(exporting),
.subjectDID(subjectDID)
]
)
default:
throw UnknownError.somethingWentWrongError(customMessage: nil, underlyingErrors: nil)
}

guard
let exporting = privateKey.exporting
else { throw PrismAgentError.cannotFindDIDKeyPairIndex }

let presentationString = try proofableCredential.presentation(
request: request.makeMessage(),
options: [
.exportableKey(exporting),
.subjectDID(subjectDID)
]
)

guard let base64String = presentationString.data(using: .utf8)?.base64EncodedString() else {
throw CommonError.invalidCoding(message: "Could not encode to base64")
}

return Presentation(
body: .init(
goalCode: request.body.goalCode,
Expand Down
2 changes: 1 addition & 1 deletion AtalaPrismSDK/PrismAgent/Sources/PrismAgent.swift
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ public class PrismAgent {
}

private func firstLinkSecretSetup() async throws {
if try await pluto.getLinkSecret().first().await().first == nil {
if try await pluto.getLinkSecret().first().await() == nil {
let secret = try apollo.createNewLinkSecret()
guard let storableSecret = secret.storable else {
throw UnknownError
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public struct DownloadDataWithResolver: Downloader {

public func downloadFromEndpoint(urlOrDID: String) async throws -> Data {
let url: URL

if let did = try? castor.parseDID(str: urlOrDID) {
let document = try await castor.resolveDID(did: did)
guard
Expand All @@ -20,7 +20,7 @@ public struct DownloadDataWithResolver: Downloader {
throw CommonError.invalidURLError(url: "Could not find any URL on DID")
}
url = validUrl
} else if let validUrl = URL(string: urlOrDID) {
} else if let validUrl = URL(string: urlOrDID.replacingOccurrences(of: "host.docker.internal", with: "localhost")) {
url = validUrl
} else {
throw CommonError.invalidURLError(url: urlOrDID)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,7 @@ final class SetupPrismAgentViewModelImpl: ObservableObject, SetupPrismAgentViewM
_ = try issued.attachments.compactMap {
switch $0.data {
case let data as AttachmentBase64:
let b64 = Data(base64URLEncoded: data.base64)!
let apollo = ApolloBuilder().build()
let castor = CastorBuilder(apollo: apollo).build()
let pollux = PolluxBuilder().build()
// let credential = try pollux.parseCredential(data: b64)
break
default:
return
}
Expand Down
Loading
Loading