Skip to content

Commit 3bbb372

Browse files
add: id to UnsignedVPToken and VPTokenSigningResult
- The id will be the linkability factor between data to be signed and signed data which is used for VP construction Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>
1 parent 966473d commit 3bbb372

20 files changed

Lines changed: 552 additions & 534 deletions

Sources/OpenID4VP/AuthorizationResponse/AuthorizationResponseHandler.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ public class AuthorizationResponseHandler {
77
private var formatToCredentialInputDescriptorMapping: [FormatType: [CredentialInputDescriptorMapping]] = [:]
88
private var credentialToCredentialQueryIdMappingsGroupedByFormat: [FormatType: [CredentialToCredentialQueryIdMapping]] = [:]
99

10-
private var unsignedVPTokenResults: [FormatType: (vpTokenSigningPayload: Any?, unsignedVPTokens: [UnsignedVPToken])] = [:]
10+
private var unsignedVPTokenResults: [FormatType: (vpTokenSigningPayload: VPTokenSigningPayload, unsignedVPTokens: [UnsignedVPToken])] = [:]
1111
private var specVersion: SpecVersion = .v1
1212
private let walletConfig: WalletConfig
1313

Sources/OpenID4VP/AuthorizationResponse/UnsignedVPToken/UnsignedVPToken.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,21 @@
11
import Foundation
22

33
public struct UnsignedVPToken: Codable {
4-
4+
public let id: String
55
public let format: FormatType
66
public let holderKeyReference: String
77
public let signatureAlgorithm: String
88
// Base64 encoded byte array of the actual data to sign
99
public let dataToSign: Data
1010

1111
public init(
12+
id: String,
1213
format: FormatType,
1314
holderKeyReference: String,
1415
signatureAlgorithm: String,
1516
dataToSign: Data
1617
) {
18+
self.id = id
1719
self.format = format
1820
self.holderKeyReference = holderKeyReference
1921
self.signatureAlgorithm = signatureAlgorithm
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import Foundation
22

3-
typealias VPTokenSigningPayload = Any
3+
typealias VPTokenSigningPayload = [String: Any]
44

55
protocol UnsignedVPTokenBuilder {
66
var specVersion: SpecVersion { get }
77
var authorizationRequest: AuthorizationRequest { get }
88
var walletConfig: WalletConfig { get }
9-
func build(credentialInputDescriptorMappings: inout [CredentialInputDescriptorMapping]) async throws -> (vpTokenSigningPayload: VPTokenSigningPayload?, unsignedVPTokens: [UnsignedVPToken])
9+
func build(credentialInputDescriptorMappings: inout [CredentialInputDescriptorMapping]) async throws -> (vpTokenSigningPayload: VPTokenSigningPayload, unsignedVPTokens: [UnsignedVPToken])
1010

11-
func build(credentialToCredentialQueryIdMappings: inout [CredentialToCredentialQueryIdMapping]) async throws -> (vpTokenSigningPayload: VPTokenSigningPayload?, unsignedVPTokens: [UnsignedVPToken])
11+
func build(credentialToCredentialQueryIdMappings: inout [CredentialToCredentialQueryIdMapping]) async throws -> (vpTokenSigningPayload: VPTokenSigningPayload, unsignedVPTokens: [UnsignedVPToken])
1212
}

Sources/OpenID4VP/AuthorizationResponse/UnsignedVPToken/types/LdpVP/UnsignedLdpVPTokenBuilder.swift

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ class UnsignedLdpVPTokenBuilder: UnsignedVPTokenBuilder {
2222
self.walletConfig = walletConfig
2323
}
2424

25-
func build(credentialInputDescriptorMappings: inout [CredentialInputDescriptorMapping]) async throws -> (vpTokenSigningPayload: Any?, unsignedVPTokens: [UnsignedVPToken]) {
25+
func build(credentialInputDescriptorMappings: inout [CredentialInputDescriptorMapping]) async throws -> (vpTokenSigningPayload: VPTokenSigningPayload, unsignedVPTokens: [UnsignedVPToken]) {
2626
guard (authorizationRequest as? AuthorizationPresentationExchangeRequest) != nil else {
2727
throw InvalidData(message: "Expected AuthorizationPresentationExchangeRequest for Presentation Exchange flow", className: className)
2828
}
@@ -32,9 +32,9 @@ class UnsignedLdpVPTokenBuilder: UnsignedVPTokenBuilder {
3232

3333
for index in 0..<credentialInputDescriptorMappings.count {
3434
var credentialInputDescriptorMapping = credentialInputDescriptorMappings[index]
35-
let uuid = UUIDGenerator.generateUUID()
35+
let identifier = UUIDGenerator.generateUUID()
3636

37-
credentialInputDescriptorMapping.identifier = uuid
37+
credentialInputDescriptorMapping.identifier = identifier
3838
credentialInputDescriptorMapping.nestedPath = "$.\(Self.internalPath)[0]"
3939
credentialInputDescriptorMappings[index] = credentialInputDescriptorMapping
4040

@@ -46,12 +46,13 @@ class UnsignedLdpVPTokenBuilder: UnsignedVPTokenBuilder {
4646
let result = try extractHolderAndSignatureSuite(credential)
4747

4848
let (vpTokenSigningPayload, unsignedVPToken) = try await buildPayloadAndUnsignedVPToken(
49+
identifier: identifier,
4950
with: verifiableCredentials,
5051
signatureSuite: result.signatureSuite,
5152
holder: sanitize(result.holder)
5253
)
5354

54-
vpTokenSigningPayloads[uuid] = vpTokenSigningPayload
55+
vpTokenSigningPayloads[identifier] = vpTokenSigningPayload
5556
if let unsignedVPToken = unsignedVPToken {
5657
unsignedVPTokens.append(unsignedVPToken)
5758
}
@@ -61,7 +62,7 @@ class UnsignedLdpVPTokenBuilder: UnsignedVPTokenBuilder {
6162
return (vpTokenSigningPayloads, unsignedVPTokens)
6263
}
6364

64-
func build(credentialToCredentialQueryIdMappings: inout [CredentialToCredentialQueryIdMapping]) async throws -> (vpTokenSigningPayload: Any?, unsignedVPTokens: [UnsignedVPToken]) {
65+
func build(credentialToCredentialQueryIdMappings: inout [CredentialToCredentialQueryIdMapping]) async throws -> (vpTokenSigningPayload: VPTokenSigningPayload, unsignedVPTokens: [UnsignedVPToken]) {
6566
guard let authorizationRequest = authorizationRequest as? AuthorizationDcqlRequest else {
6667
throw InvalidData(message: "Expected AuthorizationDcqlRequest for DCQL flow", className: className)
6768
}
@@ -70,9 +71,9 @@ class UnsignedLdpVPTokenBuilder: UnsignedVPTokenBuilder {
7071

7172
for index in 0..<credentialToCredentialQueryIdMappings.count {
7273
var credentialToCredentialQueryIdMapping = credentialToCredentialQueryIdMappings[index]
73-
let uuid = UUIDGenerator.generateUUID()
74+
let identifier = UUIDGenerator.generateUUID()
7475

75-
credentialToCredentialQueryIdMapping.identifier = uuid
76+
credentialToCredentialQueryIdMapping.identifier = identifier
7677
credentialToCredentialQueryIdMappings[index] = credentialToCredentialQueryIdMapping
7778

7879
let (credential, credentialQueryId) = (credentialToCredentialQueryIdMapping.credential, credentialToCredentialQueryIdMapping.credentialQueryId)
@@ -84,18 +85,19 @@ class UnsignedLdpVPTokenBuilder: UnsignedVPTokenBuilder {
8485
}()
8586

8687
if(!mappedCredentialQuery.requireCryptographicHolderBinding) {
87-
vpTokenSigningPayloads[uuid] = .vc(LdpVCToken(verifiableCredential: credential))
88+
vpTokenSigningPayloads[identifier] = .vc(LdpVCToken(verifiableCredential: credential))
8889
continue
8990
}
9091

91-
let result = mappedCredentialQuery.requireCryptographicHolderBinding ? try extractHolderAndSignatureSuite(credential) : nil
92+
let result = try extractHolderAndSignatureSuite(credential)
9293
let (vpTokenSigningPayload, unsignedVPToken) = try await buildPayloadAndUnsignedVPToken(
94+
identifier: identifier,
9395
with: verifiableCredentials,
94-
signatureSuite: result?.signatureSuite,
95-
holder: sanitize(result?.holder)
96+
signatureSuite: result.signatureSuite,
97+
holder: sanitize(result.holder)
9698
)
9799

98-
vpTokenSigningPayloads[uuid] = vpTokenSigningPayload
100+
vpTokenSigningPayloads[identifier] = vpTokenSigningPayload
99101
if let unsignedVPToken = unsignedVPToken {
100102
unsignedVPTokens.append(unsignedVPToken)
101103
}
@@ -105,7 +107,7 @@ class UnsignedLdpVPTokenBuilder: UnsignedVPTokenBuilder {
105107
return (vpTokenSigningPayloads, unsignedVPTokens)
106108
}
107109

108-
private func buildPayloadAndUnsignedVPToken(with credentials: [AnyCodable], signatureSuite: String?, holder: String?) async throws -> (vpTokenSigningPayload: LdpVP, unsignedVPToken: UnsignedVPToken?) {
110+
private func buildPayloadAndUnsignedVPToken(identifier: String, with credentials: [AnyCodable], signatureSuite: String?, holder: String?) async throws -> (vpTokenSigningPayload: LdpVP, unsignedVPToken: UnsignedVPToken?) {
109111
var context: [String] = ["https://www.w3.org/2018/credentials/v1"]
110112
if signatureSuite == SignatureSuite.ed25519Signature2020.rawValue {
111113
context.append("https://w3id.org/security/suites/ed25519-2020/v1")
@@ -180,6 +182,7 @@ class UnsignedLdpVPTokenBuilder: UnsignedVPTokenBuilder {
180182

181183

182184
let unsignedVPToken = UnsignedVPToken(
185+
id: identifier,
183186
format: .ldp_vc,
184187
holderKeyReference: holder,
185188
signatureAlgorithm: signatureAlgorithm,

Sources/OpenID4VP/AuthorizationResponse/UnsignedVPToken/types/Mdoc/UnsignedMdocVPTokenBuilder.swift

Lines changed: 37 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -26,87 +26,62 @@ struct UnsignedMdocVPTokenBuilder: UnsignedVPTokenBuilder {
2626
}
2727

2828

29-
func build(credentialInputDescriptorMappings: inout [CredentialInputDescriptorMapping]) async throws -> (vpTokenSigningPayload: Any?, unsignedVPTokens: [UnsignedVPToken]) {
30-
var docTypeToDeviceAuthenticationBytes: [String: String] = [:]
29+
func build(credentialInputDescriptorMappings: inout [CredentialInputDescriptorMapping]) async throws -> (vpTokenSigningPayload: VPTokenSigningPayload, unsignedVPTokens: [UnsignedVPToken]) {
30+
var uuidToDeviceAuthenticationBytes: [String: String] = [:]
3131
var unsignedVPTokens: [UnsignedVPToken] = []
32-
32+
3333
let sessionTranscript = try getSessionTranscript()
3434
let deviceNamespacesBytes = getDeviceNamespacesBytes()
35-
35+
36+
var existingDocTypes: Set<String> = []
37+
3638
for index in 0..<credentialInputDescriptorMappings.count {
3739
let credentialInputDescriptorMapping = credentialInputDescriptorMappings[index]
38-
let (docType, deviceAuthentication, unsignedVPToken) = try await buildPayloadAndUnsignedVPToken(
40+
let (_, _, unsignedVPToken) = try await buildPayloadAndUnsignedVPToken(
3941
with: credentialInputDescriptorMapping.credential,
4042
sessionTranscript: sessionTranscript,
4143
deviceNamespacesBytes: deviceNamespacesBytes,
42-
docTypeToDeviceAuthenticationBytes: docTypeToDeviceAuthenticationBytes,
43-
updateIdentifier: { docTypeString in
44-
credentialInputDescriptorMappings[index].identifier = docTypeString
45-
}
44+
uuidToDeviceAuthenticationBytes: &uuidToDeviceAuthenticationBytes,
45+
updateIdentifier: { identifier in
46+
credentialInputDescriptorMappings[index].identifier = identifier
47+
},
48+
existingDocTypes: &existingDocTypes
4649
)
4750

48-
docTypeToDeviceAuthenticationBytes[docType] = deviceAuthentication
4951
unsignedVPTokens.append(unsignedVPToken)
5052
}
51-
52-
53-
unsignedVPTokens = []
54-
for docType in docTypeToDeviceAuthenticationBytes.keys.sorted() {
55-
let mapping = credentialInputDescriptorMappings.first(where: { $0.identifier == docType })!
56-
let mdocCredential = mapping.credential.value as! String
57-
let (keyRef, alg) = try resolveMdocKeyAndAlg(mdocCredential)
58-
unsignedVPTokens.append(UnsignedVPToken(
59-
format: .mso_mdoc,
60-
holderKeyReference: keyRef,
61-
signatureAlgorithm: alg,
62-
dataToSign: Data((docTypeToDeviceAuthenticationBytes[docType]!).utf8)
63-
))
64-
}
65-
53+
6654
return (
67-
vpTokenSigningPayload: docTypeToDeviceAuthenticationBytes,
55+
vpTokenSigningPayload: uuidToDeviceAuthenticationBytes,
6856
unsignedVPTokens: unsignedVPTokens
6957
)
7058
}
7159

72-
func build(credentialToCredentialQueryIdMappings: inout [CredentialToCredentialQueryIdMapping]) async throws -> (vpTokenSigningPayload: Any?, unsignedVPTokens: [UnsignedVPToken]) {
73-
var docTypeToDeviceAuthenticationBytes: [String: String] = [:]
60+
func build(credentialToCredentialQueryIdMappings: inout [CredentialToCredentialQueryIdMapping]) async throws -> (vpTokenSigningPayload: VPTokenSigningPayload, unsignedVPTokens: [UnsignedVPToken]) {
61+
var uuidToDeviceAuthenticationBytes: [String: String] = [:]
7462
var unsignedVPTokens: [UnsignedVPToken] = []
75-
63+
7664
let sessionTranscript = try getSessionTranscript()
7765
let deviceNamespacesBytes = getDeviceNamespacesBytes()
78-
66+
var existingDocTypes: Set<String> = []
67+
7968
for index in 0..<credentialToCredentialQueryIdMappings.count {
8069
let credentialToCredentialQueryIdMapping = credentialToCredentialQueryIdMappings[index]
81-
let (docType, deviceAuthentication, unsignedVPToken) = try await buildPayloadAndUnsignedVPToken(
70+
let (_, _, unsignedVPToken) = try await buildPayloadAndUnsignedVPToken(
8271
with: credentialToCredentialQueryIdMapping.credential,
8372
sessionTranscript: sessionTranscript,
8473
deviceNamespacesBytes: deviceNamespacesBytes,
85-
docTypeToDeviceAuthenticationBytes: docTypeToDeviceAuthenticationBytes,
86-
updateIdentifier: { docTypeString in
87-
credentialToCredentialQueryIdMappings[index].identifier = docTypeString
88-
}
89-
)
74+
uuidToDeviceAuthenticationBytes: &uuidToDeviceAuthenticationBytes,
75+
updateIdentifier: { identifier in
76+
credentialToCredentialQueryIdMappings[index].identifier = identifier
77+
}, existingDocTypes: &existingDocTypes
78+
)
9079

91-
docTypeToDeviceAuthenticationBytes[docType] = deviceAuthentication
9280
unsignedVPTokens.append(unsignedVPToken)
9381
}
94-
95-
unsignedVPTokens = []
96-
for docType in docTypeToDeviceAuthenticationBytes.keys.sorted() {
97-
let mapping = credentialToCredentialQueryIdMappings.first(where: { $0.identifier == docType })!
98-
let mdocCredential = mapping.credential.value as! String
99-
let (keyRef, alg) = try resolveMdocKeyAndAlg(mdocCredential)
100-
unsignedVPTokens.append(UnsignedVPToken(
101-
format: .mso_mdoc,
102-
holderKeyReference: keyRef,
103-
signatureAlgorithm: alg,
104-
dataToSign: Data((docTypeToDeviceAuthenticationBytes[docType]!).utf8)
105-
))
106-
}
107-
82+
10883
return (
109-
vpTokenSigningPayload: docTypeToDeviceAuthenticationBytes,
84+
vpTokenSigningPayload: uuidToDeviceAuthenticationBytes,
11085
unsignedVPTokens: unsignedVPTokens
11186
)
11287
}
@@ -131,19 +106,21 @@ struct UnsignedMdocVPTokenBuilder: UnsignedVPTokenBuilder {
131106
private func buildPayloadAndUnsignedVPToken(with credential: AnyCodable,
132107
sessionTranscript: CBOR,
133108
deviceNamespacesBytes: CBOR,
134-
docTypeToDeviceAuthenticationBytes: [String: String],
135-
updateIdentifier: (String) -> Void
109+
uuidToDeviceAuthenticationBytes: inout [String: String],
110+
updateIdentifier: (String) -> Void,
111+
existingDocTypes: inout Set<String>
136112
) async throws -> (docType: String, deviceAuthenticationBytes: String, unsignedVPToken: UnsignedVPToken) {
137113
let (mdocCredential, decodedMdocCredential) = try decodeMdoc(credential, className: Self.className)
138114

139115
let (docType, docTypeString) = try extractMdocDocType(from: decodedMdocCredential, className: Self.className)
140116

141-
if docTypeToDeviceAuthenticationBytes[docTypeString] != nil {
117+
if existingDocTypes.contains(docTypeString) {
142118
throw InvalidData(
143119
message: "Duplicate Mdoc Credentials with same doctype found",
144120
className: Self.className
145121
)
146122
}
123+
existingDocTypes.insert(docTypeString)
147124

148125
let deviceAuthentication = CBOR.array([
149126
.utf8String("DeviceAuthentication"),
@@ -154,15 +131,18 @@ struct UnsignedMdocVPTokenBuilder: UnsignedVPTokenBuilder {
154131

155132
let wrapped = wrapCBORInputWithTag24(input: deviceAuthentication)!
156133
let dataToSign = cborToByteString(cbor: wrapped)
134+
let identifier = UUIDGenerator.generateUUID()
157135

158-
updateIdentifier(docTypeString)
136+
updateIdentifier(identifier)
137+
uuidToDeviceAuthenticationBytes[identifier] = dataToSign
159138

160139
let (keyRef, alg) = try resolveMdocKeyAndAlg(mdocCredential)
161140

162141
return (
163142
docTypeString,
164143
dataToSign,
165144
UnsignedVPToken(
145+
id: identifier,
166146
format: .mso_mdoc,
167147
holderKeyReference: keyRef,
168148
signatureAlgorithm: alg,
@@ -183,7 +163,7 @@ struct UnsignedMdocVPTokenBuilder: UnsignedVPTokenBuilder {
183163
case .draft23:
184164
let clientIdToHash = CBOR.array([.utf8String(authorizationRequest.clientId), .utf8String(mdocGeneratedNonce)])
185165
let clientIdHash = CBOR.byteString(sha256Hash(from: clientIdToHash))
186-
166+
187167
let responseUriToHash = CBOR.array([.utf8String(responseUri), .utf8String(mdocGeneratedNonce)])
188168
let responseUriHash = CBOR.byteString(sha256Hash(from: responseUriToHash))
189169
return CBOR.array([clientIdHash, responseUriHash, .utf8String(authorizationRequest.nonce)])

0 commit comments

Comments
 (0)