重要提示! 在继续之前,请阅读 EUDI Wallet 参考实现项目描述
此存储库包含用于 iOS 的 EUDI Wallet Kit 库。该库是 EUDI Wallet 参考实现项目的一部分。
该库充当协调器,协调实现 EUDI Wallet 功能所需的各种组件。最重要的是,它提供了一个简化的 API,应用程序可以使用它来实现 EUDI Wallet 功能。
graph TD;
A[eudi-lib-ios-wallet-kit]
B[eudi-lib-ios-wallet-storage] --> |Wallet Storage|A
C[eudi-lib-ios-iso18013-data-transfer] --> |Transfer Manager|A
D[eudi-lib-ios-openid4vci-swift] --> |OpenId4Vci Manager|A
E[eudi-lib-ios-siop-openid4vp-swift] --> |OpenId4Vp Manager|A
F[eudi-lib-ios-iso18013-security] --> |Mdoc Security|C
G[eudi-lib-ios-iso18013-data-model] --> |Mdoc Data Model|C
H[eudi-lib-ios-presentation-exchange-swift] --> E
该库提供以下功能
该库用 Swift 编写,兼容 iOS 14 或更高版本。它作为一个 Swift 包分发,可以包含在任何 iOS 项目中。
它基于以下规范
发布的软件是初始开发版本
要使用 EUDI Wallet Kit,请将以下依赖项添加到您的 Package.swift
dependencies: [
.package(url: "https://github.com/eu-digital-identity-wallet/eudi-lib-ios-wallet-kit.git", .upToNextMajor(from: "0.6.6"))
]
然后将 Eudi Wallet 包添加到您的目标的依赖项中
dependencies: [
.product(name: "EudiWalletKit", package: "eudi-lib-ios-wallet-kit"),
]
详细文档在 DocC 文档中提供,点击此处
EudiWallet 类为两个用户证明展示流程提供了一个统一的 API。它使用文档存储管理器实例进行初始化。对于 SwiftUI 应用程序,可以将 wallet 实例添加为 environmentObject
,以便可以从所有视图访问。文档存储的 KeyChain 实现可用。
钱包开发者可以通过将 SecureArea
实例传递给 wallet 来自定义加密密钥操作,否则 wallet-kit 会创建“SecureEnclave”(默认)和“Software”安全区域。钱包开发者可以为每种文档类型指定密钥创建选项,例如曲线类型、安全区域名称和密钥解锁策略。
let wallet = try! EudiWallet(serviceName: "my_wallet_app",
trustedReaderCertificates: [Data(name: "eudi_pid_issuer_ut", ext: "der")!] )
EudiWallet 类提供了一组用于处理文档的方法。
loadDocuments
方法从存储中返回具有特定状态的文档。
以下示例展示了如何检索已颁发的文档
public func loadDocuments() async throws {
let documents = try await wallet.loadDocuments(status: .issued)
}
要检索所有状态的文档,请使用 loadAllDocuments
方法。
let documents = try await wallet.loadAllDocuments()
loadDocument(id:status:)
方法返回具有给定 id 和状态的文档。
以下示例展示了如何检索文档
let document = try await wallet.loadDocument(id: documentId, status: .issued)
只读属性 storage
是 StorageManager 类的一个实例。目前使用 keychain 实现。它使用 iOS KeyChain 提供文档管理功能。
存储模型为支持的已知文档类型提供以下模型
文档类型 (DocType) | 模型 (Model) |
---|---|
eu.europa.ec.eudiw.pid.1 | EuPidModel |
org.iso.18013.5.1.mDL | IsoMdlModel |
由于检索到的已颁发 mDoc 文档仅公开基本元数据和原始数据,因此必须将其解码为相应的 CBOR 模型。该库提供了 StorageManager\toClaimsModel
函数,用于将文档原始 CBOR 数据解码为符合 DocClaimsDecodable 协议的强类型模型。
加载函数自动更新 StorageManager
成员。解码后的已颁发文档可在 docModels
属性中使用。延迟和待处理的文档分别在 StorageManager\deferredDocuments
和 StorageManager\pendingDocuments
属性中使用。
对于其他文档类型,提供了 GenericMdocModel。
deleteDocument(id:)
方法用于删除具有给定 id 的文档。
以下示例展示了如何删除文档
try await wallet.deleteDocument(id: documentId)
该库提供了使用 OpenID4VCI 颁发文档的功能。
要使用此功能颁发文档,必须正确初始化 EudiWallet。如果 userAuthenticationRequired
为 true,则需要用户身份验证。身份验证提示消息具有本地化键 "issue_document"。颁发文档后,文档数据和相应的私钥将存储在 wallet 存储中。
当要颁发的文档类型 (docType) 时,使用 issueDocument(docType:keyOptions:)
方法。
以下示例展示了如何使用 OpenID4VCI 颁发 EUDI 个人 ID 文档
do {
let doc = try await userWallet.issueDocument(docType: EuPidModel.euPidDocType, keyOptions: KeyOptions(secureAreaName: "SecureEnclave", accessControl: [.requireUserPresence])])
// document has been added to wallet storage, you can display it
}
catch {
// display error
}
您还可以通过传递配置 identifier
参数 identifier
来颁发文档。可以使用 getIssuerMetadata
方法从颁发者的元数据中检索配置标识符。
// get current issuer metadata
let configuration = try await wallet.getIssuerMetadata()
...
let doc = try await userWallet.issueDocument(identifier: "eu.europa.ec.eudi.pid_vc_sd_jwt")
该库提供了 resolveOfferUrlDocTypes(uriOffer:)
方法,用于解析凭证提供 URI。该方法返回已解析的 OfferedIssuanceModel
对象,其中包含提供的数据(提供的文档类型、颁发者名称和预授权流程的事务代码规范)。可以将提供的数据显示给用户。
以下示例展示了如何解析凭证提供
func resolveOfferUrlDocTypes(uriOffer: String) async throws -> OfferedIssuanceModel {
return try await wallet.resolveOfferUrlDocTypes(uriOffer: uriOffer)
}
在用户接受提供后,可以使用 issueDocumentsByOfferUrl(offerUri:docTypes:docTypeKeyOptions:txCodeValue:)
方法颁发选定的文档。在授权码流程的情况下,不使用 txCodeValue
参数。以下示例展示了如何通过提供 URL 颁发文档
let documents = try await walletController.issueDocumentsByOfferUrl(offerUri: uri, docTypes: docOffers,
docTypeKeyOptions: [EuPidModel.euPidDocType : KeyOptions(secureAreaName: "SecureEnclave", accessControl: [.requireUserPresence])], txCodeValue: txCodeValue )
要使授权码流程正常工作,必须通过设置 openID4VciRedirectUri
属性来指定重定向 URI。用户在授权 web 视图中被重定向到颁发者的授权端点。在用户进行身份验证并授权请求后,颁发者会将用户重定向回应用程序,并提供授权码。该库将授权码交换为访问令牌并颁发文档。
当颁发者支持预授权码流程时,解析后的提供也会包含相应的信息。具体来说,OfferedIssuanceModel
对象中的 txCodeSpec
字段将包含
从用户的角度来看,应用程序必须提供一种输入事务代码的方法。
在用户接受提供后,可以使用 issueDocumentsByOfferUrl(offerUri:docTypes:docTypeKeyOptions:txCodeValue:)
方法颁发选定的文档。当提供事务代码时,可以通过调用上述方法并在 txCodeValue
参数中传递事务代码来恢复颁发过程。
Wallet kit 支持动态的基于 PID 的颁发
在调用 issueDocument(docType:keyOptions: KeyOptions:)
或 issueDocumentsByOfferUrl(offerUri:docTypes:docTypeKeyOptions:txCodeValue:)
后,钱包应用程序需要检查文档是否处于待处理状态并具有 authorizePresentationUrl
属性。如果存在该属性,应用程序应使用展示 URL 执行 OpenID4VP 展示。成功后,应使用服务器提供的授权 URL 调用 resumePendingIssuance(pendingDoc:, webUrl:)
方法。
if let urlString = newDocs.last?.authorizePresentationUrl {
// perform openid4vp presentation using the urlString
// on success call resumePendingIssuance using the authorization url
展示服务协议 抽象了展示流程。BlePresentationService 和 OpenId4VpService 类分别实现了近距离和远程展示流程。PresentationSession 类用于包装展示服务,并为 SwiftUI 屏幕提供 @Published 属性。以下示例代码演示了使用所选 流程类型 的新展示会话初始化 SwiftUI 视图。
let session = eudiWallet.beginPresentation(flow: flow)
// pass the session to a SwiftUI view
ShareView(presentationSession: session)
在视图出现时,会使用 receiveRequest 方法展示证明。对于 BLE(近距离)情况,deviceEngagement 属性会填充要在持有者设备上显示的 QR 码。
.task {
if presentationSession.flow.isProximity { await presentationSession.startQrEngagement() }
_ = await presentationSession.receiveRequest()
}
收到请求后,presentationSession.disclosedDocuments
包含请求的已证明项目。可以通过 UI 绑定修改项目的选定状态。最后,使用以下代码发送响应
// Send the disclosed document items after biometric authentication (FaceID or TouchID)
// if the user cancels biometric authentication, onCancel method is called
await presentationSession.sendResponse(userAccepted: true,
itemsToSend: presentationSession.disclosedDocuments.items, onCancel: { dismiss() }, onSuccess: {
if let url = $0 {
// handle URL
}
})
SwiftLog 库用于日志记录。该库提供了一个默认的日志记录器,该记录器会记录到控制台。主应用程序配置日志记录输出,例如文件日志记录。要使用日志记录器,请使用所需的标签创建一个日志记录器实例。日志记录器可用于记录具有不同日志级别的消息。
import Logging
// Create a logger with a label
let logger = Logger(label: "com.example.BestExampleApp.main")
// log an info message
logger.info("Hello World!")
详细文档在 DocC 文档中提供,点击此处
钱包套件的详细功能在以下 Swift 包中实现:MdocDataModel18013、MdocSecurity18013、MdocDataTransfer18013 和 SiopOpenID4VP OpenID4VCI
一个演示如何使用该库的参考应用程序是 App Wallet UI。
我们欢迎大家为本项目做出贡献。为了确保所有参与者流程顺利,请遵循 CONTRIBUTING.md 中的指南。
版权所有 (c) 2023 欧盟委员会
根据 Apache 许可证 2.0 版(“许可证”)获得许可;除非符合许可证的规定,否则您不得使用此文件。您可以在以下位置获得许可证的副本:
https://apache.ac.cn/licenses/LICENSE-2.0
除非适用法律要求或书面同意,否则软件是按“原样”分发的,不附带任何形式的明示或暗示的担保或条件。请参阅许可证中关于权限和限制的特定语言。